MyBatis多数据源以及动态切换实现(基于SpringBoot 2.7.x)

news2024/11/15 15:49:20

MyBatis多数据源以及动态切换实现可以实现不同功能模块可以对应到不同的数据库,现在就让我们来讲解一下。

目录

  • 一、引入Maven
  • 二、配置文件
  • 三、实现多数据源
  • 四、动态切换数据源

一、引入Maven

注意:博主这边使用的springboot版本是2.7.14的

<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.75</version>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.6</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

<!-- MyBatis依赖 -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.0</version>
</dependency>

<!-- 数据库连接池依赖(这里以HikariCP为例) -->
<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
</dependency>

<!-- MySQL驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.12</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.microsoft.sqlserver/mssql-jdbc -->
<!-- SQL Server驱动 -->
<dependency>
    <groupId>com.microsoft.sqlserver</groupId>
    <artifactId>mssql-jdbc</artifactId>
    <version>8.2.0.jre8</version>
</dependency>

<!-- Spring Boot AOP依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

二、配置文件

以application.properties讲解

server.port=8099

# MySQL1
spring.datasource.mysqldb1.url=jdbc:mysql://localhost:3306/mysql?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.mysqldb1.username=root
spring.datasource.mysqldb1.password=123456
# MySQL2
spring.datasource.mysqldb2.url=jdbc:mysql://localhost:3306/ke_prd?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.mysqldb2.username=root
spring.datasource.mysqldb2.password=123456
# sqlserver
spring.datasource.sqlserver.url=jdbc:sqlserver://localhost:1433;database=TEST
spring.datasource.sqlserver.username=sa
spring.datasource.sqlserver.password=123

#mybatis
#pojo对应路径
mybatis.type-aliases-package=com.zhangximing.springbootmybatis_datasource.pojo
# 默认扫描xml
mybatis.mapper-locations=classpath:mybatis/mapper/**/*.xml
# sqlserver数据库对应扫描xml
custom.mapper.xml.sqlserver=classpath:mybatis/mapper/sqlserver/*.xml
# mysql数据库对应扫描xml
custom.mapper.xml.mysql=classpath:mybatis/mapper/mysql/*.xml
# 动态切换数据库对应扫描xml
custom.mapper.xml.dynamic=classpath:mybatis/mapper/dynamic/*.xml

# 编码utf-8
server.servlet.encoding.charset=UTF-8
server.servlet.encoding.enabled=true
server.servlet.encoding.force=true

三、实现多数据源

先实现普通的mybatis写法,写三个(两个mysql,一个sqlserver)(冗余的代码不贴出)

接口入口写法都一样,就是名称换了而已,LogMapperMySql 换 LogMapperMySqlT和LogMapperSqlServer

import com.zhangximing.springbootmybatis_datasource.pojo.LogInfo;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * @Author: zhangximing
 * @Email: 530659058@qq.com
 * @Date: 2023/6/14 13:54
 * @Description: 日志操作
 */
/*加了这个注解 就表示了 这是一个Mybatis的mapper类
就相当于之前使用的spring整合mybatis接口 也可以使用@MapperScan("com.kuang.mapper")*/
@Mapper
/**@Component 也可以用这个 万能的*/
@Repository
public interface LogMapperMySql {

    List<LogInfo> queryLogList();

    LogInfo queryLogById(int id);

    int addLog(LogInfo logInfo);

    int updateLog(LogInfo logInfo);

    int deleteLog(LogInfo logInfo);
}

