SpringBoot--中间件技术-4:整合Shiro,Shiro基于会话SessionManager实现分布式认证,附案例含源代码!
SpringBoot整合安全中间件Shiro
技术栈:SpringBoot+Shiro
代码实现
-
pom文件加坐标
Springboot版本选择2.7.14 ;java版本1.8 ; shiro做了版本锁定 1.3.2
<properties><java.version>1.8</java.version><!--shiro版本锁定--><shiro.version>1.3.2</shiro.version> </properties> <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><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-logging</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.16</version></dependency><!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.21</version></dependency><!--mp--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.3</version></dependency><!-- SECURITY begin --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>${shiro.version}</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>${shiro.version}</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-web</artifactId><version>${shiro.version}</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-ehcache</artifactId><version>${shiro.version}</version></dependency><!-- SECURITY end --> </dependencies>
-
主配置文件
#配置数据源 spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/spring?serverTimezone=GMTusername: rootpassword: 123456#配置自动驼峰映射 mybatis:configuration:map-underscore-to-camel-case: truetype-aliases-package: com.dong.pojo #MP配置自动驼峰映射 mybatis-plus:configuration:map-underscore-to-camel-case: truelog-impl: org.apache.ibatis.logging.stdout.StdOutImpl #mybatis所执行的sql输出控制台
-
POJO实体类
Permission
@NoArgsConstructor @AllArgsConstructor @Data @Component @TableName(value = "pe_permission") public class Permission {@TableField(value = "id")private String id;@TableField(value = "name")private String name;@TableField(value = "code")private String code;@TableField(value = "description")private String description; }
Role
@NoArgsConstructor @AllArgsConstructor @Data @TableName(value = "pe_role") @Component public class Role {@TableField(value = "id")private String id;@TableField(value = "name")private String name;@TableField(value = "code")private String code;@TableField(value = "description")private String description;// 外部属性@TableField(exist = false)private List<Permission> permissions; }
Users
@NoArgsConstructor @AllArgsConstructor @Data @TableName(value = "pe_user") @Component public class Users {@TableId(value = "id")private String id;@TableField(value = "username")private String username;@TableField(value = "password")private String password;@TableField(value = "salt")private String salt;// 外部属性@TableField(exist = false)private List<Role> rolesList;public Users(String id, String username, String password) {this.id = id;this.username = username;this.password = password;} }
-
dao层
UsersMapper
@Mapper public interface UserMapper extends BaseMapper<Users> {@Insert("insert into pe_user(id,username,password,salt) values(#{id},#{username},#{password},#{salt})")public int save(Users users);// 级联查询@Results(id = "users",value = {@Result(column = "id",property = "rolesList",many = @Many(select = "com.dong.springboot_mp_shiro.com.dong.mapper.RoleMapper.findById"))})@Select("select * from pe_user where username=#{v}")public Users findUserDetail(String name);// 简单查询@Select("select * from pe_user where username=#{v}")public Users findBaseUser(String name); }
RoleMapper
@Mapper public interface RoleMapper extends BaseMapper<Role> {@Results(id = "role",value = {@Result(column = "id",property = "permissions",many=@Many(select = "com.dong.springboot_mp_shiro.com.dong.mapper.PermissionMapper.findByPermissionId"))})@Select("select * from pe_role where id in (select role_id from pe_user_role where user_id =#{v} )")public Role findById(String id);}
PermissionMapper
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.dong.springboot_mp_shiro.com.dong.pojo.Permission; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; @Mapper public interface PermissionMapper extends BaseMapper<Permission> {@Select("select * from pe_permission where id in (select permission_id from pe_role_permission where role_id =#{v})")public Permission findByPermissionId(String permissionId); }
-
service层
接口:
IUserService
public interface IUserService {public int save(Users users);public Users baseFindUser(String name);public Users findUserDetail(String Name); }
IRoleService
public interface IRoleService { }
IPermissionService
public interface IPermissionService { }
实现类:
UserServiceImp
@Service public class UserServiceImp implements IUserService {@Autowired(required = false)private UserMapper uMapper;@Overridepublic int save(Users users) {System.out.println("service:"+ users);// 获取salt字符串String salt = DigestsUtil.generateSalt();// 密码加密String password = DigestsUtil.generatePassword(users.getPassword(), salt);users.setPassword(password);users.setSalt(salt);int res = uMapper.save(users);return res;}@Overridepublic Users baseFindUser(String name) {Users baseUser = uMapper.findBaseUser(name);return baseUser;}@Overridepublic Users findUserDetail(String name) {Users userDetail = uMapper.findUserDetail(name);return userDetail;} }
-
controller层
@RestController public class UserController {@Autowired(required = false)private UserServiceImp service;// 首页@RequiresPermissions("user-home")@RequestMapping("/user/home")public String home(){return "访问个人主页成功";}// 用户注册@RequiresPermissions("user-add")@RequestMapping("/user/{id}")public String save(@PathVariable String id){/*int res = service.save(users);if(res>0){return "添加成功";}else{return "添加失败";}*/return "新增成功";}@RequiresPermissions("user-delete")@RequestMapping(value = "/user/{id}",method = RequestMethod.DELETE)public String delete(@PathVariable String id){return "删除成功";}@RequiresPermissions("user-update")@RequestMapping(value = "/user/{id}",method = RequestMethod.PUT)public String update(@PathVariable String id){return "修改成功";}@RequiresPermissions("user-find")@RequestMapping(value = "/user",method = RequestMethod.GET)public String find(){return "查询成功";}// 登录认证@RequestMapping("/login")public String login(Users users){try {// 构造登录令牌UsernamePasswordToken token = new UsernamePasswordToken(users.getUsername(), users.getPassword());// 获取subjectSubject subject = SecurityUtils.getSubject();// 调用subject认证subject.login(token);return "登录成功";} catch (AuthenticationException e) {return "用户名或密码错误";}}// 未登录跳转@RequestMapping("/autherror")public String autherror(){return "未认证,请登录";} }
==@RequiresPermissions(" "):==标注访问该资源需要的权限
-
执行subject.long登录方法,执行Reaml的AuthenticationException方法
-
鉴权授权,执行Reaml的AuthorizationInfo方法
-
-
MyRealm
public class MyRealm extends AuthorizingRealm {@Autowired(required = false)private UserServiceImp serviceImp;// 授权鉴权@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {// 获取已经认证的用户数据Users users = (Users) principalCollection.getPrimaryPrincipal();// 查询用户的详细信息Users userDetail = serviceImp.findUserDetail(users.getUsername());HashSet<String> perms = new HashSet<>(); // 权限set集合HashSet<String> roles = new HashSet<>(); // 角色set集合for(Role role: userDetail.getRolesList() ){roles.add(role.getCode());for(Permission permission: role.getPermissions() ){perms.add(permission.getCode());}}SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();info.setStringPermissions(perms);info.setRoles(roles);return info;}// 认证@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {// 获取用户登陆输入的密码(token)UsernamePasswordToken upToken = (UsernamePasswordToken)authenticationToken;// 用户输入的账号String username = upToken.getUsername();Users users = serviceImp.baseFindUser(username);if(users != null){SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(users, users.getPassword(), ByteSource.Util.bytes(users.getSalt()), "MyRealm");return info;}// 账号查不到,返回null(抛出异常)return null;}@PostConstruct // 属性初始化public void initCredentialsMatcher(){// 指定密码算法HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(DigestsUtil.SHA1);// 指定迭代次数hashedCredentialsMatcher.setHashIterations(DigestsUtil.COUNTS);// 生成密码比较器setCredentialsMatcher(hashedCredentialsMatcher);} }
@PostConstruct注解,属性初始化
加密工具类
public class DigestsUtil {// 编码方式public static final String SHA1="SHA-1";// 加密次数public static final Integer COUNTS=369;// 获取salt字符串public static String generateSalt(){SecureRandomNumberGenerator secureRandomNumberGenerator = new SecureRandomNumberGenerator();return secureRandomNumberGenerator.nextBytes().toHex();}// 生成密文密码public static String generatePassword(String input,String salt){return new SimpleHash(SHA1,input,salt,COUNTS).toString();}}
-
Shiro配置类:ShiroConfiguration
@Configuration public class ShiroConfiguration {/*** 1.创建shiro自带cookie对象*/@Beanpublic SimpleCookie sessionIdCookie(){SimpleCookie simpleCookie = new SimpleCookie();simpleCookie.setName("ShiroSession");return simpleCookie;}//2.创建realm@Beanpublic MyRealm getRealm() {return new MyRealm(); //new 自定义的Reaml}/*** 3.创建会话管理器*/@Beanpublic DefaultWebSessionManager sessionManager(){DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();sessionManager.setSessionValidationSchedulerEnabled(false);sessionManager.setSessionIdCookieEnabled(true);sessionManager.setSessionIdCookie(sessionIdCookie());sessionManager.setGlobalSessionTimeout(3600000);return sessionManager;}//4.创建安全管理器@Beanpublic SecurityManager defaultWebSecurityManager() {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();securityManager.setRealm(getRealm());securityManager.setSessionManager(sessionManager());return securityManager;}/*** 5.保证实现了Shiro内部lifecycle函数的bean执行*/@Bean(name = "lifecycleBeanPostProcessor")public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {return new LifecycleBeanPostProcessor();}/*** 6.开启对shiro注解的支持* AOP式方法级权限检查*/@Bean@DependsOn("lifecycleBeanPostProcessor")public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);return defaultAdvisorAutoProxyCreator;}/*** 7.配合DefaultAdvisorAutoProxyCreator事项注解权限校验*/@Beanpublic AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor() {AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();authorizationAttributeSourceAdvisor.setSecurityManager(defaultWebSecurityManager());return authorizationAttributeSourceAdvisor;}/** 8.配置shiro的过滤器工厂再web程序中,shiro进行权限控制全部是通过一组过滤器集合进行控制* */@Beanpublic ShiroFilterFactoryBean shiroFilter(){// 1.创建过滤工厂ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();// 2.设置安全管理器filterFactoryBean.setSecurityManager(defaultWebSecurityManager());// 3.通用配置(跳转登录页面,为授权跳转的页面)filterFactoryBean.setLoginUrl("/autherror");//4.设置过滤器集合//key = 拦截的url地址//value = 过滤器类型LinkedHashMap<String, String> filterMap = new LinkedHashMap<>();filterMap.put("/login","anon");//当前请求地址可以匿名访问filterMap.put("/user/**","authc");// 当前请求地址必须认证之后才可以访问// 在过滤器工程内设置系统过滤器filterFactoryBean.setFilterChainDefinitionMap(filterMap);return filterFactoryBean;} }
-
统一异常处理器
@ControllerAdvice public class UserControllerAdv {@ExceptionHandler(value = AuthorizationException.class)@ResponseBodypublic String tongyi(HttpServletRequest request , HttpServletResponse response, AuthorizationException e){return "未授权---统一异常处理器";}}
Shiro实现分布式会话SessionManager
代码结构:代码结构和SpringBoot整合Shiro中的案例相同
问题:如图
解决思路:将当前的session会话存到缓存Redis中
实现步骤:
- 创建RedisSessionDao extends AbstractSessionDAO
- 配置ShiroConfig
代码实现:
-
RedisSessionDao
public class RedisSessionDao extends AbstractSessionDAO {@Autowiredprivate RedisTemplate redisTemplate;//创建会话@Overrideprotected Serializable doCreate(Session session) {Serializable sessionId = generateSessionId(session);assignSessionId(session, sessionId);redisTemplate.opsForValue().set(sessionId,session);return sessionId;}@Overrideprotected Session doReadSession(Serializable sessionId) {return (Session) redisTemplate.opsForValue().get(sessionId);}@Overridepublic void delete(Session session) {redisTemplate.delete(session.getId());}@Overridepublic Collection<Session> getActiveSessions() {return Collections.emptySet();}@Overridepublic void update(Session session) {redisTemplate.opsForValue().set(session.getId(),session);}}
-
需要操作Redis,整合Redis
-
导入redis坐标
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
-
yaml主配置文件配置redis
server:port: 8080 #配置数据源 spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/spring?serverTimezone=GMTusername: rootpassword: 123456redis:port: 6379#配置自动驼峰映射 mybatis:configuration:map-underscore-to-camel-case: truetype-aliases-package: com.dong.pojo #MP配置自动驼峰映射 mybatis-plus:configuration:map-underscore-to-camel-case: truelog-impl: org.apache.ibatis.logging.stdout.StdOutImpl #mybatis所执行的sql输出控制台
-
ShiroConfig
向容器中注入一个SessionDao,把SessionDao绑定给会话管理器
@Configuration public class ShiroConfiguration {/*** 1.创建shiro自带cookie对象*/@Beanpublic SimpleCookie sessionIdCookie(){SimpleCookie simpleCookie = new SimpleCookie();simpleCookie.setName("ShiroSession");return simpleCookie;}//2.创建realm@Beanpublic MyRealm getRealm() {return new MyRealm();}// 向容器中注入一个SessionDao@Beanpublic SessionDAO redisSessionDao(){RedisSessionDao sessionDAO = new RedisSessionDao();return sessionDAO;}/*** 3.创建会话管理器*/@Beanpublic DefaultWebSessionManager sessionManager(){DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();//把SessionDao绑定给会话管理器sessionManager.setSessionDAO(redisSessionDao()); sessionManager.setSessionValidationSchedulerEnabled(false);sessionManager.setSessionIdCookieEnabled(true);sessionManager.setSessionIdCookie(sessionIdCookie());sessionManager.setGlobalSessionTimeout(3600000);return sessionManager;}//4.创建安全管理器@Beanpublic SecurityManager defaultWebSecurityManager() {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();securityManager.setRealm(getRealm());securityManager.setSessionManager(sessionManager());return securityManager;}/*** 5.保证实现了Shiro内部lifecycle函数的bean执行*/@Bean(name = "lifecycleBeanPostProcessor")public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {return new LifecycleBeanPostProcessor();}/*** 6.开启对shiro注解的支持* AOP式方法级权限检查*/@Bean@DependsOn("lifecycleBeanPostProcessor")public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);return defaultAdvisorAutoProxyCreator;}/*** 7.配合DefaultAdvisorAutoProxyCreator事项注解权限校验*/@Beanpublic AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor() {AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();authorizationAttributeSourceAdvisor.setSecurityManager(defaultWebSecurityManager());return authorizationAttributeSourceAdvisor;}/** 8.配置shiro的过滤器工厂再web程序中,shiro进行权限控制全部是通过一组过滤器集合进行控制* */@Beanpublic ShiroFilterFactoryBean shiroFilter(){// 1.创建过滤工厂ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();// 2.设置安全管理器filterFactoryBean.setSecurityManager(defaultWebSecurityManager());// 3.通用配置(跳转登录页面,为授权跳转的页面)filterFactoryBean.setLoginUrl("/autherror");//4.设置过滤器集合//key = 拦截的url地址//value = 过滤器类型LinkedHashMap<String, String> filterMap = new LinkedHashMap<>();filterMap.put("/login","anon");//当前请求地址可以匿名访问filterMap.put("/user/**","authc");filterFactoryBean.setFilterChainDefinitionMap(filterMap);return filterFactoryBean;} }
-
相关文章:

SpringBoot--中间件技术-4:整合Shiro,Shiro基于会话SessionManager实现分布式认证,附案例含源代码!
SpringBoot整合安全中间件Shiro 技术栈:SpringBootShiro 代码实现 pom文件加坐标 Springboot版本选择2.7.14 ;java版本1.8 ; shiro做了版本锁定 1.3.2 <properties><java.version>1.8</java.version><!--shiro版本锁定…...
【QT基础入门】QT中的容器类
QT中有多种容器类,它们可以用来存储和操作不同类型的数据。根据容器的特性和用途,可以分为以下几类: 序列容器 这些容器按照一定的顺序存储数据,可以通过下标或迭代器访问。QT中的序列容器有: QList: 这是最通用的序列容器,它在内部实现为一个数组列表,可以快速地在头…...

IDEA没有Add Framework Support解决办法
点击File—>Settings 点击第一个设置快捷键 点击apply和ok即可 我们要点击一下项目,再按快捷键ctrlk 即可...

《009.SpringBoot之汽车租赁系统》
《009.SpringBoot之汽车租赁系统》 项目简介 [1]本系统涉及到的技术主要如下: 推荐环境配置:DEA jdk1.8 Maven MySQL 前后端分离; 后台:SpringBootMybatisPlus; 前台:Layuivue; [2]功能模块展示: 前端门户 1.登录&a…...

第四代智能井盖传感器,万宾科技助力城市安全
在迈向更为智能化、相互联系更为紧密的城市发展过程中,智能创新产品无疑扮演了一种重要的角色。智能井盖传感器作为新型科学技术产物,不仅解决传统井盖管理难的问题,也让城市变得更加安全美好,是城市生命线的一层重要保障。这些平…...
ClickHouse 面试题
文章目录 什么是 ClickHouse?ClickHouse 有哪些应用场景?ClickHouse 列式存储的优点有哪些?ClickHouse 的缺点是是什么?ClickHouse 的架构是怎样的?ClickHouse 的逻辑数据模型?ClickHouse 的核心特性&#…...

Python代码运行速度提升技巧!Python远比你想象中的快~
文章目录 前言一、使用内置函数二、字符串连接 VS join()三、创建列表和字典的方式四、使用 f-Strings五、使用Comprehensions六、附录- Python中的内置函数总结关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项…...

P6入门:项目初始化11-项目详情之计算Calculations
前言 使用项目详细信息查看和编辑有关所选项目的详细信息,在项目创建完成后,初始化项目是一项非常重要的工作,涉及需要设置的内容包括项目名,ID,责任人,日历,预算,资金,分类码等等&…...

<MySQL> 查询数据进阶操作 -- 联合查询
目录 一、什么是笛卡尔积? 二、什么是联合查询? 三、内连接 3.1 简介 3.2 语法 3.3 更多的表 3.4 操作演示 四、外连接 4.1 简介 4.2 语法 4.3 操作演示 五、自连接 5.1 简介 5.2 自连接非必要不使用 六、子查询(嵌套查询) 6.1 简介 6.…...
centos 6.10 安装 svn1.14.2
安装 apr 和 apr-util 下载地址 我下载的分别是 apr-1.7.4 和 apr-unit-1.6.3 常规的安装步骤 ./configure --prefix/usr/local/xxx make && make install注意要先安装 apr 再安装 apr-unit-1.6.3 安装 lz4 下载地址 要配置好环境变量,不然可能还是找…...

Java实现俄罗斯方块
规则 1.方块会从上方缓慢下落,玩家可以通过键盘上的上下左右键来控制方块。 2.方块移到区域最下方或是着地到其他方块上无法移动时,就会固定在该处,而新的方块出现在区域上方开始落下。 3.当区域中某一列横向格子全部由方块填满,…...

【计算思维】少儿编程蓝桥杯青少组计算思维题考试真题及解析B
STEMA考试-计算思维-U8级(样题) 1.浩浩的左⼿边是( )。 A.兰兰 B.⻉⻉ C.⻘⻘ D.浩浩 2.2时30分,钟⾯上时针和分针形成的⻆是什么⻆?( ) A.钝⻆ B.锐⻆ C.直⻆ D.平⻆ 3.下⾯是⼀年级同学最喜欢的《⻄游记》…...

第三章 栈和队列【24王道数据结构笔记】
1.栈 1.1 栈的基本概念 只允许在一端(栈顶top)进行插入或删除操作的受限的线性表。后进先出(Last In First Out)LIFO。或者说先进后出FILO。 进栈顺序:a1 > a2 > a3 > a4 > a5出栈顺序:a5 > a4 > a3 > a2 …...

保姆级教程之SABO-VMD-CNN-SVM的分类诊断,特征可视化
今天出一期基于SABO-VMD-CNN-SVM的分类诊断。 依旧是采用经典的西储大学轴承数据。基本流程如下: 首先是以最小包络熵为适应度函数,采用SABO优化VMD的两个参数。其次对每种状态的数据进行特征向量的求取,并为每组数据打上标签。然后将数据送入…...
跳跃游戏(贪心思想)
题解 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。 输入样例 示例 1…...

【JavaSE语法】类和对象(二)
六、 封装 6.1 封装的概念 面向对象程序三大特性:封装、继承、多态。而类和对象阶段,主要研究的就是封装特性。 封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互…...
【SA8295P 源码分析 (三)】121 - MAX9295A 加串器芯片手册分析 及初始化参数分析
【SA8295P 源码分析】121 - MAX9295A 加串器芯片手册分析 及初始化参数分析 一、MAX9295A 芯片特性1.1 GPIO 引脚说明1.2 功能模块框图1.3 时序分析1.3.1 GMSL2 Lock Time:25 ms1.3.2 视频初始化延时:1.1ms + 17000 x t(PCLK)1.3.3 High-Speed Data Transmission in Bursts1.…...

Maya 2024 for Mac(3D建模软件)
Maya 2024是一款三维计算机图形软件,具有强大的建模、动画、渲染、特效等功能,广泛应用于影视、游戏、广告等行业。以下是Maya 2024软件的主要功能介绍: 建模:Maya 2024具有强大的建模工具,包括多边形建模、曲面建模、…...
9. 深度学习——GAN
机器学习面试题汇总与解析——GAN 本章讲解知识点 从 GAN 讲起本专栏适合于Python已经入门的学生或人士,有一定的编程基础。本专栏适合于算法工程师、机器学习、图像处理求职的学生或人士。本专栏针对面试题答案进行了优化,尽量做到好记、言简意赅。这才是一份面试题总结的正…...
BeanUtils中的copyProperties方法使用
一、Beanutils中的copyProperties是我们在日常开发中常用的一个方法。 作用: 将a实体类中的属性赋值到b实体类中相对于的字段上 1.我们前端传参的时候我们后端通常会用vo实体类来接收,但是更新数据库的时候需要用do去操作 2.我们将vo的属性copy到do中可…...

超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...

AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...

python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...

解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...