Spring+SpringMvc+MybatisPlus+Aop实现多数据源切换

1、需求描述

  • 分别获取【server_1,server_2,server_3】数据库中t_person表信息。默认获取server_1数据库数据。

2、效果展示

3、项目目录简介

在这里插入图片描述

4、sql文件介绍

  • server_1
    在这里插入图片描述
  • server_2
    在这里插入图片描述
  • server_3
    在这里插入图片描述

5、核心配置文件代码

  • jdbc.properties
#server_1
jdbc1.driver=com.mysql.jdbc.Driver
jdbc1.url=jdbc:mysql://127.0.0.1:3306/server_1?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull
jdbc1.username=root
jdbc1.password=000

#server_2
jdbc2.driver=com.mysql.jdbc.Driver
jdbc2.url=jdbc:mysql://127.0.0.1:3306/server_2?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull
jdbc2.username=root
jdbc2.password=00

#server_3
jdbc3.driver=com.mysql.jdbc.Driver
jdbc3.url=jdbc:mysql://127.0.0.1:3306/server_3?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull
jdbc3.username=root
jdbc3.password=00

  • spring-beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       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-4.3.xsd">

    <context:component-scan base-package="com.hf.db">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!--server_1-->
    <bean id="server_1" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="${jdbc1.username}"/>
        <property name="password" value="${jdbc1.password}"/>
        <property name="url" value="${jdbc1.url}"/>
        <property name="driverClassName" value="${jdbc1.driver}"/>
        <property name="initialSize" value="5"/>
    </bean>

    <!--server_2-->
    <bean id="server_2" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="${jdbc2.username}"/>
        <property name="password" value="${jdbc2.password}"/>
        <property name="url" value="${jdbc2.url}"/>
        <property name="driverClassName" value="${jdbc2.driver}"/>
        <property name="initialSize" value="5"/>
    </bean>

    <!--server_3-->
    <bean id="server_3" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="${jdbc3.username}"/>
        <property name="password" value="${jdbc3.password}"/>
        <property name="url" value="${jdbc3.url}"/>
        <property name="driverClassName" value="${jdbc3.driver}"/>
        <property name="initialSize" value="5"/>
    </bean>

    <!--读取当前的返回值key值,选择数据源-->
    <bean id="dataSourceOption" class="com.hf.db.utils.db.DynamicDataSourceUtils">
        <!--默认链接server_1-->
        <property name="defaultTargetDataSource" ref="server_1"/>
        <property name="targetDataSources">
            <map>
                <entry key="server_1" value-ref="server_1"/>
                <entry key="server_2" value-ref="server_2"/>
                <entry key="server_3" value-ref="server_3"/>
            </map>
        </property>
    </bean>

</beans>

  • spring-mybatis.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">

    <!-- 配置用mybatis-plus操作数据库 -->
    <bean id="sqlSessionFactoryBean" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
        <!-- 指定数据源 -->
        <property name="dataSource" ref="dataSourceOption"/>
        <property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"/>
        <property name="typeAliasesPackage" value="com.hf.db.entity"/>
        <property name="globalConfig" ref="globalConfiguration"/>

    </bean>

    <!-- 定义MybatisPlus的全局策略配置-->
    <bean id="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
        <property name="dbColumnUnderline" value="true"/>
        <property name="idType" value="0"/>
        <property name="tablePrefix" value="t_"/>
    </bean>

    <!-- 将所有mapper接口的实现类自动加入到ioc容器中  -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.hf.db.dao"/>
    </bean>

</beans>

  • spring-aop.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

    <!-- spring配置事务 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSourceOption"></property>
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <aop:config>
        <aop:pointcut expression="execution(* com.hf.db.service.*.*(..))" id="txPoint"/>
        <aop:advisor advice-ref="myAdvice" pointcut-ref="txPoint"/>
    </aop:config>

    <tx:advice id="myAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*"/>
            <tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
        </tx:attributes>
    </tx:advice>

</beans>

  • springMvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
		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-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--配置只扫描controller -->
    <context:component-scan base-package="com.hf.db.controller" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!-- 映射动态资源 -->
    <mvc:annotation-driven/>

    <!-- 映射静态资源 -->
    <mvc:default-servlet-handler/>

    <!-- 启动@aspectj的自动代理支持-->
    <aop:aspectj-autoproxy expose-proxy="true"/>

    <!--允许跨域访问-->
    <mvc:cors>
        <mvc:mapping path="/**"/>
    </mvc:cors>

</beans>

  • ChooseDataSource.java
