JSTL与EL

原创
2017/01/03 09:39
阅读数 125

 

EL相关概念

JSTL一般要配合EL表达式一起使用,来实现在jsp中不出现java代码段。所以我们先来学习EL表达式

EL主要用于查找作用域中的数据,然后对它们执行简单操作;它不是编程语言,甚至不是脚本编制语言。通常与 JSTL 标记一起作用,能用简单而又方便的符号来表示复杂的行为。

 

EL基本格式
EL表达式的格式:用美元符号($)定界,内容包括在花括号({})中;
例如: ${loginInfoBean.suser}

此外,您可以将多个表达式与静态文本组合在一起以通过字符串并置来构造动态属性值;
例如:Hello {loginInfoBean.suser} ${loginInfoBean.spwd}

 

EL语法组成-标识符
EL表达式由标识符、存取器、文字和运算符组成。

标识符用来标识存储在作用域中的数据对象。EL 有 11 个保留标识符,对应于 11个EL隐式对象。除了11隐式对象外,假定所有其它标识符都用来标识作用域的变量。

 

标识符
例:
${abc} 相当于<%=pageContext.findAttribute(“abc”)%>
${og_1} <%=pageContext.findAttribute(“og_1”)%>
 …等等;就是说{}内的标识符除了11个保留字之外都表示作用域中的数据对应的名.

${requestScope}中的requestScope是11个EL隐式对象之一,它不再表示作用域中数据,而是表示request作用域;

 

EL隐藏对象
pageContext------------- PageContext 实例对应于当前页面的处理
pageScope ---------------与页面作用域属性的名称和值相关联的Map类
requestScope --------------与请求作用域属性的名称和值相关联的Map类
sessionScope---------------- 与会话作用域属性的名称和值相关联的Map类
applicationScope-------------- 与应用程序作用域属性的名称和值相关联的Map类
param----------------------------按名称存储请求参数的主要值的 Map 类
paramValues-------------------将请求参数的所有值作为 String 数组存储的 Map 类
Header-----------------------按名称存储请求头主要值的 Map 类
headerValues---------------将请求头的所有值作为 String 数组存储的 Map 类
cookie --------------------按名称存储请求附带的 cookie 的 Map 类
initParam-----------------按名称存储 Web 应用程序上下文初始化参数的Map类

 

域相关内置对象(重点)

域内置对象一共有四个:

  • l  pageScope:${pageScope.name}等同与pageContext.getAttribute(“name”);
  • l  requestScope:${requestScope.name}等同与request.getAttribute(“name”);
  • l  sessionScoep: ${sessionScope.name}等同与session.getAttribute(“name”);
  • l  applicationScope:${applicationScope.name}等同与application.getAttribute(“name”);

 

EL存取器
存取器用来检索对象的特性或集合的元素。

存取器: 通过 “[]” 或 “.” 符号获取相关数据

例:
${userBean.suser}  或  ${userBean[“suser”]}
//获取输出bean中的suser属性值;
${mcType[“id”]} //获取map中key为id对应的值;

 

EL运算符
运算符允许对数据和文字进行组合以及比较。

EL运算符:
类别  运算符
算术运算符  +、-、*、/(或 div)和 %(或 mod)
关系运算符  ==(或eq)、!=(或ne)、<(或lt)、>(或gt)、<=(或le)    和  >=(或ge)
逻辑运算符  &&(或 and)、||(或or)和 !(或 not)
验证运算符  empty
验证运算符(empty):对于验证数据特别有用。empty 运算符采用单个表达式作为其变量(也即,${empty input}),并返回一个布尔值,该布尔值表示对表达式求值的结果是不是“空”值。求值结果为 null 的表达式被认为是空,即无元素的集合或数组。如果参数是对长度为零的 String 求值所得的结果,则 empty 运算符也将返回 true。

 

EL文字
文字表示固定的值 — 数字、字符、字符串、布尔型或空值。

在 EL 表达式中,数字、字符串、布尔值和 null 都可以被指定为文字值。字符串可以用单引号或双引号定界。布尔值被指定为 true 和 false

 

EL函数库(fn)

  EL函数库是由第三方对EL的扩展.

EL函数库就是定义一些有返回值静态方法。然后通过EL语言来调用它们!当然,不只是JSTL可以定义EL函数库,我们也可以自定义EL函数库。

  EL函数库中包含了很多对字符串的操作方法,以及对集合对象的操作。

 

  导入函数库,需要使用taglib指令!

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

 