xml文件方面,除了namespace需要修改外,当是sqlserver时NOW()函数要改为GETDATE()

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhangximing.springbootmybatis_datasource.mapper.mysql.LogMapperMySql">
    <select id="queryLogList" resultType="LogInfo">
        select * from log_center
    </select>

    <select id="queryLogById" resultType="LogInfo">
        select * from log_center
        where id=#{id};
    </select>

    <insert id="addLog" parameterType="LogInfo">
        insert into log_center(method,requestJson,responseJson,createDate)
        values(#{method},#{requestJson},#{responseJson},NOW());

    </insert>

    <update id="updateLog" parameterType="LogInfo">
        update mybatis.user
        set responseJson=#{responseJson},requestJson=#{requestJson}
        where id=#{id};
    </update>

    <delete id="deleteLog" parameterType="int">
        delete
        from log_center
        where id=#{id};
    </delete>

</mapper>

pojo实体 LogInfo

//import io.swagger.annotations.ApiModel;
//import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;

/**
 * @Author: zhangximing
 * @Email: 530659058@qq.com
 * @Date: 2023/5/31 13:07
 * @Description: 日志实体类
 */
@Data
//@ApiModel(value = "日志类")
public class LogInfo implements Serializable {

//    @ApiModelProperty(value = "",required = false)
    private String id;

//    @ApiModelProperty(value = "方法名",required = false)
    private String method;

//    @ApiModelProperty(value = "请求参数",required = false)
    private String requestJson;

//    @ApiModelProperty(value = "返回参数",required = false)
    private String responseJson;

//    @ApiModelProperty(value = "创建日期",required = false)
    private String createDate;
}

开始重点部分啦,如何实现多数据源啦
先写多数据源配置类

package com.zhangximing.springbootmybatis_datasource.config.datasource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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 org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

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

/**
 * 多数据源配置类
 */
@Configuration
public class DataSourceConfig {

    @Autowired
    private Environment env;

    // 多数据源一:默认mysql
    // Primary注解是在没有指明使用哪个数据源的时候指定默认使用的主数据源
    // Primary在无动态切换的情况下可以用
    @Primary
    @Bean(name = "mysqlDataSource")
    //注意:该注解可能失效导致无法直接注入,所以手动获取装配
//    @ConfigurationProperties(prefix = "spring.datasource.mysqldb1")
    public DataSource mysqlDataSource() {
        DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
        dataSourceBuilder.url(env.getProperty("spring.datasource.mysqldb1.url"));
        dataSourceBuilder.username(env.getProperty("spring.datasource.mysqldb1.username"));
        dataSourceBuilder.password(env.getProperty("spring.datasource.mysqldb1.password"));
        return dataSourceBuilder.build();
//        return DataSourceBuilder.create().build();
    }

    // 多数据源二:mysql库2
    @Bean(name = "mysqlDataSourceT")
//    @ConfigurationProperties(prefix = "spring.datasource.mysqldb2")
    public DataSource mysqlDataSourceT() {
        DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
        dataSourceBuilder.url(env.getProperty("spring.datasource.mysqldb2.url"));
        dataSourceBuilder.username(env.getProperty("spring.datasource.mysqldb2.username"));
        dataSourceBuilder.password(env.getProperty("spring.datasource.mysqldb2.password"));
        return dataSourceBuilder.build();
    }

    // 多数据源三:sqlserver
    @Bean(name = "sqlserverDataSource")
//    @ConfigurationProperties(prefix = "spring.datasource.sqlserver")
    public DataSource sqlserverDataSource() {
        DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
        dataSourceBuilder.url(env.getProperty("spring.datasource.sqlserver.url"));
        dataSourceBuilder.username(env.getProperty("spring.datasource.sqlserver.username"));
        dataSourceBuilder.password(env.getProperty("spring.datasource.sqlserver.password"));
        return dataSourceBuilder.build();
    }

针对数据源配置(mysql)

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.annotation.Resource;
import javax.sql.DataSource;

@Configuration
@MapperScan(
		// 指定该数据源扫描指定包下面的Mapper接口文件
        basePackages = "com.zhangximing.springbootmybatis_datasource.mapper.mysql",
        sqlSessionFactoryRef = "sqlSessionFactoryPrimary",
        sqlSessionTemplateRef = "sqlSessionTemplatePrimary")
public class DataSourceMySqlConfig {

    // mapper扫描xml文件的路径
    @Value("${custom.mapper.xml.mysql}")
    private String MAPPER_LOCATION;
	
    private DataSource primaryDataSource;

    // 通过构造方法进行注入
    public DataSourceMySqlConfig(@Qualifier("mysqlDataSource") DataSource primaryDataSource) {
        this.primaryDataSource = primaryDataSource;
    }

    /**
     * SqlSession工厂方法
     * 用于创建SqlSession对象。
     * 用于管理SqlSession对象的的生命周期。
     * 可以根据需要创建不同的SqlSession子类,以支持不同的数据库操作需求。
     * 可以将SqlSession对象存储在持久化缓存中,以提高性能。
     * @return
     * @throws Exception
     */
    @Bean
    @Primary
    public SqlSessionFactory sqlSessionFactoryPrimary() throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(primaryDataSource);
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCATION));
        sqlSessionFactoryBean.setTypeAliasesPackage("com.zhangximing.springbootmybatis_datasource.pojo");
        return sqlSessionFactoryBean.getObject();
    }

    @Bean
    @Primary
    public SqlSessionTemplate sqlSessionTemplatePrimary() throws Exception {
        return new SqlSessionTemplate(sqlSessionFactoryPrimary());
    }
}

