jdk17 SpringBoot JPA集成多数据库

本文介绍了如何在SpringBoot应用中使用配置类和请求拦截器实现客户端地区切换时动态切换数据库。通过`DynamicDataSource`和`RequestContextHolder`,可以根据请求头中的地区信息从不同数据库源查询数据。
摘要由CSDN通过智能技术生成

switchRegion(切换地区)功能, 客户端可手动切换地区 , 查询不同的数据库, 后台根据地区切换数据库, 请求头添加region的key

配置类


import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;


/**
 * @author Wang
 */
@Configuration
public class DynamicDataSourceConfig {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.us")
    public DataSource usDataSource() {
        return DataSourceBuilder.create().build();
    }
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.ca")
    public DataSource caDataSource() {
        return DataSourceBuilder.create().build();
    }
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.other")
    public DataSource otherDataSource() {
        return DataSourceBuilder.create().build();
    }
    @Bean
    @Primary
    public DynamicDataSource dataSource(DataSource usDataSource, DataSource caDataSource, DataSource otherDataSource) {
        Map<Object, Object> targetDataSources = new HashMap<>(3);
        targetDataSources.put(DataSourceEnum.US.toString().toLowerCase(), usDataSource);
        targetDataSources.put(DataSourceEnum.CA.toString().toLowerCase(), caDataSource);
        targetDataSources.put(DataSourceEnum.OTHER.toString().toLowerCase(), otherDataSource);
        DynamicDataSource dynamicDataSource = new DynamicDataSource(usDataSource, targetDataSources);
        dynamicDataSource.afterPropertiesSet();
        return dynamicDataSource;
    }
}

import com.test.test.component.context.RequestContextHolder;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import javax.sql.DataSource;
import java.util.Map;

/**
 * @author Wang
 */
public class DynamicDataSource extends AbstractRoutingDataSource {

    public DynamicDataSource(DataSource firstDataSource, Map<Object, Object> targetDataSources) {
        setDefaultTargetDataSource(firstDataSource);
        setTargetDataSources(targetDataSources);
        afterPropertiesSet();
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return RequestContextHolder.getRegion();
    }
}

public enum DataSourceEnum {
    /**
     * region
     */
    US,
    CA,
    OTHER;
}

请求拦截器

import com.test.test.component.context.RequestContextHolder;
import com.test.test.core.HeaderCons;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;

/**
 * @author Wang
 */
public class RequestInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String region = request.getHeader(HeaderCons.X_REGION);
        if (region != null) {
            RequestContextHolder.setRegion(region);
        }
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        RequestContextHolder.clearRegion();
    }
}


import com.test.test.interceptor.RequestInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @author Wang
 */
@Configuration
public class ResourceConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new RequestInterceptor());
    }
}

线程上下文

/**
 * @author Wang
 */
public class RequestContextHolder {

    private RequestContextHolder(){}

    private static final ThreadLocal<String> REQUEST_HOLDER = new ThreadLocal<>();

    public static String getRegion() {
        return REQUEST_HOLDER.get();
    }

    public static void setRegion(String region) {
        REQUEST_HOLDER.set(region);
    }

    public static void clearRegion() {
        REQUEST_HOLDER.remove();
    }
}


application 配置

#jpa
spring.jpa.hibernate.ddl-auto=update
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.show-sql=true

# PostgreSQL
spring.datasource.us.jdbc-url=jdbc:postgresql://127.0.0.1:5432/test_us
spring.datasource.us.pool-name=test_us
spring.datasource.us.username=postgres
spring.datasource.us.password=123
spring.datasource.us.driver-class-name=org.postgresql.Driver

spring.datasource.ca.jdbc-url=jdbc:postgresql://127.0.0.1:5432/test_ca
spring.datasource.ca.pool-name=test_ca
spring.datasource.ca.username=postgres
spring.datasource.ca.password=123
spring.datasource.ca.driver-class-name=org.postgresql.Driver

spring.datasource.other.jdbc-url=jdbc:postgresql://127.0.0.1:5432/test_other
spring.datasource.other.pool-name=test_other
spring.datasource.other.username=postgres
spring.datasource.other.password=123
spring.datasource.other.driver-class-name=org.postgresql.Driver
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宁漂打工仔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值