有什么方法可以配置 Struts 绑定 null 而不是空字符串吗?

发布于 2024-11-10 13:40:37 字数 405 浏览 4 评论 0原文

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

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

When user decides to leave the field in the form empty the Apache Struts binds empty String as value for properties in the ActionForm. Is there any way to modify the behavior globally and opt for null instead of empty String?

I know that Spring MVC does exactly the same, but there is also StringTrimmerEditor that can be registered as property editor to trim strings to null.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

梦中楼上月下 2024-11-17 13:40:37

一种可能的解决方案(允许所有字符串字段使用单个转换入口点)是注册一个自定义转换器,但不是使用 Struts,而是使用 BeanUtils.

为了将请求参数映射到表单属性,Struts 使用 填充其 RequestUtils 类的方法。该类又使用 BeanUtils 实现来完成其工作。

一个简单的流程类似于 Struts 的 RequestUtils > BeanUtils> BeanUtilsBean> ConvertUtils> ConvertUtilsBean> 转换器。

有趣的是,还有一个 StringConverter 将字符串转换为... aaaaaa... 字符串!

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

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

然后,您可以在 web.xml 中配置侦听器,并 应该可以了

A possible solution - one that will allow a single conversion entry point for all your String fields - would be to register a custom convertor, but not with Struts but with BeanUtils.

For mapping request parameters to form properties, Struts makes use of the populate method of its RequestUtils class. This class in turn uses a BeanUtils implementation do do its work.

A simplistic flow would be something of the likes of Struts' RequestUtils > BeanUtils > BeanUtilsBean > ConvertUtils > ConvertUtilsBean > Converter.

The interesting thing is that there is also a StringConverter which converts from String to... aaaaaa... String!

The ConvertUtils class has a register method which you can use to register convertors, overwriting the existing ones. This means you could write yourself the custom String convertor which returns null for empty strings and then you could wait for your Struts application to load completely so that you have no surprises (i.e. make sure your converter is the last registered for type String).

After the application loads, you step in and overwrite the default String convertor with your own implementation. For example, you could do that using a ServletContextListener and call the ConvertUtils.register(...) in the contextInitialized method.

You then configure the listener in web.xml and you should be good to go.

橘和柠 2024-11-17 13:40:37

I think you might as well use your own implementation of the BeanUtils, overriding the class org.apache.commons.beanutils.converters.AbstractConverter and org.apache.commons.beanutils.converters.StringConverter

慕烟庭风 2024-11-17 13:40:37

在 web.xml 中使用以下代码

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

In web.xml use below code

<init-param>
      <param-name>convertNull</param-name>
      <param-value>true</param-value>
</init-param>
旧夏天 2024-11-17 13:40:37

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

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

Declare String value by default in ActionForm as NULL .
Eg: private String str = null;

EDIT : solution for this is .
I think for that attribute you have setter and getter methods, in getter method check if the value is empty, then you explisitly set for null value.

糖果控 2024-11-17 13:40:37

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

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

See Apache's StringUtils.stripToNull() method.

As for a configuration, Struts has not given us that functionality (I don't recall). I would have suggested overriding reset() method from the ActionForm but that is called before the controller repopulates the form bean.

腹黑女流氓 2024-11-17 13:40:37

参见 http://struts.apache.org/development/1.x/用户指南/configuration.html
对于convertNull ;-)

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

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

convertNull - Force simulation of the version 1.0 behavior when populating forms. If set to "true", the numeric Java wrapper class types (like java.lang.Integer ) will default to null (rather than 0). (Since version 1.1) [false]

〆凄凉。 2024-11-17 13:40:37

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

我实现了一个 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 转换器文档

It's a little old question, but I resolved this issue by implementing another solution (I think in an easier way).

I implement a TypeConverter to convert empty string to null.
Two files is necessary :

The converter.

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);
        }
    }
}

And the register, named xwork-conversion.properties. You have to put this file in your java path.

# syntax: <type> = <converterClassName>
java.lang.String = StringEmptyToNullConverter

see the struts converter documentation

梦旅人picnic 2024-11-17 13:40:37

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<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最初的问题是一个 Struts 1 约定(该问题已被正确标记),但由于 Google 仍然在这里提供了一个带有 Struts 2 查询的约定,我希望这个答案对其他人有用。

Struts 2 offers a good mechanism for this with interceptors, which I think is much safer and easier than mucking around with BeanUtils. Here is the code I used, based on Cimballi's Blog but edited to compile in Java 7 (the original was from 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;
  }
}

And here is how I use it in my struts.xml file:

<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>

It was pointed out to me that ActionForm in the original question is a Struts 1 convention (the question has since been correctly tagged) but since Google still brings one here with a Struts 2 query I hope this answer will be useful to someone else.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文