前言
之前的文章SpringBoot拦截器HandlerInterceptor实现讲了 HandlerInterceptor 拦截器。
文本讲解 OncePerRequestFilter 过滤器的使用。
一、 HandlerInterceptor拦截器与OncePerRequestFilter过滤器的区别
1.应用场景:
- HandlerInterceptor 主要用于 Spring MVC 的请求处理流程中,适合进行日志记录、参数校验等操作。
- OncePerRequestFilter 主要用于 Spring Security 的过滤器链中,适合进行安全性相关的操作,如认证、授权等。
2.生命周期:
- HandlerInterceptor 在控制器方法执行前后执行,主要用于请求处理流程的控制。
- OncePerRequestFilter 在每次请求时执行一次,主要用于安全性相关的过滤任务。
3.实现方式:
- HandlerInterceptor 通过实现 HandlerInterceptor 接口并注册到 WebMvcConfigurer 中。
- OncePerRequestFilter 通过继承 OncePerRequestFilter 类并实现 doFilterInternal 方法,并在 Spring Security 配置中注册。
选择建议
如果你需要在请求处理流程中进行一些通用的操作,如日志记录、参数校验等,可以选择使用 HandlerInterceptor。
如果你需要进行安全性相关的过滤任务,如认证、授权等,可以选择使用 OncePerRequestFilter。
根据实际需求选择合适的拦截机制,可以使代码更加清晰和易于维护。
二、OncePerRequestFilter过滤器使用示例
下面的过滤器继承自 OncePerRequestFilter 然后使用 @Component 注入到容器,当每一个请求来的时候都会执行 doFilterInternal 方法,从每一个请求的HTTP请求头中获取Authorization的值,也就是的token,并调用checkToken方法进行校验。如果token校验失败,则不继续执行过滤链,直接返回错误信息的JSON字符串。
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class AuthFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
//从头中获取token并校验
String token = request.getHeader("Authorization");
if (!checkToken(token, request, response)) {
return;
}
filterChain.doFilter(request, response);
}
private boolean checkToken(String token, HttpServletRequest request, HttpServletResponse response) throws IOException {
//检查token是否有效
if (!checkToken(token)) {
// token校验失败
writeErrorMessage(request, response);
return false;
}
return true;
}
//检查token是否有效
private boolean checkToken(String token) {
//todo 在这里验证token的有效性
//......
return true;
}
public void writeErrorMessage(HttpServletRequest request, HttpServletResponse response) throws IOException {
String jsonString = "{\n" +
" \"code\": \"-1\",\n" +
" \"msg\": \"token无效\",\n" +
" \"detail\": \"\"\n" +
"}";
String origin = request.getHeader("Origin");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Origin", origin != null && origin.trim().length() > 0 ? origin : "*");
response.setHeader("Access-Control-Allow-Methods", "*");
response.setHeader("Access-Control-Allow-Headers", "*");
response.setStatus(HttpStatus.OK.value());
response.setCharacterEncoding("utf-8");
response.setContentType("application/json");
response.getWriter().write(jsonString);
response.getWriter().flush();
}
}
参考:
Spring 过滤器:OncePerRequestFilter 应用详解
OncePerRequestFilter详解