springboot入门2

学习目标:

了解数据库配置加密方法,数据库连接池,mybatis-paginationInterceptor分页,pagehelper分页常用功能

学习内容:

1、mybatis plus配置加密

1.1、生成加密配置

package sccba.example;import com.baomidou.mybatisplus.core.toolkit.AES;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
class BootDemoApplicationTests {@Testvoid contextLoads() {//生成 16 位随机 AES 密钥String randomKey = AES.generateRandomKey();System.out.println(randomKey);//13fe43969b1bd013String url = AES.encrypt("jdbc:mysql://7.**.**.**:3306/boot_demo?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false", randomKey);String username = AES.encrypt("root", randomKey);String password = AES.encrypt("123456", randomKey);System.out.println(url);System.out.println(username);System.out.println(password);}}

1.2在配置文件中配置加密信息

spring:mvc:pathmatch:matching-strategy: ant_path_matcher #Spring Boot 2.6及以后,swagger配置报错,需添加此配置datasource:#运行命令java -jar bootDemo-0.0.1-SNAPSHOT.jar --mpw.key=*****  --spring.profiles.active=proddriverClassName: com.mysql.cj.jdbc.Driverurl: mpw:Y9zn0h//FsmBS7JJ0Frsl8qAJ9b7****mSMkoHS0QyPiooOq01ylU4s9Dcj1mqg=username: mpw:Zg+h***soXJc+fw==password: mpw:LO8p0****TY7GcQ==

1.3启动时添加参数–mpw.key

通过cmd命令运行项目

java -jar bootDemo-0.0.1-SNAPSHOT.jar --mpw.key=13fe43969b1bd013 --spring.profiles.active=prod

通过ideal运行,添加Program arguments配置
在这里插入图片描述

1.4原理

SpringBoot 提供修改Spring环境后置处理器【EnvironmentPostProcessor】,允许在应用程序之前操作环境属性值。mybatis plus的SafetyEncryptProcessor 类实现了EnvironmentPostProcessor ,此方法也可对配置文件中的其他参数进行加密

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package com.baomidou.mybatisplus.autoconfigure;import com.baomidou.mybatisplus.core.toolkit.AES;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import java.util.HashMap;
import java.util.Iterator;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.SimpleCommandLinePropertySource;public class SafetyEncryptProcessor implements EnvironmentPostProcessor {public SafetyEncryptProcessor() {}public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {String mpwKey = null;Iterator var4 = environment.getPropertySources().iterator();while(var4.hasNext()) {PropertySource<?> ps = (PropertySource)var4.next();if (ps instanceof SimpleCommandLinePropertySource) {SimpleCommandLinePropertySource source = (SimpleCommandLinePropertySource)ps;mpwKey = source.getProperty("mpw.key");break;}}if (StringUtils.isNotBlank(mpwKey)) {HashMap<String, Object> map = new HashMap();Iterator var15 = environment.getPropertySources().iterator();while(true) {PropertySource ps;do {if (!var15.hasNext()) {if (CollectionUtils.isNotEmpty(map)) {environment.getPropertySources().addFirst(new MapPropertySource("custom-encrypt", map));}return;}ps = (PropertySource)var15.next();} while(!(ps instanceof OriginTrackedMapPropertySource));OriginTrackedMapPropertySource source = (OriginTrackedMapPropertySource)ps;String[] var8 = source.getPropertyNames();int var9 = var8.length;for(int var10 = 0; var10 < var9; ++var10) {String name = var8[var10];Object value = source.getProperty(name);if (value instanceof String) {String str = (String)value;if (str.startsWith("mpw:")) {map.put(name, AES.decrypt(str.substring(4), mpwKey));}}}}}}
}

2、数据库连接池

2.1 HikaraCP 默认连接池

1、在 Spring Boot 项目中,一个简单的 Spring DataSource 配置,通常只需要设置数据库连接、用户名和密码三个参数。
2、在 Spring Boot 项目中, Spring DataSource 会使用默认的配置启用 HikaraCP 数据库连接池。需要注意程序启动时并不会创建数据库连接,而是按需创建。项目启动后执行mysql查询命令show processlist 查看数据库连接。

spring:datasource:type: com.zaxxer.hikari.HikariDataSource #连接池类型,默认自动获取#spring hikari 数据库连接池配置hikari:auto-commit: true #事务自动提交,默认trueconnection-timeout: 30000 #连接超时时间(ms),默认值30秒,如果连接池满等待释放线程最大时间,超过则报错idle-timeout: 600000 #连接池中允许闲置的时间(ms),默认值10分钟,最小允许10smax-lifetime: 1800000 #连接生命时长(ms),超时而没被使用则释放,默认值30分钟,最小允许30s。如果执行时间大于max-lifetime则在sql执行完后idle-timeout释放,如果执行时间小于max-lifetime则在max-lifetime减去执行时间后释放maximum-pool-size: 20 #连接池中允许的最大连接数,包括使用和闲置的连接,默认10,超过将进入等待队列,直到有空闲连接minimum-idle: 10 #连接池中允许的最小空闲连接数,默认10validation-timeout: 5000 #连接测试活动的最长等待时间(ms),默认5s,最小值250mspool-name: HikaraPool-1 #连接池名称,默认自动生成

2.2 Druid 连接池

2.2.1添加依赖
        <dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>${druid.version}</version></dependency>
2.2.2配置

需要指定spring.datasource.type,spring.datasource.druid参数可以不写,会按照默认参数处理

spring:datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql:///:3306/数据库名?useSSL=false&useUnicode=true&characterEncoding=UTF-8username:password:type: com.alibaba.druid.pool.DruidDataSourcedruid:initial-size: 10 # 初始化时建立物理连接的个数。min-idle: 10 # 最小连接池数量maxActive: 200 # 最大连接池数量maxWait: 60000 # 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置timeBetweenEvictionRunsMillis: 60000 # 关闭空闲连接的检测时间间隔.Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。minEvictableIdleTimeMillis: 300000 # 连接的最小生存时间.连接保持空闲而不被驱逐的最小时间validationQuery: SELECT 1 FROM DUAL # 验证数据库服务可用性的sql.用来检测连接是否有效的sql 因数据库方言而差, 例如 oracle 应该写成 SELECT 1 FROM DUALtestWhileIdle: true # 申请连接时检测空闲时间,根据空闲时间再检测连接是否有效.建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRuntestOnBorrow: false # 申请连接时直接检测连接是否有效.申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。testOnReturn: false # 归还连接时检测连接是否有效.归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。poolPreparedStatements: true # 开启PSCachemaxPoolPreparedStatementPerConnectionSize: 20 #设置PSCache值connectionErrorRetryAttempts: 3 # 连接出错后再尝试连接三次breakAfterAcquireFailure: true # 数据库服务宕机自动重连机制timeBetweenConnectErrorMillis: 300000 # 连接出错后重试时间间隔asyncInit: true # 异步初始化策略remove-abandoned: true # 是否自动回收超时连接remove-abandoned-timeout: 1800 # 超时时间(以秒数为单位)transaction-query-timeout: 6000 # 事务超时时间filters: stat,wall,log4j2useGlobalDataSourceStat: true #合并多个DruidDataSource的监控数据connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000 #通过connectProperties属性来打开mergeSql功能;慢SQL记录
2.2.3数据库密码加密

打开依赖jar所在位置
在这里插入图片描述
打开dos窗口
在这里插入图片描述
使用命令生成加密密码&密钥(两种命令二选一,推荐命令2方便后面复制使用)
命令1:java -cp druid-1.2.20.jar com.alibaba.druid.filter.config.ConfigTools 数据库密码
直接把密钥打印在dos窗口
命令2:java -cp druid-1.2.20.jar com.alibaba.druid.filter.config.ConfigTools 数据库密码 > pwd.txt
生成一个文件在当前目录下
在这里插入图片描述

生成的文件
在这里插入图片描述
修改数据库配置,password的值放在spring.datasource.druid.password。publicKey的值放在spring.datasource.druid.connection-properties: config.decrypt=true;config.decrypt.key=${publicKey}


spring:datasource:driverClassName: com.mysql.cj.jdbc.Driver#druid加密方式druid:url: jdbc:mysql://*.*.*.*:3306/boot_demo?useUnicode=true&characterEncoding=utf-8&useSSL=falseusername: password: PhFyCDrV********126LwHTvYiVKYX6La1fDlSC8g==connection-properties: config.decrypt=true;config.decrypt.key=MFwwDQYJK*******LwiyGH5rgAMCYgYToVKbvSf10dSP53pUekVMLyk0DwWEOZ8PYY565V1oQ275uRgP2kRMbX5Lcc+qmWzM+0CAwEAAQ==filter:config:enabled: true

3、分页

3.1 mybatis-plus分页插件PaginationInnerInterceptor

3.1.1 配置分页插件

在没有引入分页插件的情况下,Mybatis Plus 是不支持分页功能的,IService 和 BaseMapper 中的分页方法都无法正常生效。所以,我们必须配置分页插件,简单来说,就是创建一个配置类,然后注册一个 Bean 对象:

package sccba.example.config;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @ClassName MybatisPlusConfig* @Description TODO* @Author c_see* @Date 2024/1/23 17:41* @Version 1.0**/
@Configuration
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}
}

