Servlet_2

Servlet_2

     1.Servlet的生命周期

         在 Java 中,任何对象都有生命周期,Servlet 也不例外。Servlet 的生命周期如图 1 所示。

         Servlet的生命周期,按照功能的不同,大致可以将Servlet的生命周期分为四个阶段,分别是加载实例化阶段、初始化阶段、运行阶段【处理请求】和销毁阶段。

         1.加载实例化阶段

            当Servlet容器启动以后,会加载项目的web.xml配置文件,并解析得到所有配置好的servlet-class中配置的包名+类名,通过反射机制就实例化好了包名+类名对应的Servlet类对象。

         2.初始化阶段

            当客户端向 Servlet 容器发出 HTTP 请求要求访问 Servlet 时,Servlet 容器首先会解析请求,检查内存中是否已经有了该 Servlet 对象,如果有,则直接使用该 Servlet 对象,如果没有,

则创建 Servlet 实例对象,然后通过调用 init() 方法实现 Servlet 的初始化工作。需要注意的是,在 Servlet 的整个生命周期内,它的 init() 方法只能被调用一次。

         3.运行阶段

            这是 Servlet 生命周期中最重要的阶段,在这个阶段中,Servlet 容器会为这个请求创建代表 HTTP 请求的 ServletRequest 对象和代表 HTTP 响应的 ServletResponse 对象,然后将它们

作为参数传递给 Servlet 的 service() 方法。 service() 方法从 ServletRequest 对象中获得客户请求信息并处理该请求,通过 ServletResponse 对象生成响应结果。


            在 Servlet 的整个生命周期内,对于 Servlet 的每一次访问请求,Servlet 容器都会调用一次 Servlet 的 service() 方法,并且创建新的 ServletRequest 和 ServletResponse 对象,也就是

说,service() 方法在 Servlet 的整个生命周期中会被调用多次。

         4.销毁阶段

            当服务器关闭或 Web 应用被移除出容器时,Servlet 随着 Web 应用的关闭而销毁。在销毁 Servlet 之前,Servlet 容器会调用 Servlet 的 destroy() 方法,以便让 Servlet 对象释放它所占

用的资源。在 Servlet 的整个生命周期中,destroy() 方法也只能被调用一次。

           需要注意的是,Servlet 对象一旦创建就会驻留在内存中等待客户端的访问,直到服务器关闭或 Web 应用被移除出容器时,Servlet 对象才会销毁。

package com.wangxing.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;

public class TestServlet2 extends HttpServlet{
	@Override
	public void init() throws ServletException {
		System.out.println("初始化阶段调用 init() 方法实现 Servlet 的初始化工作");
	}
	@Override
	public void service(ServletRequest req, ServletResponse resp) throws ServletException, IOException {
		System.out.println("运行阶段Servlet 容器都会调用一次 Servlet 的 service() 方法,完成请求处理");
	}
	@Override
	public void destroy() {
		System.out.println("Servlet 容器会调用 Servlet 的 destroy() 方法,以便让 Servlet 对象释放它所占用的资源");
	}
}

      2.Servlet的service方法与doGet/doPost方法的关系

          1.service方法与doGet/doPost方法都是HttpServlet类的方法

              1.service(ServletRequest req, ServletResponse resp)---来自于Servlet接口

              2.service(HttpServletRequest req, HttpServletResponse resp)---自己定义的

              3.doGet(HttpServletRequest req, HttpServletResponse resp)----自己定义的

              4.doPost(HttpServletRequest req, HttpServletResponse resp)----自己定义的

            在具体处理请求的时候Servlet容器会默认调用来自于Servlet接口的.service(ServletRequest req, ServletResponse resp)方法来出里请求。HttpServlet类中会在用来自于Servlet接口

的.service(ServletRequest req, ServletResponse resp)方法中调用HttpServlet自己定义的service(HttpServletRequest req, HttpServletResponse resp),这是处理请求的时候,HttpServlet自己定

义的service(HttpServletRequest req, HttpServletResponse resp)就执行了,此时HttpServlet自己定义的service(HttpServletRequest req, HttpServletResponse resp)方法中用过

HttpServletRequest 对象得到请求提交方式,判断请求提交方式调用对应的doGet/doPost方法处理请求。

