SpringBoot-定制错误页面

版权声明:来一来,看一看,有钱的捧个人场,没钱的你不得捧个人场 https://blog.csdn.net/wait_for_eva/article/details/82932522

错误页面

1. 文件路径

classpath:templates/error:模板存放地址

classpath:static/error:静态页面存放地址

  • 无需额外配置,Spring-Boot自动识别
  • 文件名error,没有需要手动创建
  • server.error.path配置可以替换error,看情况配置
  • 优先采用模板,没有再找静态文件夹

2. 文件格式

  • 指定错误页
# 404跳转页面
404.html
# 500跳转页面
500.html

文件名格式:code.html

  • 默认错误页
# 4XX错误统一错误页面
4xx.html
# 5xx错误统一页面
5xx.html
  • 有详细错误页面404.html,优先采用详细错误页面,没有则采用4xx.html
  • 40x.html之类的没试过,可以看看行不行

3. 自动路由

存在错误页面就行了,多余的不需要再进行配置,能够直接生效。

4. 模板渲染

  • 静态页面

    不论是classpath:static或者classpath:templates都能够被系统映射并利用。

  • 模板渲染

    但是系统为模板注入了几个错误的显示信息:

    • timestamp:时间戳
    • status:状态码
    • error:错误信息
    • exception:异常对象
    • message:提示信息
    • errors:JSR303

    当采用模板编写错误页面时,可以直接引入这些已经注入的错误信息。

    但是如果错误页面在classpath:static静态文件夹下的话,是取不到这些信息的。

5. 默认提示

​ 如果都没有配置,那就是Spring-Boot自己的默认提示页了。

错误数据

1. 自定义异常

public class MyException extends Exception{
    public MyException(){
        super("MyException");
    }
}

2. json输出

@ControllerAdvice
public class MyHandlerException {
    @ResponseBody
    @ExceptionHandler(MyException.class)
    public Map<String,Object> handlerException(Exception e){
        Map<String ,Object> map = new HashMap<>();
        map.put("myMessage","自定义信息" );
        return map;
    }
}

@ControllerAdvice:错误跳转控制器

@ResponseBody:返回内容

@ExceptionHandler:处理的异常类,针对指定异常进行处理

Map:返回信息,自动放进域内

  • 直接返回的json信息,只包含自动一内容myMessage
  • Spring-Boot默认数据未注入
  • 浏览器和接口访问都只返回json

3. 适配输出

@ControllerAdvice
public class MyHandlerException {
    @ExceptionHandler(MyException.class)
    public String handlerException(Exception e, HttpServletRequest request){
        Map<String, Object> map = new HashMap<>();
        map.put("msg","error");
        request.setAttribute("javax.servlet.error.status_code", 400);
        return "redirect:/error";
    }
}

redirect:/error:Spring-Boot自动维护一个BasicErrorController,redirect:/error会转发到那让它自动处理

request:BasicErrorcontroller从请求域中识别错误类型

javax.servlet.error.status_code:为了让BasicErrorController能够识别,需要传入该属性,设置错误码

redirect:/error:为了流程完整,再说一遍,转发BasicErrorController进行处理

  • 转发BasicErrorController的话,就会自动识别浏览器和接口,自动跳转页面和返回json
  • 但是携带的只有Spring-Boot定制的基本信息,我们可以修改,但是新增的信息不回传达到显示

4. 信息携带

@Component
public class MyErrorAttributes extends DefaultErrorAttributes {
    @Override
    public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
        Map<String, Object> map = super.getErrorAttributes(webRequest, includeStackTrace);
        map.put("add_msg","this is new add msg");
        map.put("company", "godme");
        Map<String, Object> myMessage = (Map<String, Object>) webRequest.getAttribute("myMsg", RequestAttributes.SCOPE_REQUEST);
        map.put("myMessage", myMessage);
        return map;
    }
}

DefaultErrorAttributes:BasicErrorController取的信息都是从DefaultErrorAttributes中取得,所以需要我们进行注入

company:一般开发的话,总有公司想要注入公司名称。

webReqeust:这个是从web中去获取数据的请求对象

