第一种方法
Filters execute always before a Servlet is invoked,and a @ControllerAdvice is only useful for controller which are executed inside the DispatcherServlet
过滤器总是在servlet前面执行。并且@ControllerAdvice仅仅对于controller是有效的。
1.自己定义一个过滤器,用于处理过滤器链中抛出的异常
/**
* Filter链 异常捕获 处理
*/
@Component
public class ExceptionHandlerFilter extends OncePerRequestFilter {
@Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain){
try {
filterChain.doFilter(request, response);
// 捕获后面的过滤器抛出的BusinessException异常
} catch (BusinessException e) {
Result errorResponse = new Result(401,e.getMessage());
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write(new ObjectMapper().writeValueAsString(errorResponse));
}
}
}
2.加入到过滤器链中
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// 关闭 csrf,也在过滤器链中移除了CsrfFilter
.csrf().disable()
// 不创建HttpSession, 不使用HttpSession获取SecurityContext
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/user/login").anonymous()
.anyRequest().authenticated();
http.addFilterBefore(authenticationFilter, UsernamePasswordAuthenticationFilter.class);
// 加入到过滤器链中
http.addFilterBefore(exceptionHandlerFilter, CorsFilter.class);
return http.build();
}
第二种方法
@Component
public class ExceptionHandlerFilter extends OncePerRequestFilter {
@Autowired
@Qualifier("handlerExceptionResolver")
private HandlerExceptionResolver resolver;
@Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain){
try {
filterChain.doFilter(request, response);
} catch (BusinessException e) {
// 会交到 Springmvc的全局异常处理器那里
resolver.resolveException(request,response,null,e);
}
}
}
当然也需要进行配置到过滤链当中。
How to manage exceptions thrown in filters in Spring
Spring和SpringSecurity 的全局异常处理