Struts2学习笔记(十二) 类型转换(Type Conversion)(下)
来源:互联网 发布:苏联入侵芬兰知乎 编辑:程序博客网 时间:2024/05/21 07:06
null引用处理
我们知道,我们在Action中定义属性时并没有对他们进行初始化,那么也就是Struts2在对请求参数进行类型转换时,我们的Action属性可能还是null。那么框架会自动将这些null的属性实例化一个默认的对象(在学习Parameters拦截器时已经看过源代码了):
(1) 如果我们的属性声明为List(Collection)类型,那么默认会给他实例化一个ArrayList对象
(2) 如果我们的属性声明为Map类型,那么默认会给他实例化一个HashMap对象
(3) 如果我们的属性是一个简单的JavaBean,并且含有一个没有参数的构造器,那么Struts2会通过ObjectFactory类的buildBean方法来给他实例化一个对应的对象
自定义类型转换器
要想实现自定义类型转换器,只需我们自定义的Class实现ognl.TypeConterter接口即可。Strtus2中的DefaultTypeConverter类已经实现了这个接口,并且其子类StrutsTypeConverter对它做了更好的扩充,这是一个抽象类,需要我们继承并实现其中的两个方法。
abstract Object
convertFromString(Map context,String[] values,Class toClass)
Converts one or more String values to the specified class.
abstract String
convertToString(Map context,Object o)
Converts the specified object to a String.
这样使得不用我们自己去判断转换的方向。 那么要实现自定义的类型转换器,选择实现StrutsTypeConverter类显得最方便。下面我们就动手自己写一个自定义类型转换器,来实现将字符串转换为User对象。
User.java
public class User {private String userName;private int age;public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}
UserAction.java
public class UserAction extends ActionSupport {private User user;public User getUser() {return user;}public void setUser(User user) {this.user = user;}@Overridepublic String execute() throws Exception {return SUCCESS;}}
UserConverter.java
public class UserConverter extends StrutsTypeConverter {@Overridepublic Object convertFromString(Map context, String[] values, Class toClass) {String[] input = values[0].split(":");if(input.length != 2){throw new TypeConversionException("请输入正确的格式如,zhangsan:21");}try {User user = new User();String name = input[0];int age = Integer.parseInt(input[1]);user.setUserName(name);user.setAge(age);return user;} catch (Exception e) {throw new TypeConversionException("请输入正确的格式如,zhangsan:21");}}@Overridepublic String convertToString(Map context, Object o) {User user = (User) o;String str = "Name : "+user.getUserName()+";Age : "+user.getAge();return null;}}
input.jsp
<body>
<s:iftest="hasFieldErrors()">
<s:iteratorvalue="fieldErrors">
<fontcolor="#FF0000"><s:propertyvalue="value[0]"/></font><br>
</s:iterator>
</s:if>
<formaction="user.action"method="post">
user: <inputtype="text"name="user"/>
<inputtype="submit"value="submit"/>
</form>
success.jsp
<body>
${user.userName }<br/>
${user.age }
</body>]
现在代码就写完了,剩下的就是要来注册我们的类型转换器了。我们需要在Action类所在目录下新建一个”ActionClass-conversion.properties”形式的文件,并在其中为Action的属性配置类型转换器,格式为:属性名=类型转换器类全名(好包名)。例如本例中需要在UserAction类所在目录下新建一个UserAction-conversion.properties文件,内容如下:
user =action.UserConverter
测试:
提交:
定制错误消息
这里我们在表单中都是按照我们预定的格式输入,那么如果我们输入的数据并不是按照我们规定的格式,那么会是什么结果呢?我们将输入改为”zhangsan-21”,再次提交:
这样的错误消息可能并不是我们想要的,那么我们怎么去定制这些错误消息呢。还记得我们在学习Action的时候学到的关于validate方法验证失败时的错误消息定制吧。在这里我们同样可以使用这种方法。只需要在我们的ActionClass.properties文件中按照指定的格式配置就可以了:
invalid.fieldvalue.fieldName= 自定义消息
这个文件也需要和Action类放在同一目录。例如本例中我们在UserAction.properties文件中为user成员属性添加一条类型转换错误消息:
invalid.fieldvalue.user=\u8BF7\u8F93\u5165\u6B63\u786E\u7684\u683C\u5F0F\u5982\uFF0Czhangsan\:21(内容为:请输入正确的格式如,zhangsan:21)
还记得吧,消息的内容都必须是unicode编码的。
现在我们再来测试,输入”zhangsan-21”,提交:
非Action的属性的自定义类型转换
除了Action的成员属性以外,我们还可以给其他类的成员变量定义自定义类型转换器。比如User类中有一个Address类型的属性,Address是我们自定义的类。那么我们可以为User类中的Address属性定义一个类型转换器。和Action一样,我们需要在这个类所在的目录下新建一个ClassName-conversion.properties的文件,其中内容定义的格式和上面讲的一样。
全局类型转换器
有时候我们定义的类(bean/model)并不只是在一个Action中会被用到,那么如果需要定义自定义类型转换器的话,如果为每个Action都创建一个ActionClass-conversion.properties来完成对该类型的转换,显得很不灵活。Strtus2还提供了全局的类型转换配置,它的配置不再是针对类的属性,而是正对类本身。我们需要在src(classpath)下新建一个名为xwork-conversion.properties的文件。文件的内容和为action属性定义类型转换器的格式相似,只不过key需要是类的全路径。例如:
bean.User = action.UserConverter
这样我们在多个Action中使用该类型的属性时就可以不用在一一的配置类型转换器了。
关于List和Map类型的类型转换
在上一篇中我们讨论过如何让Struts2来完成List/Map类型的属性的自动类型转换,但是条件是List/Map中的对象类型必须是Struts2内建类型转换器能够完成转换的类型,那么如果List/Map中的对象是我们自定义的数据类型,那么该怎么让Struts2来完成转换呢。
首先我们要告诉Struts2,List/Map类型属性中元素的类型,通过在ActionClass-conversion.properties文件中使用如下形式:
List: Element_Action中List类型属性名 = List中元素类型(类的全路径)
Map:key: Key_Action中Map类型属性名 = Map中Key的类型(类的全路径)
Value Element_Action中Map类型属性名 = Map中Value的类型(类的全路径)
struts2的文档中只介绍了这些。我疑惑的地方就是根据文档中的介绍,我们只是告诉了Struts2集合中元素的类型,但是并没告诉Struts2如何将请求参数的String类型转换为这些指定的类型。但是我按照文档中的说法来做了,发现转换并不能成功。由于集合中元素的类型并没有包含在Action的属性中,那么肯定不能在ActionClass-conversion.properties中配置类型转换器了。那么就只有为这个类配置一个全局转换器了,配置了类型转换器之后,Map类型可成功转换。
例子代码如下:
User.java略
UserAction.java
public class UserAction extends ActionSupport {
private List<User>users;
public List<User> getUsers() {
returnusers;
}
public void setUsers(List<User> users) {
this.users = users;
}
@Override
public String execute()throws Exception {
System.out.println(users);
returnSUCCESS;
}
}
UserAction-conversion.properties
Element_users = bean.User
CreateIfNull_users=true
xwork-conversion.properties
bean.User =action.UserConverter
UserConverter.java
public class UserConverter extends StrutsTypeConverter {@Overridepublic Object convertFromString(Map context, String[] values, Class toClass) {String[] input = values[0].split(":");if(input.length != 2){throw new TypeConversionException("请输入正确的格式如,zhangsan:21");}try {User user = new User();String name = input[0];int age = Integer.parseInt(input[1]);user.setUserName(name);user.setAge(age);return user;} catch (Exception e) {throw new TypeConversionException("请输入正确的格式如,zhangsan:21");}}@Overridepublic String convertToString(Map context, Object o) {User user = (User) o;String str = "Name : "+user.getUserName()+";Age : "+user.getAge();return null;}}
input.jsp
<body>
<s:iftest="hasFieldErrors()">
<s:iteratorvalue="fieldErrors">
<fontcolor="#FF0000"><s:propertyvalue="value[0]"/></font><br>
</s:iterator>
</s:if>
<formaction="user.action"method="post">
user: <inputtype="text"name="users[0]"/>
<inputtype="submit"value="submit"/>
</form>
</body>
success.jsp
<body>
${users[0].userName}<br/>
</body>
测试:
结果:
备注:我们不能将自定义的interface作为Action的属性,这是因为Struts2并不知道该给它实例化一个什么样的对象。还有就是在使用泛型的时候要注意类型擦出问题。
总结:在List/Map这个问题上不知道我理解的是否正确。如果理解的有问题还请路过的前辈指正一下啊!学了类型转换之后,觉得自定义类型转换器还真是麻烦,感觉没啥必要,我想应该没几个人将User的name和age放在一个input中吧,更何况还是需要按照指定的格式来。使用系统内建的类型转换器就好了,最多不过在表单上多做一点。不过学习一下类型转换还是对理解Struts2框架有帮助的。这里还忘了一个拦截器了,Conversion Error Interceptor,他会将从ActionContext中conversionErrors属性中的所有错误信息添加为Actin的field errors,这也正是我可以在Input页面使用hasFieldErrors等获取field error的方式来获取类型转换错误信息的原因。
- Struts2学习笔记(十二) 类型转换(Type Conversion)(下)
- Struts2学习笔记(十一) 类型转换(Type Conversion)(上)
- Struts2学习——(十二)Struts2类型转换
- C++类型转换操作符(type conversion operator)
- Struts2_学习笔记(十二)----Struts2总结
- Struts2学习笔记(十二)文件上传
- struts2学习笔记(二)——类型转换
- 尚硅谷学习笔记--Struts2 类型转换(1)
- 尚硅谷学习笔记--Struts2 类型转换(2)
- struts2学习(一)类型转换--DefaultTypeConverter
- SSH学习(四)Struts2类型转换
- struts2学习笔记(3)——struts2的局部类型转换
- struts2 Type Conversion 自定义类型转化
- 【转】struts2 Type Conversion 自定义类型转化
- Struts2.1笔记(五):Struts2的类型转换
- 类型转换---struts2学习笔记
- Struts2类型转换学习笔记
- Struts2学习笔记-类型转换
- Java实现歌曲可视化效果
- Java学习路径(三)过程篇
- 递归和非递归俩种方法实现二叉树的前序遍历
- 快速搭建vsftpd笔记
- 特立但不独行
- Struts2学习笔记(十二) 类型转换(Type Conversion)(下)
- Ubuntu 10.10下安装TFTP的步骤 tftp -hpa版本
- (GPS移植三部曲)Linux下移植GPS应用程序之常见问题的分析与解决方法之二
- 指针总结
- Java web 推荐书籍
- 《转载》hdu 动态规划题集
- 开发者,请享受协作、高效的写作,不要拒绝写技术博客
- firefox中JS读取XML文件
- MFC总结