Servlet详解
内容摘要:
l Servlet的概念
l Servlet应用
l Servlet的生命周期
l httpServlet使用
l tomcat启动时创建Servlet
l ServletConfig
l Servlet路径映射
l ServletContext
l Servlet的深入分析
1. Servlet概述
1 JavaWeb三大组件
Servlet是JavaWeb三大组件之一,它是我们学习JavaWeb最为基本的组件,也就是说你一定要100%的掌握它。
其它两种:Filter(拦截器)、Listener(观察者模式),后续讲解
2 Servlet的作用
Servlet,即Server Let的意思,用来处理用户请求。当客户端发出请求后,由Tomcat去找到可以处理这一请求的Servlet来处理。
也就是说,用户的请求是由Servlet来处理的!例如用户发出登录请求,那么就应该由处理登录的Servlet来处理;用户发出登录请求,那么就应该有登录Servlet来处理。
2.实现一个servlet
servlet 是运行在 Web 服务器中的小型 Java 程序。servlet 通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求。也就是说,Servlet是由我们自己来完成的!但Servlet一定要实现javax.servlet.Servlet接口,并且还要在web.xml文件中部署!不然Tomcat是找不到我们写的Servlet的。
Servlet接口
javax.servlet.Servlet接口中方法如下:
l void init(ServletConfig servletConfig):当Tomcat创建Servlet实例后,马上调用init()方法。这个方法只在创建后调用一次!用来做Servlet初始化工作!一个Servlet实例只被创建一次,所以init()方法也只被调用一次!(本方法编写对Servlet的初始化代码)
l void service(ServletRequest request, ServletResponse response):Servlet实例在每次处理请求时都调用service()方法。
l void destroy():当Tomcat要销毁Servlet实例时,会先调用destroy()方法,再销毁它。所谓销毁Servlet,其实就是在Servlet缓存池中把Servlet移除!一般只有Tomcat关闭时,才会销毁Servlet实例!
l ServletConfig getServletConfig():这个方法返回ServletConfig对象,但我们不能自己去创建ServletConfig对象,所以一般我们会在init()方法中把init()方法的参数保存起来,然后再在本方法中返回它。ServletConfig对象对应web.xml中当前Servlet实例的配置信息。
l String getServletInfo():这个方法只是返回一个字符串,用来说明当前Servlet。基本没用!
1. 第一步:常见HelloServlet实现Servlet的接口,实现接口中的方法
package com.rl.servlet;
import java.io.IOException;
import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse;
public class LoginServlet implements Servlet { /** * servlet的销毁方法 */ @Override public void destroy() {
}
/** * servlet的 */ @Override public ServletConfig getServletConfig() { return null; }
/** * 获得servlet的基本信息 */ @Override public String getServletInfo() { return null; }
/** * servlet的初始化方法 */ @Override public void init(ServletConfig arg0) throws ServletException {
}
@Override public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { response.getOutputStream().write("I am login...".getBytes()); }
} |
2. 第二步:配置servlet的访问路径
<servlet> <servlet-name>login</servlet-name> <servlet-class>com.rl.servlet.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>login</servlet-name> <url-pattern>/logon</url-pattern> </servlet-mapping> |
当我们写好了LoginServlet类后,还需要在web.xml文件中添加上面的内容。
JavaWeb请求响应原理如下:
当Tomcat接收到请求(http://localhost:8080/servlet_pro/logon)后,Tomcat会找到servlet_pro项目中的web.xml文件,然后通过logon这个请求路径,查找处理这个请求的Servlet类型。这刚好与<url-pattern>/logon</url-pattern>匹配,这说明存在一个可以通过这个请求的Servlet。然后再通过<url-pattern>/logon</url-pattern>查找到<servlet-name>login</servlet-name>,然后再通过<servlet-name>login </servle-name>查找到<servlet-class>com.rl.servlet.LoginServlet</servlet-class>。这时Tomcat已经得到了一个Servlet类名字(一个字符串而已)。
Tomcat通过Servlet类名字去查找内存中是否存在Servlet对象,如果存在,那么就不用再去创建,直接获取这个Servlet实例,调用它的service()方法完成请求!
如果这个Servlet不存在,那么Tomcat会通过反射来创建Servlet实例,并把Servlet实例存放到Servlet池中,再去调用Servlet的service方法处理请求。
3 Servlet生命周期
javax.servlet.Servlet接口中,有三个方法说明了Servlet的生命周期:
l void init(ServletConfig):创建后马上调用init()完成初始化;
l void service(ServletRequest,ServletResponse):每次处理请求时调用service()方法;
l void destroy():当Tomcat要销毁Servlet实例时,先调用destroy()方法。
Servlet对象的实例默认情况下是在浏览器第一次调用servlet时候被创建的(可以修改其创建时机后续讲解)
现在你应该已经清楚了,Servlet的实例不由我们创建,Servlet的方法不由我们来调用,这一切都是由Tomcat来完成!!!这就是说由Tomcat来管理Servlet,而我们只需要去编写Servlet实现类,并将其部署到web.xml文件中去!
再次提醒,只有这三个方法是生命周期中的方法。也就是说,生命周期方法会被Tomcat在不同的时间点来调用!而其它方法就不会被调用了!!!如果你在自己写的Servlet中添加了其他方法,那么Tomcat也是不会去调用它们的!但你可以让生命周期方法去调用你自己写的方法就OK了!
4专注HTTP请求的Servlet
1 写一个专门处理HTTP请求的Servlet
因为现在我们的请求都是基于HTTP协议的,所以我们应该专门为HTTP请求写一个Servlet做为通用父类。
对于专注于HTTP的Servlet,我们需要处理以下几个问题:
service()方法的参数ServletRequest和ServletResponse,但因为所有的请求都是HTTP请求,所以传递给service()就去的参数其实是HttpServletRequest和HttpServletResponse对象。如果子类希望使用的是HttpServletRequest,而不是ServletRequest,那么它需要自己去做强转。
Servlet:SUN公司 设计之初 以后不仅仅依赖HTTP协议
GenericServlet --- 通用Servlet
service(ServletRequestreq, ServletResponse res)
HttpServlet --- 与协议相关的Servlet
service(HttpServletRequestreq, HttpServletResponse resp)
以后再写Servlet 继承 HttpServlet
Servlet --- 一个标准
|
GenericServlet --- 是Servlet接口子类
|
HttpServlet --- 是GenericServlet子类,一个专门处理Http请求的Servlet
HttpServlet
两个Service方法
*父类service 调用子类service 使用子类service方法就可以
*子类中service 根据请求方式不同调用不同的方法
只需要重写doGet和doPost就行.
写一个Servlet 继承HttpServlet
重写doGet和doPost 方法.
没错,Java中已经存在了javax.servlet.http.HttpServlet类。打开源代码看看这个类!
2 HTTP请求方法
HTTP请求方法不只是GET和POST,还有其他的方法,但基本上用不上。这里只是简单介绍一下。你自己心里有个数,HTTP请求除了GET和POST之外还有别的就行了。
l GET通过请求URI得到资源
l POST用于添加新的内容
l PUT用于修改某个内容
l DELETE,删除某个内容
l CONNECT用于代理进行传输,如使用SSL
l OPTIONS询问可以执行哪些方法
l PATCH部分文档更改
l RACE用于远程诊断服务器
l HEAD类似于GET, 但是不返回body信息,用于检查对象是否存在,以及得到对象的元数据
l TRACE用于远程诊断服务器
5 Tomcat启动时创建Servlet
有些Servlet需要在Tomcat启动时就被创建,而不是第一次访问时被创建,那么可以在web.xml文件中配置<servlet>元素。
在<servlet>元素中添加子元素<load-on-startup>元素!
这个元素的值必须是一个大于等于0的整数!!!
<servlet> <servlet-name>One</servlet-name> <servlet-class>com.rl.servlet.OneServlet</servlet-class> <load-on-startup>0</load-on-startup> </servlet> <servlet> <servlet-name>Two</servlet-name> <servlet-class> com.rl.servlet.TwoServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> |
所有添加了<load-on-startup>子元素的Servle,都会在Tomcat启动时被创建!当然,只是被创建,但没有处理请求!但我们知道在Servlet生命周期中init()方法会在创建后被调用,所以你可以在init()方法中做一些输出,查看是否在Tomcat启动时调用了它。
<load-on-startup>元素的值是一个序号,Tomcat会使用这个序号给多个Servlet排序!然后在Tomcat启动时会按这个顺序来创建Servlet实例对象!
6 ServletConfig
ServletConfig对象对应web.xml文件中的<servlet>元素。例如你想获取当前Servlet在web.xml文件中的配置名,那么可以使用servletConfig.getServletName()方法获取!
你不能自己去创建ServletConfig对象,Servlet的init()方法的参数就是ServletConfig类型的。Tomcat在调用init()方法时,会传递ServletConfig对象。你可以在init()方法中使用它!
在<servlet>元素中还可以配置初始化参数:
<servlet> <servlet-name>One</servlet-name> <servlet-class> com.rl.servlet.OneServlet </servlet-class> <init-param> <param-name>paramName1</param-name> <param-value>paramValue1</param-value> </init-param> <init-param> <param-name>paramName2</param-name> <param-value>paramValue2</param-value> </init-param> </servlet> |
添加了两个初始化参数,第一个参数的名称为paramName1,第一个参数的值为paramValue1;第二个参数的名称为paramName2,第二个参数值为paramValue2。
在<servlet>元素中可以加载多个<init-param>,每个<init-param>表示一个参数。<init-param>下有两个子元素:<param-name>和<param-value>,其中<param-name>表示参数的名称,而<param-value>元素参数的值。
注意,<init-param>是添加到<servlet>元素中,而不是<servlet-mapping>中。
使用ServletConfig对象的getInitParameter(String paramName)方法可以获取指定参数名称的参数值。getInitParameterNames()方法返回所有参数的名字,返回值类型为Enumeration。
7.Servlet 路径映射
关于Url-Pattern的配置:
l 1.完全路径匹配 以/开头 例如 /aaa /aaa/bbb
l 2.目录匹配 以/开头 例如 /aaa/* /*
l 3.扩展名匹配 不能以/开头 例如 *.do *.action ....
优先级:完全路径匹配 > 目录匹配 > 扩展名匹配
经典错误: /*.do
举例:
对于如下的一些映射关系:
l Servlet1 映射到 /abc/*
l Servlet2 映射到 /*
l Servlet3 映射到 /abc
l Servlet4 映射到 *.do
问题:
l 当请求URL为“/abc/a.html”,“/abc/*”和“/*”都匹配,哪个servlet响应
Servlet引擎将调用Servlet1。同样是目录匹配所限定范围更精确的先匹配
l 当请求URL为“/abc”时,“/abc/*”和“/abc”都匹配,哪个servlet响应
Servlet引擎将调用Servlet3。
l 当请求URL为“/abc/a.do”时,“/abc/*”和“*.do”都匹配,哪个servlet响应
Servlet引擎将调用Servlet1。
l 当请求URL为“/a.do”时,“/*”和“*.do”都匹配,哪个servlet响应
Servlet引擎将调用Servlet2.
l 当请求URL为“/xxx/yyy/a.do”时,“/*”和“*.do”都匹配,哪个servlet响应
Servlet引擎将调用Servlet2。
*服务器端路径 /demo4 (转发、包含...)
8.ServletContext
l WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。
l 由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为context域对象。
l 查看ServletContext API文档,了解ServletContext对象的功能。
应用:
获取WEB应用的全局初始化参数
通过ServletContext对象实现数据共享
• 案例--- 统计站点访问次数
利用ServletContext对象读取资源文件
| |
| |
| |
| |
|
|
|