getAttribute:从域中获取数据,需要指定key,和scope存储的域,从指定域中获取对象

return:返回的mapBasicErrorController会自动处理的啦,自动写入json,也会自动注入模板

5. 错误纠正

​ 为了方便,一直说的是BasicErrorController,顾名思义,它只是Controller而已。真正的处理不是它,而是路由到的指定处理器。

​ 如果有想法,可以顺着逻辑去翻一翻源码。

6. 总结梳理

1. 一般配置

  • 页面位置
    • classpath:templates/error
    • claspath:static/error

模板位置可以配置: spring.server.error.path

  • 文件名称

    • 错误页面: code.html
    • 默认页面:nxx.html
  • 模板数据

    • static;无数据注入
    • templates:自动注入数据

    BasicErrorController自动路由

2. 自定数据

  • 定义异常
public class MyException extends Exception{
    public MyException(){
        super("MyException");
    }
}
  • 信息注入
@ControllerAdvice
public class MyHandlerException {
    @ExceptionHandler(MyException.class)
    public String handlerException(Exception e, HttpServletRequest request){
        Map<String, Object> map = new HashMap<>();
        request.setAttribute("myMessage",e.getMessage());
        request.setAttribute("javax.servlet.error.status_code", 400);
        return "redirect:/error";
    }
}

@ControllerAdvice:异常访问

ExceptionHandler:异常捕捉

request.setAttribute("myMessage",e.getMessage()):信息注入

request.setAttribute("javax.servlet.error.status_code", 400):路由标记

  • 信息提取
@Component
public class MyErrorAttributes extends DefaultErrorAttributes {
    @Override
    public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
        Map<String, Object> map = super.getErrorAttributes(webRequest, includeStackTrace);
        map.put("add_msg","this is new add msg");
        map.put("company", "godme");
        Map<String, Object> myMessage = (Map<String, Object>) webRequest.getAttribute("myMsg", RequestAttributes.SCOPE_REQUEST);
        map.put("myMessage", myMessage);
        return map;
    }
}

DefaultErrorAttributes:默认采用信息

map.put("company", "godme"):注入额外信息

webRequest.getAttribute("myMsg", RequestAttributes.SCOPE_REQUEST):提取注入信息

map.put("myMessage", myMessage):添加到处理参数

@Component:别忘记标记,交给Spring

3. 流程总结

  • 三重路由
  1. 页面访问
  2. 程序异常处理
  3. 错误转发BasicErrorController
  • 数据注入
  1. 页面数据不相关
  2. 异常处理时注入新信息
  3. BasicErrorController提取新信息并设置
  • 关键步骤

    • 入口

    @ControllerAdvice:控制错误跳转

    • 注入

    @ExceptionHandler:处理异常,完成信息注入错误转发

    • 交由BasicErrorController处理,注意注入错误信息,便于路由
    • 提取

    DefaultErrorAttributes重写getErrorAttributes

    getErrorAttributes:提取上层注入信息,注入

    @Component:Spring管理

三种程度

1. 简单配置

​ 简单添加页面,无需配置,利用程度不高,具体信息无法获取。

2. 手动修改

​ 自定义信息,不论访问方式,都是json返回,无页面路由,浏览器页面不友好。

3. 嫁接方案

  • 异常拦截
  • 请求转发

通过拦截异常,把请求转发BasicErrorController。

利用Spring-Boot自己自动路由功能完成页面和接口的差异化适配。

  • request.setAttribute
  • DefaultAttributes

通过scope设置域参数,再注入到BasicErrorController中,让自定义参数得以处理。

本质上来说,三种处理方式如下

  1. 入口提供路由页面,Spring-Boot自动路由
  2. 手动路由,新参数注入但未适配客户端
  3. 修改Spring-Boot错误路由,提供页面,手动路由,注入参数

第三种方式关键点在于手动路由参数注入

手动路由:让Spring-Boot自动适配客户端

参数注入:让Spring-Boot能够采用新参数

猜你喜欢

转载自blog.csdn.net/wait_for_eva/article/details/82932522
今日推荐