package com.hf.db.aspect;

import java.lang.annotation.*;

/**
 * 功能描述: <br>
 * 〈
 * 动态切换数据源自定义注解类
 * 〉
 *
 * @className: ChooseDataSource
 * @author: hf
 * @version: 1.0.0
 * @date: 2018/12/25 18:21
 */
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ChooseDataSource {

    /**
     * 数据库名称
     */
    String dataSourceName() default "server_1";
}

  • ChooseDataSourceAspect.java
package com.hf.db.aspect;

import com.hf.db.utils.db.DataSourceCheckUtils;
import com.hf.db.utils.db.DynamicDataSourceHolder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 功能描述: <br>
 * 〈
 * Aop动态切换数据源的具体实现
 * 〉
 *
 * @className: ChooseDataSource
 * @author: hf
 * @version: 1.0.0
 * @date: 2018/12/25 18:21
 */
@Aspect
@Component
public class ChooseDataSourceAspect {

    /**
     * 功能描述: <br>
     * 〈
     * 配置接入点,切入controller层
     * 〉
     *
     * @className: ChooseDataSourceAspect
     * @author: hf
     * @version: 1.0.0
     * @date: 2018/12/25 18:25
     * @param: []
     * @return: void
     */
    @Pointcut("execution(* com.hf.db.controller..*.*(..))")
    private void controllerAspect() {
    }

    /**
     * 功能描述: <br>
     * 〈
     * 配置切面动态切换数据源
     * 〉
     *
     * @className: ChooseDataSourceAspect
     * @author: hf
     * @version: 1.0.0
     * @date: 2018/12/25 18:25
     * @param: [joinPoint 切点]
     * @return: java.lang.Object
     */
    @Around("controllerAspect()")
    public Object permission(ProceedingJoinPoint joinPoint) throws Throwable {
        Object target = joinPoint.getTarget();
        Object[] args = joinPoint.getArgs();
        Method method = getMethod(joinPoint, args);
        //获取数据库名称参数
        ChooseDataSource chooseDataSource = method.getAnnotation(ChooseDataSource.class);
        if (chooseDataSource != null) {
            String dataSourceName = chooseDataSource.dataSourceName();
            //检查数据库名称是否存在
            if (DataSourceCheckUtils.check(dataSourceName)) {
                DynamicDataSourceHolder.putDataSourceName(dataSourceName);
            } else {
                DynamicDataSourceHolder.putDataSourceName("server_1");
            }
        }
        return joinPoint.proceed();
    }

    /**
     * 功能描述: <br>
     * 〈
     * 获取切面信息
     * 〉
     *
     * @className: ChooseDataSourceAspect
     * @author: hf
     * @version: 1.0.0
     * @date: 2018/12/7 15:28
     * @param: [joinPoint 切点, args 参数]
     * @return: java.lang.reflect.Method
     */
    private Method getMethod(ProceedingJoinPoint joinPoint, Object[] args) throws NoSuchMethodException {
        String methodName = joinPoint.getSignature().getName();
        Class clazz = joinPoint.getTarget().getClass();
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            if (methodName.equals(method.getName())) {
                return method;
            }
        }
        return null;
    }
}

  • DynamicDataSourceHolder.java
package com.hf.db.utils.db;

/**
 * 功能描述: <br>
 * 〈
 * 解决线程安全问题
 * 〉
 *
 * @className: DynamicDataSourceHolder
 * @author: hf
 * @version: 1.0.0
 * @date: 2018/12/25 18:18
 * <p>
 * History:
 * <author:>          <time:>          <version:>          <desc:>
 */
public class DynamicDataSourceHolder {

    //解决线程安全问题
    private static final ThreadLocal<String> holder = new ThreadLocal<String>();

    public static void putDataSourceName(String dataName) {
        holder.set(dataName);
    }

    public static String getDataSourceName() {
        return holder.get();
    }

    //默认链接server_1服务器
    public static class DataSourceName {
        public final static String dataSource = "server_1";
    }
}
  • DataSourceCheckUtils.java
package com.hf.db.utils.db;

import java.util.Arrays;
import java.util.List;

/**
 * 功能描述: <br>
 * 〈
 * 判断数据源是否存在
 * 〉
 *
 * @className: DataSourceCheckUtils
 * @author: hf
 * @version: 1.0.0
 * @date: 2018/12/25 18:16
 */
public class DataSourceCheckUtils {

    static List<String> souList = Arrays.asList("server_1", "server_2", "server_3");

