Spring Boot中配置多个数据源
配置数据源实际上就是配置多个数据库,在一个配置文件中配置多个数据库,这样做主要的好处有以下几点:
- 数据库隔离:通过配置多个数据源,可以将不同的业务数据存储在不同的数据库中,实现数据的隔离。这样可以提高系统的安全性和稳定性,避免不同业务之间的数据相互干扰。
- 性能优化:通过配置多个数据源,可以将读写操作分离到不同的数据库中,从而提高系统的并发性能。例如,将读操作集中在一个主数据库中,将写操作分散到多个从数据库中,可以有效地减轻数据库的读写压力,提高系统的响应速度。
- 扩展性:当系统需要扩展到多个地理位置或多个数据中心时,配置多个数据源可以更好地支持分布式部署。每个地理位置或数据中心可以配置一个独立的数据源,使得数据访问更加高效和可靠。
- 多租户支持:对于多租户的系统,配置多个数据源可以实现不同租户的数据隔离。每个租户可以拥有自己独立的数据库,从而保证数据的安全性和隐私性。
- 数据库版本升级:在进行数据库版本升级时,可以通过配置多个数据源,将新版本的数据库与旧版本的数据库并行使用。这样可以在升级过程中保证系统的正常运行,减少升级带来的风险。
我们目前常用的三种数据访问方法方式:
- JDBCTemplate
- Spring Data JPA
- MyBatis
接下来我们将围绕这种数据访问方法进行配置:
JDBCTemplate
实际上这种方式,主要还是在application.properties中设置我们需要链接的数据库配置,比如我A数据库用来存储用户信息,B数据库用来存储业务数据。
spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
spring.datasource.primary.username=root
spring.datasource.primary.password=123456
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
spring.datasource.secondary.username=root
spring.datasource.secondary.password=123456
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
ok,我们继续配置完毕后数据源后,我们就通过配置类来完成加载这些配置信息,初始话数据源,以及初始化每个数据源的时候要用的JDBCTemplate。你只需要在你的Spring Boot中应用下面的配置类就可以完成。
@Configuration
public class DataSourceConfiguration {@Primary@Bean@ConfigurationProperties(prefix = "spring.datasource.primary")public DataSource primaryDataSource() {return DataSourceBuilder.create().build();}@Bean@ConfigurationProperties(prefix = "spring.datasource.secondary")public DataSource secondaryDataSource() {return DataSourceBuilder.create().build();}@Beanpublic JdbcTemplate primaryJdbcTemplate(@Qualifier("primaryDataSource") DataSource primaryDataSource) {return new JdbcTemplate(primaryDataSource);}@Beanpublic JdbcTemplate secondaryJdbcTemplate(@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {return new JdbcTemplate(secondaryDataSource);}}
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>
单元测试类:
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {@Autowiredprotected JdbcTemplate primaryJdbcTemplate;@Autowiredprotected JdbcTemplate secondaryJdbcTemplate;@Beforepublic void setUp() {primaryJdbcTemplate.update("DELETE FROM USER ");secondaryJdbcTemplate.update("DELETE FROM USER ");}@Testpublic void test() throws Exception {// 往第一个数据源中插入 2 条数据primaryJdbcTemplate.update("insert into user(name,age) values(?, ?)", "aaa", 20);primaryJdbcTemplate.update("insert into user(name,age) values(?, ?)", "bbb", 30);// 往第二个数据源中插入 1 条数据,若插入的是第一个数据源,则会主键冲突报错secondaryJdbcTemplate.update("insert into user(name,age) values(?, ?)", "ccc", 20);// 查一下第一个数据源中是否有 2 条数据,验证插入是否成功Assert.assertEquals("2", primaryJdbcTemplate.queryForObject("select count(1) from user", String.class));// 查一下第一个数据源中是否有 1 条数据,验证插入是否成功Assert.assertEquals("1", secondaryJdbcTemplate.queryForObject("select count(1) from user", String.class));}
}
有两个JdbcTemplate,为什么不用@Qualifier指定?这里顺带说个小知识点,当我们不指定的时候,会采用参数的名字来查找Bean,存在的话就注入。
这两个JdbcTemplate创建的时候,我们也没指定名字,它们是如何匹配上的?这里也是一个小知识点,当我们创建Bean的时候,默认会使用方法名称来作为Bean的名称,所以这里就对应上了。读者不妨回头看看两个名称是不是一致的。
Spring Data JPA
和上边那种方式基本上类似,所做的操作会有细微的区别。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
配置application.properties文件
# pring boot 1.x的配置:spring.datasource.primary.url=jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1
spring.datasource.primary.username=root
spring.datasource.primary.password=123456
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver# spring boot 1.x的配置:spring.datasource.secondary.url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2
spring.datasource.secondary.username=root
spring.datasource.secondary.password=123456
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver# 日志打印执行的SQL
spring.jpa.show-sql=true
# Hibernate的DDL策略
spring.jpa.hibernate.ddl-auto=create-drop
创建实体类:
@Entity
//@Data
//@NoArgsConstructor
public class User {@Id@GeneratedValueprivate Long id;private String name;private Integer age;public User(String name, Integer age) {this.name = name;this.age = age;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public User() {}
}
public interface UserRepository extends JpaRepository<User, Long> {}
@Entity
//@Data
//@NoArgsConstructor
public class Message {@Id@GeneratedValueprivate Long id;private String title;private String message;public Message(String title, String message) {this.title = title;this.message = message;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public Message() {}
}
public interface MessageRepository extends JpaRepository<Message, Long> {}
多数据源配置类:
@Configuration
public class DataSourceConfiguration {@Primary@Bean@ConfigurationProperties(prefix = "spring.datasource.primary")public DataSource primaryDataSource() {return DataSourceBuilder.create().build();}@Bean@ConfigurationProperties(prefix = "spring.datasource.secondary")public DataSource secondaryDataSource() {return DataSourceBuilder.create().build();}}
主数据源配置类:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef="entityManagerFactoryPrimary",transactionManagerRef="transactionManagerPrimary",basePackages= { "com.miaow.demo.p" }) //设置Repository所在位置
public class PrimaryConfig {@Autowired@Qualifier("primaryDataSource")private DataSource primaryDataSource;@Autowiredprivate JpaProperties jpaProperties;@Autowiredprivate HibernateProperties hibernateProperties;private Map<String, Object> getVendorProperties() {return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());}@Primary@Bean(name = "entityManagerPrimary")public EntityManager entityManager(EntityManagerFactoryBuilder builder) {return entityManagerFactoryPrimary(builder).getObject().createEntityManager();}@Primary@Bean(name = "entityManagerFactoryPrimary")public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) {
// HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
// jpaVendorAdapter.setGenerateDdl(true);return builder.dataSource(primaryDataSource).packages("com.miaow.demo.p") //设置实体类所在位置.persistenceUnit("primaryPersistenceUnit").properties(getVendorProperties()).build();}@Primary@Bean(name = "transactionManagerPrimary")public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());}
}
设置从数据库配置类:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef="entityManagerFactorySecondary",transactionManagerRef="transactionManagerSecondary",basePackages= { "com.miaow.demo.s" }) //设置Repository所在位置
public class SecondaryConfig {@Autowired@Qualifier("secondaryDataSource")private DataSource secondaryDataSource;@Autowiredprivate JpaProperties jpaProperties;@Autowiredprivate HibernateProperties hibernateProperties;private Map<String, Object> getVendorProperties() {return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());}@Bean(name = "entityManagerSecondary")public EntityManager entityManager(EntityManagerFactoryBuilder builder) {return entityManagerFactorySecondary(builder).getObject().createEntityManager();}@Bean(name = "entityManagerFactorySecondary")public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary (EntityManagerFactoryBuilder builder) {return builder.dataSource(secondaryDataSource).packages("com.miaow.demo.s") //设置实体类所在位置.persistenceUnit("secondaryPersistenceUnit").properties(getVendorProperties()).build();}@Bean(name = "transactionManagerSecondary")PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());}}
创建的单元测试:
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {@Autowiredprivate UserRepository userRepository;@Autowiredprivate MessageRepository messageRepository;@Testpublic void test() throws Exception {userRepository.save(new User("aaa", 10));userRepository.save(new User("bbb", 20));userRepository.save(new User("ccc", 30));userRepository.save(new User("ddd", 40));userRepository.save(new User("eee", 50));Assert.assertEquals(5, userRepository.findAll().size());messageRepository.save(new Message("o1", "aaaaaaaaaa"));messageRepository.save(new Message("o2", "bbbbbbbbbb"));messageRepository.save(new Message("o3", "cccccccccc"));Assert.assertEquals(3, messageRepository.findAll().size());}}
MyBatis
在Spring Boot的配置文件application.properties中设置我们需要的两个连接的数据库配置:
# pring boot 1.x的配置:spring.datasource.primary.url=jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1
spring.datasource.primary.username=root
spring.datasource.primary.password=123456
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver# spring boot 1.x的配置:spring.datasource.secondary.url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2
spring.datasource.secondary.username=root
spring.datasource.secondary.password=123456
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver#mybatis.mapper-locations=classpath:mapper/*.xml
创建一个初始化多数据源和MyBatis配置
@Configuration
public class DataSourceConfiguration {@Primary@Bean@ConfigurationProperties(prefix = "spring.datasource.primary")public DataSource primaryDataSource() {return DataSourceBuilder.create().build();}@Bean@ConfigurationProperties(prefix = "spring.datasource.secondary")public DataSource secondaryDataSource() {return DataSourceBuilder.create().build();}}
可以看到内容跟JdbcTemplate
、Spring Data JPA
的时候是一模一样的。通过@ConfigurationProperties
可以知道这两个数据源分别加载了spring.datasource.primary.*
和spring.datasource.secondary.*
的配置。@Primary
注解指定了主数据源,就是当我们不特别指定哪个数据源的时候,就会使用这个Bean真正差异部分在下面的JPA配置上。
分别创建这两个数据源的MyBatis配置文件:
Private 数据源的JPA的配置文件:
@Configuration
@MapperScan(basePackages = "com.miaow.demo.p",sqlSessionFactoryRef = "sqlSessionFactoryPrimary",sqlSessionTemplateRef = "sqlSessionTemplatePrimary")
public class PrimaryConfig {private DataSource primaryDataSource;public PrimaryConfig(@Qualifier("primaryDataSource") DataSource primaryDataSource) {this.primaryDataSource = primaryDataSource;}@Beanpublic SqlSessionFactory sqlSessionFactoryPrimary() throws Exception {SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setDataSource(primaryDataSource);return bean.getObject();}@Beanpublic SqlSessionTemplate sqlSessionTemplatePrimary() throws Exception {return new SqlSessionTemplate(sqlSessionFactoryPrimary());}}
Secondary的数据源JPA配置:
@Configuration
@MapperScan(basePackages = "com.miaow.demo.s",sqlSessionFactoryRef = "sqlSessionFactorySecondary",sqlSessionTemplateRef = "sqlSessionTemplateSecondary")
public class SecondaryConfig {private DataSource secondaryDataSource;public SecondaryConfig(@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {this.secondaryDataSource = secondaryDataSource;}@Beanpublic SqlSessionFactory sqlSessionFactorySecondary() throws Exception {SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setDataSource(secondaryDataSource);return bean.getObject();}@Beanpublic SqlSessionTemplate sqlSessionTemplateSecondary() throws Exception {return new SqlSessionTemplate(sqlSessionFactorySecondary());}}
注意在此说明一下,配置类上使用@MapperScan
注解来指定当前数据源下定义的Entity
和Mapper
的包路径;
另外需要指定sqlSessionFactory
和sqlSessionTemplate
,这两个具体实现在该配置类中类中初始化。
配置类的构造函数中,通过@Qualifier
注解来指定具体要用哪个数据源,其名字对应在DataSourceConfiguration
配置类中的数据源定义的函数名。
配置类中定义SqlSessionFactory
和SqlSessionTemplate
的实现,注意具体使用的数据源正确。
创建一个UserPrimary实体类:
public class UserPrimary {private Long id;private String name;private Integer age;public UserPrimary(String name, Integer age) {this.name = name;this.age = age;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public UserPrimary() {}
}
创建一个UserMapperPrimary用来作为填写SQL语句的接口:
public interface UserMapperPrimary {@Select("SELECT * FROM USER WHERE NAME = #{name}")UserPrimary findByName(@Param("name") String name);@Insert("INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})")int insert(@Param("name") String name, @Param("age") Integer age);@Delete("DELETE FROM USER")int deleteAll();}
创建一个UserSecondary实体类:
public class UserSecondary {private Long id;private String name;private Integer age;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public UserSecondary() {}public UserSecondary(String name, Integer age) {this.name = name;this.age = age;}
}
public interface UserMapperSecondary {@Select("SELECT * FROM USER WHERE NAME = #{name}")UserSecondary findByName(@Param("name") String name);@Insert("INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})")int insert(@Param("name") String name, @Param("age") Integer age);@Delete("DELETE FROM USER")int deleteAll();
}
之后,也是最关键的一步,我们需要在MyBatis的配置文件中使用Mapper.xml
在Resources目录下创建一个mapper文件夹,之后再mapper文件夹下边分别创建primary和secondary文件夹:
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.miaow.demo.p.mapper.UserMapperPrimary"><select id="findByName" resultType="com.miaow.demo.p.entity.UserPrimary">SELECT * FROM USER WHERE NAME = #{name}</select><insert id="insert">INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})</insert></mapper>
与上边这个几乎一样,只是两者指向的接口位置不一样:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.miaow.demo.s.mapper.UserMapperSecondary"><select id="findByName" resultType="com.miaow.demo.s.entity.UserSecondary">SELECT * FROM USER WHERE NAME = #{name}</select><insert id="insert">INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})</insert></mapper>
最后我们可以通过一个测试类进行测试:
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class ApplicationTests {//第一数据库配置类@Autowiredprivate UserMapperPrimary userMapperPrimary;//第二数据库配置文件@Autowiredprivate UserMapperSecondary userMapperSecondary;@Beforepublic void setUp() {// 清空测试表,保证每次结果一样userMapperPrimary.deleteAll();userMapperSecondary.deleteAll();}@Testpublic void test() throws Exception {// 往Primary数据源插入一条数据userMapperPrimary.insert("AAA", 20);// 从Primary数据源查询刚才插入的数据,配置正确就可以查询到UserPrimary userPrimary = userMapperPrimary.findByName("AAA");Assert.assertEquals(20, userPrimary.getAge().intValue());// 从Secondary数据源查询刚才插入的数据,配置正确应该是查询不到的UserSecondary userSecondary = userMapperSecondary.findByName("AAA");Assert.assertNull(userSecondary);// 往Secondary数据源插入一条数据userMapperSecondary.insert("BBB", 20);// 从Primary数据源查询刚才插入的数据,配置正确应该是查询不到的userPrimary = userMapperPrimary.findByName("BBB");Assert.assertNull(userPrimary);// 从Secondary数据源查询刚才插入的数据,配置正确就可以查询到userSecondary = userMapperSecondary.findByName("BBB");Assert.assertEquals(20, userSecondary.getAge().intValue());}}
相关文章:

Spring Boot中配置多个数据源
配置数据源实际上就是配置多个数据库,在一个配置文件中配置多个数据库,这样做主要的好处有以下几点: 数据库隔离:通过配置多个数据源,可以将不同的业务数据存储在不同的数据库中,实现数据的隔离。这样可以…...
C++学习笔记---命名空间namespace
文章目录 前言简介定义命名空间using指令不连续&嵌套的命名空间 前言 wu 简介 C中的命名空间(Namespace)是一种用于组织和封装代码的机制,它允许你将一组相关的函数、类、变量和其他标识符放置在一个逻辑分组内,以便在不同的…...

缓存-Spring Cache 缓存抽象
缓存-Spring Cache 缓存抽象 Spring从版本3.1开始提供非侵入的将Cache集成到Spring应用的方式。Spring Cache提供Cache的统一抽象,支持集成各种不同的缓存解决方案。从4.1版本开始,提供了注解和更多的定制参数。 Spring Cache 抽象提供了对Java方法的缓存…...

Java修仙传之神奇的ES2(巧妙的查询及结果处理篇)
SDL语句查询 查询的基本语法 GET /indexName/_search {"query": {"查询类型": {"查询条件": "条件值"}} } 根据文档id查询 #查询文档 GET hotel/_doc/36934 查询所有 会弹出该索引库下所有文档// 查询所有 GET /indexName/_searc…...
架构设计的课程资料
架构设计课 枫叶云笔记...

数据结构与算法C语言版学习笔记(5)-串,匹配算法、KMP算法
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、串的定义二、串的存储结构1.顺序结构2.链式结构 三、串的朴素的模式匹配算法(暴力匹配算法)1.背景2.假设我们要从下面的主串 S"…...

新版HI3559AV100开发注意事项
新版HI3559AV100开发注意事项 一、在Hi3559A上使用openCV VideoCapture开启.mp4影像档, isOpened一直得到false 在Hi3559A上已经cross compile ffmepg 4.1openCV 3.4.4 但使用openCV VideoCapture开启.mp4影像档, isOpened一直得到false 请问要如何知道是什么原因无法开启影像…...

Django(一、简介,安装与使用)
文章目录 一、Django引入1.web应用程序什么是web?web引用程序的优点web应用程序的缺点什么是web框架 2.纯手写web框架1.web框架的本质2.HTTP协议的特性:3.编写基于wsgire模块搭建web框架代码封装优化代码封装 二、Django框架的学习1.Python中的主流框架2…...

【Linux C IO多路复用】多用户聊天系统
目录 Server-Client mutiplexingServer mutiplexingClient mutiplexing Server-Client 在Linux系统中,IO多路复用是一种机制,它允许一个进程能够监视多个文件描述符(sockets、pipes等)的可读、可写和异常等事件。这样…...

JSON——数组语法
一段JSON可能是以 ”{“ 开头 也可能仅包含一段JSON数组 如下 [ { "name" : "hello,world"}, {"name" : "SB JSON”}, {“name” : "SB互联网房地产CNM“}, ] 瞧,蛋疼不...CJSON过来还是得搜下网…...

运营商大数据精准获客:我们提供精准客源渠道的最大资源体?
运营商大数据精准营销 谈起精准获客,竞争对手永远是为我们提供精准客源渠道的最大资源体! 最新的获客方式,就是从竞争对手的手中把他们的精准客户资源变为自己的。 今年最火的运营商大数据精准营销是拒绝传统营销方式的烧钱推广࿰…...
表象变换与矩阵元
表象变换 一维粒子哈密顿量 表象中的矩阵元 态的表象变换 不难证明 算符的表象变换 坐标表象 Non-denumerable basis...
vue乾坤微前端项目
1、主应用 安装乾坤 npm i qiankun -S 注册微应用并启动: import { registerMicroApps, start } from qiankun;//设置两个微应用 registerMicroApps([{name: vue1, //要跟package.json中的name保持一致entry: //localhost:8081, //本地就这么写container: #cont…...

大语言模型比武
今年随着 ChatGPT 的流行,并在各个领域有一定程度生产级别的应用。国内外也掀起了一股大语言模型浪潮,各大厂商都推出了自己的大语言模型,阿里推出了 通义千问,腾讯推出了 Hunyuan,亚马逊云推出了 Titan,大…...
王道数据结构第五章二叉树的遍历第13题
目录 解题思路 宏定义 二叉树定义 栈定义 实现函数 测试代码 测试结果...
微服务的发展历程的详细说明及每个阶段主流的架构和组件
微服务的发展历程的详细说明及每个阶段主流的架构和组件如下: 一、微服务的发展历程: 起始阶段:这个阶段主要是面向服务的架构(SOA)的兴起。此时,企业开始尝试将单体应用拆分为多个服务,但此时…...

2023年眼镜行业分析(京东眼镜销量数据分析):市场规模同比增长26%,消费需求持续释放
随着我国经济的不断发展,电子产品不断普及,低龄及老龄人口的用眼场景不断增多,不同年龄阶段的人群有不同的视力问题,因此,视力问题人口基数也随之不断加大,由此佩戴眼镜的人群也不断增多。 同时,…...
基础课26——业务流程分析方法论
基础课25中我们提到业务流程分析方法包括以下几种: 价值链分析法:主要是找出或设计出哪些业务能够使得客户满意,实现客户价值最大化的业务流程。要进行价值链分析的时候可以从企业具体的活动进行细分,细分的具体方面可以从生产指…...

【数字图像处理-TUST】实验二-图像噪声生成与滤波降噪
一,题目 读入一幅图像使用两种以上的方法向图像中分别添加噪声输出一幅二值图像,背景为黑色,噪声区域为白色使用三种滤波方法对上述添加了噪声的图像进行降噪处理输出降噪处理后的结果图像 二,实验原理 采用了两种方法添加了噪…...

bilibili快速升满级(使用Docker 容器脚本)
部署bilibili升级运行容器脚本 docker run --name"bili" -v /bili/Logs:/app/Logs -e Ray_DailyTaskConfig__Cron"30 9 * * *" -e Ray_LiveLotteryTaskConfig__Cron"40 9 * * *" -e Ray_UnfollowBatchedTaskConfig__Cron"…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...

基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...