MyBatis-Plus深度全解:從入門到企業級實戰

MyBatis-Plus深度全解:從入門到企業級實戰

一、為什么選擇MyBatis-Plus?

1.1 MyBatis的痛點

- 重復CRUD代碼編寫
- 分頁功能實現復雜
- 缺少通用Service層封裝
- 動態表名支持困難
- 多租戶方案需自行實現

1.2 MyBatis-Plus核心優勢

+ 無侵入:只做增強不做改變
+ 強大的CRUD操作:內置通用Mapper/Service
+ 支持Lambda形式調用
+ 主鍵自動生成策略
+ 全局攔截器(分頁/租戶/性能分析)

1.3 技術棧對比

特性MyBatisMyBatis-PlusJPA
CRUD簡化手動自動生成自動
分頁插件需集成內置內置
代碼生成器強大中等
多租戶支持手動注解配置需擴展
學習曲線中等平滑陡峭

二、SpringBoot 3.x整合實戰

2.1 環境準備

技術棧版本說明
SpringBoot3.1.0基礎框架
Java17LTS版本
MySQL8.0數據庫
MyBatis-Plus3.5.3.1ORM框架

2.2 依賴引入

<dependencies><!-- SpringBoot基礎 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- MyBatis-Plus核心 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</version></dependency><!-- 數據庫驅動 --><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><!-- Lombok簡化開發 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>
</dependencies>

2.3 配置文件

spring:datasource:url: jdbc:mysql://localhost:3306/mp_demo?useSSL=false&serverTimezone=Asia/Shanghaiusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driver# MyBatis-Plus配置
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 開啟SQL日志map-underscore-to-camel-case: true # 下劃線轉駝峰global-config:db-config:id-type: assign_id # 雪花算法ID生成logic-delete-field: deleted # 邏輯刪除字段logic-delete-value: 1 # 已刪除值logic-not-delete-value: 0 # 未刪除值

2.4 實體類與Mapper

@Data
@TableName("sys_user") // 表名映射
public class User {@TableId(type = IdType.ASSIGN_ID) // 雪花算法IDprivate Long id;@TableField("username") // 字段映射private String name;private Integer age;private String email;@TableField(fill = FieldFill.INSERT) // 自動填充private LocalDateTime createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime updateTime;
}// Mapper接口
@Mapper
public interface UserMapper extends BaseMapper<User> {// 自定義方法@Select("SELECT * FROM sys_user WHERE age > #{age}")List<User> selectUsersByAge(@Param("age") Integer age);
}

三、核心功能深度解析

3.1 CRUD接口詳解

3.1.1 Mapper層CRUD
// 插入
User user = new User();
user.setName("John");
user.setAge(30);
userMapper.insert(user); // 批量插入
List<User> users = Arrays.asList(new User(...), new User(...));
userMapper.insertBatchSomeColumn(users); // 批處理優化// 更新
User updateUser = new User();
updateUser.setId(1L);
updateUser.setEmail("new@example.com");
userMapper.updateById(updateUser);// 條件更新
UpdateWrapper<User> wrapper = new UpdateWrapper<>();
wrapper.set("email", "admin@example.com").eq("name", "admin");
userMapper.update(null, wrapper);// 刪除
userMapper.deleteById(1L); // ID刪除
userMapper.delete(new QueryWrapper<User>().eq("age", 18)); // 條件刪除
3.1.2 Service層CRUD
public interface UserService extends IService<User> {// 自定義業務方法List<User> findAdmins();
}@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {@Overridepublic List<User> findAdmins() {LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();wrapper.eq(User::getRole, "admin");return baseMapper.selectList(wrapper);}
}// 使用示例
userService.save(user); // 保存
userService.updateById(user); // 更新
userService.removeByIds(Arrays.asList(1L,2L)); // 批量刪除

3.2 條件構造器(Wrapper)

3.2.1 QueryWrapper
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.select("id", "name", "age") // 指定字段.like("name", "張")          // 模糊查詢.between("age", 20, 30)     // 范圍查詢.isNotNull("email")          // 非空判斷.orderByDesc("create_time"); // 排序
List<User> users = userMapper.selectList(wrapper);
3.2.2 LambdaQueryWrapper(推薦)
LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.select(User::getId, User::getName, User::getAge).like(User::getName, "張").ge(User::getAge, 18).orderByDesc(User::getCreateTime);
List<User> users = userMapper.selectList(lambdaWrapper);
3.2.3 復雜條件示例
LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();
wrapper.and(wq -> wq.gt(User::getAge, 18).or().isNull(User::getEmail)).nested(nq -> nq.eq(User::getRole, "admin").lt(User::getCreateTime, LocalDateTime.now())).apply("date_format(create_time,'%Y-%m-%d') = {0}", "2023-07-01");

