之前敲代碼的時候,避免不了各種try..catch, 如果業務復雜一點, 就會發現全都是try…catch
try{
..........
}catch(Exception1 e){
..........
}catch(Exception2 e){
...........
}catch(Exception3 e){
...........
}
這樣其實代碼既不簡潔好看 ,我們敲着也煩, 一般我們可能想到用攔截器去處理, 但是既然現在Spring這么火,AOP大家也不陌生, 那么Spring一定為我們想好了這個解決辦法.果然: @ExceptionHandler
源碼
//該注解作用對象為方法
@Target({ElementType.METHOD})
//在運行時有效
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExceptionHandler {
//value()可以指定異常類
Class<? extends Throwable>[] value() default {};
}
@ControllerAdvice
源碼
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
//bean對象交給spring管理生成
@Component
public @interface ControllerAdvice {
@AliasFor("basePackages")
String[] value() default {};
@AliasFor("value")
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
Class<?>[] assignableTypes() default {};
Class<? extends Annotation>[] annotations() default {};
}
從名字上可以看出大體意思是控制器增強
所以結合上面我們可以知道,使用@ExceptionHandler,可以處理異常, 但是僅限於當前Controller中處理異常, @ControllerAdvice可以配置basePackage下的所有controller. 所以結合兩者使用,就可以處理全局的異常了.
1.定義一個異常
public class CustomGenericException extends RuntimeException{
private static final long serialVersionUID = 1L;
private String errCode;
private String errMsg;
public String getErrCode() {
return errCode;
}
public void setErrCode(String errCode) {
this.errCode = errCode;
}
public String getErrMsg() {
return errMsg;
}
public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
}
public CustomGenericException(String errCode, String errMsg) {
this.errCode = errCode;
this.errMsg = errMsg;
}
}
2. 定義一個controller
這里我們就不用try catch了, 直接拋異常就可以了
@Controller
@RequestMapping("/exception")
public class ExceptionController {
@RequestMapping(value = "/{type}", method = RequestMethod.GET)
public ModelAndView getPages(@PathVariable(value = "type") String type) throws Exception{
if ("error".equals(type)) {
// 由handleCustomException處理
throw new CustomGenericException("E888", "This is custom message");
} else if ("io-error".equals(type)) {
// 由handleAllException處理
throw new IOException();
} else {
return new ModelAndView("index").addObject("msg", type);
}
}
}
3.異常處理類
這個類就可以當做controller類寫了, 返回參數跟mvc返回參數一樣
@ControllerAdvice
public class ExceptionsHandler {
@ExceptionHandler(CustomGenericException.class)//可以直接寫@ExceptionHandler,不指明異常類,會自動映射
public ModelAndView customGenericExceptionHnadler(CustomGenericException exception){ //還可以聲明接收其他任意參數
ModelAndView modelAndView = new ModelAndView("generic_error");
modelAndView.addObject("errCode",exception.getErrCode());
modelAndView.addObject("errMsg",exception.getErrMsg());
return modelAndView;
}
//可以通過ResponseStatus配置返回的狀態碼
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(Exception.class)//可以直接寫@EceptionHandler,IOExeption繼承於Exception
public ModelAndView allExceptionHandler(Exception exception){
ModelAndView modelAndView = new ModelAndView("generic_error");
modelAndView.addObject("errMsg", "this is Exception.class");
return modelAndView;
}
}
4.jsp頁面
正常的頁面
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body>
<h2>Spring MVC @ExceptionHandler Example</h2>
<c:if test="${not empty msg}">
<h2>${msg}</h2>
</c:if>
</body>
</html>
異常處理頁面
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body>
<c:if test="${not empty errCode}">
<h1>${errCode} : System Errors</h1>
</c:if>
<c:if test="${empty errCode}">
<h1>System Errors</h1>
</c:if>
<c:if test="${not empty errMsg}">
<h2>${errMsg}</h2>
</c:if>
</body>
</html>
