Java的Servlet、Filter、Interceptor、Listener

写在前面:

使用Spring-Boot时,嵌入式Servlet容器可以通过扫描注解(@ServletComponentScan)的方式注册Servlet、Filter和Servlet规范的所有监听器(如HttpSessionListener监听器)。 

Spring boot 的主 Servlet 为 DispatcherServlet,其默认的url-pattern为“/”。一般情况系统默认的Servlet就够用了,如果需要自定义Servlet,可以继承系统抽象类HttpServlet,重写方法来实现自己的Servlet。关于Servlet、过滤器、拦截器、监听器可以参考:(转)servlet、filter、listener、interceptor之间的区别和联系

Spring-Boot有两种方法注册Servlet、Filter和Listener :

1、代码注册:通过ServletRegistrationBean、 FilterRegistrationBean 和 ServletListenerRegistrationBean 获得控制。

2、在 SpringBootApplication 上使用@ServletComponentScan 注解后,Servlet、Filter、Listener 可以直接通过 @WebServlet、@WebFilter、@WebListener 注解自动注册,无需其他代码。

一、Servlet

Servlet匹配规则:匹配的优先级是从精确到模糊,复合条件的Servlet并不会都执行。

1、通过@ServletComponentScan自动扫描

a、springboot的启动入口添加注解:@ServletComponentScan;

 

@SpringBootApplication
@ServletComponentScan
public class ApplicationMain {public static void main(String[] args) {SpringApplication.run(ApplicationMain.class, args);}
}

 

b、@WebServlet 自定义Servlet,配置处理请求路径 /demo/myServlet 

@WebServlet(name = "myServletDemo1",urlPatterns = "/demo/myServlet",description = "自定义的servlet")
public class MyServletDemo1 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("==========myServletDemo Get Method==========");resp.getWriter().println("my myServletDemo1 process request");super.doGet(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("==========myServletDemo1 POST Method==========");super.doPost(req, resp);}
}

 

2、使用@ServletRegistrationBean注解

a、@ServletRegistrationBean注入自定义的Servlet,配置处理的路径为 /demo/servletDemo2 

@Configuration
public class ServletConfiguration {/*** 代码注入*/@Beanpublic ServletRegistrationBean myServletDemo() {return new ServletRegistrationBean(new MyServletDemo2(), "/demo/servletDemo2");}
}

b、自定义的Servlet

public class MyServletDemo2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("==========myServletDemo2 Get Method==========");resp.getWriter().println("my myServletDemo2 process request");super.doGet(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("==========myServletDemo2 POST Method==========");super.doPost(req, resp);}
}

 

二、Filter

完整的流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。

Filter有如下几个用处。

  • 在HttpServletRequest到达Servlet之前,拦截客户的HttpServletRequest。
  • 根据需要检查HttpServletRequest,也可以修改HttpServletRequest头和数据。
  • 在HttpServletResponse到达客户端之前,拦截HttpServletResponse。
  • 根据需要检查HttpServletResponse,也可以修改HttpServletResponse头和数据。

多个FIlter可以组成过滤器调用链,按设置的顺序逐一进行处理,形成Filter调用链。

1、通过@ServletComponentScan自动扫描

a、springboot的启动入口添加注解:@ServletComponentScan;

b、@WebFilter 配置处理全部url的Filter

@WebFilter(filterName = "myFilter",urlPatterns = "/*")
public class MyFilter implements Filter {public void init(FilterConfig filterConfig) throws ServletException {System.out.println(">>>>>>myFilter init ……");}public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println(">>>>>>执行过滤操作");filterChain.doFilter(servletRequest, servletResponse);}public void destroy() {System.out.println(">>>>>>myFilter destroy ……");}
}

 * doFilter()方法是过滤器的核心方法,实现该方法就可实现对用户请求进行预处理,也可实现对服务器响应进行后处理——它们的分界线为是否调用了filterChain.doFilter(),执行该方法之前,即对用户请求进行预处理;执行该方法之后,即对服务器响应进行后处理。

2、通过@FilterRegistrationBean注册

a、@Bean注入自定义的Filter

