zoukankan      html  css  js  c++  java
  • (八)Struts标签基础(一)

    一、Struts标签分类

    二、标签的使用

      2.1  标签的主题

    • 主题的设置与struts.xml中的常量<constant name="struts.ui.theme" value="xhtml" /> 决定。
    • 每个主题都会对一些标签产生作用,而这些作用被定义在一些文件文件里,比如

      checkbox.ftl这个文件定义的是对checkbox标签产生作用的语法。

    • 主题共有以下几种(版本为struts2-core-2.3.14.jar):

    路径为:struts2-core-2.3.14.jar包里的

        2.1.1  默认主题即template.xhtml , 会给标签自动添加一些属性或者子标签,可能打乱我们设计好的布局

    <body>
        <pre>
            <h3>默认主题</h3>
        <table border="1">
    <tr> <td>用户名</td> <td> <s:textfield></s:textfield> </td> </tr>
        </table>
    </pre> </body>
    • 我们原本的设计是这个表格一共一行且只有两个空格, 但是结果为:

    • 出现这种情况是因为,template.xhtml这个主题会自动帮标签添加一些属性或子标签,查看源代码可知产生了td和tr子标签:


       2.1.2  simple主题(最常用),额外添加的标签很少,不会对我们的布局产生大的影响。

    •  在struts.xml中设置常量<constant name="struts.ui.theme" value="simple" />

     index.jsp

    <body>
        <pre>
            <h3>默认主题</h3>
            <table border="1">
            <tr>
                <td>用户名</td>
                <td> <s:textfield></s:textfield>  </td>
            </tr>
            </table>
        </pre>
    </body>

    查看源码:

    • 对比我们的代码,文本框只添加了name属性
    • 注意:在编写页面标签的时候,最好先把主题设置为simple主题,否则在布局的时候会很麻烦。

        2.1.3  定制主题

    •   步骤: 
      •   在src目录下新建一个文件夹,叫template (template名不能改成别的)
      •   在template中在新建一个文件夹,名字自定义。
      •   在自定义的文件夹中,将要修改的控制的ftl文件拷贝,进行修改。比如我们定制的主题中有对文本输入标签进行设定,那么我们就可以到simple这个主题里找到text.ftl这个文件(注意:text.ftl这个文件主题系统会自动作用在文本框里,如果换成别的名字则无法起作用),然后拷贝到我们自定义的文件夹里,再对text.ftl这个文件进行修改。
      • 把text.ftl中需要添加的文件添加进来,text.ftl需要以下四个文件,然后在simple主题中找到这四个文件然后拷贝到自定义文件夹里即可。

      •   修改text.ftl  

    红框内的内容是我们添加的css属性。

      •   最后在标签中应用此主题,<s:textfield theme="self"></s:textfield>  //self为tempalte包的主题包名,因为这里我们只定义了一个标签的主题,如果我们在在self自定义主题包里对大量标签进行了主题设定,那么我不必每个标签都使用theme属性来引入主题,只需要struts.xml中设置常量<constant name="struts.ui.theme" value="self" /> 即可。

     结果:

    可知标签主题已经变成我们自定义的了。


      2.2  表单标签

        2.2.1  为什么要使用表单标签?(struts表单标签和input标签的区别)

    • struts表单标签可以与Action中的属性进行绑定,可以实现属性值到控件的Value值回填的操作。
    • 示例:
    • index.jsp:
    <body>
        <a href="<%=path%>/tag/form">表单标签</a>
    </body>
    • struts.xml
    <struts>
    
           <constant name="struts.i18n.encoding" value="UTF-8"></constant>
        <constant name="struts.multipart.maxSize" value="209715200"></constant>
        <constant name="struts.action.extension" value="action,,"></constant>
        <constant name="struts.enable.DynamicMethodInvocation" value="true" />
        <constant name="struts.devMode" value="true" />
        <constant name="struts.i18n.reload" value="true"></constant>
        <constant name="struts.ui.theme" value="simple" />
        <constant name="struts.configuration.xml.reload" value="true"></constant>
        <constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
        <constant name="struts.handle.exception" value="true"></constant>
    
        <package name="default" namespace="/tag" extends="struts-default">
            <action name="form" class="tag.FromAction">
                <result name="formjsp">/tag/form.jsp</result>
            </action>
        </package>
    </struts>
    • FromAction .java
    package tag;
    
    public class FromAction {
        private String textName;
        
        public String getTextName() {
            return textName;
        }
    
        public void setTextName(String textName) {
            this.textName = textName;
        }
    
        public String execute(){
            
            this.textName="Action对成员变量textNam赋值后会自动回填到表单中";
             return "formjsp";
        }
    
    }
    • form.jsp
    <body>    
        <pre>
            <s:textfield name="textName"></s:textfield>
        
        </pre>
    </body>

    结果:

    • 由结果可知,我们在Action中设置了一个成员变量textName,而这个成员变量名和<s:textfield name="textName"></s:textfield>是一样的,所以当我们在Action中对textName进行赋值的时候,struts会自动把值回填到<s:textfield name="textName"></s:textfield>标签里。 而如果在input标签中要实现数据的回填,则要在servlet中把值存放在作用域中,然后在jsp页面里用el表达式显示出来才行。
    • input标签实现数据回填:

          把值存放在作用域中 :request.setAttribute("属性", "input标签实现数据回填");

         在jsp页面中把值取出来并显示: <input type="text" value="${requestScope.属性}"/>或者 <input type="text" value="<s:property value="#request.属性"/>"/>(request.setAttribute会吧属性放在广义值栈中的非狭义值栈的位置,所以需要用#来取值)。

      2.1.2  struts表单标签的分类

      •  文本框标签:<s:textfield name="textName"></s:textfield>  name属性用来与Action中的成员变量绑定,请查看上例。
      •   文本域标签:<s:textarea  name="remark"></s:textarea>
      •   密码框标签:<s:password name="passWd"></s:password>
      •   静态单选框_1 :
        <tr>
                <td>静态单选框:</td>
                <td>
        <s:radio list="{'男','女'}" name="sex_1"></s:radio></td>
            </tr>

        静态单选框中的list属性是必填的,list里的{}是OGNL表达式,意思是定义一个集合,本题中{'男','女'}意思是定义一个集合且这个集合中有两个string值。且list中集合有几个值那么就有几个单选按钮。如下图,每个单选按钮的值对应着集合中的值,如右下图。

      •   静态单选框_2 :单选框的值由我们来设置,而不是静态单选框_1 由集合的值来定义。这里用的是OGNL表达式中的“#{}” 表示定义一个MAP集合。
    <tr>
            <td>静态单选框_2:</td>
            <td><s:radio list="#{1:'男',0:'女'}" name="sex_1" ></s:radio></td>
        </tr>

        map集合中的1代表按钮value=“1”,表示如果用户选择的是“男”这个按钮,提交到后台的数据是“1” ,另一个按钮也是如此,查看源码:


    • 单选框使用:

    在JSP页面中创建单选按钮radio的方法:

    <s:radio list="#{'1':'先生','0':'女士'}" name="gender" value="1"/>

    其中list中的键值对表示所有的选项,value表示设置的默认值,如果这个默认值是从后台传过来的,可以这样设置:

    <s:radio list="#{'1':'先生','0':'女士'}" name="gender" value="gender.id"/>

      

    当list属性为Action传过来的Map时 可以自动显示为key-value形式

    <s:radio list="%{map}" name="gender" value="gender.id "/>

    当list属性为Action传过来的List<Gender>时 需要添加 listKey listValue属性  listKey对应提交到数据库中的值  listValue对应显示的文本

    <s:radio list="%{list}" name="gender" value="gender.id" listKey="id" listValue="genderText""/>

      •   动态单选框_1: 按钮value是从数据库或者其他地方获取的。
    • 示例:从数据库中读取值。

      A、  设计数据库并插入数据:

      B、 加载数据库驱动jar包,使用数据库开源工具包(ommons-dbutils-1.3.jar),可以帮助我们快速操作数据库,编写操作数据库的工具类。

        B1. 编写工具类,获取数据库的连接Connection conn,DBUtil.java :

    package DBUtil;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    
    public class DBUtil {
            private static final String DRIVER="com.mysql.jdbc.Driver"; 
            private static final String USER="root"; 
            private static final String PASSWD=""; 
            private static final String URL="jdbc:mysql://127.0.0.1:3306/user?useUnicode=true&characterEncoding=UTF-8"; 
    
    static{
        try {
            Class.forName(DRIVER);
        } catch (Exception e) {
        
            throw new RuntimeException("无法加载驱动包");
        }
    }
     
     public static Connection getConn(){
         Connection conn=null;
         try {
            conn= DriverManager.getConnection(URL,USER,PASSWD);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        
         return conn;
     }
    }

      B2. 使用数据库开源工具包(ommons-dbutils-1.3.jar),这个包的类提供了快速增删改查方法的实现。FormAction.java

    package tag;
    
    import java.util.List;
    
    import org.apache.commons.dbutils.DbUtils;
    import org.apache.commons.dbutils.QueryRunner;
    import org.apache.commons.dbutils.ResultSetHandler;
    import org.apache.commons.dbutils.handlers.BeanListHandler;
    
    import com.opensymphony.xwork2.ActionContext;
    
    import DBUtil.DBUtil;
    import actionUtil.BaseAction;
    import bean.UserBean;
    
    public class FromAction extends BaseAction{
    /**
     * QueryRunner类为数据库开源工具包(ommons-dbutils-1.3.jar)封装的类,
     * 这个类实现了快速对数据库操作的方法。
     * 步骤: 
     * 确认sql语句确定相应的方法,本题中select * 查询结果应该是一个集合。所以应该用QueryRunner的query()方法,
     * 而query()方法里的三个参数为“Connection conn,String sql,ResultSetHandler<T> t”其中ResultSetHandler
     * 是一个接口,我们往query()方法里填的参数不可能是接口而只能是其实现类,其中ResultSetHandler<T>的实现类BeanListHandler<T>类
     * 是本题中需要的类,把这个类的对象加到query()方法里,这个方法将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里,也就是说我们
     * 此时还需要创建一个javaBean类,这个类的成员属性(要有getset方法)要跟数据库中的列名一致。
     * 
     */
    
        public String execute() throws Exception{
            ActionContext actionContext=ActionContext.getContext();
            
            String sql="select * from user order by userId";
            QueryRunner query=new QueryRunner();
            List<UserBean> list=query.query(DBUtil.getConn(), sql, new BeanListHandler<UserBean>(UserBean.class));
            actionContext.put("list", list);
    
             return "formjsp";
        }
    
    }
    • 补充:ResultSetHandler的各个实现类:
      ArrayHandler:把结果集中的第一行数据转成对象数组。
      ArrayListHandler:把结果集中的每一行数据都转成一个对象数组,再存放到List中。
      BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
      BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。//重点
      MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。//重点
      MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List
      ColumnListHandler:将结果集中某一列的数据存放到List中。
      KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里(List<Map>),再把这些map再存到一个map里,其key为指定的列。
      ScalarHandler:将结果集第一行的某一列放到某个对象中。//重点

       

     B3. 在jsp页面把值取出来  from.jsp

    <tr>
            <td>静态单选框_2:</td>
            <td><s:radio list="#list" name="sex_1" listKey="userId" listValue="userName"></s:radio></td>
        </tr>
    • list="#list" 表示往非广义值栈里取值为list的属性值(此时list存放的是javaBean对象的地址,所以取出来的也是地址),listValue="userName" 表示标签的属性value为javaBean对象的userName属性,

    listKey="userId" 表单当用户选中某个选项的时候返回到后台的值。

    结果:

    参考刚才数据库里的数据



    • 动态单选框_2: 按钮value是从数据库或者其他地方获取的。(与动态单选框_1类似)
      •   在上例中,把DBUtil.java 文件修改如下(只是把上例的list转为Map):
        package tag;
        
        import java.util.HashMap;
        import java.util.List;
        import java.util.Map;
        
        import org.apache.commons.dbutils.DbUtils;
        import org.apache.commons.dbutils.QueryRunner;
        import org.apache.commons.dbutils.ResultSetHandler;
        import org.apache.commons.dbutils.handlers.BeanListHandler;
        
        import com.opensymphony.xwork2.ActionContext;
        
        import DBUtil.DBUtil;
        import actionUtil.BaseAction;
        import bean.UserBean;
        
        public class FromAction extends BaseAction{
        /**
         * QueryRunner类为数据库开源工具包(ommons-dbutils-1.3.jar)封装的类,
         * 这个类实现了快速对数据库操作的方法。
         * 步骤: 
         * 确认sql语句确定相应的方法,本题中select * 查询结果应该是一个集合。所以应该用QueryRunner的query()方法,
         * 而query()方法里的三个参数为“Connection conn,String sql,ResultSetHandler<T> t”其中ResultSetHandler
         * 是一个接口,我们往query()方法里填的参数不可能是接口而只能是其实现类,其中ResultSetHandler<T>的实现类BeanListHandler<T>类
         * 是本题中需要的类,把这个类的对象加到query()方法里,这个方法将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里,也就是说我们
         * 此时还需要创建一个javaBean类,这个类的成员属性(要有getset方法)要跟数据库中的列名一致。
         * 
         */
        
            public String execute() throws Exception{
                ActionContext actionContext=ActionContext.getContext();
                
                String sql="select * from user order by userId";
                QueryRunner query=new QueryRunner();
                List<UserBean> list=query.query(DBUtil.getConn(), sql, new BeanListHandler<UserBean>(UserBean.class));
            
                Map<String,String> userMap=new HashMap<String, String>();
                
                if(list!=null){
                    /**
                     * 把List转换为Map
                     */
                    for(UserBean user:list){
                    String    userName=user.getUserName();
                    String    userId=user.getUserId();
                    userMap.put(userId, userName);
                        
                    }
                }
                actionContext.put("userMap", userMap);
                
                
                 return "formjsp";
            }
        
        }

        form.jsp:

    <tr>
            <td>静态单选框_2:</td>
            <td><s:radio list="#userMap" name="sex_1" ></s:radio></td>
        </tr>
    • 此时就不用添加listValue和listKey属性了,因为Map就是键值对。

      • 下拉框标签:
        •   下拉框也有动态下拉框如果需要的话,可以参考动态单选框_1/动态单选框_2,但是下拉框一般是固定的值,没必要动态获取。
    <tr>
            <td>下拉框</td>
            <td><s:select list="{'福建','山东','河南'}" name="privince" headerKey="none" headerValue="---请选择---"></s:select></td>
        </tr>

      • 下拉框分组:
        <tr>
            <td>下拉框分组</td>
            <td>
            <s:select list="{'福建','山东','河南'}" name="privince" headerKey="none"
                headerValue="---请选择---">
                <s:optgroup list="#{1:'泉州',2:'莆田',3:'福州'}" label="福建" ></s:optgroup>
            </s:select>
            </td>
            </tr>
    • <s:optgroup >标签只能放在<s:select>标签里,且list只能用"#{}"这个OGNL表达式也就是一定要用Map,否则错误。

    label标签不可选定。


        • 复选框标签和复选框分组标签:

    本例的文件与动态单选框_1中的文件相同,只有最后的form.jsp页面改成下面

    <tr>
            <td>复选框:</td>
            <td><s:checkbox  name="is_check" value="true"></s:checkbox></td>
        </tr>
    
        <tr>
            <td>复选框分组:</td>
            <td><s:checkboxlist list="#userMap" name="group"></s:checkboxlist></td>
        </tr>

    结果:

    • 其中list="userMap"是数据库的数据封装为Map对象,而且<s:checkboxlist>中的list和name属性一定要写,name如果没写ftl文件会报name属性未定义这个错误。
    • <s:checkboxlist>中的list如果是List集合,那么就要加listValue和listKey属性。

      隐藏域和文件域名标签

    <tr>
            <td>隐藏域</td>
            <td><s:hidden name="userId"></s:hidden ></td>
        </tr>
        <tr>
            <td>文本域</td>
            <td><s:file name="userface"></s:file ></td>
        </tr>

    结果:


      •  表单标签:
    <s:form name="" id="" action="" method=""></form>
      • 按钮标签:

    • struts中没有普通按钮标签。

     

      •   上下下拉框(使用这个标签要在<head>标签里定义<s:head />标签,这个标签用于引入上下下拉框等标签所需的脚本文件)
        <tr>
            <td>上下下拉框</td>
            <td><s:updownselect list="{'1','2','3'}" name="text" cssStyle="60px"
            allowMoveDown="true" allowMoveUp="true" allowSelectAll="true" moveDownLabel="向下移动" moveUpLabel="向上移动" selectAllLabel="全选"
            ></s:updownselect></td>
        </tr>
    • 用法类似动态单选框_1和动态单选框_2

      •    选项传输下拉框(1. 使用这个标签要在<head>标签里定义<s:head />标签,这个标签用于引入上下下拉框等标签所需的脚本文件 2. 使用这个标签的时候不能用submit按钮提交,否则后台取值的时候会全部取到而不是只取用户选定的,只能通过定义普通按钮然后这个按钮触发一个javaScript脚本,在脚本里定义一个submit()方法提交)

     

      •    组合框标签(1.使用这个标签要在<head>标签里定义<s:head />标签,这个标签用于引入上下下拉框等标签所需的脚本文件 2. 使用这个标签的时候不能用submit按钮提交,否则后台取值的时候会全部取到而不是只取用户选定的,只能通过定义普通按钮然后这个按钮触发一个javaScript脚本,在脚本里定义一个submit()方法提交)


  • 相关阅读:
    CF979D Kuro and GCD and XOR and SUM(01Trie)
    2020中国计量大学校赛题解
    CF16E Fish (状压dp)
    2017ccpc杭州站题解
    HDU6274 Master of Sequence(二分+预处理)
    CF899F Letters Removing(树状数组+二分)
    牛客 tokitsukaze and Soldier(优先队列+排序)
    HDU6268 Master of Subgraph(点分治)
    CF862E Mahmoud and Ehab and the function(二分)
    CF1108F MST Unification(生成树+思维)
  • 原文地址:https://www.cnblogs.com/shyroke/p/6569198.html
Copyright © 2011-2022 走看看