EL函数库介绍

  • l  String toUpperCase(String input):
  • l  String toLowerCase(String input):
  • l  int indexOf(String input, String substring):
  • l  boolean contains(String input, String substring):
  • l  boolean containsIgnoreCase(String input, String substring):
  • l  boolean startsWith(String input, String substring):
  • l  boolean endsWith(String input, String substring):
  • l  String substring(String input, int beginIndex, int endIndex):
  • l  String substringAfter(String input, String substring):hello-world, “-“
  • l  substringBefore(String input, String substring):hello-world, “-“
  • l  String escapeXml(String input):把字符串的“>”、“<”。。。转义了!
  • l  String trim(String input):
  • l  String replace(String input, String substringBefore, String substringAfter):
  • l  String[] split(String input, String delimiters):
  • l  int length(Object obj):可以获取字符串、数组、各种集合的长度!
  • l  String join(String array[], String separator):

<%@taglib prefix="fn"uri="http://java.sun.com/jsp/jstl/functions"%>

…

String[] strs = {"a", "b","c"};

List list = new ArrayList();

list.add("a");

pageContext.setAttribute("arr", strs);

pageContext.setAttribute("list", list);

%>

${fn:length(arr) }<br/><!--3-->

${fn:length(list) }<br/><!--1-->

${fn:toLowerCase("Hello") }<br/> <!-- hello -->

${fn:toUpperCase("Hello") }<br/> <!-- HELLO -->

${fn:contains("abc", "a")}<br/><!-- true -->

${fn:containsIgnoreCase("abc", "Ab")}<br/><!-- true -->

${fn:contains(arr, "a")}<br/><!-- true -->

${fn:containsIgnoreCase(list, "A")}<br/><!-- true -->

${fn:endsWith("Hello.java", ".java")}<br/><!-- true -->

${fn:startsWith("Hello.java", "Hell")}<br/><!-- true -->

${fn:indexOf("Hello-World", "-")}<br/><!-- 5 -->

${fn:join(arr, ";")}<br/><!-- a;b;c -->

${fn:replace("Hello-World", "-", "+")}<br/><!-- Hello+World -->

${fn:join(fn:split("a;b;c;", ";"), "-")}<br/><!-- a-b-c -->



${fn:substring("0123456789", 6, 9)}<br/><!-- 678 -->

${fn:substring("0123456789", 5, -1)}<br/><!-- 56789 -->

${fn:substringAfter("Hello-World", "-")}<br/><!-- World -->

${fn:substringBefore("Hello-World", "-")}<br/><!-- Hello -->

${fn:trim("     a b c")}<br/><!-- a b c -->

${fn:escapeXml("<html></html>")}<br/> <!-- <html></html> -->

 

自定义EL函数库

  • l  写一个类,写一个有返回值的静态方法;
  • l  编写itcast.tld文件,可以参数fn.tld文件来写,把itcast.tld文件放到/WEB-INF目录下;
  • l  在页面中添加taglib指令,导入自定义标签库。

 

ItcastFuncations.java

package cn.itcast.el.funcations;

public class ItcastFuncations {

    public static String test() {

       return "自定义EL函数库测试";

    }

}


itcast.tld(放到classes下)

index.jsp

<?xml version="1.0"encoding="UTF-8" ?>



<taglib xmlns="http://java.sun.com/xml/ns/j2ee"

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0">

   

  <tlib-version>1.0</tlib-version>

  <short-name>itcast</short-name>

  <uri>http://www.itcast.cn/jsp/functions</uri>



  <function>

    <name>test</name>

    <function-class>cn.itcast.el.funcations.ItcastFuncations</function-class>

    <function-signature>String test()</function-signature>

  </function>

</taglib>
<%@ page language="java"import="java.util.*" pageEncoding="UTF-8"%>

<%@ taglib prefix="itcast"uri="/WEB-INF/itcast.tld" %>



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <body>

    <h1>${itcast:test() }</h1>

  </body>

</html>

 

------------------------------------------------------------------------------------------------------------

JSTL是什么
JSTL(JSP Standard Tag Library,JSP标准标签库)是一个不断完善的开放源代码的JSP标签库,是由apache的jakarta小组来维护的。JSTL1.0 由四个定制标记库(core、format、xml 和 sql)和一对通用标记库验证器组成。core 标记库提供了定制操作,通过限制了作用域的变量管理数据,以及执行页面内容的迭代和条件操作。它还提供了用来生成和操作 URL 的标记。format 标记库定义了用来格式化数据(尤其是数字和日期)的操作。它还支持使用本地化资源束进行JSP页面的国际化。xml 库包含一些标记,这些标记用来操作通过XML表示的数据,而 sql 库定义了用来查询关系数据库的操作。 两个 JSTL 标记库验证器允许开发人员在其 JSP 应用程序中强制使用编码标准。

