运行环境
系统:windows
服务器:Tomcat 8.0.50
IDEA:2021.3版本
目录
什么是jsp?
jsp页面的本质
jsp头部page指令
jsp常用脚本
声明脚本
表达式脚本
代码脚本
jsp的常用标签
静态包含
动态包含
请求转发
EL表达式
使用EL表达式输出复杂的Bean对象
EL 表达式的 11 个隐含对象
JSTL标签库
core核心库的使用
什么是jsp?
jsp的全称是java server pages,java的服务器页面。
jsp的主要作用是代替Servlet程序回传html页面的数据。
jsp页面的本质
jsp页面的本质是一个Servlet程序。
当我们第一次访问jsp页面时,Tomcat服务器会帮我们把jsp页面翻译成为一个java源文件。并且对它进行编译成源文件。
jsp程序代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
这是一个jsp页面
</body>
</html>
通过跟踪本地编译路径发现jsp页面被编译成了java文件
打开java文件,这个类继承了HttpJspBase类,而HttpJspBase类继承了HttpServlet类,所以jsp翻译出来的java类是一个Servlet程序。
翻译出来的java类通过流的形式输出页面内容。
jsp头部page指令
1. language属性:表示jsp文件翻译后是什么语言文件,暂时只支持java。
2. contentType属性:表示jsp返回的数据类型是什么,源码当中response.setContentType()属性。
3. pageEncoding属性: 表示当前jsp页面文件本身的字符集。
4. import属性:跟java源代码中一样,用于导包,导类。
5. autoFlush属性:设置当out输出流缓冲区满了之后,是否自动刷新缓冲区。默认值是true。
6. buffer属性:设置out缓冲区的大小,默认是8KB。
7. errorPage属性:设置当jsp页面运行时出错,自动跳转的错误页面路径。
8. isErrorPage属性:设置当前jsp页面是否是错误信息提示页面,默认是false。
9. session属性:设置访问当前jsp页面,是否会创建HttpSession对象,默认是true。
10. extends属性:设置jsp翻译出来的java类默认继承谁。(除非必须。默认不修改)
jsp常用脚本
声明脚本
作用:可以给jsp翻译出来的java类定义属性、方法、静态代码块、内部类等。
格式:<%! 内容 %>
jsp程序代码
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%!
//声明属性
private String id;
private String name;
private static ArrayList<Integer> arrayList;
//声明静态代码块
static {
arrayList=new ArrayList<Integer>();
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
}
//声明方法
public int add(int a, int b) {
return a + b;
}
//声明内部类
public static class student {
private String name;
private String number;
}
%>
</body>
</html>
翻译过后的java文件新增内容
表达式脚本
作用:可以在jsp页面上输出数据。
格式:<%= 内容 %>
在声明脚本的基础上输出数据
<%--输出整数--%>
<%=10%><br>
<%--输出浮点数--%>
<%=10.1234%><br/>
<%--输出字符串--%>
<%="这是一个字符串"%><br>
<%--输出对象--%>
<%=arrayList%><br>
页面显示内容
我们并没有写页面的代码,却在网页上显示出来了对应的数据。通过查看翻译后的java源文件代码发现,上面所写的代码在源文件的_jspService方法当中被翻译成了页面。
代码脚本
作用:可以在jsp页面中用java语言编写需要的功能。
格式:<% 内容 %>
特点:(1)代码脚本翻译后在_jspService方法中,所以这个方法当中的对象和属性等都可以直接使用。
(2)可以由多个代码脚本块组合完成一个完整的java语句,因为他们都是放在_jspService方法当中。
(3)代码脚本可以和表达式脚本组合使用,在jsp页面上输出数据。
代码脚本简单样例:求20以内的素数
<%
for (int i = 2; i < 20; i++) {
boolean isPrime = true;
for (int j = 2; j <= Math.sqrt(i); j++) {
if (i % j == 0) {
isPrime = false;
break;
}
}
if (isPrime == true)
System.out.println(i);
}
%>
查看翻译后的java源代码发现上面写的代码被添加在_jspService方法当中,所以我们编写代码脚本相当于是在这个方法当中编写,既然是在这个方法当中编写,那么这个方法内的参数、对象等我们都可以在代码脚本当中使用。
多个代码脚本块组合完成一个完整的java语句样例
<%for (int i = 0; i < 12; i++) {%>
<%System.out.println(i);%>
<%}%>
代码脚本可以和表达式脚本组合使用,在jsp页面上输出数据样例
<%for (int i = 0; i < 5; i++) {%>
<%=i%>
<%}%>
页面显示内容
综合运用样例:输出10×10的表格
<table border="1">
<%for (int i = 1; i <= 10; i++) {%>
<tr>
<%for (int j = 1; j <= 10; j++) {%>
<td>(<%=i%>,<%=j%>)</td>
<%}%>
</tr>
<%}%>
</table>
显示效果
输出10组学生信息
<%--css样式--%>
<%--table {--%>
<%--border: 1px red solid;--%>
<%--width: 600px;--%>
<%--border-collapse: collapse;--%>
<%--}--%>
<%
List<Student> students = new ArrayList<>();
for (int i = 0; i < 10; i++) {
students.add(new Student("name" + i, i, i + 18, "000" + i));
}
%>
<table>
<tr>
<td>姓名</td>
<td>年龄</td>
<td>编号</td>
<td>电话号码</td>
<td>操作</td>
</tr>
<% for (Student student : students) {%>
<tr>
<td><%=student.getName()%>
</td>
<td><%=student.getAge()%>
</td>
<td><%=student.getId()%>
</td>
<td><%=student.getPhone()%>
</td>
<td>删除、修改</td>
</tr>
<%}%>
显示效果
代码脚本的使用非常的灵活,通过对代码脚本和表达式脚本的灵活使用,可以实现很多功能。
jsp的常用标签
静态包含
特点:(1)静态包含不会翻译被包含的jsp页面。
(2)静态包含是将被包含的jsp页面代码拷贝到包含的位置执行输出。
当很多网页都具有相同的内容时,如果我们要修改这一部分内容,那么修改起来就显得很麻烦。如果将这一部分内容写成jsp页面代码,然后包含到不同的网页当中。我们只需要修改这一部分对应的jsp页面代码就可以对所有使用这一部分内容的页面进行修改。
简单样例
主页代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
用户名:<input type="text">
密码:<input type="password"><br>
<%--file属性指定包含的jsp页面的路径--%>
<%@ include file="/footer.jsp" %>
</body>
</html>
包含页面代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
合作伙伴:A公司、B公司、C公司
</body>
</html>
页面显示内容
动态包含
特点:(1)动态包含会将包含的jsp页面翻译成java代码。
(2)动态包含是通过代码org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "footer.jsp", out, false)来调用被包含的jsp页面执行输出。
(3)动态包含可以传递参数。
样例主页代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
用户名:<input type="text">
密码:<input type="password"><br>
<jsp:include page="footer.jsp">
<jsp:param name="username" value="root"/><!--传递参数-->
<jsp:param name="password" value="654321"/>
</jsp:include>
</body>
</html>
被包含的页面代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
合作伙伴:A公司、B公司、C公司<br>
用户名=<%=request.getParameter("username")%><!--获取参数-->
密码=<%=request.getParameter("password")%>
</body>
</html>
页面显示内容
请求转发
因为jsp本质上是一个Servlet程序,所以依然可以使用Servlet的请求转发方式。
Servlet程序请求转发写法
<%
request.getRequestDispatcher("/dtbh.jsp").forward(request,response);
%>
jsp请求转发写法
<jsp:forward page="dtbh.jsp"></jsp:forward>
实际使用方式
实际情况下在Servlet程序当中查找到了对应的数据,通过jsp页面显示出来。所以之前的示例输出10组学生信息应当这么写。
Servlet程序代码
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求的参数
//发送sql语句查询学生的信息,使用循环代替
System.out.println("DoGet");
List<Student> students = new ArrayList<>();
for (int i = 0; i < 10; i++) {
students.add(new Student("name" + i, i, i + 18, "000" + i));
}
//保存查询到的结果到request域中
req.setAttribute("students", students);
//请求转发到showStudent.jsp当中
req.getRequestDispatcher("showStudent.jsp").forward(req, resp);
}
jsp程序代码中代码脚本修改为直接获取信息即可
<%
List<Student> students = (List<Student>) request.getAttribute("students");
%>
EL表达式
EL表达式的全称是:Ecpression Language。是表达式语言。
EL表达式的作用:EL表达式主要用来代替jsp页面的表达式脚本在jsp页面中进行数据的输出,EL表达式在输出数据的时候,要比jsp的表达式脚本要简洁。
EL表达式输出和表达式脚本输出代码对比
<%
request.setAttribute("key", "值");
%>
表达式脚本输出key的值:<%= request.getAttribute("key1")%><br/>
EL表达式输出key的值:${key1}
可以发现EL表达式代码简洁明了得多。
使用EL表达式输出复杂的Bean对象
创建一个Person类自动生成get和set方法,有如下属性
代码脚本内容
<%
Person person = new Person();
person.setName("小红");
person.setPhones(new String[]{"11111", "22222", "33333"});
List<String> list = Arrays.asList(new String[]{"重庆", "西藏", "北京"});
person.setCities(list);
Map<String, Object> map = new HashMap<>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
person.setMap(map);
pageContext.setAttribute("person", person);
%>
EL表达式代码
姓名:${person.name}<br/>
第二个电话:${person.phones[1]}<br/>
城市:${person.cities}<br/>
第二个城市:${person.cities[1]}<br/>
Map:${person.map}<br/>
key2的值:${person.map.key2}<br/>
显示结果
EL表达式中的运算和java中的运算大同小异,同样也支持三元运算符。
EL 表达式的 11 个隐含对象
EL表达式中的11个隐含对象,是 EL 表达式中自己定义的,可以直接使用。
如果有多个域当中有相同的key值,那么我们要获取特定域中的key对应的value,应当指定是从哪个域中获取,如下所示:
<%
pageContext.setAttribute("key", "pageContext");
request.setAttribute("key", "request");
session.setAttribute("key", "session");
application.setAttribute("key", "application");
%>
${requestScope.key}
JSTL标签库
JSTL标签库全称是JSP standard Tag Library。是一个不断完善的开源的JSP标签库。
JSTL标签库主要用于替代代码脚本,使得整个jsp页面变得更加简洁。
使用标签库之前要导入jar包。
core核心库的使用
<c:set />标签:往域中保存数据
<%--scope设置保存到哪个域--%>
<c:set scope="request" var="key1" value="value1"/>
${requestScope.key1}
<c:if />标签:用作if条件判断
<c:if test="${12==12}">
true <%--条件为真时的逻辑--%>
</c:if>
<c:choose><c:when><c:otherwise>标签:用作多路判断,类似于swich...case...default
<%request.setAttribute("number", 200);%>
<c:choose>
<c:when test="${requestScope.number>190}">
<h1>大于190</h1>
</c:when>
<c:when test="${requestScope.number>180}">
<h1>大于180</h1>
</c:when>
<c:when test="${requestScope.number>170}">
<h1>大于170</h1>
</c:when>
<c:otherwise>
<h1>小于等于170</h1>
</c:otherwise>
</c:choose>
<c:forEach / >标签:用作遍历输出
<%--用forEach标签打印九九乘法表--%>
<table border="1">
<c:forEach begin="1" end="9" var="i">
<tr>
<c:forEach begin="1" end="${i}" var="j">
<td><c:out value="${j }*${i }=${j*i }"></c:out></td>
</c:forEach>
</tr>
</c:forEach>
</table>
<%--用forEach标签遍历字符串数组--%>
<%request.setAttribute("arr", new String[]{"11111", "22222", "33333"});%>
<c:forEach items="${requestScope.arr}" var="item">
${item}
</c:forEach>
<br/>
<%--用forEach标签遍历Map--%>
<%
Map<String, Object> map = new HashMap<>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
request.setAttribute("map", map);
// 原生java遍历方式
// for (Map.Entry<String, Object> entry : map.entrySet()) {
// System.out.println(entry.getKey() + " " + entry.getValue());
// }
%>
<c:forEach items="${requestScope.map}" var="entry">
${entry}<br/>
</c:forEach>
<%--用forEach标签遍历List集合--%>
<%
List<Student> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add(new Student("name" + i, 12 + i, "location" + i, "phone" + i, 2022 + i));
}
request.setAttribute("students", list);
%>
<table border="1">
<tr>
<th>姓名</th>
<th>年龄</th>
<th>地址</th>
<th>电话</th>
<th>编号</th>
</tr>
<%--
begin 表示开始的下标,默认开头
end 表示结束的下标,默认结尾
step 表示步长,默认为1
items 表示遍历的集合
var 表示当前遍历到的数据
--%>
<c:forEach begin="2" end="7" step="2" items="${requestScope.students}" var="student">
<tr>
<th>${student.name}</th>
<th>${student.age}</th>
<th>${student.location}</th>
<th>${student.phone}</th>
<th>${student.id}</th>
</tr>
</c:forEach>
</table>
显示效果