Struts2 约定插件 @Actions 未与 Spring 引导映射

Struts2 Convention Plugin @Actions not mapping with Spring Boot

升级我的应用程序以使用 Spring 引导版本 2.1.8.RELEASE + struts2-convention-plugin使用 Struts2-核心版本 2.5.20 操作未正确映射,我收到错误

com.opensymphony.xwork2.config.ConfigurationException: There is no Action mapped for namespace [/] and action name [home] associated with context path [].

如果我对 struts.xml 中的动作进行 decalre,它们将完美运行。

下面是我目前的配置,为什么没有映射?

我尝试了很多不同的配置,但似乎没有任何效果,StrutsPrepareAndExecuteFilter 正在触发但未找到任何操作,就好像 Spring 没有扫描它们一样。这可能是依赖版本问题吗?

application.yaml

  server:
    port: 8080
    servlet:
      context-path: /

Struts2.xml

    <struts>
        <constant name="struts.devMode" value="false" />
        <constant name="struts.convention.action.packages" value="com.myactions.action" />
        <constant name="struts.convention.action.includeJars" value=".*?/myjar.*?jar(!/)?,.*?/myjar*?jar(!/)?" />
        <constant name="struts.objectFactory" value="spring" />
        <constant name="struts.objectFactory.spring.autoWire" value="name" />
        <constant name="struts.multipart.maxSize" value="100000000" />
        <constant name="struts.convention.default.parent.package" value="struts-default"/>

    ## THIS WORKS
    <!--    <package name="home"  extends="struts-default">-->
    <!--        <action name="actionHome" class="com.myactions.action.HomeController" method="actionHome">-->
    <!--            <result name="success">home.jsp</result>-->
    <!--        </action>-->
    <!--    </package>-->

    </struts>

控制器

@Namespace("/")
public class HomeController extends BaseController {

    @Action("home")
    public String actionHome() throws Exception {           
        return SUCCESS;
    }   
}

主要

@SpringBootApplication
@ServletComponentScan
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder springApplicationBuilder) {
        return springApplicationBuilder.sources(Application.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

Struts2 过滤器

@WebFilter("/*")
public class Struts2Filter extends StrutsPrepareAndExecuteFilter {

}

更新

逐步完成 spring2-convention-plugin class PackageBasedActionConfigBuilder 有一个方法 buildUrlSet 可以获取所有需要的 urls 到 class要扫描 Actions,这是将 urls 删除到我的 classes,因此没有扫描任何内容。

有个条件excludeParentClassLoader需要设置为false(第415行).

解决方案

将下面的常量设置为 -

<constant name="struts.convention.exclude.parentClassLoader" value="false" />
<constant name="struts.convention.action.fileProtocols" value="jar,code-source" />

经过几天的反复试验,这里有一些线索。

Spring 引导 2.1.8 与 Struts 2.5.20 配置 struts.xml 工作。 您的项目 POM 至少需要以下依赖项:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.1.8</version>
</dependency>
...
<dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts2-core</artifactId>
    <version>${struts2.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts2-spring-plugin</artifactId>
    <version>2.5.20</version>
</dependency>

我还建议添加 Config Browser Plugin 以轻松列出可用操作:

<dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts2-config-browser-plugin</artifactId>
    <version>2.5.20</version>
</dependency>

打包时有效:

要摆脱 struts.xml 并仅通过 Java 配置您的操作 类,需要 Convention plugin

<dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts2-convention-plugin</artifactId>
    <version>2.5.20</version>
</dependency>

备注:

  • struts.xml中定义的常量也可以迁移到struts.properties文件中(默认值列出here
  • struts.xml 优先于 Convention 插件和 struts.properties

当 struts.xml 被删除时,约定插件接管并使用包名和 类 映射操作 类。由于一组 annotations.

,默认约定(操作到 URL 映射、结果路径...)也可以被覆盖

不过,正如 OP 所提到的,通过注释进行配置确实 NOT 开箱即用,带有嵌入式 Tomcat(它与外部 Tomcat, 虽然).

到目前为止我能做的最好的就是使用 embedded Jetty instead of Tomcat, and adding the recommended configuration 到 struts.properties:

struts.convention.exclude.parentClassLoader=false
struts.convention.action.fileProtocols=jar,code-source

启动日志仍然显示错误,但我可以访问已配置的操作而无需更多 XML。

更新

OP 更新后,我又深入了解了一些。事实证明,通过执行以下操作,约定插件在 Tomcat 嵌入的情况下工作正常,不需要 XML:

  • 将以下行添加到 struts.properties

    struts.convention.exclude.parentClassLoader=false
    
  • 升级 asm 模块 asmasm-commonsasm- tree 发布 6.2 或更高版本以防止类似于

    的错误
    ERROR org.apache.struts2.convention.DefaultClassFinder.<init>:95 - Unable to read class [...]