springboot2.2.4自定义全局异常

原理

springboot默认将错误的页面重定向到类路径下的/error目录下,我们需要在该目录下设置相应的状态码页面。无需配置springboot就会根据状态码找到相应的页面进行展示数据。在实现前后端分离的基础上我们选择thymeleaf模板引擎,类似于jsp但springboot不支持jsp的解析。

springboot对于thymeleaf模板解析时会自动到类路径下的/templates/下寻找资源。可以查看org.springframework.boot.autoconfigure.thymeleaf;包下的默认配置文件,如下图
springboot2.2.4自定义全局异常_第1张图片
因此我们要想从模板引擎里面拿取数据,我们需要将/error/文件夹放到/templates下。左图是证明springboot默认的错误目录查找路径,右图是设置默认的错误页面。
springboot2.2.4自定义全局异常_第2张图片
springboot2.2.4自定义全局异常_第3张图片

springboot异常工作原理

首先执行请求,遇到错误后根据返回的状态码,在默认错误路径下找到相应的错误页面显示出来。

自定义错误页面根路径。

默认的路径是在类路径下的/error下,如果我们不叫这个名字,我们可以在application.properties里面写上
server.error.path=/newError

自定义错误页面显示的内容

自己没有创建/error目录时默认的错误页面模板是这样的,默认页面的代码在ErrorMvcAutoConfiguration类中
springboot2.2.4自定义全局异常_第4张图片
在error目录下定制自己的异常页面

  1. 需求1.我们想在错误页面显示公司的名字,因此我们需要将公司的名字添加到全局异常中,这样,无论哪个方法发生异常在错误页面都可以拿到公司的名字
    在DefaultErrorAttributes 类下我们发现这样的代码
    springboot2.2.4自定义全局异常_第5张图片
    因此我们可以继承该类重写该方法 将自己想要添加的属性添加在里面
@Component  //@component的意思是该类是springboot中的组件 添加上该组件后 springboot就会在运行时执行该组件
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("company","sofency");
        //这种方式添加的异常 是默认的异常,即程序中遇到的所有异常都可以取到company
        return map;
    }
}

4xx.html 凡是以4开头的状态码都会到该页面里面

<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
            <h1>status:[[${status}]]h1>
       		<h1>timestamp:[[${timestamp}]]h1>
            <h1>message:[[${message}]]h1>
            
            <h1>company:[[${company}]]h1>
main>

错误的页面如下:成功取到company
springboot2.2.4自定义全局异常_第6张图片
• 需求2:处理指定类的异常并显示数据到页面中
自定义异常类userNotExistException

public class UserNotExistException extends RuntimeException {
    public UserNotExistException(){
        super("用户不存在");
    }
}

发送查询用户aaa请求时,如果不等于aaa则抛出异常。

   @ResponseBody
    @RequestMapping("/hello")
    public String helloworld(@RequestParam("user") String user){
        if("aaa".equals(user)){
            throw new UserNotExistException();
        }
        return "Hello world";
    }

处理异常类

@ControllerAdvice
public class MyExceptionHandler {
    //ExceptionHandler(异常类)
    @ExceptionHandler(UserNotExistException.class)
    public String handlerException(Exception e, HttpServletRequest request){
        Map<String,Object> map = new HashMap<>();
        request.setAttribute("javax.servlet.error.status_code",500);//自定义状态码
        map.put("code","user.not exist");
        map.put("message",e.getMessage());
        request.setAttribute("ext",map);//是为了将自定义设置的数据显示在浏览器
        return "forward:/error";//重定向到/error下,springboot会在该路径下根据状态吗选择页面进行展示
    }
}

但是上述的map仅仅是将数据放在了请求域中,在页面上还是无法拿到数据 ,而request的作用域不能在html页面进行直接解析,因此需要被themeleaf解析,所以要像设置全局异常那样添加到map中

@Component  //@component的意思是该类是springboot中的组件 添加上该组件后 springboot就会在运行时执行该组件
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("company","sofency");
        //这种方式添加的异常 是默认的异常,即程序中遇到的所有异常都可以取到company
          //这是自己比比编写的异常处理器捕捉的异常
        Map<String,Object> ext = (Map<String,Object>) webRequest.getAttribute("ext",0);//0代表是request请求的
        map.put("ext",ext);
        return map;
    }
}

5xx.html页面的取值操作

<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
            <h1>status:[[${status}]]h1>
            <h1>message:[[${message}]]h1>
            <h1>company:[[${company}]]h1>
            <h1>ext:[[${ext.code}]]h1>
            <h1>ext:[[${ext.message}]]h1>
        main>

显示的异常页面
springboot2.2.4自定义全局异常_第7张图片

你可能感兴趣的:(SpringBoot)