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 实现功能,看存在什么问题。如下图所示,当我们登陆成功后,需要在页面上展示用户名
上图的用户名是动态展示,也就是谁登陆就展示谁的用户名。只用 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 搭建环境
创建一个maven的 web 项目,项目结构如下:
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页面
通过上面方式创建一个名为 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,我们可以在页面上看到如下内容
同时也可以看到在 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 代码。