目录
一、创建 Servlet 项目
1、创建项目
2、引入依赖
3、创建目录
4、编写代码
5、使用 Tomact 直接运行 (打包程序、部署程序、验证程序)
二、Servlet 运行原理
1、接收请求
2、根据请求计算响应
3、返回响应
三、Servlet API
1、HttpServlet
2、HttpServletRequest
3、HttpServletResponse
Servlet是一种实现动态页面的技术,是一组 Tomcat 提供给程序员的API (Tomcat 的 HTTP服务器给 Java 提供的一组 API),帮助程序员简单高效的开发一个 web app。
其主要做的工作:
- 允许我们注册一个类,当 Tomcat 收到某个特定的 HTTP请求时,就执行这个类中的代码。
- 帮助我们解析HTTP请求,把HTTP请求从一个字符串解析成一个 HttpRequest 对象。
- 帮助我们构造HTTP响应,我们只要给指定的 HttpResponse 对象填写一些属性字段,Servlet就会自动的安装 HTTP 协议的方式构造出一个 HTTP 响应字符串,并通过 Socket 写会给客户端。
一、创建 Servlet 项目
1、创建项目
创建一个 Maven 项目。
然后命名。项目创建完后,可能会出现这个。点击 Enable Auto-Import。
2、引入依赖
在 pom.xml 中引入 Servlet API 依赖的 jar 包。
<dependencies>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.6.1</version>
</dependency>
</dependencies>
添加完之后的完整代码:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>2023_4_30_Servlet</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.6.1</version>
</dependency>
</dependencies>
</project>
3、创建目录
上图中红框内是需要自己手动创建的。
- src/main/java :放 java 代码。
- src/main/resources :放一些依赖的资源。
- src/test/java :放单元测试的代码。
- pom.xml :是 maven项目的核心配置文件
web.xml 中的代码直接复制粘贴:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
</web-app>
4、编写代码
在 java 目录中创建一个类 HelloServlet。
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("hello");
resp.getWriter().write("hello");
}
}
什么时候浏览器发送的是 GET 请求?
1. 直接在地址栏里,输入 URL
2. 通过 a 标签跳转
3. 通过 img/link/script ...
4. 通过 from 表单,method 指定为 GET
5. 通过 ajax,type 指定为 GET
什么时候浏览器发送的是 POST 请求?
1. 通过 from 表单,method 指定为 POST
2. 通过 ajax ,type 指定为 POST
5、使用 Tomact 直接运行 (打包程序、部署程序、验证程序)
(1)安装 Tomcat
菜单 -> 文件 -> Settings
选择 Plugins, 选择 Marketplace, 搜索 "tomcat", 点击 "Install".
安装完成后重启 IDEA。
(2)配置 Smart Tomcat 插件
点击右上角的 "Add Configuration"
选择左侧的 "Smart Tomcat"
部署成功后,直接点击运行即可。
(3)访问页面
二、Servlet 运行原理
通俗理解,Servlet是属于上层建筑,而下面的传输层、网络层、数据链路层...就属于经济基础。
Tomcat 其实是一个应用程序,即运行在用户态的普通进程。用户写的代码(根据请求计算响应),通过 Servlet 和 Tomcat 进行交互。而 Tomcat 进一步的浏览器之间的网络传输,依然是和网络原理中是一样的(封装和分用)。
当浏览器给服务器发送请求的时候,Tomcat作为 HTTP 服务器,就可以接收到这个请求。HTTP协议作为一个应用层协议,需要底层的协议栈来支持工作。
更详细的过程:
1、接收请求
- 用户在浏览器输入一个 URL,浏览器自动通过 URL 构造一个 HTTP 请求。
- 这个HTTP请求会经过网络协议栈逐层进行 封装 成二进制的 bit 流,最后通过物理层硬件设备转成 光信号/电信号 传输出去。
- 经过一系列设备,最终到达目标主机。
- 服务器主机收到这些 光信号/电信号 ,再通过网络协议栈逐层进行 分用,层层解析。最终还原成 HTTP 请求,并交给 Tomcat 进程处理(根据端口号确定进程)。
- Tomcat 通过 Socket 读取到这个请求(一个字符串),并按照 HTTP 请求的格式来解析这个请求,根据 请求中的 Context Path 确定一个 webapp,在通过 Servlet Path 确定一个具体的类,再根据当前请求中的方法(GET/POST...)决定调用这个类的 doGet 或者是 doPost 等方法,此时我们代码中的 doGet / doPost 方法的第一个参数 HttpServletRequest 就包含了这个 HTTP 请求的详细信息。
2、根据请求计算响应
- 在 doGet / doPost 方法中,就需要我们自己实现代码,来规定根据这个请求来响应什么。即根据请求对象 HttpServletRequest 中的一些信息,来给HttpServletResponse 对象设置一些属性, 例如状态码、header、body.....
3、返回响应
- doGet / doPost 方法执行完之后,Tomcat 就会自动把 HttpServletResponse 这个我们刚设置好的对象转换成一个符合 HTTP 协议的字符串,通过 Socket 把这个响应发送出去。
- 这个响应也会通过网络协议栈逐层封装,最终得到一个二进制 bit 流,通过物理层硬件设备转换成 光信号 / 电信号 传输出去。
- 经过一系列设备,最终到达浏览器所在的主机。
- 服务器主机收到这些 光信号/电信号 ,再通过网络协议栈逐层进行 分用,层层解析。最终还原成 HTTP 响应,并交给 浏览器 处理。
- 浏览器也通过 Socket 读到这个响应(一个字符串),按照 HTTP 响应的格式来解析这个响应,并且把 body 中的数据按照一定的格式显示在浏览器的界面上。
三、Servlet API
1、HttpServlet
当我们写 Servlet 代码时,第一步就是创建类,并且继承自 HttpServlet 类,并重写其中的某些方法,来被 Tomcat 执行到。
核心方法:
方法名称 | 调用时机 |
init | 在 HttpServlet 实例化之后被调用 一次 |
destroy | 在 HttpServlet 实例不再使用的时候调用 一次 |
service | 收到 HTTP 请求的时候调用 |
doGet | 收到 GET 请求的时候调用 (由 service 方法调用) |
doPost | 收到 POST 请求的时候调用(由 service 方法调用) |
doPut / doDelete / doOptions / ... | 收到其他请求的时候调用(由 service 方法调用) |
2、HttpServletRequest
当 Tomcat 通过 socket API 读取 HTTP 请求(字符串),并且 按照 HTTP 协议的格式吧字符串解析成 HttpServletRequest 对象。
核心方法:
通过这些方法,可以获取到一个请求中的各个方面的信息。
方法 | 描述 |
String getProtocol( ) | 返回请求协议的 名称 和 版本 |
String getMethod( ) | 返回请求的 HTTP 方法的 名称(GET、POST或 PUT) |
String getRequestURL( ) | 从协议名称直到 HTTP 请求的第一行的查询字符串中,返回该请求的 URL 的一部分 |
String getContextPath( ) | 返回指示请求上下文的请求 URL 部分 |
String getQueryString( ) | 返回包含在路径后的请求 URL 中的 查询字符串 |
Enumeration getParameterNames( ) | 返回一个 String 对象的枚举,包含在该请求中包含的参数名称 |
String getParameter( String name ) | 以字符串形式返回请求参数的值,或者如果参数不存在则返回 null |
String[] getParameterValues( String name ) | 返回一个字符串对象的数组,包含所欲给定的请求参数的值,如果参数不存在则返回 null |
Enumeration getHeaderNames( ) | 返回一个枚举,包含在该请求中包含的所有的头名 |
String getHeader( String name ) | 以字符串形式返回指定的请求头的值 |
String getCharacterEncoding( ) | 返回请求主题中使用的字符编码的名称 |
String getContentType( ) | 返回请求主体的 MIME 类型,如果不知道类型则返回 null |
int getContentLength( ) | 以字节为单位返回请求主体的长度,并提供输入流,或者如果长度未知则返回 -1 |
InputStream getInputStream( ) | 用于读取请求的 body 内容,返回一个 InputStream 对象 |
3、HttpServletResponse
Servlet 中的 do××× 方法中的就是根据请求计算得到响应,然后把响应的数据设置到 HttpServletResponse 对象中。
然后 Tomcat 就会把这个 HttpServletResponse 对象按照 HTTP 协议的格式,转成一个字符串,并通过 Socket 写回给浏览器。
核心方法:
方法 | 描述 |
void setStatus( ) | 为该响应设置状态码 |
void setHeader( String name, String value ) | 设置一个带有给定的名称和值的 header,如果 name 已经存在,则覆旧的值 |
void addHeader( String name, String value ) | 添加一个带有给定的名称和值的 header,如果 name 已经存在,不覆盖就的值,并列添加新的键值对 |
void setContentType( String type ) | 设置被发送到客户端的响应的内容的类型 |
void setCharacterEncoding( String charset ) | 设置被发送到客户端的响应的字符编码(MIME 字符集)例如:UTF-8 |
void sendRedirect( String location ) | 使用指定的重定向位置 URL 发送临时重定向响应到客户端 |
PrintWriter getWriter( ) | 用于往 body 中写入 文本格式 的数据 |
OutputStream getOutputStream( ) | 用于往 body 中写入 二进制格式 的数据 |