3.1.2 测试分页功能

编写通用分页查询类

/*** 通用分页查询类*/
@Data
@ApiModel(description = "分页查询实体类")
public class PageQuery {@ApiModelProperty("页码")private Integer pageNum;@ApiModelProperty("页面大小")private Integer pageSize;@ApiModelProperty("排序字段")private String sortBy;@ApiModelProperty("是否升序")private Boolean isAsc;
}

修改UserQuery类集成PageQuery

@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserQuery extends PageQuery {@ApiModelProperty(value = "用户ID", example = "1")private Long userId;@ApiModelProperty(value = "部门ID", example = "1")private Long depId;
}

添加分页查询方法
UserController添加查询接口

    /*** 使用Mybatis-plus自带分页操作 并对parms中的Key进行模糊查询*/@ApiOperation("分页获取用户")@GetMapping("/getList")public R findPageByMybatisPlus(UserQuery userQuery) {IPage page = userService.pageByMybatisPlus(userQuery);return R.ok().putData(page);}

UserService添加分页查询方法


public interface UserService {public UserDTO getById(Long userId);UserDTO getUsersDep(Long userId);void insert(UserVO userVo);IPage pageByMybatisPlus(UserQuery userQuery);
}

UserServiceImpl实现分页查询方法

package sccba.example.admin.service.impl;import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import sccba.example.admin.dao.UserMapper;
import sccba.example.admin.domain.dto.UserDTO;
import sccba.example.admin.domain.entity.UserDO;
import sccba.example.admin.domain.query.UserQuery;
import sccba.example.admin.domain.transfer.UserTransfer;
import sccba.example.admin.domain.vo.UserVO;
import sccba.example.admin.service.UserService;import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Function;/*** @ClassName UserServiceImpl* @Description TODO* @Author c_see* @Date 2024/1/12 15:27* @Version 1.0**/
@Service(value = "userService")
public class UserServiceImpl extends ServiceImpl<UserMapper, UserDO> implements UserService {@Autowired //根据类型注入private UserMapper userMapper;@Overridepublic UserDTO getById(Long userId) {UserDO userDO = userMapper.get(userId);
//        UserDO userDO = userMapper.selectById(userId);
//        // 创建查询条件对象
//        QueryWrapper<UserDO> queryWrapper = new QueryWrapper<>();
//
//        // 添加连表条件
//        queryWrapper.lambda().eq(UserDO::getId, userId).ge(UserDO::getAge,20).like(UserDO::getName,"老");
//        // 调用selectList方法执行查询并返回结果集合
//        UserDO userDO = userMapper.selectOne(queryWrapper);//TODO 内部使用UserBO封装中间所需的逻辑对象,可以包括一个或多个其它的对象。常见操作DO转DTO,DO转BO、BO转DTOreturn UserTransfer.toDTO(userDO);}@Overridepublic UserDTO getUsersDep(Long userId) {UserDTO userDTO = userMapper.getUserWithDep(userId);//TODO 内部使用UserBO封装中间所需的逻辑对象,可以包括一个或多个其它的对象。常见操作DO转DTO,DO转BO、BO转DTOreturn userDTO;}@Overridepublic void insert(UserVO userVo) {UserDO userDO = UserTransfer.vo2DO(userVo);userDO.setDepId(1L);userDO.setPassword("12546");userMapper.insert(userDO);}@Overridepublic IPage pageByMybatisPlus(UserQuery userQuery) {QueryWrapper<UserDO> queryWrapper = new QueryWrapper<>();queryWrapper.lambda().eq(UserDO::getId, userQuery.getUserId()).or().eq(UserDO::getDepId, userQuery.getDepId());Page<UserDO> pageQ = new Page<UserDO>(userQuery.getPageNum(), userQuery.getPageSize());if (!StringUtils.isEmpty(userQuery.getSortBy())) {pageQ.addOrder(new OrderItem(userQuery.getSortBy(), userQuery.getIsAsc()));}IPage<UserDO> page = this.page(pageQ, queryWrapper);return UserTransfer.toDTOPage(page);}}

编写单元测试,执行成功
在这里插入图片描述

3.2 pagehelper分页插件

3.2.1引入依赖