3.3 分頁插件(企業級優化)

@Configuration
public class MybatisPlusConfig {/*** 分頁插件 + 性能分析插件*/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 分頁插件(MySQL方言)PaginationInnerInterceptor paginationInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);paginationInterceptor.setMaxLimit(1000L); // 單頁最大1000條paginationInterceptor.setOverflow(true);   // 超過總頁數返回第一頁interceptor.addInnerInterceptor(paginationInterceptor);// 性能分析插件(僅開發環境)if (log.isDebugEnabled()) {PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();performanceInterceptor.setFormat(true);performanceInterceptor.setMaxTime(2000); // SQL執行超過2秒記錄警告interceptor.addInnerInterceptor(performanceInterceptor);}return interceptor;}
}// 使用示例
Page<User> page = new Page<>(1, 10); // 第1頁,每頁10條
LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();
wrapper.eq(User::getRole, "admin");
Page<User> result = userMapper.selectPage(page, wrapper);// 結果處理
List<User> records = result.getRecords();
long total = result.getTotal();

四、高級特性實戰

4.1 邏輯刪除

# 全局配置
mybatis-plus:global-config:db-config:logic-delete-field: deleted  # 邏輯刪除字段名logic-delete-value: 1        # 刪除值logic-not-delete-value: 0    # 未刪除值

4.2 自動填充

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());}@Overridepublic void updateFill(MetaObject metaObject) {this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());}
}

