JavaWeb:JSP概述及原理

偏执的太偏执、 2024-03-30 13:49 198阅读 0赞

1,JSP概述

JSP(全称:Java Server Pages):Java服务端页面。 是一种动态的网页技术,其中既可以定义 HTMLJSCSS等静态内容,还可以定义Java代码的动态内容,也就是 JSP = HTML + Java。如下就是jsp代码:

  1. <html>
  2. <head>
  3. <title>Title</title>
  4. </head>
  5. <body>
  6. <h1>JSP,Hello World</h1>
  7. <%
  8. System.out.println("hello,jsp~");
  9. %>
  10. </body>
  11. </html>

上面代码 h1 标签内容是展示在页面上,而Java的输出语句是输出在idea的控制台。

那么,JSP能做什么呢?现在我们只用 servlet 实现功能,看存在什么问题。如下图所示,当我们登陆成功后,需要在页面上展示用户名

在这里插入图片描述

上图的用户名是动态展示,也就是谁登陆就展示谁的用户名。只用 servlet 如何实现呢?在今天的资料里已经提供好了一个 LoginServlet ,该 servlet 就是实现这个功能的,现将资料中的 LoginServlet.java 拷贝到 request-demo 项目中来演示。接下来启动服务器并访问登陆页面

在这里插入图片描述

输入了 zhangsan 用户的登陆信息后点击 登陆 按钮,就能看到如下图效果

在这里插入图片描述

当然如果是 lisi 登陆的,在该页面展示的就是 lisi,欢迎您,动态的展示效果就实现了。那么 LoginServlet 到底是如何实现的,我们看看它里面的内容

在这里插入图片描述

上面的代码有大量使用到 writer 对象向页面写标签内容,这样我们的代码就显得很麻烦;将来如果展示的效果出现了问题,排错也显得有点力不从心。而JSP是如何解决这个问题的呢?在资料中也提供了一个 login.jsp 页面,该页面也能实现该功能,现将该页面拷贝到项目的 webapp下,需要修改 login.html 中表单数据提交的路径为下图

在这里插入图片描述

重新启动服务器并进行测试,发现也可以实现同样的功能。那么 login.jsp 又是如何实现的呢?那我们来看看 login.jsp 的代码

在这里插入图片描述

上面代码可以看到里面基本都是 HTML 标签,而动态数据使用Java代码进行展示;这样操作看起来要比用 servlet 实现要舒服很多。

JSP作用:简化开发,避免了在Servlet中直接输出HTML标签。

2,JSP快速入门

接下来我们做一个简单的快速入门代码。

2.1 搭建环境

创建一个mavenweb项目,项目结构如下:

在这里插入图片描述

pom.xml 文件内容如下:

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>com.dcxuexi</groupId>
  5. <artifactId>jsp-demo</artifactId>
  6. <packaging>war</packaging>
  7. <version>1.0-SNAPSHOT</version>
  8. <properties>
  9. <maven.compiler.source>17</maven.compiler.source>
  10. <maven.compiler.target>17</maven.compiler.target>
  11. </properties>
  12. <dependencies>
  13. <dependency>
  14. <groupId>javax.servlet</groupId>
  15. <artifactId>javax.servlet-api</artifactId>
  16. <version>3.1.0</version>
  17. <scope>provided</scope>
  18. </dependency>
  19. <dependency>
  20. <groupId>junit</groupId>
  21. <artifactId>junit</artifactId>
  22. <version>3.8.1</version>
  23. <scope>test</scope>
  24. </dependency>
  25. </dependencies>
  26. </project>

2.2 导入JSP依赖

dependencies 标签中导入JSP的依赖,如下

  1. <dependency>
  2. <groupId>javax.servlet.jsp</groupId>
  3. <artifactId>jsp-api</artifactId>
  4. <version>2.2</version>
  5. <scope>provided</scope>
  6. </dependency>

该依赖的 scope 必须设置为 provided,因为tomcat中有这个jar包了,所以在打包时我们是不希望将该依赖打进到我们工程的war包中。

2.3 创建jsp页面

在项目的 webapp 下创建jsp页面

在这里插入图片描述

通过上面方式创建一个名为 hello.jsp 的页面。

2.4 编写代码

hello.jsp 页面中书写 HTML 标签和 Java 代码,如下

  1. <%--
  2. Created by IntelliJ IDEA.
  3. User: DongChuang
  4. Date: 2023/1/2
  5. Time: 16:04
  6. To change this template use File | Settings | File Templates.
  7. --%>
  8. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  9. <html>
  10. <head>
  11. <title>Title</title>
  12. </head>
  13. <body>
  14. <h1>hello jsp ...</h1>
  15. <%
  16. System.out.println("hello jsp ...");
  17. %>
  18. </body>
  19. </html>

