五、错误处理机制

1、默认的错误处理机制

SpringBoot在页面请求发生错误的时候,会返回一个默认的页面,如下图:

浏览器做为客户端

如果使用的是浏览器做为客户端来访问接口,那么在浏览器的请求头中会有

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8

其他客户端

Accept:    */*

默认响应一个Json数据

{
"timestamp": 1538381770900,
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/crud/aaa"
}

2、错误处理的自动配置

错误处理的自动配置类:ErrorMvcAutoConfiguration

给容器中添加了如下的组件

  • DefaultErrorAttributes

在页面中共享信息

public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {
    Map<String, Object> errorAttributes = new LinkedHashMap();
    errorAttributes.put("timestamp", new Date());
    this.addStatus(errorAttributes, requestAttributes);
    this.addErrorDetails(errorAttributes, requestAttributes, includeStackTrace);
    this.addPath(errorAttributes, requestAttributes);
    return errorAttributes;
}
  • BasicErrorController

处理默认/error请求,如果客户端为web浏览器,用下面的方法处理,产生html类型的数据。

@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);
}

如果是其他的客户端,用下面的方法处理返回json数据

@RequestMapping
@ResponseBody
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
    Map<String, Object> body = this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL));
    HttpStatus status = this.getStatus(request);
    return new ResponseEntity(body, status);
}
  • ErrorPageCustomizer

系统出现错误后来到error请求进行处理。

@Value("${error.path:/error}")
private String path = "/error";
  • DefaultErrorViewResolver
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
    ModelAndView modelAndView = this.resolve(String.valueOf(status), model);
    if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
        modelAndView = this.resolve((String)SERIES_VIEWS.get(status.series()), model);
    }

    return modelAndView;
}

private ModelAndView resolve(String viewName, Map<String, Object> model) {
    //默认SpringBoot会去找到一个页面 /error/404
    String errorViewName = "error/" + viewName;

    //如果模版引擎可以解析这个页面地址就用这个模版引擎解析
    TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName, this.applicationContext);
    //模版引擎解析后返回errorViewName指定的地址
    //模版引擎不可以使用就去静态资源文件夹下面找/error/404.html页面
    return provider != null ? new ModelAndView(errorViewName, model) :
    this.resolveResource(errorViewName, model);
}

3、配置步骤

一但系统出现4xx或者5xx之类的错误;ErrorPageCustomizer就会生效(定制错误的响应规则);就会来到/error请求;就会被BasicErrorController处理;去哪个页面是由DefaultErrorViewResolver解析得到的

定制错误页面

1)、有模板引擎的情况下:error/状态码; 【将错误页面命名为 错误状态码.html 放在模板引擎文件夹里面的 error文件夹下】,发生此状态码的错误就会来到对应的页面;

我们可以使用4xx和5xx作为错误页面的文件名来匹配这种类型的所有错误,精确优先(优先寻找精确的状态码.html);

页面能获取的信息

  • timestamp:时间戳
  • status:状态码
  • error:错误提示
  • exception:异常对象
  • message:异常消息
  • errors:JSR303数据校验的错误都在这里

采用模版引擎的情况下,可以使用下面的写法来获取信息

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

2)、没有模板引擎(模板引擎找不到这个错误页面),静态资源文件夹下找;

3)、以上都没有错误页面,就是默认来到SpringBoot默认的错误提示页面;

定制错误的json数据

自定义一个异常

public class UserNotExistException extends RuntimeException {

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

Controller中

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

    return "HelloWorld";
}

页面

<h1>5xx</h1>
<h1>[[${timestamp}]]</h1>
<h1>[[${status}]]</h1>
<h1>[[${error}]]</h1>
<h1>[[${exception}]]</h1>
<h1>[[${message}]]</h1>

效果

{
"timestamp": 1538453996437,
"status": 500,
"error": "Internal Server Error",
"exception": "cn.zhuangxp.springboot.exception.UserNotExistException",
"message": "用户不存在",
"path": "/crud/hello"
}

以上返回的json数据是SpringBoot帮助我们定义好的,我们还可以定义自己的异常json信息。

@ControllerAdvice
public class MyExceptionhandler {

    @ResponseBody
    @ExceptionHandler(UserNotExistException.class)
    public Map<String, Object> handleException(Exception e){
        Map<String,Object> map = new HashMap<>();
        map.put("code","user.notexist");
        map.put("msg",e.getMessage());

        return map;
    }
}

效果

{
"msg": "用户不存在",
"code": "user.notexist"
}

上面的异常处理没有自适应效果。自适应效果要求如果是浏览器访问返回的是页面,如果是其他客户端访问返回的是json数据。

如何变成自适应效果呢?

/**
 * 存在自适应效果
 * @param e
 * @return
 */
@ExceptionHandler(UserNotExistException.class)
public String handleException(Exception e, HttpServletRequest request){
    Map<String,Object> map = new HashMap<>();
    request.setAttribute("javax.servlet.error.status_code",500);
    map.put("code","user.notexist");
    map.put("message","用户出错啦");
    //将上面的错误信息map放在请求域中
    request.setAttribute("ext",map);

    return "forward:/error";
}

编写一个自定义错误属性类,并添加到容器中

@Component
public class MyErrorAttributes extends DefaultErrorAttributes {

