文章目录
13.1 现状
- JSP 使用情况
- Thymeleaf 使用情况, 通常和 SpringBoot 结合
- Vue 使用情况
13.2 学 JSP 前,解释一下
- 目前主流的技术是 前后端分离 (比如: Spring Boot + Vue/React),后面会学习的
- JSP 技术使用在逐渐减少,但使用少和没有使用是两个意思,一些老项目和中小公司还在使用 JSP,工作期间,很有可能遇到 JSP
- 小结:JSP 使用在减少(但是现阶段还是有必要学一下,让我们的技术栈更加全面), 我们最佳技术策略 : JSP (能基本使用,能看懂,能维护相关项目, 不用深入
13.3 为什么需要 JSP
- 程序员在开发过程中,发现 servlet 做界面非常不方便
- 引出 JSP 技术,JSP 公式
- jsp = html+java 片段+标签+javascript+css
13.4 官方文档
13.4.1 文档:java_ee_api_中英文对照版.chm
13.5 JSP 基本介绍
-
JSP 全称是 Java Server Pages,Java 的服务器页面
-
JSP 这门技术的最大的特点在于,写 JSP 就像在写 HTML
① 相比 html 而言,html 只能为用户提供静态数据,而 JSP 技术允许在页面中嵌套 java 代码,为用户提供动态数据
② 相比 Servlet 而言,Servlet 很难对数据进行排版,而 jsp 除了可以用 java 代码产生动态数据的同时,也很容易对数据进行排版
-
jsp 技术基于 Servlet,你可以理解成 JSP 就是对 Servlet 的包装
-
会使用 JSP 的程序员,再使用 thymeleaf 是非常容易的事情,几乎是无缝接轨
13.6 JSP 快速入门
13.6.1 应用实例-JSP 基本使用
- 创建 jsp WEB 项目,并引入 jar 包
- 创建 sum.jsp
<%@ page import="java.io.PrintWriter" %>
<%@ page import="org.apache.jasper.runtime.HttpJspBase" %><%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/10
Time: 8:57
--%>
<%@ 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
//小技巧:先死后活
out.print(i + " + " + j + " = " + res);
//3.特别说明,如果要看 HttpJspBase 类的关系,需要引入一个包
//HttpJspBase
%>
</body>
</html>
- 启动 tomcat,并浏览器访问
13.6.2 注意事项和细节
- jsp 页面不能像 HTML 页面,直接用浏览器运行,只能通过浏览器访问 Tomcat 来访问 jsp 页面
- 如何设置 jsp 模板
13.7 JSP 运行原理
-
jsp 页面本质是一个 Servlet 程序, 其性能是和 java 关联的, 只是长得丑
-
第 1 次访问 jsp 页面的时候:
① Tomcat 服务器会把 jsp 页面解析成为一个 java 源文件
② 并且对它进行编译成为 .class 字节码程序
③ 看下 sum.jsp 对应的 sum_jsp.java 和 sum_jsp.class 文件
- 分析下 sum_jsp.java 的源码,可以看出本质就是 Servlet ,简单分析一把…
- 特别提醒:要看到源码和分析类图,需要加入 jasper.jar 这个包[在 tomcat/lib 下拷贝]
- sum_jsp.java 的源码如下:
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/8.0.50
* Generated at: 2022-03-10 01:07:29 UTC
* Note: The last modified time of this file was set to
* the last modified time of the source file after
* generation to assist with modification tracking.
*/
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.io.PrintWriter;
public final class sum_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;
private static final java.util.Set<java.lang.String> _jspx_imports_packages;
private static final java.util.Set<java.lang.String> _jspx_imports_classes;
static {
_jspx_imports_packages = new java.util.HashSet<>();
_jspx_imports_packages.add("javax.servlet");
_jspx_imports_packages.add("javax.servlet.http");
_jspx_imports_packages.add("javax.servlet.jsp");
_jspx_imports_classes = new java.util.HashSet<>();
_jspx_imports_classes.add("java.io.PrintWriter");
}
private volatile javax.el.ExpressionFactory _el_expressionfactory;
private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public java.util.Set<java.lang.String> getPackageImports() {
return _jspx_imports_packages;
}
public java.util.Set<java.lang.String> getClassImports() {
return _jspx_imports_classes;
}
public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
if (_el_expressionfactory == null) {
synchronized (this) {
if (_el_expressionfactory == null) {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
}
}
}
return _el_expressionfactory;
}
public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
if (_jsp_instancemanager == null) {
synchronized (this) {
if (_jsp_instancemanager == null) {
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
}
}
return _jsp_instancemanager;
}
public void _jspInit() {
}
public void _jspDestroy() {
}
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
final java.lang.String _jspx_method = request.getMethod();
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD");
return;
}
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
try {
response.setContentType("text/html;charset=UTF-8");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write("\r\n");
out.write("\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write(" <title>jsp的简单求和计算器</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
out.write("<h1>jsp的简单求和计算器</h1>\r\n");
//解读
//1.在jsp该标签中,可以写Java代码
int i = 10;
int j = 20;
int res = i + j;
//2.jsp中内置了一些对象,可以直接使用,比如 out
//小技巧:先死后活
out.print(i + " + " + j + " = " + res);
out.write("\r\n");
out.write("</body>\r\n");
out.write("</html>\r\n");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
13.8 page 指令(常用的)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
- language 表示 jsp 翻译后是什么语言文件, 只支持 java
- contentType 表示 jsp 返回的数据类型,对应源码中
response.setContentType()
参数值 - pageEncoding 属性 表示当前 jsp 页面文件本身的字符集
- import 属性 跟 java 源代码中一样,用于导包,导类
13.9 JSP 三种常用脚本
13.9.1 声明脚本基本语法 statement_jsp
- 声明脚本的格式是:
<%! 声明 java 代码 %>
- 作用:定义 jsp 的需要属性、方法、静态代码块和内部类等
- 应用实例:
<%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/10
Version: 1.0
--%>
<%@ 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 = 18;
private static String company;
//2.方法
public String getName() {
return name;
}
//静态代码块
static {
company = "华为";
}
%>
</body>
</html>
13.9.2 表达式脚本基本语法
- 表达式脚本的格式是:
<%=表达式%>
- 表达式脚本的作用是:在 jsp 页面上输出数据
- 表达式脚本中的表达式不能以分号结束
13.9.3 表达式脚本应用实例 exp.jsp
- 应用实例: 演示表达式脚本的使用
- 创建 exp.jsp
<%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/10
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>
13.9.4 代码脚本基本语法
- 代码脚本的语法是:
<% java 代码%>
- 代码脚本的作用是:可以在 jsp 页面中,编写我们需要的功能 (使用 java)
- 可以由多个代码脚本块组合完成一个完整的 java 语句
- 代码脚本还可以和表达式脚本一起组合使用,在 jsp 页面上输出数据
13.9.5 代码脚本应用实例 javacode.jsp
- 演示代码脚本的使用(如图)
- 创建 Monster.java
package com.xjs.entity;
/**
* @Author: 谢家升
* @Date: 2022/3/10-03-10-13:32
* @Version: 1.0
*/
public class Monster {
private int id;
private String name;
private String skill;
public Monster(int id, String name, String skill) {
this.id = id;
this.name = name;
this.skill = skill;
}
public int getId() {
return id;
}
public void setId(int 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;
}
}
- 创建 javacode.jsp
<%@ page import="java.util.ArrayList" %>
<%@ page import="com.xjs.entity.Monster" %><%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/10
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>演示代码脚本</title>
</head>
<body>
<h1>演示代码脚本</h1>
<%
//创建一个 ArrayList,放入2个monster对象
ArrayList<Monster> monsters = new ArrayList<>();
monsters.add(new Monster(1, "牛魔王", "芭蕉扇"));
monsters.add(new Monster(2, "蜘蛛精", "吐口水"));
%>
<table border="1px" bgcolor="#faebd7" width="500px" cellspacing="0px">
<tr>
<th>id</th>
<th>name</th>
<th>skill</th>
</tr>
<%
for (int i = 0; i < monsters.size(); i++) {
//先取出monster对象
Monster monster = monsters.get(i);
%>
<tr align="center">
<td><%=monster.getId()%></td>
<td><%=monster.getName()%></td>
<td><%=monster.getSkill()%></td>
</tr>
<%
}
%>
</table>
</body>
</html>
13.10 JSP 注释
- 演示 jsp 注释的使用
13.11 JSP 内置对象
- 基本介绍
- JSP 内置对象(已经创建好的对象,直接使用 inbuild),是指 Tomcat 在翻译 jsp 页面成为 Servlet 后,内部提供的九大对象,叫内置对象
- 内置对象,可以直接使用,不需要手动定义
- 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
package com.xjs.servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @Author: 谢家升
* @Date: 2022/3/12-03-12-14:18
* @Version: 1.0
*/
public class HiServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("HiServlet 被调用...");
//梳理:在servlet中可以使用哪些对象
//1.writer
PrintWriter writer = response.getWriter();
writer.print("hello");
//2.request
String age = request.getParameter("age");
//3.response
response.setContentType("text/html;charset=utf-8");
//4.HttpSession
HttpSession session = request.getSession();
session.setAttribute("job","Java工程师");
//5.ServletContext
ServletContext servletContext = request.getServletContext();
servletContext.setAttribute("count",666);
//6.ServletConfig
ServletConfig servletConfig = getServletConfig();
String pwd = servletConfig.getInitParameter("pwd");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
- 创建 inbuild.jsp
<%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/12
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>jsp内置对象</title>
</head>
<body>
<h1>jsp内置对象</h1>
<%
//梳理:jsp的内置对象
//(1) out 类型是 JspWriter 父类就是Writer
out.print("jsp out");
//(2) request 的类型是 HttpServletRequest
String age = request.getParameter("age");
//(3) response 的类型是 HttpServletResponse
//response.sendRedirect("http://www.baidu.com");
//(4) session 的类型是 HttpSession
session.setAttribute("salary",90000);
//(5) application 的类型是ServletContext
application.setAttribute("count",999);
//(6) pageContext 可以存放数据(属性),但是该数据只能在本页面使用
pageContext.setAttribute("age",100);
//(7) exception 异常对象,使用比较少
//(8) page 内置对象,类似 this
out.print("page= "+page);
//(9) config 的类型就是 ServletConfig
String pwd = config.getInitParameter("pwd");
%>
<h1>age: <%=pageContext.getAttribute("age")%></h1>
</body>
</html>
13.12 JSP 域对象
13.12.1 JSP 四大域对象介绍[作用:存取数据]
- pageContext (域对象,存放的数据只能在当前页面使用),学习技术小技巧: 自己尝试去根据理解画出示意图
- request (域对象,存放的数据在一次 request 请求有效)
- session(域对象,存放的数据在一次会话有效)
- application(域对象,存放的数据在整个 web 应用运行期间有效,范围更大)
13.12.2 应用实例 scope.jsp scope2.jsp [运行]
- 演示域对象(四个域对象)的使用
- 创建 scope.jsp ,在域对象中存放数据
<%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/12
Version: 1.0
--%>
<%@ 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)");
//做一个请求转发
//request.getRequestDispatcher("/scope2.jsp").forward(request,response);
//做一个重定向 /jsp/scope2.jsp
//String contextPath = application.getContextPath();
response.sendRedirect(application.getContextPath() + "/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, 在域对象中读取数据
<%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/12
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>scope2</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>
13.12.3 JSP 四大域对象注意事项和细节
- 域对象是可以像 Map 一样存取数据的对象。四个域对象功能一样。不同的是它们对数据的存储范围
- 从存储范围(作用域范围看) pageContext < request < session < application
13.13 JSP 请求转发标签
- 演示请求转发标签使用,如图
- 创建 aa.jsp
<%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/12
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>jap请求转发标签</title>
</head>
<body>
<h1>aa.jsp</h1>
<%--解读:
1.jsp提供了很多标签,但是因为jsp不是重点,这里就先学习一个请求转发
2.jsp:forward 本质就是 等价 request.getRequestDispatcher("/bb.jsp").forward(request,response);
--%>
<jsp:forward page="/bb.jsp"></jsp:forward>
</body>
</html>
- 创建 bb.jsp
<%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/12
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>bb.jsp</title>
</head>
<body>
<h1>bb.jsp 页面</h1>
</body>
</html>
- 完成测试
13.14 课后作业-JSP 版本的计算器
13.14.1 作业布置
-
需求分析:使用 jsp 完成一个简单的计算器
- 要求在前端页面对输入的 num1 和 num2 进行校验【提示: 正则表达式】,要求必须是整数
- 验证成功,提交数据给服务器,能够显示结果
- 点击超链接,可以返回界面
- 其他完善考虑【思考题】
- 如果用户这样提交 http://localhost:8080/jsp/calServlet?num1=aaa&num2=90
- 需要你返回到 calUI.jsp,并给出提示信息
思路分析(程序框架图)
- calUI.jsp
<%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/12
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>JSP计算器</title>
<%--验证表单数据格式--%>
<script type="text/javascript">
var check = function () {
//获取dom对象
var num1 = document.getElementById("num1").value;
var num2 = document.getElementById("num2").value;
var regExp = /^[-]?([1-9]\d*|0)$/;
if (!regExp.test(num1)) {
alert("num1格式有误,请重新输入...")
return false;
}
if (!regExp.test(num2)) {
alert("num2格式有误,请重新输入...")
return false;
}
return true;
}
</script>
</head>
<body>
<h1>JSP计算器</h1>
<form action="/jsp/calServlet" onsubmit="return check()" method="post">
num1: <input type="text" id="num1" name="num1"><br/><br/>
num2: <input type="text" id="num2" name="num2"><br/><br/>
运算符号:
<select name="operation">
<option>+</option>
<option>-</option>
<option>*</option>
<option>/</option>
</select><br/><br/>
<input type="submit" value="计算">
</form>
</body>
</html>
- calServlet.java
package com.xjs.servlet;
import com.xjs.utils.WebUtils;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* @Author: 谢家升
* @Date: 2022/3/12-03-12-16:38
* @Version: 1.0
*/
public class CalServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("CalServlet 被调用...");
//获取请求的参数
String strNum1 = request.getParameter("num1");
String strNum2 = request.getParameter("num2");
String operation = request.getParameter("operation");
//将参数转成double
int num1 = WebUtils.parseInt(strNum1, 0);
int num2 = WebUtils.parseInt(strNum2, 0);
double res = 0.0;
//进行计算
if ("+".equals(operation)) {
res = num1 + num2;
} else if ("-".equals(operation)) {
res = num1 - num2;
} else if ("*".equals(operation)) {
res = num1 * num2;
} else if ("/".equals(operation)) {
try {
res = (double) num1 / num2;
} catch (Exception e) {
System.out.println("除数 num2 不能为0");
}
} else {
System.out.println("你输入的运算符有误...");
}
String resFormat = String.format("%s %s %s = %s", num1, operation, num2, res);
//把结果保存到request域对象中
request.setAttribute("res",resFormat);
//请求转发到 calRes.jsp 页面
request.getRequestDispatcher("/cal/calRes.jsp").forward(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
- calRes.jsp
<%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/12
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>计算结果</title>
</head>
<body>
<h1>计算结果</h1><br/>
<%
Object res = request.getAttribute("res");
out.print(res);
%>
<br/><br/>
<a href="/jsp/cal/calUI.jsp">返回再来玩一次</a>
</body>
</html>
- 工具类 WebUtils.java
package com.xjs.utils;
/**
* @Author: 谢家升
* @Date: 2022/3/12-03-12-16:56
* @Version: 1.0
*/
public class WebUtils {
//将字符串数字转成int
public static int parseInt(String strNum, int defaultVal) {
try {
return Integer.parseInt(strNum);
} catch (NumberFormatException e) {
System.out.println(strNum + " 不能转成整数...");
}
return defaultVal;
}
//将字符串数字转成double
public static Double parseDouble(String strNum, Double defaultVal) {
try {
return Double.parseDouble(strNum);
} catch (NumberFormatException e) {
System.out.println(strNum + " 不能转成double...");
}
return defaultVal;
}
//加法运算
public static int add(int num1, int num2) {
return num1 + num2;
}
//减法运算
public static int sub(int num1, int num2) {
return (num1 - num2);
}
//乘法
public static int multiplication(int num1, int num2) {
return num1 * num2;
}
//除法
public static int division(int num1, int num2) {
try {
return num1 / num2;
} catch (Exception e) {
System.out.println("分母不能为0");
}
return 0;
}
}
13.15 EL表达式【会使用】
13.15.1 EL 表达式介绍
- EL 表达式全称:Expression Language,是表达式语言
- EL 表达式主要是代替 jsp 页面的表达式脚本
<%=request.getAttribute("xx")%>
- EL 表达式输出数据的时,比 jsp 的表达式脚本简洁
- EL 表达式基本语法:
${key1}
, 你可以理解就是一个语法糖
13.15.2 EL 表达式快速入门
- 快速入门案例 el_qs.jsp
<%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/13
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>el表达式快速入门</title>
</head>
<body>
<h1>el表达式快速入门</h1>
<%
request.setAttribute("name", "谢家升");
%>
<%--解读
1.如果name是 null,request.getAttribute("name") 返回的是 "null"字符串
2.如果name是 null,${name} 返回的是 ""
--%>
<h1>jsp表达式</h1>
name= <%=request.getAttribute("name") == null ? "" : request.getAttribute("name")%><br/>
<h1>el 表达式</h1>
name= ${name}
</body>
</html>
- EL 表达式在输出 null 时,输出的是
""
- jsp 表达式脚本输出 null 的时,输出的是 “null” 字符串
13.15.3 EL 常用输出形式
13.15.3.1 EL 表达式常用输出 Bean 的普通属性、 数组属性、List 集合属性和 map 集合属性
13.15.3.2 EL 常用输出应用实例
- 演示 EL 常用输出使用
- 创建 Book.java
```java
package com.xjs.entity;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* @Author: 谢家升
* @Date: 2022/3/13-03-13-13:50
* @Version: 1.0
*/
public class Book {
private String name;//书名
private String[] writer;//作者
private List<String> reader;//读者
private Map<String, String> topics;//话题/评价
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String[] getWriter() {
return writer;
}
public void setWriter(String[] writer) {
this.writer = writer;
}
public List<String> getReader() {
return reader;
}
public void setReader(List<String> reader) {
this.reader = reader;
}
public Map<String, String> getTopics() {
return topics;
}
public void setTopics(Map<String, String> topics) {
this.topics = topics;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", writer=" + Arrays.toString(writer) +
", reader=" + reader +
", topics=" + topics +
'}';
}
}
- 创建 el_output.jsp
<%@ page import="com.xjs.entity.Book" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.HashMap" %><%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/13
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>el 表达式输出数据演示</title>
</head>
<body>
<h1>el 表达式输出数据演示</h1>
<%
//创建Book对象,放入相关的属性
Book book = new Book();
//private String name;//书名
//private String[] writer;//作者
//private List<String> reader;//读者
//private Map<String, String> topics;//话题/评价
book.setName("昆虫总动员");
String[] writer = new String[]{"jack","tom"};
book.setWriter(writer);
List<String> readers = new ArrayList<>();
readers.add("老韩");
readers.add("小谢");
book.setReader(readers);
HashMap<String, String> topics = new HashMap<>();
topics.put("topic1","这是一部非常优秀的作品");
topics.put("topic2","给我带来了许多快乐,必须好评~~");
book.setTopics(topics);
//把book放入到request域对象中
request.setAttribute("bookKey",book);
%>
<%-- ${book.name} 调用的就是 getName() --%>
book对象:${bookKey}<br/>
book.name= ${bookKey.name}<br/>
book.writer= ${bookKey.writer}<br/> <%--数组没有遍历所以输出的是一个对象--%>
book.reader= ${bookKey.reader}<br/>
book.reader第2个= ${bookKey.reader.get(1)}<br/>
book.reader第2个= ${bookKey.reader[1]}<br/>
book.topic= ${bookKey.topics}<br/>
<%--注意map取法有点奇特--%>
book.topic第1个= ${bookKey.topics["topic1"]}<br/>
</body>
</html>
13.15.4 EL 运算操作
-
基本语法语法:
${ 运算表达式 }
-
关系运算
关系运算符 | 说明 | 范例 | 结果 |
---|---|---|---|
== 或 eq | 等于 | $ { 5 == 5 } 或 $ { 5 eq 5 } | true |
!= 或 ne | 不等于 | $ { 5 != 5 } 或 $ { 5 ne 5 } | false |
< 或 lt | 小于 | $ { 3 < 5 } 或 $ { 3 lt 5 } | true |
> 或 gt | 大于 | $ { 3 > 5 } 或 $ { 3 gt 5 } | false |
<= 或 le | 小于等于 | $ { 3 <= 5 } 或 $ { 3 le 5 } | true |
>= 或 ge | 大于等于 | $ { 3 >= 5 } 或 $ { 3 ge 5 } | false |
- 逻辑运算
逻辑运算符 | 说明 | 范例 | 结果 |
---|---|---|---|
&& 或 and | 与运算 | $ { 12 == 12 && 12 < 11 } 或 $ { 12 == 12 and 12 < 11 } | false |
|| 或 or | 或运算 | $ { 12 == 12 || 12 < 11 } 或 $ { 12 == 12 or 12 < 11 } | true |
! 或 not | 取反运算 | $ { !true } 或 $ { not true } | false |
- 算数运算
算数运算符 | 说明 | 范例 | 结果 |
---|---|---|---|
+ | 加法 | $ { 12 + 18 } | 30 |
- | 减法 | $ { 18 + 8 } | 10 |
* | 乘法 | $ { 12 * 12 } | 144 |
/ 或 div | 除法 | $ { 144 / 12 } 或 $ { 144 div 12 } | 12 |
% 或 mod | 取模 | $ { 144 % 10 } 或 $ { 144 mod 10 } | 4 |
13.15.5 EL 的 empty 运算
-
empty 运算可以判断一个数据是否为空,如果为空,返回 true,否则返回 false
-
以下几种情况为空
● 值为 null
● 值为空串的时
● 值是 Object 类型数组,长度为零
● list 集合,元素个数为零
● map 集合,元素个数为零 -
应用实例 el_empty.jsp
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.HashMap" %><%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/13
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>empty 的运算</title>
</head>
<body>
<h1>empty 的运算</h1>
<%
request.setAttribute("k1", null);
request.setAttribute("k2", "");
request.setAttribute("k3", new Object[]{});
request.setAttribute("k4", new ArrayList<>());
request.setAttribute("k5", new HashMap<>());
//演示三元运算符
request.setAttribute("score",80);
%>
k1是否为空= ${empty k1}<br/>
k2是否为空= ${empty k2}<br/>
k3是否为空= ${empty k3}<br/>
k4是否为空= ${empty k4}<br/>
k5是否为空= ${empty k5}<br/><hr/>
成绩是否及格:${score > 60 ? "及格":"不及格"}
</body>
</html>
13.15.6 EL 的三元运算
- 表达式 1?表达式 2: 表达式
- 如果表达式 1 的值为真,返回表达式 2 的值,反之,返回表达式 3 的值
- 应用实例
<%
//演示三元运算符
request.setAttribute("score",80);
%>
成绩是否及格:${score > 60 ? "及格":"不及格"}
13.15.7 EL 的 11 个隐含对象
13.15.7.1 EL 的 11 个隐含对象,可以直接使用
13.15.7.2 EL 获取四个特定域中的属性
- EL 四个特定域变量
- 应用实例 创建 el_scope.jsp
<%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/13
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>演示 el 的四个常用隐藏对象(域对象)</title>
</head>
<body>
<h1>演示 el 的四个常用隐藏对象(域对象)</h1>
<%
request.setAttribute("k1","request-k1数据");
pageContext.setAttribute("k1","pageContext-k1数据");
session.setAttribute("k1","session-k1数据");
application.setAttribute("k1","application-k1数据");
%>
<h1>jsp脚本方式获取</h1>
request域中的k1= <%=request.getAttribute("k1")%>
<h1>el方式来获取域对象的数据</h1>
request域中的k1= ${requestScope.k1}<br/>
pageContext域中的k1= ${pageScope.k1}<br/>
session域中的k1= ${sessionScope.k1}<br/>
application域中的k1= ${applicationScope.k1}<br/>
</body>
</html>
13.15.7.3 pageContext 对象的使用
- pageContext 对象介绍
- 应用实例 创建 el_pc.jsp
<%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/13
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>pageContext对象的使用</title>
</head>
<body>
<h1>pageContext 对象的使用</h1>
<%--
//通过request对象来获取和HTTP协议相关的数据
request.getScheme() 它可以获取请求的协议
request.getServerName() 获取请求的服务器 ip 或域名
request.getServerPort() 获取请求的服务器端口号
getContextPath() 获取当前工程路径
request.getMethod() 获取请求的方式(GET 或 POST)
request.getRemoteHost() 获取客户端的 ip 地址
session.getId() 获取会话的唯一标识
--%>
<hr/>
<%--解读:
1.我们可以通过pageContext.request.xx 俩获取和http协议相关的信息
2.相当于替代 request.getMethod()....
--%>
协议: ${ pageContext.request.scheme }<br>
服务器 ip:${ pageContext.request.serverName }<br>
服务器端口:${ pageContext.request.serverPort }<br>
工程路径:${ pageContext.request.contextPath }<br>
请求方法:${ pageContext.request.method }<br>
客户端 ip 地址:${ pageContext.request.remoteHost }<br>
会话id :${ pageContext.session.id }<br>
<h1>使用jsp表达式脚本获取如上信息</h1>
ip地址: <%=request.getRemoteHost() %> <br>
<h1>使用el表达式形式获取信息-简化写法</h1>
<%
pageContext.setAttribute("req", request);
%>
ip地址(简化获取): ${req.remoteHost} <br>
获取请求方法(简化获取): ${req.method} <br>
</body>
</html>
13.16 JSTL【会使用】
13.16.1 JSTL 标签库介绍
- JSTL 标签库 是指 JSP Standard Tag Library ----- JSP 标准标签库
- EL 表达式是为了替换 jsp 中的表达式脚本,JSTL 是为了替换代码脚本。这样 jsp 页面变得更佳简洁
- JSTL 由五个标签库组成
- 使用 JSTL,需要导入相关的 jar 包
- 特别提醒:导入 jstl jar 包后,要重新发布 web ,否则不识别 jstl
13.16.2 JSTL 快速入门
- 快速入门案例 创建 jstl_quick_start.jsp
<%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/13
Version: 1.0
--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>jstl的快速入门</title>
</head>
<body>
<h1>jstl的快速入门</h1>
<%--解读
1. c:if ... 类似
2. if(10>2){
out.println("<h1>10 > 2 成立~</h1>")
}
--%>
<c:if test="${10>2}">
<h1>10 > 2 成立~~</h1>
</c:if>
</body>
</html>
-
注意细节
● taglib 引入标签,要放在行首
● 导入 jstl jar 包后,要重新发布 web ,否则不识别 jstl
13.16.3 core 核心库
13.16.3.1 <c:set />
- 介绍:
<c:set scope="request" var="name" value="谢家升~~"></c:set>
- 应用实例:创建 c_set.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/13
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>c:set标签的使用</title>
</head>
<body>
<h1>c:set标签的使用</h1>
<%--<%--%>
<%-- request.setAttribute("name","谢家升");--%>
<%--%>--%>
<%--解读
<c:set /> set 标签可以往域中保存数据
1. 等价 域对象.setAttribute(key,value);
2. scope 属性设置保存到哪个域
page 表示 PageContext 域(默认值)
request 表示 Request 域
session 表示 Session 域
application 表示 ServletContext 域
3. var 属性设置 key 是什么
4. value 属性设置值
--%>
<c:set scope="request" var="name" value="谢家升~~"></c:set>
c:set-name的值= ${requestScope.name}
</body>
</html>
13.16.3.2 <c:if />
- 介绍:
<c:if test="${ 10 > 2 }">hello</c:if>
- 应用实例 创建 c_if.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/13
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>c:if标签的使用</title>
</head>
<body>
<h1>c:if标签的使用</h1>
<c:set scope="request" var="num1" value="20"></c:set>
<c:set scope="request" var="num2" value="10"></c:set>
<c:if test="${num1 > num2}">
<h1>${num1} > ${num2}</h1>
</c:if>
</body>
</html>
13.16.3.3 <c:choose> <c:when> <c:otherwise>标签
- 介绍: 多路判断。跟 switch … case … default 非常接近
- 应用实例 创建 c_choose.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/13
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>c:choose标签的使用</title>
</head>
<body>
<h1>c:choose标签的使用</h1>
<%
request.setAttribute("score",90);
request.setAttribute("k1", "request-k1的值");
session.setAttribute("k1", "session-k1的值");
application.setAttribute("k1", "application-k1的值");
pageContext.setAttribute("k1", "pageContext-k1的值~");
%>
<%--多说一句:
1. 如果${requestScope.score} 那么就明确的指定从request域对象取出数据
2. 如果${score}, 这是就按照从小到大的域范围去获取 pageContext->request->session->application
3. 一会验证一把.
--%>
${k1}
<c:choose>
<c:when test="${requestScope.score > 80}">
<h1>${score}成绩优秀</h1>
</c:when>
<c:when test="${requestScope.score > 60}">
<h1>${score}成绩及格</h1>
</c:when>
<c:otherwise>
<h1>${score}没有及格,下次努力~~</h1>
</c:otherwise>
</c:choose>
</body>
</html>
13.16.3.4 <c:forEach />标签
-
介绍: c:forEach 标签 用来遍历输出, 主要有 4 种形式:
● 普通遍历输出 i 到 j
● 遍历数组
● 遍历 Map
● 遍历 List -
应用实例 创建 c_foreach.jsp
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.Map" %>
<%@ page import="com.xjs.entity.Monster" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/13
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>c:forEach 标签</title>
</head>
<body>
<h1>c:forEach 标签</h1>
<hr/>
<h1>第1种遍历方式从i到j</h1>
<ul>
<%--
1.遍历 1 到 5,
2. 输出 begin 属性设置开始的索引 end 属性设置结束的索引
3. var 属性表示循环的变量(也是当前正在遍历到的数据)
4. 等价 for (int i = 1; i <= 5; i++) {}
5. 在默认情况下, i 每次会递增1
--%>
<c:forEach begin="1" step="2" end="5" var="i">
<li>排名${i}</li>
</c:forEach>
</ul>
<hr/>
<h1>第2种遍历方式:遍历数组</h1>
<%
request.setAttribute("sports", new String[]{"打篮球", "乒乓球"});
%>
<%--
<c:forEach items="${ requestScope.sports }" var="item"/>
1. items 遍历的集合/数组
2. var 遍历到的数据
3. 等价 for (Object sport: sports) {}
--%>
<c:forEach items="${requestScope.sports}" var="sport">
运动名称:${sport}<br/>
</c:forEach>
<hr/>
<h1>第3种遍历方式:遍历Map</h1>
<%
Map<String, Object> map = new HashMap<>();
map.put("key1", "北京");
map.put("key2", "上海");
map.put("key3", "天津");
request.setAttribute("cities", map);
%>
<%--
1. items 遍历的map集合
2. var 遍历到的数据
3. entry.key 取出key
4. entry.value 取出值
--%>
<c:forEach items="${requestScope.cities}" var="city">
城市信息:${city.key}--${city.value}<br/>
</c:forEach>
<hr/>
<h1>第4种遍历方式:遍历List</h1>
<%
List<Monster> monsters = new ArrayList<>();
monsters.add(new Monster(100, "小妖怪", "巡山的"));
monsters.add(new Monster(200, "大妖怪", "做饭的"));
monsters.add(new Monster(300, "老妖怪", "打扫卫生的"));
request.setAttribute("monsters", monsters);
%>
<%--
items 表示遍历的集合
var 表示遍历到的数据
begin 表示遍历的开始索引值 ,从0开始计算
end 表示结束的索引值
step 属性表示遍历的步长值
varStatus 属性表示当前遍历到的数据的状态,可以得到step,begin,end等属性值
//特别提示, 对于jstl标签,能看懂,会使用即可
--%>
<c:forEach items="${requestScope.monsters}" var="monster">
妖怪的信息:${monster.id}--${monster.name}--${monster.skill}<br/>
</c:forEach>
</body>
</html>
13.16.4 JSTL+EL 作业
13.16.4.1 作业布置
-
需求分析:使用 jsp+servlet+jstl+el 完成查询-显示案例,需求如图
① 点击超链接, 可以显示所有的妖怪信息
② 要求显示的数据在 Servlet 准备,并放入到 request 域对象
③ 扩展,如果要求增加根据 id 条件过滤,怎么处理?
- 创建 query.jsp
<%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/13
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>查询妖怪</title>
</head>
<body>
<h1>查询妖怪</h1>
<a href="<%=request.getContextPath()%>/queryServlet">点击查询所有妖怪</a>
</body>
</html>
- 创建 Monster.java
package com.xjs.entity;
/**
* @Author: 谢家升
* @Date: 2022/3/10-03-10-13:32
* @Version: 1.0
*/
public class Monster {
private int id;
private String name;
private String skill;
public Monster(int id, String name, String skill) {
this.id = id;
this.name = name;
this.skill = skill;
}
public int getId() {
return id;
}
public void setId(int 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;
}
}
- 创建 QueryServlet.java
package com.xjs.servlet;
import com.xjs.entity.Monster;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
/**
* @Author: 谢家升
* @Date: 2022/3/13-03-13-19:51
* @Version: 1.0
*/
public class QueryServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("QueryServlet 被调用...");
//创建一个集合,存放monster
ArrayList<Monster> monsters = new ArrayList<>();
monsters.add(new Monster(1, "小钻风", "巡山的"));
monsters.add(new Monster(2, "大钻风", "做饭的"));
monsters.add(new Monster(3, "总钻风", "监督的"));
monsters.add(new Monster(4, "老钻风", "按摩的"));
//将monsters保存到request域中,供jsp页面使用
request.setAttribute("monsters", monsters);
//请求转发到show.jsp页面
request.getRequestDispatcher("/homework/show.jsp").forward(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
- 创建 show.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: 谢家升
Date: 2022/3/13
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>show</title>
</head>
<body>
<h1>妖怪信息如下</h1>
<table border="1px" bgcolor="#ffe4c4" width="500px" cellspacing="0px">
<tr>
<th>id</th>
<th>name</th>
<th>skill</th>
</tr>
<c:forEach items="${requestScope.monsters}" var="monster">
<c:if test="${monster.id <= 4}">
<tr align="center">
<td>${monster.id}</td>
<td>${monster.name}</td>
<td>${monster.skill}</td>
</tr>
</c:if>
</c:forEach>
</table>
</body>
</html>