jsp
在Servlet中输出html代码,特别是稍微复杂一点的html代码,会很麻烦。
JSP
能够直接使用Html
代码,然后在html
中写java
代码
e.g.
<%@page contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*" %>
<%--是JSP的`<%@page`指令--%>
<%--通知浏览器以UTF-8进行中文解码--%>
<%--导入其他类,如果导入多个类,彼此用逗号隔开, 像:import="java.util.*,java.sql.*"--%>
你好 JSP
<br>
<%=new Date().toLocaleString()%> //输出当前时间,相当于在Servlet中使用response.getWriter()进行输出
为什么JSP可以在html中运行java代码? 这是因为JSP被转译成了Servlet
执行过程
-
把
hello.jsp
转译为hello_jsp.java
-
hello_jsp.java
位于\tomcat\work\Catalina\localhost\_\org\apache\jsp
-
hello_jsp.java
是一个servlet
-
把
hello_jsp.java
编译为hello_jsp.class
-
执行
hello_jsp
,生成html
转译hello.jsp
后得到的hello_jsp.java
继承了类org.apache.jasper.runtime.HttpJspBase
而HttpJspBase
继承了HttpServlet
转译目录:D:\ProgramFiles\tomcat_8080\work\Catalina\localhost\_\org\apache\jsp
jsp
页面元素
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BMSycJus-1640150904018)(D:\photo\photolibrary\1657.png)]
-
静态内容
就是html,css,javascript
等内容 -
指令
以<%@
开始%>
结尾,比如<%@page import="java.util.*"%>
-
表达式
<%= %>
用于输出一段html
-
Scriptlet
在<% %>
之间,可以写任何java
代码 -
声明
在<%!%> 之间可以声明字段或者方法。但是不建议这么做 -
动作
<jsp:include page="Filename"/>
在jsp
页面中包含另一个页面 -
注释
<%-- --%>
不同于 html的注释<!-- -->
通过jsp的注释,浏览器也看不到相应的代码,相当于在servlet中注释掉了
<%=%>
和 <%out.println()%>
<%="hello jsp"%>
就相当于
<%out.println("hello jsp");%>
out是jsp的隐式对象,可以直接使用。一共有9种隐式对象
注: <%=%> 不需要分号结尾,<%%> 需要以分号结尾,和java代码一样
e.g.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*"%>
<%="hello jsp"%>
<br>
<% out.println("hello jsp");%>
两种写法均可
更多的e.g.
<table width="200px" align="center" border="1" cellspacing="0">
<%for (String word : words) {%>
<tr>
<td><%=word%></td>
</tr>
<%}%>
</table>
运用<% %>写Java代码实现for循环
jsp include
每个网页的最下方都有 版权声明等信息。 如果不使用包含,那么每个网页都需要单独写,如果版权声明要修改,则需要很大的工作量。
使用include
的办法,只需要准备一个footer.jsp
,然后在其他页面包含footer.jsp
即可。
<%@include file="footer.jsp" %>
e.g.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*"%>
你好 JSP
<%@include file="footer.jsp" %>
<jsp:include page="footer.jsp" />
e.g.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*"%>
你好 JSP
<jsp:include page="footer.jsp" />
指令include:footer.jsp的内容会被插入到 hello.jsp 转译 成的hello_jsp.java中,最后只会生成一个hello_jsp.java文件
动作include:footer.jsp的内容不会被插入到 hello.jsp 转译 成的hello_jsp.java中,还会有一个footer_jsp.java独立存在。
jsp
的客户端跳转和Servlet
中是一样的
- 客户端跳转(网站不跳转)
servlet
中:
response.sendRedirect("hello.jsp");
jsp
中:
<%
response.sendRedirect("hello.jsp");
%>
- 服务端跳转(网址也跳转)
request.getRequestDispatcher("hello.jsp").forward(request, response);
或者使用动作
<jsp:forward page="hello.jsp"/>
cookie
有的网站,登陆的时候,会出现一个选项,问你是否要一周内或者一个月内保持登陆状态。
如果你选了,那么一周之内,都不需要再输入账号密码。这个功能,就是靠cookie来实现的
Cookie是一种浏览器和服务器交互数据的方式。
Cookie是由服务器端创建,但是不会保存在服务器。
创建好之后,发送给浏览器。浏览器保存在用户本地。
下一次访问网站的时候,就会把该Cookie发送给服务器。
创建cookie
的jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="javax.servlet.http.Cookie"%>
<%
Cookie c = new Cookie("name", "Gareen");
c.setMaxAge(60 * 24 * 60); <%--表示这个cookie可以保留一天,如果是0,表示浏览器一关闭就销毁 --%>
c.setPath("/"); <%--Path表示访问服务器的所有应用都会提交这个cookie到服务端,如果其值是 /a, 那么就表示仅仅访问 /a 路径的时候才会提交 cookie--%>
response.addCookie(c); <%--通过response把这个cookie保存在浏览器端--%>
%>
<a href="getCookie.jsp">跳转到获取cookie的页面</a>
session
Session
对应的中文翻译是会话。
会话指的是从用户打开浏览器访问一个网站开始,无论在这个网站中访问了多少页面,点击了多少链接,都属于同一个会话。 直到该用户关闭浏览器为止,都属于同一个会话。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RIkC2Mmz-1640150904020)(D:\photo\photolibrary\1673.png)]
JSP4个作用域
pageContext 当前页面
requestContext 一次请求
sessionContext 当前会话
applicationContext 全局,所有用户共享
- pageContext
pageContext
表示当前页面作用域. 通过pageContext.setAttribute(key,value)
的数据,只能在当前页面访问,在其他页面就不能访问了。
setContext.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
pageContext.setAttribute("name","gareen");
%>
<%=pageContext.getAttribute("name")%>
getContent.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%=pageContext.getAttribute("name")%>
getContent.jsp
无法获得setContext.jsp的数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7pSwBbE3-1640150904021)(D:\photo\photolibrary\1678.png)]
- requestContext
表示一次请求。随着本次请求结束,其中的数据也就被回收。
常用写法是
request.setAttribute("name","gareen");
request.getAttribute("name")
但是也可以用pageContext
来做,写成
pageContext.setAttribute("name","gareen",pageContext.REQUEST_SCOPE);
pageContext.getAttribute("name",pageContext.REQUEST_SCOPE)
requestContext
指的是一次请求
如果发生了服务端跳转,从setContext.jsp
跳转到getContext.jsp
,这其实,还是一次请求。 所以在getContext.jsp
中,可以取到在requestContext
中设置的值
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
request.setAttribute("name","gareen");
%>
<jsp:forward page="getContext.jsp"/>
这也是一种页面间传递数据的方式
但是客户端跳转的情况下,是无法通过request传递数据的。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
request.setAttribute("name","gareen");
response.sendRedirect("getContext.jsp");
%>
- sessionContext
sessionContext 指的是会话,从一个用户打开网站的那一刻起,无论访问了多少网页,链接都属于同一个会话,直到浏览器关闭。
所以页面间传递数据,也是可以通过session传递的。
与requestContext类似的,也可以用如下方式来做:
pageContext.setAttribute("name","gareen",pageContext.SESSION_SCOPE);
pageContext.getAttribute("name",pageContext.SESSION_SCOPE)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
session.setAttribute("name","gareen");
response.sendRedirect("getContext.jsp");
%>
- applicationContext
指的是全局,所有用户共享同一个数据
在JSP中使用application对象, application对象是ServletContext接口的实例
也可以通过 request.getServletContext()
来获取。
与requestContext类似的,也可以用如下方式来做
pageContext.setAttribute("name","gareen",pageContext.APPLICATION_SCOPE);
pageContext.getAttribute("name",pageContext.APPLICATION_SCOPE)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
application.setAttribute("name","gareen");
System.out.println(application == request.getServletContext());
response.sendRedirect("getContext.jsp");
%>
JSP的隐式
JSP的隐式对象指的是不需要显示定义,直接就可以使用的对象,比如request
, response
JSP一共有9个隐式对象,分别是
request, response, out //请求,响应,输出
pageContext, session, application //三个作用域
page, config, exception
page 对象即表示当前对象
JSP 会被编译为一个Servlet类 ,运行的时候是一个Servlet实例。 page即代表this
JSTL
JSTL JSP Standard Tag Library
标准标签库
在页面中使用JSTL需要在jsp中 通过指令进行设置
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- 导入JSTL标签库 -->
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!-- 导入实例类Person -->
<jsp:useBean id="person" class="com.entity.Person" />
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSTL使用</title>
</head>
<body>
<h1>JSTL标签的使用</h1>
<hr>
<!-- 存值到scope中 -->
<!-- 方式一 -->
<c:set value="today" var="day" scope="session" />
<c:out value="${day}" /><br/>
<!-- 方式二 -->
<c:set var="love" scope="application" >football</c:set>
<c:out value="${love}" /><br/>
<!-- 通过set标签向person中赋值 -->
<c:set target="${person}" property="name" value="Jack"/>
<c:out value="${person.name}" /><br/>
<c:set target="${person}" property="age" >22</c:set>
<c:out value="${person.age}" /><br/>
</body>
</html>
JSTL标签分类
根据JSTL标签所提供的功能,可以将其分为5个类别:
1)核心标签(最常用、最重要,也是最基本的标签)
2)格式化标签
3)SQL标签
4)XML标签
5)JSTL函数(很常用)
核心组的标签是最常用的JSTL标签。以下是在JSP的语法包含JSTL核心库:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LZ8jIS8S-1640150904022)(D:\photo\photolibrary\Center-164014971331312.jpeg)]
-
格式化标签
使用JSTL格式标签来格式化和显示文本,日期,时间和数字的,国际化的网站, 需要包括格式化库:
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tR10AVP5-1640150904024)(D:\photo\photolibrary\Center-164014977371614.jpeg)]
-
SQL标签
JSTL的SQL标签库标签可以交互关系型数据库(如Oracle,MySQL或Microsoft SQL Server的关系数据库管理系
统)需要包括JSTL SQL库:
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H9hUz9zn-1640150904025)(D:\photo\photolibrary\Center-164014982097516.jpeg)]
-
XML标签
JSTL XML标记提供了一种创建和操作XML文档的JSP为中心的方式, 需要包括JSTL XML库。
JSTL XML标记库具有自定义标签与XML数据交互。这包括XML解析,转换XML数据,流控制,基于XPath表达式。
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7pu8KJs9-1640150904026)(D:\photo\photolibrary\Center-164014989197520.jpeg)]
-
JSTL函数
JSTL包括一些标准功能,其中大部分是常见的字符串操作函数, 需要包含JSTL函数库:
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Sg0wlngO-1640150904027)(D:\photo\photolibrary\Center-164014999081122.jpeg)]
EL表达式
为了保证EL表达式能够正常使用,需要在<%@page 标签里加上isELIgnored="false"
语法结构
EL表达式的语法格式用美元符号$
定界,内容包括在花括号{}
中。以${
开头,以}
结束,中间为合法的表达式,具体语法格式如下:
${expression}
expression:指定要输出的内容,可以是字符串,也可以是由EL运算符组成的表达式。
由于EL表达式的语法是以KaTeX parse error: Expected '}', got 'EOF' at end of input: …如果在JSP页面中要显示字符串{,则必须在前面加上"KaTeX parse error: Expected '}', got 'EOF' at end of input: {"或者写成"{’${’}"。
在页面中输出字符串“JSP学习”,代码如下:
${'JSP学习'}
EL表达式存取变量数据的方法很简单,例如:${username}。它的意思是取出某一范围中名称为username的变量。因为我们并没有指定哪一个范围的username,所以它会依序从Page、Request、Session、Application范围查
找。
假如途中找到username,就直接回传,不再继续找下去,但是假如全部的范围都没有找到时,就回传null。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6zvFeWVI-1640150904028)(D:\photo\photolibrary\Center.jpeg)]
EL表达式提供.
和[]
两种操作符来存取数据。两者通常情况是通用的:${user.sex}
或者${user["sex"]}
都是允许的。此外,[]
还可以用来进行集合元素中的定位:${booklist[0].price}
。
以下两种情况是不可以通用的:
-
包含特殊字符
当要存取的属性名称中包含一些特殊字符,如 . 或 - 等并非字母或数字的符号,就一定要使用"[ ]"。例如:
${ user. My-Name}
应当改为${user["My-Name"]}
-
通过变量动态取值:
如果要动态取值时,就可以用
[]
来做,而.
无法做到动态取值。例如:${sessionScope.user[data]}
中data 是一个变量。
String str_count = request.getParameter("count");
int count = Integer.parseInt(str_count);
count = count + 20;
EL表达式会进行自动类型转换,只需要这样写:
${param.count + 20}
运算符允许对数据和文字进行组合以及比较。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jv9WQozj-1640150904029)(D:\photo\photolibrary\Center-16401491117962.jpeg)]
最常用的表达式:
为空判断:${empty param.name}
三元运算:${A?B:C}
条件?表达式1:表达式2
算数运算:${A*(B+C)}
e.g.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6sUZDzDi-1640150904030)(D:\photo\photolibrary\Center-16401492549074.jpeg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S87QZQK5-1640150904031)(D:\photo\photolibrary\Center-16401492614936.jpeg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6cqPBA7Y-1640150904031)(D:\photo\photolibrary\Center-16401493164228.jpeg)]
JSP表达式语言定义了一组隐式对象,pageContext取得其他有关用户要求或页面的详细信息。其中许多对象在JSP scriplet和表达式中可用:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mLG5qwH1-1640150904033)(D:\photo\photolibrary\Center-164014945312310.jpeg)]
常用核心标签介绍
JSTL的核心标签共13个,从功能上可以分为4类:
- 表达式控制标签
<c:out>、<c:set>、<c:remove>、<c:catch>
- 流程控制标签
<c:if>、<c:choose>、<c:when>、<c:otherwise>
- 循环标签
<c:forEach>、<c:forTokens>
- URL操作标签
<c:import>、<c:url>、<c:redirect>
# <c:out>标签
<c:out>标签是显示表达式的结果,类似的方式<%=%>效果,与其不同的是<c:out>标签可以使用简单的"."操作符来访问属性。例如,要访问customer.address.street,使用的标签是:
<c:out value="customer.address.street"/>
- 取值
比如使用JSTL输出要写成
<c:out value="${name}" />
但是用EL只需要
${name}
e.g.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<c:set var="name" value="${'gareen'}" scope="request" />
通过标签获取name: <c:out value="${name}" /> <br>
通过 EL 获取name: ${name}
- 作用域优先级
EL表达式可以从pageContext,request,session,application
四个作用域中取到值,如果4个作用域都有name属性怎么办?
EL会按照从高到低的优先级顺序获取
pageContext>request>session>application
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<c:set var="name" value="${'gareen-pageContext'}" scope="page" />
<c:set var="name" value="${'gareen-request'}" scope="request" />
<c:set var="name" value="${'gareen-session'}" scope="session" />
<c:set var="name" value="${'gareen-application'}" scope="application" />
4个作用域都有name,优先获取出来的是 : ${name}
JavaBean
JavaBean 是一种JAVA语言写成的可重用组件。为写成JavaBean,类必须是具体的和公共的,并且具有无参数的构造器。JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性,set和get方法获取。
JavaBean的标准
- 提供无参public的构造方法(默认提供)
- 每个属性,都有public的getter和setter
- 如果属性是boolean,那么就对应is和setter方法
e.g.
package bean;
public class Hero {
public int id;
public String name;
public float hp;
public int damage;
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 float getHp() {
return hp;
}
public void setHp(float hp) {
this.hp = hp;
}
public int getDamage() {
return damage;
}
public void setDamage(int damage) {
this.damage = damage;
}
}
获取JavaBean的属性,只需要通过.符号操作就可以了。
像这样 ${hero.name}
,就会自动调用getName
方法了
注: 如果属性是boolean类型,那么就会自动调用isXXX方法了
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false" import="bean.*"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%
Hero hero =new Hero();
hero.setName("盖伦");
hero.setHp(616);
request.setAttribute("hero", hero);
%>
英雄名字 : ${hero.name} <br>
英雄血量 : ${hero.hp}