SpringBoot使用编程方式配置DataSource的方法

Spring Boot使用固定算法来扫描和配置DataSource。这使我们可以在默认情况下轻松获得完全配置的DataSource实现。

Spring Boot还会按顺序快速的自动配置连接池(HikariCP, Apache Tomcat或Commons DBCP),具体取决于路径中的哪些类。

虽然Spring Boot的DataSource自动配置在大多数情况下运行良好,但有时我们需要更高级别的控制,因此我们必须设置自己的DataSource实现,因此忽略自动配置过程。

Maven依赖

总体而言,以编程方式创建DataSource实现非常简单。

为了学习如何实现这一目标,我们将实现一个简单的存储库层,它将对某些JPA实体执行CRUD操作。

我们来看看我们的演示项目的依赖项:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
  <groupId>com.h2database</groupId>
  <artifactId>h2</artifactId>
  <version>2.4.1</version>
  <scope>runtime</scope>
</dependency>

我们将使用内存中的H2数据库实例来运行存储库层。通过这样做,我们将能够测试以编程方式配置的DataSource,而无需执行昂贵的数据库操作。

让我们确保在Maven Central上查看最新版本的spring-boot-starter-data-jpa。

配置DataSource

如果我们坚持使用Spring Boot的DataSource自动配置并以当前状态运行我们的项目,程序将按预期工作。

Spring Boot将为我们完成所有重型基础设施管道。这包括创建H2 DataSource实现,该实现将由HikariCP,Apache Tomcat或Commons DBCP自动处理,并设置内存数据库实例。

此外,我们甚至不需要创建application.properties文件,因为Spring Boot也会提供一些默认的数据库设置。

正如我们之前提到的,有时我们需要更高级别的自定义,因此我们必须以编程方式配置我们自己的DataSource实现。

实现此目的的最简单方法是定义DataSource工厂方法,并将其放在使用@Configuration注解的类中:

@Configuration
public class DataSourceConfig {

  @Bean
  public DataSource getDataSource() {
    DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
    dataSourceBuilder.driverClassName("org.h2.Driver");
    dataSourceBuilder.url("jdbc:h2:mem:test");
    dataSourceBuilder.username("SA");
    dataSourceBuilder.password("");
    return dataSourceBuilder.build();
  }
}

在这种情况下,我们使用方便的DataSourceBuilder类 - 一个简洁的Joshua Bloch构建器模式 - 以编程方式创建我们的自定义DataSource对象。

这种方法非常好,因为构建器可以使用一些常用属性轻松配置DataSource。此外,它还可以使用底层连接池。

使用application.properties文件外部化DataSource配置

当然,也可以部分外部化我们的DataSource配置。例如,我们可以在工厂方法中定义一些基本的DataSource属性:

@Bean
public DataSource getDataSource() {
  DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
  dataSourceBuilder.username("SA");
  dataSourceBuilder.password("");
  return dataSourceBuilder.build();
}

并在application.properties文件中指定一些额外的配置:

spring.datasource.url=jdbc:h2:mem:test
spring.datasource.driver-class-name=org.h2.Driver

在外部源中定义的属性(例如上面的application.properties文件或通过使用@ConfigurationProperties注解的类)将覆盖Java API中定义的属性。

很明显,通过这种方法,我们不再将DataSource配置设置保存在一个地方。

另一方面,它允许我们保持编译时和运行时配置彼此并很好地分离。

这非常好,因为它允许我们轻松设置绑定点。这样我们可以从其他来源包含不同的DataSource,而无需重构我们的bean工厂方法。

测试DataSource配置
测试我们的自定义DataSource配置非常简单。整个过程归结为创建JPA实体,定义基本存储库接口以及测试存储库层。

  • 创建JPA实体

让我们开始定义我们的示例JPA实体类,它将为用户建模:

@Entity
@Table(name = "users")
public class User {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private long id;
  private String name;
  private String email;

  // standard constructors / setters / getters / toString

}
  • 存储库层

我们需要实现一个基本的存储库层,它允许我们对上面定义的User实体类的实例执行CRUD操作。

由于我们使用的是Spring Data JPA,因此我们不必从头开始创建自己的DAO实现。我们只需要扩展CrudRepository接口获得一个工作的存储库实现:

@Repository
public interface UserRepository extends CrudRepository<User, Long> {}
  • 测试存储库层

最后,我们需要检查我们的编程配置的DataSource是否实际工作。我们可以通过集成测试轻松完成此任务:

@RunWith(SpringRunner.class)
@DataJpaTest
public class UserRepositoryIntegrationTest {

  @Autowired
  private UserRepository userRepository;

  @Test
  public void whenCalledSave_thenCorrectNumberOfUsers() {
    userRepository.save(new User("Bob", "bob@domain.com"));
    List<User> users = (List<User>) userRepository.findAll();

    assertThat(users.size()).isEqualTo(1);
  }
}

UserRepositoryIntegrationTest类是测试用例。它只是运行两个存储库接口的CRUD方法来持久化并查找实体。

请注意,无论我们是否决定以编程方式配置DataSource实现,或将其拆分为Java配置方法和application.properties文件,我们都应该始终获得有效的数据库连接。

  • 运行示例应用程序

最后,我们可以使用标准的main()方法运行我们的演示应用程序:

@SpringBootApplication
public class Application {

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

