sprngboot2.0+shiro+jwt 过滤器中的自定义异常不能被全局异常拦截

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/AinUser/article/details/100038270

情境:

     其他的地方自定义异常的拦截,都是好使的,但是过滤器中的不行,找了两天,才找到问题在这儿

我还想这是为啥呢,真是邪门了

     网上好多说是拦截不了的,然后我找了好久是可以拦截,但是拦截后抛出的是500,并不是自定义异常

不过也可以变相的处理,获取到抛出的自定义异常文字,再一次包装抛出,拦截的方案如下

package com.read.data.bi_statistics.cms.exception;

import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorViewResolver;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
  * @author: tianyong
  * @time: 2019/8/21 10:46
  * @description:
  */
@RestControllerAdvice
public class ChainExceptionHandler extends BasicErrorController {


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


    public ChainExceptionHandler(ErrorAttributes errorAttributes, ErrorProperties errorProperties) {
        super(errorAttributes, errorProperties);
    }


    public ChainExceptionHandler(ErrorAttributes errorAttributes, ErrorProperties errorProperties, List<ErrorViewResolver> errorViewResolvers) {
        super(errorAttributes, errorProperties, errorViewResolvers);
    }



    /**
      * @author: tianyong
      * @time: 2019/8/21 10:46
      * @description:处理传过来的异常(解决自定义全局异常捕获不到的问题)
      */
    @Override
    @RequestMapping(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 code=body.get("status").toString();
        String message = body.get("message").toString();
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("code",code);
        map.put("msg",message);
        return new ResponseEntity<Map<String, Object>>(map, status);
    }

}

     由于我的代码里面有了对于错误状态码,抛出的异常会先走到错误码,之后才会走到拦截的这里,所以

没有采用上面的拦截方案

package com.read.data.bi_statistics.cms.exception;

import com.read.data.bi_statistics.cms.data.enums.CodeInfo;
import com.read.data.bi_statistics.cms.entity.ReturnBone;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import static com.read.data.bi_statistics.authority.utils.JwtUtil.checkChar;
import static com.read.data.bi_statistics.cms.common.Utils.error;

/**
 * @author: tianyong
 * @Time: 2019/7/15 15:54
 * @description:状态码配置类
 */
@Controller
public class StatusCodeExceptionHandler implements ErrorController {


    /**
      * @author: tianyong
      * @time: 2019/7/16 11:36
      * @description:指定跳转路径/error
      */
    @Override
    public String getErrorPath() {
        return "/error";
    }

    /**
      * @author: tianyong
      * @time: 2019/7/16 11:37
      * @description:处理错误状态码
      */
    @RequestMapping("/error")
    public String handleError(HttpServletRequest request) {
        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        Exception attribute = (Exception)request.getAttribute("javax.servlet.error.exception");
        if(statusCode == 400) {
            return "/400";
        }else if(statusCode == 401) {
            return "/401";
        }else if(statusCode == 403) {
            return "/403";
        }else if(statusCode == 404) {
            return "/404";
        }else if(statusCode == 405) {
            return "/405";
        }else if(statusCode == 500) {
            //处理全局异常无法捕获过滤器中自定义异常问题
            String message = attribute.getCause().getMessage();
            if(checkChar(message)){
                return "/401";
            }else{
                return "/500";
            }
        }else{
            return "/500";
        }
    }


    /**
      * @author: tianyong
      * @time: 2019/7/15 16:14
      * @description:400 请求无效
      */
    @ResponseBody
    @RequestMapping("/400")
    public ReturnBone error400 (){
        return error(CodeInfo.STATUS_CODE_400);
    }


    /**
      * @author: tianyong
      * @time: 2019/8/15 14:16
      * @description:401 用户认证失败
      */
    @ResponseBody
    @RequestMapping("/401")
    public ReturnBone error401 (){
        return error(CodeInfo.STATUS_CODE_401);
    }


    /**
     * @author: tianyong
     * @time: 2019/7/15 16:14
     * @description:403 禁止访问
     */
    @ResponseBody
    @RequestMapping("/403")
    public ReturnBone error403 (){
        return error(CodeInfo.STATUS_CODE_403);
    }


    /**
     * @author: tianyong
     * @time: 2019/7/15 16:14
     * @description:404 请求的网页不存在
     */
    @ResponseBody
    @RequestMapping("/404")
    public ReturnBone error404 (){
        return error(CodeInfo.STATUS_CODE_404);
    }


    /**
     * @author: tianyong
     * @time: 2019/7/15 16:14
     * @description:405 资源被禁止
     */
    @ResponseBody
    @RequestMapping("/405")
    public ReturnBone error405 (){
        return error(CodeInfo.STATUS_CODE_405);
    }


    /**
     * @author: tianyong
     * @time: 2019/7/15 16:14
     * @description:500 内部服务器错误,请联系管理员
     */
    @ResponseBody
    @RequestMapping("/500")
    public ReturnBone error500 (){
        return error(CodeInfo.STATUS_CODE_500);
    }

}

我最后采用的方案是:第一个代码块,里面的500错误里面,我又根据抛出的自定义异常中的文字,区分与普通500异常

然后只要是有文字的都跳转401,没有做具体的区分,但是你们也可以根据具体的文字信息,再进行封装抛出自定义异常

if(authorization == null){
    loggers.error("获取token失败!");
    throw new AuthenticationException("获取token失败!");
}

或者还有种方式,我见其他的文章有的没有在过滤器中处理,而是在拦截器里面处理的,请求->过滤器->拦截器是这个访问顺序

猜你喜欢

转载自blog.csdn.net/AinUser/article/details/100038270