servlet(一)

2015-12-24 by damon


一个简单的Servlet例子
第一步:定义一个Servlet类
public class MyServlet extends HttpServlet {

    /**
     * serialVersionUID 
     */
    private static final long serialVersionUID = 7534209592270696536L;


    public void init() throws ServletException {
        System.out.println("pass init ...");
    }

    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("pass doGet ...");
    }

    public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("pass doPost ...");
    }

    public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("pass service ...");
    }

    public void destroy() {
        System.out.println("pass destroy ...");
    }
}
第二步:在web.xml中添加如下代码
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
      version="3.0">

    <servlet>
        <servlet-name>test</servlet-name>
        <servlet-class>com.damon.test.MyServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>test</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>
深入学习Servlet的原理
public class MyServlet extends HttpServlet {

这个HttpServlet是什么东东呢? 为什么要继承它?

窥探Servlet

Servlet API中的类关系图如下:

wKioL1Z784bz26LsAAC6X8NU0Ow952.png

这里只是陈列了Servlet类家族中的部分API,从上图中可以看出类的根是 javax.servlet.Servlet

servlet源码
package javax.servlet;

import java.io.IOException;

public interface Servlet {

    /**
     *负责初始化Servlet对象。容器一旦创建好Servlet对象后,就调用此方法来初始化Servlet对象
     */

    public void init(ServletConfig config) throws ServletException;

    /**
     *返回一个ServletConfig对象,该对象中包含了Servlet初始化参数信息
     */

    public ServletConfig getServletConfig();

    /**
     *方法负责响应客户的请求,提供服务。当容器接收到客户端要求访问特定的servlet请求时,就会调用Servlet的service方法
     */

    public void service(ServletRequest req, ServletResponse res)
    throws ServletException, IOException;

    /**
     *返回一个字符串,在该字符串中包含servlet的创建者,版本和版权等信息
     */

    public String getServletInfo();

    /**
     *负责释放Servlet 对象占用的资源,当servlet对象结束生命周期时,servlet容器调用此方法来销毁servlet对象.
     */

    public void destroy();
}

它定义了所有的后续Servlet必须实现的方法,Servlet是一个Web服务器中运行的一个小型的Java程序。 Servlets接收和响应来自Web客户端的请求,通信通常是通过HTTP超文本传输协议。

要实现该接口,你可以写一个继承自javax.servlet.GenericServletr的genericServlet 或继承自javax.servlet的HttpServlet(这就是为什么我们自定义的Servlet通常是extentds HttpServlet的)。

此接口定义了方法可以来初始化Servlet、服务请求、从服务器上删除一个Servlet。这些被众所周知为生命周期方法,它们被按如下顺序调用:

  1. Servlet被构造器构造后,用init()方法进行对象初始化

  2. 任何从客户端的调用,都是service()方法在处理。

  3. Servlet停止提供服务后,用destroy()方法进行销毁,最后被垃圾回收器回收掉。

除了生命周期方法,该接口提供了getServletConfig方法(该servlet可以用它来得到任何启动信息)与getServletInfo方法(它允许servlet返回它自身的基本信息,如作者,版本和版权所有)。 在上面javax.servlet.Servlet源码中有如下代码:

public void init(ServletConfig config) throws ServletException;

这里用到了ServletConfig,从字面意思看,应该是一个与配置信息有关的类。

package javax.servlet;

import java.util.Enumeration;

public interface ServletConfig {

    /**
     *返回servlet实例的名称
     */

    public String getServletName();

    /**
     *返回servlet实例的上下文
     */

    public ServletContext getServletContext();

    /**
     *返回初始化参数中明为name的value值
     */

    public String getInitParameter(String name);


    /**
     *返回初始化参数的枚举
     */

    public Enumeration getInitParameterNames();
}

API文档中对它的描述是:这是一个接口,其实例是Servlet的配置对象,在Servlet初始化期间,Servlet容器通过它传信息到Servlet中。

一个servlet初始化参数的例子
第一步:在web.xml文件中进行入参
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">

    <servlet>
        <servlet-name>test</servlet-name>
        <servlet-class>com.damon.test.MyServlet</servlet-class>
        <init-param>
            <param-name>name</param-name>
            <param-value>damon</param-value>
        </init-param>
        <init-param>
            <param-name>age</param-name>
            <param-value>26</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>test</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>
第二步:在Servlet中的service方法中获取参数
public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("pass service ...");
    ServletConfig config = this.getServletConfig();
    System.out.println("name:" + config.getServletName());  

    @SuppressWarnings("unchecked")
    Enumeration<String> enums = config.getInitParameterNames();  
    for(String s : Collections.list(enums)){  
        System.out.println("init-param-name:" + s);  
        System.out.println("init-param-value:" + config.getInitParameter(s));  
    } 
}

控制台输出:

pass service ...

name:test

init-param-name:name

init-param-value:damon

init-param-name:age

init-param-value:26

两个servlet传参不一样,ServletConfig也是不一样(这样Web容器才能把不同的参数传到不同的Servlet)

wKioL1Z786LgilFwAABViz78AZg062.png

总结:对于ServletConfig而言,从一个servlet被实例化后,对任何客户端在任何时候访问有效,但仅对本servlet有效,一个servlet的ServletConfig对象不能被另一个servlet访问。