You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Struts2 Spring插件autoWire为no时仍按类型注入内部类问题咨询

问题:Struts 2与Spring整合下String类型Bean导致重定向URL异常

环境信息

  • Struts版本:2.5.30

Struts-Spring配置

<constant name="struts.objectFactory" value="spring" />
<!-- spring injection wont auto happen.  Need to annotate with @autowired -->
<constant name="struts.objectFactory.spring.autoWire" value="no" />

Action映射配置

<action name="loginAuthentication" class="com.webexchange.actions.security.Login" method="executeNoSecurity">
    <interceptor-ref name="token" />
    <interceptor-ref name="stackWithSecurity" />

    <result name="success" type="redirectAction">
        <param name="actionName">${forwardUrl}</param>
        <param name="namespace">${forwardNamespace}</param>
        <param name="struts.token.name">token</param>
        <param name="token">${token}</param>
    </result>
    <result name="input">/Login.jsp</result>
    <result name="invalid.token">/WEB-INF/jsp/centers/common/SystemActionErrors.jsp</result>
</action>

引发问题的String类型Spring Bean

@Bean("passwordRuleString")
public String passwordRuleString(@Autowired @Qualifier("passwordRuleList") List<String> passwordRuleList) {

   StringBuilder sb = new StringBuilder();

    sb.append("Password must be ");

    boolean comma = false;

    for (String s : passwordRuleList){
        if(comma) {
            sb.append(", ");
        }
        sb.append(s);
        comma = true;
    }

    return sb.toString();
}

问题现象

使用redirectAction类型结果时,Struts会调用org.apache.struts2.result.ServletActionRedirectResult的四参数构造函数,该构造函数的所有字符串参数都被上述String Bean实例注入。尽管已配置struts.objectFactory.spring.autoWire="no"(文档说明此配置关闭外部自动装配,仅保留注解驱动和*Aware接口注入),但问题仍发生。

多数参数在构造后会被覆盖,但methodName值保留,导致重定向URL变为:

/myNamespace/myAction.action!Password must be Min length of 5, Contain at least 1 Number, Contain at least 1 Letter

而非预期的:

/myNamespace/myAction.action

最终引发应用404错误。

疑问解答

有没有配置能阻止Struts内部按类型自动注入?

单靠struts.objectFactory.spring.autoWire="no"挡不住这种情况,可以试试这两个办法:

  • 别直接在Spring容器里注册String类型Bean,把这类字符串封装到自定义配置类里。比如写个PasswordConfig类,把规则字符串作为它的属性,再把这个配置类注册成Bean,用的时候注入这个配置类就行,代码示例如下:
@Bean
public PasswordConfig passwordConfig(@Autowired @Qualifier("passwordRuleList") List<String> passwordRuleList) {
    PasswordConfig config = new PasswordConfig();
    StringBuilder sb = new StringBuilder("Password must be ");
    boolean comma = false;
    for (String s : passwordRuleList){
        if(comma) sb.append(", ");
        sb.append(s);
        comma = true;
    }
    config.setRuleString(sb.toString());
    return config;
}

class PasswordConfig {
    private String ruleString;
    // 添加上getter和setter
}
  • 或者给那个String Bean设置autowireCandidate = false,让Spring自动注入时忽略它。注解方式的话,修改@Bean注解:@Bean(name = "passwordRuleString", autowireCandidate = false)。

这算Bug吗?

严格来说不算Bug,属于框架整合的边界场景问题。当Struts用Spring当对象工厂时,Spring的构造注入逻辑会起作用——哪怕你设了autoWire="no",如果构造函数参数对应的类型在Spring容器里有Bean,Spring还是可能会自动匹配注入。Struts文档没把这种基础类型Bean的注入情况说清楚,才导致出现预期外的问题。

用Struts时只能创建自定义类的Spring Bean?

不是必须,但强烈不建议直接注册String、Integer这类基础类型的Bean。框架内部很多组件(比如Struts的Result、Interceptor)的构造函数里会用到这些基础类型,Spring会优先按类型匹配注入,很容易搞出莫名其妙的问题。如果要管理这类配置,最好封装到自定义类里,通过类属性来暴露值,既清晰又不会冲突。

内容的提问来源于stack exchange,提问作者Paul Zepernick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 17:45:46