SpringBoot拦截过滤与监听
上一篇讲解了thymeleaf基础语法及内置对象,结束了SpringBoot整合静态资源与模版引擎的所有讲解。本篇开始讲解SpringBoot拦截过滤与监听。
Servlet规范实现监听器servlet监听器是servlet规范中定义的特殊的类用于监听servletContext(application级别)、httpsession(session级别)、servletRequest(request级别)等作用域对象的创建与销毁事件,以及监听这些作用域对象中属性发生修改的事件。开发Servlet监听器需要实现相应的监听器接口并重写接口中的方法。ServletListener监听监听ServletContext、HttpSession、HttpServletRequest这三个对象创建和销毁事件的监听器:ServletContext监听 ServletContext 对象的创建与销毁过程,一个完整的应用里只存在一个HttpSession监听 HttpSession 对象的创建和销毁过程,同一个用户在使用浏览器从开启到关闭的过程中使用的是一个sessionHttpServletRequest监听 ServletRequest 对象的创建和销毁过程(HTTP请求)作用域比较:ServletContext>HttpSession>HttpServletRequest还可以使用HttpSessionAttributeListenerServletContextAttributeListenerServletRequestAttributeListener来监听域对象内属性的变化实现监听器的创建与销毁在config文件下创建ListenerContextConfig.java:package com.javafamily.familydemo.config;import javax.servlet.*;import javax.servlet.annotation.WebListener;// 将当前Listener实例化,注入到Spring上下文中去@WebListenerpublic class ListenerContextConfig implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent se) { System.out.println("初始化context"); } @Override public void contextDestroyed(ServletContextEvent se) { System.out.println("销毁context"); }}1234567891011121314151617181920复制代码类型:[java]创建ListenerRequestConfig.java:package com.javafamily.familydemo.config;import javax.servlet.ServletRequestEvent;import javax.servlet.ServletRequestListener;import javax.servlet.annotation.WebListener;@WebListenerpublic class ListenerRequestConfig implements ServletRequestListener { @Override public void requestDestroyed(ServletRequestEvent sre) { System.out.println("销毁request监听器"); } @Override public void requestInitialized(ServletRequestEvent sre) { System.out.println("初始化request监听器"); }}123456789101112131415161718复制代码类型:[java]创建ListenerSessionConfig.java:package com.javafamily.familydemo.config;import javax.servlet.annotation.WebListener;import javax.servlet.http.HttpSessionEvent;import javax.servlet.http.HttpSessionListener;@WebListenerpublic class ListenerSessionConfig implements HttpSessionListener { @Override public void sessionCreated(HttpSessionEvent se) { System.out.println("创建session"); } @Override public void sessionDestroyed(HttpSessionEvent se) { System.out.println("销毁session"); }}12345678910111213141516171819复制代码类型:[java]创建ListenRequestAttributeConfig.java:package com.javafamily.familydemo.config;import javax.servlet.ServletRequestAttributeEvent;import javax.servlet.ServletRequestAttributeListener;import javax.servlet.annotation.WebListener;@WebListenerpublic class ListenRequestAttributeConfig implements ServletRequestAttributeListener { @Override public void attributeAdded(ServletRequestAttributeEvent srae) { System.out.println("attributeAdded"); } @Override public void attributeRemoved(ServletRequestAttributeEvent srae) { System.out.println("attributeRemoved"); } @Override public void attributeReplaced(ServletRequestAttributeEvent srae) { System.out.println("attributeReplaced"); }}123456789101112131415161718192021222324复制代码类型:[java]创建ListenSessionAttributeConfig.java:package com.javafamily.familydemo.config;import javax.servlet.annotation.WebListener;import javax.servlet.http.HttpSessionAttributeListener;import javax.servlet.http.HttpSessionBindingEvent;@WebListenerpublic class ListenSessionAttributeConfig implements HttpSessionAttributeListener { @Override public void attributeAdded(HttpSessionBindingEvent sbe) { System.out.println("attributeAdded1"); } @Override public void attributeRemoved(HttpSessionBindingEvent arg0) { System.out.println("attributeRemoved1"); } @Override public void attributeReplaced(HttpSessionBindingEvent arg0) { System.out.println("attributeReplaced1"); }}1234567891011121314151617181920212223复制代码类型:[java]再在controller文件下创建ListenerController.java:package com.javafamily.familydemo.controller;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;@RestControllerpublic class ListenerController { @GetMapping("/listener") public String Listener(HttpServletRequest request, HttpSession session) { // set一个值 request.setAttribute("Java", "Family"); // 替换一个值 request.setAttribute("Java", "OtherFamily"); // get一个值 request.getAttribute("Java"); // 删除一个值 request.removeAttribute("Java"); session.setAttribute("Java", "Our"); session.setAttribute("Java", "Other"); session.getAttribute("Java"); session.invalidate(); return "Listener测试"; }}1234567891011121314151617181920212223242526272829303132复制代码类型:[java]在request.setAttribute("Java","Family");和return"Listener测试";这两处打好断点进行debug。在代码执行完之后context就已经初始化了:
浏览器访问链接http://localhost:8888/listener。查看打印结果:
通过debug打印出的顺序,可以看出代码的执行顺序。点击左侧红色方块,停止debug,得到打印结果销毁context:
注:记得在启动类中添加@ServletComponentScan注解:@SpringBootApplication@MapperScan(basePackages = {"com.javafamily.familydemo.mapper"})// 扫描Servlet主键(监听器是Servlet主键的一种)@ServletComponentScanpublic class FamilyDemoApplication { public static void main(String[] args) { SpringApplication.run(FamilyDemoApplication.class, args); }}123456789复制代码类型:[java]Servlet规范实现过滤器Servlet过滤器是服务器与客户端请求与响应的中间层组件,能够在前端向后端请求数据之前拦截请求,也能在后端的响应发送回前端之前处理响应。它能够过滤请求和改变请求的数据。
在SpringBoot项目中过滤器有两种比较主流的注册方式,一种是使用@WebFilter注解,另一种是使用springboot提供的FilterRegistrationBean方式。使用@WebFilter注解在config文件下创建FilterConfig.java:package com.javafamily.familydemo.config;import javax.servlet.*;import javax.servlet.annotation.WebFilter;import java.io.IOException;// urlPatterns={"/*"}表示过滤器过滤所有的请求@WebFilter(filterName = "WebFilterConfig", urlPatterns = {"/*"})public class FilterConfig implements Filter { @Override public void init(javax.servlet.FilterConfig filterConfig) throws ServletException { System.out.println("拦截器初始化"); } @Override // 实现业务处理的核心函数 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("doFilter方法之前进行过滤请求"); filterChain.doFilter(servletRequest, servletResponse); System.out.println("doFilter方法之后进行响应处理"); } @Override public void destroy() { System.out.println("销毁拦截器"); }}123456789101112131415161718192021222324252627复制代码类型:[java]@WebFilter注解无法保证过滤器之间的执行顺序,当使用多个过滤器时,我们会有对过滤器制定执行顺序的需求,@WebFilter注解是无法满足的。使用FilterRegistrationBean方式FilterRegistrationBean提供了setOrder方法,可以通过设置优先级进行排序:package com.javafamily.familydemo.config;import org.springframework.boot.web.servlet.FilterRegistrationBean;import org.springframework.context.annotation.Bean;public class BeanFilterConfig { @Bean public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new FilterConfig()); registration.setName("filter"); // 拦截路径 registration.addUrlPatterns("/*"); // 设置优先级,1最高 registration.setOrder(1); return registration; }}123456789101112131415161718复制代码类型:[java]拦截器的实现在Spring中拦截器有三个方法:preHandle预处理回调方法,实现处理器的预处理postHandle后处理回调方法,实现处理器的后处理afterCompletion 整个请求处理完毕回调方法方法到达Controller之前preHandle对方法进行预处理,Controller给出响应之后交给postHandle进行处理,处理完成到达模版引擎页面进行页面渲染,最后到达postHandle方法。
拦截器和过滤器的规范,作用范围,使用资源,粒度都有不同。在config文件下创建MyHandlerInterceptor.java:package com.javafamily.familydemo.config;import org.springframework.stereotype.Component;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@Componentpublic class MyHandlerInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandle"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion"); }}1234567891011121314151617181920212223242526272829303132复制代码类型:[java]继承WebMvcConfigurerAdapter注册拦截器:package com.javafamily.familydemo.config;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import javax.annotation.Resource;@Configurationpublic class MyWebMvcConfigurer implements WebMvcConfigurer { @Resource MyHandlerInterceptor myHandlerInterceptor; @Override // 添加拦截器 public void addInterceptors(InterceptorRegistry registry) { // 注册到Spring容器中 registry.addInterceptor(myHandlerInterceptor).addPathPatterns("/*"); // 多个拦截器(注册顺序就是执行顺序)// registry.addInterceptor(myHandlerInterceptor1).addPathPatterns("/*");// registry.addInterceptor(myHandlerInterceptor2).addPathPatterns("/*");// registry.addInterceptor(myHandlerInterceptor3).addPathPatterns("/*"); }}12345678910111213141516171819202122232425复制代码类型:[java]执行代码后,浏览器访问http://localhost:8888,在控制台得到执行顺序: