英文:
Deploying a Spring-Boot project using Maven and further importing it in other projects
问题
目前,我有两个项目,我们称为 Storefront 和 Dashboard,这两个项目都有相同的 POJO 类、服务和一些 API 端点。例如,考虑一个名为 Student 的类,在 Storefront 和 Dashboard 中都有这个类,以及它的服务类。此外,在不久的将来,我们将为客户实施另一个项目,即客户 Dashboard,它将拥有几乎 90% 相同的资源。
于是我想,如果我创建一个 Maven 项目,将所有项目需要的库都放在里面,按需进行导入。这将减少冗余,并使其他项目变得更加轻量。我之前使用过项目内仓库和 Dropbox 作为 Maven 仓库,所以这次对我来说会比较容易。
现在的问题是:我有一个与 Student 对应的 StudentRepository,它会使用 @Autowired
注解,对吗?据我所知,当我运行 @SpringBootApplication
时,一切都会正常工作,但正如我之前提到的,我将会导入这些包,这样做的话,程序会抛出空指针异常,因为 StudentRepository 的实例将为 null。
@SpringBootApplication
@EnableAutoConfiguration
@EntityScan
public class DemoApplication implements CommandLineRunner {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
StudentRepository repository;
public static void main(String[] args) {
SpringApplication.run(PaperTrueLibrariesApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
// This will work
logger.info("Inserting -> {}", repository.save(new Student("studentName", "primaryKey")));
}
// This won't
public void addAStudent(String studentName, String primaryKey) {
repository.save(new Student(studentName, primaryKey));
}
}
public class Test {
public static void main(String[] args) {
// This will throw a NullPointerException
new DemoApplication().addAStudent("yourNameProbably", "yourSocialSecurityNumber");
}
}
那么,有没有其他方法使这个工作起来?欢迎提出任何建议,提前谢谢。
英文:
So currently, I have two projects, let's say Storefront and Dashboard, and both of these projects have the same POJO classes, Services, and some API Endpoints. For example, consider a class Student, we have this class in Storefront as well as in the Dashboard along with its service class. Further, in near future, we'll be implementing another project for clients, a Client Dashboard, that'll have almost 90% of the same resources.
So I thought, what if I create a maven project with all the libraries I need across all projects and import them as needed. This would reduce the redundancy and would also make other projects light weighted. I've previously used the in-project repository and Dropbox as a maven repository so it'll be a bit easier for me this time.
Now the problem is: I have the StudentRepository corresponding to the Student, which is further used with the '@Autowired' annotation right? As per my knowledge, everything will work when I run the '@SpringBootApplication' but as I previously mentioned, I'll be importing these packages, and doing so, the program will through a NullPointerException cause the instance of the StudentRepository will be null.
@SpringBootApplication
@EnableAutoConfiguration
@EntityScan
public class DemoApplication implements CommandLineRunner {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
StudentRepository repository;
public static void main(String[] args) {
SpringApplication.run(PaperTrueLibrariesApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
// This will work
logger.info("Inserting -> {}", repository.save(new Student("studentName", "primaryKey")));
}
// This won't
public void addAStudent(String studentName, String primaryKey) {
repository.save(new Student(studentName, primaryKey));
}
}
public class Test {
public static void main(String[] args) {
// This will throw a NullPointerException
new DemoApplication().addAStudent("yourNameProbably", "yourSocialSecurityNumber");
}
}
So is there any other way to make this work? Any suggestions will be appreciated and thanks in advance.
答案1
得分: 1
有两种方法可以实现你想要的 -
首先,将你已经在构建文件(比如maven的pom.xml)中创建的必需jar包添加到你当前的项目中。
如果你在不同的项目中导入的类或代码不是一个Spring Bean,那么
在你的配置类中,将其以bean的形式返回,使用@Bean
注解。
@Configuration
public class YourConfigurationClass {
@Bean
SomeBean returnSomeBean() {
return new SomeBean();
}
}
如果你的类已经是一个Spring Bean,你只需要让Spring扫描所需的包,因为你已经通过在Maven中添加依赖项将其添加到了类路径中。
@Configuration
@ComponentScan({"com.yourpackage.fromCommanCodeJar"})
public class YouApplicationConfigurationClass {...}
英文:
There are two ways to achieve what you want -
First of all, add required jar that you have already created in your build file, say pom.xml for maven, in your current project.
If the class or code you are importing in different project is not a spring bean, then
In your configuration class, return it as a bean, using @Bean annotaion.
@Configuration
public class YourConfigurationClass {
@Bean
SomeBean returnSomeBean() {
return new SomeBean();
}
If your class is already a spring bean, you just need to ask spring to scan required package, as you already have that in your class path by adding dependency in maven.
@Configuration
@ComponentScan({"com.yourpackage.fromCommanCodeJar"})
public class YouApplicationConfigurationClass {....}
答案2
得分: 1
假设您有一个库 FooLibrary
和主应用程序 FooApplication
。其思想是在 FooApplication
中导入 FooLibrary
。
让我们从 FooLibrary
开始。主要有两个重要文件。这些是 FooLibraryInterface
和 FooLibraryConfiguration
。在这个示例中,我将不使用 FooLibraryInterface
。
FooLibraryInterface
是一个包含客户端可能需要 override
的重要方法的接口,而 FooLibraryConfiguration
则用于扫描并注入在 FooLibrary
中找到的 bean。因此,它如下所示:
public interface FooLibraryInterface {
public abstract Datasource configureDatabaseConnection();
}
FooLibraryConfiguration
将如下所示:
@Configuration
@ComponentScan("package.to.scan")
public class FooLibraryConfiguration {
@Bean
public YourBean beanName() {
return new YourBean();
}
}
您可以在 FooLibrary
中添加所有您需要的内容。现在我们的库已经准备好可以在 FooApplication
中导入,借助于 FooLibraryConfiguration
。
@SpringBootApplication
@Import(FooLibraryConfiguration.class) //this will import all the beans defined in the library
public class FooApplication {
public static void main(String[] args) {
SpringApplication.run(FooApplication.class, args);
}
}
注意:如果您有 EntityManager
管理的类(实体、存储库),则应在主应用程序中进行额外的库包扫描,因为我们不需要为单个应用程序使用不同的 EntityManager
。或者您可以一起扫描所有文件(从 @EnableJpaRepositories 或 em.setPackagesToScan("library.entities.package"); 到 @ComponentScan("base.library.package")
的单独扫描)
@Configuration
@EnableJpaRepositories(basePackages = { "library.repository.package" })
@EnableTransactionManagement
public class PersistenceConfig {
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan("library.entities.package");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
.....
}
更新
感谢 @keshavram-kuduwa,您可以从 https://spring.io/guides/gs/multi-module/#_create_the_library_project 访问 Spring 指南。
英文:
Assume that you have a library FooLibrary
and main application FooApplication
. The idea is importing FooLibrary
in FooApplication
.
Let's begin with FooLibrary
. So mainly there are 2 important files. These are FooLibraryInterface
and FooLibraryConfiguration
. In this example I will not use FooLibraryInterface
.
FooLibraryInterface
is an interface that holds important methods that the client might need to override
and FooLibraryConfiguration
to scan and inject beans found in FooLibrary
. So, here it follows
public interface FooLibraryInterface {
public abstract Datasource configureDatabaseConnection();
}
FooLibraryConfiguration
will be as the following:
@Configuration
@ComponentScan("package.to.scan")
public class FooLibraryConfiguration {
@Bean
public YourBean beanName() {
return new YourBean();
}
}
You can add all that you need in FooLibrary
. Now our library is ready to be imported in FooApplication
with the help of FooLibraryConfiguration
@SpringBootApplication
@Import(FooLibraryConfiguration.class) //this will import all the beans defined in the library
public class FooApplication {
public static void main(String[] args) {
SpringApplication.run(FooApplication.class, args);
}
}
NOTE: If you have EntityManager
managed classes(entity, repository), you should do an additional scan of the lib packages in the main application, since we don't need to have different EntityManager
for a single application. Or you may scan all files together (leaving individual scans from @EnableJpaRepositories or em.setPackagesToScan("library.entities.package"); with @ComponentScan("base.library.package")
)
@Configuration
@EnableJpaRepositories(basePackages = { "library.repository.package" })
@EnableTransactionManagement
public class PersistenceConfig {
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan("library.entities.package");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
.....
}
UPDATE
Thank you @keshavram-kuduwa, you can reach the spring guides from https://spring.io/guides/gs/multi-module/#_create_the_library_project
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论