IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring Boot之异常处理 -> 正文阅读

[Java知识库]Spring Boot之异常处理

关于异常的理解

首先要清楚,一切异常对系统来说,都是不正常的表现,尽管有时由于业务处理的需要我们会主动抛出一些异常,但也不意味对这些异常可以不管不顾,总有一个地方需要对自己抛出的异常进行特殊处理。
在日常开发中,我们应该尽量提高系统可用性,最大限度的避免任何异常的出现,而不是去指望完善异常处理来完善系统。
异常处理是异常无法避免的出现后而采取的一种应急措施,主要目的是对外增加友好性,对内提供补救措施。
异常处理很重要,但不要因此就认为完善的异常处理是系统核心,不要指望异常处理尽善尽美,不要指望异常处理来给系统缺陷擦屁股;
如果系统异常过多,那么我们要做的不是去尽可能的完善异常处理机制,而是要好好去反思:系统架构设计是否合理,系统逻辑设计是否合理。

Spring Boot 中全局异常处理

在spring boot中提供了默认的异常处理机制:Spring Boot 默认提供了程序出错的结果映射路径/error。这个/error请求会在BasicErrorController中处理,其内部是通过判断请求头中的Accept的内容是否为text/html来区分请求是来自客户端浏览器(浏览器通常默认自动发送请求头内容Accept:text/html)还是客户端接口的调用,以此来决定返回页面视图还是 JSON 消息内容。
默认返回的视图或Json消息内容如下:

{
    "timestamp": "2018-05-12T06:11:45.209+0000",
    "status": 404,
    "error": "Not Found",
    "message": "No message available",
    "path": "/index.html"
} 

在这里插入图片描述
很显然,把这样的响应结果返回给前端或者浏览器不太友好。在实际开发中,如果需要返回页面,我们也是希望返回公司自定义的统一的错误页面,而不是“Whitelabel Error Page”;如果要返回json也最好是公司统一规定格式的json,这样有利于前后端分离更好的协作。幸运的是,在Spring boot中我们可以实现这样的愿望。

@ControllerAdvice+ @ExceptionHandler

这种组合可以实现全局的异常统一处理,既可以返回json格式的结果,也可以返回指定的错误页。事实上,@ControllerAdvice+ @ExceptionHandler这种组合方式并不是spring boot特有的,而是spring提供的异常处理方式,使用如下:

@ControllerAdvice
public class GlobalExceptionController {

	//返回json格式的响应结果
    @ExceptionHandler(RuntimeException.class)
    @ResponseBody
    public BaseResp exceptionHandler(RuntimeException e, HttpServletResponse response) {
        BaseResp resp = new BaseResp();
        resp.setCode(300);
        resp.setMsg("未知错误");
        return resp;
    }

	//返回页面 ,这里有多种实现方式,错误页面如何放置取决于我们使用什么样的模板引擎或者是否使用模板引擎,这里不多讲述,网上有大把的参考样例,这里想说的是,现在基本都是前后端分离的开发模式,所以这种直接返回页面的方式其实很少使用
    @ExceptionHandler(value = Exception.class)
    public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        ModelAndView mav = new ModelAndView();
        mav.addObject("exception", e);  //异常内容(页面展示)
        mav.addObject("url", req.getRequestURL()); //请求的url地址(页面展示)
        mav.setViewName("error"); //设置视图名称
        return mav;
    }

}

注解解释:

  • @ControllerAdvice:属于类注解,被此注解标识的类可以处理全局的异常
  • @ExceptionHandler:属于方法注解,用于指定此方法可以处理的异常类型,如:@ExceptionHandler(value = Exception.class)

注意事项:
@ControllerAdvice+ @ExceptionHandler虽然可以处理全局的异常,但是这种方式只能处理应用级别的异常,有一些容器级别的异常它就无能为力了,例如Filter抛出异常,若需要处理这类容器级别的异常,我们只须要提供自定义的ErrorController便可,自定义的ErrorController有两种方式:一种是实现ErrorController接口,另外一种是直接继承BasicErrorController,因为接口只提供一个待实现的方法,而BasicErrorController已实现了不少功能,所以我们可以选择继承BasicErrorController来实现自己的ErrorController。

有时还会遇到@RestontrollerAdvice注解,它相当于@ResponseBody + @ControllerAdvice,如果我们的全局异常处理类中的方法返回的都是Json格式的结果,那就可以在类上使用@RestontrollerAdvice注解,同时可以省去每个方法上的@ResponseBody注解。

另外,如果我们希望全局异常处理类只特定的处理某些Controller的异常,可以通过@ControllerAdvice的basePackages属性来指定范围。

除了全局异常处理,还有局部异常处理 @Controller + @ExceptionHandler
局部异常处理就是在@Controller类中定义一个被@ExceptionHandler注解的异常处理方法,当此Controller中的方法抛出异常且异常类型符合@ExceptionHandler指定的异常类型时,就会被异常处理方法捕获并处理,但是这个异常处理方法作用的范围仅限于此Controller。

@Controller
public class GlobalExceptionController {
    @Autowired
    private UserService userService;

    @RequestMapping("/test1")
    @ResponseBody
    public User test1(int userId) {
        return userService.getUser(userId);
    }

    @ExceptionHandler(value = Exception.class) 
    public BaseResp defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        BaseResp resp = new BaseResp();
        resp.setCode(300);
        resp.setMsg("未知错误");
        return resp;
    }
}

ErrorController接口实现全局异常处理

上面说过@ControllerAdvice只能统一处理应用级别的异常,而对于容器级别的异常,如Filter异常,@ControllerAdvice就无能为力了,这时就需要我们自定义ErrorController来处理全局异常,具体方式有两种:一种是实现ErrorController接口,另外一种是直接继承BasicErrorController。因为BasicErrorController本身就实现了ErrorController接口,并提供了额外的功能,所以这里使用继承BasicErrorController的方式来实现全局异常处理。
事实上,通过观察 BasicErrorController 可以发现,它处理的就是 /error 请求,所以我们只需要继承 BasicErrorController 之后,重写 /error方法,然后在 error() 方法里面对全局异常进行统一处理即可。代码如下:

@RestController
public class GlobalExceptionController extends BasicErrorController {

    private static final Logger log = LoggerFactory.getLogger(ErrorController.class);

    public ErrorController() {
        super(new DefaultErrorAttributes(), new ErrorProperties());
    }

    /**
     * produces 设置返回的数据类型:application/json
     *
     * @param request 请求
     * @return 自定义的返回实体类
     */
    @Override
    @RequestMapping(value = "", produces = {MediaType.APPLICATION_JSON_VALUE})
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
        HttpStatus status = getStatus(request);
        // 获取错误信息
        String message = body.get("message").toString();
        int code = EnumUtil.getCodeByMsg(message, ResultEnum.class);

        HttpStatus httpStatus;
        if (code == 500) {
            // 服务端异常,状态码为500
            httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
        } else {
            // 其余异常(手动throw)为逻辑校验,状态码为200
            httpStatus = HttpStatus.OK;
        }
        return new ResponseEntity(Result.failed(code, message), httpStatus);
    }

}
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-11 21:59:56  更:2022-03-11 22:02:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 10:33:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码