Servlet、过滤器、监听器、拦截器

简介: Servlet是javaEE规范中的一种,javaEE中的规范很多除了Servlet还有很多我们熟悉的JSP、JDBC、RMI、XML、EJB、JTS等等。

前言:Servlet是javaEE规范中的一种,javaEE中的规范很多除了Servlet还有很多我们熟悉的JSP、JDBC、RMI、XML、EJB、JTS等等。他们每个都有自己不同的角色,每一种规范在企业级java应用中都承担了不可或缺的角色。Servlet是Service + Applet的缩写,表示小服务程序。从命名就可以看出他是被用来书写服务端程序的。但是在这个很讲究开发效率的年代已久见不到原生的Servlet程序写的服务端程序了。几乎主流的框架都对他进行了封装,比如SpringMVC便是如此,比如SpringMVC的核心DispatcherServlet,SpringMVC正是基于他来将请求进行解析、适配、映射的最后到达我们想要调用的接口中。


一、Servlet



1.Servlet是什么


Servlet = Service + Applet,表示小服务程序,他是javaEE中的一种规范,狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中比如Tomcat。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。


2.Servlet的作用


从上面的介绍我们可以看出,Servlet的作用就是写服务端程序的,这是没有任何问题的,在开发者的角度这就是Servlet的作用,此外Servlet其他的作用都是相对于服务器来说的,他指定了Http服务器管理动态资源文件的规则等。java中所有的前端发送的请求都必须经过Servlet接口的实现类。我们使用的主流框架中比如SpringBoot、SpringCloud都看不到Servlet的身影,那是因为他们内置的SpringMVC中对Servlet都进行了封装。


3.ServletDemo


下面展示一个Servlet程序的写法,首先需要使用IDEA创建一个javaEE的工程,

第一步:选择Module来进行创建。


20210604141231179.png


第二步:选择java企业版,然后勾选web应用即可,剩余的部分都是自己随便填好了,这样我们就可以创建出一个Servlet的应用了。


20210604141437220.png


第三步:创建一个java类继承Servlet接口,并重写doGet、doPost方法。

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class Servlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("执行了post请求。。。");
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("执行了get请求。。。");
    }
}


第四步:在web.xml中配置Servlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>Servlet</servlet-name><!-- 为Servlet起个别名 -->
        <servlet-class>com.cn.controller.Servlet</servlet-class><!-- Servlet的全限定名 -->
    </servlet>
    <servlet-mapping>
        <servlet-name>Servlet</servlet-name><!-- 上方起的别名在下面为他配映射地址 -->
        <url-pattern>/test</url-pattern><!-- 为该别名配置地址,相当于我们在注解RequestMapping中配地址 -->
    </servlet-mapping>
</web-app>


到这里为止,一个简单的Servlet就开发完了,剩下的就是部署测试了,我们需要将这个程序打成war包发布到Tomcat上,IDEA已经帮我们打好了包,我们只需要将该包加载进Tomcat即可,值得注意的是我们最好服务名从新配置一个,不然会有些长,就是图中所示位置


20210604142545510.png


这一切都准备完了,我们就可以来开始启动Tomcat访问了,启动后自动弹出地址,我们加上自己配的test即可访问到刚刚的Servlet了。展示如下,可以看到IDEA中正常输出了“执行了get请求。。。”,地址栏请求都是get请求,因此我们程序是没有问题的,这样就完成了简单的前后端交互,说明这个Servlet没有问题。

image.gif


4.Servlet的生命周期


说Servlet就必须提的是Servlet的声明周期,Servlet默认是在有请求到达时才会创建,可以通过配置实现在Http服务器启动时就启动,且默认也都是单利模式。然后会调用Servelt的init方法,然后就是service方法,然后service会根据是get还是post请求去调用不同的子类方法,最后在Http服务器关闭时会调用distroy方法销毁Servlet的实例。这里还涉及到了一个设计模式的使用即模板模式,我们继承HttpServlet时只要重写doGet、doPost等方法,是因为在HttpServlet中会根据请求的不同去分别调用不同的方法,我们只需要提供方法的实现就可以,逻辑都是确定的了,这便是模板模式。