针对数据源配置(mysql库2)(sqlserver的参考这个写即可,扫描路径以及配置文件获取修改)

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

/**
 * sqlserver数据源配置
 */
@Configuration
@MapperScan(
        basePackages = "com.zhangximing.springbootmybatis_datasource.mapper.mysql",
        sqlSessionFactoryRef = "sqlSessionFactorySecondaryMySql")
public class DataSourceMySqlTConfig {

    // mapper扫描xml文件的路径
    @Value("${custom.mapper.xml.mysql}")
    private String MAPPER_LOCATION;

    private DataSource secondaryDataSource;

	// 通过构造方法进行注入
    public DataSourceMySqlTConfig(@Qualifier("mysqlDataSourceT") DataSource secondaryDataSource) {
        this.secondaryDataSource = secondaryDataSource;
    }

    @Bean("sqlSessionFactorySecondaryMySql")
    public SqlSessionFactory sqlSessionFactorySecondary() throws Exception {

        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();

        // 指定数据源
        sqlSessionFactoryBean.setDataSource(secondaryDataSource);
        /*
			获取xml文件资源对象
			当Mapper接口所对应的.xml文件与Mapper接口文件分离,存储在 resources
			文件夹下的时候,需要手动指定.xml文件所在的路径
		*/
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCATION));
        //指定实体目录
        sqlSessionFactoryBean.setTypeAliasesPackage("com.zhangximing.springbootmybatis_datasource.pojo");
        return sqlSessionFactoryBean.getObject();
    }

    @Bean("SecondaryDataSourceManagerMySql")
    public DataSourceTransactionManager SecondaryDataSourceManager() {
        return new DataSourceTransactionManager(secondaryDataSource);
    }
}

到这里基本上就可以了,写测试类测试

import com.alibaba.fastjson.JSONObject;
//import io.swagger.annotations.Api;
//import io.swagger.annotations.ApiOperation;
import com.zhangximing.springbootmybatis_datasource.annotation.DataBase;
import com.zhangximing.springbootmybatis_datasource.mapper.mysql.LogMapperMySql;
import com.zhangximing.springbootmybatis_datasource.mapper.mysql.LogMapperMySqlT;
import com.zhangximing.springbootmybatis_datasource.mapper.sqlserver.LogMapperSqlServer;
import com.zhangximing.springbootmybatis_datasource.pojo.LogInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * @Author: zhangximing
 * @Email: 530659058@qq.com
 * @Date: 2023/5/31 13:00
 * @Description: 测试接口
 */
//@Api(value="日志模块",tags = "日志模块管理")
@RestController
@RequestMapping("/log")
public class LogController {

    @Autowired
    private LogMapperMySql logMapper_mysql;

    @Autowired
    private LogMapperMySqlT logMapper_mysqlT;

    @Autowired
    private LogMapperSqlServer logMapper_sqlserver;

//    @ApiOperation(value="插入日志")
    @PostMapping(value = "/addLog", produces = {"text/plain;charset=UTF-8"})
    public String addLog(@RequestBody LogInfo logInfo){

        int cnt = logMapper_sqlserver.addLog(logInfo);

        JSONObject result = new JSONObject();
        result.put("count",cnt);

        return result.toJSONString();
    }

    @RequestMapping("/getLogById/{id}")
    public String getLogById(@PathVariable("id") int logId){

        System.out.println("logId:"+logId);
        LogInfo logInfo = logMapper_sqlserver.queryLogById(logId);

        JSONObject result = new JSONObject();
        result.put("data",JSONObject.toJSONString(logInfo));

        return result.toJSONString();
    }
}

