Allin's blog

先做正确的事,然后才是正确的做事

leeshaoqunID:leeshaoqun
135161次访问,排名549好友0人,关注者2
leeshaoqun的文章
原创 90 篇
翻译 1 篇
转载 129 篇
评论 35 篇
allin的公告
  • leeshaoqun的博客
  • 电子科技大学中山学院
  • 计算机工程系
老照片
最近评论
mldstk:wow gold,
mldstk:wow gold,
alex.xu:漂亮 ,说实话 比官方文档写的好
lkuzhi:是啊,能不能找个能用的过来啊
泽雄:已经不能用了
文章分类
收藏
    相册
    ♡韩国可爱的小童星 ♡
    korea
    韩佳人
    金泰熙
    宋惠乔
    宋慧乔车太贤《我和我的女友》
    微笑美女——韩孝珠
    Hibernate
    Hibernate中文网
    Hibernate官方网站
    php
    Haohappy的专栏--PHP5研究中心
    Spring
    Raible's Wiki -- AppFuse
    Spring 开发参考手册
    SpringFramework中文论坛
    SpringFramework官方站点
    个人博客
    greengnn's space
    开源
    java开源大全(RSS)
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    转载 第七章 (类型转换)Type Convertion 收藏

    新一篇: 第八章 Result Types  | 旧一篇: 第六章 Localization

    为什么会有类型转换?

    HTTP协 议中传递的任何内容都是String类型的,所以一旦我们在服务器上需要一个非String类型的对象,例如:int或者Date,那么我们就需要在收到 HTTP请求的数据的时候,首先将String类型的数据变换为我们需要的对应类型的数据,之后再使用。这个过程就是类型转换

    类型转换在Struts2中是透明的,即Struts2内置了类型转换机制。

     
    转换原理:
    以一个例子来说明如何使用Struts2内置的类型转换功能。加入我们希望用户在画面上输入一个字符形式的坐标点,例如(33,2)而我们希望在程序中得到一个Point(33, 2)的类型与之对应。
    要想达到上面的功能我们需要一个名字位:ActionName-conversion.properties的文件,在文件中定义Action中的属性和画面字段之间的转换关系。例如:

    point = com.jpleasure.convertor.PointConverter

    也 就是说画面一个叫做point的项目(input类型,name为point)提交到服务器上之后,在向Action中的point属性赋值之前需要使用 PointConverter将字符串转换为Point类,在Action中的point属性向画面显示的时候需要使用PointConverter将 Point类转换为字符串类型。
    其中PointConverter需要实现ognl.TypeConverter接口。TypeConverter有两个接口,一个负责将字符串转变为对象类型,另一个负责将对象类型转换为字符串类型,分别对应着内容的提交和显示。
    有些时候我们希望所有的Point类在默认的情况下使用PointConverter来转换,这时候我们需要定义全局的Converter类。这可以在xwork-conversion.properties文件中定义,例如:
    com.jpleasure.Point = com.jpleasure.convertor.PointConverter
    在Struts2中提供了一个TypeConverter接口的默认实现:
    org.apache.struts2.action.util.StrutsTypeConverter
    这个类有两个默认的抽象转换方法和performFallbackConversion,performFallbackConversion方法负责处理类型转换出错的处理。
    在 自定义TypeConverter的时候,可以实现TypeConverter接口,之后编写TypeConverter的转换方法,也可以从 StrutsTypeConverter继承而来,StrutsTypeConverter本身实现了TypeConverter接口,并且实现了基本的 转换方法。
    内建的转换:
    Struts2内建了对以下类型的转换的支持:
    String
    boolean / Boolean
    char / Character
    int / Integer, float / Float, long / Long, double / Double
    dates - 使用HTTP 请求对应地域(Locale)的SHORT形式转换字符串和日期类型。
    arrays -每一个字符串内容可以被转换为不同的对象
    collections - 转换为Collection类型,默认为ArrayList类型,其中包含String类型。
    对于Array类型和Collection类型,需要对其中的每一个元素进行单独的转换。
    自定义TypeConverter:
    使用如下的代码自定义需要的TypeConverter
    public class MyConverter extends StrutsTypeConverter {
        public Object convertFromString(Map context, String[] values, Class toClass) {
           .....
        }
        public String convertToString(Map context, Object o) {
           .....
        }
     }
    为了让Struts2框架发现类型转换的错误,需要在出错的情况下在上述的两个方法中抛出XWorkException或者TypeConversionException。

    我们使用一个例子来展现如何实现TypeConvertor类型:

    // Point 类
    package com.jpleasure.conversion;

    /**
     * Created by IntelliJ IDEA.
     * User: ma.zhao@dl.cn
     * Date: 2007/09/04
     * Time: 12:33:43
     * To change this template use File | Settings | File Templates.
     */
    public class Point {
        private int x;
        private int y;

        public Point() {

        }
       
        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public int getX() {
            return x;
        }

        public void setX(int x) {
            this.x = x;
        }

        public int getY() {
            return y;
        }

        public void setY(int y) {
            this.y = y;
        }

        public String toString() {
            StringBuffer sb = new StringBuffer("Point(");
            sb.append(x).append(", ").append(y).append(")");
            return sb.toString();
        }
    }

    // PointConvertor 类
    package com.jpleasure.conversion;

    import org.apache.struts2.util.StrutsTypeConverter;

    import java.util.Map;

    /**
     * Created by IntelliJ IDEA.
     * User: ma.zhao@dl.cn
     * Date: 2007/09/04
     * Time: 12:34:18
     * To change this template use File | Settings | File Templates.
     */
    public class PointConvertor extends StrutsTypeConverter {
       
        // 从字符串转换为对象的方法。
        public Object convertFromString(Map map, String[] strings, Class aClass) {
            if (strings.length > 0) {
                String pointStr = strings[0];
                String[] pointStrArray = pointStr.split(",");
                if (pointStrArray.length == 2) {
                    Point p = new Point();
                    p.setX(Integer.parseInt(pointStrArray[0]));
                    p.setY(Integer.parseInt(pointStrArray[1]));
                    return p;
                } else {
                    return null;
                }

            } else {
                return null;
            }
        }
       
        // 从对象转换为字符串的方法。
        public String convertToString(Map map, Object o) {
            if (o instanceof Point) {
                return o.toString();
            } else {
                return "";
            }
        }
    }

    // 测试用PointAction类
    package com.jpleasure.action;

    import com.jpleasure.conversion.Point;
    import com.opensymphony.xwork2.ActionSupport;

    /**
     * Created by IntelliJ IDEA.
     * User: ma.zhao@dl.cn
     * Date: 2007/09/04
     * Time: 12:45:11
     * To change this template use File | Settings | File Templates.
     */
    public class PointAction extends ActionSupport {
        private Point point;

        public Point getPoint() {
            return point;
        }

        public void setPoint(Point point) {
            this.point = point;
        }

        public String execute() {
            return SUCCESS;
        }
    }

    // JSP文件
    <%--
      Created by IntelliJ IDEA.
      User: ma.zhao@dl.cn
      Date: 2007/09/04
      Time: 12:47:40
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@ taglib prefix="s" uri="/struts-tags" %>
    <html>
    <head><title>Point Page</title></head>
    <body>
    <s:form action="point" namespace="/point" method="post">
        <s:textfield name="point"/>

        <s:property value="point"/>
        <s:submit/>
    </s:form>
    </body>
    </html>


    // PointAction配置文件类。
    <?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>

        <package name="point" namespace="/point" extends="struts-default">

            <action name="point" class="com.jpleasure.action.PointAction">
                <result>/point/Point.jsp</result>
                <!-- 定义input的result是为了处理转换出错的情况,在输入格式不正确的情况下转移到这个画面 -->
                <result name="input">/point/Point.jsp</result>
            </action>
            <!-- Add actions here -->
        </package>
    </struts>

    复杂的类型转换:
    (1)处理Null值
    有 些时候我们会被NullPointerException搞的焦头烂额,为什么系统不能为我们定义了但是没有初始化的对象建立一个空的Object的引用 呢?Struts2有这个功能,但是在默认情况下Struts2关闭了这个功能,要想开启这个功能,需要在ParameterInterceptor开始 处理参数之前在ValueStack中将一个值开启,这个值是:
    InstantiatingNullHandler.CREATE_NULL_OBJECTS。
    在Java代码中InstantiatingNullHandler.CREATE_NULL_OBJECTS的值是:xwork.NullHandler.createNullObjects
    创建空值对象的规则为:
    • 如果属性声明为Collection或List, 将返回一个ArrayList并赋值给空引用.
    • 如果属性声明为Map, 将返回一个HashMap并赋值给空引用.
    • 如果空值属性是一个带有无参构造函数的简单Bean, 将使用ObjectFactory.buildBean(java.lang.Class, java.util.Map)方法创建一个实例.

    (2)Collection和Map

    简单List转换
    //JSP代码
    <%--
      Created by IntelliJ IDEA.
      User: mazhao
      Date: 2007/09/04
      Time: 12:47:40
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@ taglib prefix="s" uri="/struts-tags" %>
    <html>
    <head><title>Point Page</title></head>
    <body>
    <s:form action="point" namespace="/point" method="post">
        <s:textfield label="Point" name="point"/>

        <s:textfield label="References" name="references"/>
        <s:textfield label="References" name="references"/>
        <s:textfield label="References" name="references"/>
        <s:textfield label="References" name="references"/>
        <s:textfield label="References" name="references"/>
                       

        <s:property value="point"/>
        <s:submit/>
    </s:form>
    </body>
    </html>

    //Action代码
    package com.jpleasure.action;

    import com.jpleasure.conversion.Point;
    import com.opensymphony.xwork2.ActionSupport;

    import java.util.List;

    /**
     * Created by IntelliJ IDEA.
     * User: ma.zhao@dl.cn
     * Date: 2007/09/04
     * Time: 12:45:11
     * To change this template use File | Settings | File Templates.
     */
    public class PointAction extends ActionSupport {
        private Point point;
        private List references;

        public Point getPoint() {
            return point;
        }

        public void setPoint(Point point) {
            this.point = point;
        }

        public List getReferences() {
            return references;
        }

        public void setReferences(List references) {
            this.references = references;
        }

        public String execute() {

            if(references == null) {
                System.out.println("references is null");
            } else {
                System.out.println("references length is:" + references.size());
               
                for(Object s: references) {
                    System.out.println("" + s);
                }
            }

            return SUCCESS;
        }
    }

    对象类型List转换(key-value pair 方式)
    // Person 类型

    package org.apache.struts2.showcase.conversion;

    import java.io.Serializable;

    /**
     *
     */
    public class Person implements Serializable {
        private String name;
        private Integer age;

        public void setName(String name) { this.name = name; }
        public String getName() { return this.name; }

        public void setAge(Integer age) { this.age = age; }
        public Integer getAge() { return this.age; }
    }

    // PersionAction 类型

     package org.apache.struts2.showcase.conversion;

    import java.util.List;

    import com.opensymphony.xwork2.ActionSupport;

    /**
     *
     */
    public class PersonAction extends ActionSupport {

        private List persons;

        public List getPersons() { return persons; }
        public void setPersons(List persons) { this.persons = persons; }

     

        public String input() throws Exception {
            return SUCCESS;
        }

        public String submit() throws Exception {
            return SUCCESS;
        }
    }
    // PersonAction转化配置文件PersonAction-conversion.properties

     

    # PersonAction中persons属性(List类型)中元素的类型

    Element_persons=org.apache.struts2.showcase.conversion.Person

     

    // JSP部分代码

     <s:iterator value="new int[3]" status="stat">
            <s:textfield    label="%{'Person '+#stat.index+' Name'}"
                            name="%{'persons['+#stat.index+'].name'}" />
            <s:textfield    label="%{'Person '+#stat.index+' Age'}"
                            name="%{'persons['+#stat.index+'].age'}" />
      </s:iterator>
    其中stat记录了当前循环的信息,其中stat.index表示当前循环的下标。

    所以上述代码会生成如下的代码:

    <s:textfield    label="Person 1 Name"
                    name="persons[0].name" />
    <s:textfield    label="Person 1 Age"
                    name="persons[0].age" />
    <s:textfield    label="Person 2 Name"
                    name="persons[1].name" />
    <s:textfield    label="Person 2 Age"
                    name="persons[1].age" />
    <s:textfield    label="Person 3 Name"
                    name="persons[2].name" />
    <s:textfield    label="Person 3 Age"
                    name="persons[2].age" />

     

    对象类型List转换(value 方式)

    // Address 类型 

    package org.apache.struts2.showcase.conversion;


    /**
     * @version $Date: 2006-11-23 12:31:52 -0500 (Thu, 23 Nov 2006) $ $Id: Address.java 478625 2006-11-23 17:31:52Z wsmoak $
     */
    public class Address {

        private String id;
        private String address;

        public String getId() { return id; }
        public void setId(String id) { this.id = id; }

        public String getAddress() { return address; }
        public void setAddress(String address) { this.address = address; }

    }

    // AddressAction 类型

     package org.apache.struts2.showcase.conversion;

    import java.util.LinkedHashSet;
    import java.util.Set;

    import com.opensymphony.xwork2.ActionSupport;

    /**
     * @version $Date: 2006-11-23 12:31:52 -0500 (Thu, 23 Nov 2006) $ $Id: AddressAction.java 478625 2006-11-23 17:31:52Z wsmoak $
     */
    public class AddressAction extends ActionSupport {

        private Set addresses = new LinkedHashSet();

        public Set getAddresses() { return addresses; }
        public void setAddresses(Set addresses) { this.addresses = addresses; }


        public String input() throws Exception {
            return SUCCESS;
        }

        public String submit() throws Exception {
            System.out.println(addresses);
            return SUCCESS;
        }
    }

     

    //AddressAction转换配置文件AddressAction-conversion.properties

    KeyProperty_addresses=id
    Element_addresses=org.apache.struts2.showcase.conversion.Address
    CreateIfNull_addresses=true

     

    // JSP代码 

    <s:form action="submitAddressesInfo" namespace="/conversion">
      <s:iterator value="%{new int[3]}" status="stat">
       <s:textfield label="%{'Address '+#stat.index}"
            name="%{'addresses(\\'id'+#stat.index+'\\').address'}" />
      </s:iterator>
      <s:submit />
     </s:form>

     

     上述代码会转换为:

    <s:form action="submitAddressInfo" namespace="/conversion">
      <s:textfield label="Address 0"
          name="addresses('id0')" />
      <s:textfield label="Address 1"
          name="addresses('id1')" />
      <s:textfield label="Address 2"
          name="addresses('id2')" />
      <s:submit />
     </s:form>

     

    注意两个地方:

    第一,没有向服务器提交Address的id属性,那么Address的id属性是什么呢?
    KeyProperty_addresses=id表示向服务器提交的内容的key部分("id0”, "id1”, "id2”)会被认定为Addredd的id。

    第二,CreateIfNull_addresses=true表示及时客户端没有向服务器提交任何Address内容,服务器也会为AddressAction的addresses 建立一个长度为0的Set。

     

    相关的一些经验

    开 发的过程中不要一味的使用String类型,使用String类型无论在处理的速度还是内存的使用上都不是最好的方式。一般情况下,Java的模型类 (JavaBean, Action等都可以视为Java模型类,因为其中表示了模型的信息),一般情况下需要和数据库中的类型一致。这样才能保证最好的性能。

    那么像java.util.Date,Integer等类型需要表示到JSP页面上的时候还是需要表示为String类型的,但是Struts2都已经帮助实现了,所以请使用具体的类型吧,不要总是使用String类型。

     

     

    发表于 @ 2007年12月05日 20:23:00|评论(loading...)|编辑

    评论

    #alex.xu 发表于2008-01-08 23:39:14  IP: 218.80.119.*
    漂亮 ,说实话 比官方文档写的好
    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © allin