簡體   English   中英

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

[英]Is there any way to configure Struts to bind null instead of empty String?

當用戶決定將表單中的字段留空時,Apache Struts 會將空String綁定為ActionForm中屬性的值。 有什么方法可以全局修改行為並選擇null而不是空String

我知道 Spring MVC 的功能完全相同,但也有StringTrimmerEditor可以注冊為屬性編輯器,以將字符串修剪為null

一種可能的解決方案 - 允許所有字符串字段的單個轉換入口點 - 將注冊一個自定義轉換器,但不是使用 Struts 而是使用BeanUtils

為了將請求參數映射到表單屬性,Struts 使用了 RequestUtils class 的填充方法 這個 class 反過來使用BeanUtils實現來完成它的工作。

一個簡單的流程類似於 Struts 的RequestUtils > BeanUtils > BeanUtilsBean > ConvertUtils > ConvertUtilsBean > Converter

有趣的是,還有一個StringConverter可以將 String 轉換為... aaaaaa ... String!

ConvertUtils class 有一個注冊方法,您可以使用它來注冊轉換器,覆蓋現有的。 這意味着您可以自己編寫自定義字符串轉換器,它為空字符串返回 null,然后您可以等待您的 Struts 應用程序完全加載,這樣您就不會感到意外(即確保您的轉換器是最后一次注冊為String類型的轉換器)。

應用程序加載后,您介入並用您自己的實現覆蓋默認的字符串轉換器。 例如,您可以使用ServletContextListener並在contextInitialized方法中調用ConvertUtils.register(...)

然后你在web.xml中配置監聽器,你應該對 go 很好

在 web.xml 使用下面的代碼

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

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

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

convertNull - 填充 forms 時強制模擬版本 1.0 行為。 If set to "true", the numeric Java wrapper class types (like java.lang.Integer ) will default to null (rather than 0). (從 1.1 版開始)[假]

這是一個有點老的問題,但我通過實施另一個解決方案解決了這個問題(我認為以更簡單的方式)。

我實現了一個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 轉換器文檔

Struts 2 通過攔截器為此提供了一個很好的機制,我認為這比使用BeanUtils更安全、更容易。 這是我使用的代碼,基於Cimbali 的博客,但經過編輯以在 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 查詢的問題帶到這里,我希望這個答案對其他人有用。

在 ActionForm 中默認將 String 值聲明為NULL
Eg: private String str = null;

編輯:解決方案是。 我認為對於該屬性,您有 setter 和 getter 方法,在 getter 方法中檢查值是否為空,然后明確設置 null 值。

請參閱 Apache 的StringUtils.stripToNull()方法。

至於配置,Struts 沒有為我們提供該功能(我不記得了)。 我會建議從ActionForm覆蓋reset()方法,但在 controller 重新填充表單 bean 之前調用該方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM