关云长重生

导航

什么是Servlet

写Web应用时,直接用的spring框架,没有接触过Servlet,于是遇到问题不知道根本原因,所以还是学一下吧!
一、 什么是Servlet
看见这个词我就晕,到底是什么?我试着说清楚,从大的方面来说,它是一个在Web中生成动态内容的标准,即是用于开发Web应用程序的基本技术;从小的方面来说它是Java提供的一个接口Servlet,我们也把实现这个接口的类称为Servlet。它和CGI相对,但是它不向CGI一样每次接受一个Http请求都会创建一个进程(想想Chrome),它每次执行完它的第一个请求之后都会驻留在内存中,等待后续的请求。
一个Servlet应用程序经常包括一个或者多个Servlet,Servlet是运行在Servlet容器中的,它不能自动运行。Servlet容器又是什么东西?我的理解就是实现了Servlet规范,然后暴露出来一些编程的接口供我们实现自己的逻辑,所以每个自定义的Servlet类都要实现Servlet接口,它能够生成动态的内容,不向Web服务器一样,只是提供静态资源。更细节的内容看如下的相关文章。Servlet容器将用户的请求传给Servlet应用程序,并将Servlet应用程序的响应回传给用户。比较流行的Servlet容器有Tomcat和Jetty。这两个本质上是Servlet容器 ,而不是Web服务器,但是它们把Web服务器要做的工作也集成到容器中了,所以不需要额外的Web服务器。
二、 Servlet API
我使用的是Servlet的3.1.0版本,有4个Java包:
javax.servlet:包含Servlet与Servlet容器进行通信需要的类和接口,比如请求、响应、过滤和监听等;
javax.servlet.http:包含Servlet的实现类httpServlet与Servlet容器进行通信需要的类和接口;
javax.servlet.annotation:使用Servlet、Filter和Listener时需要的注解;
javax.servlet.descriptor:提供对配置信息进行编程式访问的类型;
在Servlet技术的核心当然是Servlet接口,每个自定义的类都是直接或者间接实现了这个接口。在这个接口中说明了Servlet怎么被Servlet容器调用,首先容器会把Servlet类加载到内存中,并在Servlet类调用特定的方法,在每个应用程序中,每个Servlet只有一个实例(单实例)。下面试一下Servlet中的方法:

  1. public class TestServlet implements Servlet {  
  2.     private transient ServletConfig servletConfig;  
  3.       
  4.     public void init(ServletConfig config) throws ServletException {  
  5.         this.servletConfig = config;  
  6.         System.out.println("init");  
  7.     }  
  8.   
  9.     public ServletConfig getServletConfig() {  
  10.         return servletConfig;  
  11.     }  
  12.   
  13.     public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {  
  14.         System.out.println("service");  
  15.     }  
  16.   
  17.     public String getServletInfo() {  
  18.         return this.servletConfig.getServletName();  
  19.     }  
  20.   
  21.     public void destroy() {  
  22.         System.out.println("destroy");  
  23.     }  
  24. }  
除了要自定义一个Servlet类,我们还要想一个办法来确定怎么访问到我们自定义的Servlet?显然要指定url,有两种方法:
通过注解,比较简单,直接在类上加上注解:
  1. @WebServlet(name="testServlet", urlPatterns="/testServlet",loadOnStartup=-1)  
  2. public class TestServlet implements Servlet {}  

通过web.xml配置:

  1. <servlet>  
  2.     <servlet-name>TestServlet</servlet-name>  
  3.     <servlet-class>com.javaservlet.servlet.TestServlet</servlet-class>  
  4. </servlet>  
  5. <servlet-mapping>  
  6.     <servlet-name>TestServlet</servlet-name>  
  7.     <url-pattern>/TestServlet</url-pattern>  
  8. </servlet-mapping>  

注意:
配置url-pattern时,可以对一个Servlet配置多个url,也就是可以通过多个url来访问同一个servlet;
配置url-pattern时,也可以使用通配符进行配置,但是只有两种固定方法:一是“*.扩展名”,类似“*.html”;另外一个则是以“/”开头,以“/*”结尾,类似“/test/*”;
启动Servlet容器,这里我们使用Tomcat,经过多次使用浏览器发送请求,输出如下:

Servlet接口中有三个生命周期方法:
init():刚启动Servlet容器时不会调用这个方法,当第一次请求来的时候才会调用该方法,其实什么时候调用由loadOnStartup属性决定,如果是非0值则该方法会在容器启动时被调用,但是该值默认是-1,在后续的请求时不会再调用该方法,所以说在该方法中进行程序初始化相关的代码,另外值得注意的是该方法总是在servlet的构造器之后运行;
service():每次请求Servlet时候,Servlet容器会调用这个方法,是具体编写业务逻辑的地方;
destroy():销毁Servlet的时候,Servlet容器会调用这个方法,发生在卸载应用程序或者关闭Servlet容器时,另外从上面的输出来看,每次修改代码后保存都会reload,这个时候其实销毁该Servlet类,关闭Servlet容器并重新开启,可以在这个方法中进行资源清理的工作;
该接口中还有其他两个非生命周期的方法:getServletInfo()感觉不是很常用,只是返回对Servlet的描述;getServletConfig()返回init()传入的ServletConfig类实例,是关于Servlet的配置信息。
由于Servlet实例是单实例,在每一个应用程序中,多次请求都是针对一个对象,很容易造成并发问题,所以可以把它当做只读的,或者使用java并发机制中成员。

posted on 2017-08-31 16:12  关云长重生  阅读(265)  评论(0编辑  收藏  举报