1. 现状
1、JSP 使用情况
2、Thymeleaf 使用情况, 通常和 SpringBoot 结合(也会讲)
3、Vue 使用情况
2. 学 JSP 前,老师要说的几句话
- 目前主流的技术是 前后端分离 (比如: Spring Boot + Vue/React), 我们会讲的.[看一下]
- JSP 技术使用在逐渐减少,但使用少和没有使用是两个意思,一些老项目和中小公司还在使用 JSP,工作期间,你很有可能遇到 JSP
- 小结:JSP 使用在减少(但是现阶段还是有必要学一下,让我们的技术栈更加全面), 我们最佳技术策略 : JSP (能基本使用,能看懂,能维护相关项目, 不用深入)
3. 为什么需要 JSP
- 程序员在开发过程中,发现 servlet 做界面非常不方便
- 引出 JSP 技术,JSP 公式
jsp=html+java 代码+标签+javascript+css
4. 官方文档
4.1 文档
java_ee_api_中英文对照版.chm
5. JSP 基本介绍
-
JSP 全称是 Java Server Pages,Java 的服务器页面(服务器渲染技术)
-
JSP 这门技术的最大的特点在于,写 JSP 就像在写 HTML
- 相比 html 而言,html 只能为用户提供静态数据,而 JSP 技术允许在页面中嵌套 java 代码,为用户提供动态数据
- 相比 Servlet 而言,Servlet 很难对数据进行排版,而 jsp 除了可以用 java 代码产 生动态数据的同时,也很容易对数据进行排版。
-
jsp 技术基于 Servlet, 你可以理解成 JSP 就是对 Servlet 的包装.
-
会使用 JSP 的程序员, 再使用 thymeleaf 是非常容易的事情, 几乎是无缝接轨.
6. JSP 快速入门
6.1 应用实例-JSP 基本使用
- 创建 hspedu_jsp WEB 项目,并引入 jar
- 创建 sum.jsp(在web目录下)
<%@ page import="java.io.PrintWriter" %>
<%@ page import="org.apache.jasper.runtime.HttpJspBase" %><%--
Created by IntelliJ IDEA.
User: 吴嘉旭
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>jsp的简单的求和计算器</title>
</head>
<body>
<h1>jsp的简单的求和计算器</h1>
<%
//解读
//1. 在jsp的 该标签中, 可以写java代码
int i = 10;
int j = 20;
int res = i + j;
//2. jsp 中内置对象,可以直接使用, 比如 out
// 小技巧:先死后活 格式化快捷键:ctrl + alt + l
// 需要引入jar包方可使用
out.println(i + " + " + j + " = " + res);
%>
<!--html注释 -->
</body>
</html>
- 启动 tomcat,并浏览器访问
6.2 注意事项和细节
- jsp 页面不能像 HTML 页面, 直接用浏览器运行。只能通过浏览器访问 Tomcat 来访问jsp 页面
- 如何设置 jsp 模板
7. JSP 运行原理
- jsp 页面本质是一个 Servlet 程序, 其性能是和 java 关联的, 只是长得丑.
- 第 1 次访问 jsp 页面的时候。Tomcat 服务器会把 jsp 页面解析成为一个 java 源文件。并 且 对 它 进 行 编 译 成 为 .class 字 节 码 程 序 。 看 下 Cal.jsp 对 应 的 cal_jsp.java 和
cal_jsp.class 文件
<%@ page import="java.io.PrintWriter" %>
<%@ page import="org.apache.jasper.runtime.HttpJspBase" %><%--
Created by IntelliJ IDEA.
User: 吴嘉旭
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>jsp的简单的求和计算器</title>
</head>
<body>
<h1>jsp的简单的求和计算器</h1>
<%
//解读
//1. 在jsp的 该标签中, 可以写java代码
int i = 10;
int j = 20;
int res = i + j;
//2. jsp 中内置对象,可以直接使用, 比如 out
// 小技巧:先死后活 ctrl + alt + l
out.println(i + " + " + j + " = " + res);
//3. 老师说明,如果要看HttpJspBase类的关系, 需要引入一个包,jasper.jar => alt+enter
//在java片段中,仍然是java的注释
String email = "xx@qq.com";
/*
多行注释
*/
HttpJspBase
%>
<%--email: <%=email%>--%>
<!--html注释 -->
</body>
</html>
- 分析下 cal_jsp.java 的源码,可以看出本质就是 Servlet, 老师给大家简单分析一把… 提醒:要看到源码和分析类图,需要加入 jasper.jar 这个包[在 tomcat/lib 下拷贝]
8. page 指令(常用的)
- language 表示 jsp 翻译后是什么语言文件, 只支持 java
- contentType 表示 jsp 返回的数据类型,对应源码中 response.setContentType()参数值
- pageEncoding 属性 表示当前 jsp 页面文件本身的字符集
- import 属性 跟 java 源代码中一样。用于导包,导类
9. JSP 三种常用脚本
9.1 声明脚本基本语法
- 声明脚本的格式是:
<%! 声明 java 代码 %>
- 作用:定义 jsp 的需要属性、方法、静态代码块和内部类等
- 应用实例:
创建 statement.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>jsp声明脚本</title>
</head>
<body>
<h1>jsp声明脚本</h1>
<%!
//这里我们可以声明该jsp需要使用的属性,方法,静态代码块, 内部类
//老师一句话: 也就是给 statement.jsp 对应的 statement_jsp 类定义成员
//1. 属性
private String name = "jack";
private int age;
private static String company;
//2 方法
public String getName() {
return name;
}
//3. 静态代码块
static {
company = "字节跳动";
}
%>
</body>
</html>
9.2 表达式脚本基本语法
- 表达式脚本的格式是:
<%=表达式%>
- 表达式脚本的作用是:在 jsp 页面上输出数据
- 表达式脚本中的表达式不能以分号结束。
9.3 表达式脚本应用实例
应用实例: 演示表达式脚本的使用
<%--
Created by IntelliJ IDEA.
User: 吴嘉旭
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>表达式脚本的使用</title>
</head>
<body>
<h1>个人信息</h1>
<%
String name = "老韩";
String email = request.getParameter("email");
%>
用户名: <%=name%><br/>
工作是: <%="java工程师"%><br/>
年龄: <%=request.getParameter("age")%><br/>
电邮: <%=email%>
</body>
</html>
9.4 代码脚本基本语法
- 代码脚本的语法是:
<% java 代码%>
- 代码脚本的作用是:可以在 jsp 页面中,编写我们需要的功能(使用 java )
- 可以由多个代码脚本块组合完成一个完整的 java 语句。
- 代码脚本还可以和表达式脚本一起组合使用,在 jsp 页面上输出数据
9.5 代码脚本应用实例
- 演示代码脚本的使用(如图)
- 创建 Monster.java
public class Monster {
private Integer id;
private String name;
private String skill;
public Monster(Integer id, String name, String skill) {
this.id = id;
this.name = name;
this.skill = skill;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSkill() {
return skill;
}
public void setSkill(String skill) {
this.skill = skill;
}
}
- 创建 java_code.jsp
<%@ page import="java.util.ArrayList" %>
<%@ page import="com.hspedu.entity.Monster" %>
<%--
Created by IntelliJ IDEA.
User: 吴嘉旭
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>演示代码脚本</title>
</head>
<body>
<h1>演示代码脚本</h1>
<%
//创建ArrayList ,放入两个monster对象
ArrayList<Monster> monsterList = new ArrayList<>();
monsterList.add(new Monster(1, "牛魔王", "芭蕉扇"));
monsterList.add(new Monster(2, "蜘蛛精", "吐口水"));
%>
<table bgcolor="#f0f8ff" border="1px" width="300px">
<tr>
<th>id</th>
<th>名字</th>
<th>技能</th>
</tr>
<%
for (int i = 0; i < monsterList.size(); i++) {
//先取出monster对象
Monster monster = monsterList.get(i);
%>
<tr>
<td><%=monster.getId()%></td>
<td><%=monster.getName()%></td>
<td><%=monster.getSkill()%></td>
</tr>
<%
}
%>
</table>
</body>
</html>
10. JSP 注释
- 演示 jsp 注释的使用
11. JSP 内置对象
● 基本介绍 [讲解]
1、JSP 内置对象(已经创建好的对象, 直接使用 inbuild),是指 Tomcat 在翻译 jsp 页面成为Servlet 后,内部提供的九大对象,叫内置对象
2、内置对象,可以直接使用,不需要手动定义
● JSP 九大内置对象
- out 向客户端输出数据,
out.println("");
- request 客户端的 http 请求
- response 响应对象
- session 会话对象
- application 对应 ServletContext
- pageContext jsp 页面的上下文,是一个域对象,可以 setAttribue(),作用范围只是本页面
- exception 异常对象 , getMessage()
- page 代表 jsp 这个实例本身
- config 对应 ServletConfig
● 对照 Servlet 来理解就比较轻松了. (老师学技术的思路: 只要去学某个类,建议熟练该类的继承关系)
-
一张图, 展示了 JSP 的父类 HttpJspBase 继承关系, 说明 JSP 内置对象的来源是 Servlet 和 HttpJspPage
-
创建 HiServlet.java
public class HiServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("HiServlet 被调用..");
//梳理 servlet中可以使用哪些对象
PrintWriter writer = response.getWriter();
writer.println("haha");
request.getParameter("age");
response.setContentType("text/html;charset=utf-8");
HttpSession session = request.getSession();
session.setAttribute("job", "java工程师90000");
//
ServletContext servletContext = request.getServletContext();
servletContext.setAttribute("count", 666);
ServletConfig servletConfig = getServletConfig();
servletConfig.getInitParameter("pwd");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
- 创建 inbuild.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>jsp内置对象</title>
</head>
<body>
<h1>jsp内置对象</h1>
<%
//梳理jsp的内置对象
//out 类型是 JspWriter 父类就是 Writer.
out.println("jsp out");
//request是HttpServletRequest
request.getParameter("age");
//response就是 HttpServletResponse
//response.sendRedirect("http://www.baidu.com");
//session 就是 HttpSession
session.setAttribute("job", "PHP工程师");
//application类型就是ServletContext
application.setAttribute("name", "老师");
//pageContext 可以存放数据(属性), 但是该数据只能在本页面使用
pageContext.setAttribute("age", 100);
//exception 异常对象 使用比较少
//page 内置对象,类似 this
out.println("page=" + page);
//config 内置对象的类型就是ServletConfig
String pwd = config.getInitParameter("pwd");
%>
</body>
age: <%=pageContext.getAttribute("age")%>
</html>
12. JSP 域对象
12.1 JSP 四大域对象介绍[作用:存取数据]
- pageContext (域对象,存放的数据只能在当前页面使用),
自己尝试去根据理解画出示意图
- request (域对象,存放的数据在一次 request 请求有效), 【示意图】
- session(域对象,存放的数据在一次会话有效), 【示意图】
- application(域对象,存放的数据在整个 web 应用运行期间有效, 范围更大), 【示意图】
12.2 应用实例
- 演示域对象(四个域对象)的使用
- 创建 scope.jsp , 在域对象中存放数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>scope文件</title>
</head>
<body>
<%
//在不同的域对象中,放入数据
//解读
//1. 因为四个域对象,是不同的对象,因此name(key) 相同时,并不会冲突
pageContext.setAttribute("k1", "pageContext数据(k1)");
request.setAttribute("k1", "request数据(k1)");
session.setAttribute("k1", "session数据(k1)");
application.setAttribute("k1", "application数据(k1)");
//做一个请求转发的操作
//路径应该怎么写,请不清楚地小伙伴,去看韩老师讲的web路径专题
//request.getRequestDispatcher("/scope2.jsp").forward(request, response);
//做一个重定向
String contextPath = request.getContextPath();//返回的就是 web路径=>/jsp
//response.sendRedirect("/jsp/scope2.jsp");
response.sendRedirect(contextPath + "/scope2.jsp");
%>
<h1>四个域对象,在本页面获取数据的情况</h1>
pageContext-k1: <%=pageContext.getAttribute("k1")%><br/>
request-k1: <%=request.getAttribute("k1")%><br/>
session-k1: <%=session.getAttribute("k1")%><br/>
application-k1: <%=application.getAttribute("k1")%><br/>
</body>
</html>
- 创建 scope2.jsp, 在域对象中读取数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>scope2.js</title>
</head>
<body>
<h1>在scope2页面获取数据的情况</h1>
pageContext-k1: <%=pageContext.getAttribute("k1")%><br/>
request-k1: <%=request.getAttribute("k1")%><br/>
session-k1: <%=session.getAttribute("k1")%><br/>
application-k1: <%=application.getAttribute("k1")%><br/>
</body>
</html>
12.3 JSP 四大域对象注意事项和细节
- 域对象是可以像 Map 一样存取数据的对象。四个域对象功能一样。不同的是它们对数据的存储范围
- 从存储范围(作用域范围看) pageContext < request < session < application
13. JSP 请求转发标签
- 演示请求转发标签使用,如图
- 创建 aa.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>aa.jsp</title>
</head>
<body>
<h1>aa.jsp</h1>
<%--老师解读
1. jsp提供了很多标签,但是因为jsp不是重点,就讲一个常用forward
2. jsp:forward 本质就是 等价 request.getRequestDispatcher("/bb.jsp").for...
--%>
<jsp:forward page="/bb.jsp"></jsp:forward>
</body>
</html>
- 创建 bb.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>bb.jsp</title>
</head>
<body>
<h1>bb.jsp页面</h1>
</body>
</html>
- 完成测试
14. 课后作业-JSP 版本的计算器
14.1 作业布置
● 需求分析: 使用 jsp 完成一个简单的计算器, 需求如图
- 要求在前端页面对输入的 num1 和 num2 进行校验【提示: 正则表达式, 如果忘了回去看 java 的正则表达式 27 章】, 必须是整数
- 验证成功, 提交数据给服务器, 能够显示结果
- 点击超链接, 可以返回界面
- 其 它 完 善 考 虑 [ 思 考 题 ]=> 如 果 用 户 这 样 提 交
http://localhost:8080/jsp/calServlet?num1=aaa&num2=90
, 需要你返回 calUI.jsp , 并给出提示信息
● 思路分析(程序框架图), 小伙伴也尝试自己设计一把.->实现->听老师评讲
14.2 实现
calUI.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>JSP计算器</title>
<!--使用js+正则表达式完成数据校验-->
<script type="text/javascript">
function check() {
//得到 num1 和 num2值
var num1 = document.getElementById("num1").value;
var num2 = document.getElementById("num2").value;
//验证 正则表达式, 整数 => 在java基础讲过 => 学习技术一定要经常回顾
//我们学习的所有java技术=> 其实都是基础组合[oop,io,反射,注解,集合,线程,网络]
var reg = /^[-]?([1-9]\d*|0)$/;
if (!reg.test(num1)) {//如果不满足验证条件
alert("num1 不是一个整数");
return false;//放弃提交
}
if (!reg.test(num2)) {//如果不满足验证条件
alert("num2 不是一个整数");
return false;//放弃提交
}
return true;//提交到action指定的位置
}
</script>
</head>
<body>
<h1>JSP计算器</h1>
<form action="<%=request.getContextPath()%>/calServlet"
method="post" onsubmit="return check()">
num1: <input type="text" id="num1" name="num1"> num1错误:xx <br/>
num2: <input type="text" id="num2" name="num2"> num2错误:xx<br/>
运算符号:
<select name="oper">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select><br/>
<input type="submit" value="提交计算">
</form>
</body>
</html>
思考与总结:
1.js的正则表达式需要使用/表达式/
不能使用双引号
2.js可以使用调用test的方法实现正则表达式或者使用字符串提供的match方法
CalServlet.java
public class CalServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("CalServlet 被调用...");
//思路 ==> 代码
//1. 是Servlet
//2. 接收数据
//String num1 = request.getParameter("num1");
//String num2 = request.getParameter("num2");
//进行转换->int
double num1 = WebUtils.parseDouble(request.getParameter("num1"), 0);
double num2 = WebUtils.parseDouble(request.getParameter("num2"), 0);
String oper = request.getParameter("oper");
double res = 0; //使用变量来接收运算结果
//3. 完成计算
if ("+".equals(oper)) {
res = num1 + num2;
} else if ("-".equals(oper)) {
res = num1 - num2;
} else if ("*".equals(oper)) {
res = num1 * num2;
} else if ("/".equals(oper)) {
res = num1 / num2;
} else {
System.out.println(oper + " 不正确...");
}
//4. 把结果保存到域对象[request, session, servletContext]
// 解读:因为一次请求对应一次计算, 所以我建议将结果保存到request
// 思路: 把结果组织到一个字符串中., 方便我们在下一个页面显示
// java基础: String.format ,可以格式化字符串
String formatRes = String.format("%s %s %s = %s", num1, oper, num2, res);
request.setAttribute("res", formatRes);
//System.out.println("formatRes= " + formatRes);
//5. 转发到显示页面 calRes.jsp
request.getRequestDispatcher("/cal/calRes.jsp").forward(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
思考与总结:
1.如果将每个数字都放到request域对象中,显得过于麻烦,可以将结果作为一个整体放到域对象中
calRes.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>计算结果</title>
</head>
<body>
<h1>计算结果</h1>
<%=request.getAttribute("res")%><br/>
<%--<a href="/jsp/cal/calUI.jsp">返回重新来玩一把</a>--%>
<a href="<%=request.getContextPath()%>/cal/calUI.jsp">返回重新来玩一把~</a>
</body>
</html>
● 完成测试