生命周期:创建-init----->service----->doGet(doPost)----->distroy


二、过滤器Filter、监听器Listener



1.过滤器


Servlet是javaEE的一种规范,而过滤器Filter可以看成是Servlet的一种规范,过滤器的作用主要是过滤请求地址,过滤请求参数的信息,过滤器在实际开发中最常用的就是Xss过滤(Xss过滤就是将报文中可能产生危害的信息进行替换)。


2.监听器


与过滤器类似,监听器也是Servlet的一种规范,我们可以将它们都看出是Servlet,因为他们的实现机制都是一样的,但是监听器的用途就比较单一了。监听器主要用于监控作用域以及作用域中属性的变化。监听器总共有8种,与过滤器类似,他们都是接口都需要我们自己实现。下面列出8种监听器接口:

监听作用域的声明周期的监听器:
  ServletContextListener
  ServletRequestListener
  HttpSessionListener
监听作用域属性变化的监听器:
  ServletContextAttributeListener
  ServletRequestAttributeListener
  HttpSessionAttributeListener
监听Session的活化与钝化
  HttpSessionActivationListener
监听Session与对象的绑定
  HttpSessionBindingListener


3.过滤器的示例Demo


3.1实现Filter接口


写一个类继承Filter,然后重写doFilter方法即可,init和destroy重不重写没有关系

public class LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("初始化");
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("进入到过滤器1");
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("退出了过滤器1");
    }
    @Override
    public void destroy() {
        System.out.println("销毁");
    }
}


3.2配置web.xml


在web.xml中配置该Filter,如下,这样就完成了Filter的开发。

  <filter>
        <filter-name>LoginFilter</filter-name>
        <filter-class>com.cn.filter.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>LoginFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


3.3 展示测试结果


因为过滤器中只是打印了进入和退出,就直接放行了,所以正常就会输出进入过滤器->进入请求->退出过滤器,下面来看下结果也正如预测那样。


20210607201623919.gif


3.4多个Filter时,过滤器是如何执行的


这里就不展示了,我们可以看到一个过滤器时请求到达服务端是先进入过滤器,再到达接口,接口处理完再经过过滤器退出服务器的。多个过滤器时其实就是对接口进行套娃,或者说对多虑的内容进行套娃。画个丑图理解下:


20210607202358351.png


如上图所示一个请求想要到达接口需要穿过所有的过滤器,进入过滤时的顺序和退出时恰恰是相反的,整个流程应该是Filter1—>Filter2—>Filter3—>进入接口执行完毕—>Filter3—>Filter2—>Filter1。这样一看这个流程是不是就像个俄罗斯套娃呢,最里面的就相当于接口,他被层层过滤器所包裹。上面所说的是多个过滤器的执行顺序固定后就是这么处理的,多个处理器到底应该先执行哪一个则是根据他们在web.xml中的配置顺序决定的。


4.比较监听器与过滤器


监听器与过滤器的实现没啥区别,就不一一赘述了,说下监听器与过滤器的区别,监听器主要作用就是监听作用域的,所有监听器都是为了监听作用域,再无他用,不能说应用场景很少,只能说开发中很少用到,写框架应该会经常用到,开发中用的确实不多,而过滤器的作用就很明显了,基本上每个项目都是必不可少的,我们可以通过过滤器对请求和响应都设置一些通用的东西,或者过滤掉有安全隐患的内容,以上是他们作用的不同,他们的相同点就是都是Servlet的规范的实现。


三、拦截器interceptor



说到过滤器和监听器不提拦截器是不合适的,因为他们是java里面的三大器,这三大器各司其职共同保证了程序的稳定运行。每当提起其中一个都会自然而然想到另外两个,那下面我们就来总结下拦截器。


1.拦截器是什么


拦截器我们使用时基本都是使用框架已经实现好的拦截器,基本不会自己写,现在常用的框架中SpringBoot、SpringCloud中我们可以去继承HandlerInterceptorAdapter类来去重写里面的preHandle、postHandle、afterHandle三个方法,如下所示:

public class LoginInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截器预处理");
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("拦截器返回之前执行");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("拦截器返回之后执行");
    }
}