@Configuration
public class ServletConfiguration {@Beanpublic FilterRegistrationBean myFilterDemo(){FilterRegistrationBean registration = new FilterRegistrationBean();registration.setFilter(new MyFilter2());registration.addUrlPatterns("/demo/myFilter2");registration.addInitParameter("paramName", "paramValue");registration.setName("myFilter2");registration.setOrder(2);//指定filter的顺序return registration;}
}

b、自定义的Filter

public class MyFilter2 implements Filter {public void init(FilterConfig filterConfig) throws ServletException {System.out.println("======MyFilter2 init ……");}public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("======MyFilter2执行过滤操作");filterChain.doFilter(servletRequest, servletResponse);}public void destroy() {System.out.println("======MyFilter2 destroy ……");}
}

三、Listener

目前 Servlet 中提供了 6 种两类事件的观察者接口,它们分别是:4 个 EventListeners 类型的,ServletContextAttributeListener、ServletRequestAttributeListener、ServletRequestListener、HttpSessionAttributeListener 和 2 个 LifecycleListeners 类型的,ServletContextListener、HttpSessionListener。

  • ServletContextAttributeListener监听对ServletContext属性的操作,比如增加、删除、修改属性。
  • ServletContextListener监听ServletContext。当创建ServletContext时,激发contextInitialized(ServletContextEvent sce)方法;当销毁ServletContext时,激发contextDestroyed(ServletContextEvent sce)方法。
  • HttpSessionListener监听HttpSession的操作。当创建一个Session时,激发session Created(HttpSessionEvent se)方法;当销毁一个Session时,激发sessionDestroyed (HttpSessionEvent se)方法。
  • HttpSessionAttributeListener监听HttpSession中的属性的操作。当在Session增加一个属性时,激发attributeAdded(HttpSessionBindingEvent se) 方法;当在Session删除一个属性时,激发attributeRemoved(HttpSessionBindingEvent se)方法;当在Session属性被重新设置时,激发attributeReplaced(HttpSessionBindingEvent se) 方法。

1、通过@ServletComponentScan自动扫描

a、ServletListenerRegistrationBean 注入自定义的Listener;

b、自定义的Listener

@WebListener
public class MyLisener implements ServletContextListener {public void contextInitialized(ServletContextEvent servletContextEvent) {System.out.println("MyLisener contextInitialized method");}public void contextDestroyed(ServletContextEvent servletContextEvent) {System.out.println("MyLisener contextDestroyed method");}
}

2、通过@ServletListenerRegistrationBean 注册

a、@Bean注入自定义的Listener;

@Configuration
public class ServletConfiguration {@Beanpublic ServletListenerRegistrationBean myListener(){return new ServletListenerRegistrationBean(new MyLisener());}
}

b、自定义的Listener

public class MyLisener implements ServletContextListener {public void contextInitialized(ServletContextEvent servletContextEvent) {System.out.println("MyLisener contextInitialized method");}public void contextDestroyed(ServletContextEvent servletContextEvent) {System.out.println("MyLisener contextDestroyed method");}
} 

四、验证servlet、filter、listener的顺序

a、使用MyServletDemo2、MyFilter2、MyFilter3、MyLisener做测试;

b、设置servlet处理url格式为 /demo/*;设置MyFilter2顺序为2;MyFilter3的顺序为3;

@Configuration
public class ServletConfiguration {/**代码注入*/@Beanpublic ServletRegistrationBean myServletDemo(){return new ServletRegistrationBean(new MyServletDemo2(),"/demo/*");}@Beanpublic FilterRegistrationBean myFilterDemo(){FilterRegistrationBean registration = new FilterRegistrationBean();registration.setFilter(new MyFilter2());registration.addUrlPatterns("/demo/myFilter");registration.addInitParameter("paramName", "paramValue");registration.setName("myFilter2");registration.setOrder(2);//指定filter的顺序return registration;}@Beanpublic FilterRegistrationBean myFilterDemo2(){FilterRegistrationBean registration = new FilterRegistrationBean();registration.setFilter(new MyFilter3());registration.addUrlPatterns("/demo/*");registration.addInitParameter("paramName", "paramValue");registration.setName("myFilter3");registration.setOrder(1);return registration;}@Beanpublic ServletListenerRegistrationBean myListener(){return new ServletListenerRegistrationBean(new MyLisener());}
}
View Code

