Java 如何为多个.WAR项目构建和连接Spring数据库依赖项.JAR项目?

Java 如何为多个.WAR项目构建和连接Spring数据库依赖项.JAR项目?,java,spring,maven,jndi,mybatis,Java,Spring,Maven,Jndi,Mybatis,我正在构建一套web服务,它们都访问相同的数据库,但使用不同的凭据。因此,为了模块化数据库代码,我将其从每个web app.WAR文件中移出,并为数据库调用自己的.JAR文件。因此,如果WebApp1和WebApp2使用getAllColumnsFromTable1 MyBatis调用,我不必在两个项目中定义相同的映射器和域对象。这样,如果表1发生更改,我只需在一个地方更改MyBatis代码,并减少复制和粘贴错误 WebApp1 applicationContext.xml: <beans

我正在构建一套web服务,它们都访问相同的数据库,但使用不同的凭据。因此,为了模块化数据库代码,我将其从每个web app.WAR文件中移出,并为数据库调用自己的.JAR文件。因此,如果WebApp1和WebApp2使用getAllColumnsFromTable1 MyBatis调用,我不必在两个项目中定义相同的映射器和域对象。这样,如果表1发生更改,我只需在一个地方更改MyBatis代码,并减少复制和粘贴错误

WebApp1 applicationContext.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

  <context:annotation-config />

  <context:component-scan base-package="com.example.webapp1.service" />
  <context:component-scan base-package="com.example.webapp1.controller" />

  <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:/example/ds/WebApp1DS" />
  </bean>

  <bean id="databaseConnector" class="com.example.databaseconnector.connector"
    <property name="dataSource" ref="dataSource" />
  </bean>
</beans>

当我运行WebApp1时,程序失败,因为它找不到TableMapper bean来自动连接服务中的映射器。我缺少了什么样的Spring设置来让这一切一起工作,还是我的做法完全错了?

您似乎缺少了
TableMapper
bean的Spring配置。该类需要是一个Springbean,以便将其注入到
服务中。

将相关bean配置添加到您的
applicationContext.xml

Spring上下文层次结构在常见代码场景中会有所帮助。 如果您在一个EAR中有多个webapp,EAR可以有自己的上下文,即各个webapp上下文的父上下文。 此外,在每个webapp中,还可以有一个根上下文和单个子上下文。 您可以在web.xml中定义此层次结构。父上下文可以通过上下文参数指定:locatorFactorySelector和parentContextKey。通过上下文参数contextConfigLocation创建根上下文(在servlet外部)。可以在每个servlet的init param-context参数中指定子上下文

在EAR中放一个jar,保存所有公共服务和DAO层代码,并在beanRefContext.xml(基本上是另一个应用程序上下文xml)中定义它们。使这个jar在类路径中可用

在要引用父上下文代码的每个应用程序的web.xml中:

    <!--  root application context -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:rootContextBeans.xml</param-value>
    </context-param>
    <!--  shared service layer - parent application context -->
    <context-param>
        <param-name>locatorFactorySelector</param-name>
        <param-value>classpath:beanRefContext.xml</param-value>
    </context-param>
    <context-param>
        <param-name>parentContextKey</param-name>
        <param-value>servicelayer-context</param-value>
    </context-param>
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>     
    <servlet>
        <servlet-name>dispatcherServletApp1</servlet-name> 
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
        <init-param> 
            <param-name>contextConfigLocation</param-name> 
            <param-value>classpath*:webApp1.xml</param-value> 
        </init-param> 
    </servlet> 

上下文配置位置
类路径:rootContextBeans.xml
定位器工厂选择器
类路径:beanRefContext.xml
parentContextKey
服务层上下文
org.springframework.web.context.ContextLoaderListener
调度员ServletApp1
org.springframework.web.servlet.DispatcherServlet
上下文配置位置
classpath*:webApp1.xml
其中beanRefContext.xml类似于:

    <beans>
      <bean id="servicelayer-context" class="org.springframework.context.support.ClassPathXmlApplicationContext">
        <constructor-arg>
          <list>
            <value>data-layer-context.xml</value>
          </list>
        </constructor-arg>
      </bean>
    </beans>

data-layer-context.xml

这样您就可以实现您想要的。

我添加了一个应用程序上下文,并将数据源bean从.war传递到.jar。在java文件中设置它没有问题,但是我无法将数据源传递到applicationContext。因此,我只传递我的Jndi名称字符串,同样的问题再次无法从java类中的变量转到应用程序上下文中的bean。我做的最后一件事是在我的类上实现ApplicationContextAware。我能够将.war中定义的数据源传递给.jar的applicationContext,但是在.jar applicationContext中创建的任何内容都没有传递给.war。
<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>databaseconnector</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>Database Connector</name>

  <dependencies>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.2.3</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.2.1</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>4.0.0.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>4.0.0.RELEASE</version>
    </dependency>
  </dependencies>
</project>
package com.example.databaseconnector.connector;

import javax.sql.DataSource;

import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

public class DatabaseConnection implements InitializingBean {
  private DataSource dataSource;
  private DataSourceTransactionManager dataSourceTransactionManager;
  private SqlSessionFactoryBean sqlSessionFactoryBean;
  private MapperScannerConfigurer mapperScannerConfigurer;

  public DataSource getDataSource() {
    return this.dataSource;
  }

  public void setDataSource(DataSource dataSource) {
    this.dataSource = dataSource;
  }

  @Override
  public void afterPropertiesSet() throws Exception {
    if (getDataSource() == null) {
      throw new IllegalArgumentException("Property 'dataSource' is required");
    } else {
      this.configureDataSourceTransactionManager();
      this.configureSqlSessionFactoryBean();
      this.configureMapperScannerConfigurer();
    }
  }

  private void configureDataSourceTransactionManager() {
    this.dataSourceTransactionManager = new DataSourceTransactionManager();

    this.dataSourceTransactionManager.setDataSource(dataSource);
  }

  private void configureSqlSessionFactoryBean() {
    this.sqlSessionFactoryBean = new SqlSessionFactoryBean();

    this.sqlSessionFactoryBean.setDataSource(dataSource);

    this.sqlSessionFactoryBean.setConfigLocation(
        new ClassPathResource("mybatis-config.xml"));

    this.sqlSessionFactoryBean.setTypeAliasesPackage(
        "com.example.sewp5databaseconnector.domain");
  }

  private void configureMapperScannerConfigurer() {
    this.mapperScannerConfigurer = new MapperScannerConfigurer();

    this.mapperScannerConfigurer.setBasePackage(
        "com.example.databaseconnector.persistence");

    this.mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactoryBean");
  }
}
    <!--  root application context -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:rootContextBeans.xml</param-value>
    </context-param>
    <!--  shared service layer - parent application context -->
    <context-param>
        <param-name>locatorFactorySelector</param-name>
        <param-value>classpath:beanRefContext.xml</param-value>
    </context-param>
    <context-param>
        <param-name>parentContextKey</param-name>
        <param-value>servicelayer-context</param-value>
    </context-param>
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>     
    <servlet>
        <servlet-name>dispatcherServletApp1</servlet-name> 
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
        <init-param> 
            <param-name>contextConfigLocation</param-name> 
            <param-value>classpath*:webApp1.xml</param-value> 
        </init-param> 
    </servlet> 
    <beans>
      <bean id="servicelayer-context" class="org.springframework.context.support.ClassPathXmlApplicationContext">
        <constructor-arg>
          <list>
            <value>data-layer-context.xml</value>
          </list>
        </constructor-arg>
      </bean>
    </beans>