struts form类型转换问题,通过自定义convert类来实现类型转换一
struts form会自动将表单中输入的值转换为定义的类型.
表单提交过来的类型均为String类型.而在form中可以定义诸如:int,double等类型.
演示如下:
配置文件:
<action path="/convertAction" type="com.lwf.struts.action.ConvertAction" name="convertForm" scope="request"><forward name="success" path="/convertResult.jsp"></forward></action>
?
<form-bean name="convertForm" type="com.lwf.struts.form.ConvertForm"></form-bean>
?
?
表单文件:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body><form action="convertAction.do" method="post">intvalue:<input type="text" name="intval"/><br>doublevalue:<input type="text" name="doubleval"/><br>booleanvalue:<input type="text" name="booleanval"/><br>sqldatevalue:<input type="text" name="dateval"/><br><input type="submit" value="submit"/></form></body></html>
?
?
form文件
package com.lwf.struts.form;import java.sql.Date;import org.apache.struts.action.ActionForm;public class ConvertForm extends ActionForm {private int intval;private double doubleval;private boolean booleanval;private Date dateval;public int getIntval() {return intval;}public void setIntval(int intval) {this.intval = intval;}public double getDoubleval() {return doubleval;}public void setDoubleval(double doubleval) {this.doubleval = doubleval;}public boolean isBooleanval() {return booleanval;}public void setBooleanval(boolean booleanval) {this.booleanval = booleanval;}public Date getDateval() {return dateval;}public void setDateval(Date dateval) {this.dateval = dateval;}}
?
?
action文件
package com.lwf.struts.action;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.struts.action.Action;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionForward;import org.apache.struts.action.ActionMapping;public class ConvertAction extends Action {public ActionForward execute(ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response)throws Exception {return mapping.findForward("success");}}
?
?
结果文件:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body>intvalue:${convertForm.intval }<br>doublevalue:${convertForm.doubleval }<br>booleanvalue:${convertForm.booleanval }<br>sqldatevalue:${convertForm.dateval }<br></body></html>
?
?
?
输出结果:
intvalue:0doublevalue:333.0booleanvalue:falsesqldatevalue:2009-03-02
?
?
可以改变表单中输入的值:
你会发现:在intvalue中输入非数字类型时,结果会自动显示为0
而doublevalue中输入一个整数如33时,结果会自动显示为33.0
而booleanvalue中输入1或Y或yes或on等结果显示为true.输入0或N或off时结果显示为false.
要注意的是这个测试我们使用的是java.sql.date来测试日期类型,我测试发现当输入2009-03-02时结果输出正确,而如果输入的值为2009/03/02时会报错.这说明类型转换是有选择性的..
上面可以得出一个结论,struts form做了类型转换.那么它是怎么实现的呢?
看struts源代码ActionServlet的init方法调用了initOther方法
里面我们会看到有许多类似以下方法:
ConvertUtils.register(new BooleanConverter(null), Boolean.class); ConvertUtils.register(new ByteConverter(null), Byte.class); ConvertUtils.register(new CharacterConverter(null), Character.class); ConvertUtils.register(new DoubleConverter(null), Double.class); ConvertUtils.register(new FloatConverter(null), Float.class);
??这里实际上使用了策略模式.
BooleanConverter,CharacterConverter等都实现了Converter接口.并实现了里面的方法.
所以如果有一些类型struts没有做转换时,如java.util.Date,我们可以写自己的convert类来实现Converter接口
public Object convert(Class type, Object value);
?
?
?
我们列出来initOther方法的源代码
protected void initOther() throws ServletException { String value; value = getServletConfig().getInitParameter("config"); if (value != null) { config = value; } // Backwards compatibility for form beans of Java wrapper classes // Set to true for strict Struts 1.0 compatibility value = getServletConfig().getInitParameter("convertNull"); if ("true".equalsIgnoreCase(value) || "yes".equalsIgnoreCase(value) || "on".equalsIgnoreCase(value) || "y".equalsIgnoreCase(value) || "1".equalsIgnoreCase(value)) { convertNull = true; } if (convertNull) { ConvertUtils.deregister(); ConvertUtils.register(new BigDecimalConverter(null), BigDecimal.class); ConvertUtils.register(new BigIntegerConverter(null), BigInteger.class); ConvertUtils.register(new BooleanConverter(null), Boolean.class); ConvertUtils.register(new ByteConverter(null), Byte.class); ConvertUtils.register(new CharacterConverter(null), Character.class); ConvertUtils.register(new DoubleConverter(null), Double.class); ConvertUtils.register(new FloatConverter(null), Float.class); ConvertUtils.register(new IntegerConverter(null), Integer.class); ConvertUtils.register(new LongConverter(null), Long.class); ConvertUtils.register(new ShortConverter(null), Short.class); } }
?
我们可以看到可能通过设置配置文件里面的参数convertNull来设置form的转换功能.如要取消转换可将convertNull设为N
?
?
将上面的Form中的dateval类型改为java.util.Date再测试发现报错:
DateConverter does not support default String to 'Date' conversion.
这说明当actionForm实例化之后准备setDateval的时候无法将String转换为java.util.Date类型.而上面演示的由String转换成java.sql.Date是可以了.
那么下面自己定义convert类,并注册进去..让它可以把String转换为java.util.Date类型
?
以下:convert类:
package com.lwf.struts.servlet;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import org.apache.commons.beanutils.Converter;public class UtilDateConverter implements Converter {public UtilDateConverter(Object object) {}public Object convert(Class type, Object value) {if(value == null){return value;}if(value instanceof Date){return value;}if(value instanceof String){try {SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");return sdf.parse((String)value);} catch (ParseException e) {// TODO Auto-generated catch blocke.printStackTrace();}}return null;}}
?
?
增加一个servlet在服务器启动的时候加载
package com.lwf.struts.servlet;import java.util.Date;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import org.apache.commons.beanutils.ConvertUtils;public class DateConvertServlet extends HttpServlet{public void init() throws ServletException {ConvertUtils.register(new UtilDateConverter(null), Date.class);}}
?
?
配置web.xml加入以下内容,并重启web服务
<servlet><servlet-name>DateConvertServlet</servlet-name><servlet-class>com.lwf.struts.servlet.DateConvertServlet</servlet-class><load-on-startup>10</load-on-startup></servlet>
?
?
把convertForm 的dateval改为java.util.Date类型.
在表单中输入2009/03/02
结果为:
intvalue:0doublevalue:0.0booleanvalue:falsesqldatevalue:Mon Mar 02 00:00:00 CST 2009
?实践表明,调用了我们上面创建的convert类进行转换,将String类型转换为java.util.Date.
?
总结:
ActionServlet启动时将不同类型的convert放入map中.
public void register(Converter converter, Class clazz) { converters.put(clazz, converter); }
?当实例化actionForm后,按照对应的属性类型在map中寻找对应的convert类调用convert方法进行类型转换.
所以我们可以创建自己的convert类,再创建一个servlet在这个servlet的init方法里面注册convert类.并让servlet能够在ActionServlet启动后跟着加载就可以了..