2.5 测试

启动服务器并在浏览器地址栏输入 http://localhost:8080/jsp-demo/hello.jsp,我们可以在页面上看到如下内容

在这里插入图片描述

在这里插入图片描述

同时也可以看到在 idea 的控制台看到输出的 hello jsp ... 内容。

3,JSP原理

我们之前说JSP就是一个页面,那么在JSP中写 html 标签,我们能理解,但是为什么还可以写 Java 代码呢?

因为 JSP本质上就是一个Servlet。 接下来我们聊聊访问jsp时的流程

在这里插入图片描述

  1. 浏览器第一次访问 hello.jsp 页面
  2. tomcat 会将 hello.jsp 转换为名为 hello_jsp.java 的一个 Servlet
  3. tomcat 再将转换的 servlet 编译成字节码文件 hello_jsp.class
  4. tomcat 会执行该字节码文件,向外提供服务

我们可以到项目所在磁盘目录下找 target\tomcat\work\Tomcat\localhost\jsp-demo\org\apache\jsp 目录,而这个目录下就能看到转换后的 servlet

在这里插入图片描述

打开 hello_jsp.java 文件,来查看里面的代码

在这里插入图片描述

由上面的类的继承关系可以看到继承了名为 HttpJspBase 这个类,那我们在看该类的继承关系。

在这里插入图片描述

可以看到该类继承了 HttpServlet ;那么 hello_jsp 这个类就间接的继承了 HttpServlet ,也就说明 hello_jsp 是一个 servlet

继续阅读 hello_jsp 类的代码,可以看到有一个名为 _jspService() 的方法,该方法就是每次访问 jsp 时自动执行的方法,和 servlet 中的 service 方法一样 。

而在 _jspService() 方法中可以看到往浏览器写标签的代码:

在这里插入图片描述

以前我们自己写 servlet 时,这部分代码是由我们自己来写,现在有了 jsp 后,由tomcat完成这部分功能。

4,JSP脚本

JSP脚本用于在JSP页面内定义Java代码。在之前的入门案例中我们就在JSP页面定义的Java代码就是JSP脚本。

4.1 JSP脚本分类

JSP脚本有如下三个分类:

  • <% … %>:内容会直接放到_jspService()方法之中
  • <%= … %>:内容会放到out.print()中,作为out.print()的参数
  • <%! … %>:内容会放到_jspService()方法之外,被类直接包含

代码演示:

hello.jsp 中书写

  1. <%
  2. System.out.println("hello,jsp~");
  3. int i = 3;
  4. %>

通过浏览器访问 hello.jsp 后,查看转换的 hello_jsp.java 文件,i 变量定义在了 _jspService() 方法中

在这里插入图片描述

hello.jsp 中书写

  1. <%="hello"%>
  2. <%=i%>

通过浏览器访问 hello.jsp 后,查看转换的 hello_jsp.java 文件,该脚本的内容被放在了 out.print() 中,作为参数

在这里插入图片描述

hello.jsp 中书写

  1. <%!
  2. void show(){}
  3. String name = "zhangsan";
  4. %>

通过浏览器访问 hello.jsp 后,查看转换的 hello_jsp.java 文件,该脚本的内容被放在了成员位置

在这里插入图片描述

4.2 案例

4.2.1 需求

使用JSP脚本展示品牌数据

在这里插入图片描述

说明:

  • 在该案例中数据不从数据库中查询,而是在JSP页面上写死
