Spring Boot 2.X 学习日记——搞定全局异常

前言

在实际项目中,程序往往会出现各种各样的异常。而针对这些异常,如果我们不做处理,直接抛出到页面的话,不仅不友好,而且会给一些别有用心的人制造空当。所以,处理这些异常信息显然是十分必要的。

异常处理

在笔者以往的开发经验中,程序中针对异常的处理,往往采取这种方式

public Map test(){
  Map<String,String> result = new HashMap<>();
  try {
    //业务代码
    result.put("code","200");
    result.put("msg","请求成功");
  } catch (Exception e){
    logger.error("请求失败",e.getLocalizedMessage(),e);
    result.put("code","500");
    result.put("msg","请求失败");
  }

  return result;
}

这样写,虽然没问题,也是处理异常的一种方式,但看上去一点也不优雅。这里捕获的是Exception,并没有针对其子异常去做特殊处理。假如我们需要处理更多异常的返回信息的话,这里就需要写更多的catch块,显然一点也不优雅。

那么,在Spring Boot中如何处理这诸多的异常呢?下面笔者将带着大家一起来了解Spring Boot中的异常处理方式。

@ControllerAdvice 和 @RestControllerAdvice

Spring 3.2以后,新增了一个注解**@ControllerAdvice**。在该注解标识的类下,我们不仅对请求数据做处理,同时,也可以通过在方法上标识**@ExceptionHandler**的注解,来针对某个或某几个异常进行处理。

而在Spring 4.2以后,新增的**@RestControllerAdvice注解,则在原来@ControllerAdvice**的基础上做了进一步的加强。

编码

讲到这,相信读者朋友对我接下来的处理异常方式,心中已经有了大概的答案了吧。没错,笔者采用的就是**@ControllerAdvice加上@ExceptionHandler**的方式来处理异常。

  1. 新建GlobalExceptionHandler.java,用来处理控制层抛出的异常

    package com.boot.demo.controller;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.lang.Nullable;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RestControllerAdvice;
    import org.springframework.web.context.request.WebRequest;
    
    import java.util.HashMap;
    import java.util.Map;
    
    @RestControllerAdvice
    public class GlobalExceptionHandler {
    
        private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
    
        /**
         * 处理异常
         * @param ex
         * @return
         */
        @ExceptionHandler(Exception.class)
        public Map exceptionHandler(Exception ex){
            logger.error("请求失败",ex.getLocalizedMessage(),ex);
            Map<String,Object> result = new HashMap<>();
            result.put("code",500);
            result.put("msg","请求失败");
            return result;
        }
    }
    
    
  2. 为了进一步处理Spring中抛出的异常,我们需要对GlobalExceptionHandler.java作出一点改变

    package com.boot.demo.controller;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.lang.Nullable;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RestControllerAdvice;
    import org.springframework.web.context.request.WebRequest;
    import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
    
    import java.util.HashMap;
    import java.util.Map;
    
    @RestControllerAdvice
    public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
    
        private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
    
        /**
         * 处理异常
         * @param ex
         * @return
         */
        @ExceptionHandler(Exception.class)
        public Map exceptionHandler(Exception ex){
            logger.error("请求失败",ex.getLocalizedMessage(),ex);
            Map<String,Object> result = new HashMap<>();
            result.put("code",500);
            result.put("msg","请求失败");
            return result;
        }
    
        /**
         * 处理Spring内部异常
         * @param ex
         * @param body
         * @param headers
         * @param status
         * @param request
         * @return
         */
        protected ResponseEntity<Object> handleExceptionInternal(
                Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
            logger.info("服务器端响应失败,status : {},ex : {}",status.getReasonPhrase(),ex);
            Map<String,Object> result = new HashMap<>();
            result.put("code",status.value());
            result.put("msg",ex.getLocalizedMessage());
            return new ResponseEntity<>(result,HttpStatus.OK);
        }
    }
    

到这里,处理异常的逻辑就写完了,下面我们新建一个Controller,用于测试吧。

TestController.java

package com.boot.demo.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
public class TestController {

    private static final Logger logger = LoggerFactory.getLogger(TestController.class);


    @RequestMapping("test")
    public Map test(){
        Map<String,String> result = new HashMap<>();
        try {
            //业务代码
            result.put("code","200");
            result.put("msg","请求成功");
        } catch (Exception e){
            logger.error("请求失败",e.getLocalizedMessage(),e);
            result.put("code","500");
            result.put("msg","请求失败");
        }

        return result;
    }

    @RequestMapping("test2")
    public Map test2(){
        Map<String,String> result = new HashMap<>();
        int i = 10 / 0;
        result.put("code","200");
        result.put("msg","请求成功");
        return result;
    }
}

测试

启动项目,访问http://localhost:8080/test2,返回内容如下

在这里插入图片描述

全文代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值