Servlet入门
前言
Servlet是JavaWeb开发的基础,本系列文章是笔者学习Servlet的笔记或者视频,本系列以Kotlin开发,从环境配置开始一步步入门Servlet。
开发环境
- IntelliJ IDEA 2022.2.4 (Ultimate Edition)
- JDK 8
- Gradle 7.4.2
- Kotlin 1.7.21
- Tomcat 10.1.13
创建项目
打开 IDEA 点击 New Project
,弹出上图的界面,选择 New Project
选项,填写以下内容:
- 项目名称,
- 项目位置,
- 选择 Kotlin 语言,
- 选择 Gradle 构建系统,
- 选择 JDK 1.8 版本,
- Gradle DSL 选择 Kotlin,
- 其他的选项暂时不做修改。
最后点击 Create
按钮创建项目,创建完成后如下图:
在上图中,笔者已经编辑了 build.gradle.kts
文件,并添加了 war
插件和 jakarta.servlet-api
依赖:
plugins {
kotlin("jvm") version "1.7.21"
+ war
}
dependencies {
+ providedCompile("jakarta.servlet:jakarta.servlet-api:6.0.0")
testImplementation(kotlin("test"))
}
引入 war
插件是因为需要打包成 war
而不是 jar
,表示:Java Web Application Archive。
通过 war
插件提供的依赖关系配置 providedCompile
引入Servlet API,表示仅在编译时使用,但不会打包到 .war
文件中,因为在运行期 Web 服务器本身已经提供了 Servlet API相关的 jar
包。
Servlet 版本
要务必注意 servlet-api
的版本。4.0 及之前的 servlet-api
由 Oracle 官方维护,引入的依赖项是 javax.servlet:javax.servlet-api
,编写代码时引入的包名为:
import javax.servlet.*;
而 5.0 及以后的 servlet-api
由 Eclipse 开源社区维护,引入的依赖项是 jakarta.servlet:jakarta.servlet-api
,编写代码时引入的包名为:
import jakarta.servlet.*;
本系列笔记使用最新的 Servlet 6.0.0
版本,可以在 Maven Central Servlet-API 中查询 Servlet 版本。
Tomcat 版本
Servlet 版本与 Tomcat 版本的对应关系:
Servlet | Tomcat | Java |
---|---|---|
4.0 | 9.0.x | >= 8 |
5.0 | 10.0.x | >= 8 |
6.0 | 10.1.x | >= 11 |
本系列笔记使用最新的 Tomcat 10.1.13
版本,可以在 Apache Tomcat® - Which Version 查询最新的版本。
新建Servlet
在 main -> kotlin
目录下新建一个名为 servlet
的包并在其中新建一个名为 HelloServlet.kt
的 Kotlin 类,并添加以下代码:
package servlet
import jakarta.servlet.http.HttpServlet
class HelloServlet : HttpServlet() {
}
我们不应该直接实现 Servlet
接口,我们应该继承 HttpServlet
抽象类,然后复写其中的 init()
和 doGet()
函数,并导入相关的类,代码如下所示:
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
class HelloServlet : HttpServlet() {
override fun init() {
}
override fun doGet(req: HttpServletRequest, resp: HttpServletResponse) {
}
}
注意:区分
init()
函数与 Kotlin 中的init{}
代码块
在 init()
函数中添加以下代码:
println("HelloServlet init")
当 init()
函数调用时输出 HelloServlet init
字符串。
在 doGet()
函数体中添加以下代码:
resp.contentType = "text/html"
with(resp.writer) {
write("<h1>Hello Servlet!</h1>")
flush()
}
- 通过
resp.contentType
设置响应类型, - 然后在
with
函数中调用resp.writer
对象的write
函数写入响应内容, - 最后调用
flush
函数强制输出。
配置文件
低版本
在低版本的 Servlet 中,需要在 web.xml
配置文件中配置我们写好的 Servlet。在 main
目录下新建一个名为 webapp
的目录,在其中再新建名为 WEB-INF
的目录,在 WEB-INF
目录下新建 web.xml
配置文件,目录结构如下:
main
├── kotlin
│ └── servlet
│ └── HelloServlet.kt
├── resources
└── webapp
└── WEB-INF
└── web.xml
然后在 web.xml
配置文件中添加以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
version="6.0"
metadata-complete="true">
<servlet>
<servlet-name>Hello</servlet-name>
<servlet-class>servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
- 在
<servlet>
标签中通过<servlet-name>
为HelloServlet
起了一个别名,其中<servlet-class>
标签中的内容是HelloServlet.kt
的全限定名(Full Qualified Name), - 通过
<servlet-mappig>
标签为 Servlet 配置 URL 地址映射,其中的<servlet-name>
是 Servlet 的别名,<url-pattern>
是对应的 URL 地址映射。
高版本
在高版本的 Servlet 中可以使用注解的方式配置 Servlet,而不需要再通过 web.xml
配置文件配置了。
注意:如果存在
web.xml
配置文件,优先使用web.xml
配置文件,这是对低版本的兼容。
接下来修改 HelloServlet.kt
为其增加以下注解:
@WebServlet(name = "Hello", value = arrayOf("/servlet"))
class HelloServlet : HttpServlet() {
... // 剩余代码
}
我们为 HelloServlet
类增加了 WebServlet
注解,其中的:
name
参数对应web.xml
中的<servlet-name>
标签,此处为Hello
,value
或者urlPatterns
参数对应web.xml
中的<url-pattern>
标签,此处为/servlet
。
运行Servlet
在项目根目录下运行 Gradle 命令 ./gradlew :clean :war
,然后在 /build/libs
目录下得到名为 learn-servlet-1.0-SNAPSHOT.war
文件,这个文件就是我们编译打包后的 Web 应用程序。
我们将在 Tomcat 10.1.13 Web 服务器运行这个 war
包。
首先需要创建一个 Tomcat Server,点击 Edit Configurations
按钮:
然后在弹出的对话框中点击左上角 +
号,下滑选择 Tomcat Server -> Local
,如下图:
点击 Local
按钮后,弹出以下界面:
- 上图标记1处,JRE要选择为 Java 11,因为 Tomcat 10.1.x 版本最低支持 Java 11,如果低于 Java 11 服务器将无法启动,
- 上图标记2处,HTTP port 默认是 8080,因与我本地的 Vuepress 项目端口冲突,所以改为 8081。
然后切换到 Deployment
标签页:
点击左上角 +
号按钮,在对话框中选择 Artifact
,然后再弹出的对话框中选择第一个工件,如下图:
完成后如下图:
修改 Application context 为:/
,最后点击 OK 按钮完成配置,然后启动服务器。
~/Spring/apache-tomcat-10.1.13/bin/catalina.sh run
服务器版本: Apache Tomcat/10.1.13
服务器版本号: 10.1.13.0
操作系统名称: Mac OS X
OS.版本: 11.5
架构: x86_64
Java虚拟机版本: 11.0.12+8-LTS-237
JVM.供应商: Oracle Corporation
........................... 其他启动日志
初始化协议处理器 ["http-nio-8081"]
服务器在[657]毫秒内初始化
正在启动服务[Catalina]
正在启动 Servlet 引擎:[Apache Tomcat/10.1.13]
开始协议处理句柄["http-nio-8081"]
[91]毫秒后服务器启动
Connected to server
........................... 其他日志
HelloServlet init
在浏览器中访问 http://localhost:8081/servlet
, 即可看到 HelloServlet
的输出:
我们在
HelloServlet
的WebServlet
注解中为其配置了url-pattern
,所以访问时的路径是/servlet
。
总结
本文学习了如何编写 Servlet 来处理 HTTP 请求,同时学习了如何在 Tomcat 服务器中运行 Servlet。
Servlet API 提供了 HttpServet
接口方便我们处理各种 HTTP 请求方法,同时也提供了 HttpServletRequest
和 HttpServletResponse
两个接口来封装 HTTP 的请求和响应。
注意 Servlet 版本的不同,相应的包名也不同。
Tomcat 版本对 Servlet 和 Java 版本敏感,需要我们配置对应的版本才能正常启动。