Struts2自定义标签2自定义一个按班级id查询出该班级下的学生,存放进值栈,并遍历出来。

时间:2022-02-09 13:23:17
Struts2自定义标签的流程概念:
(1)需要两个类:标签类(继承相应的tag类),基本类(继承Component)。标签类专门负责从客户端取得用户输入的一些属性,这个普通的jsp自定义标签一样,取出来以后,需要把取出的属性值赋给基本类。从而可以看到基本类里面的属性也跟tag里面差不多。
(2)tag类里面,需要定义你客户端传来的属性。私有化。并相应的set get。
     必须的两个方法是public Component getBean(ValueStack stack,HttpServletRequest req, HttpServletResponse res);
             protected void populateParams();
    第一个方法就是获得一个基本类的对象。在基本类里面需要有传入ValueStack的构造函数,如果基本类逻辑里面需要request或者response,那么需要有传入ValueStack stack, HttpServletRequest req, HttpServletResponse res的构造函数;
    第二个方法是用来将客户端传来的值赋给基本类。这里是继承来的,所以首先调用super的相应方法。我理解上面第一个方法返回的对象就是全局的一个Component对象,也就是第二个方法里面使用的对象。上面这些就是在准备参数。
(3)所有的逻辑都放到了基本类里面了,基本类里面有两个方法是需要覆盖的,当然这是常用的两个方法,还有很多其它的方法,那些继承自jsp里面的 BodyContentTag(好像是)里面的一些方法。简单说说这两个方法是一个是public boolean start(Writer writer);public boolean end(Writer writer);顾名思义,start是标签开始时的输出,end是标签结束时的输出。这里都必须执行父类里面的方法,因为很多的输出Struts2都做 好了,所以要继承过来。然后再将自己需要输出的逻辑通过writer输出字符串就可以了。
    这里面需要注意start的返回值,如果是true表示将标签内的body内容显示出来,否则不显示。end好像无所谓。
第一步:建立tld文件,str.tld在项目根目录webroot/web-inf下(类似web.xml项目启动时,读取tld文件,利用反射,实例化标签对应的java类)
 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<taglib> <!-- 自定义库标签的根 -->
<tlibversion>1.2</tlibversion> <!-- 版本号 -->
<jspversion>1.1</jspversion> <!-- JSP版本号 -->
<shortname>stu</shortname> <!-- prefix="stu"标签名称-->
<uri>StudentTags</uri> <!-- uri="StudentTags" 外界导入标签时,认识的名字,很重要。--> <tag>
<name>selectAll</name> <!-- 标签名称 -->
<tagclass>com.bjsxt.sxf.tag.SeclectAllSt</tagclass> <!-- 对应的java类的全路径 -->
</tag> <!-- 有属性的标签,可以有多个属性 <attribute>并列 -->
<tag>
<name>selectBySex</name> <!-- 标签名称 -->
<tagclass>com.bjsxt.sxf.tag.SeclectStBySex</tagclass>
<attribute> <!-- 对应标签的属性。 -->
<name>sex</name>
<required>true</required> <!-- 是必需写的属性,即没有写属性标签不能被正常使用 -->
</attribute>
</tag>
<!-- 按班级学生id查询出班级集合,存放到属性var指定的变量中,然后利用s标签的迭代标签,将var指定的变量存放的学生集合遍历出来 -->
<tag>
<name>selectByClassId</name> <!-- 标签名称 -->
<tagclass>com.bjsxt.sxf.tag.MyTag</tagclass> <!-- 对应的java类的全路径 -->
<body-content>JSP</body-content><!-- 如果不需要标签体则设置empty,反之设定jsp,内部可以运行jsp所有的语法 -->
<attribute>
<name>classId</name><!--指定属性名 和标签java类一致-->
<required>true</required><!--该属性是否是必须,如果非必须没设置则为空。 -->
<rtexprvalue>true</rtexprvalue><!-- 该属性能不能动态使用表达式为该属性赋值 true可以 false不可以 使用脚本和EL表达式来获取动态的值 -->
</attribute>
<attribute>
<name>var</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>num</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag> </taglib>

第二步:建立标签类MyTag.java继承ComponentTagSupport类

 package com.bjsxt.sxf.tag;

 import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.struts2.components.Component;
