一、体系结构

我们通过一张图来了解一下 Servlet 的体系结构:

1614151794621.png

可以看到,抽象类GenericServlet实现了 Servlet 接口,而抽象类HttpServlet则继承了抽象类GenericServlet,下面我们将对这两个类进行详细介绍。

1、GenericServlet

GenericServlet类将 Servlet 接口中的其他方法做了默认空实现,只将 service 方法作为抽象方法。我们在自定义 Servlet 类时,可以继承GenericServlet类,实现其中的 service 方法即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package cn.frankfang.servlet;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;

public class ServletDemo extends GenericServlet {
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
// 处理请求方法
}
}

不过一般在实际应用中并不是继承GenericServlet类,而是继承它的子类HttpServlet,下面我们将对HttpServlet类进行详细介绍。

2、HttpServlet

抽象类HttpServlet继承了抽象类GenericServlet,复写了 service 方法且根据请求方式添加了doGetdoPost等方法并进行了默认实现。因此当自定义的 Servlet 继承HttpServlet之后,只需根据需求来复习doGetdoPost方法即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package cn.frankfang.servlet;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
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 ServletDemo4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 处理请求
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}

二、ServletContext

1、基本概念

代表整个Web应用,可以和Web容器(如Tomcat)来通信。

2、获取方式

(1)通过request对象获取
1
2
3
4
5
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 通过request对象获取
ServletContext context1 = req.getServletContext();
}
(2)通过HttpServlet来获取
1
2
3
4
5
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 通过HttpServlet获取
ServletContext context2 = this.getServletContext();
}

3、功能

(1)获取MIME类型

MIME类型:在互联网通信过程中定义的一种文件数据类型,若需获取更多关于MIME的内容,请参阅:W3school - MIME 参考手册

下面将举例说明如何通过 ServletContext 获取MIME类型:

1
2
3
4
5
6
7
8
9
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1.获取ServletContext对象
ServletContext context = this.getServletContext();
// 2.获取MIME类型
String mimeType = context.getMimeType("a.jpg");
// 3.打印结果
System.out.println(mimeType);
}

当该方法被调用之后,控制台会打印出image/jpeg

(2)共享数据

ServletContext 对象范围包括所有用户所有请求的数据,因此我们可以通过 ServletContext来共享数据,下面我们将举例说明如何通过 ServletContext 来共享数据。

首先在其中一个 HttpServlet 的子类中添加以下内容:

1
2
3
4
// 1.获取ServletContext对象
ServletContext context = this.getServletContext();
// 2.设置Attribute
context.setAttribute("msg", "hello");

之后在另一个 HttpServlet 的子类中添加以下内容:

1
2
3
4
5
6
// 1.获取ServletContext对象
ServletContext context = this.getServletContext();
// 2.获取Attribute
Object msg = context.getAttribute("msg");
// 3.打印结果
System.out.println(msg);

启动服务器,首先访问第一个 Servlet,之后再访问第二个 Servlet,此时就可在控制台中看到打印出来的共享数据。

(3)获取文件的真实(服务器)路径

ServletContext 除了能获取MIME类型和共享数据之外,还可以获取文件的真实路径。下面将通过举例来说明如何使用 ServletContext 来获取文件的真实路径:

1
2
3
4
5
6
// 获取文件的服务器路径
String realPath = context1.getRealPath("/a.txt");//web目录下的资源访问
String realPath1 = context1.getRealPath("/WEB-INF/b.txt"); // WEB-INF目录下的资源访问
String realPath2 = context1.getRealPath("/WEB-INF/classes/c.txt");// src目录下的资源访问
// 打印结果
System.out.println(realPath);

启动服务器,当该 Servlet 被访问时即可在控制台中看到文件的真实路径,尤其要注意/WEB-INF目录下和/src路径下的资源访问方式。