Filter
1)SpringBoot 启动时默认加载四个 Filter
characterEncodingFilter、hiddenHttpMethodFilter、httpPutFormContentFilter、requestContextFilter
2)Filter 优先级
Ordered.HIGHEST_PRECEDENCE 表示最高的优先级,对应最小的整数值;Ordered.LOWEST_PRECEDENCE 表示最低的优先级,对应最大的整数值。
低位值意味着更高的优先级。自定义 Filter 避免和默认的 Filter 优先级一样,不然会冲突
3)在 SpringBoot 中使用 Servlet3.0 配置自定义 Filter
步骤1:使用 @WebFilter 注解来标记一个类为 Filter,当然这个类还需实现 Filter 接口
import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebFilter(urlPatterns = "/api/*", filterName = "loginFilter") public class LoginFilter implements Filter{ /** * 容器加载的时候调用 */ @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("init loginFilter"); } /** * 请求被拦截的时候进行调用 */ @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("doFilter loginFilter"); HttpServletRequest req = (HttpServletRequest) servletRequest; HttpServletResponse resp = (HttpServletResponse) servletResponse; String username = req.getParameter("username"); if ("xdclass".equals(username)) { filterChain.doFilter(servletRequest,servletResponse); } else { resp.sendRedirect("/index.html"); return; } } /** * 容器被销毁的时候被调用 */ @Override public void destroy() { System.out.println("destroy loginFilter"); } }
步骤2:启动类需要添加 @ServletComponentScan 注解,用于扫描到 Filter。
过滤器一般用于非前后分离场景(如:权限控制、用户登录),如果校验不通过,可以使用 resp.sendRedirect("/index.html"); 跳转到错误页面等。
Servlet
1)在 SpringBoot 中使用 Servlet3.0 的注解自定义原生 Servlet
步骤1:使用 @WebServlet 注解来标记一个类为 servlet,当然这个类还需实现 HttpServlet 接口
@WebServlet(name = "userServlet",urlPatterns = "/test/customs") public class UserServlet extends HttpServlet{ @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().print("custom sevlet"); resp.getWriter().flush(); resp.getWriter().close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } }
步骤2:启动类需要添加 @ServletComponentScan 注解,用于扫描到 Servlet。
Listener
1)在 SpringBoot 中使用 Servlet3.0 的注解自定义原生 Listener
步骤1:使用 @WebListener 注解来标记一个类为 Listener,当然这个类还需实现对应的 Listener 接口。常用的监听器 servletContextListener、httpSessionListener、servletRequestListener。
@WebListener public class RequestListener implements ServletRequestListener { @Override public void requestDestroyed(ServletRequestEvent sre) { System.out.println("======requestDestroyed========"); } @Override public void requestInitialized(ServletRequestEvent sre) { System.out.println("======requestInitialized========"); }
}
步骤2:启动类需要添加 @ServletComponentScan 注解,用于扫描到 Servlet。
Interceptor
1)在 SpringBoot 中使用 Interceptor
步骤1:新建自定义的 Interceptor 类,实现 HandlerInterceptor 接口
public class LoginIntercepter implements HandlerInterceptor{ /** * 进入controller方法之前 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("LoginIntercepter------->preHandle"); return HandlerInterceptor.super.preHandle(request, response, handler); } /** * 调用完controller之后,视图渲染之前 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("LoginIntercepter------->postHandle"); HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); } /** * 整个完成之后,通常用于资源清理 */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("LoginIntercepter------->afterCompletion"); HandlerInterceptor.super.afterCompletion(request, response, handler, ex); } }
步骤2:Spring Boot 2.0 的实现方式:新建一个配置类(实现 WebMvcConfigurer 接口),使用 @Configuration 注解
@Configuration public class CustomWebMvcConfigurer implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/api2/*/**"); registry.addInterceptor(new TwoIntercepter()).addPathPatterns("/api2/*/**"); WebMvcConfigurer.super.addInterceptors(registry); } }
老的实现方式:新建一个配置类(继承 WebMvcConfigurerAdapter 父类),使用 @Configuration 注解
@Configuration public class CustomOldWebMvcConfigurer extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/api/"); super.addInterceptors(registry); } }
拦截器几个方法的含义: https://www.cnblogs.com/jwen1994/p/11210901.html
2)拦截器不生效常见问题:
① 是否有加@Configuration
② 拦截路径是否有问题 ** 和 *
③ 拦截器最后路径一定要 “/**”, 如果是目录的话则是 /*/
3)过滤器(Filter)和拦截器(Interceptor)的区别
① Filter 是基于函数回调 doFilter(),而 Interceptor 则是基于 AOP 思想
② Filter 在只在 Servlet 前后起作用,而 Interceptor 够深入到方法前后、异常抛出前后等
③ 依赖于 Servlet 容器即 Web 应用中,而 Interceptor 不依赖于 Servlet 容器所以可以运行在多种环境。
④ 在接口调用的生命周期里,Interceptor 可以被多次调用,而 Filter 只能在容器初始化时调用一次。
⑤ Filter 和 Interceptor 的执行顺序:过滤前->拦截前->action执行->拦截后->过滤后