10级学员 张家玮课堂笔记
建立项目、添加Struts 2所需的类库及修改web.xml的步骤不再提示,本例取项目名为“Struts2TypeConverter”。本例建立一个简单的页面,如图所示,让客户端填写用户信息,然后提交,在另一个页面展示出所填信息。
本例中应用了模型传值方式,故需要建立一个模型类User.java。代码如下:
package org.vo; import java.util.Date; public class User { private String username; private String password; private int age; private Date bir; private String tel; //这里省略上述属性的get和set方法 }
故typeconverter.jsp页面代码可以写为:
<%@ page language="java" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>类型转换</title> </head> <body> <s:form action="typeconverter" method="post"> <s:textfield name="user.username" label="姓名"></s:textfield> <s:password name="user.password" label="密码"></s:password> <s:textfield name="user.age" label="年龄"></s:textfield> <s:textfield name="user.bir" label="生日"></s:textfield> <s:textfield name="user.tel" label="电话"></s:textfield> <s:submit value="提交"></s:submit> </s:form> </body> </html>
自定义Action类“SimpleTypeConverter.java”的代码为:
package org.action; import org.vo.User; import com.opensymphony.xwork2.ActionSupport; public class SimpleTypeConverter extends ActionSupport{ private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public String execute() throws Exception { return SUCCESS; } }
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> <package name="default" extends="struts-default"> <action name="typeconverter" class="org.action.SimpleTypeConverter"> <result name="success">/show.jsp</result> </action> </package> </struts>
Action类处理完成后跳转的show.jsp页面代码为:
<%@ page language="java" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>类型转换显示界面</title> </head> <body> 姓名:<s:property value="user.username"/><br> 密码:<s:property value="user.password"/><br> 年龄:<s:property value="user.age"/><br> 生日:<s:property value="user.bir"/><br> 电话:<s:property value="user.tel"/><br> </body> </html>
运行该程序,提交后出现如图所示的界面。
如果想要把输入的电话的区号和号码分开显示,Struts 2的内置类型转换器就不能做到了,这时就需要程序员自定义类型转换器。这里要达到这样的目的,输入界面如图所示,当输入一个正确的电话后(因为还没讲到输入校验,故这里为做测试用例先输入正确的号码),单击“提交”按钮,出现如图所示的界面,分别输出区号和电话号(本项目名为MyTypeConverter,从图中的浏览器地址栏中可以看出)。
typeconverter2.jsp页面代码非常简单,还是一个输入框及“提交”按钮:
<%@ page language="java" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>自定义类型转换器</title> </head> <body> <s:form action="typeconverter2" method="post"> <s:textfield name="tel" label="请输入电话"></s:textfield> <s:submit value="提交"></s:submit> </s:form> </body> </html>
实现的Action类也正常写出:
package org.action; import org.vo.Tel; import com.opensymphony.xwork2.ActionSupport; public class MyTypeConverterAction extends ActionSupport{ private Tel tel; public String execute() throws Exception { return SUCCESS; } public Tel getTel() { return tel; } public void setTel(Tel tel) { this.tel = tel; } }
对应的Tel类Tel.java实现为:
package org.vo; public class Tel { private String sectionNo; private String telNo; public String getSectionNo() { return sectionNo; } public void setSectionNo(String sectionNo) { this.sectionNo = sectionNo; } public String getTelNo() { return telNo; } public void setTelNo(String telNo) { this.telNo = telNo; } }
自定义类型转换器需要实现Struts 2框架提供的TypeConverter接口,但这个接口比较复杂,里面的convertValue方法参数太多,不容易实现,Struts 2框架还提供了继承该接口的实现类DefaultTypeConverter。该类结构如下:
public class ognl.DefaultTypeConverter implements ognl.TypeConverter{
public DefaultTypeConverter();
public java.lang.Object convertValue(
java.util.Map context,
java.lang.Object value,
java.lang.Class toType
);
public java.lang.Object convertValue(
java.util.Map context,
java.lang.Object target,
java.lang.reflect.Member member,
java.lang.String prepertyName,
java.lang.Object value,
java.lang.Class toType
);
}
该类中有两个convertValue方法,其中第2个参数比较多的是TypeConverter类中的方法,所以继承该方法后,只需重写第1个convertValue方法即可。故本例中自定义类型转换器可写为。
该类主要重写了下面这个方法:
public Object convertValue(Map context, Object value, Class toType) {}
该方法中的参数有3个,下面分别介绍:
context:该参数就是类型转换的上下文,也就是Action的上下文。
value:value是需要转换的数据,这个数据可以是String类型,或者是需要转换的目标类型。从页面传递的数值有时可能不止一个,例如有几个输入框的名称相同,那么value就有多个值,不能用单独的String来接收值了,这时就必须用数组。这也就解释了上面为什么把value转换为字符串数组而不是字符串了
这里是要把提交的字符串类型转换为Action类中的tel属性的Tel类型,故在该Action类所在路径下编写一个配置文件即可。该配置文件名称必须遵守“action类型-conversion.properties”格式,所以该例的配置文件名就必须为:“MyTypeConverterAction-conversion.properties”,并且同Action放在同一位置下,这里即放在“org.action”包下。而配置文件的内容为“变量名=包名.类名”。其中,“变量名”是Action类中转换的属性名,本例就为“tel”,“包名.类名”就是要用的自定义的类型转换器所在的包及其类名,本例就为“org.converter. MyTypeConverter”。故本例中配置文件的内容就为:
tel=org.converter.MyTypeConverter
这样配置后,系统就会根据该路径找到类型转换器来完成其类型转换工作。下面就可以配置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> <package name="default" extends="struts-default"> <action name="typeconverter2" class="org.action.MyTypeConverterAction"> <result name="success">/show.jsp</result> </action> </package> </struts>
最后是显示页面show2.jsp:
<%@ page language="java" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>自定义类型转换</title> </head> <body> <s:property value="tel"/><br> 区号:<s:property value="tel.sectionNo"/><br> 号码:<s:property value="tel.telNo"/> </body> </html>
页面传递的数据被Struts 2拦截,根据struts.xml中的配置找到MyTypeConverterAction类,然后在系统环境中寻找是否含有该Action类对应的MyTypeConverterAction-conversion.properties配置文件,如果找到,将其触发,对变量tel进行类型转换。完成后,执行Action类中的execute方法,最后跳转到show.jsp页面。
自定义的类型转换器继承了DefaultTypeConverter类,并重写了其convertValue方法,里面用了一些if…else语句来判断是从String向对象类型转换,还是从对象向String类型转换(实际上,类型转换也就两个方面,当接收数据时是从String向目标类型转换,而当输出时是向String类型转换),Struts 2框架还提供了一个StrutsTypeConverter类,该类继承了DefaultTypeConverter类。该类的部分源代码。
该类已经实现了convertValue方法,并把对不同方向(String到目标类型还是目标类型到String)的处理分成两个方法来处理,程序员只需重写这两个对应的方法即可,比之继承DefaultTypeConverter方法较为简单些。故可以把上例的自定义转换器用继承该类来实现。
这样可以更简单明了地完成类型转换的工作。当然,要对该转换器进行应用,需要在配置文件中进行修改,内容修改为:
tel=org.converter.MyStrutsTypeConverter
需要把前面的配置语句删除,也可以注释掉,在.properties文件中对代码进行注释只需在该行代码头部加上“#”即可。例如,注释掉前面的配置:
#tel=org.converter.MyTypeConverter
前面的例子中,对类型的转换指定到了某个Action类中的属性,但如果有另外的Action类中也有“Tel”类型的属性,势必还要写一个配置文件,对其进行转换,Struts 2框架提供了全局类型转换器的配置。相对而言,前面配置的就属于局部类型转换器,全局类型转换器就是让整个系统关于某个类型的转换都可以应用配置的类型转换器,全局类型转换器的配置非常简单,只需改变配置文件的名称、内容及位置即可,在上例中如果要配置全局类型转换器,只需在“src”下建立配置文件“xwork-conversion.properties”,也就是和struts.xml文件在同一目录下,而内容编写为:
org.vo.Tel=org.converter.MyStrutsTypeConverter