Servlet的一点零碎知识

来源:互联网 发布:js 指定时间转时间戳 编辑:程序博客网 时间:2024/05/22 07:50

Servlet是一个Java编写的程序,此程序是基于Http协议的,在服务器端运行的(如tomcat),是按照Servlet规范编写的一个Java类,主要是处理客户端的请求并将其结果发送到客户端。

**

Servlet的生命周期

**

Servlet的生命周期是由Servlet的容器来控制的,它可以分为3个阶段;初始化,运行,销毁。

初始化阶段
1,Servlet容器加载servlet类,把servlet类的.class文件中的数据读到内存中。
2,然后Servlet容器创建一个ServletConfig对象。ServletConfig对象包含了Servlet的初始化配置信息。
3,Servlet容器创建一个servlet对象。
4,Servlet容器调用servlet对象的init方法进行初始化。

运行阶段
当servlet容器接收到一个请求时,servlet容器会针对这个请求创建servletRequest和servletResponse对象。
然后调用service方法。并把这两个参数传递给service方法。Service方法通过servletRequest对象获得请求的信息。并处理该请求。再通过servletResponse对象生成这个请求的响应结果。然后销毁servletRequest和servletResponse对象。我们不管这个请求是post提交的还是get提交的,最终这个请求都会由service方法来处理。

销毁阶段
当Web应用被终止时,servlet容器会先调用servlet对象的destrory方法,然后再销毁servlet对象,同时也会销毁与servlet对象相关联的servletConfig对象。我们可以在destroy方法的实现中,释放servlet所占用的资源,如关闭数据库连接,关闭文件输入输出流等。

在servlet生命周期中,servlet的初始化和和销毁阶段只会发生一次,而service方法执行的次数则取决于servlet被客户端访问的次数。

Servlet怎么处理一个请求
当用户发送一个请求到某个Servlet的时候,Servlet容器会创建一个ServletRequst和ServletResponse对象。
在ServletRequst对象中封装了用户的请求信息,然后Servlet容器把ServletRequst和ServletResponse对象传给用户所请求的Servlet,Servlet把处理好的结果写在ServletResponse中,然后Servlet容器把响应结果传给用户。

Servlet与JSP有什么区别

1,jsp经编译后就是servlet,也可以说jsp等于servlet。
2,jsp更擅长页面(表现)。servlet更擅长逻辑编辑。 (最核心的区别)。
3,在实际应用中采用Servlet来控制业务流程,而采用JSP来生成动态网页.在struts框架中,JSP位于MVC设计模式的视图层,而Servlet位于控制层。

Servlet里的cookie技术

cookies是一种WEB服务器通过浏览器在访问者的硬盘上存储信息的手段,是由Netscape公司开发出来的。
cookie技术的好处
1,Cookie有效期限未到时,Cookie能使用户在不键入密码和用户名的情况下进入曾经浏览过的一些站点。
2,Cookie能使站点跟踪特定访问者的访问次数、最后访问时间和访问者进入站点的路径。

Servlet里的过滤器

过滤器的主要作用
1,任何系统或网站都要判断用户是否登录。
2,网络聊天系统或论坛,功能是过滤非法文字
3,统一解决编码
怎么创建一个过滤器:
1,生成一个普通的class类,实现Filter接口(javax.servlet.Filter;)。
2,重写接口里面的三个方法:init,doFilter,destroy。
3,然后在web.xml配置过滤器。

Servlet里的监听器

监听器的作用:自动执行一些操作。

三种servlet监听器:
对request的监听。对session的监听。对application的监听。

怎么创建一个session监听器:
1,生成一个普通的class类,如果是对session的监听,则实现HttpSessionListener。
2,然后重写里面的五个方法:

public void sessionCreated(HttpSessionEvent arg0) {} // 创建public void sessionDestroyed(HttpSessionEvent arg0) {} // 销毁public void attributeAdded(HttpSessionEvent arg0) {} // 增加public void attributeRemoved(HttpSessionEvent arg0) {} // 删除public void attributeReplaced(HttpSessionEvent arg0) {} // 替换

