前言
上一篇讲解了Look My Eyes 最新IDEA快速搭建Java Web工程的两种方式,本篇分析如何通过Servlet、JSP快速渲染网页。
有些小伙伴可能疑惑了:Servlet、JPS是多古老的技术了,我SpringBoot一梭哈,还在这卷啥呢?其实不然,SpringBoot也是基于Servlet封装的,通过编写简单的Servlet,认识基本原理,后续可以更好地理解SpringBoot,同时也了解Java Web发展历程。
通过本篇文章,你将了解到:
- TCP/IP协议栈
- HTTP协议
- Servlet 处理Get/Post请求
- Servlet、JSP珠联璧合
1. TCP/IP协议栈
讲Servlet之前先来了解前置知识。
OSI 模型(Open Systems Interconnection Model,开放系统互连模型),它是由国际标准化组织(ISO)提出的一种网络通信框架,用于标准化网络协议和通信过程,总共有7层。
而事实上的网络模型是TCP/IP,它有四层:
当发起HTTP请求时,BS架构数据流转如下:

所谓协议,其实就是B、S双方约定好如何处理特定的数据规范,而这些规范是固化在网络栈(主要是传输层/网络层/数据链路层)。
Browser实现了HTTP客户端功能,而Server端实现了HTTP服务端的功能,两者通过HTTP协议进行了联动。
2. HTTP协议
HTTP是应用层协议,它提供了许多请求方式,以最常用的Get、Post请求为例。
Get 请求
Get 请求格式:
在浏览器地址栏里输入如下网址:
http://localhost:8080/java_web_war_exploded/myServlet?key=name
打开F12,查看网络选项:
GET--->请求方式
java_web_war_exploded/myServlet?key=name--->请求路径,其中?之后为key-value对,是Get请求携带的参数
HTTP/1.1 请求协议版本
Post 请求
Post比Get请求多了个请求体。
向服务端发起Post请求:

请求头里的Content-Type表明请求体的内容是什么类型,此处是表单类型,因此实际请求体为:
响应格式
当客户端发起Get/Post请求时,服务端需要返回针对该请求的响应。
实际内容如下:
HTTP/1.1--->协议版本 200--->状态码
Content-Type 用于指定响应体的内容格式,此处是html,而我们实际返回就是一个html内容:
3. Servlet 处理Get/Post请求
处理Get请求
前置知识了解之后,接下来进入Servlet世界探索吧。
现在有个需求:
在浏览器地址栏访问网页,该网址显示内容:Welcome to Java Web
分几个步骤实现该需求:
- 引入Servlet库
在pom.xml里引入Servlet。
xml
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
此处是provided模式,意思是编译期会借助这个库使得能够正常编译,实际打包时不会打进JAR/WAR包里,因为Servlet相关库在Tomcat里有实现。
- 编写Servlet类,处理Get请求
java
public class WelcomeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置响应内容类型为 HTML
resp.setContentType("text/html");
// 提取 PrintWriter 对象
PrintWriter out = resp.getWriter();
// 输出 HTML 内容
out.println("<html>");
out.println("<head><title>Welcome</title></head>");
out.println("<body>");
out.println("<h1>Welcome to Java Web</h1>");
out.println("</body>");
out.println("</html>");
}
}
- 配置访问映射
有了Servlet处理类,还需要将该Servlet与访问路径绑定起来,映射关系在web.xml里体现:
xml
<servlet>
<servlet-name>WelcomeServlet</servlet-name>
<servlet-class>com.example.WelcomeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>WelcomeServlet</servlet-name>
<url-pattern>/welcome</url-pattern>
</servlet-mapping>
/welcome 表示访问的路径,访问该路径时映射到WelcomeServlet,而该Servlet实际的类是: com.example.WelcomeServlet,因此最终是它处理了Get请求。
- 查看效果
在地址栏输入待访问的地址。

