一 概述
1 介绍
Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。
狭义的 Servlet 是指Java语言实现的一个接口,广义的 Servlet 是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
Servlet 本质为运行在 Web服务器(如Tomcat服务器)的,使用 Java编写的小应用程序。
2 作用
接收浏览器请求并响应数据给浏览器。开发动态资源:Servlet 也是服务器的一种资源,可以供外界(浏览器)去访问。
3 开发步骤
java
1. 创建一个类实现 javax.servlet.Servlet 接口
2. 实现接口中的所有方法
3. 在 service 方法处理请求和响应数据
4. 配置 Servlet 的访问地址(供外界:浏览器访问)
可以通过 web.xml 文件配置,也可以通过注解配置
4 若找不到Servlet
① 打开project Structure,找到Modules
② 选择模块
③ 点击Dependencies
④ 点加号,选择Libraries,选择tomcat,添加即可找到Servlet接口
5 web.xml 开发 Servlet
① 实现步骤
创建一个 HelloServlet 实现 Servlet 接口
重写接口中的所有方法,在 service 方法中输出内容到控制台
配置 web/WEB-INF/web.xml 文件
② 创建 HelloServlet 实现 Servlet 接口
java
// 重写所有方法,在 service 方法中往控制台输出:Hi~
public class PlayServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("Hi~");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
③ web配置
java
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 真实路径与映射路径通过name连接-->
<!-- servlet 信息配置 真实路径-->
<servlet>
<!--servlet 名字-->
<servlet-name>HelloServlet</servlet-name>
<!-- servlet类全限定名-->
<servlet-class>com.tj.PlayServlet</servlet-class>
</servlet>
<!--servlet 访问地址配置(映射路径) -->
<servlet-mapping>
<!--servlet 名字:与上面的名字相同 -->
<servlet-name>HelloServlet</servlet-name>
<!-- 浏览器访问地址,必须以/开头 -->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
④ 部署项目后通过浏览器访问 Servlet(本地地址+项目虚拟访问路径+Servlet访问路径)
6 注解开发 Servlet
① @WebServlet 注解 -- 简化 javaweb 代码,省略 web.xml配置文件
@WebServlet注解属性 | 说明 |
---|---|
name = "PlayServlet" | Servlet名字,等价 < servlet-name >PlayServlet</ servlet-name> |
urlPatterns = "/hello" | 访问地址,等价 < url-pattern>/hello</ url-pattern> |
value="/hello" | 如果其它属性都不写,可以省略 value,只写访问地址即可。不能与urlPatterns同时指定 |
② 开发步骤
使用注解,必须是 JavaEE 6.0 版本以上,Servlet3.0 之后才可以,Tomcat8 已经实现了3.0规范
创建类实现 Servlet 接口,在类上使用 @WebServlet 注解中添加 urlPatterns="/hello"或value="/hello",作为请求路径
③ 创建 PlayServlet,实现接口所有方法,使用注解 @WebServlet 配置访问地址
java
// 使用注解 @WebServlet 配置访问地址
@WebServlet(name = "PlayServlet",urlPatterns = "/hello")
public class PlayServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {}
@Override
public ServletConfig getServletConfig() {return null;}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("Hi~");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {}
}
④ 登录 http://localhost:8080/hello 控制台会输出Hi~
二 Servlet 的生命周期
1 名词解释
类的生命周期:创建对象--> 运行操作-->销毁操作
Servlet 对象的生命周期:Servlet 创建对象-->初始化操作--> 运行操作-->销毁操作
Web 服务器管理了 Servlet 的生命周期,Servlet 对象整个过程都是 Web 服务器来管理的。
生命周期 | 操作 |
---|---|
实例化 | Servlet容器Tomcat创建Servlet的实例 |
初始化 | 该容器调用init()方法,调用一次 |
请求处理 | 若请求Servlet,则容器调用service()方法,调用多次 |
服务终止 | 销毁实例之前调用destroy()方法 |
2 Servlet 接口中生命周期方法
生命周期方法 | 作用 | 运行次数 |
---|---|---|
构造方法 | 在对象实例化的时候执行必须有公共的无参数构造方法 | 一次 |
void init(ServletConfig config) | 初始化时执行 | 一次 |
void service(ServletRequest req, ServletResponse res) | 每次请求都会执行 | N次 |
void destroy() | 在服务器正常关闭的时候 | 一次 |
3 Servlet 的请求流程
java
localhost:8080/play/hello
1. 浏览器发送请求,Tomcat接收到请求并通过解析请求地址获取到要访问的项目和资源路径
项目访问路径:/play
资源路径: /hello
2. Tomcat服务器内部会扫描play项目下的所有Servlet:获得每一个Servlet的访问地址并存储到集合
中:
Map<String,String> map1 = new HashMap<>();
map1.put("/hello","cn.tj.servlet.PlayServlet");
3. 将资源路径 /hello 作为键从 map1 集合中获得值:得到类全限定名
4. 需要判断是否是第一次访问:
Servlet实例缓存池: Map<String, Servlet> map2 = new HashMap<>();
if(map2.get("全限定名") == null){
// 第一次访问,执行第5步
} else{
// 第N次,直接执行第7步
}
5. 通过反射实例化这个 Servlet 对象,存入实例缓存池中.
6. Tomcat 创建 ServletConfig 对象然后调用 init 方法
7. 创建 request 和 response 对象
8. 调用 service 方法,将 request和 response 对象传递进来,在 service 方法中通过
response对象返回输出到浏览器,在浏览器上显示出来。
9. 等待下一次的访问
三 Servlet 继承体系
1 继承结构
2 GenericServlet类
默认实现了 Servlet 和 ServletConfig 这两个接口,将Servlet接口中其他的方法做了默认空实现,只将service()方法作为抽象。定义Servlet类继承GenericServlet时,只需实现service()方法即可。它的子类是 HttpServlet。
java
@WebServlet(name = "Play",urlPatterns = "/play")
public class Play extends GenericServlet {
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.err.println("OK");
}
}
3 HttpServlet类
本类是对http协议的一种封装,可提前判断请求方式,针对view层传递的get,post请求复写doGet/dopost方法,简化操作。
java
@WebServlet(name = "Play",urlPatterns = "/play")
public class Play extends HttpServlet {
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.err.println("OK");
}
}
四 ServletConfig 对象
1 作用
用来封装 Servlet 初始化的时候的一些配置信息,与Servlet有关的配置信息,写在web.xml中,便于修改和维护。
java
// ServletConfig接口常用方法
String getInitParameter("参数名") // 通过指定的参数名得到参数
2 使用
① 于 web.xml 中通过 init 设置属性
java
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- servlet 信息配置 -->
<servlet>
<!--servlet 名字-->
<servlet-name>PlayServlet</servlet-name>
<!-- servlet类全限定名-->
<servlet-class>com.tj.PlayServlet</servlet-class>
<!--配置初始化参数init-->
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</servlet>
<!--servlet 访问地址配置 -->
<servlet-mapping>
<!--servlet 名字:与上面的名字相同 -->
<servlet-name>PlayServlet</servlet-name>
<!-- 浏览器访问地址,必须以/开头 -->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
② 通过 getInitParameter 获取属性
java
public class PlayServlet extends HttpServlet {
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
// 父类中的方法
ServletConfig servletConfig = this.getServletConfig();
// 获取web.xml文件的配置信息
String code=servletConfig.getInitParameter("encoding");
servletRequest.setCharacterEncoding(code);
System.out.println(code);
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {}
}
3 配置多个路径
① 一个 < servlet-mapping> 中写多个 < url-pattern>
java
< servlet-mapping>
< servlet-name>PlayServlet< /servlet-name>
// 使用两个路径都能访问 PlayServlet
< url-pattern>/hello.html< /url-pattern>
< url-pattern>/hello1.html< /url-pattern>
< /servlet-mapping>
② 一个 < servlet> 对应多个 < servlet-mapping>
java
// <url-pattern> 中的内容必须唯一,必须以 / 开头。
<servlet-mapping>
<servlet-name>PlayServlet</servlet-name>
<url-pattern>/hello.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>PlayServlet</servlet-name>
<url-pattern>/hello1.html</url-pattern>
</servlet-mapping>
③ 注解形式
java
@WebServlet(name = "Play",urlPatterns = {"/play","/play1"})
public class Play extends HttpServlet {
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.err.println("OK");
}
}
4 loadOnStartup 属性
servlet在创建对象或者是初始化的时候需要执行耗时操作,导致相第一个访问的用户要等待比较长的时间。让 web 容器启动的时候创建并初始化 Servlet,这样用户体验度就会增加
① web
java
<servlet>
<!--servlet 名字-->
<servlet-name>PlayServlet</servlet-name>
<!-- servlet类全限定名-->
<servlet-class>com.tj.PlayServlet</servlet-class>
<!--取值范围1到10,值越小越先加载。默认值是-1:代表第1次访问时创建和初始化-->
<load-on-startup>1</load-on-startup>
<!--配置初始化参数init-->
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</servlet>
② 注解
java
@WebServlet(name = "Play",urlPatterns = {"/play","/play1"},loadOnStartup = 1)
public class Play extends HttpServlet {
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.err.println("OK");
}
}
5 通配符映射 *
通配符格式 | 说明 |
---|---|
/* /目录名/* | /* :匹配所有的访问地址,必须以 / 开头/admin/*:匹配 admin 目录下的所有地址 |
*.扩展名 | 匹配某个扩展名结尾的访问地址。如:*.action *.do |
映射路径必须保证唯一性,除通配符结合扩展名使用,否则必须以 / 开头