2020年_Jsp & Jstl 笔记
servlet
每创建/修改一个servlet,都要重新部署一遍项目。(修改Jsp不需要,支持热更新)
@WebServlet(name = "ServletDemo",value="/scope") //value的值是路径
一、Jsp的脚本
普通脚本
<% %>
所有Java语句都可以在里面书写,除了函数语句。
声明脚本
<%! %>
-
声明脚本声明的变量是全局变量
-
声明脚本的内容必须在普通脚本<% %>中调用
-
如果声明脚本中的函数具有返回值,使用输出脚本调用<%= %>
输出脚本
<%= %>
后面可以写函数,但是必须有返回值,结尾不需要加分号。
Jsp注释
<%-- 注释的内容 --%> // 不会输出,甚至不会被编译
当然也可以直接使用html注释
<!-- 这是一条注释 --> // 这个注释在页面中通过 F12能看到
Jsp指令
JSP指令用来设置与整个Jsp页面相关的属性。
Page指令
语法 <% @page attribute1=“value1” attribute2=“value2” %>
属性 | 描述 |
---|---|
contentType | 指定当前Jsp页面的MIME类型和字符编码格式 |
errorPage | 指定当JSP页面发生异常时需要转向的错误处理页面 |
isErrorPage | 指定当前页面是否作为宁一个Jsp页面的错误处理页面 |
import | 导入要使用的Java类 |
language | 定义JSP页面所用的脚本语言,默认是Java |
session | 制定Jsp页面是否使用session。默认为true则立即创建,false为使用时创建 |
Include指令
- 语法: <%@ include file= “被包含的JSP路径”
- 被包含的文件可以使JSP文件、html文件或者文本文件,包含的文件就好是当前JSP文件的一部分,会被同时编译执行(静态包含)。
<%@ include file="header.jsp"%>
```
<%@ include file="footer.jsp"%>
- 注意可能会出现 重名的问题,不建议使用
动作标签
- 语法:<jsp:action name attribute=“value”/>
- 动作标签指的是 jsp页面在运行期间的命令
include(动作标签)
- 语法:< jsp:include page=“相对URL地址”/>
- <jsp:include > 动作元素会将外部文件输出的结果包含在jsp中(动态包含)
<jsp:include page="index.jsp"/>
- 注意: 前面已经介绍过include指令,它是将外部文件的输出代码复制到当前Jsp文件中,而这里的jsp:include动作不同,是将外部文件的输出结果引入到了当前Jsp文件中。
useBean(注册对象)
- 语法 <jsp:useBean id=“name” class=“package.className” />
- jsp:useBean 动作用来加载一个将在JSP页面中使用的JavaBean。
属性 | 描述 |
---|---|
id | 必须,对象的名字 |
class | 必须,全限定名 |
<jsp:useBean id="user" class="com.qf.entity.User"/>
-
在类载入后,我们可以通过jsp:setProperty 和 jsp:getProperty动作来修改和获取bean的属性。
-
在创建类的时候,属性要全部私有化,必须含有getter and setter、无参构造方法 和 有参构造方法
setProperty
可以在jsp:useBean元素之后使用jsp:setProperty进行属性的赋值
属性 | 描述 |
---|---|
name | 必须,用来指定设置属性的是哪个bean |
property | 必须,表示要设置哪个属性 |
value | value属性是可选的。该属性用来指定Bean属性的值 |
<jsp:useBean id="user" class="com.qf.entity.User" />
<jsp:setProperty name="user" property="name" value="gavin"/>
getProperty
jsp:getProperty动作提取指定Bean属性的值,转换成字符串,然后输出。
属性 | 描述 |
---|---|
name | 要检索的Bean属性名称。Bean必须已定义。 |
property | 表示要提取Bean属性的值 |
<jsp:useBean id="user" class="com.qf.entity.User"/>
<jsp:setProperty name="user" property="name" value="gavin"/>
<jsp:getProperty name="user" property="name" />
forward
- 语法:< jsp:forwar page=“相对URL”
- jsp:forward 动作把请求转到另外的页面。
属性 | 描述 |
---|---|
page | page属性包含的是一个相对url地址 |
<jsp:forward page="index.jsp"/>
forward
- 语法: <jsp:param name="" value="" />
- 在转发动作的内部使用,作为参数传递
<jsp:forward page="index.jsp"
<jsp:param name="sex" value="nam"/>
</jsp:forward>
内置对象
由JSP自动创建的对象,可以直接使用,九大内置对象。
四大域对象
JSP有四大作用域对象,存储数据和获取数据的方式一样,不同的是取值的范围有差别
- pageContext(javax.servlet.jsp.PageContext) 当前JSP页面范围
- request(javax.servlet.http.HttpServletRequest) 一次请求有效
- session(javax.servlet.http.HttpSession) 一次会话有效(关闭浏览器失效)
- application(javax.servlet.ServletContext) 整个web应用有效(服务器重启或关闭失效)
pageContext对象
- pageContext对象是javax.servlet.jsp.PageContext类的实例,拥有作用域,用来代表整个Jsp页面。
- 当前页面的作用域对象,一旦跳转则失效
- 通过setAttribute(“name”,“value”)存储值
- 通过getAttribute(“name”) 获取值
- 用于获取其他8个内置对象或者操作其他对象的作用域
<%
pageContext.setAttribute("name",value);
%>
pageContext获取其他内置对象
<%
pageContext.getRequest();
pageContext.getResponse();
pageContext.getSession();
pageContext.getServletConfig();
pageContext.getServletContext();
pageContext.getOut();
pageContext.getException();
pageContext.getPage();
%>
pageContext操作其他作用域
pageContext.setAttribute("page","123");
pageContext.setAttribute("req","aaa",PageContext.REQUEST_SCOPE);
pageContext.setAttribute("session","bbb",PageContext.SESSION_SCOPE);
String req = (String) request.getAttribute("req");
String session = (String) session.getAttribute("sess");
String sess = (String) session.getAttribute("sess");
String app = (String) qpplication.getAttribute("app");
// 全能王
String result = (String) pageContext.findAttribute("req");
// 它会依次查找 pageContext 、 request 、session 、 application
// 如果查找到了,它就直接返回
二、EL表达式(express Language)
2.1 概念
EL使JSP写起来更简洁。主要用于获取作用域中的数据
2.2 作用
用于替换作用域对象getAttribute(“name”)
2.3 应用
- ${scope.name } 获取具体某个作用域中的数据
- ${name} 获取作用域中的数据,逐级查找 pageContext、request、session、application
2.4.1 EL案例
<%
request.setAttribute("name","tom");
request.setAttribute("age","18");
%>
${requestScope.name}
${name} // 从最小作用域逐级查找,找不到则返回“”
2.4.2 EL和JSP脚本的区别
- <%= request.getAttribute() %> // 没有找到返回null
- ${requestScope.name} // 没有找到返回“”
2.5 EL获得引用对象
使用 .成员变量名方式访问,或者arr[i]来访问,或者使用get方法
<%
Emp e = new Emp();
e.setName("gavin");
e.setAge("19");
request.setAttribute("e",e);
%>
${requestScope.e.name}
2.6 EL的empty运算符
用于测试数值是否为空值
<%
request.setAttribute("aaa","");
request.setAttribute("bbb",null);
%>
${empty aaa} //true
${empty bbb} //true
2.7 隐式对象
2.7.1 获取应用上下文
<%=
request.getContextPath()
%>
${
pageContext.request.contextPath
}
2.7.2 获取Cookie对象
${cookie.name.value}<br>
${cookie.pass.value}
<hr/>
<%-- 使用传统方法 --%>
<%
Cookie[] cookies = request.getCookies();
String username = "";
String pass = "";
if (cookies != null){
for (Cookie cookie : cookies){
if (cookie.getName().equals("name")){
username=cookie.getValue();
}
if (cookie.getName().equals("pass")){
pass = cookie.getValue();
}
}
}
%>
<%=
username
%>
<%=
pass
%>
六、JSTL标准标签库
6.1 现有问题
- EL主要是用于作用域获取数据,虽然可以做运算判断,但是得到的都是一个结果,作展示。
- EL不存在流程控制。比如判断
- EL对于集合智能做单点访问,不能实现遍历操作。
6.2 什么是JSTL?
- JSTL:全称Java Server Pages Standard Tag Liabrary
- JSP标准标签库(JSTL)是一个JSP标签机和。
6.3 JSTL的作用
- 可对EL获取到的数据进行逻辑操作。
- 与EL合作完成数据的展示。
6.4 JSTL使用
- 导入两个jar文件:stardard.jar 和 jstl.jar 文件拷贝到/WEB-INF/lib/下
- 在JSP页面引入标签库 <%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>
6.5 核心标签
6.5.1 条件标签if判断
语法: <c:if test=“条件”> < /c:if >
<%
pageContext.setAttribute("username","jerry");
pageContext.setAttribute("age",1000);
%>
<c:if test="${username eq 'tom'}">
<h1>欢迎访问,${username}</h1>
</c:if>
<c:if test="${username != 'tom'}">
<h1>请重新登录</h1>
</c:if>
6.5.2 多条件choose判断
语法:< c:choose>
<c:when test=“条件1”> 结果1 < /c:when>
<c:when test=“条件2”> 结果2 < /c:when>
<c:otherwise > 结果4 </c:otherwise >
< /c:choose>
<c:choose>
<c:when test="${age<=18}"><h1>青年</h1></c:when>
<c:when test="${age<=30}"><h1>中年</h1></c:when>
<c:when test="${age<=80}"><h1>老年</h1></c:when>
<c:otherwise><h1>修仙者</h1></c:otherwise>
</c:choose>
6.5.3 迭代foreach标签
语法
<c:foreach
var=“变量名”
items=“集合”
begin=“起始下标”
end=“结束下标”
step=“间隔长度”
varstatus=“遍历状态” > //very important
< /c:foreach>
<%
List<Person> persons = new ArrayList<Person>();
persons.add(new Person("tom","18"));
persons.add(new Person("jerry","18"));
persons.add(new Person("alice","18"));
persons.add(new Person("mike","18"));
request.setAttribute("persons",persons);
%>
<c:forEach var="item" items="${persons}" begin="0" end="2" step="1" varStatus="i">
${item.name} - ${item.age} - ${i.first} - ${i.last} - ${i.count} - ${i.index}<br>
</c:forEach>
特别标注:forEach循环无法主动停止。如果想执行某些操作后停止循环,
可以采用以下方式不执行循环里的操作。
<c:set var="exitId" value="0"/> //set 变量
<c:forEach var="element" items="${reserveArr}" varStatus="vs">
<c:if test="${exitId eq '0' && item.bookId eq element}">
<a href="${baseUrl}/user/book/cancel?username=${u.username}&bid=${item.bookId}">
<button type="button" class="btn btn-default">取消预定</button>
</a>
<c:set var="exitId" value="1"/> // 完成循环目的后,停止循环, set 变量等于1
</c:if>
<c:if test="${exitId eq '0' && vs.last && item.bookId ne element}">
<a href="${baseUrl}/user/book/reserve?username=${u.username}&BookId=${item.bookId}">
<button type="button" class="btn btn-primary">提前预定</button>
</a>
<c:set var="exitId" value="1"/>
</c:if>
</c:forEach>
<c:set var="exitId" value="0"/> //值恢复成原来的
6.5.4 url标签
在Cookie禁用的情况下,通过重写URL拼写JESSIONID来传递ID值。便于下一次访问时可查找到上一次的Session对象。(如果Cookie没有被禁用url就不会被禁止)
<%-- 当指定 var属性后,就不会渲染到页面中,而是可以通过${} 进行访问 --%>
<c:url context="${pageContext.request.contextPath}" value="/user/book.jsp" var="lianjie"/>
<a href="<c:url context='${pageContext.request.contextPath}' value='/user' />">链接</a>
<a href="${lianjie}">链接</a>
- 经验: 所有涉及到链接的都应该使用url重写机制。