糟糕,又得重新认识上古技术--Servlet/JSP

前言

上一篇讲解了Look My Eyes 最新IDEA快速搭建Java Web工程的两种方式,本篇分析如何通过Servlet、JSP快速渲染网页。

有些小伙伴可能疑惑了:Servlet、JPS是多古老的技术了,我SpringBoot一梭哈,还在这卷啥呢?其实不然,SpringBoot也是基于Servlet封装的,通过编写简单的Servlet,认识基本原理,后续可以更好地理解SpringBoot,同时也了解Java Web发展历程。

通过本篇文章,你将了解到:

  1. TCP/IP协议栈
  2. HTTP协议
  3. Servlet 处理Get/Post请求
  4. 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

分几个步骤实现该需求:

  1. 引入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里有实现。

  1. 编写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>");
    }
}
  1. 配置访问映射
    有了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请求。

  1. 查看效果
    在地址栏输入待访问的地址。

可以看出:

当在浏览器发起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珠联璧合

上面输出的都是静态页面,现在有个场景:需要将用户的姓名、邮箱展示出来。

  1. Get请求携带姓名和邮箱的数据
    浏览器访问如下地址
html 复制代码
http://localhost:8080/java_web_war_exploded/welcome?name=fish&[email protected]
  1. 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。

  1. 创建welcome.jsp
html 复制代码
<html>
<head>
    <title>WelcomeJSP</title>
</head>
<body>
<h1>Welcome to Java Web In JSP</h1>
</body>
</html>

可以看出,JSP和html语法基本一致。

  1. 将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 写一个登录注册的的例子,用以加深对前后端交互的理解。

如果你觉得有帮助,请一键三连哦~

相关推荐
陳長生.8 分钟前
JAVA EE_初始网络原理
java·开发语言·网络·java-ee
USER_A00111 分钟前
【VUE3】练习项目——大事件后台管理
前端·vue.js·axios·pinia·elementplus·husky·vuerouter4
fruge14 分钟前
Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.
前端·css·sass
菜鸟起航ing19 分钟前
【Java面试系列】Spring Boot微服务架构下的分布式事务处理与性能优化详解 - 3-5年Java开发必备知识
java·spring boot·微服务·性能优化·分布式事务
其实你热情似火20 分钟前
Java基础第20天-JDBC
java·数据库·oracle
开心猴爷22 分钟前
Flutter 开发系列(八):Flutter 项目的自动化测试与调试
后端
开心就好202523 分钟前
将Flutter推向极限:你应该知道的44个性能提示
后端
00后程序员24 分钟前
【Flutter】自动测试探索
后端
aiopencode26 分钟前
Flutter快学快用24讲--09 单元测试:Flutter 应用单元测试,提升代码质量
后端
调试人生的显微镜27 分钟前
Nativefier——可以把网页打包成exe的工具
后端