此外我们还需要将这个拦截器交给Spring容器去管理,还需要为该拦截器配置拦截路径和排除路径,如下:

@Configuration
public class InterceptorConfiguration extends WebMvcConfigurerAdapter {
    @Bean
    public LoginInterceptor getLoginInterceptor(){
        return new LoginInterceptor();
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(getLoginInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/find");
    }
}


这样我们就完成了拦截器的开发了,如果你使用的是最新版本的SpringBoot和SpringCloud你会发现,WebMvcConfigurerAdapter 和HandlerInterceptorAdapter 都已经被弃用了。他们的实现类上都被加了Deprecated这个注解,最新的实现方式已经不使用者两个类了,而是变成了两个接口,但是对于使用者来说实现的方式还是完全一样,对使用影响很小,最新版我们分别使用这两个接口就可以,操作什么的都还是一样:


WebMvcConfigurer、HandlerInterceptor,此外这里值得提一句的是配置过滤路径是我们一定要写成/**而不能写成/*,前者代表拦截所有请求,后者则只拦截根路径下的请求,在真实项目中使用后者基本没有意义。


2.拦截器的原理


与过滤器和监听器不同的是,拦截器的实现不是Servlet,而是通过java的动态代理来实现的。java的动态代理相信基本都会知道,如果不清楚可以翻下资料,拦截器正是使用的java的动态代理机制,来对接口执行前后来进行处理的,从而达到了对接口进出拦截的目的。


3.多个拦截器是如何执行的


前面说过多个过滤器的执行顺序就像是套娃,那拦截器呢,拦截器也是一样多个拦截器的执行也和俄罗斯套娃一样,图就不重复画了。值得注意的一点是postHandle是在方法返回之前执行的。


4.多个拦截器的执行顺序


我们在addInterceptors中可以配置多个拦截器,在该方法中配置拦截器的顺序就是拦截器执行的顺序,假如有如下的代码,那就是先执行CSRFInterceptor再执行LoginInterceptor。


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(getCSRFInterceptor())
                .addPathPatterns("/**");
        registry.addInterceptor(getLoginInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/find");
    }


5.拦截器的应用场景


拦截器常被用于拦截CSRF(跨站点请求伪造)的请求,还经常被应用于登录拦截,验证用户是否已经登录。这些都是比较常用的。


四、过滤器和拦截器



上面已经总结完了,过滤器、监听器、拦截器。其中监听器作用比较单一仅是被用作监听作用域(这里只讨论Servlet提供的原生监听接口),但是过滤器和拦截器好像都可以拦截用户发出的请求,那他们有什么区别呢。


区别:

1.实现原理不同,拦截器是动态代理,过滤器是Servlet

2.作用点不一样,过滤器因为是Servlet所以请求肯定先到达过滤器才能到达拦截器。

3.拦截器除了可以处理响应前后的数据,还可以对返回之前的数据进行处理,这得益于java的动态代理。

相同点

1.都可以对请求响应前后进行处理。


有人说过滤器可以过滤所有请求,而拦截器不可以拦截所有请求,这里笔者不敢苟同,他们虽然实现机制不一样,但是都是可以拦截到所有请求的,只是拦截的位置不一样,过滤器相当于第一层、然后才会走到Servelt(可以看成DispatherServlet)再然后才到拦截器最后才能进入到接口,其实他们都可以对所有请求进行拦截,只不过过滤器的拦截点更靠前,所以对于安全性要求较高的拦截还是应该使用过滤器来处理。下面画个丑图来展现下过滤器和拦截器。


2021060721521316.png

相关文章
|
3月前
|
JavaScript Java 容器
servlet过滤器Filter简要回顾-过滤请求字符编码,/和/*和/**的区别
本文简要回顾了Servlet过滤器Filter的概念和使用,通过实例演示了如何创建过滤器以过滤请求字符编码,并解释了在web.xml中配置过滤器时使用`/`、`/*`和`/**`的区别。
servlet过滤器Filter简要回顾-过滤请求字符编码,/和/*和/**的区别
|
4月前
|
存储 前端开发 Java
servlet过滤器--使用过滤器统计网站访问人数的计数(注解形式)
该文章展示了如何使用Servlet过滤器(Filter)通过注解方式创建一个网站访问人数统计功能,通过`@WebFilter`注解定义过滤器及其URL模式,并在`doFilter`方法中实现计数逻辑,将访问次数存储在`ServletContext`中,最后在JSP页面展示访问人数。
servlet过滤器--使用过滤器统计网站访问人数的计数(注解形式)
|
4月前
|
C# 数据可视化 开发者
WPF开发者福音:深度解析OxyPlot与LiveCharts图表库,轻松实现数据可视化不再是难题!
【8月更文挑战第31天】在WPF应用中,数据可视化对提升用户体验至关重要。本文介绍并演示了两种流行图表库OxyPlot和LiveCharts的集成与使用方法。OxyPlot是一款适用于.NET应用的开源图表库,提供多种图表类型,易于集成。LiveCharts则以其丰富的图表类型和动画效果,特别适合实时数据展示。通过具体代码示例,本文展示了如何利用这两种图表库创建折线图和柱状图,并详细说明了安装和配置步骤。希望本文能帮助开发者在WPF应用中轻松实现高效、美观的数据可视化。
233 0
|
4月前
|
监控 前端开发 Java
揭秘Web开发神器:Servlet、过滤器、拦截器、监听器如何联手打造无敌博客系统,让你的用户欲罢不能!
【8月更文挑战第24天】在Java Web开发中,Servlet、过滤器(Filter)、拦截器(Interceptor,特指Spring MVC中的)及监听器(Listener)协同工作,实现复杂应用逻辑。以博客系统为例,Servlet处理文章详情请求,过滤器(如LoginFilter)检查登录状态并重定向,Spring MVC拦截器(如LoggingInterceptor)提供细粒度控制(如日志记录),监听器(如SessionListener)监控会话生命周期事件。这些组件共同构建出高效、有序的Web应用程序。
42 0
|
4月前
|
缓存 安全 Java
Java服务器端技术:Servlet与JSP的集成与扩展
Java服务器端技术:Servlet与JSP的集成与扩展
40 3
|
4月前
|
存储 缓存 前端开发
Servlet与JSP在Java Web应用中的性能调优策略
Servlet与JSP在Java Web应用中的性能调优策略
38 1
|
4月前
|
存储 Java 关系型数据库
基于Servlet和JSP的Java Web应用开发指南
基于Servlet和JSP的Java Web应用开发指南
79 0
|
4月前
|
前端开发 安全 Java
在Java服务器端开发的浩瀚宇宙中,Servlet与JSP犹如两颗璀璨的明星,它们联袂登场,共同编织出动态网站的绚丽篇章。
在Java服务器端开发的浩瀚宇宙中,Servlet与JSP犹如两颗璀璨的明星,它们联袂登场,共同编织出动态网站的绚丽篇章。
31 0
|
6月前
|
自然语言处理 前端开发 Java
Servlet与JSP:Java Web开发的基石技术详解
【6月更文挑战第23天】Java Web的Servlet与JSP是动态网页的核心。Servlet是服务器端的Java应用,处理HTTP请求并响应;JSP则是结合HTML与Java代码的页面,用于动态内容生成。Servlet通过生命周期方法如`init()`、`service()`和`destroy()`工作,而JSP在执行时编译成Servlet。两者在MVC架构中分工,Servlet处理逻辑,JSP展示数据。尽管有Spring MVC等框架,Servlet和JSP仍是理解Web开发基础的关键。
112 12
|
6月前
|
存储 Java 关系型数据库
基于Servlet和JSP的Java Web应用开发指南
【6月更文挑战第23天】构建Java Web应用,Servlet与JSP携手打造在线图书管理系统,涵盖需求分析、设计、编码到测试。通过实例展示了Servlet如何处理用户登录(如`LoginServlet`),JSP负责页面展示(如`login.jsp`和`bookList.jsp`)。应用基于MySQL数据库,包含用户和图书表。登录失败显示错误信息,成功后展示图书列表。部署到Tomcat服务器测试功能。此基础教程为深入Java Web开发奠定了基础。
129 10