(八)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="width: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()方法提交)

 

 

 


 

posted @ 2017-03-17 23:40  shyroke、  阅读(331)  评论(0编辑  收藏  举报
作者:shyroke 博客地址:http://www.cnblogs.com/shyroke/ 转载注明来源~