搭建springboot+shiro+jwt的时候,发现RestControllerAdvice全局异常处理无法获取filter中的异常
记一次RestControllerAdvice无法拦截Filter内抛出异常
原因
请求进来 会按照 filter -> interceptor -> controllerAdvice -> aspect -> controller的顺序调用
当controller返回异常 也会按照controller -> aspect -> controllerAdvice -> interceptor -> filter来依次抛出
这种Filter发生的404、405、500错误都会到Spring默认的异常处理。如果你在配置文件配置了server.error.path的话,就会使用你配置的异常处理地址,如果没有就会使用你配置的error.path路径地址,如果还是没有,默认使用/error来作为发生异常的处理地址。如果想要替换默认的非Controller异常处理直接实现Spring提供的ErrorController接口就行了
方法一
新建MyErrorController并继承BasicErrorController
import cn.hutool.core.util.ObjectUtil;
import com.iof.upms.common.result.Result;
import io.swagger.annotations.Api;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
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.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
@RestController
@Api(value = "filter错误处理", description = "filter错误处理")
public class MyErrorController extends BasicErrorController {
public MyErrorController() {
super(new DefaultErrorAttributes(), new ErrorProperties());
}
@Override
@RequestMapping(produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
getErrorProperties().setIncludeException(true);
getErrorProperties().setIncludeMessage(ErrorProperties.IncludeAttribute.ALWAYS);
getErrorProperties().setIncludeStacktrace(ErrorProperties.IncludeAttribute.ALWAYS);
Map<String, Object> body = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL));
HttpStatus status = getStatus(request);
//错误信息
Object obj = body.get("message");
//获取异常信息
String exception = String.valueOf(body.get("exception"));
//如果是shiro异常则返回666,否则返回500
int code = "org.apache.shiro.authc.AuthenticationException".equals(exception) ? 666 : 500;
return new ResponseEntity(Result.error(code, ObjectUtil.isNull(obj) ? "系统异常,请重新登录!" : String.valueOf(obj)), HttpStatus.OK);
}
}
方法二
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
@RestController
public class ErrorControllerImpl implements ErrorController {
@Override
public String getErrorPath() {
return "/error";
}
@RequestMapping("/error")
public void handleError(HttpServletRequest request) throws Throwable {
if (request.getAttribute("javax.servlet.error.exception") != null) {
throw (Throwable) request.getAttribute("javax.servlet.error.exception");
}
}
}