欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Servlet与filter

程序员文章站 2022-06-03 09:13:12
...

转自:
https://www.cnblogs.com/gaoxiangde/p/4339571.html

Servlet

什么是Servlet?

其主要功能在于交互式地浏览和修改数据,生成动态Web内容。
Servlet运行于支持Java的应用服务器中。从实现上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
Servlet是一个Java应用程序,运行在服务器端,用来处理客户端请求并作出响应的程序。

通俗点说,servlet 就是运行在java服务器后端的一个程序,如果有人想访问我们的服务器,发来一个 http 请求,我们的 Tomcat 会将它解析为 request 请求。但是怎么处理这个请求呢?servlet 就是用于处理这个请求的,它接收request请求,并处理它,返回response响应。由Tomcat转换为http请求,返回给客户端。

动画版见:
https://blog.csdn.net/qq_19782019/article/details/80292110

Servlet多线程体系

Servlet多线程体系结构是建立在Java多线程机制之上的,它的生命周期是由Web容器负责的。
当客户端第一次请求某个Servlet时,Servlet容器将会根据web.xml配置文件实例化这个Servlet类,此时它贮存于内存中。。当有新的客户端请求该Servlet时,一般不会再实例化该Servlet类,也就是有多个线程在使用这个实例。 这样,当两个或多个线程同时访问同一个Servlet时,可能会发生多个线程同时访问同一资源的情况,数据可能会变得不一致。所以在用Servlet构建的Web应用时要注意线程安全的问题。每一个请求都是一个线程,而不是进程,因此,Servlet对请求的处理的性能非常高。

对于Servlet,它被设计为多线程的(如果它是单线程的,你就可以想象,当1000个人同时请求一个网页时,在第一个人获得请求结果之前,其它999个人都在郁闷地等待),如果为每个用户的每一次请求都创建 一个新的线程对象来运行的话,系统就会在创建线程和销毁线程上耗费很大的开销,大大降低系统的效率。
因此,Servlet多线程机制背后有一个线程池在支持,线程池在初始化初期就创建了一定数量的线程对象,通过提高对这些对象的利用率,避免高频率地创建对象,从而达到提高程序的效率的目的。

Servlet运行过程

Servlet与filter
①客户端向服务器端发出请求;
②这个过程比较重要,这时Tomcat会创建两个对象:HttpServletResponse和HttpServletRequest。并将它们的引用(注意是引用)传给刚分配的线程;
③线程开始着手接洽servlet;
④servlet根据传来的是GET和POST,分别调用doGet()和doPost()方法进行处理;
⑤和⑥servlet将处理后的结果通过线程传回Tomcat,并在之后将这个线程销毁或者送还线程池;
⑦Tomcat将处理后的结果变成一个HTTP响应发送回客户端,这样,客户端就可以接受到处理后的结果了。

简单servlet实例

//导入所需的包
 
import javax.servlet.http.*;
import javax.servlet.*;
import java.io.*;
public class FirstServlet extends HttpServlet {
//处理请求的方法
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, java.io.IOException {
//数据发送给客户端—>控制台方式输出
//System.out.println(“Hello Servlet”);
//数据发送给客户端—>HTML页面输出
resp.setContentType(“text/html”);
resp.getWriter().print(“<html>”);
resp.getWriter().print(“<head>”);
resp.getWriter().print(“</head>”);
resp.getWriter().print(“<body>”);
resp.getWriter().print(“Hello World”);
resp.getWriter().print(“</body>”);
resp.getWriter().print(“</html>”);
}
}

servlet配置到Tomcat中

Tomcat是一个web容器,也叫web服务器。我们都知道J2EE有十三个标准,这些标准大部分都是接口,Tomcat只是实现了JSP 和 servlet 开发标准。实现了所有的开发标准,就是应用程序服务器,比如Jboss。
编译好的servlet类只能运行在tomcat容器中,客户端浏览器不可以直接访问Servlet,需要在web.xml中配置一下

<servlet>
 
<servlet-name>FirstServlet</servlet-name>
<servlet-class>FirstServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FirstServlet</servlet-name>
<url-pattern>/servlet/FirstServlet</url-pattern>
</servlet-mapping>

Servlet的生命周期

