转换器的使用[转自网络]
时间:2010-06-14 来源:hkebao
转换器的使用
时间:2010-6-11
开发Web应用程序与开发传统桌面应用程序不同,Web应用程序实际上是分布个不同的主机(当然也可以同一个主机,不过比较少见)上的两个进程之间互交。这种互交建立在HTTP之上,它们互相传递是都是字符串。换句话说, 服务器可以的接收到的来自用户的数据只能是字符串或字符数组,而在服务器上的对象中,这些数据往往有多种不同的类型,如日期(Date),整数(int),浮点数(float)或自定义类型(UDT)等,如图1所示。因此,我们需要服务器端将字符串转换为适合的类型。
同样的问题也发生在使用UI展示服务器数据的情况。HTML的Form控件不同于桌面应用程序可以表示对象,其值只能为字符串类型,所以我们需要通过某种方式将特定对象转换成字符串。
即服务器端接收到的数据只能是字符串或字符数组。
而真正其操作的数据类型有可能是日期、整数、浮点数、或UDT类型。这样就需要转换了如:int age = Integer.parseInt((String)request.getParameter(“age”));
一般我们会这样将接收到的参数作一次转换处理。转成我们要的数据类型。
示例:
Date birthday = DateFormat.getInstance(DateFormat.SHORT).parse(strDate);
<input type="text" value="<%= DateFormat.getInstance(DateFormat.SHORT).format(birthday) %>" />
已有的转换器
对于一此经常用到的转换器,如日期、整数或浮点数等类型,Struts 2.0已经为您实现了。
- 预定义类型,例如int、boolean、double等;
- 日期类型, 使用当前区域(Locale)的短格式转换,即DateFormat.getInstance(DateFormat.SHORT);
- 集合(Collection)类型, 将request.getParameterValues(String arg)返回的字符串数据与java.util.Collection转换;
- 集合(Set)类型, 与List的转换相似,去掉相同的值;
- 数组(Array)类型, 将字符串数组的每一个元素转换成特定的类型,并组成一个数组。
对于已有的转换器,大家不必再去重新发明轮子。Struts在遇到这些类型时,会自动去调用相应的转换器。
PS:实现自己转换功能。
批量封装对象BEAN
业务需求:在同一个页面里面同时发布几个产品。如何实现?
1、 编写JAVABEAN代码
package tutorial;
import java.util.Date;
public class Product {
private String name;
private Double price;
private Date dateOfProduction;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public Date getDateOfProduction() {
return dateOfProduction;
}
public void setDateOfProduction(Date dateOfProduction) {
this.dateOfProduction = dateOfProduction;
}
}
2、 编写Action类
package tutorial;
import java.util.List;
import com.opensymphony.xwork2.ActionSupport;
public class ProductConfirm extends ActionSupport{
public List<Product> products; //类合成
public List<Product> getProducts() {
return products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
@Override
public String execute() {
for (Product p : products) {
System.out.println(p.getName() + "|" +p.getPrice() + "|" + p.getDateOfProduction());
}
return SUCCESS;
}
}
3、 配置配置文件
<?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>
<include file="struts-default.xml"/>
<package name="IOCDemo" extends="struts-default">
<action name="ProductConfirm" class="tutorial.ProductConfirm">
<result>/ShowProducts.jsp</result>
<result name="input">/error.jsp</result>
</action>
</package>
</struts>
注意啊!这里面的我们需要配置error错误页面。即如果校验失败的话如表单提交的数据有问题则进入到error页面。
如果这里面没有定义error页面的话就会抛404了!
4、 编写输入JSP页面AddProducts.jsp
<s:form action="ProductConfirm" theme="simple">
<table>
<tr style="background-color:powderblue; font-weight:bold;">
<td>Product Name</td>
<td>Price</td>
<td>Date of production</td>
</tr>
<s:iterator value="new int[3]" status="stat">
<!-遍历这个对象其值为new int[3]-à
<tr>
<td>
<s:textfield name="%{'products['+#stat.index+'].name'}" />
</td>
<td><s:textfield name="%{'products['+#stat.index+'].price'}"/></td>
<td><s:textfield name="%{'products['+#stat.index+'].dateOfProduction'}"/></td>
</tr>
</s:iterator>
<tr>
<td colspan="3"><s:submit /></td>
</tr>
</table>
</s:form>
注意:FORM里面的名称与BEAN直接匹配映射起来的!
4、编写ShowProducts.jsp.
<table>
<tr style="background-color:powderblue; font-weight:bold;">
<td>Product Name</td>
<td>Price</td>
<td>Date of production</td>
</tr>
<s:iterator value="products" status="stat">
<tr>
<td><s:property value="name"/></td>
<td>$<s:property value="price"/></td>
<td><s:property value="dateOfProduction"/></td>
</tr>
</s:iterator>
</table>
解释:
这个过程是JSP--à提交数据到JAVABEN存储。即先对JAVABEAN做set操作。然后在展现页面再做一次GET处理即可。
注意:
1、FORM表单的名称与BEAN里面的属性名称要保持一致。
2、JAVABEAN的好处就是提交之后匹配然后其实就相当于存储起来了。然后dispatcher到展现页面就可以直接遍历提取出来了。
转换错误处理
现在我们在struct.xml配置文件里面添加如下的一句
<result name="input">/AddProducts.jsp</result>
这一句的含义是什么呢?这表示如果输入的值有错误的话就返回到当前这个JSP页面。如果我们在这个JSP页面中添加如下的标签
<div style="color:red"><s:fielderror /></div>
这样的话就会将错误信息打印出来了!
- Invalid field value for field "products[0].dateOfProduction".
- Invalid field value for field "products[1].dateOfProduction".
以上的功能的都是通过Struts 2.0里的一个名为conversionError的拦截器(interceptor)工作,它被注册到默认拦截器栈(default interceptor stack)中。Struts 2.0在转换出错后,会将错误放到ActionContext中,在conversionError的作用是将这些错误封装为对应的项错误(field error),因此我们可以通过<s:fielderror />来将其在页面上显示出来。另外,大家看第二和第三行的Price都被赋为0.0的值,而第一行则保留其错误值。这同样是conversionError的功劳——没有出错的行调用的products[index].price(默认值为0.0),而出错的行则会被赋为页面所提交的错误值,这样可以提供更好的用户体验。
哦明白了。原来是它内置的一个拦截器处理了我们的输入错误了。不过呢我们一般不需要这样来做的我们可以在JS层处理。当然在服务端接收到的参数中我们也可以做一次过滤!
还有一种解决方案是什么呢?
就是修改我们的BEAN了如
public void setPrice(Double price) {
if (price == null) {
this.price = 0.0;
return;
}
if (price < 0) {
this.price = 0.0;
return;
}
this.price = price;
}
将客户端的数据进行一次修改处理转换。感觉这个功能应当于转换器功能是一样的/1