4.2.2 实现
  • 在项目的 webapp 中创建 brand.jspbrand.jsp 内容如下

    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <!DOCTYPE html>
    3. <html lang="en">
    4. <head>
    5. <meta charset="UTF-8">
    6. <title>Title</title>
    7. </head>
    8. <body>
    9. <input type="button" value="新增"><br>
    10. <hr>
    11. <table border="1" cellspacing="0" width="800">
    12. <tr>
    13. <th>序号</th>
    14. <th>品牌名称</th>
    15. <th>企业名称</th>
    16. <th>排序</th>
    17. <th>品牌介绍</th>
    18. <th>状态</th>
    19. <th>操作</th>
    20. </tr>
    21. <tr align="center">
    22. <td>1</td>
    23. <td>三只松鼠</td>
    24. <td>三只松鼠</td>
    25. <td>100</td>
    26. <td>三只松鼠,好吃不上火</td>
    27. <td>启用</td>
    28. <td><a href="#">修改</a> <a href="#">删除</a></td>
    29. </tr>
    30. <tr align="center">
    31. <td>2</td>
    32. <td>优衣库</td>
    33. <td>优衣库</td>
    34. <td>10</td>
    35. <td>优衣库,服适人生</td>
    36. <td>禁用</td>
    37. <td><a href="#">修改</a> <a href="#">删除</a></td>
    38. </tr>
    39. <tr align="center">
    40. <td>3</td>
    41. <td>小米</td>
    42. <td>小米科技有限公司</td>
    43. <td>1000</td>
    44. <td>为发烧而生</td>
    45. <td>启用</td>
    46. <td><a href="#">修改</a> <a href="#">删除</a></td>
    47. </tr>
    48. </table>
    49. </body>
    50. </html>

    现在页面中的数据都是假数据。

  • brand.jsp 中准备一些数据

    1. <%
    2. // 查询数据库
    3. List<Brand> brands = new ArrayList<Brand>();
    4. brands.add(new Brand(1,"三只松鼠","三只松鼠",100,"三只松鼠,好吃不上火",1));
    5. brands.add(new Brand(2,"优衣库","优衣库",200,"优衣库,服适人生",0));
    6. brands.add(new Brand(3,"小米","小米科技有限公司",1000,"为发烧而生",1));
    7. %>

    注意: 这里的类是需要导包的

  • brand.jsp 页面中的 table 标签中的数据改为动态的

    1. <table border="1" cellspacing="0" width="800">
    2. <tr>
    3. <th>序号</th>
    4. <th>品牌名称</th>
    5. <th>企业名称</th>
    6. <th>排序</th>
    7. <th>品牌介绍</th>
    8. <th>状态</th>
    9. <th>操作</th>
    10. </tr>
    11. <%
    12. for (int i = 0; i < brands.size(); i++) {
    13. //获取集合中的 每一个 Brand 对象
    14. Brand brand = brands.get(i);
    15. }
    16. %>
    17. <tr align="center">
    18. <td>1</td>
    19. <td>三只松鼠</td>
    20. <td>三只松鼠</td>
    21. <td>100</td>
    22. <td>三只松鼠,好吃不上火</td>
    23. <td>启用</td>
    24. <td><a href="#">修改</a> <a href="#">删除</a></td>
    25. </tr>
    26. </table>

    上面的for循环需要将 tr 标签包裹起来,这样才能实现循环的效果,代码改进为

    1. <table border="1" cellspacing="0" width="800">
    2. <tr>
    3. <th>序号</th>
    4. <th>品牌名称</th>
    5. <th>企业名称</th>
    6. <th>排序</th>
    7. <th>品牌介绍</th>
    8. <th>状态</th>
    9. <th>操作</th>
    10. </tr>
    11. <%
    12. for (int i = 0; i < brands.size(); i++) {
    13. //获取集合中的 每一个 Brand 对象
    14. Brand brand = brands.get(i);
    15. %>
    16. <tr align="center">
    17. <td>1</td>
    18. <td>三只松鼠</td>
    19. <td>三只松鼠</td>
    20. <td>100</td>
    21. <td>三只松鼠,好吃不上火</td>
    22. <td>启用</td>
    23. <td><a href="#">修改</a> <a href="#">删除</a></td>
    24. </tr>
    25. <%
    26. }
    27. %>
    28. </table>

    注意:<%%>里面写的是Java代码,而外边写的是HTML标签

    上面代码中的 td 标签中的数据都需要是动态的,所以还需要改进

    1. <table border="1" cellspacing="0" width="800">
    2. <tr>
    3. <th>序号</th>
    4. <th>品牌名称</th>
    5. <th>企业名称</th>
    6. <th>排序</th>
    7. <th>品牌介绍</th>
    8. <th>状态</th>
    9. <th>操作</th>
    10. </tr>
    11. <%
    12. for (int i = 0; i < brands.size(); i++) {
    13. //获取集合中的 每一个 Brand 对象
    14. Brand brand = brands.get(i);
    15. %>
    16. <tr align="center">
    17. <td><%=brand.getId()%></td>
    18. <td><%=brand.getBrandName()%></td>
    19. <td><%=brand.getCompanyName()%></td>
    20. <td><%=brand.getOrdered()%></td>
    21. <td><%=brand.getDescription()%></td>
    22. <td><%=brand.getStatus() == 1 ? "启用":"禁用"%></td>
    23. <td><a href="#">修改</a> <a href="#">删除</a></td>
    24. </tr>
    25. <%
    26. }
    27. %>
    28. </table>
