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

    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类)
     1 <?xml version="1.0" encoding="UTF-8"?>  
     2     <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">  
     3     <taglib>     <!-- 自定义库标签的根 -->  
     4     <tlibversion>1.2</tlibversion>     <!-- 版本号 -->  
     5     <jspversion>1.1</jspversion>       <!-- JSP版本号 -->  
     6     <shortname>stu</shortname>        <!-- prefix="stu"标签名称-->  
     7     <uri>StudentTags</uri>   <!-- uri="StudentTags" 外界导入标签时,认识的名字,很重要。-->  
     8       
     9     <tag>  
    10      <name>selectAll</name>                            <!-- 标签名称 -->  
    11      <tagclass>com.bjsxt.sxf.tag.SeclectAllSt</tagclass>          <!-- 对应的java类的全路径 -->  
    12     </tag>  
    13       
    14     <!-- 有属性的标签,可以有多个属性  <attribute>并列 -->  
    15       <tag>  
    16            <name>selectBySex</name>  <!-- 标签名称 -->
    17             <tagclass>com.bjsxt.sxf.tag.SeclectStBySex</tagclass> 
    18             <attribute>   <!-- 对应标签的属性。 -->  
    19                  <name>sex</name>  
    20                  <required>true</required>  <!-- 是必需写的属性,即没有写属性标签不能被正常使用 -->  
    21             </attribute>         
    22        </tag>  
    23       <!-- 按班级学生id查询出班级集合,存放到属性var指定的变量中,然后利用s标签的迭代标签,将var指定的变量存放的学生集合遍历出来 -->
    24        <tag>
    25                <name>selectByClassId</name> <!-- 标签名称 --> 
    26                <tagclass>com.bjsxt.sxf.tag.MyTag</tagclass> <!-- 对应的java类的全路径 -->  
    27                <body-content>JSP</body-content><!-- 如果不需要标签体则设置empty,反之设定jsp,内部可以运行jsp所有的语法 -->
    28                <attribute>
    29                    <name>classId</name><!--指定属性名 和标签java类一致-->
    30                    <required>true</required><!--该属性是否是必须,如果非必须没设置则为空。 -->
    31                    <rtexprvalue>true</rtexprvalue><!-- 该属性能不能动态使用表达式为该属性赋值 true可以  false不可以  使用脚本和EL表达式来获取动态的值 -->
    32                </attribute>
    33                <attribute>
    34                    <name>var</name>
    35                    <required>true</required>
    36                    <rtexprvalue>false</rtexprvalue>
    37                </attribute>
    38                <attribute>
    39                    <name>num</name>
    40                    <required>false</required>
    41                    <rtexprvalue>false</rtexprvalue>
    42                </attribute>
    43        </tag>
    44        
    45     </taglib>  
    View Code

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

     1 package com.bjsxt.sxf.tag;
     2 
     3 import javax.servlet.http.HttpServletRequest;
     4 import javax.servlet.http.HttpServletResponse;
     5 
     6 import org.apache.struts2.components.Component;
     7 import org.apache.struts2.views.jsp.ComponentTagSupport;
     8 
     9 import com.opensymphony.xwork2.util.ValueStack;
    10 /**
    11  * 标签体,传递标签的参数
    12 * @ClassName: MyTag 
    13 * @Description: TODO(这里用一句话描述这个类的作用) 
    14 * @author 尚晓飞
    15 * @date 2014-10-21 下午5:07:16 
    16 *
    17  */
    18 public class MyTag extends ComponentTagSupport {
    19     private String classId;//标签属性
    20     private String num;//标签属性
    21     private String var;//标签属性
    22     
    23     
    24     //继承ComponentTagSupport类是为了获得标签中的属性值,并包装成Component对象。继承Component类是为了从Struts2中的ValueStack中获得相对应的值。
    25     @Override
    26     public Component getBean(ValueStack valueStack, HttpServletRequest req,
    27             HttpServletResponse resp) {
    28         System.out.println("MyTag.getBean()");//标签运行第一站
    29         return new StuComponent(valueStack, req, resp);//返回标签业务逻辑类的对象
    30     }
    31     
    32     //将标签传递过来的值,赋值给标签业务逻辑类中的属性,业务处理逻辑会用到
    33     @Override
    34     protected void populateParams() {
    35         super.populateParams();
    36         System.out.println("MyTag.populateParams()");//标签运行第三站
    37         StuComponent stuComponent=(StuComponent) getComponent();
    38         stuComponent.setVar(var);//将前台传来的存放结果集合的变量名,赋值给逻辑类的父类中一个属性。个人理解,值栈中的一个存放结果集的集合引用。
    39         stuComponent.setClassId(classId);
    40         stuComponent.setNum(num);
    41         //stuComponent.setVard(var);将储存数据的变量传递到标签逻辑类中
    42         
    43     }
    44 
    45     public String getClassId() {
    46         return classId;
    47     }
    48 
    49     public void setClassId(String classId) {
    50         this.classId = classId;
    51     }
    52 
    53     
    54     public String getNum() {
    55         return num;
    56     }
    57 
    58     public void setNum(String num) {
    59         this.num = num;
    60     }
    61 
    62     public String getVar() {
    63         return var;
    64     }
    65 
    66     public void setVar(String var) {
    67         this.var = var;
    68     }
    69     
    70     
    71 
    72 }
    View Code

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

      1 package com.bjsxt.sxf.tag;
      2 
      3 import java.io.Writer;
      4 import java.util.List;
      5 import java.util.Map;
      6 
      7 import javax.servlet.http.HttpServletRequest;
      8 import javax.servlet.http.HttpServletResponse;
      9 
     10 
     11 import org.apache.struts2.ServletActionContext;
     12 
     13 import org.apache.struts2.components.ContextBean;
     14 import org.apache.struts2.views.annotations.StrutsTag;
     15 import org.apache.struts2.views.annotations.StrutsTagAttribute;
     16 
     17 import org.springframework.context.ApplicationContext;
     18 import org.springframework.web.context.support.WebApplicationContextUtils;
     19 
     20 
     21 
     22 import com.bjsxt.sxf.dao.StudentDao;
     23 import com.bjsxt.sxf.po.Student;
     24 import com.opensymphony.xwork2.util.ValueStack;
     25 
     26 /**
     27  * MyTag标签的业务逻辑
     28 * @ClassName: StuComponent 
     29 * @Description: TODO(这里用一句话描述这个类的作用) 
     30 * @author 尚晓飞
     31 * @date 2014-10-21 下午5:12:31 
     32 *
     33  */
     34 //注解现在还不清楚什么意思,就当时描述作用,没有也行。
     35 @StrutsTag(name="selectByClassId", tldBodyContent="JSP", tldTagClass="com.bjsxt.sxf.tag.MyTag", description="sxf zdy")
     36 public class StuComponent extends ContextBean {
     37     protected  String classId;
     38     protected  String callBack="data";
     39     protected  String num;
     40     protected String vard;
     41     //标签进来,先运行该方法
     42     public StuComponent(ValueStack stack,HttpServletRequest req, HttpServletResponse res) {
     43         super(stack);
     44         System.out.println("StuComponent.StuComponent()");//标签运行第二站
     45         //下面可以直接获取,也可以通过标签体中的populateParams()方法,给该对象中的属性赋值set方法
     46 //        classId=req.getParameter("classId");
     47 //        num=req.getParameter("num");
     48                 
     49     }
     50     
     51     
     52     
     53     
     54     
     55 
     56 
     57     //业务逻辑开始
     58     @Override
     59     public boolean start(Writer writer) {
     60         //班级id
     61         System.out.println("StuComponent.start()");//标签运行第四站
     62         Integer classIds=Integer.valueOf(classId);
     63         //查询出该班级的集合
     64         //ssh框架获取spring的ioc容器,从而获取与数据库交互的dao对象
     65         ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(ServletActionContext.getServletContext());
     66         //获取与数据库交互的dao
     67         StudentDao dao=(StudentDao) app.getBean("StudentDao");
     68         List<Student> students=dao.queryByClassId(classIds);
     69         //获取标签的储存属性名
     70         String varString=getVar();//此方法是继承ContextBean才有的,返回的是存储数据的变量名
     71         if(varString!=null){
     72             callBack=varString;
     73         }
     74         //将得到的数据库数据集合,存放入集合。
     75         //应该是struts2中的值栈,用来存放显示层要去的从数据库查询出来的值
     76         ValueStack stack=getStack();
     77         Map<String, Object> listMap=stack.getContext();
     78         
     79         //标签逻辑类继承ContextBean类时,该类里有getVar()方法返回引用数据的变量
     80         listMap.put(callBack, students);
     81         
     82         //标签类继承Component类时,该类里没有getVar()方法,但可以从标签类中,将引用数据的变量通过 populateParams()
     83         //传递到逻辑类里,直接存放到值栈的map中
     84         //说白了,标签中取出的数据,都是从值栈的map中取,只要值栈的map<key:vlaue>中有key,就能得到value
     85         //listMap.put(vard, students);
     86         
     87         return true;//retrun true则执行标签体内的jsp页面内容,return false则跳过标签体内容,执行标签后面的内容
     88     }
     89 
     90     @Override
     91     public boolean end(Writer writer, String body) {
     92         System.out.println("StuComponent.end()");//标签运行第五站
     93         //清空引用,可以使垃圾回收机制,回收没用的对象,减轻内存压力
     94         getStack().getContext().remove(vard);
     95         
     96         return false;//return false 或true意思暂时不明确
     97     }
     98 
     99 
    100     
    101     public String getClassId() {
    102         return classId;
    103     }
    104     @StrutsTagAttribute(description="classId",required=true)//必须有
    105     public void setClassId(String classId) {
    106         this.classId = classId;
    107     }
    108     public String getCallBack() {
    109         return callBack;
    110     }
    111     public void setCallBack(String callBack) {
    112         this.callBack = callBack;
    113     }
    114     public String getNum() {
    115         return num;
    116     }
    117     @StrutsTagAttribute(description="num",required=false)//非必须
    118     public void setNum(String num) {
    119         this.num = num;
    120     }
    121 
    122 
    123 
    124 
    125 
    126 
    127 
    128     public String getVard() {
    129         return vard;
    130     }
    131 
    132 
    133 
    134 
    135 
    136 
    137 
    138     public void setVard(String vard) {
    139         this.vard = vard;
    140     }
    141 
    142     
    143     
    144     
    145     
    146 
    147 }
    View Code

    第四步:页面测试代码

     1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
     2 <%@ taglib uri="StudentTags" prefix="stu" %>
     3 <%@ taglib uri="/struts-tags" prefix="s"%>
     4 <%
     5 String path = request.getContextPath();
     6 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
     7 %>
     8 
     9 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    10 <html>
    11   <head>
    12   </head>
    13   
    14   <body>
    15     This is my JSP page. <br>
    16     <a href="<%=request.getContextPath()%>/StudentAction!reportStudent.action">班级表单下载</a>
    17     <!-- 查询出所有学生 -->
    18        <stu:selectAll></stu:selectAll>
    19        <!-- 查询出指定性别的学生 -->
    20        <stu:selectBySex sex="男"></stu:selectBySex>
    21        <!-- 查询出指定班级的学生 -->
    22        <stu:selectByClassId var="students" classId="1" >
    23            <table border="2">
    24                <tr>
    25                    <td>id</td>
    26                    <td>姓名</td>
    27                    <td>性别</td>
    28                    <td>班级</td>
    29                </tr>
    30                <s:iterator value="#students" var="stu">
    31                    <tr>
    32                        <td><s:property value="#stu.id"/></td>
    33                        <td><s:property value="#stu.name"/></td>
    34                        <td><s:property value="#stu.sex"/></td>
    35                        <td><s:property value="#stu.classRoom.name"/></td>
    36                    </tr>
    37                </s:iterator>
    38            </table>
    39        </stu:selectByClassId>
    40        
    41        <h1>我是中国人</h1>
    42   </body>
    43   
    View Code

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

     
       
    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>则报错,具体可参考后面附源码。

  • 相关阅读:
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp 8 Web基础
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp7 网络欺诈防范
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp6 MSF基础应用
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp5 信息搜集与漏洞扫描
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp4 恶意代码分析
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp3 免杀原理与实践
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp2 后门原理与实践
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp1 PC平台逆向破解
    2019-2020-1 20175312 20175333 实验五 通讯协议设计
    2019-2020-2 20175320 《网络对抗技术》免考实践报告 手工实现对PE文件的shellcode注入
  • 原文地址:https://www.cnblogs.com/shangxiaofei/p/4040794.html
Copyright © 2011-2022 走看看