    @Override
    public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {
        Map<String, Object> map = super.getErrorAttributes(requestAttributes, includeStackTrace);
        Map<String,Object> ext = (Map<String, Object>) requestAttributes.getAttribute("ext", 0);
        //异常处理器携带的数据
        map.put("name","zxp");
        map.put("ext",ext);
        return map;
    }
}

这样写之后,用浏览器访问的时候,发生错误会跳转到我们设置好的页面上。用其他的浏览器就会返回相应的json错误信息。

{
"timestamp": 1538466112389,
"status": 500,
"error": "Internal Server Error",
"exception": "cn.zhuangxp.springboot.exception.UserNotExistException",
"message": "用户不存在",
"path": "/crud/hello",
"name": "zxp",
"ext":{
    "code": "user.notexist",
    "message": "用户出错啦"
    }
}

原文地址:https://www.cnblogs.com/beanbag/p/9737320.html

时间: 2024-10-19 17:19:56

五、错误处理机制的相关文章

嵌入式 Linux网络编程(五)——epoll机制

嵌入式 Linux网络编程(五)--epoll机制 一.epoll简介 epoll是在2.6内核中提出的,是select和poll的增强版本.epoll更加灵活,没有描述符限制,使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中. 1.epoll函数 #include <sys/epoll.h> int epoll_create(int size); 创建一个epoll的句柄,size表示监听的文件描述的数量 int epoll_ctl(int epfd,

SpringCloud 基础教程(五) 服务熔断机制(Eureka + Ribbon + Hystrix)

1.启动[服务中心]集群,即 Eureka Server 参考 SpringCloud 基础教程(一) 服务中心及集群(Eureka Server) 2.启动[服务提供者]集群,即 Eureka Client 参考 SpringCloud 基础教程(二) 服务注册及集群(Eureka Client) 3.启动[服务消费者],即 Eureka Discovery Client 参考 SpringCloud 基础教程(三) 服务发现及负载均衡(Eureka Discovery Client + Ri

Map/Reduce 工作机制分析 --- 错误处理机制

前言 对于Hadoop集群来说,节点损坏是非常常见的现象. 而Hadoop一个很大的特点就是某个节点的损坏,不会影响到整个分布式任务的运行. 下面就来分析Hadoop平台是如何做到的. 硬件故障 硬件故障可以分为两种 - JobTracker节点损坏和TaskTracker节点损坏. 1. JobTracker节点损坏 这是Hadoop集群中最为严重的错误. 出现了这种错误,那就只能重新选择JobTracker节点,而在选择期,所有的任务都必须停掉,而且当前已经完成了的任务也必须通通重来. 2.

hbase 学习(十五)缓存机制以及可以利用SSD作为存储的BucketCache

下面介绍Hbase的缓存机制: a.HBase在读取时,会以Block为单位进行cache,用来提升读的性能 b.Block可以分类为DataBlock(默认大小64K,存储KV).BloomBlock(默认大小128K,存储BloomFilter数据).IndexBlock(默认大小128K,索引数据,用来加快Rowkey所在DataBlock的定位) c.对于一次随机读,Block的访问顺序为BloomBlock.IndexBlock.DataBlock,如果Region下面的StoreFi

php中的错误处理机制

1.如果没有错误处理机制会怎样? 案例1: <?php  $fp=fopen("aa.txt","r");//打开文件,没有验证,是否存在该文件?  echo "ok";   ?> 结果: Warning: fopen(aa.txt) [function.fopen]: failed to open stream: No such file or directory in E:\Software_default\wamp_wwwroo

linux系统编程之错误处理机制

在讲解liunx错误处理机制之前我们先来看一段代码: 1 #include<sys/types.h> 2 #include<sys/stat.h> 3 #include<fcntl.h> 4 #include<stdio.h> 5 #include<stdlib.h> 6 7 int main(void) 8 { 9 int fd; 10 fd=open("abc",O_WRONLY); 11 if(fd<0){ 12

关于面向切面编程的部分内容-错误处理机制

错误处理机制. 面对多个web服务器,多线程处理,我们想把错误信息记录到一个txt文档中. 但是把错误信息写到内存是很快.写到硬盘上就有一堆的问题.比如说读写慢.并发问题. 今天我们就利用这个实现错误处理 此文以MVC为例 1.首先要在  golable  文件的  protected void Application_Start() 注册一个错误处理机制. MVC中自带一个  过滤器 FilterConfig.RegisterGlobalFilters(GlobalFilters.Filter

php中错误处理机制

php中,异常处理机制是有限的,无法自动抛出异常,必须手动进行,并且内置异常有限. php把许多异常看作错误,这样就可以把这些异常想错误一样用set_error_handler接管,进而主动抛出异常. 比如以下warning类型的错误是捕获不到的 :   Warning: Division by zero in 1 try{ 2 $a = 5/0; 3 }catch (Exception $e){ 4 echo '错误信息:',$e->getMessage(); 5 } 使用set_error_

hadoop 错误处理机制

hadoop 错误处理机制 1.硬件故障 硬件故障是指jobtracker故障或TaskTracker 故障 jobtracker是单点,若发生故障,目前hadoop 还无法处理,唯有选择最牢靠的硬件作为jobtracker jobtracker通过心跳(周期1分钟) 信号来了解TaskTracker 是否发生故障或者负载过重 jobtracker 将从任务节点列表中移除发生故障的TaskTracker 如果故障节点在执行map任务并且尚未完成,jobtracker 会要求其他节点 重新执行 次