测试结果就不展示了,就手动修改需要调用的数据源进行请求测试

四、动态切换数据源

在第三点的基础上,我们在 多数据源配置类 增加 如下代码

/**
 *  动态数据源配置
 */
@Primary
@Bean(name = "dynamicDataSource")
public DataSource dynamicDataSource(){
    DynamicDataSource dynamicDataSource = new DynamicDataSource();
    //默认数据源
    dynamicDataSource.setDefaultTargetDataSource(mysqlDataSource());

    //配置多数据源
    Map<Object, Object> dsMap = new HashMap<Object, Object>(5);
    dsMap.put("mysqldb1", mysqlDataSource());
    dsMap.put("mysqldb2", mysqlDataSourceT());
    dsMap.put("sqlserver", sqlserverDataSource());
    dynamicDataSource.setTargetDataSources(dsMap);
    return dynamicDataSource;
}

/**
 * 配置@Transactional注解事物(管理事务)
 *  @return
 */
@Bean
public PlatformTransactionManager transactionManager(){
    return new DataSourceTransactionManager(dynamicDataSource());
}

DynamicDataSource(动态数据源配置类)

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * 动态数据源配置
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    // 确定当前的数据源键
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDB();
    }
}

DataSourceContextHolder(切换数据库类)

import lombok.extern.slf4j.Slf4j;

/**
 * 上下文切换(切换数据库)
 */
@Slf4j
public class DataSourceContextHolder {
    // 默认数据源
    public static final String DEFAULT_DS = "mysqldb1";

    // 本地线程共享变量
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    public static void setDB(String dbType) {
        log.info("切换至" + dbType + "数据源");
        contextHolder.set(dbType);
    }

    public static String getDB() {
        return (contextHolder.get());
    }

    public static void clearDB() {
        contextHolder.remove();
    }
}

增加与mysql配置mybatis一致的xml和接口(由于我们只用一个表测试,所以就以同类型数据库切换进行演示),此处省略代码…

自定义注解(这边打算用注解标记哪些接口需要进行切换数据库的)

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义注解:参数为数据库标识
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DataBase {
    String value() default "mysqldb1";
}

切面部分,这里测试是以请求头传数据库标识来动态实现,也可以通过数据库或配置文件存储多种方式

import com.zhangximing.springbootmybatis_datasource.annotation.DataBase;
import com.zhangximing.springbootmybatis_datasource.config.datasource.DataSourceContextHolder;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 *  切面拦截切换数据库
 */
@Aspect
@Component
public class DataBaseAspect {

    // 拦截用过注释的
    @Pointcut("@annotation(com.zhangximing.springbootmybatis_datasource.annotation.DataBase)")
    public void dbPointCut(){

    }

    // 拦截切换数据源
    @Before("dbPointCut()")
    public void beforeSwitchDS(JoinPoint point){
        //获得当前访问的class
        Class<?> className = point.getTarget().getClass();
            //获得访问的方法名
            String methodName = point.getSignature().getName();
            //得到方法的参数的类型
            Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes();

            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            //获取请求头数据库(模拟动态切换数据库)
            String myDataSource = request.getHeader("dataSource");

            // 获取默认数据源
            String dataSource = DataSourceContextHolder.DEFAULT_DS;
            try {
                // 得到访问的方法对象
                Method method = className.getMethod(methodName, argClass);

                // 判断是否存在@DateBase注解
                if (method.isAnnotationPresent(DataBase.class)) {
                    DataBase annotation = method.getAnnotation(DataBase.class);
                    // 取出注解中的数据源名
                    dataSource = annotation.value();
                }

                if (null != myDataSource && myDataSource.length() > 0){
                    dataSource = myDataSource;
                }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 切换数据源
        DataSourceContextHolder.setDB(dataSource);
    }

    // 结束后清除线程共享变量
    @After("dbPointCut()")
    public void afterSwitchDS(JoinPoint point){
        DataSourceContextHolder.clearDB();
    }
}

测试类增加如下代码

//置空根据请求头dataSource动态切库
 @DataBase()
 @PostMapping(value = "/addLogDy", produces = {"text/plain;charset=UTF-8"})
 public String addLogDy(@RequestBody LogInfo logInfo){

     int cnt = logMapperDynamic.addLog(logInfo);

     JSONObject result = new JSONObject();
     result.put("count",cnt);

     return result.toJSONString();
 }

