`
paddy.w
  • 浏览: 498255 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

关于Servlet基础的一点东西

阅读更多
        刚接触Servlet时感觉有点晕,各种与servlet相关的东西。从API上弄了点东西,供初学者参考。

        Servlet是运行在服务器端的程序,Sun只是制定了其规范(即只定义了接口),而由Servlet容器来具体实现。所以,Servlet程序的具体实现因容器的不同而不同。但是都遵循同一个规范。

        javax.servlet.Servlet是个Interface,其他的各种Servlet都必须继承或者实现这个接口。

        Servlet这个接口被以下类、抽象类或者接口实现:FacesServlet(类), GenericServlet(抽象类), JspPage(接口)。

        这三个里面我们讲一下GenericServlet(javax.servlet.GenericServlet):
public abstract class GenericServlet implements Servlet,ServletConfig,java.io.Serializable

        以上可知,这个抽象类实现了Servlet, ServletConfig, java.io.Serializable。但这些都是空实现,而且没有实现service方法,由容器具体实现。HttpServlet(javax.servlet.http.HttpServlet)这个有具体实现的抽象类继承了GenericServlet,这是个基于http特定协议的servlet。举个Servlet类的例子:
public class LoginPage extends HttpServlet

        可以看到,我们一般的基于http协议编程的Servlet类直接继承了HttpServlet。

        在每个Servlet类中都有doGet和doPost方法,我们看看他们后面的参数,比如doPost:
public void doPost(HttpServletRequest request, HttpServletResponse response)


        其实,根据规范应该有这个通用方法来服务请求:
public void service(ServletRequest req, ServletResponse res)

        而HttpServlet是针对Http协议的实现,所以HttpServlet把这个方法重写为:
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(HttpServletRequest req, HttpServletResponse resp)

        而在这个方法内部,又根据http协议的规定,分别对请求进行分析。如果是get请求,执行doGet方法;如果是post请求,执行doPost方法,等等等等。

        我们看HttpServletRequest(HttpServletResponse类似)。这是个接口,它实现了ServletRequest接口,ServletRequest中有我们熟悉的setAttribute、getAttribute、getParameter、getParameterMap、getParameterValues、getRequestDispatcher等方法。

—————————————————————低调的分割线————————————————————

        Servlet初始化阶段:

            在下列时刻,Servlet容器装载Servlet:
  • Servlet容器启动时自动装载某些Servlet
  • 在Servlet容器启动后,客户首次向Servlet发出请求
  • Servlet的类文件被更新后,重新装载Servlet(.class文件)。访问时,同第二种情况
  •         Servlet被装载后,Servlet容器创建一个Servlet实例并且调用Servlet的init()方法进行初始化。在Servlet的整个生命周期中,init方法只被调用一次。

        Servlet终止阶段

            在下列情况,Servlet容器终止Servlet:
  • 当Web应用被终止
  • Servlet容器终止运行
  • Servlet容器重新装载新实例
  •         Servlet容器会先调用Servlet的destory方法。在destory方法中可以释放Servlet所占用的资源


—————————————————————低调的分割线————————————————————

        访问Servlet:

        要访问Servlet,首先需要在web.xml文件中进行配置,其格式如下:
<servlet>
    <servlet-name>test</servlet-name>
    <servlet-class>test.test</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>test</servlet-name>
    <url-pattern>/test</url-pattern>
</servlet-mapping>

        我们通过浏览器http://localhost:8080/projectname/test来进行访问。可以看到,通过浏览器地址的/test对应到了<servlet-mapping>中的url-pattern,在根据其对应的servlet-name找到<servlet>中的servlet-class,这样就可以访问到相应的servlet了。

        有的servlet配置并没有<servlet-mapping>,这样的servlet的作用并不是用来访问,而是用于servlet容器启动之后的初始化工作。在servlet类中重写init方法,并在web.xml中如下配置:
<servlet>
    <servlet-name>test</servlet-name>
    <servlet-class>test.test</servlet-class>
    <load-on-startup>3</load-on-startup>
</servlet>

        <load-on-startup>内的数字无关紧要,只是标识这个servlet在容器启动后初始化的顺序。在容器启动后,会自动加载这个servlet,并执行其中的init方法。

—————————————————————低调的分割线————————————————————

        关于ServletContext:

        servlet容器启动一个应用时,会为此应用创建一个全局共享的ServletContext对象。此对象任何时候都可以访问,而且所有的servlet实例共享此对象。此外还有一个全局的ServletConfig对象,此对象包含了servlet的初始化信息。

        如何获得ServletContext对象?

        1、假设request为HttpServletRequest对象,则可以如下方式获取:
ServletContext context = request.getSession().getServletContext();


        2、ServletConfig中有getServletContext()这样一个方法,这也是ServletConfig主要的用处。但是如何获取ServletConfig对象呢?注意:在前文中已经提到,我们一般的servlet继承了HttpServlet,而HttpServlet又继承了GenericServlet,GenericServlet实现了ServletConfig接口。因此可以这么获取ServletContext对象:
ServletContext context = this.getServletContext();


—————————————————————低调的分割线————————————————————

        Servlet是单例的!

        Servlet是单例的,即多个请求由同一个Servlet对象进行处理。虽然只有一个对象进行处理,但对象会生成多个线程来处理多个请求。因此,在servlet中如果涉及写操作的话,最好不要使用成员变量,而使用局部变量。
        三种避免多线程混乱的方法:
        1、实现javax.servlet.SingleThreadModel(servlet2.4中已经废止)
        2、使用局部变量(推荐,忘掉其他两种方法吧……)
        3、使用synchronized块

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

相关推荐

Global site tag (gtag.js) - Google Analytics