之前我们搭建好了自己的 Java Web 开发环境,现在当然要进行实际应用啦。下面就开始我们 Java Web 之旅第二站 - Servlet and JSP。
Servlet
Servlet 是基于 Java 的 Web 组件,作为 Web 容器的功能模块,它运行在服务端,处理来自客户端的网络请求,并返回相应数据包。任何 Servlet 组件都实现了 javax.servlet.Servlet
接口, Web 容器可以统一管理这些 Servlet 组件。
Servlet 生命周期
Servlet 整个生命周期由 Web 容器管理,它会经历以下 4 个阶段:
- 载入阶段 load
Web 容器部署后,将加载所有 Servlet。 - 初始化阶段 init
Web 容器在首次接收到来自客户端请求或者 Web 容器启动时指定(web.xml 中设置), 将调用对应 Servlet 类的 init 方法,实例化 Servlet 对象并初始化数据。 - 处理请求 service
Web 容器启用一个线程来处理客户端请求,根据 Request URI 调用对于 Servlet 实例的 service 方法,并传入 HttpServletRequest 和 HttpServletResponse 参数, 默认的 service 方法将请求分发到对应的 doGet 或 doPost 方法中。 - 销毁阶段 destroy
当 Web 容器终止 或者 Servlet 重新装载时,Web 容器将调用前面 Servlet 实例的 destroy 方法,销毁实例。最后 servlet 实例将被 JVM 垃圾回收。
IDEA 搭建 Servlet 项目
使用 IDEA 可以很方便地搭建出 Servlet 项目骨架。让我们开始吧~
首先新建一个项目,选择 JavaEE Web Application 骨架,然后在此基础上集成 Maven 环境,最后会得到如下的项目结构:
1 | ├── pom.xml |
下面描述下各文件的作用:
- pom.xml: Maven 的配置文件,用于管理项目依赖等
- servlet_demo.iml: IDEA 的项目设置文件,保存模块路径,依赖关系和其他设置等
- src: 保存功能或测试代码的目录
- web: 保存前端页面或资源的目录
- web.xml: Java Web 项目的配置文件,用于配置 Servlet, 路由映射等
在开始编写代码前,我们需要先引入 servlet-api.jar 到项目中。打开 pom.xml 并按下 ALT
+ Insert
, 在弹窗中选择 Dependency
, 搜索 servlet
并选中相应的依赖包,最后在 Maven 面板中选择同步依赖即可[2]。
First Servlet
准备工作已经做好了,现在让我们着手编写第一个 Servlet 吧。
首先在 web 目录下添加一个 HTML 页面,它有个登录表单提交用户输入的用户名和密码:
1 | <!-- index.html --> |
然后在 src/main/java 目录下创建一个 Servlet Java 文件:
1 | // LoginServlet.java |
前面提到一个 Servlet 类需要实现 javax.servlet.Servlet
接口,上面定义的 LoginServlet
继承的 HttpServlet
类就实现了 javax.servlet.Servlet
, 此外实现了此接口的还有 GenericServlet
类。而 GenericServlet
比起 HttpServlet
,它没有派发 service 方法,需要自己实现。
这里的 LoginServlet
获取到请求中的 username
和 password
参数,并对其验证,输出验证结果。
别忘了还需要映射 servlet 到路由上哦,更新 web.xml 如下:
1 |
|
其中 welcome-file 就是网站首页。
最后点击启动 Tomcat 运行我们的站点吧~(别忘了,运行前配置下 Tomcat)
JSP
JSP - Java Server Pages 是一种特殊的 Servlet, 主要用于处理 Web 视图部分。它允许在 HTML, XML 中嵌入 Java 代码,调用 Java API。
JSP 生命周期
JSP 有着类似 Servlet 一样的生命周期,区别在于 JSP 比起 Servlet 多了编译阶段。 JSP 会经历以下 4 个阶段:
- 编译阶段
当客户端请求 JSP 页面时, Web 容器会检查此 JSP,若 JSP 未被编译或编译后修改, Web 容器将解析此 JSP,并将其转换 Servlet 再编译。 - 初始化阶段
Web 容器编译完 JSP 后,将会调用 jspInit 方法初始化 JSP。 - 处理请求
Web 容器调用 _jspService 方法来处理每个请求, _jspService 接收了 HttpServletRequest 和 HttpServletResponse 两个参数。 - 销毁阶段
Web 容器终止或 JSP 被重新编译时,Web 容器将调用 jspDestroy 方法来销毁之前的 JSP。
JSP 语法
JSP 在 XML 中嵌入 Java 代码,它也有着自己特殊的语法,下面我们简单介绍下:
- 基本格式:
<% 代码片段 %>
- 声明语法:
<%! int c = 1; %>
- 插值语法:
<%= (new java.util.Date()).toLocaleString() %>
- 指令语法:
<%@ page attribute="value" %>
, 用于描述页面属性等 - 行为语法:
<% jsp:include page="value" %>
JSP 隐含对象
JSP 上下文中存在一些隐含对象,我们用它们控制 JSP 行为。
- request: HttpServletRequest 实例
- response: HttpServletResponse 实例
- out: PrintWriter 实例,用于把结果输出至网页上
- session: HttpSession 实例
- application: ServletContext 实例,与应用上下文有关
- config: ServletConfig 实例
- pageContext: PageContext 实例,提供对 JSP 页面所有对象以及命名空间的访问
- page: 类似于 Java 类中的 this 关键字
- Exception: Exception 对象,代表发生错误的 JSP 页面中对应的异常对象
JSP 编码问题
如果我们要在页面正常显示中文,我们需要在 JSP 文件头部添加以下代码:
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> |
First JSP
我们已经了解 JSP 的基本概念了,现在就编写第一个 JSP 吧。
首先在前面的 index.html 中增加下面的表单,接收输入的用户名提交后跳转到 JSP 页面:
1 | <!-- index.html --> |
在 JSP 页面中,我们将接收到的用户名输出页面中:
1 | <%-- welcome.jsp --%> |