读书人

struts form类型转换有关问题,通过自定

发布时间: 2012-10-09 10:21:45 作者: rapoo

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启动后跟着加载就可以了..

读书人网 >软件架构设计

热点推荐