public abstract class HttpServlet extends GenericServlet {
    private static final String METHOD_GET = "GET";
    private static final String METHOD_POST = "POST";
    @Override
	public void service(ServletRequest req, ServletResponse resp) throws ServletException, IOException {
		HttpServletRequest arg0=(HttpServletRequest)req;
		HttpServletResponse arg1=(HttpServletResponse)resp;
		service(arg0,  arg1); 
	}
    protected void service(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException {
		String method=arg0.getMethod();
		if(method.equals("get")){
			doGet(arg0, arg1);
		}
		if(method.equals("post")){
			doPost(arg0, arg1);
		}
	}
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
		super.doGet(req, resp);
	}
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
		super.doPost(req, resp);
	}
   
}

     3.Servlet配置虚拟路径映射

          Servlet 的多重映射指同一个 Servlet 可以被映射成多条虚拟路径。也就是说,客户端可以通过多条路径实现对同一个 Servlet 的访问。Servlet 多重映射的实现方式有以下两种。

         1.配置多个 <servlet-mapping> 元素

<servlet>
  	<servlet-name>testservlet</servlet-name>
  	<servlet-class>com.wangxing.servlet.TestServlet3</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>testservlet</servlet-name>
  	<url-pattern>/test3</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
  	<servlet-name>testservlet</servlet-name>
  	<url-pattern>/test33</url-pattern>
  </servlet-mapping>

         http://localhost:8080/TestServlet3/test3

         http://localhost:8080/TestServlet3/test33

        上面这两个不同的路径就可以访问同一个Servlet程序。

        2.配置多个 <url-pattern> 子元素

           在<servlet-mapping> 元素进行配置,配置多个 <url-pattern>

<servlet>
  	<servlet-name>testservlet</servlet-name>
  	<servlet-class>com.wangxing.servlet.TestServlet3</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>testservlet</servlet-name>
  	<url-pattern>/test3</url-pattern>
  	<url-pattern>/test33</url-pattern>
  </servlet-mapping>

          http://localhost:8080/TestServlet3/test3

         http://localhost:8080/TestServlet3/test33

       上面这两个不同的路径就可以访问同一个Servlet程序。

     4.Servlet映射路径中使用通配符

        在实际开发过程中,开发者有时会希望某个目录下的所有路径都可以访问同一个 Servlet,这时,可以在 Servlet 映射的路径中使用通配符“*”。通配符的格式有两种,具体如下:

        1.格式为“*.扩展名”,例如 *.do 匹配以 .do 结尾的所有 URL 地址。匹配以 .hello 结尾的所有 URL 地址:

