问题复现

发送了一个请求,但拦截器拦截了两个请求,打断点一看
好家伙,还拦截了/error,查资料才发现:
SpringBoot 默认提供了一个全局的 handler 来处理所有的 HTTP 错误, 并把它映射为 /error。当发生一个错误,例如系统异常抛出了Exception,SpringBoot会将页面重定向到 /error 中。
所以当请求/user/generate时,拦截器拦截该请求,处理请求时发生错误,默认全局的 handler把它映射为/error,因此拦截器会再次拦截/error请求。这会多进行一次系统处理,消耗了宝贵的系统资源。
解决方法
需要关闭工程中的资源文件建立映射
1
| spring.resources.add-mappings=false
|
1 2 3
| spring: resources: add-mappings: false
|
效果
只log.error了一次图中所示的内容

问题代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| package com.gxmzu.score.interceptor;
import com.gxmzu.score.domain.entity.User; import com.gxmzu.score.exception.AccessDeniedException; import com.gxmzu.score.service.TokenService; import com.gxmzu.score.service.VerifyUser; import com.gxmzu.score.utils.HttpStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView;
import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
public class GlobalInterceptor implements HandlerInterceptor {
private static final Logger log = LoggerFactory.getLogger(GlobalInterceptor.class);
@Resource private TokenService tokenService;
@Resource private VerifyUser verifyUser;
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { User user = tokenService.getUser(request); String url = request.getRequestURI(); if (user == null) { throw new AccessDeniedException("未认证", HttpStatus.UNAUTHENTICATED); } if (!verifyUser.verify(url, user)) { log.error("用户:{" + user.getUserName() + "}请求越权接口"); throw new AccessDeniedException("未授权", HttpStatus.UNAUTHORIZED); } tokenService.verifyToken(user); return true; }
@Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
} }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
| package com.gxmzu.score.exception;
import com.gxmzu.score.domain.AjaxResult; import com.gxmzu.score.utils.HttpStatus; import com.gxmzu.score.utils.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.validation.BindException; import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
@RestControllerAdvice public class GlobalExceptionHandler extends RuntimeException {
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(AccessDeniedException.class) public AjaxResult handleAccessDeniedException(AccessDeniedException e, HttpServletRequest request) { String requestURI = request.getRequestURI(); Integer code = e.getCode(); log.error("请求地址'{}',权限校验失败'{}'", requestURI, e.getMessage()); return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(HttpStatus.ERROR, e.getMessage()); }
@ExceptionHandler(HttpRequestMethodNotSupportedException.class) public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e, HttpServletRequest request) { String requestURI = request.getRequestURI(); log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod()); return AjaxResult.error(HttpStatus.NO_SUPPORT_REQUEST_METHOD, e.getMessage()); }
@ExceptionHandler(ServiceException.class) public AjaxResult handleServiceException(ServiceException e, HttpServletRequest request) { log.error(e.getMessage(), e); Integer code = e.getCode(); return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(HttpStatus.ERROR, e.getMessage()); }
@ExceptionHandler(RuntimeException.class) public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request) { String requestURI = request.getRequestURI(); log.error("请求地址'{}',发生未知异常.", requestURI, e); return AjaxResult.error(HttpStatus.ERROR, e.getMessage()); }
@ExceptionHandler(Exception.class) public AjaxResult handleException(Exception e, HttpServletRequest request) { String requestURI = request.getRequestURI(); log.error("请求地址'{}',发生系统异常.", requestURI, e); return AjaxResult.error(HttpStatus.ERROR, e.getMessage()); }
@ExceptionHandler(BindException.class) public AjaxResult handleBindException(BindException e) { log.error(e.getMessage(), e); String message = e.getAllErrors().get(0).getDefaultMessage(); return AjaxResult.error(HttpStatus.ERROR, message); }
@ExceptionHandler(MethodArgumentNotValidException.class) public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { log.error(e.getMessage(), e); String message = e.getBindingResult().getFieldError().getDefaultMessage(); return AjaxResult.error(HttpStatus.ERROR, message); }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| package com.gxmzu.score.exception;
public class AccessDeniedException extends RuntimeException {
private Integer code;
private String message;
public AccessDeniedException() { }
public AccessDeniedException(String msg, Integer code) { this.code = code; this.message = msg; }
public Integer getCode() { return this.code; }
public void setCode(Integer code) { this.code = code; }
@Override public String getMessage() { return this.message; }
public void setMessage(String message) { this.message = message; } }
|
参考文章
springboot全局异常处理中的404的/error重复拦截问题