JSP标签、EL表达式、JSTL
(一)JSP标签技术
一、JSP标签技术概述
- jsp本质上是一种动态web资源开发技术 , 看起来像是html , 但其中可以写java代码 , 非常方便用来开发动态web资源 。
- 但是一旦在jsp中写了太多的java代码 , 仍然会造成代码和标签混杂在一起 , 不便于开发维护 , 所以sun公司在JSP2.0开始已经不再推荐 在jsp页面中出现任何一行java代码了 。
- 所有的java代码应该替换问为jsp标签技术来实现 。
- jsp标签技术提供的标签 , 看起来像是一个标签 , 但本质上仍然是Java代码 , 所以仍然是web动态资源开发技术
- 由于JSP原生的标签库标签比较少, 且不太好用 , 所以目前的开发越来越趋势:
- jsp原生标签 只替代jsp页面中的转发和包含的java代码
- el表达式替代jsp页面中脚本表达式
- JSTL替代jsp页面中的脚本片段 。
(二)JSP标签
一、jsp标签
- 是sun公司 在jsp2.0中提供的原生的标签 不需要导入任何开发包就可以直接使用
- 但是 这个标签库中的标签 比较少 且不太好用 所以现在用的很少
- 我们只需了解几个即可
<jsp:inclue> 用来替代request.getRequestDispatcher().include()实现页面包含 <jsp:forward>用来替代request.getRequestDispatcher().forward() <jsp:param>配合前两个标签使用,可以在包含或转发时,带一些参数过去
(三)EL表达式
一、概述及注意
- 全称叫做Expression Language ,用来替代jsp页面中的jsp的脚本表达式 <%= java表达式%>
- el表达式的形式 $(el表达式)
- 注意:
- el只能获取域中的数据
- el只能获取不能遍历
- el只能获取不能修改
二、获取数据
- 获取常量数据
- 支持包括数值类型 、 在字符串类型 、 布尔类型
<%--获取常量数据 --%> ${123.342 } ${"abc" } ${true } ${false }
- 支持包括数值类型 、 在字符串类型 、 布尔类型
- 获取变量中的数据
- el中直接写变量的名称, el会按照由小到大的顺序自动搜寻四大作用域找该名称对应的值 , 如果找到则返回 ,找不到则返回空字符串 。
<%--获取变量 --%> <% //pageContext.setAttribute("country", "CN"); //request.setAttribute("country", "US"); //session.setAttribute("country", "UK"); //application.setAttribute("country", "JP"); %> <%= pageContext.findAttribute("country") %> ${country }
- el中直接写变量的名称, el会按照由小到大的顺序自动搜寻四大作用域找该名称对应的值 , 如果找到则返回 ,找不到则返回空字符串 。
- 获取数组中的数据
- 可以通过中括号来访问数组中的数据
<%--获取数组中的数据 --%> <% String [] provs = {"京","粤","沪","鲁"}; pageContext.setAttribute("provs", provs); %> ${provs[2]}
- 可以通过中括号来访问数组中的数据
- 获取集合中的数据
- 可以通过中括号来访问数组中的数据
<%--获集合中的数据 --%> <% List list = new ArrayList(); list.add("孙悟空"); list.add("哈利波特"); list.add("萨达姆"); list.add("朴乾"); pageContext.setAttribute("list", list); %> ${list[3] }
- 可以通过中括号来访问数组中的数据
- 获取Map中的数据
- 可以通过中括号或点的形式来获取map中的数据 , 大部分情况下使用哪个都可以 , 但是如果担心产生歧义(变量名中可能有点), 最好使用中括号
- 中括号中键的名称加引号就是常量, 直接使用来获取map中的值 , 如果不加引号 , 则是一个变量 , el会先去获取对应的值 , 在根据其中的值获取map中对应变量的值
<%--获取map中的数据 --%> <% Map<String,String> map = new HashMap<String,String>(); map.put("name", "韦小宝"); map.put("addr", "扬州"); map.put("wife", "双儿"); map.put("shifu", "陈近南"); map.put("wife.xiao","阿珂"); pageContext.setAttribute("map", map); pageContext.setAttribute("shifu", "addr"); %> ${map } ${map["name"] } ${map.wife } ${map["wife.xiao"] } ${map[shifu] }
- 获取JavaBean的属性
- 可以在el中通过【 bean的.属性 】的方法来获取bean中的属性
- 要注意 ,前提是这个bean中必须要有对应的getxxx()方法
<%--获取javabean的属性 --%> <% Person p = new Person(); p.setName("张三丰"); p.setAge(120); p.setAddr("武当山"); pageContext.setAttribute("p", p); %> ${p.name } ${p.addr }
- 延伸~~
- pageContext来获取当前应用的名称
<%= request.getContextPath()%> ${pageContext.request.contextPath}
- pageContext来获取当前应用的名称
二、执行简单的运算
- 算术运算
- +
- -
- *
- /
- %
<%--算数运算 --%> ${ 2 + 3 } ${ 2*3 } ${ 10/3 } ${ 2+"3" } <%-- ${ 2 + "a" } ${"a" + "b" } --%>
- 注意:el在进行算术运算时 , 会尝试将参与运算的非数字字符转换为数字参与运算 , 如果转换不成功则直接抛出异常
- 注意:el执行算术运算时运算结果为double类型
- 关系运算
- == eq
- != ne
- < lt
- <= le
- > gt
-
= ge
<!--关系运算 --> ${3 == 4 } ${5>=3 }
- 逻辑运算
- && and
- || or
- ! not
<!--逻辑运算符 --> ${3>5 or 3<=4 } ${3>5 and 3<=4 } ${!(3>5 and 3<=4)}
- 三元运算
${3>2 ? "yes" : "no" }
- empty运算
- 判断对象是否是null
- 判断对象内容是否为空
- 判断集合数组中是否没有任何元素
- 判断域中是否没有任何属性
<% String str = null; str = ""; str = "abc"; pageContext.setAttribute("str", str); List list = null; list = new ArrayList(); list.add("abc"); pageContext.setAttribute("list", list); request.setAttribute("like", "football"); %> ${empty str} ${empty list } ${empty requestScope} ${empty sessionScope} ${empty pageScope} ${empty applicationScope}
三、获取常用开发对象
- 概述:
- 了为了方便使用 , 在其内部定义了11个el内置的对象 , 不需要 提亲存入域中就能使用 。
- 要注意 , 着了所谓的11个内置对象域之jsp中九大饮食对象不是一回事 , 没有关系
- 11个内置对象
- pageContext :代表当前页面 , 有了它就意味着有了 九大隐式对象
<!-- pageContext 代表当前页面的对象 有了它就相当于有了九大隐式对象 --> ${pageContext.request } ${pageContext.session }
- pageScope :pageContext域
- requestScope: request域
- sessionScope :session域
- applicationScope : application域
<!-- 代表四大作用域的对象,注意!是作用域 不是对象本身! pageScope -- pageContext域 requestScope -- request域 sessionScpoe -- sessiono域 applicationScope -- ServletContext域 --> <% request.setAttribute("name", "特朗普"); session.setAttribute("name", "普京"); application.setAttribute("name", "朴乾"); %> ${name } ${sessionScope.name } ${applicationScope.name }
- param : 浏览器提交的请求所有参数组成的Map
- pageContext :代表当前页面 , 有了它就意味着有了 九大隐式对象
四、调用函数
- 可以调用JSTL中fn子库中的函数 , 在JSTL中详解
- 可以调用自定义的函数 , 但是在开发中几乎不用
(四)JSTL标签
一、JSTL标签概述
- JavaServer Pages Standard Tag Library 是提供给JavaWeb开发人员的一个标准通用的标签函数库
- 可以与EL表达式配合来取代传统JSP页面上嵌入大量的java代码的做法 , 可以提高 程序的可读性 、维护性 、 和方便性
- 在javaee4.0之前需要导入相关的jar包才能使用 ,但是在javaee5.0开始 , 默认已经包含了此jar包
- 在使用时需要在jsp页面通过用<%@ taglib %> 标签来引入相应的标签库
<%@ taglib uri="xxxx" prefix=""%> uri用来指定引入的包 prefix用于指定标签的前缀 ,可以是任意字符串, 在开发中一般使用默认的c 。
二、JSTL的子库
- core : 核心标签库
- fn : JSTL提供的el函数库 有很多可以通过el调用的函数
- fmt : 国际化标签库
- xml : 操作xml文件的标签库
- sql : 操作sql的标签库
- 但是在开发中一般jsp文件只用来作数据的展示 , 而逻辑处理全部交给servlet , 所以xml子库和sql子库没人用 , 国际化标签fmt以后详解。
三、core子库
-
- 输出常量
- 输出变量
- 转义输出
- 输出默认值
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> <!DOCTYPE HTML> <html> <head> </head> <body> <h1>输出固定值</h1> <c:out value="987"></c:out> <c:out value="abc"></c:out> ${987 } ${"abc" } <hr> <h1>输出变量</h1> <% pageContext.setAttribute("name", "马里奥"); pageContext.setAttribute("name", "路易吉"); %> <c:out value="${name}"></c:out> ${name } <hr> <h1>转义输出</h1> <c:out value="<a href='#'>xxx</a>"></c:out> <c:out value="<a href='#'>xxx</a>" escapeXml="false"></c:out> ${fn:escapeXml("<a href='#'>xxx</a>") } <hr> <h1>输出默认值</h1> <% pageContext.setAttribute("addr", "上海"); %> <c:out value="${addr}" default="北京"></c:out> ${addr == null ? "北京" : addr } <hr> </body> </html>
-
- 向四大作用域中添加域属性
- 向map中添加或修改键值对
- 修改javaBean中的属性
<%@page import="cn.tedu.Person"%> <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE HTML> <html> <head> </head> <body> <h1>向四大作用域增加域属性</h1> <c:set scope="request" var="name" value="张飞"></c:set> <c:set scope="page" var="name" value="关羽"></c:set> ${requestScope.name } ${pageScope.name } <hr> <h1>操作Map 增加或修改Map中的属性</h1> <% Map map = new HashMap(); map.put("name", "刘备"); map.put("wife", "糜夫人"); pageContext.setAttribute("map", map); %> <c:set target="${map }" property="wife" value="孙尚香"></c:set> ${map } <c:set target="${map }" property="son" value="刘禅"></c:set> ${map } <hr> <h1>操作JavaBean的属性</h1> <% Person p = new Person(); p.setName("诸葛亮"); p.setAge(20); p.setAddr("南阳"); pageContext.setAttribute("p", p); %> <c:set target="${p }" property="name" value="孔明"></c:set> ${p.name } <hr> </body> </html>
-
- 移除指定域中的指定名称的属性
- 如果不指定哪个域 , 则默认删除所有域中的该属性
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE HTML> <html> <head> </head> <body> <h1>删除指定域中的属性</h1> <% pageContext.setAttribute("name", "乔峰"); request.setAttribute("name", "段誉"); session.setAttribute("name", "虚竹"); application.setAttribute("name", "玄慈"); %> ${name } <c:remove var="name" scope="page"/> ${name } <c:remove var="name" scope="request"/> ${name } <c:remove var="name" scope="session"/> ${name } <c:remove var="name" scope="application"/> ${name } <hr> <h1>删除所有域中指定名称的属性</h1> <% pageContext.setAttribute("name", "乔峰"); request.setAttribute("name", "段誉"); session.setAttribute("name", "虚竹"); application.setAttribute("name", "玄慈"); %> <c:remove var="name"/> ${name } <hr> </body> </html>
-
- 捕捉指定范围内的异常
- 捕获到的异常可以通过声明var属性来指定一个名字 , 并自动写入pageContext域中 , 以便后续处理
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE HTML> <html> <head> </head> <body> <% try{ String str = null; str.toUpperCase(); }catch(Exception e){ out.write("哈哈哈 捕获了异常~"); } %> <c:catch var="e"> <% String str = null; str.toUpperCase(); %> </c:catch> ${e } </body> </html>
-
- 实现判断
- test写判断表达式
- scope声明将判断结果存入哪个域中
- var声明存入域中时的变量名
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE HTML> <html> <head> </head> <body> <h1>实现判断</h1> <% int num = 1000; pageContext.setAttribute("num", num); %> <c:if test="${num<100}" scope="page" var="result"> yes~ </c:if> <c:if test="${num >= 100}"> no~ </c:if> ${result } <hr> </body> </html>
- -
- 实现多重判断
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE HTML> <html> <head> </head> <body> <% request.setAttribute("day", 2); %> <c:choose> <c:when test="${day == 1 }"> 星期一 </c:when> <c:when test="${day == 2 }"> 星期二 </c:when> <c:when test="${day == 3 }"> 星期三 </c:when> <c:when test="${day == 4 }"> 星期四 </c:when> <c:when test="${day == 5 }"> 星期五 </c:when> <c:otherwise> 休息日 </c:otherwise> </c:choose> </body> </html>
- 实现多重判断
-
- 实现循环遍历 , 类似于java中的foe循环
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE HTML> <html> <head> </head> <body> <h1>实现普通for循环</h1> <c:forEach begin="0" end="10" step="2" var="i"> ${i } </c:forEach> <hr> <h1>实现增强for循环</h1> <% List list = new ArrayList(); list.add("北京"); list.add("上海"); list.add("广州"); list.add("深圳"); list.add("铁岭"); pageContext.setAttribute("list", list); %> <c:forEach items="${list }" var="addr"> ${addr } </c:forEach> <hr> <h1>实验:遍历10到100的偶数,如果数字所在的位置是3的倍数,显示成红色</h1> <c:forEach begin="10" end="100" step="2" var="i" varStatus="stat"> <c:if test="${stat.count % 3 == 0 }"> <font color="red">${i }</font> </c:if> <c:if test="${stat.count % 3 != 0 }"> <font color="blue">${i }</font> </c:if> </c:forEach> <hr> </body> </html>
- 实现循环遍历 , 类似于java中的foe循环
-
- 将一串字符按照指定的字符切割
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE HTML> <html> <head> </head> <body> <c:set scope="page" var="addr" value="www.tedu.cn"></c:set> ${addr } <br> <c:forTokens items="${addr }" delims="." var="x"> ${x } <br> </c:forTokens> </body> </html>
- 将一串字符按照指定的字符切割
-
- 实现url重写 - 可以实现url重写 , 在浏览器禁用cookie时 , 在请求地址后加上jsessionid从而使用session
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE HTML> <html> <head> </head> <body> <c:url var="addr" scope="page" value="/index.jsp" context="/Day14"></c:url> <a href="${addr }" target="_blank" rel="external nofollow" >xx</a> </body> </html>
- 实现url重写 - 可以实现url重写 , 在浏览器禁用cookie时 , 在请求地址后加上jsessionid从而使用session
四、fn函数库
- JSTL提供了 可以供el表达式调用的函数库
- 其中提供了大量的操作字符串的函数
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> <!DOCTYPE HTML> <html> <head> </head> <body> <c:set var="infos" value="${fn:split('www.tarena.com.cn','.') }" scope="page"></c:set> <c:forEach var="info" items="${infos }"> ${info }<br> </c:forEach> ${fn:toUpperCase("asdfasLKJasdfgLKjasdfgjk,lHJKqwertbnmassdfKL:HJ") } </body> </html>