Servlet 是 Server Applet 的简称,译为“服务器端小程序”。
文章目录
Servlet的定义:
- Servlet 运行在
服务端
的Java小程序; - 是
sun公司提供一套规范
(接口),用来处理客户端请求、响应给浏览器的动态资源; - servlet的
实质就是java代码
,通过java的API动态的向客户端输出内容;
Servlet的开发步骤
实现步骤:
- 创建类继承HttpServlet类;
- 重写doGet和doPost方法;
- 在web.xml中进行servlet的配置;
- 部署到Tomcat服务器;
- 在浏览器中输入URL,进行访问;
第一个Servlet程序实现,参照前一篇文章:Hello,Servlet
**Servlet运行的过程解析: **
tomcat服务器启动时,首先加载webapps中的每个Web项目的web.xml配置文件。
webapps文件夹里就是一个对外开放的资源库。
用户在浏览器输入:http://localhost:8080/KrojectDynamicWeb/HelloServlet后,
http://
:表明http协议localhost
:到本地的hosts文件中查找是否存在该域名对应的IP地址,查找到是127.0.0.18080
:根据端口找到运行中的Tomcat服务器KrojectDynamicWeb
:在tomcat的webapps目录下找到KrojectDynamicWeb文件夹HelloServlet
:资源名称,在KrojectDynamicWeb中的web.xml中查找,是否有匹配url-pattern的内容如果找到匹配的url-pattern
,则使用当前的servlet-name的名称到web.xml文件中查询是否有相同名称的servlet配置如果找到,则取出
对象的servlet配置信息中的servlet-class内容
:net.hackyle.HelloServlet,即一个Java类- 通过
反射,构造HelloServlet对象
,调用该对象里面的方法 - 执行方法
,Tomcat服务器给浏览器做出响应
,显示在浏览器的页面上
就是这样,你就看到了页面上你编写的内容。
Servlet接口
Servlet接口是已经过时了的开发接口,它的开发步骤是:
- 创建类实现Servlet接口
- 覆盖尚未实现的方法,如service方法
- 在web.xml进行servlet的配置
在实际开发中,我们不会直接去实现Servlet接口,因为那样需要覆盖的方法太多,我们一般创建类继承HttpServlet
。但是它以及其里面的方法任然有学习的价值,因为HttpServlet是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)init(ServletConfig config)
- 何时执行:servlet对象创建的时候执行,由服务器创建对象并调用init方法。
ServletConfig :代表的是该servlet对象的配置信息
2)service(ServletRequest request,ServletResponse response)
- 何时执行:每次请求都会执行
ServletRequest :代表请求,认为ServletRequest 内部封装的是http请求的信息
ServletResponse :代表响应 认为要封装的是响应的信息
3)destroy()
- 何时执行:servlet销毁的时候执行
Servlet的生命周期
Servlet程序的生命周期由tomcat服务器控制。
1)Servlet何时创建:默认第一次访问servlet时创建该对象
2)Servlet何时销毁:服务器关闭servlet就销毁了
3)每次访问必然执行的方法:service(ServletRequest req, ServletResponse res)方法
Servlet四个生命周期方法
- 构造方法:创建servlet对象的时候调用。默认情况下,
第一次
访问servlet的时候创建servlet对象只调用1次
。证明servlet对象在tomcat是单实例的。 - init方法:
创建完servlet对象
的时候调用。只调用1次。 - service方法: 每次
发出请求
时调用。调用n次
。 - destroy方法:
销毁servlet对象
的时候调用。停止服务器或者重新部署web应用时销毁servlet对象。只调用1次。
证明Servlet生命周期方法调用次数
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
public class HelloServlet extends HttpServlet {
// 1.构造方法
public HelloServlet(){
System.out.println("1.servlet对象被创建了。");
}
// 2.init方法
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("2.init方法被调用");
}
// 3.service方法
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
System.out.println("3.service方法被调用");
}
// 4.destroy方法
@Override
public void destroy() {
System.out.println("4.servlet对象销毁了");
}
}
web.xml
功能:
- Web项目一启动,服务器就读取web.xml这个文件;
- 因为这个文件告诉了Tomcat该从那个类开始执行,如何去执行;
HelloServlet的web.xml配置详情:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>KrojectDynamicWeb</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<description></description>
<display-name>HelloServlet</display-name>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>hello.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/HelloServlet</url-pattern>
</servlet-mapping>
</web-app>
servlet标签
<servlet>
元素用于注册Servlet,它包含有两个主要的子元素:<servlet-name>
和<servlet-class>
,分别用于设置Servlet的注册名称和Servlet的完整类名。
一个<servlet-mapping>
元素用于映射一个已注册的Servlet的一个对外访问路径,它包含有两个子元素:<servlet-name>
和<url-pattern>
,分别用于指定Servlet 的注册名称和Servlet的对外访问路径。
url-pattern的映射
访问Web项目的URL中,最后一个组成成分(“http://localhost:8080/KrojectDynamicWeb/HelloServlet”),将会在项目工程中的web.xml中查找是否有匹配的url-pattern的内容,匹配成功才能正常运行URL;
例如URL: http://localhost:8080/Kroject/first;映射路径是指把”/first”在web.xml中的url-pattern中寻找是否有一样的;
在执行URL最后部分与url-pattern的匹配过程中,有两种匹配类型:
A. 精确匹配
浏览器输入:url-pattern
http://localhost:8080/day10/first: /first
http://localhost:8080/day10/itcast/demo1: /itcast/demo1
B. 模糊匹配
浏览器输入 ===> url-pattern
http://localhost:8080/day10/任意路径 ===> /*
http://localhost:8080/day10/itcast/任意路径 ===> /itcast/*
http://localhost:8080/day10/任意路径.后缀名 ===> *.后缀名
http://localhost:8080/day10/任意路径.do ===> *.do
http://localhost:8080/day10/任意路径.action ===> *.action
注意事项:
- 在url-pattern中有两种固定的格式:一种格式是“*.扩展名”;另一种格式是以正斜杠(/)开头并以*结尾。
- url-pattern要么以 / 开头,要么以*开头。
- 不能同时使用两种模糊匹配,例如 /itcast/*.do是非法路径
- 当有输入的URL有多个servlet同时被匹配的情况下:
a) 精确匹配优先。(长的最像优先被匹配)
b) 以后缀名结尾。(*.后缀名)的模糊url-pattern优先级最低!!!
缺省路径
Tomcat的安装“config”目录下的web.xml文件指定了缺省路径(即当我们输入的一个URL,在webapps目录下并没有找到,于是就把缺省路径下的一个HTML资源返回。)
servlet的缺省路径(/)是在tomcat服务器内置的一个路径。该路径对应的是一个DefaultServlet(缺省Servlet)。这个缺省的Servlet的作用是用于解析web应用的静态资源文件。
匹配问题例题
问题: URL输入http://localhost:8080/day10/index.html 如何读取文件????
解答:
1)到当前day10应用下的web.xml文件查找是否有匹配的url-pattern。
2)如果没有匹配的url-pattern,则交给tomcat的内置的DefaultServlet处理
3)DefaultServlet程序到day10应用的根目录下查找是存在一个名称为index.html的静态文件。
4)如果找到该文件,则读取该文件内容,返回给浏览器。
5)如果找不到该文件,则返回404错误页面。
结论:先找动态资源,再找静态资源。尽量不要在web.xml文件下配置伪静态文件。
Tomcat服务器运行Servlet的过程
-
当服务器接收到URL后;
-
经过URL与web.xml中的
url-pattern
进行映射匹配后; -
找到了
servlet-class
的内容,得到了本次URL需要调用的类的全名:net.hackyle.HelloServlet; -
通过
反射
构造该类对象,即构造HelloServlet类的对象;
- 得到字节码对象:Class class = class.forName("net.hackyle.HelloServlet ");
- 调用无参数的构造方法来构造对象:Object obj = class.newInstance(); (注意:此时servlet的构造方法被调用)
创建ServletConfig对象
,通过反射调用init方法
- 得到方法对象:Method m = class.getDeclareMethod(“init”,ServletConfig.class);
- 调用方法:m.inmoke(obj,config); (注意:此时servlet的init方法被调用)
创建request,response对象
,通过反射调用service方法
- 得到方法对象:Methodm m=class.getDeclareMethod(“service”,HttpServletRequest.class,HttpServletResponse.class);
- 调用方法:m.invoke(obj,request,response); (注意:servlet的service方法被调用)
- 当tomcat服务器停止或web应用重新部署,通过
反射调用destroy方法
- 得到方法对象:Method m = clazz.getDeclareMethod(“destroy”,null);
- 调用方法:m.invoke(obj,null); (注意:servlet的destroy方法被调用)
再次请求相同URL
① Web服务器首先检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第④步,否则,执行第②步。
② 装载并创建该Servlet的一个实例对象。
③ 调用Servlet实例对象的init()方法。
④ 创建一个用于封装HTTP请求消息的HttpServletRequest对象和 一个代表HTTP响应消息的HttpServletResponse对象,然后调用 Servlet的service()方法并将请求和响应对象作为参数传递进去。
⑤ WEB应用程序被停止或重新启动之前,Servlet引擎将卸载 Servlet,并在卸载之前调用Servlet的destroy()方法。
自动加载机制
出现背景:
- 默认情况下,第一次访问servlet的时候创建servlet对象。
- 如果servlet的构造方法或init方法中执行了比较多的逻辑代码,那么导致用户第一次访问sevrlet的时候比较慢。
解决方案:
- 改变servlet创建对象的时机;
- 提前到加载web应用的时候!!! 即在servlet的web.xml配置信息中,加上一个即可!!
- 在中的整数值越大,创建优先级越低!!
- 可以为多个类创建快速启动;