如果要使用JSTL,则必须引用jstl.jar和 standard.jar两个包。

 


为什么要用JSTL
我们JSP用于开发信息展现页非常方便;也可以嵌入java代码(scriptlet、表达式和声明)代码用来实现相关逻辑控制。看下面程序。但这样做会带来如下问题:
jsp维护难度增加;
出错提示不明确,不容易调试;
分工不明确;(即jsp开发者是美工,也是程序员);
最终增加程序的开发成本;
解决上面的问题可以使用定制标记库,JSTL使JSP开发者可以减少对脚本元素的需求,甚至可以不需要它们,从而避免了相关的维护成本。使分工更明确。

<% if (session.getAttribute(“user”).equals(“member”)) { %>
    <p>Welcome, member!</p>
<% } else { %>
    <p>Welcome, guest!</p>
<% } %>


JSTL一般配合EL一起使用,因此先看看EL.

 

JSTL标签库

JSTL一共包含四大标签库:

  • l  core:核心标签库,我们学习的重点;
  • l  fmt:格式化标签库,只需要学习两个标签即可;
  • l  sql:数据库标签库,不需要学习了,它过时了;
  • l  xml:xml标签库,不需要学习了,它过时了。


在JSP使用JSTL-core标签库
core在jsp中的使用:
在 web.xml 中添加

<jsp-config>
  <taglib>
      <taglib-uri>http://java.sun.com/jsp/jstl/core</taglib-uri>
      <taglib-location>/WEB-INF/c.tld</taglib-location>
  </taglib>
</jsp-config>


在jsp文件中添加
<%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>或<%@ taglib prefix="c" uri="/WEB-INF/c.tld" %>
使用<c:out value=“HelloWorld” />

 

Core的操作作用域变量标签
获取输出作用域中变量.
<c:out >      属性: value [default] [escapeXml]
定义作用域中变量
<c:set >      属性: value var [scope]
删除作用域中变量
<c:remove >   属性: var [scope]

Core的条件控制标签
单分支条件
<c:if >  属性:test [var] [scope]
多分支条件
 <c:choose >  
   <c:when > 属性: test
   <c:otherwise >

 

Core的其它标签
输出转换成的URL:
<c:url > 属性:value [context] [var] [scope]
和<jsp:include >相似用于包含其它页面的内容:
<c:import >属性:url [context] [charEncoding] [var] [scope]
重定向
<c:redirect >属性: url [context]
与<c:url><c:import><c:redirect>配合使用,用于传参
<c:param >属性: name value

Core的循环控制标签
实现简单循环
<c:forEach >  var='item' begin='5' end='10' step='2‘ varStatus=‘’
实现迭代(遍历)
<c:forEach > items='' var='item‘ varStatus=‘’

属性varStatus和var相似设置一个作用域变量;只是varStatus作用域变量中存的是包括运行状态的对象;此对象包含如下属性:
current  index  count  first  last  begin  end  step

 

简单循环

<%@ page language="java" contentType="text/html; charset=GBK"%>
<%@ taglib prefix="c" uri="/WEB-INF/c.tld" %>
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
 <title>testjstl1</title>
</head>
<body>
 <c:forEach var="i" step="1" begin="1" end="100">
 ${i} <br>
 </c:forEach>
</body>
</html>

 

循环迭代

<%@ page language="java" contentType="text/html; charset=GBK"%>
<%@ taglib prefix="c" uri="/WEB-INF/c.tld" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>testjstl1</title>
</head>
<body>
<c:forEach var="mcBean" items="${mcList}" varStatus="mcStatus">
当前遍历索引:${mcStatus.index} ;  商品名:${mcBean.sname} ; .... <br>
</c:forEach>
</body>
</html>

 

在JSP使用JSTL-format标签库
format在jsp中的使用:
在 web.xml 中添加

<jsp-config>
  <taglib>
      <taglib-uri>http://java.sun.com/jstl/fmt</taglib-uri>
      <taglib-location>/WEB-INF/fmt.tld</taglib-location>
  </taglib>
</jsp-config>


在jsp文件中添加

<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %>

使用

<fmt:formatDate value=“” pattern=“yyyy-MM-dd” />

 