 //可注解指定数据库
 @DataBase("mysqldb2")
 @RequestMapping("/getLogByIdDy/{id}")
 public String getLogByIdDy(@PathVariable("id") int logId){

     System.out.println("logId:"+logId);
     LogInfo logInfo = logMapperDynamic.queryLogById(logId);

     JSONObject result = new JSONObject();
     result.put("data",JSONObject.toJSONString(logInfo));

     return result.toJSONString();
 }
--附上表结构创建(mysql)
CREATE TABLE IF NOT EXISTS `log_center`(
   `id` INT UNSIGNED AUTO_INCREMENT,
   `method` VARCHAR(200),
   `requestJson` TEXT,
	 `responseJson` TEXT,
   `createDate` DATE,
   PRIMARY KEY ( `id` )
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

整体代码结构
在这里插入图片描述

功能测试正常,大家可以自行试下,代码完整包已放到博主资源(SpringBoot-MyBatis-DataSource(多数据源以及动态切换))。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1436770.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

用 Delphi 程序调用 Python 代码画曲线图

用 Python 的库画图 Python 代码如下&#xff1a; import matplotlib.pyplot as pltsquares [1, 4, 9, 16, 25]; plt.plot(squares); plt.grid(True) # 网格线 plt.show(); # 这句话会弹出个窗口出来&#xff0c;里面是上述数据的曲线。 把以上代码&#xff0c;放进 PyS…

Node.js(五)-跨域(了解)

一 、CORS相关 1. 接口的跨域问题 html: server: 访问结果&#xff1a; 刚才编写的 GET 和 POST接口&#xff0c;存在一个很严重的问题&#xff1a;不支持跨域请求。 解决接口跨域问题的方案主要有两种&#xff1a; ① CORS&#xff08;主流的解决方案&#xff0c;推荐使…

基础面试题整理7之Redis

1.redis持久化RDB、AOF RDB(Redis database) 在当前redis目录下生成一个dump.rdb文件&#xff0c;对redis数据进行备份 常用save、bgsave命令进行数据备份&#xff1a; save命令会阻塞其他redis命令&#xff0c;不会消耗额外的内存&#xff0c;与IO线程同步&#xff1b;bgsav…

gem5学习(17):ARM功耗建模——ARM Power Modelling

目录 一、Dynamic Power States 二、Power Usage Types 三、MathExprPowerModels 四、Extending an existing simulation 五、Stat dump frequency 六、Common Problems 官网教程&#xff1a;gem5: ARM Power Modelling 通过使用gem5中已记录的各种统计数据&#xff0c;…

掌握Web服务器之王:Nginx 学习网站全攻略!

介绍&#xff1a;Nginx是一款高性能的Web服务器&#xff0c;同时也是一个反向代理、负载均衡和HTTP缓存服务器。具体介绍如下&#xff1a; 轻量级设计&#xff1a;Nginx的设计理念是轻量级&#xff0c;这意味着它在占用最少的系统资源的同时提供高效的服务。 高并发能力&#x…

ROS笔记二:launch

目录 launch node标签 参数 参数服务器 节点分组 launch launch文件是一种可以可实现多节点启动和参数配置的xml文件,launch文件用于启动和配置ROS节点、参数和其他相关组件。launch文件通常使用XML格式编写&#xff0c;其主要目的是方便地启动ROS节点和设置节点之间的连…

【Unity优化(一)】音频优化

整理资教程&#xff1a;https://learn.u3d.cn/tutorial/unity-optimization-metaverse 1.音频优化 音频一般不会成为性能瓶颈&#xff0c;是为了节省内存和优化包体大小。 1.0 文件格式和压缩格式 原始音频资源尽量采用WAV格式。 移动平台音频尽量采用Vorbis压缩格式&#x…

PyTorch 2.2 中文官方教程(十八)

开始使用完全分片数据并行&#xff08;FSDP&#xff09; 原文&#xff1a;pytorch.org/tutorials/intermediate/FSDP_tutorial.html 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 作者&#xff1a;Hamid Shojanazeri&#xff0c;Yanli Zhao&#xff0c;Shen Li 注意…

微信小程序学习指南:从基础知识到代码展示

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

Windows系统安装Flink及实现MySQL之间数据同步

Apache Flink是一个框架和分布式处理引擎&#xff0c;用于对无界和有界数据流进行有状态计算。Flink的设计目标是在所有常见的集群环境中运行&#xff0c;并以内存执行速度和任意规模来执行计算。它支持高吞吐、低延迟、高性能的流处理&#xff0c;并且是一个面向流处理和批处理…

【Leetcode】292. Nim 游戏

文章目录 题目思路代码结果 题目 题目链接 你和你的朋友&#xff0c;两个人一起玩 Nim 游戏&#xff1a; 桌子上有一堆石头。你们轮流进行自己的回合&#xff0c; 你作为先手 。每一回合&#xff0c;轮到的人拿掉 1 - 3 块石头。拿掉最后一块石头的人就是获胜者。 假设你们每…

C++ 动态规划 状态压缩DP 最短Hamilton路径

给定一张 n 个点的带权无向图&#xff0c;点从 0∼n−1 标号&#xff0c;求起点 0 到终点 n−1 的最短 Hamilton 路径。 Hamilton 路径的定义是从 0 到 n−1 不重不漏地经过每个点恰好一次。 输入格式 第一行输入整数 n 。 接下来 n 行每行 n 个整数&#xff0c;其中第 i 行…

【MySQL】学习如何使用DCL进行用户管理

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-JwFD16F1Kh0fle0X {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

百面嵌入式专栏(面试题)进程管理相关面试题1.0

沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇我们将介绍进程管理相关面试题 。 一、进程管理相关面试题 进程是什么?操作系统如何描述和抽象一个进程?进程是否有生命周期?如何标识一个进程?进程与进程之间的关系如何?Linux操作系统的进程0是什么?Linux操…

OJ_浮点数加法(高精度运算)

题干 C实现 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<map> #include<string> using namespace std;string GetInteger(string a) {return a.substr(0, a.find(.)); }string GetFraction(string a) {return a.substr(a.find(.) 1 ,a.siz…

记一次VulnStack渗透

信息收集 netdiscover的主机发现部分不再详解&#xff0c;通过访问端口得知20001-2003端口都为web端口&#xff0c;所以优先考虑从此方向下手 外网渗透 GetShell Struct漏洞 访问2001端口后&#xff0c;插件Wappalyzer爬取得知这是一个基于Struct的web站点&#xff0c;直接…

浅谈bypass Etw

文章目录 c#ExecuteAssemblybypass etw c# loader 一种是通过反射找到指定空间的类中method进行Invoke 另一种是通过EntryPoint.Invoke加载 反射加载 Assembly.Load()是从String或AssemblyName类型加载程序集&#xff0c;可以读取字符串形式的程序集 Assembly.LoadFrom()从指定…

记录下Flybirds移动端ui自动化框架的搭建

一、参考文档 1.官方文档&#xff1a;携程机票跨端跨框架 BDD UI 自动化测试方案Flybirds — flybirds v0.1.5 文档 2.Flybirds运行环境&#xff1a;Flybirds运行环境 - 简书 3.Windows系统连接IOS安装tidevice&#xff1a;iOS自动化之tidevice-CSDN博客 二、Windows系统演…

Nacos注册中心和服务发现

Nacos注册中心 01 认识和安装Nacos Nacos比Eureka功能更为丰富&#xff0c;是SpringCloud中的一个组件&#xff0c;Nacos是阿里巴巴的产品&#xff0c;在国内更流行。 NACOS功能&#xff1a;服务发现&#xff08;对标Eureka)、配置管理、服务管理 下载见&#xff1a;D:\zwx\…

【EI会议征稿通知】第三届智能控制与应用技术国际学术会议(AICAT 2024)

第三届智能控制与应用技术国际学术会议&#xff08;AICAT 2024&#xff09; 2024 3rd International Symposium on Artificial Intelligence Control and Application Technology 2024年第三届智能控制与应用技术国际学术会议&#xff08;AICAT 2024&#xff09;定于2024年5月…