  @Bean
  public CommandLineRunner run(UserRepository userRepository) throws Exception {
    return (String[] args) -> {
      User user1 = new User("John", "john@domain.com");
      User user2 = new User("Julie", "julie@domain.com");
      userRepository.save(user1);
      userRepository.save(user2);
      userRepository.findAll().forEach(user -> System.out.println(user);
    };
  }
}

我们已经测试了存储库层,因此我们确信我们的DataSource已经成功配置。因此,如果我们运行示例应用程序,我们应该在控制台输出中看到存储在数据库中的User实体列表。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • SpringBoot项目集成日志的实现方法

    SpringBoot使用Commons Logging进行所有内部日志记录,但保留底层日志实现.默认提供了Java Util Logging, Log4j2 和Logback日志配置.在每种情况下,都预先配置为使用控制台输出,并且还提供了可选的文件输出.(来自官网) 日志格式 SpringBoot默认的日志输出如下所示: 2014-03-05 10:57:51.112 INFO 45469 --- [ main] org.apache.catalina.core.StandardEngine :

  • SpringBoot中关于static和templates的注意事项以及webjars的配置

    1. 默认情况下, 网页存放于static目录下, 默认的"/"指向的是~/resouces/static/index.html文 2. 如果引入了thymeleaf, 则默认指向的地址为~/resouces/templates/index.html <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymel

  • SpringBoot个性化配置的方法步骤

    在上一篇中我们简单的介绍了SpringBoot项目的创建及其启动方式.在这一篇中我们主要介绍一下SpringBoot项目的个性化配置.因为通过上一篇中知识我们知道SpringBoot项目的默认端口为8080,那如果我要修改这个默认端口,应该怎么改呢?又比如SpringBoot项目在启动时,默认是没有项目名字的,那如果我们想要添加自己喜欢的项目名字又该怎么办呢?这些都在这一篇的内容中.好了,下面我们详细介绍一下怎么修改SpringBoot项目中的默认配置. 修改默认端口 在上一篇的SpringBo

  • SpringBoot AOP使用笔记

    1. 启用AOP a. 在类上添加@Aspect注解 b. 注入该类, 可以使用@Component进行注入到Spring容器中 2. 通过PointCut对象创建切入点 a. 在某个方法使用类似下面的方法进行注入 @Pointcut("execution(* com.sguess.service.IAOPService.*(..))") private void pointcut() { } i. 其中,execution表达式为 execution(modifiers-patter

  • SpringBoot实战之SSL配置详解

    1.SSL介绍和说明 SSL的配置也是我们在实际应用中经常遇到的场景 SSL(Secure Sockets Layer,安全套接层)是为网络通信提供安全及数据完整性的一种协议,SSL在网络传输层对网络连接进行加密.SSL协议位于TCP/IP协议与各种应用层协议之间,为数据通信提供安全支持.SSL协议可以分为两层:SSL记录协议(SSL Record Protocal),它建立在可靠的传输协议(如TCP)之上,为高层协议提供数据封装.压缩.加密等基础功能的支持.SSL握手协议(SSL Handsh

  • 配置SpringBoot方便的切换jar和war的方法示例

    网上关于如何切换,其实说的很明确,本文主要通过profile进行快速切换已实现在不同场合下,用不同的打包方式. jar到war修改步骤 pom文件修改 packaging配置由jar改为war 排除tomcat等容器的依赖 配置web.xml或者无web.xml打包处理 入口类修改 添加ServletInitializer 特别注意:当改成war包的时候,application.properties配置的server.port和server.servlet.context-path就无效了,遵从

  • SpringBoot之Java配置的实现

    Java配置也是Spring4.0推荐的配置方式,完全可以取代XML的配置方式,也是SpringBoot推荐的方式. Java配置是通过@Configuation和@Bean来实现的: 1.@Configuation注解,说明此类是配置类,相当于Spring的XML方式 2.@Bean注解,注解在方法上,当前方法返回的是一个Bean eg: 此类没有使用@Service等注解方式 package com.wisely.heighlight_spring4.ch1.javaconfig; publ

  • SpringBoot项目访问任意接口出现401错误的解决方案

    之前搭建了一个SpringBoot项目用于测试集成Redis和MyBatis以及Freemarker,搭建完成测通之后就没有再打开过.今天打开之后想要测试一个问题,发现在这个项目下无论请求哪个接口,浏览器都会跳转到一个登录页面,而且这个页面不是我写的,如下图: 地址栏里的login也是在我输入了自己的接口之后,自动跳转到了login 于是用Postman测试,得到401响应: 当时一脸蒙蔽,心想我代码里面没有写拦截器啊,而且拦截之后的页面也不是我写的.刚开始认为可能和端口有关,后来发现不是.于是

  • 在SpringBoot中通过jasypt进行加密解密的方法

    1.用途 在SpringBoot中,通过jasypt可以进行加密解密. 这个是双向的, 且可以配置密钥. 2.使用: 2.1通过UT创建工具类,并认识jasypt import org.jasypt.util.text.BasicTextEncryptor; import org.junit.Test; public class UtilTests { @Test public void jasyptTest() { BasicTextEncryptor encryptor = new Basi

  • SpringBoot下使用定时任务的方式全揭秘(6种)

    本文旨在用通俗的语言讲述枯燥的知识 定时任务作为一种系统调度工具,在一些需要有定时作业的系统中应用广泛,如每逢某个时间点统计数据.在将来某个时刻执行某些动作...定时任务在主流开发语言均提供相应的API供开发者调用,在Java中,实现定时任务有很多种方式,原生的方式实现一个完整定时任务需要由Timer.TimerTask两个类,Timer是定时器类,用来按计划开启后台线程执行指定任务,TimerTask一个抽象类,它的子类代表一个可以被Timer计划的任务.除此之外,还可以用ScheduledE

随机推荐