解决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监控