<servlet>
  	<servlet-name>testservlet</servlet-name>
  	<servlet-class>com.wangxing.servlet.TestServlet3</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>testservlet</servlet-name>
  	<url-pattern>*.hello</url-pattern>
  </servlet-mapping>

          http://localhost:8080/TestServlet3/abc.hello

          http://localhost:8080/TestServlet3/hello.hello

     2.格式为 /*,例如 /abc/* 匹配以 /abc 开始的所有 URL 地址。匹配所有 URL 地址:

<servlet>
  	<servlet-name>testservlet</servlet-name>
  	<servlet-class>com.wangxing.servlet.TestServlet3</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>testservlet</servlet-name>
  	<url-pattern>/*</url-pattern>
  </servlet-mapping>

          http://localhost:8080/TestServlet3/test3

          http://localhost:8080/TestServlet3/test33

          http://localhost:8080/TestServlet3/abc

          http://localhost:8080/TestServlet3/hello

     匹配以 /test开始的所有 URL 地址:

<servlet>
  	<servlet-name>testservlet</servlet-name>
  	<servlet-class>com.wangxing.servlet.TestServlet3</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>testservlet</servlet-name>
  	<url-pattern>/test/*</url-pattern>
  </servlet-mapping>

          http://localhost:8080/TestServlet3/test

          http://localhost:8080/TestServlet3/test/abc

        需要注意的是,这两种通配符的格式不能混合使用,例如,/abc/*.do 是不合法的映射路径。另外,当客户端访问一个 Servlet 时,如果请求的 URL 地址能够匹配多条虚拟路径,那么

Tomcat 将采取最具体匹配原则查找与请求 URL 最接近的虚拟映射路径。

        例如,对于如下所示的一些映射关系:

/abc/* 

Servlet1

/*

Servlet2

/abc 

Servlet3

*.do

Servlet4

          当请求 URL 为 /abc/a.html----/abc/* 和 /* 都可以匹配这个 URL,Tomcat 会调用 Servlet1.

          当请求 URL 为 /abc----/*、/abc/* 和 /abc 都可以匹配这个URL,Tomcat 会调用 Servlet3。

          当请求 URL 为 /abc/a.do-----/*、*.do 和 /abc/*都可以匹配这个URL,Tomcat 会调用 Servlet1。

          当请求 URL 为 /a.do--------/* 和 *.do 都可以匹配这个URL,Tomcat 会调用 Servlet2。

          当请求 URL 为 /xxx/yyy/a.do----*.do 和 /* 都可以匹配这个URL,Tomcat 会调用 Servlet2。

          如果某个 Servlet 的映射路径仅仅是一个正斜线(/),那么这个 Servlet 就是当前 Web 应用的默认 Servlet。Servlet 服务器在接收到访问请求时,如果在 web.xml 文件中找不到匹配的

<servlet-mapping> 元素的 URL,则会将访问请求交给默认 Servlet 处理,也就是说,默认 Servlet 用于处理其他 Servlet 都不处理的访问请求。

          需要注意的是,在 Tomcat 安装目录下的conf文件夹中 web.xml 文件中也配置了一个默认的 Servlet,配置信息如下所示:

<servlet>
    <servlet-name>default</servlet-name>
    <serlet-class>org.apache.catalina.servlets.DefaultServlet</serlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

          在上面的配置信息中,org.apache.catalina.servlets.DefaultServlet 被设置为默认的 Servlet,它对 Tomcat 服务器上所有的 Web 应用都起作用。

当 Tomcat 服务器中的某个 Web 应用没有默认 Servlet 时,都会将 DefaultServlet 作为默认的 Servlet。当客户端访问 Tomcat 服务器中的某个静态 HTML 文件时,DefaultServlet 会判断 HTML

是否存在,如果存在,则会将数据以流的形式回送给客户端,否则会报告 404 错误。

     5.servlet处理用户请求的完整流程

          针对 Servlet 的每次请求,Web 服务器在调用 service() 方法之前,都会创建 HttpServletRequest 和 HttpServletResponse 对象。其中,HttpServletRequest 对象用于封装 HTTP 请求消

息,简称 request 对象。HttpServletResponse 对象用于封装 HTTP 响应消息,简称 response 对象。浏览器访问 Servlet 的交互过程如图 1 所示。

          在图中,首先浏览器向 Web 服务器发送了一个 HTTP 请求,Web 服务器根据收到的请求,会先创建一个 HttpServletRequest 和 HttpServletResponse 对象,然后再调用相应的 Servlet 程

序。在 Servlet 程序运行时,它首先会从 HttpServletRequest 对象中读取数据信息,然后通过 service() 方法处理请求消息,并将处理后的响应数据写入到 HttpServletResponse 对象中。最后,

Web 服务器会从 HttpServletResponse 对象中读取到响应数据,并发送给浏览器。

          需要注意的是,在 Web 服务器运行阶段,每个 Servlet 都只会创建一个实例对象,针对每次 HTTP 请求,Web 服务器都会调用所请求 Servlet 实例的 service(HttpServletRequest

request,HttpServletResponse response)方法,并重新创建一个 request 对象和一个 response 对象。

     6.Servlet中常用的接口、类、方法

        Sun 公司提供了一系列的接口和类用于 Servlet 技术的开发,其中最重要的接口是 javax.servlet.Servlet。

        1.Servlet接口        public abstract interface Servlet

方法声明

功能描述

void init(ServletConfig config)

容器在创建好 Servlet 对象后,就会调用此方法。该方法接收一个 ServletConfig 类型的参数,Servlet 容器通过该参数向 Servlet 传递初始化配置信息

ServletConfig getServletConfig ()

用于获取 Servlet 对象的配置信息,返回 Servlet 的 ServletConfig 对象

String getServletInfo()

返回一个字符串,其中包含关于 Servlet 的信息,如作者、版本和版权等信息

void service (ServletRequest request,ServletResponse response)

负责响应用户的请求,当容器接收到客户端访问 Servlet 对象的请求时,就会调用此方法。
容器会构造一个表示客户端请求信息的 ServletRequest 对象和一个用于响应客户端的 ServletResponse 对象作为参数传递给 service() 方法。
在 service() 方法中,可以通过 ServletRequest 对象得到客户端的相关信息和请求信息,在对请求进行处理后,调用 ServletResponse 对象的方法设置响应信息

void destroy()

负责释放 Servlet 对象占用的资源。当服务器关闭或者 Servlet 对象被移除时,Servlet 对象会被销毁,容器会调用此方法

          针对 Servlet 的接口,Sun 公司提供了两个默认的接口实现类:GenericServlet 和 HttpServlet。其中,GenericServlet 是一个抽象类,该类为 Servlet 接口提供了部分实现,它并没有实现

HTTP 请求处理。

          HttpServlet 是 GenericServlet 的子类,它继承了 GenericServlet 的所有方法,并且为 HTTP 请求中的 GET 和 POST 等类型提供了具体的操作方法。通常情况下,编写的 Servlet 类都继

承自 HttpServlet,在开发中使用的也是 HttpServlet 对象。

          HttpServlet 类中包含两个常用方法:

方法声明

功能描述

protected void doGet (HttpServletRequest req, HttpServletResponse resp)

用于处理 GET 类型的 HTTP 请求的方法

protected void doPost(HttpServletRequest req, HttpServletResponse resp)

用于处理 POST 类型的 HTTP 请求的方法

        2.ServletConfig接口         public  abstract  interface  ServletConfig

          在运行 Servlet 程序时,可能需要一些辅助信息,例如,文件使用的编码、使用 Servlet 程序的共享信息等,这些信息可以在 web.xml 文件中使用一个或多个 <init-param> 元素进行配置。

当 Tomcat 初始化一个 Servlet 时,会将该 Servlet 的配置信息封装到 ServletConfig 对象中,此时可以通过调用 init(ServletConfig config)方法将 ServletConfig 对象传递给 Servlet。

          ServletConfig就是封装Servlet运行时的辅助信息的接口。

          ServletConfig 接口中定义了一系列获取配置信息的方法。

方法说明

功能描述

String getInitParameter(String name)

根据初始化参数名返回对应的初始化参数值

ServletContext getServletContext()

返回一个代表当前 Web 应用的 ServletContext 对象

String getServletName()

返回 Servlet 的名字,即 web.xml 中 <servlet-name>元素的值

         例如:通过ServletConfig接口对象得到web.xml文件中配置的初始化参数值,和配置的servlet-name的值。

<servlet>
    <servlet-name>testservlet4</servlet-name>
    <servlet-class>com.wangxing.servlet.TestServlet4</servlet-class>
    <!-- 配置初始化参数 -->
    <init-param>
    	<param-name>myname</param-name>
    	<param-value>zhangsan</param-value>
    </init-param>
    <init-param>
    	<param-name>mypassword</param-name>
    	<param-value>123456</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
  	 <servlet-name>testservlet4</servlet-name>
  	 <url-pattern>/test4</url-pattern>
  </servlet-mapping>
@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//得到ServletConfig接口对象
		ServletConfig config=this.getServletConfig();
		//通过ServletConfig接口对象得到web.xml文件中配置的初始化参数值
		//String getInitParameter(String name)	根据初始化参数名返回对应的初始化参数值
		String myname=config.getInitParameter("myname");
		String mypassword=config.getInitParameter("mypassword");
	System.out.println("初始化参数值myname=="+myname+",mypassword=="+mypassword);
//得到web.xml 中 <servlet-name>元素的值
	    //String getServletName()	返回 Servlet 的名字,即 web.xml 中 <servlet-name>元素的值
	    String servletName=config.getServletName();
	    System.out.println(" web.xml 中 <servlet-name>元素的值==="+servletName);
	}

        3.ServletContext接口

          当 Tomcat 启动时,Tomcat 会为每个 Web 应用创建一个唯一的 ServletContext 对象代表当前的 Web 应用,该对象封装了当前 Web 应用的所有信息。可以利用该对象获取 Web 应用程序

的Servlet版本,初始化信息、读取资源文件等。

ServletConfig接口

ServletContext getServletContext()

返回一个代表当前 Web 应用的 ServletContext 对象

方法说明

功能描述

int getMajorVersion()

得到servlet规范的主版本号

int getMinorVersion()

得到servlet规范的次版本号

String  getInitParameter(String)

得到指定的初始化信息<context-param>

Enumeration<String> getInitParameterNames()

得到包含所有初始化信息名的Enumeration对象

 

           配置web.xml:

<!-- 配置初始化信息 -->
  <context-param>
     <param-name>myname</param-name>
     <param-value>lisi</param-value>
  </context-param>
  <context-param>
  	<param-name>myage</param-name>
  	<param-value>24</param-value>
  </context-param>
  <servlet>
    <servlet-name>testservlet5</servlet-name>
    <servlet-class>com.wangxing.servlet.TestServlet5</servlet-class>
  </servlet>
  <servlet-mapping>
  	 <servlet-name>testservlet5</servlet-name>
  	 <url-pattern>/test5</url-pattern>
  </servlet-mapping>
@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//得到ServletContext接口对象
		ServletContext context=this.getServletContext();
		//得到Servlet版本号
		int majorVersion=context.getMajorVersion();
		int minorVersion=context.getMinorVersion();
		System.out.println("Servlet版本号=="+majorVersion+"."+minorVersion);
		//得到初始化信息
		//String  getInitParameter(String)	得到指定的初始化信息<context-param>
		String name=context.getInitParameter("myname");
		String age=context.getInitParameter("myage");
		System.out.println("初始化信息myname=="+name+",age=="+age);
		// 得到包含所有初始化信息名的Enumeration对象
        Enumeration<String> paramNames = context.getInitParameterNames();
        // 遍历所有的初始化参数名,得到相应的参数值并打印
        while (paramNames.hasMoreElements()) {
          String paramname = paramNames.nextElement();
          String value = context.getInitParameter(paramname);
          System.out.println("初始化信息=="+paramname+"="+value);
        }
	}

     7.读取 Web 应用下的资源文件

        在实际开发中,有时会需要读取 Web 应用中的一些资源文件,如配置文件和日志文件等。为此,在 ServletContext 接口中定义了一些读取 Web 资源的方法,这些方法是依靠 Servlet 容器

实现的。Servlet 容器根据资源文件相对于 Web 应用的路径,返回关联资源文件的 I/O 流或资源文件在系统的绝对路径等。

       ServletContext 接口中用于获取资源路径的相关方法。

方法说明

功能描述

Set getResourcePaths(String path)


返回一个 Set 集合,集合中包含资源目录中子目录和文件的路径名 称。参数 path 必须以正斜线(/)开始,指定匹配资源的部分路径

String getRealPath(String path) 

返回资源文件在服务器文件系统上的真实路径(文件的绝对路径)。参数 path 代表资源文件的虚拟路径,它应该以正斜线(/)开始,/ 表示当前 Web 应用的根目录,如果 Servlet 容器不能将虚拟路径转换为文 件系统的真实路径,则返回 null


URL getResource(String path)

返回映射到某个资源文件的 URL 对象。参数 path 必须以正斜线(/)开始,/ 表示当前 Web 应用的根目录

InputStream getResourceAsStream(String path)

返回映射到某个资源文件的 InputStream 输入流对象。参数 path 的传递规则和 getResource() 方法完全一致

         1.在项目的 src 目录中创建一个名称为xxxxx.properties 的文件

            testname=zhangsan

            testage=23

            testaddress=\u897F\u5B89

         2.编写读取xxxxx.properties 的文件的Servlet处理类。

package com.wangxing.servlet;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet6 extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req, resp);
	}
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//得到ServletContext接口对象
		ServletContext context=this.getServletContext();
		//读取资源文件
		//InputStream getResourceAsStream(String path)	返回映射到某个资源文件的 InputStream 输入流对象。
		InputStream in=context.getResourceAsStream("/WEB-INF/classes/mytest.properties");
		Properties pros = new Properties();
	    pros.load(in);
	    String name=pros.getProperty("testname");
	    String age=pros.getProperty("testage");
	    String address=pros.getProperty("testaddress");
	    System.out.println("mytest.properties---testname===="+name);
	    System.out.println("mytest.properties---testage===="+age);
	    System.out.println("mytest.properties---testaddress===="+address);
	}
}

          3.配置web.xml

  <servlet>
    <servlet-name>testservlet6</servlet-name>
    <servlet-class>com.wangxing.servlet.TestServlet6</servlet-class>
  </servlet>
  <servlet-mapping>
  	 <servlet-name>testservlet6</servlet-name>
  	 <url-pattern>/test6</url-pattern>
  </servlet-mapping>

          4.测试

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值