4.3 多租戶方案

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 多租戶插件TenantLineInnerInterceptor tenantInterceptor = new TenantLineInnerInterceptor();tenantInterceptor.setTenantLineHandler(new TenantLineHandler() {@Overridepublic Expression getTenantId() {// 從安全上下文獲取租戶IDreturn new LongValue(SecurityUtils.getTenantId());}@Overridepublic String getTenantIdColumn() {return "tenant_id";}@Overridepublic boolean ignoreTable(String tableName) {// 忽略系統表return "sys_config".equals(tableName);}});interceptor.addInnerInterceptor(tenantInterceptor);return interceptor;
}

4.4 枚舉處理

// 枚舉定義
@Getter
public enum UserStatus {ENABLED(1, "啟用"),DISABLED(0, "禁用");@EnumValue // 標記數據庫存儲值private final int code;private final String desc;UserStatus(int code, String desc) {this.code = code;this.desc = desc;}
}// 實體類字段
private UserStatus status;

4.5 動態表名

public class DynamicTableNameParser implements TableNameHandler {private ThreadLocal<String> tableName = new ThreadLocal<>();public void setTableName(String tableName) {this.tableName.set(tableName);}@Overridepublic String dynamicTableName(String sql, String tableName) {return this.tableName.get() != null ? this.tableName.get() : tableName;}
}// 使用示例
DynamicTableNameParser parser = new DynamicTableNameParser();
parser.setTableName("user_2023"); // 設置動態表名TableNameHelper.setTableNameParser(parser);
List<User> users = userMapper.selectList(null); // 操作user_2023表

五、代碼生成器(企業級配置)

5.1 生成器配置

public class CodeGenerator {public static void main(String[] args) {AutoGenerator generator = new AutoGenerator();// 全局配置GlobalConfig globalConfig = new GlobalConfig();globalConfig.setOutputDir(System.getProperty("user.dir") + "/src/main/java");globalConfig.setAuthor("YourName");globalConfig.setOpen(false);globalConfig.setSwagger2(true); // 開啟Swagger注解generator.setGlobalConfig(globalConfig);// 數據源配置DataSourceConfig dataSourceConfig = new DataSourceConfig();dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/mp_demo");dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");dataSourceConfig.setUsername("root");dataSourceConfig.setPassword("123456");generator.setDataSource(dataSourceConfig);// 包配置PackageConfig packageConfig = new PackageConfig();packageConfig.setParent("com.example.mp");packageConfig.setEntity("entity");packageConfig.setMapper("mapper");packageConfig.setService("service");packageConfig.setController("controller");generator.setPackageInfo(packageConfig);// 策略配置StrategyConfig strategy = new StrategyConfig();strategy.setNaming(NamingStrategy.underline_to_camel);strategy.setColumnNaming(NamingStrategy.underline_to_camel);strategy.setEntityLombokModel(true); // 使用Lombokstrategy.setRestControllerStyle(true); // RESTful風格strategy.setInclude("sys_user", "sys_role"); // 生成表// 自定義模板TemplateConfig templateConfig = new TemplateConfig();templateConfig.setController("templates/controller.java");templateConfig.setService("templates/service.java");templateConfig.setServiceImpl("templates/serviceImpl.java");generator.setTemplate(templateConfig);generator.execute();}
}

5.2 自定義模板示例

// templates/controller.java.vm
package ${package.Controller};@RestController
@RequestMapping("/${table.entityPath}")
@RequiredArgsConstructor
public class ${table.controllerName} {private final ${table.serviceName} ${table.entityPath}Service;@GetMapping("/{id}")public Result<${entity}> getById(@PathVariable ${table.keyType} id) {return Result.success(${table.entityPath}Service.getById(id));}// 其他方法...
}

六、性能優化指南

6.1 SQL執行效率優化

// 1. 啟用批處理
@Bean
public ConfigurationCustomizer configurationCustomizer() {return configuration -> {configuration.setDefaultExecutorType(ExecutorType.BATCH); // 批處理模式};
}// 2. 使用流式查詢
try (Cursor<User> cursor = userMapper.selectCursor(queryWrapper)) {cursor.forEach(user -> process(user));
}// 3. 禁用XML熱加載(生產環境)
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl # 關閉日志local-cache-scope: statement # 減小緩存范圍

6.2 查詢優化技巧

// 1. 只查詢必要字段
LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();
wrapper.select(User::getId, User::getName);// 2. 避免N+1查詢(關聯查詢優化)
@Select("SELECT u.*, d.name AS dept_name FROM user u LEFT JOIN dept d ON u.dept_id = d.id")
List<UserVO> selectUserWithDept();// 3. 使用二級緩存
@CacheNamespace(implementation = MybatisRedisCache.class, eviction = MybatisRedisCache.class)
public interface UserMapper extends BaseMapper<User> {
}

6.3 索引優化建議

-- 聯合索引示例
CREATE INDEX idx_user_age_role ON sys_user(age, role);-- 覆蓋索引查詢
EXPLAIN SELECT id, name FROM sys_user WHERE age BETWEEN 20 AND 30;

七、企業級實戰案例

7.1 數據權限控制

public class DataPermissionInterceptor implements InnerInterceptor {@Overridepublic void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {// 獲取當前用戶數據權限DataScope dataScope = SecurityUtils.getDataScope();if (dataScope != null) {// 修改SQL添加權限過濾String sql = boundSql.getSql();String newSql = sql + " AND " + dataScope.getSqlSegment();// 反射修改BoundSQLField field = boundSql.getClass().getDeclaredField("sql");field.setAccessible(true);field.set(boundSql, newSql);}}
}// 注冊攔截器
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new DataPermissionInterceptor());return interceptor;
}

7.2 多數據源動態切換

// 1. 配置多數據源
@Configuration
public class DataSourceConfig {@Bean@ConfigurationProperties("spring.datasource.master")public DataSource masterDataSource() {return DruidDataSourceBuilder.create().build();}@Bean@ConfigurationProperties("spring.datasource.slave")public DataSource slaveDataSource() {return DruidDataSourceBuilder.create().build();}@Beanpublic DataSource dynamicDataSource() {Map<Object, Object> dataSourceMap = new HashMap<>();dataSourceMap.put("master", masterDataSource());dataSourceMap.put("slave", slaveDataSource());DynamicDataSource dataSource = new DynamicDataSource();dataSource.setDefaultTargetDataSource(masterDataSource());dataSource.setTargetDataSources(dataSourceMap);return dataSource;}
}// 2. 數據源切換注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DS {String value() default "master";
}// 3. 切面實現
@Aspect
@Component
public class DataSourceAspect {@Around("@annotation(ds)")public Object around(ProceedingJoinPoint point, DS ds) throws Throwable {String dsKey = ds.value();DynamicDataSourceContextHolder.push(dsKey);try {return point.proceed();} finally {DynamicDataSourceContextHolder.poll();}}
}// 4. 使用示例
@Service
public class UserService {@DS("slave") // 從庫查詢public User getById(Long id) {return userMapper.selectById(id);}@DS("master") // 主庫寫入public void saveUser(User user) {userMapper.insert(user);}
}

八、源碼解析(核心設計思想)

8.1 SQL注入器原理

// 核心流程
AbstractSqlInjector#inspectInject() -> 解析Mapper接口方法-> 根據方法名匹配內置方法(selectById等)-> 構造對應的SqlMethod-> 創建MappedStatement// 自定義注入示例
public class MySqlInjector extends DefaultSqlInjector {@Overridepublic List<AbstractMethod> getMethodList(Class<?> mapperClass) {List<AbstractMethod> methods = super.getMethodList(mapperClass);methods.add(new FindAll()); // 添加自定義方法return methods;}
}// 自定義方法實現
public class FindAll extends AbstractMethod {@Overridepublic MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {String sql = "SELECT * FROM %s";String formattedSql = String.format(sql, tableInfo.getTableName());SqlSource sqlSource = languageDriver.createSqlSource(configuration, formattedSql, modelClass);return this.addSelectMappedStatementForTable(mapperClass, "findAll", sqlSource, tableInfo);}
}

8.2 條件構造器原理

// 核心:AbstractWrapper
public abstract class AbstractWrapper<T, R, Children> implements Compare<Children, R>, Nested<Children, Children> {// 存儲條件表達式protected List<SqlSegment> expression = new ArrayList<>();// 條件構建示例public Children eq(boolean condition, R column, Object val) {if (condition) {expression.add(new SimpleSqlSegment(() -> columnToString(column), () -> " = ", () -> formatSqlValue(val)));}return typedThis;}
}// SQL片段生成
public String getSqlSegment() {return expression.stream().map(SqlSegment::getSqlSegment).filter(Objects::nonNull).collect(Collectors.joining(" "));
}

九、常見問題排查

9.1 字段映射問題

問題現象:實體類字段與數據庫列不匹配
解決方案

// 1. 明確指定映射
@TableField(value = "db_column")// 2. 關閉自動駝峰轉換
mybatis-plus:configuration:map-underscore-to-camel-case: false// 3. 檢查字段類型是否匹配

9.2 分頁失效問題

問題現象:分頁查詢返回所有結果
排查步驟

  1. 檢查是否配置分頁插件
  2. 確認Page對象作為第一個參數
  3. 驗證SQL是否支持分頁(無order by可能導致分頁異常)

9.3 邏輯刪除不生效

解決方案

# 1. 確認全局配置
mybatis-plus:global-config:db-config:logic-delete-field: deleted# 2. 實體類添加注解
@TableLogic
private Integer deleted;

9.4 多租戶SQL異常

典型錯誤:INSERT語句缺少租戶ID
解決方案

// 在TenantLineHandler中實現租戶ID獲取
@Override
public Expression getTenantId() {return new LongValue(SecurityUtils.getTenantId());
}// 確保INSERT操作包含租戶字段

十、未來展望(MyBatis-Plus 4.0)

10.1 新特性預覽

  • 響應式編程支持:整合Project Reactor
  • GraalVM原生鏡像:提升啟動速度
  • 增強的多租戶方案:支持更復雜的租戶隔離
  • 分布式ID生成器:內置更多分布式ID方案

10.2 架構演進

MyBatis Core
MyBatis-Plus 3.x
擴展接口
SQL注入器
元數據處理
攔截器鏈
4.0插件體系

結語

MyBatis-Plus作為MyBatis的增強工具,在企業級應用開發中展現出強大價值。本文涵蓋了從基礎配置到高級特性的全鏈路實踐,重點包含:

  1. 核心功能深度解析:條件構造器、分頁插件、代碼生成器
  2. 企業級方案:多租戶、數據權限、動態數據源
  3. 性能優化:批處理、流式查詢、索引優化
  4. 源碼級原理:SQL注入器、條件構造器實現
  5. 生產環境問題排查

最佳實踐建議

  • 復雜查詢仍推薦XML方式
  • 生產環境關閉SQL日志
  • 使用LambdaQueryWrapper避免字段魔法值
  • 定期進行SQL性能分析

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/908294.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/908294.shtml
英文地址,請注明出處:http://en.pswp.cn/news/908294.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【無標題】路徑著色問題的革命性重構:拓撲色動力學模型下的超越與升華

路徑著色問題的革命性重構&#xff1a;拓撲色動力學模型下的超越與升華 一、以色列路徑著色模型的根本局限 mermaid graph TB A[以色列路徑著色模型] --> B[強連通約束] A --> C[僅實邊三角剖分] A --> D[靜態色彩分配] B --> E[無法描述非相鄰關系] C --> F[忽…

01 Deep learning神經網絡的編程基礎 二分類--吳恩達

二分類 1. 核心定義 二分類任務是監督學習中最基礎的問題類型&#xff0c;其目標是將樣本劃分為兩個互斥類別。設樣本特征空間為 X ? R n \mathcal{X} \subseteq \mathbb{R}^n X?Rn&#xff0c;輸出空間為 Y { 0 , 1 } \mathcal{Y} \{0,1\} Y{0,1}&#xff0c;學習目標為…

數據結構:遞歸:泰勒展開式(Taylor Series Expansion)

目錄 第一步&#xff1a;?我們要解決什么&#xff1f; 第二步&#xff1a;將其類比為求自然數和 第三步&#xff1a;什么是每一項&#xff1f; 第四步&#xff1a;定義要計算的每一項&#xff08;term&#xff09; 第五步&#xff1a;定義遞歸函數結構 &#x1f333; 調用…

Hadolint:Dockerfile 語法檢查與最佳實踐驗證的終極工具

在容器化應用開發的浪潮中,Dockerfile 作為構建 Docker 鏡像的核心配置文件,其質量直接影響著應用的安全性、穩定性和可維護性。然而,隨著項目復雜度的增加,手動檢查 Dockerfile 不僅耗時,還容易遺漏潛在問題。今天,我要向大家介紹一款強大的工具——Hadolint,它將徹底改…

redis數據過期策略、淘汰策略

過期鍵的刪除策略? ??1. 被動刪除&#xff08;惰性刪除&#xff09;?? ??觸發時機??&#xff1a;當客戶端嘗試訪問某個鍵時&#xff0c;Redis會先檢查該鍵是否過期。就是說&#xff0c;我們不時時檢查每個鍵是否過期&#xff0c;而是在使用到這個鍵時檢查是否過期&a…

ES 學習總結一 基礎內容

ElasticSearch學習 一、 初識ES1、 認識與安裝2、 倒排索引2.1 正向索引2.2 倒排索引 3、 基本概念3.1 文檔和字段3.2 索引和倒排 4 、 IK分詞器 二、 操作1、 mapping 映射屬性2、 索引庫增刪改查3、 文檔的增刪改查3.1 新增文檔3.2 查詢文檔3.3 刪除文檔3.4 修改文檔3.5 批處…

鴻蒙任務項設置案例實戰

目錄 案例效果 資源文件與初始化 string.json color.json CommonConstant 添加任務 首頁組件 任務列表初始化 任務列表視圖 任務編輯頁 添加跳轉 任務目標設置模型&#xff08;formatParams&#xff09; 編輯頁面 詳情頁 任務編輯列表項 目標設置展示 引入目標…

DeepSeek-R1-0528重磅升級:三大突破重新定義AI生產力

2025年5月28日&#xff0c;中國AI領軍企業深度求索&#xff08;DeepSeek&#xff09;正式發布DeepSeek-R1-0528版本&#xff0c;這是繼2025年1月R1模型登頂中美App Store后&#xff0c;DeepSeek在通用大模型領域的又一次戰略級突破。此次升級雖為小版本迭代&#xff0c;卻在推理…

【算法訓練營Day07】字符串part1

文章目錄 反轉字符串反轉字符串II替換數字 反轉字符串 題目鏈接&#xff1a;344. 反轉字符串 雙指針法&#xff0c;兩個指針的元素直接調轉即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …

中國西部逐日1 km全天候地表溫度數據集(TRIMS LST-TP;2000-2024)

時間分辨率&#xff1a;日空間分辨率&#xff1a;100m - 1km共享方式&#xff1a;開放獲取數據大小&#xff1a;474.31 GB數據時間范圍&#xff1a;2000-01-01 — 2024-12-31元數據更新時間&#xff1a;2025-05-31 數據集摘要 青藏高原是全球氣候變化的敏感區域。地表溫度&…

PPT轉圖片拼貼工具 v1.0

軟件介紹 這個軟件的作用就是將單個PPT的每一頁轉換為單獨的圖片&#xff0c;然后將圖片進行拼接起來。 但是我沒有還沒有解決一次性處理多個文件。 效果展示如下&#xff1a; 軟件安裝 軟件源碼 import os import re import win32com.client from PIL import Imagedef con…

嵌入式學習筆記DAY33(網絡編程——TCP)

一、網絡架構 C/S &#xff08;client/server 客戶端/服務器&#xff09;&#xff1a;由客戶端和服務器端兩個部分組成。客戶端通常是用戶使用的應用程序&#xff0c;負責提供用戶界面和交互邏輯 &#xff0c;接收用戶輸入&#xff0c;向服務器發送請求&#xff0c;并展示服務…

拋磚引玉:RadarDet4D,NuScenes數據集Radar模態目標檢測第二名(即將開源)

這幾年一直在關注自動駕駛3D目標檢測相關的研究。在NuScenes數據集上有很多經典的模型被提出并得到了驗證&#xff0c;純視覺3D目標檢測經典的方法有BEVFormer、BEVDet系列、DETR3D、Sparse4D等工作&#xff0c;基于LiDAR的有CenterPoint、多模態有BEVFusion、DAL、UniTR等。 …

更新Java的環境變量后VScode/cursor里面還是之前的環境變量

最近我就遇到這個問題&#xff0c;這個一般是安裝了多個版本的Java&#xff0c;并設置好環境變量&#xff0c;但VScode/cursor內部環境變量卻沒有改變 解決辦法 打開設置&#xff0c;或者直接快捷鍵CTRL&#xff0c;搜索Java:Home編輯settings.json文件 把以下部分改為正確的…

線程的基礎知識

進程和線程的區別&#xff1f; 從實例去引入我們的進程和線程的概念&#xff0c;說出進程和線程的關系&#xff0c;引出線程&#xff0c;說出兩者的內存分配占用&#xff0c;上下文切換的區別 當操作系統把我們磁盤中的程序加載到我們的內存當中&#xff0c;為其分配內存空間&a…

x86 匯編中的【條件跳轉指令】:從基礎到擴展的全面解析(查表版)

為了徹底覆蓋 x86 架構中所有條件跳轉指令&#xff0c;包括 8086 到現代 x86-64 的全部變體&#xff0c;我重新整理了分類體系&#xff0c;并補充了鮮為人知的指令變體、操作數大小前綴和歷史演進。 本文需要運用的知識(需要詳細了解可點擊對應的點)&#xff1a; flags寄存器…

FPGA點亮ILI9488驅動的SPI+RGB接口LCD顯示屏(一)

FPGA點亮ILI9488驅動的SPIRGB接口LCD顯示屏 ILI9488 RGB接口初始化 目錄 前言 一、ILI9488簡介 二、3線SPI接口簡介 三、配置寄存器介紹 四、手冊和初始化verilog FPGA代碼 總結 前言 ILI9488是一款廣泛應用于嵌入式系統和電子設備的彩色TFT LCD顯示控制器芯片。本文將介…

Git忽略規則.gitignore不生效解決

我在gitlab中新建了一個項目倉庫&#xff0c;先把項目文件目錄綁定到倉庫&#xff0c;并全部文件都上傳到了倉庫中。 然后又從別的項目復制了忽略文件配置過來&#xff0c;怎么搞他都不能生效忽略我不要提交倉庫的文件。 從網上查到說在本地倉庫目錄中&#xff0c;打開命…

記一個判決書查詢API接口的開發文檔

一、引言 在企業風控、背景調查、盡職調查等場景中&#xff0c;判決書查詢是一個非常重要的環節。通過判決書查詢&#xff0c;可以了解個人或企業的司法涉訴情況&#xff0c;為風險評估提供數據支持。本文將詳細介紹如何開發和使用一個司法涉訴查詢API接口&#xff0c;包括客戶…

mac版excel如何制作時長版環形圖

設置輔助列 創建簇狀柱形圖 將輔助列繪制在次坐標軸 工作時長在主坐標軸&#xff0c;右鍵分別更改圖表類型為圓環。 輔助列圓環全部為灰色&#xff0c;邊框為白色 輔助列設置透明度100% 設置輔助列和工作時長列同樣的圓環大小 可得 核心&#xff1a;只要輔助列邊框不透明…