有没有办法配置Struts绑定null而不是空String?

当用户决定将表单中的字段保留为空时,Apache Struts将空String绑定为ActionForm属性的值。 有没有办法全局修改行为并选择null而不是空String

我知道Spring MVC完全相同,但也有StringTrimmerEditor可以注册为属性编辑器将字符串修剪为null

一个可能的解决方案 – 允许所有String字段的单个转换入口点 – 将注册一个自定义转换器,但不能使用Struts但使用BeanUtils 。

为了将请求参数映射到表单属性,Struts使用其RequestUtils类的populate方法 。 这个类反过来使用BeanUtils实现来做它的工作。

一个简单的流程就像 Struts的RequestUtils > BeanUtils > BeanUtilsBean > ConvertUtils > ConvertUtilsBean > Converter 。

有趣的是,还有一个StringConverter ,它可以从String转换为… aaaaaa … String!

ConvertUtils类有一个寄存器方法,可用于注册转换器,覆盖现有的转换器。 这意味着您可以自己编写自定义字符串转换器,它为空字符串返回null,然后您可以等待Struts应用程序完全加载,这样您就不会感到意外(即确保您的转换器是最后一个为String类型注册的)。

加载应用程序后,您将介入并使用您自己的实现覆盖默认的String转换器。 例如,您可以使用ServletContextListener执行此操作,并在contextInitialized方法中调用ConvertUtils.register(...)

然后在web.xml配置监听器,你应该很高兴 。

我想你也可以使用你自己的BeanUtils实现,重写类org.apache.commons.beanutils.converters.AbstractConverter和org.apache.commons.beanutils.converters.StringConverter

在web.xml中使用下面的代码

  convertNull true  

默认情况下,在ActionForm中将String值声明为NULL
Eg: private String str = null;

编辑:解决方案是这样的。 我认为对于该属性你有setter和getter方法,在getter方法中检查值是否为空,然后你explisitly设置为null值。

请参阅Apache的StringUtils.stripToNull()方法。

至于配置,Struts没有给我们这个function(我不记得)。 我建议从ActionForm重写reset()方法,但是在控制器重新填充表单bean之前调用它。

Cf http://struts.apache.org/development/1.x/userGuide/configuration.html for convertNull 😉

convertNull – 填充表单时强制模拟1.0版本的行为。 如果设置为“true”,则数字Java包装器类类型(如java.lang.Integer)将默认为null(而不是0)。 (从1.1版开始)[false]

这是一个有点老问题,但我通过实施另一个解决方案(我想以更简单的方式)解决了这个问题。

我实现了一个TypeConverter来将空字符串转换为null。 需要两个文件:

转换器。

 public class StringEmptyToNullConverter implements TypeConverter { private static final Logger log = LoggerFactory.getLogger(StringEmptyToNullConverter.class); @Override public Object convertValue(Map arg0, Object arg1, Member member, String arg3, Object obj, Class arg5) { String[] value = (String[]) obj; if (value == null || value[0] == null || value[0].isEmpty()) { logDebug("is null or empty: return null"); return null; } logDebug("not null and not empty: return '{}'", value[0]); return value[0]; } private void logDebug(String msg, Object... obj) { if (log.isDebugEnabled()) { log.debug(msg, obj); } } } 

寄存器名为xwork-conversion.properties 。 您必须将此文件放在Java路径中。

 # syntax:  =  java.lang.String = StringEmptyToNullConverter 

请参阅struts 转换器文档

Struts 2为拦截器提供了一个很好的机制,我认为它比使用BeanUtils更安全,更容易。 这是我使用的代码,基于Cimballi的博客,但编辑为在Java 7中编译(原始版本是2009年):

 import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.Interceptor; import java.util.ArrayList; import java.util.Collection; import java.util.Map; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; public class RemoveEmptyParametersInterceptor implements Interceptor { public RemoveEmptyParametersInterceptor() { super(); } /** * @see com.opensymphony.xwork2.interceptor.Interceptor#destroy() */ public void destroy() { // Nothing to do. } /** * @see com.opensymphony.xwork2.interceptor.Interceptor#init() */ public void init() { // Nothing to do. } public String intercept(final ActionInvocation invocation) throws Exception { final String result; final ActionContext actionContext = invocation.getInvocationContext(); final Map parameters = actionContext.getParameters(); if (parameters == null) { // Nothing to do. } else { final Collection parametersToRemove = new ArrayList(); for (final Map.Entry entry : parameters.entrySet()) { final Object object = entry.getValue(); if (object instanceof String) { final String value = (String) object; if (StringUtils.isEmpty(value)) { parametersToRemove.add((String) entry.getKey()); } } else if (object instanceof String[]) { final String[] values = (String[]) object; final Object[] objects = ArrayUtils.removeElement(values, ""); if (objects.length == 0) { parametersToRemove.add((String) entry.getKey()); } } else { throw new IllegalArgumentException(); } } for (final String parameterToRemove : parametersToRemove) { parameters.remove(parameterToRemove); } } result = invocation.invoke(); return result; } } 

以下是我在struts.xml文件中使用它的方法:

          ...  

有人向我指出,原始问题中的ActionForm是一个Struts 1约定(此问题已被正确标记),但由于Google仍然带有一个Struts 2查询,我希望这个答案对其他人有用。