4.2.3 成品代码
  1. <%@ page import="com.dcxuexi.pojo.Brand" %>
  2. <%@ page import="java.util.List" %>
  3. <%@ page import="java.util.ArrayList" %>
  4. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  5. <%
  6. // 查询数据库
  7. List<Brand> brands = new ArrayList<Brand>();
  8. brands.add(new Brand(1,"三只松鼠","三只松鼠",100,"三只松鼠,好吃不上火",1));
  9. brands.add(new Brand(2,"优衣库","优衣库",200,"优衣库,服适人生",0));
  10. brands.add(new Brand(3,"小米","小米科技有限公司",1000,"为发烧而生",1));
  11. %>
  12. <!DOCTYPE html>
  13. <html lang="en">
  14. <head>
  15. <meta charset="UTF-8">
  16. <title>Title</title>
  17. </head>
  18. <body>
  19. <input type="button" value="新增"><br>
  20. <hr>
  21. <table border="1" cellspacing="0" width="800">
  22. <tr>
  23. <th>序号</th>
  24. <th>品牌名称</th>
  25. <th>企业名称</th>
  26. <th>排序</th>
  27. <th>品牌介绍</th>
  28. <th>状态</th>
  29. <th>操作</th>
  30. </tr>
  31. <%
  32. for (int i = 0; i < brands.size(); i++) {
  33. Brand brand = brands.get(i);
  34. %>
  35. <tr align="center">
  36. <td><%=brand.getId()%></td>
  37. <td><%=brand.getBrandName()%></td>
  38. <td><%=brand.getCompanyName()%></td>
  39. <td><%=brand.getOrdered()%></td>
  40. <td><%=brand.getDescription()%></td>
  41. <td><%=brand.getStatus() == 1 ? "启用":"禁用"%></td>
  42. <td><a href="#">修改</a> <a href="#">删除</a></td>
  43. </tr>
  44. <%
  45. }
  46. %>
  47. </table>
  48. </body>
  49. </html>
4.2.4 测试

在浏览器地址栏输入 http://localhost:8080/jsp-demo/brand.jsp ,页面展示效果如下

在这里插入图片描述

4.3 JSP缺点

通过上面的案例,我们可以看到JSP的很多缺点。

由于JSP页面内,既可以定义HTML标签,又可以定义Java代码,造成了以下问题:

  • 书写麻烦:特别是复杂的页面

    既要写HTML标签,还要写Java代码

  • 阅读麻烦

    上面案例的代码,相信你后期再看这段代码时还需要花费很长的时间去梳理

  • 复杂度高:运行需要依赖于各种环境,JREJSP容器,JavaEE ···
  • 占内存和磁盘:JSP会自动生成.java.class文件占磁盘,运行的是.class文件占内存
  • 调试困难:出错后,需要找到自动生成的.java文件进行调试
  • 不利于团队协作:前端人员不会Java,后端人员不精HTML

    如果页面布局发生变化,前端工程师对静态页面进行修改,然后再交给后端工程师,由后端工程师再将该页面改为JSP页面

由于上述的问题, JSP已逐渐退出历史舞台, 以后开发更多的是使用 HTML + Ajax 来替代。Ajax是我们后续会重点介绍。有个这个技术后,前端工程师负责前端页面开发,而后端工程师只负责前端代码开发。下来对技术的发展进行简单的说明

在这里插入图片描述

  1. 第一阶段:使用 servlet 即实现逻辑代码编写,也对页面进行拼接。这种模式我们之前也接触过
  2. 第二阶段:随着技术的发展,出现了 JSP ,人们发现 JSP 使用起来比 Servlet 方便很多,但是还是要在 JSP 中嵌套 Java 代码,也不利于后期的维护
  3. 第三阶段:使用 Servlet 进行逻辑代码开发,而使用 JSP 进行数据展示

    在这里插入图片描述

  4. 第四阶段:使用 servlet 进行后端逻辑代码开发,而使用 HTML 进行数据展示。而这里面就存在问题,HTML 是静态页面,怎么进行动态数据展示呢?这就是 ajax 的作用了。

那既然JSP已经逐渐的退出历史舞台,那我们为什么还要学习 JSP 呢?原因有两点:

  • 一些公司可能有些老项目还在用 JSP ,所以要求我们必须动 JSP
  • 我们如果不经历这些复杂的过程,就不能体现后面阶段开发的简单

发表评论

表情:
评论列表 (有 0 条评论,198人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Kafka原理概述

    Kafka 是一个分布式消息队列,具有高性能、持久化、多副本备份、横向扩展能力。生产者往队列里写消息,消费者从队列里取消息进行业务逻辑。一般在架构设计中起到解耦、削峰、异步处理