    /**
     * 功能描述: <br>
     * 〈
     * 检查动态切换的数据源是否存在
     * 〉
     *
     * @className: DataSourceCheckUtils
     * @author: hf
     * @version: 1.0.0
     * @date: 2018/12/25 18:16
     * @param: [dataSourceName 传递过来的数据源名称]
     * @return: boolean
     */
    public static boolean check(String dataSourceName) {
        boolean flag = false;
        if (souList.contains(dataSourceName)) {
            flag = true;
        }
        return flag;
    }
}

  • PersonController.java
package com.hf.db.controller;


import com.hf.db.aspect.ChooseDataSource;
import com.hf.db.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author hf
 * @since 2018-12-25
 */
@RestController
public class PersonController {

    @Autowired
    PersonService personService;

    /**
     * 功能描述: <br>
     * 〈
     * 动态切换一号数据库【server_1】、获取所有人员信息
     * 〉
     *
     * @className: PersonController
     * @author: hf
     * @version: 1.0.0
     * @date: 2018/12/25 18:08
     * @param: []
     * @return: java.lang.Object
     */
    @ChooseDataSource()
    @GetMapping("/server_1/resultJson")
    public Object resultJson1() {
        return personService.selectList(null);
    }

    /**
     * 功能描述: <br>
     * 〈
     * 动态切换一号数据库【server_2】、获取所有人员信息
     * 〉
     *
     * @className: PersonController
     * @author: hf
     * @version: 1.0.0
     * @date: 2018/12/25 18:09
     * @param: []
     * @return: java.lang.Object
     */
    @ChooseDataSource(dataSourceName = "server_2")
    @GetMapping("/server_2/resultJson")
    public Object resultJson2() {

        return personService.selectList(null);
    }

    /**
     * 功能描述: <br>
     * 〈
     * 动态切换一号数据库【server_3】、获取所有人员信息
     * 〉
     *
     * @className: PersonController
     * @author: hf
     * @version: 1.0.0
     * @date: 2018/12/25 18:09
     * @param: []
     * @return: java.lang.Object
     */
    @ChooseDataSource(dataSourceName = "server_3")
    @GetMapping("/server_3/resultJson")
    public Object resultJson3() {

        return personService.selectList(null);
    }
}

7、其它

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
在信号处理领域,DOA(Direction of Arrival)估计是一项关键技术,主要用于确定多个信号源到达接收阵列的方向。本文将详细探讨三种ESPRIT(Estimation of Signal Parameters via Rotational Invariance Techniques)算法在DOA估计中的实现,以及它们在MATLAB环境中的具体应用。 ESPRIT算法是由Paul Kailath等人于1986年提出的,其核心思想是利用阵列数据的旋转不变性来估计信号源的角度。这种算法相比传统的 MUSIC(Multiple Signal Classification)算法具有较低的计算复杂度,且无需进行特征值分解,因此在实际应用中颇具优势。 1. 普通ESPRIT算法 普通ESPRIT算法分为两个主要步骤:构造等效旋转不变系统和估计角度。通过空间平移(如延时)构建两个子阵列,使得它们之间的关系具有旋转不变性。然后,通过对子阵列数据进行最小二乘拟合,可以得到信号源的角频率估计,进一步转换为DOA估计。 2. 常规ESPRIT算法实现 在描述中提到的`common_esprit_method1.m`和`common_esprit_method2.m`是两种不同的普通ESPRIT算法实现。它们可能在实现细节上略有差异,比如选择子阵列的方式、参数估计的策略等。MATLAB代码通常会包含预处理步骤(如数据归一化)、子阵列构造、旋转不变性矩阵的建立、最小二乘估计等部分。通过运行这两个文件,可以比较它们在估计精度和计算效率上的异同。 3. TLS_ESPRIT算法 TLS(Total Least Squares)ESPRIT是对普通ESPRIT的优化,它考虑了数据噪声的影响,提高了估计的稳健性。在TLS_ESPRIT算法中,不假设数据噪声是高斯白噪声,而是采用总最小二乘准则来拟合数据。这使得算法在噪声环境下表现更优。`TLS_esprit.m`文件应该包含了TLS_ESPRIT算法的完整实现,包括TLS估计的步骤和旋转不变性矩阵的改进处理。 在实际应用中,选择合适的ESPRIT变体取决于系统条件,例如噪声水平、信号质量以及计算资源。通过MATLAB实现,研究者和工程师可以方便地比较不同算法的效果,并根据需要进行调整和优化。同时,这些代码也为教学和学习DOA估计提供了一个直观的平台,有助于深入理解ESPRIT算法的工作原理。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值