import org.apache.struts2.views.jsp.ComponentTagSupport; import com.opensymphony.xwork2.util.ValueStack;
/**
* 标签体,传递标签的参数
* @ClassName: MyTag
* @Description: TODO(这里用一句话描述这个类的作用)
* @author 尚晓飞
* @date 2014-10-21 下午5:07:16
*
*/
public class MyTag extends ComponentTagSupport {
private String classId;//标签属性
private String num;//标签属性
private String var;//标签属性 //继承ComponentTagSupport类是为了获得标签中的属性值,并包装成Component对象。继承Component类是为了从Struts2中的ValueStack中获得相对应的值。
@Override
public Component getBean(ValueStack valueStack, HttpServletRequest req,
HttpServletResponse resp) {
System.out.println("MyTag.getBean()");//标签运行第一站
return new StuComponent(valueStack, req, resp);//返回标签业务逻辑类的对象
} //将标签传递过来的值,赋值给标签业务逻辑类中的属性,业务处理逻辑会用到
@Override
protected void populateParams() {
super.populateParams();
System.out.println("MyTag.populateParams()");//标签运行第三站
StuComponent stuComponent=(StuComponent) getComponent();
stuComponent.setVar(var);//将前台传来的存放结果集合的变量名,赋值给逻辑类的父类中一个属性。个人理解,值栈中的一个存放结果集的集合引用。
stuComponent.setClassId(classId);
stuComponent.setNum(num);
//stuComponent.setVard(var);将储存数据的变量传递到标签逻辑类中 } public String getClassId() {
return classId;
} public void setClassId(String classId) {
this.classId = classId;
} public String getNum() {
return num;
} public void setNum(String num) {
this.num = num;
} public String getVar() {
return var;
} public void setVar(String var) {
this.var = var;
} }

第三步:建立标签业务逻辑类StuComponent.java类继承ContextBean类

 package com.bjsxt.sxf.tag;

 import java.io.Writer;
