Servlet
Servlet接口
- public interface Servlet {
- public void init(ServletConfig config) throws ServletException;
- public ServletConfig getServletConfig();
- public void service(ServletRequest req, ServletResponse res)
- throws ServletException, IOException;
- public String getServletInfo();
- public void destroy();
- }
Init()
在Servlet实例化之后,Servlet容器会调用init()方法,来初始化该对象,主要是为了让Servlet对象在处理客户端请求前可以完成一些初始化的工作,例如:建立数据库连接、获取配置信息等。对于每一个Servlet实例,init()方法只能被调用一次。init()方法有一个类型为ServletConfig的参数,Servlet容器通过这个参数向Servlet传递配置信息。Servlet使用Servlet对象从Web应用程序的配置信息中获取以名-值对形式提供的初始化参数。另外,在Servlet中,还可以通过ServletConfig对行啊获取描述Servlet运行环境的ServletContext对象,使用该对象,Servlet可以和它的Servlet容器进行通信。
service()
容器调用service()方法来处理客户端请求。要注意,在Servlet方法被容器调用之前,必须确保init()方法正确完成。容器会构造一个表示客户端请求信息的请求对象(类型为ServletRequest)和一个用于对客户端进行响应的响应对象(类型为ServletResponse)作为参数传递给service()方法。在service方法中,Servlet对象通过ServletRequest对象得到客户端的相关信息和请求信息,在对请求进行处理后,调用ServletResponse对象的方法设置响应信息。
destory()
当容器检测到一个Servlet对象应该从服务中被移除的时候,容器会调用该对象的destory()方法,以便让Servlet对象可以释放它所使用的资源,同时保存数据到持久存储设备中,例如将内存中的数据保存到数据库中,关闭数据库连接等。当需要释放内存或者容器关闭时,容器就会调用Servlet对象的destory()方法。在Servlet容器调用destory()方法之前,如果还有其他线程正在service()方法中执行,容器将会等待这些线程执行完毕或等待服务器设定的超时时间到达。一旦Servlet对象的destory()方法被调用,容器不会再把其他的请求发送给该对象。如果需要该Servlet再次为客户端服务,容器将会重新产生一个Servlet对象来处理客户端请求。在destory()方法调用之后,容器会释放这个Servlet对象,在随后的时间内,该对象会被Java垃圾收集器所回收。
getServletConfig()
该方法返回容器调用init()方法时传递给Servlet对象的ServletConfig对象,ServletConfig对象包含了Servlet的初始化参数。
getServletInfo()
返回一个String类型的字符串,其中包括了关于Servlet的信息,例如,作者、版本和版权。
ServletConfig接口
- public interface ServletConfig {
- public String getServletName();//返回Servlet实例的名字
- public ServletContext getServletContext();//返回Servlet上下文对象
- public String getInitParameter(String name);//返回名称为name的初始化参数的值
- public Enumeration getInitParameterNames();//返回Servlet所有初始化参数的名字和枚举集合
- }
GenericServlet抽象类
- public abstract class GenericServlet
- implements Servlet, ServletConfig, java.io.Serializable
- {//GenericServlet抽象类定义了一个通用的、不依赖于具体协议的Servlet,简化子类的实现。
- private transient ServletConfig config;//config为transient,不参与序列化
- public GenericServlet() { }
- public void destroy() {
- }
- public String getInitParameter(String name) {
- return getServletConfig().getInitParameter(name);
- }
- public Enumeration getInitParameterNames() {
- return getServletConfig().getInitParameterNames();
- }
- public ServletConfig getServletConfig() {
- return config;
- }
- public ServletContext getServletContext() {
- return getServletConfig().getServletContext();
- }
- public String getServletInfo() {
- return "";
- }
- //对Servlet接口中init()方法的实现。其中调用了不带参数的的init()方法。
- public void init(ServletConfig config) throws ServletException {
- this.config = config;
- this.init();
- }
- //不带参数的init()方法。通常我们在编写继承自GenericServlet的Servlet类时,只需重写该方法。
- public void init() throws ServletException {
- }
- public void log(String msg) {
- getServletContext().log(getServletName() + ": "+ msg);
- }
- public void log(String message, Throwable t) {
- getServletContext().log(getServletName() + ": " + message, t);
- }
- public abstract void service(ServletRequest req, ServletResponse res)
- throws ServletException, IOException;
- public String getServletName() {
- return config.getServletName();
- }
- }
HTTPServlet抽象类
- public abstract class HttpServlet extends GenericServlet
- implements java.io.Serializable
- {
- //绝大多数的网络应用中,都是客户端(浏览器)通过HTTP协议去访问服务器端的资源。
- //而我们所编写的Servle也主要是应用于HTTP协议的请求和响应。该抽象类简化了开发应用于HTTP协议的Servlet。
- ......
- //对GenericServlet类中service()方法的实现。
- public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
- HttpServletRequest request;
- HttpServletResponse response;
- //首先进行显示类型转换
- try {
- request = (HttpServletRequest) req;
- response = (HttpServletResponse) res;
- } catch (ClassCastException e) {
- throw new ServletException("non-HTTP request or response");
- }
- service(request, response);//调用下一个service方法
- }
- //在编写HTTPServlet子类时,通常不需要覆盖该方法,而只需要重写相应的doXXX()方法。
- protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- String method = req.getMethod();//获取HTTP请求方法的类型
- //HTTP1.1中定义了7种请求方法:Get、Post、Head、Put、Delete、Trace和Options
- //然后根据请求方法的类型,调用相应的doXXX()方法
- if (method.equals(METHOD_GET)) {
- long lastModified = getLastModified(req);
- if (lastModified == -1) {
- // servlet doesn't support if-modified-since, no reason
- // to go through further expensive logic
- doGet(req, resp);
- } else {
- long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
- if (ifModifiedSince < (lastModified / 1000 * 1000)) {
- // If the servlet mod time is later, call doGet()
- // Round down to the nearest second for a proper compare
- // A ifModifiedSince of -1 will always be less
- maybeSetLastModified(resp, lastModified);
- doGet(req, resp);
- } else {
- resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
- }
- }
- } else if (method.equals(METHOD_HEAD)) {
- long lastModified = getLastModified(req);
- maybeSetLastModified(resp, lastModified);
- doHead(req, resp);
- } else if (method.equals(METHOD_POST)) {
- doPost(req, resp);
- } else if (method.equals(METHOD_PUT)) {
- doPut(req, resp);
- } else if (method.equals(METHOD_DELETE)) {
- doDelete(req, resp);
- } else if (method.equals(METHOD_OPTIONS)) {
- doOptions(req, resp);
- } else if (method.equals(METHOD_TRACE)) {
- doTrace(req, resp);
- } else {
- //不支持的请求方法,提示错误
- // Note that this means NO servlet supports whatever
- // method was requested, anywhere on this server.
- String errMsg = lStrings.getString("http.method_not_implemented");
- Object[] errArgs = new Object[1];
- errArgs[0] = method;
- errMsg = MessageFormat.format(errMsg, errArgs);
- resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
- }
- }
- ......}
Servlet生命周期
Servlet运行在Servlet容器中,其生命周期由容器来管理。Servlet的生命周期通过Servlet接口中的init()、service()和destory()方法来表示。
注:如果需要让Servlet容器在启动时自动加载Servlet,可以在web.xml文件中配置。
单实例多线程的Servlet模型
Servlet规范中定义,默认情况下(Servlet不是在分布式的环境中部署),Servlet容器对声明的每一个Servlet,只创建一个实例。如果有多个客户端请求同时访问这个Servlet,Servlet容器如何处理多个请求呢?答案是采用多线程,Servlet容器维护一个线程池来服务请求。当容器接收到一个访问Servlet的请求,调度者线程从线程池中选取一个工作线程,将请求传递给该线程,然后由这个线程执行Servlet的service()方法。
线程安全的Servlet
变量的线程安全
因为Servlet是单实例多线程模型,多个线程共享一个Servlet实例,因此对于实例变量的访问是非线程安全的。
建议:在Servlet中尽可能的使用局部变量,应该只使用只读的实例变量和静态变量。如果非得使用共享的实例变量或静态变量,在修改共享变量时应该注意线程同步。
属性的线程安全
在Servlet中,可以访问保存在ServletContext、HttpSession和ServletRequest对象中的属性。那么这三种不同范围的对象,属性访问是否是线程安全的呢?
ServletContext:该对象被Web应用程序的所有Servlet共享,多线程环境下肯定是非线程安全的。
HttpSession:HttpSession对象只能在同属于一个Session的请求线程中共享。对于同一个Session,我们可能会认为在同一时刻只有一个用户请求,因此,Session对象的属性访问是线程安全的。但是,如果用户打开多个同属于一个进程的浏览器窗口,在这些窗口中的访问请求同属于一个Session,对于多个线程的并发修改显然不是线程安全的。
ServletRequest:因为Servlet容器对它所接收到的每一个请求,都创建一个新的ServletRequest对象,所以ServletRequest对象只在一个线程中被访问,因此对ServletRequest的属性访问是线程安全的。但是,如果在Servlet中创建了自己的线程,那么对ServletRequest的属性访问的线程安全性就得自己去保证。此外,如果作死的将当前请求的Servlet通过HttpSession或者ServletContext共享,那当然也是非线程安全的。
相关问题
1、重定向和转发的区别
JSP
JSP是一种建立在Servlet规范提供的功能之上的动态网页技术,它通过在网页文件中嵌入脚本代码,用于产生动态内容。
JSP文件在用户第一次请求时,会被编译成Servlet,然后由这个Servlet处理用户请求,所以JSP也可以看成是运行时的Servlet。
相关问题
JSP和Servlet的区别与联系?
JSP在本质上就是SERVLET,但是两者的创建方式不一样.Servlet完全是JAVA程序代码构成,擅长于流程控制和事务处理,通过Servlet来生成动态网页很不直观.JSP由HTML代码和JSP标签构成,可以方便地编写动态网页.因此在实际应用中采用Servlet来控制业务流程,而采用JSP来生成动态网页.在struts框架中,JSP位于MVC设计模式的视图层,而Servlet位于控制层.JSP是Servlet技术的扩展,本质上就是Servlet的简易方式。JSP编译后是“类servlet”。Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。而JSP是Java和HTML组合成一个扩展名为.jsp的文件。JSP侧重于视图,Servlet主要用于控制逻辑。
Filter
Filter接口
- public interface Filter {
- //用于完成Filter的初始化
- public void init(FilterConfig filterConfig) throws ServletException;
- //实现过滤功能
- public void doFilter ( ServletRequest request, ServletResponse response,
- FilterChain chain ) throws IOException, ServletException;
- //用于销毁Filter前,完成某些资源的回收
- public void destroy();
- }
Filter生命周期
web.xml 中声明的每个 filter 在每个虚拟机中仅仅只有一个实例。
(1) 加载和实例化
Web 容器启动时,即会根据 web.xml 中声明的 filter 顺序依次实例化这些 filter。
(2) 初始化
Web 容器调用 init(FilterConfig) 来初始化过滤器。容器在调用该方法时,向过滤器传递 FilterConfig 对象,FilterConfig 的用法和 ServletConfig 类似。利用 FilterConfig 对象可以得到 ServletContext 对象,以及在 web.xml 中配置的过滤器的初始化参数。在这个方法中,可以抛出 ServletException 异常,通知容器该过滤器不能正常工作。此时的 Web 容器启动失败,整个应用程序不能够被访问。实例化和初始化的操作只会在容器启动时执行,而且只会执行一次。
(3) doFilter
doFilter 方法类似于 Servlet 接口的 service 方法。当客户端请求目标资源的时候,容器会筛选出符合 filter-mapping 中的 url-pattern 的 filter,并按照声明 filter-mapping 的顺序依次调用这些 filter 的 doFilter 方法。在这个链式调用过程中,可以调用 chain.doFilter(ServletRequest, ServletResponse) 将请求传给下一个过滤器(或目标资源),也可以直接向客户端返回响应信息,或者利用 RequestDispatcher 的 forward 和 include 方法,以及 HttpServletResponse 的 sendRedirect 方法将请求转向到其它资源。需要注意的是,这个方法的请求和响应参数的类型是 ServletRequest 和 ServletResponse,也就是说,过滤器的使用并不依赖于具体的协议。
(4) 销毁
Web 容器调用 destroy 方法指示过滤器的生命周期结束。在这个方法中,可以释放过滤器使用的资源。
Filter运行原理
Filter应用场景
1、统一POST请求中文字符编码的过滤器
2、控制浏览器缓存页面中的静态资源的过滤器
有些动态页面中引用了一些图片或css文件以修饰页面效果,这些图片和css文件经常是不变化的,所以为减轻服务器的压力,可以使用filter控制浏览器缓存这些文件,以提升服务器的性能。
3、使用Filter实现URL级别的权限认证
在实际开发中我们经常把一些执行敏感操作的servlet映射到一些特殊目录中,并用filter把这些特殊目录保护起来,限制只能拥有相应访问权限的用户才能访问这些目录下的资源。从而在我们系统中实现一种URL级别的权限功能。
4、实现用户自动登陆
首先,在用户登陆成功后,发送一个名称为user的cookie给客户端,cookie的值为用户名和md5加密后的密码。编写一个AutoLoginFilter,这个filter检查用户是否带有名称为user的cookie,如果有,则调用dao查询cookie的用户名和密码是否和数据库匹配,匹配则向session中存入user对象(即用户登陆标记),以实现程序完成自动登陆。
Filter应用实例
与开发 Servlet 不同的是,Filter 接口并没有相应的实现类可供继承,要开发过滤器,只能直接实现 Filer 接口。
此过滤器用来解决全站中文乱码问题:设置统一的字符编码集
- public class CharacterEncodingFilter implements Filter {
- private FilterConfig filterConfig = null;
- //设置默认的字符编码
- private String defaultCharset = "UTF-";
- public void doFilter(ServletRequest req, ServletResponse resp,
- FilterChain chain) throws IOException, ServletException {
- HttpServletRequest request = (HttpServletRequest) req;
- HttpServletResponse response = (HttpServletResponse) resp;
- String charset = filterConfig.getInitParameter("charset");
- if(charset==null){
- charset = defaultCharset;
- }
- request.setCharacterEncoding(charset);
- response.setCharacterEncoding(charset);
- response.setContentType("text/html;charset="+charset);
- MyCharacterEncodingRequest requestWrapper = new MyCharacterEncodingRequest(request);
- chain.doFilter(requestWrapper, response);
- }
- public void init(FilterConfig filterConfig) throws ServletException {
- //得到过滤器的初始化配置信息
- this.filterConfig = filterConfig;
- }
- public void destroy() {
- }
- }
Listener
当Web应用在Web容器中运行时,Web应用内部会不断地发生各种事件:如Web应用的启动和停止、用户Session的开始和结束等,通常这些Web事件对开发者是透明的。Listener(监听器)是观察者模式的应用,通过方法回调来实现。
Listener生命周期
Listener在当web容器启动的时候,去读取每个web应用的web.xml配置文件,当配置文件中配有filter和listener时,web容器实例化listener,listener是当某个事件发生时,调用它特定方法,如HttpSessionListener,当创建一个session时会调用它的sessionCreated()方法,当servlet容器关闭或者重新加载web应用时lister对象被销毁。
Listener分类
不同功能的Listener 需要实现不同的 Listener 接口,一个Listener也可以实现多个接口,这样就可以多种功能的监听器一起工作。常用监听器:
1)监听 Session、request、context 的创建于销毁,分别为
HttpSessionLister、ServletContextListener、ServletRequestListener
2)监听对象属性变化,分别为:
HttpSessionAttributeLister、ServletContextAttributeListener、ServletRequestAttributeListener
Listener应用
1、利用HttpSessionLister,统计当前在线人数。
- public class OnLineCountListener implements HttpSessionListener {
- @Override
- public void sessionCreated(HttpSessionEvent se) {
- ServletContext context = se.getSession().getServletContext();
- Integer onLineCount = (Integer) context.getAttribute("onLineCount");
- if (onLineCount == null) {
- context.setAttribute("onLineCount", 1);
- } else {
- onLineCount++;
- context.setAttribute("onLineCount", onLineCount);
- }
- }
- @Override
- public void sessionDestroyed(HttpSessionEvent se) {
- ServletContext context = se.getSession().getServletContext();
- Integer onLineCount = (Integer) context.getAttribute("onLineCount");
- if (onLineCount == null) {
- context.setAttribute("onLineCount", 1);
- } else {
- onLineCount--;
- context.setAttribute("onLineCount", onLineCount);
- }
- }
- }
2、自定义Session扫描器
当一个Web应用创建的Session很多时,为了避免Session占用太多的内存,我们可以选择手动将这些内存中的session销毁,那么此时也可以借助监听器技术来实现。
转自:http://blog.csdn.net/sunxianghuang/article/details/52107376
相关推荐
Servlet、Filter、Listener 详解 Servlet 是运行在服务器上的小程序,它可以使任何 Java 应用程序、浏览器或任何设备。Servlet 的客户端可以提出请求并获得该请求的响应。Servlet 在初始化后即驻留内存中,因此每次...
Web.xml 中的 listener、filter、servlet 加载顺序及其详解 在 Web 应用程序中,web.xml 文件扮演着非常重要的角色,它定义了 Web 应用的结构和配置。其中,listener、filter、servlet 是三个非常重要的概念,它们...
SpringBootServlet、Filter、Listener配置详解 在SpringBoot中,Servlet、Filter、Listener是三个重要的组件,它们在Web应用程序中扮演着关键的角色。本篇文章将详细介绍如何在SpringBoot中配置Servlet、Filter、...
在Servlet3.0中,我们可以使用注解(@WebServlet、@WebFilter、@WebListener)来替代web.xml中的XML配置,使得部署更简洁。例如,`@WebServlet("/example")`可以直接在Servlet类上声明URL映射。 2. **异步处理**:...
### Spring管理Filter与Servlet详解 在现代Web应用开发中,Spring框架因其强大的依赖注入和面向切面编程功能而被广泛采用。特别是在Java EE环境中,如何有效地整合Spring与Servlet、Filter等核心组件,对于构建高...
Servlet 3.0 还增加了对注解的支持,这为简化 Servlet、过滤器(Filter)和监听器(Listener)的声明提供了便利。在之前的版本中,Servlet、过滤器和监听器都需要在 web.xml 文件中进行声明式配置,而在 Servlet 3.0 中...
在Servlet 2.5及之前版本中,Servlet、Filter和Listener的配置通常需要在`web.xml`文件中手动编写XML元素,而Servlet 3.0通过注解的方式,使得开发者可以直接在源代码中进行配置,提高了开发效率和代码的可读性。...
Java Web开发中,Servlet、Filter、Listener和Interceptor这四种组件在处理请求和响应的过程中扮演着不同的角色,它们都是Java EE规范中不可或缺的部分,用于增强应用程序的功能和灵活性。 **1. Servlet** Servlet...
import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet....
Servlet API详解 Servlet技术是Java Web开发中的核心组成部分,它为服务器端的动态网页和应用程序提供了基础。Servlet API是Java Servlet规范的一部分,由Java EE(Enterprise Edition)定义,用于处理客户端请求并...
Filter 过滤器是 JavaWeb 的三大组件之一,另外两个组件是 Servlet 程序和 Listener 监听器。Filter 过滤器是一个接口,它的作用是拦截请求,过滤响应。常见的应用场景有权限检查、日记操作、事务管理等等。 ...
Servlet 3.0 新规范提出了模块化开发,也就是每个 Servlet、Filter、Listener 都可以有属于自己的配置文件,功能和 web.xml 一样,它只负责配置当前的 Servlet。然后我们只需要将配置文件和自己写的 Servlet 等内容...
4. **filter-mapping**:将过滤器与URL模式或Servlet关联。 5. **session-config**:配置会话的默认超时时间、跟踪模式等。 6. **welcome-file-list**:指定应用的默认欢迎页面。 7. **error-page**:定义错误页面,...
除了Servlet本身,Servlet API还包括Filter和Listener。Filter可以在请求到达Servlet之前对其进行预处理,或者在响应发送给客户端之后进行后处理。Listener则可以监听Web应用中的特定事件,如session创建、销毁等,...
总的来说,Spring Boot为Servlet、Filter和Listener提供了灵活的注册方式,既支持传统的XML配置,也支持更现代的Java配置和注解驱动的编程模式。选择哪种方式取决于项目需求和个人喜好,但推荐使用Java配置和注解,...
`Servlet,Filter的url-pattern详解`文件可能解释了如何精确匹配URL以决定哪些请求需要通过`Filter`。 `[转载]java web开发中的listener和filter`文件可能会介绍`Listener`,它们是另一种类型的Web组件,监听特定的...
15.2.3 [listener]元素 457 15.2.4 [tag]元素 458 15.2.5 [tag-file]元素 460 15.2.6 [function]元素 461 15.3 传统标签的开发 462 15.3.1 实例一:[hello]标签 462 15.3.2 实例二:[max]标签 465 15.3.3 ...
### Web.xml配置详解(Servlet 2.3) #### 一、概述 `web.xml`作为Java Web应用程序的核心配置文件,在Servlet 2.3规范中扮演着至关重要的角色。该文件通常位于WEB-INF目录下,用于定义和配置Web应用程序的各种...