简体   繁体   中英

Struts2 Convention Plugin @Actions not mapping with Spring Boot

When upgrading my application to use Spring Boot version 2.1.8.RELEASE + struts2-convention-plugin with Struts2-core version 2.5.20 the actions are not being mapped correctly and I am getting the error

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

If I decalre the actions in struts.xml they work perfectly.

Below is my current configuration, why are they not mapping?

I have tried many diffrent configs and nothing seems to work, the StrutsPrepareAndExecuteFilter is firing but not actions are found, as if Spring has not scanned them. Could this be a dependency version issue?

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>

Controller

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

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

Main

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

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

}

UPDATE

依赖项

Having stepped through spring2-convention-plugin the class PackageBasedActionConfigBuilder has a method buildUrlSet which gets all the urls to classes that need to be scanned for Actions this was removing the urls to my classes and hence nothing was being scanned.

There is a condition excludeParentClassLoader which needs to be set to false (line 415) .

Solution

Set below constant's to -

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

After a couple days of trials and errors, here are a few clues.

Spring Boot 2.1.8 with Struts 2.5.20 configured with struts.xml works. Your projet POM requires at least the following dependencies:

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

I would also recommend adding the Config Browser Plugin to easily list the available actions:

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

It works when you package:

To get rid of struts.xml and configure your actions only through Java classes, the Convention plugin is required:

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

Notes:

  • the constant defined in struts.xml can also be migrated to the struts.properties file (default values listed here )
  • struts.xml takes precedence over the Convention plugin and struts.properties

When struts.xml is removed, the Convention plugin takes over and Action classes are mapped using the name of packages and classes

Still, as mentioned by the OP, configuration through annotations does NOT work out of the box with an embedded Tomcat (it does with an external Tomcat, though).

Best I could do so far, is make it work using an embedded Jetty instead of Tomcat, and adding the recommended configuration to struts.properties:

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

The starting log still shows errors, but I'm able to access the configured actions with no more XML.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM