视图层传递参数(Struts2)

  1. 说明:struts2中前端页面传递各种参数(简单参数,数组,List,Set,Map 及复合结构)至后端。
  2. 建议:如果你需要了解如何传递数组的,先看页面再看对应的Action,再看里面的注释(如果想了解传参的具体细节或底层思想)。演示输出结果,请看控制台。
  3. 环境:tomcat+struts2+Ognl
  4. 主代码如下:
**************************1视图层CODE*****************************
findUser.jsp>>>>>>>>>>>


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    String basePath = request.getScheme()+"://"
                + request.getServerName() +":"
                +request.getServerPort() +"/"
                + request.getContextPath()+"/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<!-- 重写href,作为相对路径 -->
 <base href="<%=basePath%>">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>findUser.jsp</title>
</head>
<body>


    <h1>前端提交到服务器的数据的数据结构</h1>
    <p>

http://localhost:8080/应用名/findUser.action?
user.id=1688&pnames=tom&pnames=anie&pnames=maniy&names%5B0%5D=%E6%9D%8E%E4%B8%89&names%5B1%5D=%E6%9D%8E%E5%9B%9B
&names%5B2%5D=%E7%8E%8B%E4%BA%94&user.ids%5B0%5D=10086&user.ids%5B1%5D=10082&user.ids%5B2%5D=10085
&user.orders%5B0%5D.orderId=order1688&user.orders%5B0%5D.orderName=AJ%E9%A3%9E%E4%BA%BA&user.orders%5B0%5D.productPrice=1500
&user.orders%5B1%5D.orderId=order1699&user.orders%5B1%5D.orderName=Ads%E4%B8%89%E5%8F%B6&user.orders%5B1%5D.productPrice=800
&orderSet.makeNew%5B0%5D.orderName=hi&orderSet.makeNew%5B1%5D.orderName=hello&userMap.user.id=2600
&userMap.user.name=jack&userMap%5B%27mu2%27%5D.id=2700&userMap%5B%27mu2%27%5D.name=jack2
    <br/>

    <span>
     <blockquote>前端(视图层)映射到后端时的数据结构。可以看出都是弱类型(文本类型String)来表示前端的所有数据。 
    也就是说:不论你是float,int,String,Date,object在前端都视为弱类型,那为映射到java中,必须要进行数据类型转换。
    转换的具体思路或过程,在UserAction.java文件中搜索:"前端的弱类型数据转换成java强类型思路或过程"有说明。</blockquote>
    </span><br/>
    {<br/> <blockquote>
        用户id:<br/>
        user.id=[Ljava.lang.String;@1504a84, <br/>

        用户名数组,方式一<br/>
        pnames=[Ljava.lang.String;@1644c9, <br/>

        用户名数组,方式二(Ognl)<br/>
        names[0]=[Ljava.lang.String;@3da671, names[1]=[Ljava.lang.String;@13aa7d4, names[2]=[Ljava.lang.String;@49968b,<br/>

        对象中数组:<br/>
        user.ids[0]=[Ljava.lang.String;@28ad5a, user.ids[1]=[Ljava.lang.String;@13864d9, user.ids[2]=[Ljava.lang.String;@1c66091,<br/>

        List传参:List<Order>  <br/>   
        user.orders[0].orderId=[Ljava.lang.String;@a87a8, <br/>
        user.orders[0].orderName=[Ljava.lang.String;@164e850, user.orders[0].productPrice=[Ljava.lang.String;@eeda37,<br/> 

        user.orders[1].orderId=[Ljava.lang.String;@17a8369,<br/>
        user.orders[1].orderName=[Ljava.lang.String;@1fdf894, user.orders[1].productPrice=[Ljava.lang.String;@4c4ff8,<br/>

        Set传参:Set<Order><br/>
        orderSet.makeNew[0].orderName=[Ljava.lang.String;@1e070c0, <br/>
        orderSet.makeNew[1].orderName=[Ljava.lang.String;@edfb95, <br/>

        Map传参:Map<User><br/>
        userMap.user.id=[Ljava.lang.String;@201dbc, userMap.user.name=[Ljava.lang.String;@8024c8,<br/> 
        userMap['mu2'].id=[Ljava.lang.String;@8d241b, userMap['mu2'].name=[Ljava.lang.String;@1cfee57<br/>
        </blockquote>
    }
    </p><hr>
    <h1>开发中实用传参方式及原理说明(实验时建议选中所有数据再提交)</h1>
    <form action="findUser.action" method="get">
        <div>
            <span>1.根据用户id查询用户</span><br/>
            <input type="text" name="user.id" value="1688"/><br/>
        </div>

        <div>
            <span>2.简单数组传参1(原始方式,但后端设值还是用到Ognl)</span><br/>
            <!-- 获取user,再获取ids,运用Array.set(array, index, value)设值<br/> -->
            tom<input type="checkbox" name="pnames" value="tom"><br/>
            anie<input type="checkbox" name="pnames" value="anie"><br/>
            maniy<input type="checkbox" name="pnames" value="maniy"><br/><br/>
        </div>

        <!-- 以下全是ognl方式传参 -->
        <div>
            <span>3.简单数组传参2(这以下皆为Ognl方式传递参数)</span><br/>
            <!-- 获取user,再获取ids,运用Array.set(array, index, value)设值<br/> -->
            李三<input type="checkbox" name="names[0]" value="李三"><br/>
            李四<input type="checkbox" name="names[1]" value="李四"><br/>
            王五<input type="checkbox" name="names[2]" value="王五"><br/>
        </div>

        <div>
            <span>4.对象中的数组传参</span><br/>
            <!-- 获取user,再获取ids,运用Array.set(array, index, value)设值<br/> -->
            10086<input type="checkbox" name="user.ids[0]" value="10086"><br/>
            10082<input type="checkbox" name="user.ids[1]" value="10082"><br/>
            10085<input type="checkbox" name="user.ids[2]" value="10085"><br/>
        </div>

        <div>
            <span>5.List传参(List&lt;Order&gt;)</span><br/>
            <span>第一个订单</span><br/>
            order1688<input type="checkbox" name="user.orders[0].orderId" value="order1688"><br/>
            AJ飞人<input type="checkbox" name="user.orders[0].orderName" value="AJ飞人"><br/>
            1500<input type="checkbox" name="user.orders[0].productPrice" value="1500"><br/><br/>

            <!-- 第二个订单 :重复异常user.orders[0].productPrice-->
            <span>第二个订单</span><br/>
            order1699<input type="checkbox" name="user.orders[1].orderId" value="order1699"><br/>
            Ads三叶<input type="checkbox" name="user.orders[1].orderName" value="Ads三叶"><br/>
            800<input type="checkbox" name="user.orders[1].productPrice" value="800"><br/><br/>     
        </div> 

        <div>6.Set传参<br/>
            hi<input type="checkbox" name="orderSet.makeNew[0].orderName" value="hi"><br/>
            hello<input type="checkbox" name="orderSet.makeNew[1].orderName" value="hello"><br/><br/>
        </div>

        <div>7.Map接收参数<br/>
            <span>第一个Entry(指定Map的key为user)</span><br/>
            2600<input type="checkbox" name="userMap.user.id" value="2600"><br/>
            jack<input type="checkbox" name="userMap.user.name" value="jack"><br/><br/>

            <span>第二个Entry(指定Map的key为mu2,若作用相同的key则进行"追加赋值")</span><br/>
            2700<input type="checkbox" name="userMap['mu2'].id" value="2700"><br/>
            jack2<input type="checkbox" name="userMap['mu2'].name" value="jack2"><br/>
        </div>

        <input type="submit" value="提交数据" /><br/>


    </form>
</body>
</html>


showFindUser.jsp >>>>>>>>>>>>>


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"
    import="java.util.*"
    import="com.opensymphony.xwork2.ognl.OgnlValueStack"
    import="com.opensymphony.xwork2.util.CompoundRoot"
    import="org.yl.action.UserAction"
    import="org.yl.domain.User"


%>
<!-- 引入struts2标签库 -->
<%@ taglib uri="/struts-tags" prefix="s" %>
<%
  String basePath = request.getScheme()+"://"
                + request.getServerName() +":"
                +request.getServerPort() +"/"
                + request.getContextPath()+"/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
 <base href="<%=basePath%>">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h1>视图层:JSP,从ValueStack中的CompoundRoot中取值</h1>

    <div>
        <span>用户信息:</span><br/>
        <!-- 1.java直接取值 -->
        <%
            OgnlValueStack vs = (OgnlValueStack)request.getAttribute("struts.valueStack");
            //值栈的上下文
            Map<String,Object> vsContext = vs.getContext();
            for(Map.Entry<String, Object> entry: vsContext.entrySet()){
                //System.out.println("key:" + entry.getKey() + "--value:" + entry.getValue() + "\n");
            }
            //值栈的根(CompoundRoot数据结构为栈,使用ArrayList实现的)
            CompoundRoot root = vs.getRoot();
            Object obj = root.peek();//从root栈中取出一个数据
            UserAction userAction = null;
            User user = null;
            String name = null;
            if(obj instanceof UserAction){
                userAction = (UserAction)obj;
                user = userAction.getUser();
                System.out.println("************showFindUser.jsp页面展示信息*************");
                System.out.println("Action中的成员变量信息:" +"\n"
                            + "1.user信息 ======"
                            + "id:" + user.getId() + "\n"
                            + "name:" + user.getName() + "\n"
                            + "sex:" + user.getSex() + "\n"
                            + "deposit:" + user.getDeposit()+ "\n"
                            + "telephone:" + user.getTelephone() + "\n"
                            +"");
                name = user.getName();//供页面使用,与html标签进行整合
            }

        %>
        java直接取值:<input type="text" value="<%=name %>" readonly="readonly" /><br/>

        <!-- 2.标签库解药or毒药 -->
        <!-- el表达式 -->
        el表达式取值:<input type="text" value="${user.name }" readonly="readonly" /><br/>

        <!-- 使用struts2标签库中的标签 
        <s:property value="user.telephone"/><br/>-->
        struts2标签取值:<input type="text" value="<s:property value="user.telephone"/>" readonly="readonly" /><br/>

    </div>

</body>
</html>
**************************2控制层CODE*****************************
UserAction.java >>>>>>>

package org.yl.action;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.yl.domain.Order;
import org.yl.domain.User;

import com.opensymphony.xwork2.util.Element;
import com.opensymphony.xwork2.util.KeyProperty;


/**
 * 演示:显示层从ValueStack中取值
 *  (1)视图层传递参数
 *  (2)el+jstl
 *  (3)struts2标签库+Ognl
 * 
 * @author 拈花为何不一笑
 *
 *  此UserAction对应的页面:findUser.jsp
 */
public class UserAction {//何时何地创建Action?服务Action时创建ActionProxy,
    //而在创建代理时ObjectFactory创建Action并且把Action放入至值栈中(实际是放入CompoundRoot中)
    //何地?DefaultActionInvocation作为场地

    //初始化
    private User user = new User();

    //普通数组(原始方式接收数组)
    private String pnames[];


    //普通数组(Ognl方式:names[0])
    private String names[] = new String[6];


    //Xwork2重写Ognl中的SetPropertyAccessor等Accessor
    //Set中不支持存放基本数据类型和String类型(即使String被实例化为"",也不能当作类对象操作String中的属性或方法),可以存放javaBean
    //private Set<String> sts = new HashSet<String>();

    //Set集合接收参数
    /**
     * 表达式:orderSet.makeNew[0].orderName
     * 问题一:如何把新创建了的Order作为元素被添加到orderSet中的?怎么辨别或区分新创建的Order的?引入了一个包装类:SurrugeList
     *  且它的成员变量surrugate存放orderSet(HashSet)
     * 简要而关键的流程:
     *  1.把orderSet(HashSet类型)包装成一个SurrugateList用于对应下标[0][1]……
     * (因为Set中取值是用iterator,而没有get(index)。为了与表达式中的下标关联List类型,用到了SurrugateList)
     * 2.ATS Node:makeNew获取Property时创建SurrugateList
     * 3.后面逻辑就按List Accessor进行处理
     * 
     * 4.ATS Nod:[0]获取Property时,使用XWorkListPropertyAccessor
     *      对象工厂创建bean,用@Element注解(orderSet属性上的注解)获取bean的Class
     *  来创建bean(Order):
     *      objectFactory.buildBean(beanClass, context)
     *  并把这个创建的Order元素放到SurrugateList的的成员变量surrugate(存放的是orderSet)中:
     *      orderSet.add(Order);
     * 
     * 5.再然后,通过Ognl给Order.setOrderName("前端的参数值"),就OK了。
     * 
     * 问题二:这个过程中用到了两个注解:@KeyProperty和@Element,它们的作用是什么呢?
     *       注解:@KeyProperty 作为后面逻辑,进行数据类型转换的Class参数
     *          (不设置会报异常:Error getting property descriptor影响整个过程。对当前的参数映射到Set中并无逻辑关系)
     *       注解:@Element 创建Set<T>中的T时,使用到的beanClass
     *
     * 以上过程总结起来就是一句话:Ognl解析Set类型的表达式时,是披着ListAccessor的外衣把Set当作List来处理的。(当然这是Xwork2对Ognl的扩展了)
     * 
     * 建议:由于Set逻辑处理繁琐且复杂,昼量用List替代Set接收参数。(Set食之无味,弃之可惜!)    
     */
    @KeyProperty(value="orderId")
    @Element(value=org.yl.domain.Order.class )
    private Set<Order> orderSet = new HashSet<Order>();//若不初始化,默认创建一个ArrayList,显然不正确 


    //Map接收参数
    private Map<String,User> userMap = new HashMap<String,User>();






    //业务方法(struts.xml的UserAction配置中不指定具体方法时,excute或doExecute作为默认方法)
    public String doExecute(){//执行action阶段调用
        System.out.println("findUser...");


        /**
         * 下面逻辑发生在拦截器阶段
         * 1.xwork2的InstantiatingNullHandler类调用对象工厂objectFactory.buildBean(clazz, context);
         * 来创建了UserAction中为空的成员属性User:user。
         * 2.当UserAction中的成员属性是类对象时且开发人员没有初始化时,
         *  由Ognl+CompoundRootAccessor+InstantiatingNullHandler经过一系列逻辑创建了该成员属性
         *  创建User实例后,再通过Ognl把前端传递过来的参数值:user.id="m-p6"赋给User对象中的成员变量id。
         * 3.由于步骤2开销不少,建议开发中先初始化Action中的成员变量(类对象作为Action的成员变量),避免程序执行步骤2
         */
        if(this.user != null){//UserAction中的User实例也被框架创建了。(谁创建的?在哪创建的?)
            System.out.println("user.id:" + this.user.getId());
            //模拟从DB或企业信息系统中获取到的数据
            if(user.getId() != null && user.getId().equals("1688")){
                this.user.setName("张天见");
                this.user.setSex("男");
                this.user.setTelephone("13638885606");
                this.user.setDeposit(73000);
            }
            /**
             * 原始方式接收参数
             * 
             */
            //数组接收参数:接收前端传递的多个pnames
            String[] mypnames = this.pnames;
            if(mypnames != null && mypnames.length > 0){
                System.out.println("***数组接收参数1:前端参数pnames映射到UserActoin中的成员变量pnames***");
                for(String pn:mypnames){
                    System.out.println(pn);
                }
            }

            /**
             * 以下都是ognl方式接收参数,顺便说一说前端的弱类型数据转换成java强类型思路或过程
             * Ongl设值过程序,前端传递过来的参数被xwork+ognl进行了文本弱类型转换成java强类型
             *  比如:前端传递一个文本类型(弱类型)name=user.orders[0].productPrice" value="1500"
             *   1500是个文本类型,如何转换成java强类型float?
             *  简要说下过程:拿到setProductPrice(float)方法,再拿到这个方法的参数类型float。
             *  知道了是对float进行设值,那么xwork+ognl就把弱类型1500转换成float类型。
             *  
             *  说明:xwork对ognl数据类型转换进行了扩展。
             */
            //数组来接收参数:前端参数ids映射到UserActoin中的成员变量User中的ids
            String ids[] = this.user.getIds();
            if(ids !=null && ids.length > 0){
                System.out.println("***数组接收参数2:前端参数ids映射到UserActoin中的成员变量User中的ids***");
                for(String e:ids){
                    System.out.println(e);
                }
            }


            //数组来接收参数:前端参数names映射到UserActoin中的成员变量names
            String names[] = this.names;
            if(names != null && names.length > 0){
                System.out.println("***数组接收参数:前端参数names映射到UserActoin中的成员变量names***");
                for(String n:names){

                    try {
                        if(n!= null)
                        n = new String(n.getBytes("ISO-8859-1"),"UTF-8");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                    System.out.println(n);
                }
            }

            //List接收数据List<Order> orders
            List<Order> orders = this.user.getOrders();
            if(orders != null && orders.size() > 0){
                System.out.println("***List接收数据:前端参数orders映射到UserActoin中的成员变量User中的orders***");
                for(Order order:orders){
                        if(order!= null){
                            String orderName = null;
                            try {
                                orderName = new String(order.getOrderName().getBytes("ISO-8859-1"),"UTF-8");
                            } catch (UnsupportedEncodingException e) {
                                e.printStackTrace();
                            }
                            System.out.println("订单号:" + order.getOrderId() +"\n"
                                    + "订单名称:" + orderName  +"\n"
                                    + "产品单价:" + order.getProductPrice() + "\n"
                                    );

                            System.out.println("\n\n");
                        }
                }
            }//

            //set接收数据,与list逻辑相似只是多了一个披外衣的过程
            System.out.println("************Set接收数据*******************");
            if(this.orderSet != null && this.orderSet.size() > 0){
                for(Order or: orderSet){
                    System.out.println(or.getOrderName());
                }
            }//

            //Map接收参数
            System.out.println("************Map接收数据*******************");
            Map<String,User> uMap = this.userMap;
            if(uMap != null && !uMap.isEmpty()){
                for(Map.Entry<String, User> entry:uMap.entrySet()){
                    String key = entry.getKey();
                    User u = entry.getValue();
                    //使用userMap.user.id的user作为key
                    System.out.println("key-String:" + key);
                    System.out.println("value-User如下:");
                    if(u!=null){
                        System.out.println("用户Id:"+u.getId()+", 用户名:"+u.getName());
                    }
                }
            }

        }


        //struts2中提供与Web容器直接交互的类:ServletActionContext
        //获取服务器路径
        /*HttpServletRequest request =ServletActionContext.getRequest();
        String serverPath = request.getSession().getServletContext().getRealPath("/");
        System.out.println("serverPath: " + serverPath);*/

        return "showFindUser";
    }


    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }


    public void setNames(String names[]) {
        this.names = names;
    }


    public String[] getNames() {
        return names;
    }



    public void setOrderSet(Set<Order> orderSet) {
        this.orderSet = orderSet;
    }


    public Set<Order> getOrderSet() {
        return orderSet;
    }


    public void setUserMap(Map<String,User> userMap) {
        this.userMap = userMap;
    }


    public Map<String,User> getUserMap() {
        return userMap;
    }

    public void setPnames(String pnames[]) {
        this.pnames = pnames;
    }


    public String[] getPnames() {
        return pnames;
    }



}

**************************3配置文件E*****************************
struts.xml  >>>>>>


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
    <!-- 常量bean配置 -->
    <constant name="struts.devMode" value="true" />
    <!-- action事件映射 -->
    <package name="default" namespace="/" extends="struts-default">
       <action name="reg" class="org.yl.action.Register">
          <result name="success">/success.jsp</result>
        </action>

       <action name="findUser" class="org.yl.action.UserAction">
          <result name="showFindUser">/showFindUser.jsp</result>
        </action>


    </package>

</struts>

*******************=123向左向右向前向后。///*************************

猜你喜欢

转载自blog.csdn.net/Netaa001/article/details/82597118