创建Servlet对象的时机

1、Servlet容器启动时:读取web.xml配置文件中的信息,构造指定的Servlet对象,创建ServletConfig对象,同时将ServletConfig对象作为参数来调用Servlet对象的init方法。
2、在Servlet容器启动后:客户首次向Servlet发出请求,Servlet容器会判断内存中是否存在指定的Servlet对 象,如果没有则创建它,然后根据客户的请求创建HttpRequest、HttpResponse对象,从而调用Servlet
对象的service方法。
3、Servlet的类文件被更新后,重新创建Servlet。 Servlet容器在启动时自动创建Servlet,这是由在web.xml文件中为Servlet设置的 属性决定的。从中我们也能看到同一个类型的Servlet对象在Servlet容器中以单例的形式存在。
创建Servlet对象的时机

注意:初始化与实例化是两个不同的概念,实例化是根据Java类生成的一个该类的对象,在实例化时会调用Java对象的构造方法,任意一个非抽象的Java类都可以被实例化;初始化时一个特殊的概念,并不是所有的Java类都有初始化的概念,Servlet的初始化是指在从一个Servlet类实例化一个Servlet对象后再调用该Servlet对象的初始化方法对其进行初始化。可见初始化的前提是先实例化。所以Tomcat对Servlet的初始化默认就包括了从Servlet类实例化一个Servlet对象。

销毁Servlet对象的时机

1、Servlet容器停止或者重新启动:Servlet容器调用Servlet对象的destroy方法来释放资源。
销毁Servlet对象的时机

以上所讲的就是Servlet对象的生命周期。那么Servlet容器如何知道创建哪一个Servlet对象?Servlet对象如何配置?实际上这些信息是通过读取web.xml配置文件来实现的。

当Servlet容器启动的时候读取 配置节信息,根据 配置节信息创建Servlet对象,同时根据 配置节信息创建HttpServletConfig对象,然后执行Servlet对象的init方法,并且根据配置节信息来决定创建Servlet对象的顺序,如果此配置节信息为负数或者没有配置,那么在Servlet容器启动时,将不加载此Servlet对象。
当客户访问Servlet容器时,Servlet容器根据客户访问的URL地址,通过 配置节中的 配置节信息找到指定的Servlet对象,并调用此Servlet对象的service方法。

Tomcat具体加载处理细节

(1). Tomcat (App)首先读取配置文件web.xml中配置好的Servlet的子类名称
(2). Tomcat根据读取到的客户端实现的Servlet子类的类名字符串去寻找对应的字节码文件。如果找到就将其加载到内存。
(3). Tomcat通过预先设置好的Java反射处理机制解析字节码文件并创建相应的实例对象。之后调用所需要的方法。
(4).Tomcat一启动,用户自定义的Servlet的子类通过Tomcat内部的反射框架也随之运行。

Tomcat如何找到并实例化Servlet

(1)服务器根据客户端的访问路径,获得Servlet的访问路径;
(2)服务器拿着这个路径去web.xml中进行匹配,这个过程需要对web.xml解析;(3)匹配成功后,会找到相应的标签,其值为Servlet的类名,可以通过反射获得该Servlet的Class对象;
(4)然后调用Class对象的newInstance()方法,实例化一个Servlet对象,注意一定要为Servlet提供一个无参的构造方法;
(5)利用反射获得service()方法的Method对象,然后调用service()方法,即执行method.invoke(Servlet实例,参数的Class对象),这样就实现了service()方法的执行。
服务器创建Servlet底层原理图

Servlet的线程安全问题