import java.util.List;
import java.util.Map; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.struts2.ServletActionContext; import org.apache.struts2.components.ContextBean;
import org.apache.struts2.views.annotations.StrutsTag;
import org.apache.struts2.views.annotations.StrutsTagAttribute; import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils; import com.bjsxt.sxf.dao.StudentDao;
import com.bjsxt.sxf.po.Student;
import com.opensymphony.xwork2.util.ValueStack; /**
* MyTag标签的业务逻辑
* @ClassName: StuComponent
* @Description: TODO(这里用一句话描述这个类的作用)
* @author 尚晓飞
* @date 2014-10-21 下午5:12:31
*
*/
//注解现在还不清楚什么意思,就当时描述作用,没有也行。
@StrutsTag(name="selectByClassId", tldBodyContent="JSP", tldTagClass="com.bjsxt.sxf.tag.MyTag", description="sxf zdy")
public class StuComponent extends ContextBean {
protected String classId;
protected String callBack="data";
protected String num;
protected String vard;
//标签进来,先运行该方法
public StuComponent(ValueStack stack,HttpServletRequest req, HttpServletResponse res) {
super(stack);
System.out.println("StuComponent.StuComponent()");//标签运行第二站
//下面可以直接获取,也可以通过标签体中的populateParams()方法,给该对象中的属性赋值set方法
// classId=req.getParameter("classId");
// num=req.getParameter("num"); } //业务逻辑开始
@Override
public boolean start(Writer writer) {
//班级id
System.out.println("StuComponent.start()");//标签运行第四站
Integer classIds=Integer.valueOf(classId);
//查询出该班级的集合
//ssh框架获取spring的ioc容器,从而获取与数据库交互的dao对象
ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(ServletActionContext.getServletContext());
//获取与数据库交互的dao
StudentDao dao=(StudentDao) app.getBean("StudentDao");
List<Student> students=dao.queryByClassId(classIds);
//获取标签的储存属性名
String varString=getVar();//此方法是继承ContextBean才有的,返回的是存储数据的变量名
if(varString!=null){
callBack=varString;
}
//将得到的数据库数据集合,存放入集合。
//应该是struts2中的值栈,用来存放显示层要去的从数据库查询出来的值
ValueStack stack=getStack();
Map<String, Object> listMap=stack.getContext(); //标签逻辑类继承ContextBean类时,该类里有getVar()方法返回引用数据的变量
listMap.put(callBack, students); //标签类继承Component类时,该类里没有getVar()方法,但可以从标签类中,将引用数据的变量通过 populateParams()
//传递到逻辑类里,直接存放到值栈的map中
//说白了,标签中取出的数据,都是从值栈的map中取,只要值栈的map<key:vlaue>中有key,就能得到value
//listMap.put(vard, students); return true;//retrun true则执行标签体内的jsp页面内容,return false则跳过标签体内容,执行标签后面的内容
} @Override
public boolean end(Writer writer, String body) {
System.out.println("StuComponent.end()");//标签运行第五站
//清空引用,可以使垃圾回收机制,回收没用的对象,减轻内存压力
getStack().getContext().remove(vard); return false;//return false 或true意思暂时不明确
} public String getClassId() {
return classId;
}
@StrutsTagAttribute(description="classId",required=true)//必须有
public void setClassId(String classId) {
this.classId = classId;
}
public String getCallBack() {
return callBack;
}
public void setCallBack(String callBack) {
this.callBack = callBack;
}
public String getNum() {
return num;
}
@StrutsTagAttribute(description="num",required=false)//非必须
public void setNum(String num) {
this.num = num;
} public String getVard() {
return vard;
} public void setVard(String vard) {
this.vard = vard;
} }

第四步:页面测试代码

 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="StudentTags" prefix="stu" %>
<%@ taglib uri="/struts-tags" prefix="s"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head> <body>
This is my JSP page. <br>
<a href="<%=request.getContextPath()%>/StudentAction!reportStudent.action">班级表单下载</a>
<!-- 查询出所有学生 -->
<stu:selectAll></stu:selectAll>
<!-- 查询出指定性别的学生 -->
<stu:selectBySex sex="男"></stu:selectBySex>
<!-- 查询出指定班级的学生 -->
<stu:selectByClassId var="students" classId="1" >
<table border="2">
<tr>
<td>id</td>
<td>姓名</td>
<td>性别</td>
<td>班级</td>
</tr>
<s:iterator value="#students" var="stu">
<tr>
<td><s:property value="#stu.id"/></td>
<td><s:property value="#stu.name"/></td>
<td><s:property value="#stu.sex"/></td>
<td><s:property value="#stu.classRoom.name"/></td>
</tr>
</s:iterator>
</table>
</stu:selectByClassId> <h1>我是中国人</h1>
</body>

第五步:效果图(只截图了最后一个自定义标签的效果图)

Struts2自定义标签2自定义一个按班级id查询出该班级下的学生,存放进值栈,并遍历出来。

 
   
struts2自定义标签编写tld文件时。<body-content>的意思
 
body-content的值有下面4种:

<xsd:enumeration value="tagdependent"/>

<xsd:enumeration value="JSP"/>

<xsd:enumeration value="empty"/>

<xsd:enumeration value="scriptless"/>

tagdependent标签体内容直接被写入BodyContent,由自定义标签类来进行处理,而不被JSP容器解释,

如下:

<test:myList>

select name,age from users

</test:myList>

JSP接受所有JSP语法,如定制的或内部的tag、scripts、静态HTML、脚本元素、JSP指令和动作。如:

<my:test>

<%=request.getProtocol()%>      //

</my:test>

具体可参考后面附源码。

empty空标记,即起始标记和结束标记之间没有内容。

下面几种写法都是有效的,

<test:mytag />

<test:mytag uname="Tom" />

<test:mytag></test:mytag>

scriptless接受文本、EL和JSP动作。如上述使用<body-content> scriptless </body-content>则报错,具体可参考后面附源码。

Struts2自定义标签2自定义一个按班级id查询出该班级下的学生,存放进值栈,并遍历出来。的更多相关文章

  1. Struts2自定义标签4自定义分页标签

    第一步:webroot/web-inf下的str.tld文件 <?xml version="1.0" encoding="UTF-8"?> < ...

  2. 如何将自定义标签封装成一个Jar包

    当我们在一个web应用中开发好一些自定义标签的时候,这些自定义标签通常有标签处理器Java类,和一个描述这些标签tld文件,如果我们想在以后别的web工程中还能用上这些标签,可以将这些自定义标签封装在 ...

  3. Jsp开发自定义标签,自定义标签将字符串转成指定的时间格式显示

    本例以将 字符串格式的时间转成指定的时间格式显示. 第一步.定义一个标签处理程序类,需要集成javax.servlet.jsp.tagext.TagSupport,代码如下: import java. ...

