springboot 之 异常

ErrorController、RestControllerAdvice、ResponseEntityExceptionHandler、HandlerInterceptor

在java web中,原生listenerfilterservlet执行顺序为:

Listener------>Filter----->Servlet

而在SpringMVC中,实质就是一个DispatchServlet

而在Servlet中,则是调用了HandlerInterceptor的各个方法,和最后ExceptionHandler处理,调用顺序会变成:

Listener------>Filter----->DispatchServlet ---->HandlerInterceptor.preHandle---->handle---->HandlerInterceptor. postHandle------>ExceptionHandler

所以,在调用过程中,HandlerInterceptor是在Filter调用之后,而ExceptionHandler异常处理也是在Filter之后,同理可得,Filter中的异常是不能被ExceptionHandler处理的。

Spring @ControllerAdvice vs ErrorController

An implementation of the ErrorController is used to provide a custom whitelabel error page.

A class annotated with @ControllerAdvise is used to add a global exception handling logic for the whole application. Thus, more than one controller in your application.

错误访问


import com.Utils.ReturnCode;
import com.Utils.ReturnVO;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

/**
 * 在项目中我们遇到404找不到的错误、或者500服务器错误都需要配置
 * 相应的页面给用户一个友好的提示,而在Spring Boot中我们需要如何设置。
 * 我们需要实现ErrorController接口,重写handleError方法。
 * 处理请求要放到启动类下面
 */
@RestController
public class ExceptionHandler implements ErrorController {
    @Override
    public String getErrorPath() {
        /**
         * 设置当错误时返回的页面
         */
        return null;
//        return "/404";
    }

    @RequestMapping(value = "/error")
    public ReturnVO handleError(HttpServletRequest request){
        //获取statusCode:401,404,500
//        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code")
//        if(statusCode == 401){
//            return "/401";
//        }else if(statusCode == 404){
//            return "/404";
//        }else if(statusCode == 403){
//            return "/403";
//        }else{
//            return "/500";
//        }
        return new ReturnVO(ReturnCode.URL_ERROR);
    }
}

控件处理异常捕获

import com.Utils.ReadPropertiesUtil;
import com.Utils.ReturnCode;
import com.Utils.ReturnVO;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.Properties;

/**
 * 用于全局返回json,如需返回ModelAndView请使用ControllerAdvice
 * 继承了ResponseEntityExceptionHandler,对于一些类似于请求方式异常的异常进行捕获
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    private static Properties properties = ReadPropertiesUtil.getProperties(null);

    /**
     * 异常捕获
     * @param e 捕获的异常
     * @return 封装的返回对象
     **/
    @ExceptionHandler(value = Exception.class)
    public String handlerException(Exception e) {
        ReturnVO returnVO = new ReturnVO();
        String errorName = e.getClass().getName();
        errorName = errorName.substring(errorName.lastIndexOf(".") + 1);
        //如果没有定义异常,而是直接抛出一个运行时异常,需要进入以下分支
        if (e.getClass() == RuntimeException.class) {
            returnVO.setMsg(properties.getProperty(ReturnCode.valueOf("EXCEPTION").msg()) +": "+ e.getMessage());
            returnVO.setCode(properties.getProperty(ReturnCode.valueOf("EXCEPTION").val()));
        } else {
            returnVO.setMsg(properties.getProperty(ReturnCode.valueOf(errorName).msg()));
            returnVO.setCode(properties.getProperty(ReturnCode.valueOf(errorName).val()));
        }
        return returnVO.toString();
    }
}

测试代码:

    @RequestMapping(value = "/test")
    public ReturnVO test() {
        throw new RuntimeException("测试非自定义运行时异常");
    }

测试结果:

以上两种方法都是针对Controller层的异常进行捕获。针对过滤器或者拦截器的异常,一般处理方法是将异常捕获,并转发到controller,专门处理异常。

举例:

过滤器中

try{
	...
} catch (BusinessException e) {
	// 解决异常,全局异常处理器捕获不到的问题
	request.setAttribute("exception", e);
	request.getRequestDispatcher("/business/error").forward(request, response);
}

controller层

@Controller
@RequestMapping(value = "/business")
public class BusinessErrorController {
    @RequestMapping("/error")
    public void error(HttpServletRequest request) throws BusinessException {
        throw (BusinessException) request.getAttribute("exception");
    }
}

这样就可以像处理controller层的异常一样处理过滤器和拦截器中的异常了。

参考网址:

Spring @ControllerAdvice vs ErrorController - Stack Overflow

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值