Servlet接口SUN公司定义了两个默认实现类,分别为:GenericServlet,HttpServlet(目前主流)
HttpServlet指能够处理HTTP请求的servlet,它在原有Servlet接口上添加了一些与HTTP协议处理方法,它比Servlet接口拥有更为强大的功能。因此开发人员在编写Servlet时,通常应该继承这个类,而避免直接去实现servlet接口。
HttpServlet在实现Servlet接口时,重写了service方法,该方法体内的代码会自动判断用户的请求方式,例如GET请求,则调用HttpServlet的doGet方法,如果为post请求,则调用doPost方法。因此,开发人员在编写servlet时,通常只需要重写doGet方法和doPost方法,而不需要重写service方法
******细节(1)
由于客户端是通过URL地址访问服务器中的资源,所以servlet程序若想被外界访问,必须把servlet程序映射到一个url地址上,这个工作在web.xml文件中使用<servlet>元素和<servlet-mapping>元素完成
<servlet>元素用于注册servlet。它包含两个主要的子元素:<servlet-name>和<servlet-class>,分别用于设置servlet的注册名称和servlet的完整类名(包名+类名)
<servlet-mapping>元素用于映射一个已经注册的servlet的一个对外访问路径,它包含两个子元素:<servlet-name>和<url-pattern>,分别用于指定servlet的注册名称和servlet的对外访问路径。
一个servlet可能对应多个servlet-mapping
******细节(2)
*******细节(3)
同一个servlet可以被映射到多个URL上,即多个<servlet-mapping>的<servlet-name>子元素的设置值可以是同一个servlet的注册名
在servlet映射到的URL中可以使用通配符“*”,但是只能有两种固定的格式(上图中)
通配符可以在当用户输入错误URL时,通过通配符的映射到一个提示错误的servlet,显示出界面 友好的提示页面。
******细节(4):servlet的单例模式:
当servlet第一次被访问后,就被加载到内存,以后该实例对各个请求服务。因此会出现线程安全问题,比如我们要在网上订票,所有用户共享剩余票数这个变量,但是如果不采取同步(synchr)机制,会出现错误。
可以遵守一个简单的原则:
(1)如果一个变量需要多个用户共享,则应当在访问该变量的时候,如同步机制:
synchronized(对象){
//同步代码
}
(2)如果一个变量不需要共享,则直接在doGet()或者doPost()定义,这样就不会存在线程安全问题
*******细节(5)
需求:当网站在启动时,可能会要求初始化一些数据,比如创建一些临时表。再例如我们的网站可能会要求定时完成一些任务,比如定时写一些日志文件,备份数据库。
如果在<servlet>元素中配置了一个<load-on-startup>元素,那么WEB应用程序在启动时,就会装载并且创建servlet的实例对象、以及调用servlet实例对象的init()方法。
用途:为web应用写一个InitServlet,这个servlet配置为启动时装载,为整个web应用创建必要的数据库表和数据。或者是启动一个后台线台,定时去完成某些工作(比如每隔一定时间发送一封电子邮件)
解决方案:可以通过<servlet-on-startup>配合线程知识搞定。
因为当一个网站功能强大时,可能要初始化启动多个servlet。
我们来模拟一个定时发送电子邮件的功能:
实现思路:
1.要有一张表来保存用户设定的发送邮件信息。
表名:sendEmailTable
字段:id contnt sendtime
值: 1 "hello" 2015-06-01 20:19
2 "study" 2016-02-02 10:09
2.使用线程去完成任务
简单模拟一下: