@ControllerAdvice,是Spring3.2+提供的新注解,它是一个Controller增强器,可对Controller中被 @RequestMapping注解的方法加一些逻辑处理。最常用的就是异常处理。
统一异常处理
需要配合@ExceptionHandler使用。当将异常抛到Controller时,可以对异常进行统一处理,规定返回的json格式或是跳转到一个错误页面。
全局异常捕捉处理
1package cn.itechyou.cms.exception;
2
3import org.apache.shiro.authz.UnauthorizedException;
4import org.slf4j.Logger;
5import org.slf4j.LoggerFactory;
6import org.springframework.http.HttpStatus;
7import org.springframework.http.converter.HttpMessageNotReadableException;
8import org.springframework.web.HttpMediaTypeNotSupportedException;
9import org.springframework.web.HttpRequestMethodNotSupportedException;
10import org.springframework.web.bind.annotation.ControllerAdvice;
11import org.springframework.web.bind.annotation.ExceptionHandler;
12import org.springframework.web.bind.annotation.ResponseStatus;
13import org.springframework.web.servlet.ModelAndView;
14import org.springframework.web.servlet.NoHandlerFoundException;
15
16import cn.itechyou.cms.common.ExceptionEnum;
17
18/**
19 * 全局异常处理
20 *
21 * @author Wangjunnan
22 *
23 */
24@ControllerAdvice
25public class GlobalExceptionHandler {
26
27 private Logger logger = LoggerFactory.getLogger(this.getClass());
28
29 /**
30 * 400 - 错误的请求
31 */
32 @ResponseStatus(HttpStatus.BAD_REQUEST)
33 @ExceptionHandler(HttpMessageNotReadableException.class)
34 public ModelAndView handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
35 logger.error("错误的请求", e);
36 ModelAndView mv = new ModelAndView();
37 mv.setViewName("error/400");
38 mv.addObject("code", ExceptionEnum.HTTP_BAD_REQUEST.getCode());
39 mv.addObject("message", ExceptionEnum.HTTP_BAD_REQUEST.getMessage());
40 return mv;
41 }
42
43 /**
44 * 403 - 禁止访问
45 */
46 @ResponseStatus(HttpStatus.FORBIDDEN)
47 @ExceptionHandler(UnauthorizedException.class)
48 public ModelAndView handleUnauthorizedException(UnauthorizedException e) {
49 logger.error("禁止访问", e);
50 ModelAndView mv = new ModelAndView();
51 mv.setViewName("error/403");
52 mv.addObject("code", ExceptionEnum.HTTP_FORBIDDEN.getCode());
53 mv.addObject("message", ExceptionEnum.HTTP_FORBIDDEN.getMessage());
54 return mv;
55 }
56
57 /**
58 * 404 -没有找到
59 */
60 @ResponseStatus(HttpStatus.NOT_FOUND)
61 @ExceptionHandler(NoHandlerFoundException.class)
62 public ModelAndView handleNotFoundException(NoHandlerFoundException e) {
63 logger.error("资源没有找到", e);
64 ModelAndView mv = new ModelAndView();
65 mv.setViewName("error/404");
66 mv.addObject("code", ExceptionEnum.HTTP_NOT_FOUND.getCode());
67 mv.addObject("message", ExceptionEnum.HTTP_NOT_FOUND.getMessage());
68 return mv;
69 }
70
71 /**
72 * 405 - 方法不允许
73 */
74 @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
75 @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
76 public ModelAndView handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
77 logger.error("没有权限!", e);
78 ModelAndView mv = new ModelAndView();
79 mv.setViewName("error/405");
80 mv.addObject("code", ExceptionEnum.HTTP_METHOD_NOT_ALLOWED.getCode());
81 mv.addObject("message", ExceptionEnum.HTTP_METHOD_NOT_ALLOWED.getMessage());
82 return mv;
83 }
84
85 /**
86 * 415 - 不支持的媒体类型
87 */
88 @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
89 @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
90 public ModelAndView handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
91 logger.error("不支持的媒体类型", e);
92 ModelAndView mv = new ModelAndView();
93 mv.setViewName("error/415");
94 mv.addObject("code", ExceptionEnum.HTTP_UNSUPPORTED_MEDIA_TYPE.getCode());
95 mv.addObject("message", ExceptionEnum.HTTP_UNSUPPORTED_MEDIA_TYPE.getMessage());
96 return mv;
97 }
98
99 /**
100 * 500 - 内部服务器错误
101 */
102 @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
103 @ExceptionHandler(Exception.class)
104 public ModelAndView handleUnauthorizedException(Exception e) {
105 logger.error("内部服务器错误", e);
106 ModelAndView mv = new ModelAndView();
107 mv.setViewName("error/500");
108 mv.addObject("code", ExceptionEnum.HTTP_INTERNAL_SERVER_ERROR.getCode());
109 mv.addObject("message", ExceptionEnum.HTTP_INTERNAL_SERVER_ERROR.getMessage());
110 return mv;
111 }
112
113 /**
114 * CMSException
115 */
116 @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
117 @ExceptionHandler(CmsException.class)
118 public ModelAndView cmsException(CmsException e) {
119 logger.error("异常:", e);
120 ModelAndView mv = new ModelAndView();
121 mv.setViewName("error/exception");
122 mv.addObject("code", e.getCode());
123 mv.addObject("message", e.getMessage());
124 mv.addObject("reason", e.getReason());
125 return mv;
126 }
127}
自定义异常类
1package cn.itechyou.cms.exception;
2
3public class CmsException extends Exception {
4
5 private static final long serialVersionUID = 2415656102753230136L;
6
7 private String code;
8 private String message;
9 private String reason;
10
11 public CmsException() {
12 super();
13 }
14
15 public CmsException(String code, String message, String reason) {
16 super(message);
17 this.code = code;
18 this.message = message;
19 this.reason = reason;
20 }
21
22 public String getCode() {
23 return code;
24 }
25
26 public void setCode(String code) {
27 this.code = code;
28 }
29
30 public String getMessage() {
31 return message;
32 }
33
34 public void setMessage(String message) {
35 this.message = message;
36 }
37
38 public String getReason() {
39 return reason;
40 }
41
42 public void setReason(String reason) {
43 this.reason = reason;
44 }
45
46}
找不到模版文件Exception
1package cn.itechyou.cms.exception;
2
3public class TemplateNotFoundException extends CmsException{
4
5 private static final long serialVersionUID = 3969404221975913175L;
6
7 public TemplateNotFoundException(String code, String message, String reason) {
8 super(code, message, reason);
9 }
10
11}
测试类
1@RestController
2public class TestController {
3 @RequestMapping("testException")
4 public String testException() throws CmsException{
5 throw new TemplateNotFoundException(
6 ExceptionEnum.TEMPLATE_NOTFOUND_EXCEPTION.getCode(),
7 ExceptionEnum.TEMPLATE_NOTFOUND_EXCEPTION.getMessage(),
8 "请仔细检查" + template.getAbsolutePath() + "文件,或检查application.yml中的资源目录配置项(web.resource-path)。");
9 }
10}
访问testException接口,可得到以下结果:
如果需要返回json数据,而要渲染某个页面模板返回给浏览器,那么可以这么实现:
1@ResponseBody
2@ExceptionHandler(value = CmsException.class)
3public Map<String,Object> jsonErrorHandler(CmsException ex) {
4 Map<String,Object> map = new HashMap<String,Object>();
5 map.put("code", "40001");
6 //判断异常的类型,返回不一样的返回值
7 if(ex instanceof TemplateNotFoundException){
8 map.put("msg","缺少必需参数:"+((TemplateNotFoundException) ex).getMessage());
9 }else if(ex instanceof TemplateReadException){
10 map.put("msg", ((TemplateReadException) ex).getMessage());
11 }
12 return map;
13}
这样子很方便吧~
I Tech You, 我教你!(www.itechyou.cn)
一个专注于技术分享、免费教程、学习资源的博客!爱好网页技术、网络安全、技术分享、经验分享、IT资讯;最全网络技术学习资源,云服务器折扣活动分享。
欢迎关注,一起学习,共成长!