简介
Servlet 是 Java 提供的一门动态 web 资源开发技术。动态资源是指不同的用户或者不同的参数在访问时返回不同的结果。Servlet 是 JavaEE 的规范之一,其实就是一个接口,将来我们需要定义 Servlet 类来实现 Servlet 接口,并由 web 服务器创建并调用 Servlet 对象中的方法。
快速入门
可以先简单看一下这段示例代码,里边的一些用法会在后文提到。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package org.example;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
// 设置 URL 映射路径和loadOnStartup的值
@WebServlet(urlPatterns = "/Servlet", loadOnStartup = 1)
public class ServletLearn implements Servlet {
private ServletConfig config;
// 提供服务,每次 Servlet 被访问都会调用该方法
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("servlet service~");
}
// 初始化,在 Servlet 被创建时执行,只执行一次
@Override
public void init(ServletConfig servletConfig) throws ServletException {
this.config = servletConfig;
System.out.println("servlet init~");
}
// 获取 ServletConfig 对象
@Override
public ServletConfig getServletConfig() {
return config;
}
// 获取 Servlet 信息
@Override
public String getServletInfo() {
return "";
}
// 销毁方法,当内存释放或者服务器关闭时销毁 Servlet
@Override
public void destroy() {
System.out.println("servlet destroy~");
}
}
生命周期
Servlet 运行在 Servlet 容器(web服务器)中,其生命周期由容器来管理,分为四个阶段:
1、加载和实例化:默认情况下,当 Servlet 第一次被访问时,由容器创建 Servlet 对象
2、初始化:在 Servlet 实例化之后,容器会调用 Servlet 对象的 init() 方法初始化这个对象,完成一些加载配置文件、创建连接等初始化的工作。该方法只被调用一次。
3、请求处理:每次请求 Servlet 时,Servlet 容器都会调用 Servlet 的 service() 方法对请求进行处理。
4、服务终止:当需要释放内存或者容器关闭时,容器就会调用 Servlet 实例的 destroy() 方法完成资源的释放。当 destory() 方法被调用之后,容器就会释放这个 Servlet 实例,该实例随后会被 Java 的垃圾收集器回收。
上面提到在加载和实例化时默认情况下是当 Servlet 第一次被访问时创建 Servlet 对象,除此之后用户也可以设置实例化的时期。修改注解如下
1
@WebServlet(urlPatterns = "/Servlet", loadOnStartup = 1)
设置 loadOnStartUp 可以修改实例化的时期:
1、负整数:第一次被访问时创建 Servlet 对象
2、0或正整数:服务器启动时创建 Servlet 对象,数字越小优先级越高
HttpServlet
HttpServlet 是 Servlet 的一个对 HTTP 协议封装的 Servlet 实现类,关系如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package org.example;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/HttpServlet")
public class HttpServletLearn extends HttpServlet {
// 当使用 get 请求访问时调用此方法
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("get...");
}
// 当使用 post 请求访问时调用此方法
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("post...");
}
}
配置
urlPattern 配置
一个 Servlet 可以配置多个 urlPattern
1
@WebServlet(urlPatterns = {"/Servlet1", "/Servlet2"})
urlPattern 有四种配置规则如下:
1
2
3
4
5
6
7
8
9
10
11
12
// 1、精准匹配:只能通过 /user/Servlet 访问
@WebServlet(urlPatterns = "/user/Servlet")
// 2、目录匹配:可以通过 /user/ 或者 /user/ 后面加任意字符访问
@WebServlet(urlPatterns = "/user/*")
// 3、任意匹配:可以通过 / 或者 / 后面加任意字符访问,支持多级目录如 /dir1/dir2/ 访问
@WebServlet(urlPatterns = "/*")
@WebServlet(urlPatterns = "/")
// 4、扩展名匹配:任意字符加 '.do' 访问,甚至 /dir1/dir2/.do 也可以访问
@WebServlet(urlPatterns = "*.do")
注意:任意匹配中 / 和 /* 是有区别的,而且区别比较复杂,请自行搜索。
优先级:精确路径 > 目录路径 > 扩展名路径 > /* > /
XML 配置
Servlet 从 3.0 版本之后开始支持使用注解配置,而 3.0版本之前只支持 XML 配置文件的配置方式。
首先在 we.xml 文件中配置如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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"
metadata-complete="false">
<servlet>
<servlet-name>HttpServlet</servlet-name>
<servlet-class>org.example.HttpServletLearn</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HttpServlet</servlet-name>
<url-pattern>/httpServlet</url-pattern>
</servlet-mapping>
</web-app>
HttpServletLearn 代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package org.example;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HttpServletLearn extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("get...");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("post...");
}
}
然后可以通过 /httpServlet 路径访问。
其他
在运行 Tomcat 的时候遇到了一些问题如下:
1、web.xml 没有 metadata-complete="false" 配置导致无法解析注解。
1
2
3
4
5
6
7
<?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"
metadata-complete="false">
</web-app>