JSP(全称:Java Server Pages):Java 服务端页面(上)

简介: JSP(全称:Java Server Pages):Java 服务端页面

1,JSP 概述


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


<html><head><title>Title</title></head><body><h1>JSP,HelloWorld</h1><%System.out.println("hello,jsp~");
%></body></html>


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


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


5d7097f209314fb180f4ca71e9ed1d1d.png


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


8d2621f1ac0941aabecefcdc517130ef.png


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


29a073fd76f84ae19152af7fd8fb967b.png


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


d8426907b00f4536834283c49f9ec356.png


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


6a85bd32347840718c3a5f38c447117f.png


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


9eda7238dfc84952a9d7cd4abbbd37ca.png


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


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


2,JSP 快速入门

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


2.1 搭建环境

创建一个maven的 web 项目,项目结构如下:


2209cb3f52ca445c954eb335d2e63721.png


pom.xml 文件内容如下:


<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>jsp-demo</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency></dependencies><build><plugins><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.2</version></plugin></plugins></build></project>


2.2 导入 JSP 依赖

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


<dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.2</version><scope>provided</scope></dependency>


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


2.3 创建 jsp 页面

在项目的 webapp 下创建jsp页面


dcf5505bca6a4ef49bfd2c828ecf18ee.png


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


2.4 编写代码

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


<%@pagecontentType="text/html;charset=UTF-8"language="java"%><html><head><title>Title</title></head><body><h1>hellojsp</h1><%System.out.println("hello,jsp~");
%></body></html>


2.5 测试

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


19fa8ec8e5f24611b71121b7dd2ec5a3.png


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


3,JSP 原理

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


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


浏览器第一次访问 hello.jsp 页面

tomcat 会将 hello.jsp 转换为名为 hello_jsp.java 的一个 Servlet

tomcat 再将转换的 servlet 编译成字节码文件 hello_jsp.class

tomcat 会执行该字节码文件,向外提供服务

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


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


由上面的类的继承关系可以看到继承了名为 HttpJspBase 这个类,那我们在看该类的继承关系。到资料中的找如下目录: 资料\tomcat源码\apache-tomcat-8.5.68-src\java\org\apache\jasper\runtime ,该目录下就有 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 中书写


<%System.out.println("hello,jsp~");
inti=3;
%>


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


在 hello.jsp 中书写


<%="hello"%><%=i%>


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


在 hello.jsp 中书写


<%!voidshow(){}
Stringname="zhangsan";
%>


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


4.2 案例


4.2.1 需求

使用JSP脚本展示品牌数据


说明:


在资料 资料\1. JSP案例素材 中提供了 brand.html 静态页面

在该案例中数据不从数据库中查询,而是在 JSP 页面上写死

4.2.2 实现

将资料 资料\1. JSP案例素材 中的 Brand.java 文件放置到项目的 com.itheima.pojo 包下


在项目的 webapp 中创建 brand.jsp ,并将 brand.html页面中的内容拷贝过来。brand.jsp 内容如下


<%@pagecontentType="text/html;charset=UTF-8"language="java"%><!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title></head><body><inputtype="button"value="新增"><br><hr><tableborder="1"cellspacing="0"width="800"><tr><th>序号</th><th>品牌名称</th><th>企业名称</th><th>排序</th><th>品牌介绍</th><th>状态</th><th>操作</th></tr><tralign="center"><td>1</td><td>三只松鼠</td><td>三只松鼠</td><td>100</td><td>三只松鼠,好吃不上火</td><td>启用</td><td><ahref="#">修改</a><ahref="#">删除</a></td></tr><tralign="center"><td>2</td><td>优衣库</td><td>优衣库</td><td>10</td><td>优衣库,服适人生</td><td>禁用</td><td><ahref="#">修改</a><ahref="#">删除</a></td></tr><tralign="center"><td>3</td><td>小米</td><td>小米科技有限公司</td><td>1000</td><td>为发烧而生</td><td>启用</td><td><ahref="#">修改</a><ahref="#">删除</a></td></tr></table></body></html>


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


在 brand.jsp 中准备一些数据


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


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


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


<tableborder="1"cellspacing="0"width="800"><tr><th>序号</th><th>品牌名称</th><th>企业名称</th><th>排序</th><th>品牌介绍</th><th>状态</th><th>操作</th></tr><%for (inti=0; i<brands.size(); i++) {
//获取集合中的 每一个 Brand 对象Brandbrand=brands.get(i);
     }
%><tralign="center"><td>1</td><td>三只松鼠</td><td>三只松鼠</td><td>100</td><td>三只松鼠,好吃不上火</td><td>启用</td><td><ahref="#">修改</a><ahref="#">删除</a></td></tr></table>



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


<tableborder="1"cellspacing="0"width="800"><tr><th>序号</th><th>品牌名称</th><th>企业名称</th><th>排序</th><th>品牌介绍</th><th>状态</th><th>操作</th></tr><%for (inti=0; i<brands.size(); i++) {
//获取集合中的 每一个 Brand 对象Brandbrand=brands.get(i);
%><tralign="center"><td>1</td><td>三只松鼠</td><td>三只松鼠</td><td>100</td><td>三只松鼠,好吃不上火</td><td>启用</td><td><ahref="#">修改</a><ahref="#">删除</a></td></tr><%     }
%></table>



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


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


