Servlet 简明笔记

Servlet 简介

Servlet 是 Java 提供的一门动态 web 资源开发技术
01-Servelet功能示意图.png

Servlet 是 JavaEE 规范之一,其实就是一个 接口,将来我们需要定义 Servlet 类实现 Servlet 接口,并在 web 服务器运行 Servlet。Servlet 接口 API 文档中的五个方法,实现这个接口的话需要实现这五个方法

02-Servlet需要重写的5个方法.png

Servlet 入门案例

  1. 创建 Web 项目,导入 Servlet 依赖坐标

pom.xml 文件中,插入如下代码

1
2
3
4
5
6
<dependency>  
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>

注意:需要加上 scope,设置为 provided

  1. 创建:定义一个类,实现 Servlet 接口,并重写接口中的所有方法,并在 service 方法中输入一句话

根据提示(Alt+Enter),重写类中的五个方法,这里我们重点关注 service 方法;因为 serlvet 在被访问的时候,service 方法被自动执行。

1
2
3
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {  
System.out.println("servlet hello world");
}
  1. 配置:在类上使用 @WebServlet 注解,配置该 Servlet 的访问路径
1
2
3
@WebServlet("/demo1")  
public class ServletDemo1 implements Servlet {
}
  1. 访问:启动 Tomcat,浏览器输入 URL 访问该 Servlet

Servlet 的执行流程

我们并没有创建 Servlet 对象,也没有调用 service 方法,那么程序是如何执行的呢?
Servlet 对象是由服务器 Tomcat 创建的,并且 service 方法也是 Tomcat 调用的

03-Servlet的执行流程.png

服务器怎么知道 Servlet 中一定有 service 方法呢?
因为实现 Sevlet 接口必须复写其方法,而 Servlet 接口中有 service 方法

Sevlet 生命周期

那 Tomcat 什么时候给我们创建的 servlet 对象呢?

Servlet 运行在 Servlet 容器(Web 服务器)中,其生命周期由容器来管理,分为四个阶段

  1. 加载和实例化:默认情况下,当 Servlet 第一次被访问时,由容器创建 Servlet 对象
  2. 初始化:在 Servlet 实例化之后,容器将调用 Servlet 的 init () 方法初始化这个对象,完成一些如加载配置文件、创建连接等初始化的工作。该方法只调用一次
  3. 请求处理:每次请求 Servlet 时,Servlet 容器都会调用 Servlet 的 service () 方法对请求进行处理
  4. 服务终止:当需要释放内存或者容器关闭时,容器就会调用 Servlet 实例的 destroy () 方法完成资源的释放。在 destroy () 方法调用之后,容器会释放这个 Servlet 实例,该实例随后会被 Java 的垃圾收集器所回收

初始化方法

1
2
3
4
5
6
//初始化方法  
//1.调用时机:默认情况下,servlet被第一次访问时调用
//2.调用次数:1次
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("服务器正在初始化");
}

注:也可以通过配置手动改变 Servlet 的创建时机

  • 负整数:第一次被访问时创建 Servlet 对象;默认值是 -1
  • 0 或正整数:服务器启动时创建 Servlet 对象,数字越小优先级越高;创建的时机提前了
1
@WebServlet(urlPatterns = "/demo",loadOnStartup = 1)

服务方法

1
2
3
4
5
//1.调用时机:每一次servlet被访问时调用  
//2.调用次数:每一次
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("服务器正在服务中");
}

销毁方法

1
2
3
4
5
//1.调用时机:内存释放或服务器关闭,servlet对象被销毁  
//2.调用次数:1次
public void destroy() {
System.out.println("服务器已被关闭");
}

Servlet 体系结构

我们常用的就是 service 方法,其他四个方法都用的少,但是每次都还是得去实现它们,如何才能更简化一些呢?

04-HttpServlet.png

我们将来开发 B/S 架构的 Web 项目,都是针对 HTTP 协议,所以我们自定义 Servlet,直接继承 HttpServlet 即可(用于简化开发)⇒ 复写 HttpServlet 中的方法即可(doPost 方法和 doGet 方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
@WebServlet("/demo4")  
public class ServletDemo4 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...");
}
}

在项目的 webapp 文件夹下新建一个 html 页面,用表单来模拟 post 请求

1
2
3
<form action="/web-demo/demo4" method="post">  
<input type="text" name="username"><input type="submit">
</form>

注意:form 标签中,action 属性值为虚拟目录的路径

HttpServlet 中为什么要根据请求方式的不同,调用不同的方法呢?

实现 Servlet 接口,重写那五个方法,并且在 service 方法中用来处理逻辑(获取请求参数信息),但是不同的请求方式,请求参数所在的位置不同,post 请求请求参数在请求体中,而 get 请求请求方式在请求行中。因此,应该写不同的处理逻辑代码,根据请求方式的不同进行分别的处理 ⇒ 因此,出现了 HttpServlet