zoukankan      html  css  js  c++  java
  • Spring Boot系列(7)——自定义异常反馈

    〇、原始的异常反馈

      当出现4xx或5xx错误时,spring boot项目返回的原始异常反馈是如下风格。

      

    一、指定异常页面

      1.ErrorMvcAutoConfiguration

      按照Spring Boot的惯例,默认的配置都在xxxAutoConfiguration类中。而异常处理则在ErrorMvcAutoConfiguration中。

      错误请求会交由BasicErrorController处理,从类名可以看出这是一个错误处理控制器

    @Controller
    @RequestMapping({"${server.error.path:${error.path:/error}}"})
    public class BasicErrorController extends AbstractErrorController {
    
      /**
      * 该方法响应错误请求
      * 其中resolvErrorView形成错误反馈页面的路径
      */ @RequestMapping( produces
    = {"text/html"} ) public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { HttpStatus status = this.getStatus(request); Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); ModelAndView modelAndView = this.resolveErrorView(request, response, status, model); return modelAndView != null ? modelAndView : new ModelAndView("error", model); }
    }

      2.错误反馈页面路径

      

       

      3.总结

      把错误反馈页面放在根目录 error文件下(使用templeaf模板时,在/templates/error下),并且页面文件名为状态码,则发送该类错误,就会返回此页面。

      例如:发生 404 Http请求错误时,会返回  /error/404.html的页面 或 /error/4xx.html的页面。

      

    二、定制反馈信息

      1.编写异常处理方法

      注意:客户端或服务器异常会首先被处理再返回,而处理过后再返回则Http状态码会变为200,所以要通过"javax.servlet.error.status_code"指定Http的错误状态码

           通过以下代码,当发生UserNotExistException异常时,就来到此方法,我们就可以在其中添加自定义的反馈信息。

     1 /*
     2  * 增强的Controller,作用如下:
     3  * 1.全局异常处理
     4  * 2.全局数据绑定
     5  * 3.全局数据预处理
     6  */
     7 @ControllerAdvice
     8 public class ExceptionController {
     9 
    10     /*
    11      * @ExceptionHandler( )处理特定的异常
    12      * UserNotExistException为自定义异常
    13      * 即当发生该异常时,就转到该方法处理
    14      */
    15     @ExceptionHandler(UserNotExistException.class)
    16     public String hanldException(Exception e, HttpServletRequest request){
    17         Map<String,Object> map = new HashMap<>();
    18         request.setAttribute("javax.servlet.error.status_code",404);
    19         
    20         //转到“/error”请求处理控制器处理方法
    21         return "forward:/error";
    22     }
    23 }

      2.错误反馈信息要写在哪?

       回答该问题,我们可以参考本文开头图片中的Spring Boot默认返回的 错误反馈数据出处,如下:

      BasicErrorController控制器中errorHtml( )方法是响应/error请求的方法,其中调用了getErrorAttributes( )方法,而默认的错误反馈数据正是来自getErrorAttributes( )方法。

     1 //BasicErrorController类
     2   @RequestMapping(
     3         produces = {"text/html"}
     4     )
     5     public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
     6         HttpStatus status = this.getStatus(request);
     7         Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML)));
     8         response.setStatus(status.value());
     9         ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);
    10         return modelAndView != null ? modelAndView : new ModelAndView("error", model);
    11     }
     1 //DefaultErrorAttributes类
     2 public Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
     3         Map<String, Object> errorAttributes = new LinkedHashMap();
     4         errorAttributes.put("timestamp", new Date());
     5         errorAttributes.put("path", request.path());
     6         Throwable error = this.getError(request);
     7         MergedAnnotation<ResponseStatus> responseStatusAnnotation = MergedAnnotations.from(error.getClass(), SearchStrategy.TYPE_HIERARCHY).get(ResponseStatus.class);
     8         HttpStatus errorStatus = this.determineHttpStatus(error, responseStatusAnnotation);
     9         errorAttributes.put("status", errorStatus.value());
    10         errorAttributes.put("error", errorStatus.getReasonPhrase());
    11         errorAttributes.put("message", this.determineMessage(error, responseStatusAnnotation));
    12         errorAttributes.put("requestId", request.exchange().getRequest().getId());
    13         this.handleException(errorAttributes, this.determineException(error), includeStackTrace);
    14         return errorAttributes;
    15     }

      3.自定义反馈信息

      按照上面所述,我们可以通过继承DefaultErrorAttributes类,重写getErrorAttributes( )方法以加入自定义的错误反馈信息:

      再在页面中通过templeaf的标签将值取出

     1 import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
     2 
     3 
     4 //继承DefaultErrorAttributes类
     5 @Component
     6 public class MyErrorAttributes extends DefaultErrorAttributes {
     7 
     8     //重写getErrorAttributes方法
     9     @Override
    10     public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
    11         Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest, includeStackTrace);
    12         
    13         //加入自定义信息
    14         errorAttributes.put("message","页面找不到");
    15         return errorAttributes;
    16     }
    17 }
    //页面
    <h1>错误码:404</h1>
    <P>message:[[${message}]]</P>

       3.各方法执行顺序

          (1)异常处理器@ExceptionHandler(异常类)  ;  

       (2)BasicErrorController的errorHtml( )方法(调用getErrorAttributes( )方法);

       (3)重写的getErrorAttributes( )方法 ;

       (4)返回BasicErrorController的errorHtml( )方法;

      根据此执行顺序,我们可以把自定义反馈信息在异常处理器中编写,并放入request中。再在重写的getErrorAttributes( )方法 中通过request取出,如下:

     1 /*
     2  * 增强的Controller,作用如下:
     3  * 1.全局异常处理
     4  * 2.全局数据绑定
     5  * 3.全局数据预处理
     6  */
     7 @ControllerAdvice
     8 public class ExceptionController {
     9 
    10     /*
    11      * @ExceptionHandler( )处理特定的异常
    12      * UserNotExistException为自定义异常
    13      * 即当发生该异常时,就转到该方法处理
    14      */
    15     @ExceptionHandler(UserNotExistException.class)
    16     public String hanldException(Exception e, HttpServletRequest request){
    17         System.out.println("ExceptionController的hanldException方法");
    18         Map<String,Object> map = new HashMap<>();
    19         request.setAttribute("javax.servlet.error.status_code",404);
    20        //将自定义的反馈信息放入request
    21         map.put("message","页面找不到!");
    22         request.setAttribute("ext",map);
    23         //转到“/error”请求处理控制器处理方法
    24         return "forward:/error";
    25     }
    26 }
     1 //继承DefaultErrorAttributes类
     2 @Component
     3 public class MyErrorAttributes extends DefaultErrorAttributes {
     4 
     5     //重写getErrorAttributes方法
     6     @Override
     7     public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
     8         Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest, includeStackTrace);
     9         System.out.println("MyErrorAttributes的getErrorAttributes方法");
    10         //从request取出自定义信息
    11         errorAttributes.put("ext",webRequest.getAttribute("ext",0));
    12         return errorAttributes;
    13     }
    14 }
  • 相关阅读:
    43前端
    42 前端
    python 列表
    python 字符串方法
    python while语句
    zhy2_rehat6_mysql02
    zhy2_rehat6_mysql01
    bay——安装_Oracle 12C-RAC-Centos7.txt
    bay——RAC_ASM ORA-15001 diskgroup DATA does not exist or is not mounted.docx
    bay——Oracle RAC集群体系结构.docx
  • 原文地址:https://www.cnblogs.com/Drajun/p/12262094.html
Copyright © 2011-2022 走看看