简体   繁体   中英

How to register beans that can be shared by multiple WARs (Spring boot + Tomcat)

I am developing an application with Spring boot and deploying multiple WARs to an external tomcat. I want to register a shareable bean with these WARs when tomcat starts.

I use: Java8, Spring boot(2.5.5) and Tomcat9

Bean I want to be shared by Apps:

public class TestData {
    private String username;
    
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
}

SampleApp(There are multiple apps that Autowire an instance of TestData in the same way):

@SpringBootApplication
@RestController
public class App extends SpringBootServletInitializer {
    @Autowired
    TestData testData;
    
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(App.class);
    }

    @RequestMapping(value = "SampleApp1", method = RequestMethod.GET)
    public String getUsername() {
        return testData.getUsername();
    }
}

Create a new project, lets call it yourapplication-commons and create your beans there. Add this project as a dependency to the projects that you will be converting to wars. If you are using maven, add this to the pom.xml of all the projects that need this dependency, if any other tool, manage accordingly. Reference: https://everyday.codes/java/creating-production-artifacts-in-a-multi-module-maven-project/

I think your question is about sharing the data of one singleton Bean between different application containers deployed in the same webserver.

This is not possible for security reasons. Each deployed application has its own classloader and hence cannot easily access beans residing in the memory of the other containers.

I suggest you add a microservice that is accessed by the different deployed applications and use that instead. It can easily be accessed via eg OpenFeign as a client and almost looks like a bean with getters and setters if done right.

There are several approaches to your problem, solving it on different levels.

  1. Create a shared library with required stuff and install it to Tomcat server. "Install" normally means to put assemled jars to $CATALINA_HOME/lib directory or similar. Class Loader HOW-TO can give you more details. Not sure how it works with shared instances of classes, but it's definitely possible to share classes (factories, for example) and configurations through shared library. With shared configuration and factories you can at least produce identical beans (not necessary the same , but it seems enough for you case).

  2. Define a JNDI resource shared between all applications. Of course, this requires your class to be accessible by Tomcat, so you first have to go through option 1. This way you can have "published" instance of a class shared between all applications. Details can be found at JNDI Resources HOW-TO . With this approach you can inject published resource with @Resource annotation.

  3. Create a microservice (as one of other answers suggests) that can provide you data and features and access it from your application. This gives you maximum flexibility but also brings complexity requiring actual communication to the microservice.

Obviously, options 1 and 2 require direct access to the server configuration.

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