Springboot学习(十一) 解决springboot/springmvc过滤器内的错误抛不出的问题

解决springboot/springmvc过滤器内的错误抛不出的问题

springboot过滤器出现异常可能会用@RestControllerAdvice
或@ControllerAdvice处理不到,那么可以按下面方式处理

1 定义错误处理页面
 @Configuration
public class ErrorPageConfig implements ErrorPageRegistrar {
    @Override
    public void registerErrorPages(ErrorPageRegistry registry) {
        registry.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/404"));
        registry.addErrorPages(new ErrorPage(HttpStatus.FORBIDDEN, "/403"));
        registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/400"));
        registry.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500"));
    }
}   
2 在500错误处,获取request里的javax.servlet.error.exception,这是servlet规范规定的方式,肯定能获取到,
在这里根据获取异常抛出一个自己的异常

@RestController
public class ErrorPageController {
    @Value("${spring.servlet.multipart.max-file-size}")
    private String maxFileSize;
    @RequestMapping(value = "/401", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity to401(){
        ResponseEntity responseEntity = new ResponseEntity();
        responseEntity.setStatus(401);
        responseEntity.setMessage("未登录");
        return responseEntity;
    }

    @RequestMapping(value = "/403", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity to403(){
        ResponseEntity responseEntity = new ResponseEntity();
        responseEntity.setStatus(403);
        responseEntity.setMessage("没有权限");
        return responseEntity;
    }

    @RequestMapping(value = "/404", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity to404(){
        ResponseEntity responseEntity = new ResponseEntity();
        responseEntity.setStatus(404);
        responseEntity.setMessage("找不到资源");
        return responseEntity;
    }

    @RequestMapping(value = "/502", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity to502(){
        ResponseEntity responseEntity = new ResponseEntity();
        responseEntity.setStatus(502);
        responseEntity.setMessage("网关错误");
        return responseEntity;
    }
    @RequestMapping(value = "/400", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity to400(){
        ResponseEntity responseEntity = new ResponseEntity();
        responseEntity.setStatus(400);
        responseEntity.setMessage("请求无效");
        return responseEntity;
    }
    @RequestMapping(value = "/500", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity to500() throws Exception {
//        ResponseEntity responseEntity = new ResponseEntity();
//        responseEntity.setStatus(400);
//        responseEntity.setMessage("请求无效");
//        return responseEntity;
        HttpServletRequest request = SpringUtils.getRequest();
        Object attribute = request.getAttribute("javax.servlet.error.exception");
        //如果是文件太大了异常 抛处错误给前台
        if(attribute != null && attribute instanceof IllegalStateException ){
            IllegalStateException exception = (IllegalStateException) attribute;
            Throwable cause = exception.getCause();
            //TODO 这里耦合的Undertow的包,如果以后替为tomcat这段要删除或作其他处理
            if(cause != null && cause instanceof MultiPartParserDefinition.FileTooLargeException){
                throw new OptoconException("文件大小超过限制,最大限制" + maxFileSize, ((Exception)attribute).getMessage());
            }

        }
        throw new Exception("服务器内部错误");
    }

}
3 这样就可以在RestControllerAdvice处理了
@RestControllerAdvice
@Component
@Slf4j
//@CrossOrigin
public class ExceptionAdivisor {
    @Autowired
    private CrosProps crosProps;

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResponseEntity to400(MethodArgumentNotValidException e){
        ResponseEntity responseEntity = new ResponseEntity(HttpStatus.BAD_REQUEST.value(), "请求参数校验失败");
        StringBuilder result = new StringBuilder();
        result.append("error 400 :");
        BindingResult bindingResult = e.getBindingResult();
        List<FieldError> errors = bindingResult.getFieldErrors();
        if(errors != null){
            for (FieldError error: errors) {
                String field = error.getField();
                String msg = error.getDefaultMessage();
                // 这里可以使用field 和msg 组合成返回的内容,这里就是做一个拼接
                result.append(field).append(",").append(msg).append(";");
            }
        }
        responseEntity.setDesc(result.toString());
        log.error("请求参数有误",e);
        setResponseCros();
        return responseEntity;
    }

    @ExceptionHandler(value = ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResponseEntity to400(ConstraintViolationException e){
        ResponseEntity responseEntity = new ResponseEntity(HttpStatus.BAD_REQUEST.value(), "请求参数校验失败");
        StringBuilder result = new StringBuilder();
        result.append("error 400 :");
        Set<ConstraintViolation<?>> cvs = e.getConstraintViolations();
        if(cvs != null){
            for (ConstraintViolation cv: cvs) {
                Path path = cv.getPropertyPath();
                String msg = cv.getMessage();
                result.append(path).append(",").append(msg).append(";");

            }
        }
        responseEntity.setDesc(result.toString());
        log.error("请求参数有误",e);
        setResponseCros();
        return responseEntity;
    }

    @ExceptionHandler(value = LoginException.class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public ResponseEntity loginException(LoginException e){
        ResponseEntity responseEntity = new ResponseEntity(HttpStatus.UNAUTHORIZED.value(), e.getMessage());
        responseEntity.setDesc(e.getMsgDetail() != null ? e.getMsgDetail() : getMessage(e));
        responseEntity.setMessage(e.getMessage());
        HttpSession session = SpringUtils.getSession();
        String data = RandomStringUtils.randomStr(16);
        responseEntity.setData(data);
        session.setAttribute(SESSION_LOGIN_KEY, data);
        log.error("异常", e);
        setResponseCros();
        return responseEntity;
    }

    @ExceptionHandler(value = OptoconRunTimeException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseEntity to500(OptoconRunTimeException e){
        ResponseEntity responseEntity = new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());
        responseEntity.setDesc(e.getMsgDetail() != null ? e.getMsgDetail() : getMessage(e));
        responseEntity.setMessage(e.getMessage());
        log.error("异常", e);
        setResponseCros();
        return responseEntity;
    }

    @ExceptionHandler(value = OptoconException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseEntity to500(OptoconException e){
        ResponseEntity responseEntity = new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());
        responseEntity.setDesc(e.getMsgDetail() != null ? e.getMsgDetail() : getMessage(e));
        responseEntity.setMessage(e.getMessage());
        log.error("异常", e);
        setResponseCros();
        return responseEntity;
    }
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseEntity to500(MaxUploadSizeExceededException e){
        ResponseEntity responseEntity = new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR.value(), "上传文件大小超过限制");
//        responseEntity.setMessage(e.getMessage());
        responseEntity.setDesc(getMessage(e));
        responseEntity.setMessage("文件上传大小超过限制");
        log.error("异常", e);
        setResponseCros();
        return responseEntity;
    }

    @ExceptionHandler(value = Throwable.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseEntity to500(Throwable throwable){
//        throwable.printStackTrace();
        ResponseEntity responseEntity = new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR.value(), "服务器内部错误");
//        responseEntity.setDesc(throwable.getMessage());
        responseEntity.setDesc(getMessage(throwable));
        log.error("异常", throwable);
        setResponseCros();
        return responseEntity;
    }

    private void setResponseCros(){
        HttpServletRequest request = SpringUtils.getRequest();
        HttpServletResponse response = SpringUtils.getResponse();
        String origin = request.getHeader("Origin");
        if (origin == null || "null".equals(origin)) {
            origin = crosProps.getOrigin();
        }
        response.setHeader("Access-Control-Allow-Origin", origin);
        response.setHeader("Access-Control-Allow-Credentials", crosProps.getCredentials());//服务器同意客户端发送cookies
        response.setHeader("Access-Control-Allow-Methods", crosProps.getMethods());
        response.setHeader("Access-Control-Allow-Headers", crosProps.getHeaders());

    }

    /**
     * 递归获取异常的message
     * */
    private String getMessage(Throwable throwable){
        String message = null;
        if(throwable != null){
            String message1 = throwable.getMessage();
            if(message1 != null){
                return message1;
            }else{
                Throwable cause = throwable.getCause();
                return getMessage(cause);
            }
        }
        return message;
    }


}

上一篇 springboot 添加druid监控,开启慢日志,配置spring监控

下一篇 springboot 使用redis实现session共享

猜你喜欢

转载自blog.csdn.net/u011943534/article/details/82468173