Servlet的生命周期包含了下面4个阶段:
(1)加载和实例化
Servlet容器负责加载和实例化Servlet。当Servlet容器启动时,或者在容器检测到需要这个Servlet来响应第一个请求时,创建Servlet实例。当Servlet容器启动后,它必须要知道所需的Servlet类在什么位置,Servlet容器可以从本地文件系统、远程文件系统或者其他的网络服务中通过类加载器加载Servlet类,成功加载后,容器创建Servlet的实例。因为容器是通过Java的反射API来创建Servlet实例,调用的是Servlet的默认构造方法(即不带参数的构造方法),所以我们在编写Servlet类的时候,不应该提供带参数的构造方法。
(2)初始化
在Servlet实例化之后,容器将调用Servlet的init()方法初始化这个对象。初始化的目的是为了让Servlet对象在处理客户端请求前完成一些初始化的工作,如建立数据库的连接,获取配置信息等。对于每一个Servlet实例,init()方法只被调用一次。在初始化期间,Servlet实例可以使用容器为它准备的ServletConfig对象从Web应用程序的配置信息(在web.xml中配置)中获取初始化的参数信息。在初始化期间,如果发生错误,Servlet实例可以抛出ServletException异常或者UnavailableException异常来通知容器。ServletException异常用于指明一般的初始化失败,例如没有找到初始化参数;而UnavailableException异常用于通知容器该Servlet实例不可用。例如,数据库服务器没有启动,数据库连接无法建立,Servlet就可以抛出UnavailableException异常向容器指出它暂时或永久不可用。
(3)请求处理
Servlet容器调用Servlet的service()方法对请求进行处理。要注意的是,在service()方法调用之前,init()方法必须成功执行。在service()方法中,Servlet实例通过ServletRequest对象得到客户端的相关信息和请求信息,在对请求进行处理后,调用ServletResponse对象的方法设置响应信息。在service()方法执行期间,如果发生错误,Servlet实例可以抛出ServletException异常或者UnavailableException异常。如果UnavailableException异常指示了该实例永久不可用,Servlet容器将调用实例的destroy()方法,释放该实例。此后对该实例的任何请求,都将收到容器发送的HTTP 404(请求的资源不可用)响应。如果UnavailableException异常指示了该实例暂时不可用,那么在暂时不可用的时间段内,对该实例的任何请求,都将收到容器发送的HTTP 503(服务器暂时忙,不能处理请求)响应。
(4)服务终止
当容器检测到一个Servlet实例应该从服务中被移除的时候,容器就会调用实例的destroy()方法,以便让该实例可以释放它所使用的资源,保存数据到持久存储设备中。当需要释放内存或者容器关闭时,容器就会调用Servlet实例的destroy()方法。在destroy()方法调用之后,容器会释放这个Servlet实例,该实例随后会被Java的垃圾收集器所回收。如果再次需要这个Servlet处理请求,Servlet容器会创建一个新的Servlet实例。

Filter

Filter是什么

Filter,过滤器,顾名思义,即是对数据等的过滤,预处理过程。为什么要引入过滤器呢?在平常访问网站的时候,有时候发一些敏感的信息,发出后显示时 就会将敏感信息用*等字符替代,这就是用过滤器对信息进行了处理。

filter是在servlet与Tomcat之间的一个类似于过滤网的东西。

Filte是干什么的

这只是一个简单的例子,当然,过滤器那么强大,它的功能也不可能局限于此,它不仅能预处 理数据,只要是发送过来的请求它都是可以预处理的,同时,它还可以对服务器返回的响应进行预处理,这样,大大减轻了服务器的压力。例如,实现URL级别的 权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。下面来详细介绍一下过滤器。

Filte运行过程

过滤作用,对从客户端向服务器端发送的请求进行过滤,也可以对服务器端返回的响应进行处理。它使用户可以改变一个request和修改一个 response.。Filter 不是一个servlet,它不能产生一个response,但是它能够在一个request到达servlet之前预处理request,也可以在 response离开servlet时处理response。换句话说,filter其实是客户端与servlet中间的一个传递者,并且它可以对要传递 的东西进行修改。
Servlet与filter
注意:过滤器是用来拦截请求和响应的,不能产生响应,而servlet是用来处理请求并产生响应的。

过滤器如何实现拦截

1、当客户端发生请求后,在HttpServletRequest 到达Servlet 之前,过滤器拦截客户的HttpServletRequest 。

2、根据需要检查HttpServletRequest ,也可以修改HttpServletRequest 头和数据。

3、在过滤器中调用doFilter方法,对请求放行。请求到达Servlet后,对请求进行处理并产生HttpServletResponse发送给客户端。

4、在HttpServletResponse 到达客户端之前,过滤器拦截HttpServletResponse 。

5、根据需要检查HttpServletResponse ,可以修改HttpServletResponse 头和数据。

6、最后,HttpServletResponse到达客户端。

Filter接口

Servlet API提供了一个Filter接口,编写的过滤器必须实现该接口。

Filter的生命周期

(1)Filter接口中有三个重要的方法。
• init()方法:初始化参数,在创建Filter时自动调用。当我们需要设置初始化参数的时候,可以写到该方法中。
• doFilter()方法:拦截到要执行的请求时,doFilter就会执行。这里面写我们对请求和响应的预处理。
• destroy()方法:在销毁Filter时自动调用。

(2)Filter的生命周期
   Filter的创建和销毁由web服务器控制。
• 服务器启动的时候,web服务器创建Filter的实例对象,并调用其init方法,完成对象的初始化功能。filter对象只会创建一次,init方法也只会执行一次。
• 拦截到请求时,执行doFilter方法。可以执行多次。
• 服务器关闭时,web服务器销毁Filter的实例对象。

Filter对象——FilterConfig

用 户在配置filter时,可以使用为filter配置一些初始化参数,当web容器实例化Filter对象,调用其 init方法时,会把封装了filter初始化参数的filterConfig对象传递进来。因此开发人员在编写filter时,通过 filterConfig对象的方法,就可获得:
• String getFilterName():得到filter的名称。
• String getInitParameter(String name): 返回在部署描述中指定名称的初始化参数的值。如果不存在返回null.
• Enumeration getInitParameterNames():返回过滤器的所有初始化参数的名字的枚举集合。
• public ServletContext getServletContext():返回Servlet上下文对象的引用。