c、启动项目后输出:(FIlter2先执行init,因为@Ben在前)

MyLisener contextInitialized method
======MyFilter2 init ……
======MyFilter3 init ……

d、浏览器输入地址地址:http://localhost:8080/demo/myFilter,输出:

======MyFilter3执行过滤操作
======MyFilter2执行过滤操作
>>>>>>>>>>test Get Method==========

可以看出:

  1. Filter3比Filter2先执行;
  2. Filter可以匹配上的url都会执行,并且按顺序执行(Filter的调用链);
  3. Filter比servlet先执行。
  4. servlet先按具体匹配,然后模糊匹配,并且只能有一个servlet匹配上,没有servlet调用链。

执行顺序是:Listener》Filter》Servlet

五、ApplicationListener自定义侦听器类

参考:http://blog.csdn.net/liaokailin/article/details/48186331

六、Interceptor

拦截器只会处理DispatcherServlet处理的url

a、自定义拦截器

public class MyInterceptor implements HandlerInterceptor {public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {System.out.println(">>>>MyInterceptor preHandle");return true;}public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {System.out.println(">>>>MyInterceptor postHandle");}public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {System.out.println(">>>>MyInterceptor afterCompletion");}
}

 

b、注册拦截器

@Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");super.addInterceptors(registry);}
}

c、拦截器验证

输入地址:http://localhost:8080/home/test

>>>>MyInterceptor preHandle
>>>>MyInterceptor postHandle
>>>>MyInterceptor afterCompletion

输入地址:http://localhost:8080/demo/myFilter (自定义的Servlet处理了请求,此时拦截器不处理)

拦截器不处理。

转载于:https://www.cnblogs.com/mr-yang-localhost/p/7784607.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/390854.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leetcode 1035. 不相交的线(dp)