<tableborder="1"cellspacing="0"width="800"><tr><th>序号</th><th>品牌名称</th><th>企业名称</th><th>排序</th><th>品牌介绍</th><th>状态</th><th>操作</th></tr><%for (inti=0; i<brands.size(); i++) {
//获取集合中的 每一个 Brand 对象Brandbrand=brands.get(i);
%><tralign="center"><td><%=brand.getId()%></td><td><%=brand.getBrandName()%></td><td><%=brand.getCompanyName()%></td><td><%=brand.getOrdered()%></td><td><%=brand.getDescription()%></td><td><%=brand.getStatus() ==1?"启用":"禁用"%></td><td><ahref="#">修改</a><ahref="#">删除</a></td></tr><%     }
%></table>



4.2.3 成品代码

<%@pageimport="com.itheima.pojo.Brand"%><%@pageimport="java.util.List"%><%@pageimport="java.util.ArrayList"%><%@pagecontentType="text/html;charset=UTF-8"language="java"%><%// 查询数据库List<Brand>brands=newArrayList<Brand>();
brands.add(newBrand(1,"三只松鼠","三只松鼠",100,"三只松鼠,好吃不上火",1));
brands.add(newBrand(2,"优衣库","优衣库",200,"优衣库,服适人生",0));
brands.add(newBrand(3,"小米","小米科技有限公司",1000,"为发烧而生",1));
%><!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title></head><body><inputtype="button"value="新增"><br><hr><tableborder="1"cellspacing="0"width="800"><tr><th>序号</th><th>品牌名称</th><th>企业名称</th><th>排序</th><th>品牌介绍</th><th>状态</th><th>操作</th></tr><%for (inti=0; i<brands.size(); i++) {
Brandbrand=brands.get(i);
%><tralign="center"><td><%=brand.getId()%></td><td><%=brand.getBrandName()%></td><td><%=brand.getCompanyName()%></td><td><%=brand.getOrdered()%></td><td><%=brand.getDescription()%></td><td><%=brand.getStatus() ==1?"启用":"禁用"%></td><td><ahref="#">修改</a><ahref="#">删除</a></td></tr><%        }
%></table></body></html>


4.2.4 测试

在浏览器地址栏输入 http://localhost:8080/jsp-demo/brand.jsp ,


4.3 JSP 缺点

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


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


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


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


阅读麻烦


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


复杂度高:运行需要依赖于各种环境,JRE,JSP容器,JavaEE…


占内存和磁盘:JSP会自动生成.java和.class文件占磁盘,运行的是.class文件占内存


调试困难:出错后,需要找到自动生成的.java文件进行调试


不利于团队协作:前端人员不会 Java,后端人员不精 HTML


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


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


第一阶段:使用 servlet 即实现逻辑代码编写,也对页面进行拼接。这种模式我们之前也接触过


第二阶段:随着技术的发展,出现了 JSP ,人们发现 JSP 使用起来比 Servlet 方便很多,但是还是要在 JSP 中嵌套 Java 代码,也不利于后期的维护


第三阶段:使用 Servlet 进行逻辑代码开发,而使用 JSP 进行数据展示


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


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


一些公司可能有些老项目还在用 JSP ,所以要求我们必须动 JSP

我们如果不经历这些复杂的过程,就不能体现后面阶段开发的简单

接下来我们来学习第三阶段,使用 EL表达式 和 JSTL 标签库替换 JSP 中的 Java 代码。

相关文章
|
5月前
|
NoSQL Java Shell
2025服务端java搭建篇:蜻蜓I即时通讯系统私有化部署深度指南-优雅草卓伊凡|麻子|贝贝
2025服务端java搭建篇:蜻蜓I即时通讯系统私有化部署深度指南-优雅草卓伊凡|麻子|贝贝
230 8
2025服务端java搭建篇:蜻蜓I即时通讯系统私有化部署深度指南-优雅草卓伊凡|麻子|贝贝
|
9月前
|
JavaScript NoSQL Java
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
448 96
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
|
9月前
|
前端开发 JavaScript Java
【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
438 13
【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
|
10月前
|
SQL Java API
|
SQL XML 缓存
java中jsp详解!!!
JSP(Java Server Pages)是一种动态网页技术标准,允许在HTML页面中嵌入Java代码,实现网页逻辑与设计分离。JSP本质上是Servlet的简化,支持跨平台运行。JSP通过内置对象(如request、response、session等)和指令(如page、include、taglib)提供强大的功能,同时利用EL表达式和JSTL标签库简化页面开发。JSP的核心优势在于快速开发和维护Web应用。
489 0
|
JSON Java 开发工具
Java服务端集成Google FCM推送的注意事项和实际经验
本文分享了作者在公司APP海外发布过程中,选择Google FCM进行消息推送的集成经验。文章详细解析了Java集成FCM推送的多种实现方式,包括HTTP请求和SDK集成,并指出了通知栏消息和透传消息的区别与应用场景。同时,作者还探讨了Firebase项目的创建、配置和服务端集成的注意事项,帮助读者解决文档混乱和选择困难的问题。
727 1
|
JSON Java 开发工具
Java服务端集成Google FCM推送的注意事项和实际经验
公司的app要上海外,涉及到推送功能,经过综合考虑,选择Google FCM进行消息推送。 查看一些集成博客和官方文档,看的似懂非懂,迷迷惑惑。本篇文章除了将我实际集成的经验分享出来,也会对看到的博客及其中产生的疑惑、注意事项一一评论。 从官方文档和众多博客中,你会发现Java集成FCM推送有多种实现方式,会让生产生文档很乱,不知作何选择的困惑。
365 0
|
存储 Java 关系型数据库
基于Servlet和JSP的Java Web应用开发指南
基于Servlet和JSP的Java Web应用开发指南
398 0
|
1月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
118 1
|
1月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
132 1