1. Servlet简介

Servlet是sun公司提供的一门用于开发动态web资源的技术。sun公司在其API中提供了一个servlet接口,用户若想要发一个动态web资源,只需要完成以下两步即可:

1)编写一个servlet,即实现servlet接口的Java类;

2) 把开发好的servlet部署到web服务器中。

Servlet接口定义了所有servlet必须实现的方法。一个servlet是运行在web服务器中的一个小java程序,servlet通过HTTP协议接收并响应web客户端发来的请求。这个接口中定义的方法包括初始化servlet,服务请求,以及remove servlet,这些方法即servlet的生命周期方法,调用顺序如下:

1)某个创建servlet对象的时候,调用初始化方法: void init(ServletConfig config)

2)客户端发送请求的时候,service方法被执行:void service(ServletRequest req, ServletResponse res)

3)某个servlet对象被摧毁的时候,调用destroy方法: void destroy()

除了这些与生命周期有关的方法外,Servlet接口还提供了getServletConfig方法和getServletInfo方法,getServletConfig方法可以获得servlet的一些启动信息,getServletInfo方法可以返回servlet本身的一些信息。

sun公司定义了Servlet接口的两个默认实现类,分别为javax.servlet.GenericServlet和javax.servlet.http.HttpServlet。

HttpServlet指能够处理HTTP请求的servlet,它再原有的Servlet接口上添加了一些与HTTP协议处理方法,它比Servlet接口的功能更为强大,因此开发人员在编写Servlet时,通常应继承这个类,而避免直接去实现Servlet接口。HttpServlet在实现Servlet接口时,覆写了service方法,该方法体内的代码会自动判断用户的请求方式,如为GET请求,则调用HttpServlet的doGet方法,如为Post请求,则调用doPost方法。因此,开发人员在编写Servlet时,通常只需要覆写doGet或doPost方法,而不要去覆写service方法

2. Servlet的运行过程

Servlet程序是由web服务器调用,web服务器接收到客户端的Servlet访问请求后:
           1)web服务器首先检查是否已经装载并创建了该Servlet的实例对象,如果是,则直接执行第4步,否则执行第2步。
           2)装载并创建该Servlet的一个实例对象。
           3)调用Servlet实例对象的init()方法。
           4)创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个代表HTTP相应消息的HttpServletResponse对象,然后调用Servlet的service()方法并将请求和响应对象作为参数传递进去。
           5)web应用程序被停止或重新启动前,Servlet引擎将卸载Servlet,并在卸载之前调用Servlet的destroy()方法。

3. Servlet的几个细节

1. Servlet细节1

由于客户端是通过URL地址访问文本服务器中的资源,所以servlet程序若想被外界访问,必须把servlet程序映射到一个URL地址上,这个工作在web.xml文件中使用<servlet>元素和<servlet-mapping>元素完成。

1) <servlet>元素用于注册Servlet,它包含两个主要的子元素:

<servlet-name>:用于设置Servlet的注册名称

<servlet-class>:用于设置Servlet的完整类名

2)<servlet-mapping>元素用于映射一个已注册的Servlet的一个对外访问路径,它包含两个子元素:

<servlet-name>:用于设置Servlet的注册名称

<url-pattern>:用于指定Servlet的对外访问路径(可以随便指定)

例如:

<web-app>
<servlet>
<servlet-name>AnyName</servlet-name>
<servlet-class>HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AnyName</servlet-name>
<url-pattern>/demo/hello.html</url-pattern>
</servlet-mapping>
</web-app>

2. Servlet细节2

