jsp中所需jar包
一、jsp标签语言的特点
1.组成
①开始标签
②标签体
③结束标签
组成形式:<开始标签 属性="属性值">标签体</结束标签>
2.分类
可分为以下四种:
①空标签: br、hr...
②ui标签:input、table...
③控制标签:if、foreach...
④数据标签:set标签、out标签...
二:自定义标签开发及步骤
1、助手类(继承BodyTagSupport)
2、重写doStartTag、doAfterBodyTag、doEndTag。
3、标签库描述文件(tld);(tld文件必须保存到WEB-INF目录或其子目录)
4、JSP通过taglib指令导入标签库( <%@taglib uri="http://jsp.veryedu.cn" prefix="z"%>)
标签库描述文件:
<?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">
<description>zking 1.1 core library</description>
<display-name>zking core</display-name>
<tlib-version>1.1</tlib-version>
<short-name>zking</short-name>
<uri>http://java.veryedu.cn</uri>
<validator>
<description>
Provides core validation features for JSTL tags.
</description>
<validator-class>
org.apache.taglibs.standard.tlv.JstlCoreTLV
</validator-class>
</validator>
<tag>
<name>Test</name>
<tag-class>com.mwy.tag.Test</tag-class>
<body-content>JSP</body-content>
</tag>
</taglib>
三:标签生命周期
1.、标签开发的场景的三种路线
①、doStartTag——>SKIP_BODY——>doEndTag
②、doStartTag——>EVAL_BODY_INCLUDE——>doAfterBody——>EVAL_PAGE——>doEndTag
③、doStartTag——>EVAL_BODY_INCLUDE——>doAfterBody——>EVAL_BODY_AGAIN(N次)——>doEndTag
2、返回值
①.SKIP_BODY:跳过主体
②.EVAL_BODY_INCLUDE:计算标签主体内容并输出
③.EVAL_BODY_AGAIN:在计算主体一次
④.EVAL_PAGE:计算页面的后续部分
⑤.SKIP_PAGE:跳过页面的后续部分
测试:
package com.zxy.tag;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
/**
* 三种路线(根据生命周期图整理出来的)
* 1、doStartTag——SKIP_BODY——doEndTag
* 2、doStartTag——EVAL_BODY_INCLUDE——doAfterBody——EVAL_PAGE——doEndTag
* 3、doStartTag——EVAL_BODY_INCLUDE——doAfterBody——EVAL_BODY_AGAIN(N次)——doEndTag
*/
public class Demo1 extends BodyTagSupport{
//第一个例子:根据代码论证这三条路线的执行顺序(涉及三个类:Demo1.java,Demo2.java,Demo3.java)
@Override
public int doStartTag() throws JspException {
System.out.println("Demo1_doStartTag");
//return super.doStartTag();
return SKIP_BODY;
}
@Override
public int doEndTag() throws JspException {
System.out.println("Demo1_doEndTag");
// TODO Auto-generated method stub
return super.doEndTag();
}
}
public class Demo2 extends BodyTagSupport{
//第一个例子:根据代码论证这三条路线的执行顺序(涉及三个类:Demo1.java,Demo2.java,Demo3.java)
@Override
public int doStartTag() throws JspException {
System.out.println("Demo2_doStartTag");
//return super.doStartTag();
return EVAL_BODY_INCLUDE;
}
@Override
public int doAfterBody() throws JspException {
System.out.println("Demo2_doAfterBody");
// TODO Auto-generated method stub
return EVAL_PAGE;
}
@Override
public int doEndTag() throws JspException {
System.out.println("Demo2_doEndTag");
// TODO Auto-generated method stub
return super.doEndTag();
}
}
public class Demo3 extends BodyTagSupport{
//第一个例子:根据代码论证这三条路线的执行顺序(涉及三个类:Demo1.java,Demo2.java,Demo3.java)
@Override
public int doStartTag() throws JspException {
System.out.println("Demo3_doStartTag");
//return super.doStartTag();
return EVAL_BODY_INCLUDE;
}
@Override
public int doAfterBody() throws JspException {
System.out.println("Demo3_doAfterBody");
// TODO Auto-generated method stub
return EVAL_BODY_AGAIN;
}
@Override
public int doEndTag() throws JspException {
System.out.println("Demo3_doEndTag");
// TODO Auto-generated method stub
return super.doEndTag();
}
}
四:实例:
1:z:if标签
1.tag助手继承BodyTagSupport
需要一个变量来控制返回值,从而控制本标签走第一路线还是第二路线
return this.test ? EVAL_BODY_INCLUDE:SKIP_BODY;
package com.zxy.tag;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class If extends BodyTagSupport{
private boolean test;
public boolean isTest() {
return test;
}
public void setTest(boolean test) {
this.test = test;
}
@Override
public int doStartTag() throws JspException {
//需要一个变量来控制返回值。从而控制本标签走第一路线还是第二路线
return this.test ? EVAL_BODY_INCLUDE:SKIP_BODY;
}
@Override
public int doEndTag() throws JspException {
// TODO Auto-generated method stub
return super.doEndTag();
}
}
2.set与out标签
set/out标签,本身是没有标签体的,需要在页面上输出内容,需要借助一个类JspWriter
out标签:
package com.zxy.tag;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
public class OutTag extends BodyTagSupport {
private Object value;
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
@Override
public int doStartTag() throws JspException {
JspWriter out = pageContext.getOut();
try {
out.print(value);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return super.doStartTag();
}
}
标签库描述文件
<tag>
<name>out</name>
<tag-class>com.zxy.OutTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<!-- 自定义标签的成员变量名称-->
<name>value</name>
<!-- 该成员变量是否必传-->
<required>true</required>
<!-- 是否支持EL表达式-->
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
测试
<zking:out value="${name} "></zking:out>
set标签:
package com.zxy.tag;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
import com.sun.glass.ui.Application;
import jdk.nashorn.internal.ir.RuntimeNode.Request;
/**
* 开发一个数据标签
* 用第一条路线
* 1、doStartTag——SKIP_BODY——doEndTag
*只不过,set/out标签,本身是没有标签体的,需要在页面上输出内容,需要借助一个类JspWriter
*
*在没有标签体的情况下,是通过JspWriter来输出内容的
*/
public class SetTag extends BodyTagSupport {
//存放标签的键
private String var;
//存放标签的值,可以是字符串,对象,集合
private Object value;
public String getVar() {
return var;
}
public void setVar(String var) {
this.var = var;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
//set标签
@Override
public int doStartTag() throws JspException {
// 将value值保存到var对应的变量中
//四大作用域:pageContext,Request,session,Application
pageContext.setAttribute(var, value);
return super.doStartTag();
}
}
标签库描述文件
<tag>
<name>set</name>
<tag-class>com.zxy.setTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<!-- 自定义标签的成员变量名称-->
<name>var</name>
<!-- 该成员变量是否必传-->
<required>true</required>
<!-- 是否支持EL表达式-->
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<!-- 自定义标签的成员变量名称-->
<name>value</name>
<!-- 该成员变量是否必传-->
<required>true</required>
<!-- 是否支持EL表达式-->
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
测试
<zking:set var="name" value="zxy"></zking:set>
五:ForEach标签和Select标签
5.1、z:foreach
package com.zxy.tag;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyTagSupport;
/**
* 2.doStartTag...EVAL_BODY_INCLUDE....doAfterBody...EVAL_PAGE...doEndTag
* 3.doStartTag...EVAL_BODY_INCLUDE....doAfterBody...EVAL_BODY_AGAIN...doAfterBody...
* EVAL_BODY_AGAIN...doAfterBody...EVAL_BODY_AGAIN...doEndTag
* 案例5 foreach
* 熟悉第二第三的开发流程
* 实现思路
* 1.最少要有两个参数 var/items
* 2.一定要有标签体,那么对应需要重新doAfterBody方法
* 3.必定有判断条件决定doAfterBody的返回值是EVAL_PAGE还是EVAL_BODY_AGAIN
* 将去元素集合的过程,看成指针下移的过程,如果指针还能指向下一个,那么返回值为EVAL_BODY_AGAIN
* 如果指针没有下一个元素,那么返回值为EVAL_PAGE
* 指针是迭代器里面的产物,所以需要将迭代器保存并提供到doAfterBody中使用
* @author zjjt
*
*/
public class ForeachTag extends BodyTagSupport {
private String var;
private List<Object> items=new ArrayList<>();
public String getVar() {
return var;
}
public void setVar(String var) {
this.var = var;
}
public List<Object> getItems() {
return items;
}
public void setItems(List<Object> items) {
this.items = items;
}
@Override
public int doStartTag() throws JspException {
// 在此处保存迭代器,工doAfterBody中使用
Iterator<Object> it = items.iterator();
pageContext.setAttribute("it",it);
return EVAL_BODY_INCLUDE;
}
@Override
public int doAfterBody() throws JspException {
Iterator<Object> it=(Iterator<Object>) pageContext.getAttribute("it");
if(it.hasNext()) {
// 在页面上需要通过var将集合中的对象拿到
// 让指针下移,it.next()代表了指针下移
pageContext.setAttribute(var, it.next());
// 保存指针下移后的状态
pageContext.setAttribute("it",it);
// 继续循环
return EVAL_BODY_AGAIN;
}else {
// 结束循环
return EVAL_PAGE;
}
}
@Override
public int doEndTag() throws JspException {
// TODO Auto-generated method stub
return super.doEndTag();
}
}
测试中的user类
package com.zxy.entity;
public class User {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public User(String id, String name) {
super();
this.id = id;
this.name = name;
}
public User() {
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}
测试:
测试:
<%
List u=new ArrayList<>();
u.add(new User("1","张三"));
u.add(new User("2","李四"));
u.add(new User("3","王五"));
request.setAttribute("u", u);
%>
<z:foreach items="${u }" var="user">
${user.id }:${user.name }<br>
</z:foreach>
5.2、select标签(美化包括在内)
package com.zxy.tag;
import java.util.ArrayList;
import java.util.List;
import java.lang.reflect.Field;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
import org.apache.commons.beanutils.PropertyUtils;
/**
* 目的:将所学的自定义标签的知识点用于实际项目开发
* 不管是if/set/out/foreach标签那是别人已经具备的功能,直接用别人的就行
* 学习自定义标签理解其底层结构,就是弥补现成C标签没有的功能
* 以前
* 查询下拉框
* <select>
* <option value=''>-==请选择==m</option>
* <option value= '1'>晓哥</option>
* <option checked value='2'>胡哥</option>
* <option value='3'>娜姐</option>
* </ select>
* 修改回显,在这里面有大量的c:foreach. c:if到断
* 不足之处:代码过大。以及凡是涉及到下拉框以及复选框。粗类似的代码过多
* 目前:
* <z:selectc/z: select>
* 目的:通过上述标签能够实现上述代码相同的功能
* 分析属性:
* 1.数据源属懂items,用于遍历展示的 users->List<User>->id=option>value;name=option>text
* 2.对象key属性textKey,用于对应option>value
* 3.对象value属性textval。用于对应option>text
* 4.对象默认key属性headerTextKey,用于对应默认的option>value
* 5.对象默认value属性headerTextval,用于对应默认的option>text
* 6.对象回显值属性selectedVal,用于判断是否数据回显选中
* 没有标签体又需要往页面输出内容
* @author zjjt
*
*/
public class SelectTag extends BodyTagSupport {
private List<Object> items=new ArrayList<Object>();//用于遍历展示的
private String textKey;//用于对应option>value
private String textVal;//用于对应option>text
private String headerTextKey;//用于对应默认的option>value
private String headerTextVal;//用于对应默认的option>text
private String selectedVal;//用于判断是否数据回显选中
//定义属性美化、拓展/操作标签
private String cssStyle;//美化
private String id;//绑定事件
private String className;//美化
public String getCssStyle() {
return cssStyle;
}
public void setCssStyle(String cssStyle) {
this.cssStyle = cssStyle;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
@Override
public int doStartTag() throws JspException {
// TODO Auto-generated method stub
JspWriter out = pageContext.getOut();
try {
out.print(toHTML());
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return super.doStartTag();
}
private String toHTML() throws Exception{
// TODO Auto-generated method stub
StringBuffer sb=new StringBuffer();
sb.append("<select id='"+id+"' class='"+className+"' style='"+cssStyle+"'>");
//拼接默认显示标签
if(headerTextVal!=null&&!"".equals(headerTextVal)) {
sb.append("<option value='"+headerTextKey+"'>"+headerTextVal+"</option>");
}
//循环显示数据源
if(items.size()>0) {
for (Object obj : items) {
//obj对应的user
//希望拿到当前user的id放入option中的value,name放入option中的text
//<option value= '1'>晓哥</option>
//通过反射获取id对应的属性对象
Field textKeyField = obj.getClass().getDeclaredField(textKey);
textKeyField.setAccessible(true);
//获取id对应的值
//textKeyField.get(obj);
//此代码等于上面三行代码
// PropertyUtils.getProperty(obj, textVal);
String value = textKeyField.get(obj).toString();
//修改页面下拉框回显选中
//当下拉框的value值等于selectedVal,那么就要默认下拉框选中
if(value.equals(selectedVal)) {
sb.append("<option selected value= '"+value+"'>"+PropertyUtils.getProperty(obj, textVal)+"</option>");
}else {
sb.append("<option value= '"+value+"'>"+PropertyUtils.getProperty(obj, textVal)+"</option>");
}
}
}
sb.append("</select>");
return sb.toString();
}
// <select>
// <option value=''>-==请选择==m</option>
// <option value= '1'>晓哥</option>
// <option checked value='2'>胡哥</option>
// <option value='3'>娜姐</option>
// </ select>
public List<Object> getItems() {
return items;
}
public void setItems(List<Object> items) {
this.items = items;
}
public String getTextKey() {
return textKey;
}
public void setTextKey(String textKey) {
this.textKey = textKey;
}
public String getTextVal() {
return textVal;
}
public void setTextVal(String textVal) {
this.textVal = textVal;
}
public String getHeaderTextKey() {
return headerTextKey;
}
public void setHeaderTextKey(String headerTextKey) {
this.headerTextKey = headerTextKey;
}
public String getHeaderTextVal() {
return headerTextVal;
}
public void setHeaderTextVal(String headerTextVal) {
this.headerTextVal = headerTextVal;
}
public String getSelectedVal() {
return selectedVal;
}
public void setSelectedVal(String selectedVal) {
this.selectedVal = selectedVal;
}
}
标签库描述文件:
<tag>
<name>select</name>
<tag-class>com.zxy.tag.SelectTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>id</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>cssStyle</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>className</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>items</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>textKey</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>textVal</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>headerTextKey</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>headerTextVal</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>selectedVal</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
测试:
<!-- 模拟新增场景 -->
<z:select textVal="name" items="${u }" textKey="id"></z:select>
<!-- 默认显示 -->
<!-- 模拟修改场景 -->
<z:select selectedVal="u002" textVal="name" items="${u }" textKey="id"></z:select>
<!-- 模拟查询场景 查询所有 -->
<z:select headerTextKey="" headerTextVal="===请选择===" textVal="name" items="${u }" textKey="id"></z:select>
<!-- 美化后 -->
<z:select cssStyle="font-size; 26px;color: red;" textVal="name" items="${u }" textKey="id"></z:select>
see you~