spring MVC统一异常处理的几种方式
异常统一处理分为三种方式:
1.使用@ExceptionHandler + @ControllerAdvice注解
2.使用spring AOP (@AfterThrowing + @Aspect)
3.继承HandlerExceptionResolver 接口
4.使用@ExceptionHandler注解
1.使用@ExceptionHandler + @ControllerAdvice注解
此方法需要进行异常处理的方法必须与出错的方法在同一个Controller里面。那么当代码加入了 @ControllerAdvice,则不需要必须在同一个 controller 中了。这也是 Spring 3.2 带来的新特性。从名字上可以看出大体意思是控制器增强。 也就是说,@controlleradvice + @ ExceptionHandler 也可以实现全局的异常捕捉。
请确保此WebExceptionHandle 类能被扫描到并装载进 Spring 容器中。
@RestControllerAdvice
public class RestMyExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(RestMyExceptionHandler.class);
@ExceptionHandler(value = Exception.class)
public String handle(Exception e){
log.info("参数异常:"+e.getMessage());
return e.getMessage();
}
}
继承 ResponseEntityExceptionHandler 类来实现针对 Rest 接口 的全局异常捕获,并且可以返回自定义格式:
@Slf4j
@ControllerAdvice
public class ExceptionHandlerBean extends ResponseEntityExceptionHandler {
/**
* 数据找不到异常
* @param ex
* @param request
* @return
* @throws IOException
*/
@ExceptionHandler({DataNotFoundException.class})
public ResponseEntity<Object> handleDataNotFoundException(RuntimeException ex, WebRequest request) throws IOException {
return getResponseEntity(ex,request,ReturnStatusCode.DataNotFoundException);
}
/**
* 根据各种异常构建 ResponseEntity 实体. 服务于以上各种异常
* @param ex
* @param request
* @param specificException
* @return
*/
private ResponseEntity<Object> getResponseEntity(RuntimeException ex, WebRequest request, ReturnStatusCode specificException) {
ReturnTemplate returnTemplate = new ReturnTemplate();
returnTemplate.setStatusCode(specificException);
returnTemplate.setErrorMsg(ex.getMessage());
return handleExceptionInternal(ex, returnTemplate,
new HttpHeaders(), HttpStatus.OK, request);
}
}
2.使用spring AOP (@AfterThrowing + @Aspect)
@Aspect
@Component
public class WebExceptionAspect {
private static final Logger logger = LoggerFactory.getLogger(WebExceptionAspect.class);
//凡是注解了RequestMapping的方法都被拦截
@Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
private void webPointcut() {
}
/**
* 拦截web层异常,记录异常日志,并返回友好信息到前端 目前只拦截Exception,是否要拦截Error需再做考虑
* @param e 异常对象
*/
@AfterThrowing(pointcut = "webPointcut()", throwing = "e")
public void handleThrowing(Exception e) {
e.printStackTrace();
logger.error("发现异常!" + e.getMessage());
logger.error(JSON.toJSONString(e.getStackTrace()));
//这里输入友好性信息
writeContent("出现异常");
}
/**
* 将内容输出到浏览器
*
* @param content 输出内容
*/
private void writeContent(String content) {
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getResponse();
response.reset();
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "text/plain;charset=UTF-8");
response.setHeader("icop-content-type", "exception");
PrintWriter writer = null;
try {
writer = response.getWriter();
} catch (IOException e) {
e.printStackTrace();
}
writer.print(content);
writer.flush();
writer.close();
}
}
3.继承HandlerExceptionResolver 接口
这种方式可以进行全局的异常控制。例如:
@Component
public class ExceptionTest implements HandlerExceptionResolver{
/**
* TODO 简单描述该方法的实现功能(可选).
* @see org.springframework.web.servlet.HandlerExceptionResolver#resolveException(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)
*/
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
System.out.println("This is exception handler method!");
return null;
}
}
4.使用@ExceptionHandler注解
使用该注解有一个不好的地方就是:进行异常处理的方法必须与出错的方法在同一个Controller里面。使用如下:
@Controller
public class GlobalController {
/**
* 用于处理异常的
* @return
*/
@ExceptionHandler({MyException.class})
public String exception(MyException e) {
System.out.println(e.getMessage());
e.printStackTrace();
return "exception";
}
@RequestMapping("test")
public void test() {
throw new MyException("出错了!");
}
}
可以看到,这种方式最大的缺陷就是不能全局控制异常。每个类都要写一遍。
还没有评论,来说两句吧...