Format常用标签
格式化输出日期:
<fmt:formatDate > value type var pattern
type取值:
short: 10/19/00 6:07 PM
medium: Oct 19, 2000 6:07:01 PM
long: October 19, 2000 6:07:01 PM MDT
full: Thursday, October 19, 2000 6:07:01 PM MDT
例: <fmt:formatDate value=“” pattern=“yyyy/MM/dd” />
格式化输出数字:
<fmt:formatNumber> value var pattern
例:<fmt:formatNumber value=“” pattern=“###.##” />format实例

<%@ page language="java" contentType="text/html; charset=GBK"%>
<%@ taglib prefix="fmt" uri="/WEB-INF/fmt.tld" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>testjstl1</title>
</head>
<body>
<jsp:useBean id="curDate" class="java.util.Date" scope="page"/>
<fmt:formatDate value="${curDate}" pattern="yyyy-MM-dd HH:mm:ss"/><br>

<fmt:formatNumber value="10.32898432" pattern="#.##"/><br>
<% request.setAttribute("var1",3.1415926); %>
<fmt:formatNumber value="${var1}" pattern="#.##"/><br>
</body>
</html>

 

自定义标签

1 自定义标签概述

 

1.1 自定义标签的步骤

其实我们在JSP页面中使用标签就等于调用某个对象的某个方法一样,例如:<c:if test=””>,这就是在调用对象的方法一样。自定义标签其实就是自定义类一样!

  • l  定义标签处理类:必须是Tag或SimpleTag的实现类;
  • l  编写标签库描述符文件(TLD);

 

SimpleTag接口是JSP2.0中新给出的接口,用来简化自定义标签,所以现在我们基本上都是使用SimpleTag。

 

1.2 SimpleTag接口介绍

SimpleTag接口内容如下:

  • void doTag():标签执行方法;
  • JspTag getParent():获取父标签;
  • void setParent(JspTag parent):设置父标签
  • void setJspContext(JspContext context):设置PageContext
  • void setJspBody(JspFragment jspBody):设置标签体对象;

 

请记住,万物皆对象!在JSP页面中的标签也是对象!所有标签都会变成对象的方法调用。标签对应的类我们称之为“标签处理类”!

标签的生命周期:

  1. 当容器(Tomcat)第一次执行到某个标签时,会创建标签处理类的实例;
  2. 然后调用setJspContext(JspContext)方法,把当前JSP页面的pageContext对象传递给这个方法;
  3. 如果当前标签有父标签,那么使用父标签的标签处理类对象调用setParent(JspTag)方法;
  4. 如果标签有标签体,那么把标签体转换成JspFragment对象,然后调用setJspBody()方法;
  5. 每次执行标签时,都调用doTag()方法,它是标签处理方法。

 

HelloTag.java

public class HelloTag implements SimpleTag {

    private JspTag parent;

    private PageContext pageContext;

    private JspFragment jspBody;

    public void doTag() throws JspException, IOException {

       pageContext.getOut().print("Hello Tag!!!");//Hello Tag!!!对象,输出out获取 

    }

    public void setParent(JspTag parent) {

       this.parent = parent;

    }

    public JspTag getParent() {

       return this.parent;

    }

    public void setJspContext(JspContext pc) {

       this.pageContext = (PageContext) pc;

    }

    public void setJspBody(JspFragment jspBody) {

       this.jspBody = jspBody;

    }

}


1.3 标签库描述文件(TLD)

标签库描述文件是用来描述当前标签库中的标签的!标签库描述文件的扩展名为tld,你可以把它放到WEB-INF下,这样就不会被客户端直接访问到了。

hello.tld

<?xml version="1.0"encoding="UTF-8"?>

<taglib version="2.0"xmlns="http://java.sun.com/xml/ns/j2ee"

    xmlns:xml="http://www.w3.org/XML/1998/namespace"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee

               http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd ">



    <tlib-version>1.0</tlib-version>//指定当前标签库的版本

    <short-name>itcast</short-name>//指定当前标签库的简称

    <uri>http://www.itcast.cn/tags</uri>//指定标签库的uri

    <tag>//部署一个标签!一个<tag>表示一个标签。

       <name>hello</name>//指定标签的名称 

       <tag-class>cn.itcast.tag.HelloTag</tag-class>//指定标签处理类

       <body-content>empty</body-content>//指定标签体内容类型为空类型,即没有标签体。

    </tag>

</taglib>


1.4 使用标签

