Servlet的框架

Java 发表评论

Servlet的框架是由两个java包组成的:javax.servlet和javax.servlet.http. javax.servlet包含了支持普通协议无关的Servlet的类。 javax.servlet.http包括了对HTTP协议的特别支持。  servlet的框架的核心是javax.servlet.Servlet接口,所有的Servlet都必须实现这一接口。在Servlet接口中定义了5个方法,其中有3个方法代表了Servlet的生命周期:  (1)init方法,负责初始化Servlet对象  (2)service方法,负责初始响应客户的请求 (3)destroy方法,当Servlet对象退出生命周期时,负责释放占用的资源 由上图可知,GenericServlet实现了Servlet接口,HttpServlet扩展了GenericServlet。用户开发自己的Servlet类时,扩展HttpServlet类即可。如果Servlet类扩展了HttpServlet类,通常不必实现service方法,因为HttpServlet类已经实现了service方法。在HttpServlet的service方法中,首先从HttpServletRequest对象中获取HTTP请求方式的信息,然后再根据请求方式调用相应的方法。该方法的声明形式如下: protected void service(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException 在HttpServlet的service方法中,有两个参数:HttpServletRequest和HttpServletResponse,这两个类分别扩展了javax.servlet.ServletRequest和javax.servlet.ServletResponse接口。 ServletRequest接口:ServletRequest接口封装了客户请求信息,如客户请求方式、参数名和参数值、客户端正在使用的协议,以及发出客户请求的远程主机信息等。ServletRequest接口还为Servlet提供了直接以二进制数方式读取客户请求数据流的ServletInputStream。ServletRequest的子类可以为Servlet提供更多的与特定协议相关的数据 ServletRequest接口:ServletRequest接口为Servlet提供了返回响应结果的方法。它允许Servlet设置返回数据的长度和MIME类型,并且提供了输出流ServletOutputStream。ServletResponse子类可以提供更多和特定协议相关的方法。 HttpServlet能够根据客户发出的HTTP请求,生成相应的HTTP响应结果。HttpServlet首先必须读取HTTP请求的内容。Servlet容器负责创建HttpRequest对象,并把HTTP请求信息封装到HttpRequest对象中,这样通过调用HttpServletRequest的相关方法,就可以方便地读取HTTP请求中的任何一部分消息。 Servlet生命周期 阶段一:Servlet实现类的加载 (1)所有的web-server加载Servlet实现类的时候,都将搜索web-app根目录下WEB-INF目录的子目录lib和classes,在lib目录中搜索*.jar文件,在classes目录中搜索*.class文件;它将遍历WEB-INF目录下的web.xml配置文件,根据文件中的Servlet标签下Servlet-class子标签的内容加载相应的class文件。 (2)tomcat安装的根目录下的common目录的子目录lib中存放webapps目录下所有web-app的公共jar包,当web-app使用jar包时首先搜索本app中的lib,如果没有找到需要的jar包,将在common目录的lib中找jar包; (3)web服务器启动时加载Servlet实现类的方法(配置WEB-INF目录下的web.xml) 在web.xml文件中与Servlet实现类相对应的Servlet标签中添加子标签,如: 1 标签内部的文本应是正整数,当多个Servlet实现类相对应的Servlet标签都添加了子标签时,根据该文本对应整数之的大小加载相应的Servlet实现类;整数值越小,加载顺序越靠前;值相等时,加载顺序由web-server决定。 阶段二:Servlet对象的创建与初始化 (1)大多数web-server会在客户端第一次访问服务器时加载Servlet实现类,创建对象并执行初始化方法,(如果设置服务器启动时加载,则服务器启动时创建对象并执行初始化方法,客户端第一次访问服务器时,直接进入service阶段执行service方法);以后每个客户端在发送请求就不会再调用init方法,也就是说它只能被调用一次。一个Servlet对象的初始化方法只执行一次; (2)为Servlet对象设置初始化参数(配置WEB-INF目录下的web.xml) 1> 在web.xml文件中与Servlet实现类相对应的Servlet标签中添加子标签,如: 参数名 参数值 每对init-param标签只能设置一个初始化参数,如果要设置多个初始化参数,需重复以上四行代码;参数名一般都不能改,因为我们要在java程序中用到;参数值可以修改。 2> Servlet实现类中覆盖无参的init()方法,方法内部使用getInitParameter(“参数名”)获得相应的参数值,该方法在javax.Servlet.ServletConfig,javax.Servlet.GenericServlet两个类中都有定义,一般使用后者(即在Servlet实现类中直接使用getInitParameter(“参数名”)获得相应的参数值); 3> HttpServlet直接继承了GenericServlet类中init(ServletConfig)方法,GenericServlet类的init()方法有两种形式:常规初始化、由初始化参数控制的初始化 public void init()throws ServletException{} //可以调用不带参数的方法 public void init(ServletConfig config)throws ServletException{ this.config=config;//初始化成员变量config init(); //这里直接调用了不带参数的init方法。 } 常规初始化:创建、载入在servlet生命周期内用到的一些数据,如为即将处理的请求建立数据库连接共享、将数据文件载入HashMap等 由初始化参数控制的初始化 1. 通过向web.xml的servlet元素添加init-param子元素,可以指定初始化参数的名称和值 2. 在servlet的init方法中,调用getServletConfig,获取ServletConfig对象的引用 3. 以init方法的参数名称为参数,调用ServletConfig的getInitParameter方法,返回值就是init参数的值,或null——如果在web.xml文件中没有找到这个init参数。 init(ServletConfig)方法中第一行初始化了config成员变量,GenericServlet类中getInitParameter(“参数名”)方法返回的是getConfig().getInitParameter(“参数名”);当Servlet实现类中直接使用 getInitParameter(“参数名”),由于没有初始化成员变量config,getConfig()将返回null;故会产生空指针异常,所以应该总是在第一行加上super.init(con)。 阶段三:Servlet对象根据客户端的请求提供service (1)HttpServlet类继承自Servlet的实现类javax.Servlet.GenericServlet,HttpServlet类中覆盖的service()方法完成了由一个service方法向多个方法(doGet、doPost、doDelete等方法)转换的过程,细化了service方法的功能,doGet、doPost分别表示当客户端”method”属性设置为get和post时调用;HttpServlet的子类中只需要覆盖其中的一个功能方法; (2)Service方法会在服务器被访问时调用,Servlet对象的生命周期中service方法可能被多次调用,由于web-server启动后,服务器中公开的部分资源将处于网络中,当网络中的不同主机(客户端)并发访问服务器中的同一资源,服务器将开设多个线程处理不同的请求,多线程同时处理同一对象时,有可能出现数据并发访问的错误。多线程同时处理同一变量时(如:对同一文件进行写操作),且有读写操作时,必须考虑是否加上同步(synchronized),同步添加时,不要添加范围过大,有可能使程序变为纯粹的单线程,大大削弱了系统性能;只需要做到多个线程安全的访问相同的对象就可以了; 在servlet中需要同步的有:成员变量,网络资源,文件,静态变量,数据库连接等,用到这些一定要考虑线程同步,安全的问题。 阶段四:Servlet对象的销毁(destroy()方法) 当程序中的Servlet对象不再使用时,web-server将有可能销毁该对象,不同的web-server销毁时机不同;一个Servlet对象的销毁(destroy()方法)只执行一次; 我们可以在这个方法里做关闭数据库,关闭流,终止后台线程等收尾工作。注意:不要把持久化的对象存入内存中,程序结束时统一转移到外部存储设备;因为在web-server异常退出(断电等因素引起)的时候,未能来得及转移数据,这样的话会造成数据丢失。 Servlet容器响应Web客户请求的步骤 1:Web客户向Servlet容器发出HTTP请求;2:Servlet容器解析Web客户的HTTP请求;3:Servlet容器创建一个HttpRequset对象,在这个对象中封装了HTTP请求信息;4:Servlet容器创建一个HttpResponse对象;5:Servlet容器调用HttpServlet的service方法,把HttpRequest和HttpResponse对象作为service方法的参数传给HttpServlet对象;6:HttpServlet调用HttpResponse的有关方法,获取HTTP请求信息7:HttpServlet调用HttpResponse的有关方法,生成响应数据8:Servlet容器把HttpServlet的响应结果传给Web客户 SERVLET API中forward() 与redirect()的区别? 答:前者仅是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址;后者则是完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接。这样,从浏览器的地址栏中可以看到跳转后的链接地址。所以,前者更加高效,在前者可以满足需要时,尽量使用forward()方法,并且,这样也有助于隐藏实际的链接。在有些情况下,比如,需要跳转到一个其它服务器上的资源,则必须使用sendRedirect()方法。

发表评论

邮箱地址不会被公开。 必填项已用*标注

昵称 *