一. 什么是servlet
servlet是服务器端(tomcat)运行的一段java程序(java接口),通过http协议,负责接收和响应web客户端(浏览器)的请求。
先附上servlet家族图谱。
以一个简单servlet小程序,讲述servlet的实现方式:
- 1 编写java类,实现servlet接口,主要实现service方法。
- 2 配置web.xml文件,给servlet一个可访问的统一资源标识符URI(servlet-mapping)。
类HelloServlet 实现了servlet接口
配置web.xml文件
<servlet>
<servlet-name>wahaha</servlet-name>
<servlet-class>cn.ishuai.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>wahaha</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-name>
名字随便取,只是个标识符而已,只要<servlet-mapping>
和<servlet>
的<servlet-name>
子元素相同就行。
二 执行过程
2 tomcat收到请求后,查询web.xml配置文件。先查
<servlet-mapping>
,因为该配置属性向浏览器刻意暴露了访问地址hello。然后读取mapping的子元素<servlet-name>
,确定servlet名字为wahaha。然后去查询<servlet-name>
为wahaha的<servlet>
元素,读取<servlet>
子元素<servlet-class>
的值,确定要访问的类名及路径为cn.ishuai.HelloServlet。- 3 到tomcat安装目录/webapps/day01/WEB-INF/classes/cn/ishuai目录下查找到HelloServlet.class文件,执行。
注:看一下web项目目录:
WebRoot web应用所在目录
|-html css js jsp文件 这些文件存在根目录下,可被外界直接访问
|-WEB-INF目录 该目录下文件不能被外界访问,由web服务器负责调用
|-class目录 (java 类)
|-lib (jar包)
|-web.xml (配置文件)
浏览器想要执行的就是服务器中的HelloServlet这个类,可是它如何才能访问到这个类呢?答案就是通过配置文件web.xml,通过<servlet-mapping>
这个元素,向外暴露可访问的URL,浏览器输入URL来访问服务器,服务器通过URL找到对应的servlet名字及地址,向浏览器返回结果。<url-pattern>
向外暴露的名称需加反斜线,其相当于http://localhost:8080/projectName/Hello中项目名projectName后的hello类,day01就是项目名。如果不加反斜线,表示在8080后找,认为projectName是类,这样就不能执行了。
详细执行过程:
Servlet程序是由WEB服务器调用,web服务器收到客户端的Servlet访问请求后:
1> Web服务器首先检查是否已经装载(装进内存,包括web配置文件)并创建了该Servlet的实例对象。如果是,则直接执行第4步,否则,执行第2步。
2> 装载并创建该Servlet的一个实例对象 (调用初始化方法)。
3> 调用Servlet实例对象的init()方法。
4> 创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用Servlet的service()方法并将请求和响应对象作为参数传递进去。service方法读取请求信息,写入相应信息,然后web容器读取相应信息,通过http协议返回给浏览器。
5> WEB应用程序被停止或重新启动之前,Servlet引擎将卸载Servlet(删除掉项目文件),并在卸载之前调用Servlet的destroy()方法。
三 servlet的生命周期
分为四个阶段,实例化(构造函数)–>初始化(init)–>服务(service)->销毁(destroy)
出生:(实例化–>初始化)浏览器第一次访问Servlet就出生(默认情况下,如果想在web容器启动时就出生,需要在
<servlet>
元素中添加<load-on-startup>2</load-on-startup>
这个子元素,其值为正整数,越小,优先级越高,表示在多个servlet下会优先被启动)。活着:(服务)应用活着,servlet就活着。
死亡:(销毁)应用卸载了servlet就销毁。(卸载是指通过浏览器的tomcat界面—manage
app—undeploy,点击undeploy表示卸载应用,即在tomcat的webapps目录下,会把day01这个应用(项目)删掉)
针对客户端的多次Servlet请求,通常情况下,服务器只会创建一个Servlet实例对象,也就是说Servlet实例对象一旦创建,它就会驻留在内存中,为后续的其它请求服务,直至web容器退出,servlet实例对象才会销毁。
在Servlet的整个生命周期内,Servlet的init方法只被调用一次。而对一个Servlet的每次访问请求都导致Servlet引擎调用一次servlet的service方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doXXX方法。
四 servlet的三种创建方式
- 1 实现javax.servlet.Servlet接口.(需要重写servlet里的5个抽象方法)
- 2 继承javax.servlet.GenericServlet(由于GenericServlet简单实现了Servlet接口,只需你重写service方法即可—适配器模式)
- 3 继承javax.servlet.http.HttpServlet(HttpServlet继承了GenericServlet类,不再需要重写service方法。原因是HttpServlet重写了service方法,里面调用了自己重载的service方法,而重载的service方法里又调用了doGet和doPost方法,故在使用HttpServlet时,需要重写doGet和doPost方法,以便让web容器调用我们自己的程序–模板方法设计模式)
servlet映射(<servlet-mapping>
)细节:
1 同一个servlet可以有多个servlet-mapping(同一个servlet可以被映射到多个URL上),maping的子元素servlet-name必须是相同的,向外暴露的url-pattern不同。
2 URL(url-pattern)中可以使用通配符。 /**: 浏览器输入/day01/haha 、day01/ha 、
day01/haha/aha/hahd都符合要求3 *.xx 注:不加斜线,表示任意扩展名,如day01/ha.do 、day01/haha/ha.dododo符合要求 /xx/ * 以任意字符开头,如day01/action/haha、day01/wahaha/ha都是符合要求的
通配符匹配优先级:绝对匹配–> /开头 匹配 –> 扩展名方式匹配。/是可以匹配任何输入的。除了绝对匹配,/* 优先级始终大于*.do
五 servlet获取配置信息
主要通过ServletConfig对象获取配置信息,该对象有四种方法:
通过三种方式获得ServletConfig对象,可调用下面这四种方法获取对象信息。
- 1> 通过(父)接口servlet的init(ServletConfig)方法,得到该对象。
public class ServletGetInfo extends HttpServlet {
private ServletConfig config;
@Override
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
this.config=config;
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.print(config.getInitParameter("encoding"));
}
}
- 2>通过使用父类(GenericServlet)的getServletConfig方法,获取ServletConfig对象,然后调用getInitParameter获取配置信息。(不要重写init方法)
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String ec=this.getServletConfig().getInitParameter("encoding");
System.out.println(ec);
}
- 3>使用父类(GenericServlet)的getInitParameter方法.(GenericServlet继承了ServletConfig)。(不要重写init方法,否则Tomcat不会自己创建ServletConfig对象)
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String ec=this.getInitParameter("encoding");
System.out.println(ec);
}
六 servletContext
通过ServletConfig可获得ServletContext。
有4个作用:
- 作为域对象(map集合),在当前应用中使多个servlet共享数据
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletContext sc=this.getServletContext();
sc.setAttribute("name", "xiaoqiang");
//String str=(String)sc.getAttribute("name");
//System.out.print(str);
}
- 获取全局配置信息
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String str=this.getServletContext().getInitParameter("encoding");
//String str=this.getInitParameter("encoding");
System.out.println(str);
String s=(String)this.getServletContext().getAttribute("name");
System.out.println(s);
}
- 获取资源路径
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletContext sc=this.getServletContext();
String path=sc.getRealPath("/WEB-INF/a.properties");
Properties prop=new Properties();
prop.load(new FileInputStream(path)); //IO操作
System.out.println(prop.getProperty("key"));
}