可以看出:
当在浏览器发起Get请求后,服务端根据访问的路径找到对应处理的Servlet,该Servlet输出HTML内容,该内容作为HTTP响应返回到浏览器,浏览器解释执行该HTML,最终展示页面。
处理Post请求
WelcomeServlet 除了能够处理Get请求,也可以处理Post请求(通常一个Servlet只处理一种方式的请求,此处为了方便就一起描述了)。
只需要重写相关post方法:
java
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置响应内容类型为 HTML
resp.setContentType("text/html");
// 提取 PrintWriter 对象
PrintWriter out = resp.getWriter();
// 输出 HTML 内容
out.println("<html>");
out.println("<head><title>Welcome</title></head>");
out.println("<body>");
out.println("<h1>Welcome to Java Web I'm from post</h1>");
out.println("</body>");
out.println("</html>");
}
浏览器访问默认发起的是Get请求,我们使用APIFOX进行Post请求:
同样的,Servlet正常处理了Post请求,并输出HTML内容。
4. Servlet、JSP珠联璧合
上面输出的都是静态页面,现在有个场景:需要将用户的姓名、邮箱展示出来。
- Get请求携带姓名和邮箱的数据
浏览器访问如下地址
html
http://localhost:8080/java_web_war_exploded/welcome?name=fish&[email protected]
- Servlet处理Get请求并取出参数
java
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置响应内容类型为 HTML
resp.setContentType("text/html");
// 提取 PrintWriter 对象
PrintWriter out = resp.getWriter();
// 从请求中获取 name 和 email 参数
String name = req.getParameter("name");
String email = req.getParameter("email");
// 输出 HTML 内容
out.println("<html>");
out.println("<head><title>Welcome</title></head>");
out.println("<body>");
out.println("<h1>Welcome to Java Web</h1>");
// 展示用户的姓名和邮箱
if (name != null && email != null) {
out.println("<p>Name: " + name + "</p>");
out.println("<p>Email: " + email + "</p>");
} else {
out.println("<p>No name or email provided.</p>");
}
out.println("</body>");
out.println("</html>");
}
最终效果:
虽然能够动态输出了页面,但页面渲染和业务逻辑耦合在Servlet里,如果有单独处理页面渲染的方式就好了。
于是JSP(Java Server Pages)出场了。
Servlet将与页面相关的渲染交给JSP,自己只处理逻辑相关的动作,而JSP则专注于页面,当然JSP最终也会编译为Servlet执行。
通过以下几个步骤使用JSP改造WelcomeServlet。
- 创建welcome.jsp
html
<html>
<head>
<title>WelcomeJSP</title>
</head>
<body>
<h1>Welcome to Java Web In JSP</h1>
</body>
</html>
可以看出,JSP和html语法基本一致。
- 将Servlet转发到JSP
当Servlet收到Get请求时,转发给JSP:
java
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取 RequestDispatcher 对象,用于转发请求到 welcome.jsp
RequestDispatcher dispatcher = req.getRequestDispatcher("welcome.jsp");
// 转发请求
dispatcher.forward(req, resp);
}
最终效果:
当然此时的JSP依然静态的,我们还需要处理name和email。
Servlet保持不变,只需要改动JSP:
html
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>WelcomeJSP</title>
</head>
<body>
<h1>Welcome to Java Web In JSP</h1>
<%
// 从请求中提取 name 和 email 参数
String name = request.getParameter("name");
String email = request.getParameter("email");
%>
<!-- 显示 name 和 email -->
<p>Name: <%= name != null ? name : "No name provided" %></p>
<p>Email: <%= email != null ? email : "No email provided" %></p>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
使用的脚本语言是Java,最终输出html。
request是JSP内置的属性,我们可以像编写Java逻辑一样处理JSP里的逻辑。处理逻辑的地方需要使用<% %>框起来,表示需要执行Java 代码。
最后的效果:
可以看到,使用JSP之后,Servlet就简洁了许多,同时我们可以在JSP里方便设计各种样式的页面,而不用在Servlet写一堆输出html的代码。
因为JSP里可以执行Java代码,通过代码产生的结果渲染不同的页面,因此JSP是名副其实的动态页面。
本篇涉及代码均在此处
下一篇,将会以Servlet 写一个登录注册的的例子,用以加深对前后端交互的理解。
如果你觉得有帮助,请一键三连哦~