经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Spring Boot » 查看文章
Spring Boot处理全局统一异常的两种方法与区别
来源:jb51  时间:2019/6/12 13:02:33  对本文有异议

前言

在后端发生异常或者是请求出错时,前端通常显示如下

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Fri Jun 07 15:38:07 CST 2019
There was an unexpected error (type=Not Found, status=404).
No message available

对于用户来说非常不友好。

本文主要讲解如何在SpringBoot应用中使用统一异常处理。

实现方式

  • 第一种:使用@ControllerAdvice和@ExceptionHandler注解
  • 第二种: 使用ErrorController类来实现。

第一种:使用@ControllerAdvice和@ExceptionHandler注解

  1. @Slf4j
  2. @ControllerAdvice
  3. public class GlobalExceptionHandler {
  4.  
  5. @ResponseBody
  6. @ExceptionHandler(NullPointerException.class)
  7. public BaseResult globalException(HttpServletResponse response,NullPointerException ex){
  8.  
  9.  
  10. log.info("GlobalExceptionHandler...");
  11. log.info("错误代码:" + response.getStatus());
  12. BaseResult result = new WebResult(WebResult.RESULT_FAIL,"request error:"+response.getStatus()
  13. ,"GlobalExceptionHandler:"+ex.getMessage());
  14. return result;
  15. }
  16.  
  17. }

注解@ControllerAdvice表示这是一个控制器增强类,当控制器发生异常且符合类中定义的拦截异常类,将会被拦截。

可以定义拦截的控制器所在的包路径

  1. @Target({ElementType.TYPE})
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. @Component
  5. public @interface ControllerAdvice {
  6. @AliasFor("basePackages")
  7. String[] value() default {};
  8.  
  9. @AliasFor("value")
  10. String[] basePackages() default {};
  11.  
  12. Class<?>[] basePackageClasses() default {};
  13.  
  14. Class<?>[] assignableTypes() default {};
  15.  
  16. Class<? extends Annotation>[] annotations() default {};
  17. }

注解ExceptionHandler定义拦截的异常类

  1. @Target({ElementType.METHOD})
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. public @interface ExceptionHandler {
  5. Class<? extends Throwable>[] value() default {};
  6. }

第二种: 使用ErrorController类来实现。

系统默认的错误处理类为BasicErrorController,将会显示如上的错误页面。

这里编写一个自己的错误处理类,上面默认的处理类将不会起作用。

getErrorPath()返回的路径服务器将会重定向到该路径对应的处理类,本例中为error方法。

  1. @Slf4j
  2. @RestController
  3. public class HttpErrorController implements ErrorController {
  4.  
  5. private final static String ERROR_PATH = "/error";
  6.  
  7. @ResponseBody
  8. @RequestMapping(path = ERROR_PATH )
  9. public BaseResult error(HttpServletRequest request, HttpServletResponse response){
  10. log.info("访问/error" + " 错误代码:" + response.getStatus());
  11. BaseResult result = new WebResult(WebResult.RESULT_FAIL,"HttpErrorController error:"+response.getStatus());
  12. return result;
  13. }
  14. @Override
  15. public String getErrorPath() {
  16. return ERROR_PATH;
  17. }
  18. }

测试

以上定义了一个统一的返回类BaseResult,方便前端进行处理。

  1. package com.microblog.common.result;
  2.  
  3. import java.io.Serializable;
  4.  
  5.  
  6. public class BaseResult implements Serializable {
  7.  
  8. private static final long serialVersionUID = 1L;
  9.  
  10. public static final int RESULT_FAIL = 0;
  11. public static final int RESULT_SUCCESS = 1;
  12.  
  13. //返回代码
  14. private Integer code;
  15.  
  16. //返回消息
  17. private String message;
  18.  
  19. //返回对象
  20. private Object data;
  21.  
  22. public BaseResult(Integer code, String message) {
  23. this.code = code;
  24. this.message = message;
  25. }
  26.  
  27. public BaseResult(Integer code, String message, Object object) {
  28. this.code = code;
  29. this.message = message;
  30. this.data = object;
  31. }
  32.  
  33.  
  34. public Integer getCode() {
  35. return code;
  36. }
  37.  
  38. public void setCode(Integer code) {
  39. this.code = code;
  40. }
  41.  
  42. public String getMessage() {
  43. return message;
  44. }
  45.  
  46. public void setMessage(String message) {
  47. this.message = message;
  48. }
  49.  
  50. public Object getData() {
  51. return data;
  52. }
  53.  
  54. public void setData(Object data) {
  55. this.data = data;
  56. }
  57. }

编写一个测试控制器

  1. @Slf4j
  2. @RestController
  3. @RequestMapping("/user")
  4. public class TestController {
  5.  
  6. @RequestMapping("/info1")
  7. public String test(){
  8. log.info("/user/info1");
  9.  
  10. throw new NullPointerException("TestController have exception");
  11.  
  12. }
  13. }

1.发出一个错误的请求,也就是没有对应的处理类。

从返回可以看到是由HttpErrorController类处理

  1. {"code":0,"message":"HttpErrorController error:404","data":null}

2.发出一个正常的请求(TestController的test()处理),处理类中抛出空异样

从返回中可以看出是由GlobalExceptionHandler类处理

  1. {"code":0,"message":"request error:200","data":"GlobalExceptionHandler:TestController have exception"}

区别

1.注解@ControllerAdvice方式只能处理控制器抛出的异常。此时请求已经进入控制器中。

2.类ErrorController方式可以处理所有的异常,包括未进入控制器的错误,比如404,401等错误

3.如果应用中两者共同存在,则@ControllerAdvice方式处理控制器抛出的异常,类ErrorController方式未进入控制器的异常。

4.@ControllerAdvice方式可以定义多个拦截方法,拦截不同的异常类,并且可以获取抛出的异常信息,自由度更大。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对w3xue的支持。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号