同一个Servlet可以被映射到多个URL上,即多个<servlet-mapping>元素的<servlet-name>子元素的设置值可以是同一个Servlet的注册名。在Servlet映射到的URL中也可以使用*通配符,但是只能有两种固定的格式:一种格式是:“*.扩展名”;另一种格式是:以“/”开头,并以“/*”结尾。例如:

<servlet-mapping>
<servlet-name>AnyName</servlet-name>
<url-pattern>*do</url-pattern>
</servlet-mapping>

也可以映射到另一个url:

<servlet-mapping>
<servlet-name>AnyName</servlet-name>
<url-pattern>/action/*</url-pattern>
</servlet-mapping>

3. servlet细节3

Servlet是一个供其他java程序(Servlet引擎)调用的java类,它不能独立运行,它的运行完全由Servlet引擎来控制和调度。针对客户端的多次Servlet请求,通常情况下,服务器只会创建一个Servlet实例对象,也就是说Servlet实例对象一旦创建,它就会驻留在内存中,为后续的其它请求服务,直至web容器退出,servlet实例对象才销毁。
        在Servlet的整个生命周期中,Servlet的init方法只被调用一次,而对一个Servlet的每次访问请求都导致Servlet引擎调用一次servlet的service方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doGet或doPost方法。

4. servlet细节4

如果再<servlet>元素中配置了一个<load-on-startup>元素,那么web应用程序在启动时,就会装载并创建Servlet的实例对象,以及调用Servlet实例对象的init()方法。该技术可以用来为web写一个initServlet,这个servlet配置为启动时装载,为整个web应用床架必要的数据库表和数据。如:

<servlet>
<servlet-name>...</servlet-name>
<servlet-class>...</servlet-class>
<load-on-startup>1<load-on-startiup>
</servlet>

5. servlet细节5

如果某个Servlet的映射路径仅仅为一个正斜杠(/),那么这个Servlet就成为当前Web应用程序的缺省Servlet。凡是在web.xml文件中找不到匹配的<servlet-mapping>元素的url,它们的访问请求都将交给缺省Servlet处理,也就是说,缺省Servlet用于处理所有其他Servlet都不处理的访问请求。
        在<tomcat安装目录>\conf\web.xml文件中,注册了一个名称为org.apache.catalina.servlets.DefaulServlet的Servlet,并将这个Servlet设置为了缺省Servlet。当访问Tomcat服务器中的某个静态HTML文件和图片时,实际上是在访问这个缺省Servlet。
        假设现在在工程名为test的WebRoot目录下新建一个1.html,在web.xml文件中并没有配置<servlet-mapping>,即在工程中没有Servlet映射成1.html,然后访问:http://localhost:8080/test/1.html时,这时候这个请求就交给缺省的Servlet,缺省的Servlet收到请求后,会首先看一下web应用下面有没有这个1.html,如果有则读取并返回到浏览器,如果没有则返回一个错误页面。

6. servlet细节6

当多个客户端并发访问同一个Servlet时,web服务器会为每一个客户端的访问请求创建一个线程,并在这个线程上调用Servlet的service方法,因为Servlet只有一个实例化对象,因此service方法内如果访问了同一个资源的话,就有可能引发线程安全问题。那么如何解决Servlet中的线程安全问题呢?
       1) 如果某个Servlet实现了SingleThreadModel接口,那么Servlet引擎将以单线程模式来调用其service方法。该接口没有任何方法,它起到了一个标志的作用。对于实现了SingleThreadModel接口的Servlet,Servlet引擎仍然支持对该Servlet的多线成并发访问,其采用的方式是产生多个Servlet实例对象,并发的每个线程分别调用一个独立Servlet实例对象。

2)使用synchronized 关键字,synchronized能保证一次只有一个线程可以访问被保护的区段,从而可以通过同步块操作来保证线程的安全。

3)尽量避免在Servlet里使用实例变量,只要在Servlet里面的任何方法里面都不使用共有的实例变量,那么该Servlet就是线程安全的。

以上三种方式中,实现SingleThreadModel接口可以解决问题,但是并不是真正解决Servlet的线程安全问题,因为Servlet引擎会创建多个Servlet实例对象,而真正意义上解决多线程安全问题是指一个Servlet实例对象被多个线程同时调用的问题。另外,创建多个Servlet实例对象也会引起大量的开销。事实上,在Servlet API 2.4中,已经将SingleThreadModel标记为过时的了。

同样,如果在程序中使用同步来保护要使用的共享的数据,也会使系统的性能大大下降。这是因为被同步的代码块在同一时刻只能有一个线程执行它,使得其同时处理客户请求的吞吐量降低,而且很多客户处于阻塞状态。所以在实际的开发中也应避免或最小化 Servlet 中的同步代码。

所以,在Servlet中避免使用实例变量是保证Servlet线程安全的最佳选择。

3. Servlet的Hello Word

最后写一个再简单不过的Hello Word吧……

public class ServletDemo extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Hello word!");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

web.xml:

<servlet>
<servlet-name>ServletDemo</servlet-name>
<servlet-class>servlet.ServletDemo</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo</servlet-name>
<url-pattern>/ServletDemo</url-pattern>
</servlet-mapping>

入门就这么多吧,如有错误之处,欢迎留言指正~

最新文章

  1. MySQL(无GUI) Windows安装和启动
  2. 深入分析JavaWeb 技术内幕
  3. 【水题】NOIP201504推销员
  4. Oracle数据库——触发器的创建与应用
  5. GCD - Extreme (II)
  6. SQLServer 2005 数据库定阅复制实现双机热备(主要是sharepoint 内容数据库)
  7. windows FileZilla Server 开启FTP over TLS
  8. Java 多线程 从无到有
  9. base加密解密工具类
  10. 融云(API)
  11. 浅谈JavaScript 函数作用域当中的“提升”现象
  12. JavaScript深入之执行上下文栈
  13. PHP字符串函数之 sscanf echo print sprintf vsprintf printf vprintf fprintf vfprintf
  14. JAVA记录-Servlet介绍
  15. psd页面切割成html技巧总结
  16. abap对象的创建和调用。方法调用
  17. Java实现经理与员工的差异
  18. 新一代Java模板引擎Thymeleaf
  19. 1.Anaconda安装Tensorflow报错UnicodeDecodeError: &#39;utf-8&#39; codec can&#39;t decode ## invalid start byte的问题之解决
  20. vmware虚拟机下linux centos6.6只有lo,没有eth0网卡、随机分配ip地址,固定ip地址等问题

热门文章

  1. C++11 lambda表达式(19篇C++11文章)
  2. 如何在natTable表格上添加双击事件
  3. Educational Codeforces Round 33 (Rated for Div. 2) A. Chess For Three【模拟/逻辑推理】
  4. ZOJ 3949 (17th 浙大校赛 B题,树型DP)
  5. Codeforces 908 D New Year and Arbitrary Arrangement
  6. UITableView的横向使用
  7. Mycat查询时出现:Error Code: 1064. can&#39;t find any valid datanode
  8. SQL Server判断某个字段是否包含中文/英文字符/数字
  9. [bug]The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
  10. Javascript中的原型链、prototype、__proto__的关系