在两条独立的水平线上按给定的顺序写下 nums1 和 nums2 中的整数。 现在,可以绘制一些连接两个数字 nums1[i] 和 nums2[j] 的直线,这些直线需要同时满足满足: nums1[i] nums2[j] 且绘制的直线不与任何其他连线(非水平线&#x…

SPI和RAM IP核

学习目的: (1) 熟悉SPI接口和它的读写时序; (2) 复习Verilog仿真语句中的$readmemb命令和$display命令; (3) 掌握SPI接口写时序操作的硬件语言描述流程(本例仅…

个人技术博客Alpha----Android Studio UI学习

项目联系 这次的项目我在前端组,负责UI,下面简略讲下学到的内容和使用AS过程中遇到的一些问题及其解决方法。 常见UI控件的使用 1.TextView 在TextView中,首先用android:id给当前控件定义一个唯一标识符。在活动中通过这个标识符对控件进行事…

数据科学家数据分析师_站出来! 分析人员,数据科学家和其他所有人的领导和沟通技巧...

数据科学家数据分析师这一切如何发生? (How did this All Happen?) As I reflect on my life over the past few years, even though I worked my butt off to get into Data Science as a Product Analyst, I sometimes still find myself begging the question, …

react-hooks_在5分钟内学习React Hooks-初学者教程

react-hooksSometimes 5 minutes is all youve got. So in this article, were just going to touch on two of the most used hooks in React: useState and useEffect. 有时只有5分钟。 因此,在本文中,我们仅涉及React中两个最常用的钩子: …

分析工作试用期收获_免费使用零编码技能探索数据分析

分析工作试用期收获Have you been hearing the new industry buzzword — Data Analytics(it was AI-ML earlier) a lot lately? Does it sound complicated and yet simple enough? Understand the logic behind models but dont know how to code? Apprehensive of spendi…

select的一些问题。

这个要怎么统计类别数呢? 哇哇哇 解决了。 之前怎么没想到呢?感谢一楼。转载于:https://www.cnblogs.com/AbsolutelyPerfect/p/7818701.html

重学TCP协议(12)SO_REUSEADDR、SO_REUSEPORT、SO_LINGER

1. SO_REUSEADDR 假如服务端出现故障,主动断开连接以后,需要等 2 个 MSL 以后才最终释放这个连接,而服务重启以后要绑定同一个端口,默认情况下,操作系统的实现都会阻止新的监听套接字绑定到这个端口上。启用 SO_REUSE…

残疾科学家_数据科学与残疾:通过创新加强护理

残疾科学家Could the time it takes for you to water your houseplants say something about your health? Or might the amount you’re moving around your neighborhood reflect your mental health status?您给植物浇水所需的时间能否说明您的健康状况? 还是…

Linux 网络相关命令

1. telnet 1.1 检查端口是否打开 执行 telnet www.baidu.com 80,粘贴下面的文本(注意总共有四行,最后两行为两个空行) telnet [domainname or ip] [port]例如: telnet www.baidu.com 80 如果这个网络连接可达&…

spss23出现数据消失_改善23亿人口健康数据的可视化

spss23出现数据消失District Health Information Software, or DHIS2, is one of the most important sources of health data in low- and middle-income countries (LMICs). Used by 72 different LMIC governments, DHIS2 is a web-based open-source platform that is used…

01-hibernate注解:类级别注解,@Entity,@Table,@Embeddable

Entity Entity:映射实体类 Entity(name"tableName") name:可选,对应数据库中一个表,若表名与实体类名相同,则可以省略。 注意:使用Entity时候必须指定实体类的主键属性。 第一步:建立实体类: 分别…

COVID-19研究助理

These days scientists, researchers, doctors, and medical professionals face challenges to develop answers to their high priority scientific questions.如今,科学家,研究人员,医生和医学专家面临着挑战,无法为其高度优先…

Go语言实战 : API服务器 (8) 中间件

为什么需要中间件 我们可能需要对每个请求/返回做一些特定的操作,比如 记录请求的 log 信息在返回中插入一个 Header部分接口进行鉴权 这些都需要一个统一的入口。这个功能可以通过引入 middleware 中间件来解决。Go 的 net/http 设计的一大特点是特别容易构建中间…

缺失值和异常值的识别与处理_识别异常值-第一部分

缺失值和异常值的识别与处理📈Python金融系列 (📈Python for finance series) Warning: There is no magical formula or Holy Grail here, though a new world might open the door for you.警告 : 这里没有神奇的配方或圣杯,尽管…

leetcode 664. 奇怪的打印机(dp)

题目 有台奇怪的打印机有以下两个特殊要求: 打印机每次只能打印由 同一个字符 组成的序列。 每次可以在任意起始和结束位置打印新字符,并且会覆盖掉原来已有的字符。 给你一个字符串 s ,你的任务是计算这个打印机打印它需要的最少打印次数。…

PHP7.2 redis

为什么80%的码农都做不了架构师?>>> PHP7.2 的redis安装方法: 顺便说一下PHP7.2的安装: wget http://cn2.php.net/distributions/php-7.2.4.tar.gz tar -zxvf php-7.2.4.tar.gz cd php-7.2.4./configure --prefix/usr/local/php…

梯度 cv2.sobel_TensorFlow 2.0中连续策略梯度的最小工作示例

梯度 cv2.sobelAt the root of all the sophisticated actor-critic algorithms that are designed and applied these days is the vanilla policy gradient algorithm, which essentially is an actor-only algorithm. Nowadays, the actor that learns the decision-making …

垃圾回收算法优缺点对比

image.pngGC之前 说明:该文中的GC算法讲解不仅仅局限于某种具体开发语言。 mutator mutator 是 Edsger Dijkstra 、 琢磨出来的词,有“改变某物”的意思。说到要改变什么,那就是 GC 对象间的引用关系。不过光这么说可能大家还是不能理解&…

yolo人脸检测数据集_自定义数据集上的Yolo-V5对象检测

yolo人脸检测数据集计算机视觉 (Computer Vision) Step by step instructions to train Yolo-v5 & do Inference(from ultralytics) to count the blood cells and localize them.循序渐进的说明来训练Yolo-v5和进行推理(来自Ultralytics )以对血细胞进行计数并将其定位。 …