由于Filter异常Spring MVC无法进行统一处理,所以需要手动处理一下异常
定义一个Filter,这个Filter位于所有Filter的最前面,当其他Filter发生异常,捕获异常栈,然后转发到ErrorController
@Slf4j
public class ExceptionFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("ex filter init .......");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 是否已经放有异常栈, 避免循环
boolean isRethrow = !Objects.isNull(request.getAttribute(Req.Attr.EX));
if (isRethrow) {
chain.doFilter(request, response);
return;
}
try {
chain.doFilter(request, response);
} catch (AbstractCustomException e) {
// 发生异常,保存异常栈
request.setAttribute(Req.Attr.EX, e);
request.getRequestDispatcher(UrlUtil.ERROR_RETHROW).forward(request, response);
}
}
@Override
public void destroy() {
}
}
注册Filter为第一个
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Bean
public ExceptionFilter exceptionFilter() {
return new ExceptionFilter();
}
@Bean
public FilterRegistrationBean registerExceptionFilter() {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(exceptionFilter());
bean.addUrlPatterns("/*");
bean.setOrder(1);
return bean;
}
ErrorController如下:
@RestController
public class ErrorController {
@Resource
private HttpServletRequest request;
/**
* 重新抛出异常
*/
@RequestMapping("/error/rethrow")
public void rethrow() {
throw ((AbstractCustomException) request.getAttribute(Req.Attr.EX));
}
}
ErrorController抛出的异常会被Spring的全局异常处理捕获
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
/**
* 登录异常处理
* @param e 异常
* @return 处理结果
*/
@ExceptionHandler(LoginException.class)
@ResponseBody
public Result<String> loginExceptionHandler(LoginException e) {
OperatorContext.remove();
log.error("登录异常", e);
return Result.loginError(e.getMessage());
}
/**
* 业务异常处理
* @param e 异常
* @return 处理结果
*/
@ExceptionHandler(BizException.class)
@ResponseBody
public Result<String> bizExceptionHandler(BizException e) {
log.error("业务异常", e);
return Result.error(e.getMessage());
}
@ExceptionHandler(LawlessInvokeException.class)
@ResponseBody
public Result<String> lawlessException(LawlessInvokeException e) {
log.error("@非法调用@", e);
return Result.error(e.getMessage());
}
/**
* 全局异常处理
* @param e 异常
* @return 处理结果
*/
@ExceptionHandler(Exception.class)
@ResponseBody
public Result<String> exceptionHandler(Exception e) {
log.error("服务器异常", e);
return Result.error("服务器异常");
}
这样我们就可以在Filter中和其他地方一样抛出异常了