学习jsp不得不学习jsp标签,一般来说,对于一个jsp开发者,可以理解为jsp页面中出现的java代码越少,对jsp的掌握就越好,而替换掉java代码的重要方式就是使用jsp标签。
1)内置标签(动作标签): 不需要在jsp页面导入标签
2)jstl标签: 需要在jsp页面中导入标签
3)自定义标签 : 开发者自行定义,需要在jsp页面导入标签
<jsp:forward />转发标签:
语法:<jsp:forward page="/MyJsp001.jsp"></jsp:forward>
相当于java代码:request.getRequestDispatcher("/MyJsp001.jsp?name=jxf").forward(request, response);
注意:但是java代码的转发可以通过url带参数的方式进行传递参数,而转发标签需要借助于下面的<jsp:param>标签实现参数传递
<jsp:pararm/>参数标签:
语法: <jsp:param value="jxf" name="name"/> <%-- 传递一个名为name,值为jxf的参数,参数一般作为其他标签的子标签使用--%> 结合<jsp:forward>标签用法: <jsp:forward page="/MyJsp001.jsp"> <jsp:param value="jxf" name="name"/> </jsp:forward>
<jsp:include/>包含标签:
语法: <jsp:include page="/MyJsp001.jsp"> <jsp:param value="jxf" name="name"/><%--可以将参数传递给包含进来的页面--%> </jsp:include> jsp中还有一个包含指令,也是将一个页面包含另外的页面 他们之间的区别: 1、首先是语法不同 <jsp:include page="/MyJsp001.jsp"> <%@inclue file="被包含的页面"%> 2、<jsp:include>可以传递参数,<%@inclue%>不可以 3、<jsp:include>:包含页面与被包含页面分别编译为两个java源文件,在运行时引用 <%@inclue%>:包含页面与被包含页面合并编译为一个java源文件
JSTL (java standard tag libarary - java标准标签库)
jstl标签的类型: 核心标签库 (c标签库)//这里主要介绍c标签库,因为用的真的很多 国际化标签(fmt标签库) EL函数库(fn函数库) xml标签库(x标签库)//一般不用该库,这属于数据操作,而数据操作应于dao层中,jsp页面主要用于展示数据 sql标签库(sql标签库)//与xml标签库类似,不应在jsp页面中操作数据(当然他们是可以在jsp页面写)
使用jstl标签库使用前提(此处以c标签库为例):
1、导入jstl支持包:jstl-1.2.jar(如果用MyEclipse创建项目时候选择java EE5.0,则不需要导包,工程中已经包含)
2、在页面中使用Taglib指令导入标签库
<%--uri:tld文件中的uri名称,prefix:标签前缀--%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
uri和prefix怎样写?以标签库的为例:
工程名->Java EE 5 Libraries->jstl-1.2.jar->META-INF-c.tld
c标签库的主要标签:
<c:set>标签:用于保存数据到域对象中
<%--var为属性名 value为属性值 scope为保存属性到那个域对象,默认为page域 --%> <%--相当于java代码<%pageContext.setAttribute("name", "jxf") --%> <c:set var="name" value="jxf" scope="page"></c:set> ${name}<%--EL表达式输出page域中的name属性值--%>
<c:out>标签:显示数据
<%--value:输出到浏览器的值,${name}EL表达式取出域对象属性值为name的值,
default:当value值为null时显示的默认值,
escapeXml:表示是否转义为xml格式(也可以理解为普通文本格式),true表示转义,默认false --%> <c:out value="${name}" default="<h1>标题h1<h1>" escapeXml="false"></c:out>
<c:if>标签:但条件判断
<%--test支持EL表达式 --%> <c:if test="${true}"> 条件成立! </c:if>
<c:choose>+<c:when>+<c:otherwise>标签:多条件判断
<%--相当于if else结构,当有一条件满足后其他条件都不满足,证:此实例只输出 10>5--%> <c:choose> <c:when test="${10>5}"> 10>5<br /> </c:when> <c:when test="${6>2}"> 6>2<br /> </c:when> <c:otherwise> 条件都不成立 </c:otherwise> </c:choose>
<c:forEach>标签:遍历
<%-- begin : 从哪个元素开始遍历,默认从0开始 end : 到哪个元素结束。默认到最后一个元素 step : 步长,默认1 items : 需要遍历的数据(集合) var : 每个元素的名称 varStatus: 当前正在遍历元素的状态对象。(count属性:当前位置,从1开始)
--%> <%
//Student{
// public String name;
// public int age;
// public Student(String Name,int Age){
// this.name = Name;
// this.age = age;
// }
//} //List数据准备 List<Student> list = new ArrayList<Student>(); list.add(new Student("name001",18)); list.add(new Student("name002",19)); list.add(new Student("name003",20)); pageContext.setAttribute("list",list);//放入域中 //Map数据准备 Map<String,Student> map = new HashMap<String,Student>(); map.put("001",new Student("name001",18)); map.put("002",new Student("name002",19)); map.put("003",new Student("name003",20)); pageContext.setAttribute("map",map);//放入域中 //array数据准备 Student[] array = new Student[]{ new Student("name001",18), new Student("name002",19), new Student("name003",20)}; pageContext.setAttribute("array",array);//放入域中 %> <%--遍历list --%> <c:forEach var="student" begin="0" end="2" items="${list}" step="1" varStatus="varSta"> name:${student.name}---age:${student.age}<br/> </c:forEach> <%--遍历map --%> <c:forEach var="student" begin="0" end="2" items="${map}" step="1" varStatus="varSta"> key:${student.key}---name:${student.value.name}---age:${student.value.age}<br/> </c:forEach> <%--遍历array --%> <c:forEach var="student" begin="0" end="2" items="${array}" step="1" varStatus="varSta"> name:${student.name}---age:${student.age}<br/> </c:forEach> <%--一般遍历集合或者数组都是全部遍历,所以只写2个属性var和items,其他取默认值 --%> <c:forEach var="student" items="${array}"> name:${student.name}---age:${student.age}<br/> </c:forEach>
<c:forTokens>标签:切割字符串
<%-- 切割字符串,相当于split函数 var:切割出来的每一部分字符串 items:要切割的字符串 delims:分割的字符,若内容为字符串,则这个字符串的每个字符都会当作一个分割的字符 如:items="a-b-c=d=e" dilims="-=",分割的结果为 a,b,c,d,e --%> <% //数据准备 String str = "a-b-c=d=e"; pageContext.setAttribute("str", str); %> <c:forTokens var="item" items="${str}" delims="-="> ${item}<br /> </c:forTokens>
当JSTL标签库已经无法满足我们的需求时候,就需要自己开发自定义标签,来满足我们的需求,自定义标签实际上是一个普通的java类,继承SimpleTagSupport类。
在介绍自定义标签之前,先介绍SimpleTagSupport类:
SimpleTagSupport类继承自SimpleTag接口,而SimpleTag接口主要有以下4个方法,也可将这四个方法理解为标签处理器类的生命周期:
1 public interface SimpleTag extends JspTag { 2 3 /** 4 * 执行标签时调用的方法,一定会调用 5 */ 6 public void doTag() throws javax.servlet.jsp.JspException, java.io.IOException; 7 8 /** 9 * 设置父标签对象,传入父标签对象,当标签存在父标签时会调用 10 */ 11 public void setParent( JspTag parent ); 12 13 /** 14 * 设置JspContext对象,其实他真实传入的是其子类PageContext 15 */ 16 public void setJspContext( JspContext pc ); 17 18 /** 19 * 设置标签体内容。标签体内容封装到JspFragment对象 中,然后传入JspFragment对象 20 */ 21 public void setJspBody( JspFragment jspBody ); 22 23 }
SimpleTagSupport类在其基础上封装出了3个方法,方便自定义标签类编写,该方法实现也比较简单,无非就是内部维护一个变量,通过set方法将其赋值,再返回该对象,这样继承SimpleTagSupport拿到如PageContext对象就直接调用getJspContext()即可。
1 /*SimpleTagSupport 类的一部分*/ 2 public class SimpleTagSupport implements SimpleTag 3 { 4 /** Reference to the enclosing tag. */ 5 private JspTag parentTag; 6 7 /** The JSP context for the upcoming tag invocation. */ 8 private JspContext jspContext; 9 10 /** The body of the tag. */ 11 private JspFragment jspBody; 12 13 public void setParent( JspTag parent ) { 14 this.parentTag = parent; 15 } 16 17 public JspTag getParent() { 18 return this.parentTag; 19 } 20 21 public void setJspContext( JspContext pc ) { 22 this.jspContext = pc; 23 } 24 25 protected JspContext getJspContext() { 26 return this.jspContext; 27 } 28 29 public void setJspBody( JspFragment jspBody ) { 30 this.jspBody = jspBody; 31 } 32 33 protected JspFragment getJspBody() { 34 return this.jspBody; 35 } 36 }
编写自定义标签的步骤:
以写一个自定义标签为例:功能:向浏览器输出一句话“酒香逢 博客园欢迎您”
1)编写一个普通的java类(OutInfo.java),继承SimpleTagSupport类,并重写doTag方法。(jsp文件最后编译为java文件,查看该java文件可知_jspService方法中,会创建标签类OutInfo对象,并执行doTag方法。编译后原文件路径:如D:\Program Files\Tomcat\apache-tomcat-6.0.39\work\Catalina\localhost\Tag\org\apache\jsp\xxx.java)
1 /* 2 * OutInfo.java 3 */ 4 public class OutInfo extends SimpleTagSupport { 5 6 @Override 7 public void doTag() throws JspException, IOException { 8 PageContext pageContext = (PageContext)getJspContext(); 9 pageContext.getOut().write("酒香逢 博客园欢迎您"); 10 } 11 }
2)在web项目的WEB-INF目录下建立tld文件(jxf.tld),这个tld文件为标签库的声明文件,并配置好相应的信息。(可以参考核心标签库的tld文件,如:项目/Java EE 5 Libraries/jstl-1.2jar/META-INF/c.tld)
1 <?xml version="1.0" encoding="UTF-8" ?> 2 3 <taglib xmlns="http://java.sun.com/xml/ns/javaee" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd" 6 version="2.1"> 7 8 <description>JSTL 1.1 core library</description> 9 <display-name>JSTL core</display-name> 10 <tlib-version>1.1</tlib-version> 11 <!--标签库前缀 taglib指令中的prefix属性 --> 12 <short-name>jxf</short-name> 13 <!--tld文件的唯一标记 taglib指令中的uri属性 --> 14 <uri>http://jxf.tag</uri> 15 16 <tag> 17 <description> 18 这是自定义标签的描述信息,可以在MyEclipse中有提示 19 </description> 20 <!-- 标签名 --> 21 <name>outInfo</name> 22 <!-- 标签类的完名 --> 23 <tag-class>jxf.OutInfo</tag-class> 24 <body-content>scriptless</body-content> 25 <!-- <attribute> 26 <description> 27 这是属性的描述信息 28 </description> 29 <name>var</name> 30 <required>false</required> 31 <rtexprvalue>false</rtexprvalue> 32 </attribute> --> 33 </tag> 34 35 </taglib>
3)在jsp页面的头部导入自定义标签库
<%@taglib uri="http://jxf.tag" prefix="jxf" %>
4)在jsp中使用自定义标签
<jxf:outInfo></jxf:outInfo>
5)jsp页面
1 <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> 2 <%@taglib uri="http://jxf.tag" prefix="jxf" %> 3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 4 <html> 5 <head> 6 <title>自定义标签</title> 7 </head> 8 <body> 9 <jxf:outInfo></jxf:outInfo> 10 </body> 11 </html>
自定义标签能够做的:
1)控制标签体内容输出
1 /* 2 * 1)输出标签题内容 3 */ 4 JspFragment jspBody = getJspBody(); 5 //方法:invoke(java.io.Writer out) 6 //当参数为null时等价于 jspBody.invoke(getJspContext().getOut()); 7 jspBody.invoke(null);
2)控制标签余下内容输出
1 /* 2 * 2)控制标签体余下内容是否输出 3 * 抛出一个SkipPageException异常后,标签体余下内容输出 4 */ 5 throw new SkipPageException();
3)改变标签体内容
1 /* 2 * 3)改变标签体内容并输出到浏览器 3 */ 4 //获取到标签体内容,并保存到自定义的款冲字符流中 5 StringWriter sw = new StringWriter(); 6 //jspBodyString得到的即是标签体的内容 7 String jspBodyString = sw.toString(); 8 jspBodyString = "简单将字符串的值改变掉"; 9 getJspContext().getOut().write(jspBodyString);//输出到浏览器
4)带属性的标签(以模仿c标签的<c:choose>+<c:when>+<c:otherwise>标签为例)
编写3个自定义标签处理器类 ChooseTag.java、 When.java、 Otherwise.jave
1 /* 2 * ChooseTag.java 3 */ 4 public class ChooseTag extends SimpleTagSupport { 5 private boolean flag = false; 6 7 public boolean isFlag() { 8 return flag; 9 } 10 11 public void setFlag(boolean flag) { 12 this.flag = flag; 13 } 14 @Override 15 public void doTag() throws JspException, IOException { 16 getJspBody().invoke(null); 17 } 18 }
/* * WhenTag.java */ public class WhenTag extends SimpleTagSupport { private boolean test; //tld文件中的属性必须要有对应的set方法,否则报错 public void setTest(boolean test) { this.test = test; } @Override public void doTag() throws JspException, IOException { ChooseTag parent = (ChooseTag)getParent(); if(!parent.isFlag()){ if(test){ parent.setFlag(true); getJspBody().invoke(null); } } } }
1 /* 2 * OtherwiseTag.java 3 */ 4 public class OtherwiseTag extends SimpleTagSupport { 5 @Override 6 public void doTag() throws JspException, IOException { 7 ChooseTag parent = (ChooseTag)getParent(); 8 if(!parent.isFlag()){ 9 getJspBody().invoke(null); 10 } 11 } 12 }
tld文件
1 <?xml version="1.0" encoding="UTF-8" ?> 2 3 <taglib xmlns="http://java.sun.com/xml/ns/javaee" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd" 6 version="2.1"> 7 8 <description>JSTL 1.1 core library</description> 9 <display-name>JSTL core</display-name> 10 <tlib-version>1.1</tlib-version> 11 <!--标签库前缀 taglib指令中的prefix属性 --> 12 <short-name>jxf</short-name> 13 <!--tld文件的唯一标记 taglib指令中的uri属性 --> 14 <uri>http://jxf.tag</uri> 15 16 <tag> 17 <name>chooseTag</name> 18 <tag-class>jxf.ChooseTag</tag-class> 19 <body-content>scriptless</body-content> 20 </tag> 21 <tag> 22 <description> 23 自定义的when标签 24 </description> 25 <name>whenTag</name> 26 <tag-class>jxf.WhenTag</tag-class> 27 <body-content>scriptless</body-content> 28 <attribute> 29 <description> 30 when标签属性test 31 </description> 32 <!-- 标签处理器类中的必须要有对应的set方法,否则会报错,如此时对应的标签处理器类中应有getTest()方法。 --> 33 <name>test</name> 34 <!-- 该属性是否是必须的 ,true为必须的,false为非必须的--> 35 <required>true</required> 36 <!-- 该属性是否支持EL表达式 true支持,false不支持 --> 37 <rtexprvalue>true</rtexprvalue> 38 </attribute> 39 </tag> 40 <tag> 41 <name>otherwiseTag</name> 42 <tag-class>jxf.OtherwiseTag</tag-class> 43 <body-content>scriptless</body-content> 44 </tag> 45 </taglib>
jsp代码
1 <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> 2 <%@taglib uri="http://jxf.tag" prefix="jxf"%> 3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 4 <html> 5 <head> 6 <title>模仿c标签库的choose,when,otherwise</title> 7 </head> 8 <body> 9 <jxf:demoTag>标签体内容</jxf:demoTag> 10 标签体余下内容 11 <br /> 12 <jxf:chooseTag> 13 <jxf:whenTag test="${4>5}"> 14 4>5是不输出的 15 </jxf:whenTag> 16 <jxf:whenTag test="${10>5}"> 17 10>5是成立的 18 </jxf:whenTag> 19 <jxf:whenTag test="${9>5}"> 20 9>5是成立的,但是不输出 21 </jxf:whenTag> 22 <jxf:otherwiseTag> 23 当条件都不成立时候输出(由于第二个提条件成立,故不应输出) 24 </jxf:otherwiseTag> 25 </jxf:chooseTag> 26 </body> 27 </html>