  4. Android 之 自定义标签 和 自定义组件

    1    自定义标签 这是我的模板项目目录     既然想像 android:text  那样使用自己的标签,那么首先得有标签. 在 res/values/ 下我新建了个 mm_tag.xml (切记 ...

  5. django-DIL模板自定义过滤器,自定义标签,自定义包含标签

    自定义过滤器 DTL模板语言生来只是为了方便的展示信息,所以与编程语言相比显得有点薄弱,有时候不能满足我们的需求.因此django提供了一个接口,让开发者能自定义标签和过滤器. 首先,你需要添加一个t ...

  6. 一个学生分数表,用sql语句查询出各班级的前三名

    昨天去一家公司面试,被这道题难住了,哎,又失去一次好的机会. 回来 之后就再想这个问题 表结构及数据如下:

  7. Struts2自定义标签3模仿原有的s&colon;if s&colon;elseif s&colon;else自定义自己的if elsif else

    第一步:webroot/web-inf下简历str.tld文件 <?xml version="1.0" encoding="UTF-8"?> &lt ...

  8. &lbrack;JavaWeb基础&rsqb; 012&period;Struts2 自定义标签使用

    在做开发中,我们会把一些比较经常使用到的代码封装起来,这样可以加快开发的速度和减少错误,并且在修改bug可以一次修改多次修复.那么在前端页面上,如果我们要经常用到公用的显示功能,并涉及到服务端逻辑操作 ...

  9. EL函数以及自定义标签的应用

    一.EL函数(调用普通类的静态方法) 编写步骤(自定义EL函数的编写步骤即自定义标签的编写步骤): ①编写一个普通的java类,提供一个静态方法,功能自定,例如下: package cn.wzbril ...

随机推荐

  1. Visual C&plus;&plus;中的一些编程小技巧

    在应用程序的任意地方实现窗体的最大化.最小化.正常窗口等功能 // 设置Windows窗体的状态void CMinWindowsDlg::SetWindowState(int nWindowSize) ...

  2. 在WINDOWS上安装oracle database 11

    1:在CD-ROM中插入oracle database 11G安装盘会自动运行程序,打开[欢迎使用]窗口 2:弹出[选择安装类型] 3:弹出[制定主目录详细信息]‘oracle基目录’:用于设置环境变 ...

  3. 移位操作&lt&semi;&lt&semi;和&gt&semi;&gt&semi;,是逻辑数字上的移动(和大端小端无关)

    问题描述 这几天帮同事调试DSP TMS320F28335,这鬼东西蛋疼死了.char是16bit的,16位就是他的最小内存单元.但是PC机串口发过来的有8bit的数据,然后转换就出问题. 一开始不知 ...

  4. 试用windows Azure

    试用windows Azure, 需要国外手机注册,信用卡注册. windows操作系统,只有2008R2,2012,2012R2可以选择,我选择XS最低档,然后选2012R2,欧洲数据中心,那个慢啊 ...

  5. RSA和DES------加密和解密类

    public class CryptogramUtil { //******************************************************************** ...

  6. IE浏览器下面要实现滤镜(transparent),必须要加filter

    遇到的问题是: ie9下面的a标签样式是background-color:transparent;导致链接失效,点不动.这个问题跟IE9及其以下a标签链接加 background-color:tran ...

  7. Swift 变量、常量、数据类型

    import Foundation print("HelloSwift") // 声明变量 var a = var b = a = b = // 常量 let c = a+b va ...

  8. No1&lowbar;7&period;类和对象&lowbar;Java学习笔记

    一.面向对象的特点:a.封装:封装是面向对象的核心思想,将对象的属性和行为封装起来的载体就是类,类通常对客户隐藏其实现细节,这就是封装的思想: 保证了类内部数据的完整性,应用该类的用户不能轻易直接操纵 ...

  9. meta标签的少许语法&comma;慢慢收集中&period;&period;&period;

    收集了一些meta的语法,也将不断的更新.不断做点滴的收集,总之,为了前端这些东西呀,我也是操碎了心... 1 <meta http-equiv="Content-Type" ...

  10. 数十种TensorFlow实现案例汇集:代码&plus;笔记(转)

    转:https://www.jiqizhixin.com/articles/30dc6dd9-39cd-406b-9f9e-041f5cbf1d14 这是使用 TensorFlow 实现流行的机器学习 ...