在页面中使用标签分为两步:

  • l  使用taglib导入标签库;
  • l  使用标签;
<%@ taglib prefix="it"  uri="/WEB-INF/hello.tld"  %>

......

<it:hello/>

 

2 自定义标签进阶

2.1 继承SimpleTagSupport

  继承SimpleTagSuppport要比实现SimpleTag接口方便太多了,现在你只需要重写doTag()方法,其他方法都已经被SimpleTagSuppport完成了。

public class HelloTag extends SimpleTagSupport {

    public void doTag() throws JspException, IOException {

       //向页面输出!

       this.getJspContext().getOut().write("<p>Hello SimpleTag!</p>") ;

    }

}


2.2 有标签体的标签

我们先来看看标签体内容的可选值:

<body-content>元素的可选值有:

  • l  empty:无标签体。
  • l  JSP:传统标签支持它,标签体内容可以是任何东西:EL、JSTL、<%=%>、<%%>,以及html;
  • l  scriptless:标签体内容不能是Java脚本,但可以是EL、JSTL等。在SimpleTag中,如果需要有标签体,那么就使用该选项
  • l  tagdependent:标签体内容不做运算,由标签处理类自行处理,无论标签体内容是EL、JSP、JSTL,都不会做运算。这个选项几乎没有人会使用!

 

自定义有标签体的标签需要:

  • l  获取标签体对象:JspFragment jspBody = getJspBody();;
  • l  把标签体内容输出到页面:jspBody.invoke(null);
  • l  tld中指定标签内容类型:scriptless。
  • l  在TLD中部属相关属性。
  • l  在处理类中给出JavaBean属性(提供get/set方法);

  一般标签都会带有属性,例如<c:if test=””>,其中test就是一个boolean类型的属性。完成带有属性的标签需要:

2.4 带有属性的标签

  如果希望在执行了自定义标签后,不再执行JSP页面下面的东西,那么就需要在doTag()方法中使用SkipPageException。

2.3 不执行标签下面的页面内容

public class HelloTag extends SimpleTagSupport {

    public void doTag() throws JspException, IOException {

       PageContext pc = (PageContext) this.getJspContext();

       HttpServletRequest req = (HttpServletRequest) pc.getRequest();

       String s = req.getParameter("exec");

       if(s != null && s.endsWith("true")) {

           JspFragment body = this.getJspBody();//获取当前标签的标签体对象

           body.invoke(null);//向页面输出标签体内容

       }

    }

}
<tag>
       <name>hello</name>

       <tag-class>cn.itcast.tags.HelloTag</tag-class>

       <body-content>scriptless</body-content>//scriptless指定标签体内容为

</tag>
<itcast:hello>

        <h1>哈哈哈~</h1>

</itcast:hello>

 

public class SkipTag extends SimpleTagSupport {

    public void doTag() throws JspException, IOException {

       this.getJspContext().getOut().print("<h1>只能看到我!</h1>");

       throw new SkipPageException();

    }
}
<tag>
       <name>skip</name>

       <tag-class>cn.itcast.tags.SkipTag</tag-class>

       <body-content>empty</body-content>
</tag>
<itcast:skip/>

  <h1>看不见我!</h1>
public class IfTag extends SimpleTagSupport {

    private boolean test;

    public boolean isTest() {

       return test;

    }

    public void setTest(boolean test) {//该方法会在doTag()之前被调用,传入属性值。

       this.test = test;

    }

    @Override

    public void doTag() throws JspException, IOException {

       if(test) {

           this.getJspBody().invoke(null);

       }//如果test为true,执行标签体内容,否则什么都不做。

    }

}
<tag>

       <name>if</name>

       <tag-class>cn.itcast.tag.IfTag</tag-class>

       <body-content>scriptless</body-content>

       <attribute>//声明属性 

           <name>test</name>

           <required>true</required>//为true表示属性是必须的,为false表示属性为可选的。为true表示 

           <rtexprvalue>true</rtexprvalue>//属性值可以为EL或JSTL,否则表示只能是常量。

       </attribute>

</tag>
<%
    pageContext.setAttribute("one", true);

    pageContext.setAttribute("two", false);

%>

<it:if test="${one }">xixi</it:if>//可以看到xixi

<it:if test="${two }">haha</it:if>//不会执行haha

<it:if test="true">hehe</it:if>//可以看到hehe 

 

 

 

展开阅读全文
打赏
0
4 收藏
分享
加载中
更多评论
打赏
0 评论
4 收藏
0
分享
返回顶部
顶部