        <dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.5</version></dependency>

3.2.2使用PageHelper分页

controller

       /*** 使用pagehelper分页操作 并对parms中的Key进行模糊查询*/@ApiOperation("分页获取用户PageHelper")@GetMapping("/getList2")public R findPageByPageHelper(UserQuery userQuery) {return R.ok().putData(userService.pageByPageHelper(userQuery));}

serviceImp

    @Overridepublic PageInfo<UserDTO> pageByPageHelper(UserQuery userQuery) {//使用PageHelper以下三句之间不能插入其他语句PageHelper.startPage(userQuery.getPageNum(), userQuery.getPageSize(), true).setOrderBy(userQuery.getSortBy());List<UserDO> userDOList = userMapper.getList(userQuery);PageInfo<UserDO> page =  new PageInfo<UserDO>(userDOList);return UserTransfer.toDTOPage(page);//错误写法
//        List<UserDTO> userDTOList = UserTransfer.toDTOList(userDOList);
//        return new PageInfo<UserDTO>(userDTOList);}

3.2.3 编写测试案例测试

在这里插入图片描述

3.2.4原理概述

PageHelper是MyBatis的一个插件,内部实现了一个PageInterceptor拦截器。Mybatis会加载这个拦截器到拦截器链中。在我们使用过程中先使用PageHelper.startPage这样的语句在当前线程上下文中设置一个ThreadLocal变量,再利用PageInterceptor这个分页拦截器拦截,从ThreadLocal中拿到分页的信息,如果有分页信息拼装分页SQL(limit语句等)进行分页查询,最后再把ThreadLocal中的东西清除掉。
PageHelper原理详情参考:https://blog.csdn.net/fedorafrog/article/details/104412140
ThreadLocal 详解参考:https://blog.csdn.net/u010445301/article/details/111322569

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

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

相关文章

盲盒App小程序开发:引领未来购物新潮流

随着科技的不断发展&#xff0c;我们的购物方式也在不断改变。近年来&#xff0c;盲盒购物逐渐成为了一种新型的消费模式&#xff0c;受到了广大消费者的热烈欢迎。为了满足消费者的需求&#xff0c;越来越多的企业开始涉足盲盒App的开发。本文将探讨盲盒App开发的意义、前景以…

[嵌入式软件][启蒙篇][仿真平台] STM32F103实现IIC控制OLED屏幕

上一篇&#xff1a;[嵌入式软件][启蒙篇][仿真平台] STM32F103实现LED、按键 [嵌入式软件][启蒙篇][仿真平台] STM32F103实现串口输出输入、ADC采集 [嵌入式软件][启蒙篇][仿真平台]STM32F103实现定时器 [嵌入式软件][启蒙篇][仿真平台] STM32F103实现IIC控制OLED屏幕 文章目…

【GitHub项目推荐--国外名校AI教程】【转载】

这个开源项目搜集了 YouTube 上优质的机器学习教程&#xff0c;方向包括机器学习、深度学习、计算机视觉、自然语言处理、无监督学习等等。 开源地址&#xff1a;https://github.com/dair-ai/ML-YouTube-Courses

[260. 只出现一次的数字 III](C语言题解)(位运算)(力扣)

> Problem: [260. 只出现一次的数字 III](260. 只出现一次的数字 III - 力扣&#xff08;LeetCode&#xff09;) # 思路 > 想到数组中只有一个数只出现了一次的解法&#xff1a;**所有数异或&#xff0c;最后答案就是那个只出现一次的数**&#xff0c;该题只需将两个不…

Kubernetes成本优化

云原生可以帮助团队更精细化利用资源&#xff0c;但如果缺乏工具的帮助&#xff0c;很难采取适当的措施优化资源的使用。本文介绍了若干用于可视化Kubernetes资源使用情况的工具&#xff0c;并且可以自定义策略优化资源使用&#xff0c;实现更好的成本优化。原文: Kubernetes C…

《WebKit 技术内幕》学习之十五(5):Web前端的未来

5 Crosswalk项目 Crosswalk项目是由英特尔公司发起的一个开源项目&#xff0c;该项目基于WebKit&#xff08;Blink&#xff09;和Chromium等开源项目打造&#xff0c;其目的是提供一个跨不同操作系统的Web运行环境&#xff0c;包括Android、Tizen、Linux、Windows、MacOS等众多…

python使用PaddleOCR实现《命名实体识别项目》OCR(已实现)(ai领域必看,简单易用)

1.简介&#xff1a; PaddleOCR是飞桨&#xff08;PaddlePaddle&#xff09;推出的一个端到端的光学字符识别开源工具集&#xff0c;支持中文、英文、数字以及特殊符号等各种类型的文字检测、识别和词语整体识别。该工具集使用PaddlePaddle深度学习框架技术&#xff0c;提供了多…

Likeshop多商户商城源码系统,支持二开

在电商行业高速发展的当下&#xff0c;拥有一套功能强大、易于操作的开源商城系统至关重要。Likeshop多商户商城系统正是这样一款集H5、小程序、独立APP于一体的开源电商解决方案&#xff0c;助力商家实现智能营销。 一、产品简介 Likeshop多商户商城系统为商家提供了丰富的营…

Spring Boot 中 Service 层依赖注入问题

目录 问题描述 产生错误 问题原因 解决方法 手动注入方法 1、使用工具集 hutool&#xff0c;引入 Maven 依赖 2、编写 SpringUtil 工具类 问题描述 Controller 层方法为 static 静态&#xff0c;引入 Service 层时使用 Autowired 注解自动装配&#xff0c;Controller层方…

C#用 DateAndTime.DateAdd方法和DateTime.Add(TimeSpan) 方法分别添加一段时间间隔

目录 一、基本方法 1.用 DateAndTime.DateAdd方法添加一段时间间隔 2.用DateTime.Add方法添加一段时间间隔 二、实例 1.实例1&#xff1a;用 DateAndTime.DateAdd方法 2.实例2&#xff1a;用DateTime.Add方法 一、基本方法 1.用 DateAndTime.DateAdd方法添加一段时间间隔…

Android发展历程及安装

目录 发展历程 下载网址 安装过程 发展历程 安卓基于Linux内核&#xff0c;Linux内核相当于房屋的地基 开源不等于免费&#xff0c;不能商用 安卓一般每半年小更新&#xff0c;一年大更新 对应API相当于别名 现在安卓安全性越来越高&#xff0c;性能越来越快&#xff0c…

2024年预制菜行业市场发展趋势分析(2021-2023年预制菜行业数据分析)

近期&#xff0c;老干妈被称为预制菜、预制菜国标报送稿出炉等事件再次引起大众对于预制菜市场的讨论。随着国家对预制菜审核标准的严格化&#xff0c;预制菜市场未来走向将会如何&#xff1f;鲸参谋带大家从数据角度来了解。 首先来看下预制菜市场的行业发展情况。 根据鲸参…

蓝桥杯备赛 week 4 —— DP 背包问题

目录 &#x1f308;前言&#x1f308;&#xff1a; &#x1f4c1; 01背包问题 分析&#xff1a; dp数组求解&#xff1a; 优化&#xff1a;滚动数组&#xff1a; &#x1f4c1; 完全背包问题 &#x1f4c1; 总结 &#x1f308;前言&#x1f308;&#xff1a; 这篇文章主…

大数据就业方向-(工作)ETL开发

上一篇文章&#xff1a; 大数据 - 大数据入门第一篇 | 关于大数据你了解多少&#xff1f;-CSDN博客 目录 &#x1f436;1.ETL概念 &#x1f436;2. ETL的用处 &#x1f436;3.ETL实现方式 &#x1f436;4. ETL体系结构 &#x1f436;5. 什么是ETL技术&#xff1f; &…

MySQL JSON数据类型全解析(JSON datatype and functions)

JSON&#xff08;JavaScript Object Notation&#xff09;是一种常见的信息交换格式&#xff0c;其简单易读且非常适合程序处理。MySQL从5.7版本开始支持JSON数据类型&#xff0c;本文对MySQL中JSON数据类型的使用进行一个总结。 目录 一、MySQL中的JSON 1.1 JSON数据格式 1.2 …

spring-boot-starter-validation常用注解

文章目录 一、使用二、常用注解三、Valid or Validated &#xff1f;四、分组校验1. 分组校验的基本概念2. 定义验证组3. 应用分组到模型4. 在控制器中使用分组5. 总结 一、使用 要使用这些注解&#xff0c;首先确保在你的 Spring Boot 应用的 pom.xml 文件中添加了 spring-bo…

探秘Dmail:Web3世界的通讯引领者

摘要&#xff1a;在一个充满潜力并且对创新要求严格的领域中&#xff0c;Dmail作为一种开创性的Web3通讯协议应运而生。 1月24日&#xff0c;OKX Jumpstart宣布上线Dmail&#xff0c;在Web3领域引起了巨大反响&#xff0c;这是一个旨在重新定义数字通讯范式的富有远见的项目&a…

[足式机器人]Part2 Dr. CAN学习笔记- 最优控制Optimal Control Ch07

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记 - 最优控制Optimal Control Ch07-1最优控制问题与性能指标 1. 最优控制问题与性能指标2. 动态规划 Dynamic Programming2.1 基本概念2.2 代码详解2.3 简单一维案例 3. 线性二次型调节器&#xff…

GIt同时存在传入和传出更改修改,无法合并

前言 Git是常用的版本管理工具&#xff0c;之前面试被问到过一次——Git有无遇到过使用错误情况&#xff1f;当时卡壳了没答上来&#xff0c;所以这次遇到&#xff0c;特此记录学习。 问题概述 前一天提交了代码&#xff0c;mt进行了修改。但我忘记拉取最新&#xff0c;就进…

深度解析单片机:历史、发展与您关心的问题

什么是单片机&#xff1f; 定义&#xff1a;单片机是一种集成了中央处理器&#xff08;CPU&#xff09;、内存和外设功能的微型计算机系统。与传统计算机相比&#xff0c;单片机通常集成在一个芯片上&#xff0c;用于控制特定的应用。#单片机# 特点&#xff1a; 封装紧凑&…