一,因为一个类型的Servlet只有一个实例对象,那么就有可能会现时出一个Servlet同时处理多个请求,那么Servlet是否为线程安全的呢?答案是:“不是线程安全的”。这说明Servlet的工作效率很高,但也存在线程安全问题!
所以我们不应该在Servlet中随便创建成员变量,因为可能会存在一个线程对这个成员变量进行写操作,另一个线程对这个成员变量进行读操作。

  1. 变量的线性安全:这里的变量指字段和共享数据(如表单参数值)。
    将参数变量本地化。多线程并不共享局部变量,所以要尽可能地在servlet中使用局部变量。例如:String user=request.getParameter(“user”);
    使用同步块Synchronized,防止可能异步调用的代码块,这就意味着线程需要排队处理。但要注意在使用同步块的范围要尽可能的小,不要直接在sevice方法和响应方法上使用,这样会严重影响性能。

  2. 属性的线性安全:ServletContext,HttpSession,ServletRequest对象中的属性。
    ServletContext(线程不安全):ServletContext可以同时进行多线程读/写属性,线程是不安全的。要对属性的读写进行同步处理或进行深度Clone()。所以在Servlet上下文中要尽量少保存会被修改(写)的数据,可以使用其他的方式在多个Servlet中共享,比如使用单例模式处理共享数据。HttpSession(线程不安全):HttpSession在用户会话期间存在,只能在处理属于同一个Session请求的线程中被访问,因此理论上访问Session对象的属性是线程安全的。但是当用户打开同属于同一个进程的浏览窗口,对这些窗口的访问属于同一个session,会出现多次请求,需要多个工作线程来处理,可能会造成多个线程同时读写操作。这时我们就需要对属性的读写进行同步处理:使用同步块或读/写器来处理。
    ServletRequest(线程安全):对于每一个请求,由一个线程来执行,都会创建一个新的ServletRequest对象,所以ServletRequest只能在一个线程中被访问。注意:ServletRequest对象在service方法的范围内是有效的,不要试图在service方法结束后仍然保存访问请求对象的引用。

  3. 不要在Servlet中创建自己的线程以完成某个功能:servlet本身就是多线程,再创建线程会导致问题复杂化,会带来线程安全的问题。

  4. 在多个Servlet中对外部对象(比如文件)修改一定要加锁,做到互斥的访问。

  5. javax.servlet.SingleThreadModel接口是一个标识接口,如果一个servlet实现了这个接口,那么servlet容器将保证在一个时刻仅有一个线程可以在给定的servlet实例的service方法中执行,将其他所有请求进行排队。

  6. 服务器可以使用多个实例来处理请求,代替单个实例的请求排队带来的效益问题。服务器创建一个Servlet类的多个Servlet实例组成的实例池,对于每个请求分配Servlet实例进行响应处理,之后放回到实例池中等待下此请求。这样就造成并发访问的问题。此时,局部变量(字段)也是安全的,但对于全局变量和共享数据是不安全的,需要进行同步处理。而对于这样多实例的情况SingleThreadModel接口并不能解决并发访问问题。

  7. 使用同步块Synchronized,防止可能异步调用的代码块。这意味着线程需要排队处理。在使用同板块的时候要尽可能的缩小同步代码的范围,不要直接在sevice方法和响应方法上使用同步,这样会严重影响性能。

  8. ServletRequest:(线程是安全的)
    对于每一个请求,由一个工作线程来执行,都会创建有一个新的ServletRequest对象,所以ServletRequest对象只能在一个线程中被访问。ServletRequest是线程安全的。注意:ServletRequest对象在service方法的范围内是有效的,不要试图在service方法结束后仍然保存请求对象的引用。
    详细可参阅Servlet 单例多线程

二,Servlet体系结构是建立在Java多线程机制之上的,它的生命周期是由Web容器负责的。
当客户端第一次请求某个Servlet时,Servlet容器将会根据web.xml配置文件实例化这个Servlet类。当有新的客户端请求该Servlet时,一般不会再实例化该Servlet类,也就是有多个线程在使用这个实例。Servlet容器会自动使用线程池等技术来支持系统的运行。
TOMCAT线程池

0 0
原创粉丝点击