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



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

我知道SpringMVC也做同样的事情,但也有StringTrimmerEditor可以注册为属性编辑器,将字符串修剪为null

一个可能的解决方案是注册一个自定义转换器,但不是使用Struts,而是使用BeanUtils。

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

一个简单的流可以是Struts的RequestUtils>BeanUtils>BeanUtsBean>ConvertUtilsConvertUtilsBean>Converter。

有趣的是,还有一个StringConverter,它将String转换为…aaaaaa。。。一串

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

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

然后在web.xml中配置侦听器,就可以开始了。

我认为您还可以使用自己的BeanUtils实现,覆盖类org.apache.commons.BeanUtils.coverers.AbstractConverter和org.apache.communs.beanuutils.coverers.StringConverter

在web.xml中使用以下代码

<init-param>
      <param-name>convertNull</param-name>
      <param-value>true</param-value>
</init-param>

ActionForm中的String值默认声明为NULL
Eg: private String str = null;

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

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

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

Cfhttp://struts.apache.org/development/1.x/userGuide/configuration.html对于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: <type> = <converterClassName>
java.lang.String = StringEmptyToNullConverter

请参阅struts转换器文档

Struts2通过拦截器提供了一个很好的机制,我认为它比使用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<String, Object> parameters = actionContext.getParameters();
    if (parameters == null) {
        // Nothing to do.
    } else {
        final Collection<String> parametersToRemove = new ArrayList<String>();
        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文件中使用它:

<package name="webdefault" namespace="/" extends="struts-default">
      <interceptors>
        <interceptor name="removeEmptyParameters" class="com.sentrylink.web.struts.RemoveEmptyParametersInterceptor"/>
        <interceptor-stack name="webStack">
            <interceptor-ref name="removeEmptyParameters"/>
            <interceptor-ref name="defaultStack"/>
        </interceptor-stack>
      </interceptors>
     <default-interceptor-ref name="webStack"/>
     ...
</package>

有人向我指出,最初问题中的ActionForm是Struts1约定(该问题已经被正确标记),但由于谷歌仍然在这里引入了Struts2查询,我希望这个答案对其他人有用。

最新更新