当前位置: 首页 > news >正文

Springboot整合shiro

导入依赖

   <!--    引入springboot的web项目的依赖        --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
​
<!--    shiro    --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring-boot-web-starter</artifactId><version>1.12.0</version></dependency>

配置类

package com.qf.shiro2302.config;
​
import com.qf.shiro2302.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
​
import java.util.Arrays;
import java.util.List;
​
@Configuration
@Slf4j
public class ShiroConfig {
​
​
​@Beanpublic Realm realm(){AuthorizingRealm authorizingRealm = new AuthorizingRealm() {
​/**** @param token 这的token就是调用login方法时,传入的token对象* @return AuthenticationInfo 对象中,封装了用户的身份信息(principals),密码(credentials),提供信息的realm的名字* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {System.out.println("===========获取身份信息===============");//查询数据库获取当前用户名对应的User对象String username = (String) token.getPrincipal();System.out.println("username="+username);System.out.println("this.getName()={}"+this.getName());User user=getUserFromDB(username);
​//需要返回shiro规定的AuthenticationInfo类型的对象//这个对象中,包含了用户的身份认证信息// SimpleAuthenticationInfo的构造函数中的第一个参数,principals代表用户的身份信息// 一般可以使用 user对象,或者使用用户名也可以// 第三个参数,代表当前realm的名字,固定写法//Authentication 证明的意思SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
​return authenticationInfo;}
​@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {System.out.println("============获取授权===============");
​// 从数据库表中查询当前用户具有的角色和权限字符串User user = (User) principalCollection.getPrimaryPrincipal();
​List<String> roles= getRolesFromDB(user);List<String> permissions= getPermissionFromDB(user);
​// 按照约定返回AuthorizationInfo对象SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();// 放入从数据库中查询到的当前用户的角色信息
//                authorizationInfo.addRole("test");authorizationInfo.addRoles(roles);
​// 放入从数据库中查询到的当前用户的权限信息
//             authorizationInfo.addStringPermission("document:read");authorizationInfo.addStringPermissions(permissions);return authorizationInfo;}};
​
​return authorizingRealm;
​
​}
​private List<String> getRolesFromDB(User user) {return Arrays.asList("test","admin");}
​private List<String> getPermissionFromDB(User user) {return Arrays.asList("document:read","document:write");}
​private User getUserFromDB(String username) {User user = new User(100, "数据库用户", "123456", "123@qq.com");return user;}
​@Beanpublic ShiroFilterChainDefinition shiroFilterChainDefinition() {//ShiroFilterChainDefinition 此接口就一个实现类  默认Shiro过滤器链定义类DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
​// 让登录接口直接被shiro的过滤器放行//第一个参数:接口的路径//第二个参数:shiro内部的过滤器的名字,anon代表无需登录即可访问的特殊的过滤器,注意过滤器的名字是固定的,不能乱写chainDefinition.addPathDefinition("/login/dologin", "anon");// 放行springboot的错误页面的请求url  这个页面就是个response拼接的页面chainDefinition.addPathDefinition("/error", "anon");
​
​//增加角色或者权限,对于某些请求// logged in users with the 'test' role
//        chainDefinition.addPathDefinition("/test/**", "authc, roles[test,admin], perms[document:read,document:write]");  这个如果改成anon,就不能加后面的角色或者权限,否则,将会被认为需要登录,重定向到登录页
​// all other paths require a logged in userchainDefinition.addPathDefinition("/**", "authc");return chainDefinition;}
}

调用接口

package com.qf.shiro2302.controller;
​
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
​
@RestController
@RequestMapping("/login")
@Slf4j
public class LoginController {
​@PostMapping("/dologin")public String dologin(String username,String password){
​//使用Shiro进行登录处理Subject subject = SecurityUtils.getSubject();//获取shiro核心对象//为了调用shiro的登录方法,需要准备一个Token对象UsernamePasswordToken token = new UsernamePasswordToken(username,password);System.out.println(token);subject.login(token);//使用shiro登录流程
​return "登陆成功 ";
​
​}
​
}

获取ShiroSession中的用户,注解添加权限

package com.qf.shiro2302.controller;
​
import com.qf.shiro2302.entity.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
​
@RestController
@RequestMapping("/test")
public class TestController {
​
​@RequiresRoles({"test","admin"})@RequiresPermissions({"document:read","document:write"})@RequestMapping("/test1")public String hello1(){return "hello shiro !!!";}
​
​@RequestMapping("/test2")public User hello2(){//如果使用shiro获取当前登录用户的身份信息Subject subject = SecurityUtils.getSubject();User principal = (User) subject.getPrincipal();System.out.println(principal);return principal;}
}
shiro:loginUrl: /login.html#配置没登陆的时候重定向的页面。这个请求是可以放行的

优化整合shiro,登录密码MD5Hash加密,内置处理

1.配置类

package com.qf.shiroHomework.config;
​
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qf.shiroHomework.entity.*;
import com.qf.shiroHomework.mapper.TPersMapper;
import com.qf.shiroHomework.mapper.TRoleMapper;
import com.qf.shiroHomework.mapper.TRolePermsMapper;
import com.qf.shiroHomework.mapper.TUserRoleMapper;
import com.qf.shiroHomework.service.ITUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
​
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
​
@Configuration
@Slf4j
public class ShiroConfig {
​@Autowiredprivate ITUserService itUserService;@Autowiredprivate TUserRoleMapper tUserRoleMapper;@Autowiredprivate TRolePermsMapper tRolePermsMapper;@Autowiredprivate TPersMapper tPersMapper;@Autowiredprivate TRoleMapper tRoleMapper;
​//将Realm对象放入IOC容器里@Beanpublic Realm realm(){AuthorizingRealm authorizingRealm = new AuthorizingRealm() {
​/**** @param token 这的token就是调用login方法时,传入的token对象* @return AuthenticationInfo 对象中,封装了用户的身份信息(principals),密码(credentials),提供信息的realm的名字* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {System.out.println("===========获取身份信息===============");//获取身份信息String username = (String) token.getPrincipal();
​QueryWrapper<TUser> wrapper = new QueryWrapper<>();wrapper.eq("username",username);TUser user = itUserService.getOne(wrapper);
​// 需要返回shiro规定的AuthenticationInfo类型的对象// 这个对象中,包含了用户的身份认证信息// SimpleAuthenticationInfo的构造函数中的第一个参数,principals代表用户的身份信息// 一般可以使用 user对象,或者使用用户名也可以// 第三个参数: 盐// 第四个参数,代表当前realm的名字,就是一个标识,标识是这个Bean调用的这个方法,没有作用,固定写法
​SimpleAuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo(user,user.getPassword(), ByteSource.Util.bytes(user.getSalt()),this.getName());
​return authenticationInfo;}
​@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {TUser user = (TUser) principalCollection.getPrimaryPrincipal();SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo();log.info("用户角色={}",getRolesFromDB(user));log.info("用户权限={}",getPermissionFromDB(user));authorizationInfo.addRoles(getRolesFromDB(user));authorizationInfo.addStringPermissions(getPermissionFromDB(user));return authorizationInfo;}};
​// 把HashedCredentialsMatcher对象设置到authorizingRealm对象中authorizingRealm.setCredentialsMatcher(hashedCredentialsMatcher());
​return authorizingRealm;}
​
​@Beanpublic HashedCredentialsMatcher hashedCredentialsMatcher(){
​HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();//设置算法名称matcher.setHashAlgorithmName("md5");//设置hash次数matcher.setHashIterations(1024);return matcher;
​
​}
​
​
​
​//配置Shiro过滤器链@Beanpublic ShiroFilterChainDefinition shiroFilterChainDefinition(){DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();chainDefinition.addPathDefinition("/register.html","anon");chainDefinition.addPathDefinition("/error/500.html","anon");chainDefinition.addPathDefinition("/error","anon");chainDefinition.addPathDefinition("/user/register","anon");chainDefinition.addPathDefinition("/user/login","anon");chainDefinition.addPathDefinition("/user/**","authc");chainDefinition.addPathDefinition("/**","authc");
​
​return chainDefinition;
​}
​public List<String> getPermissionFromDB(TUser user) {if (user.getPerms()!=null){return user.getPerms();}
​
​Integer id = user.getId();//通过用户ID找到角色
​QueryWrapper<TUserRole> wrapper1 = new QueryWrapper<>();wrapper1.eq("userid",id);TUserRole tUserRole = tUserRoleMapper.selectOne(wrapper1);Integer roleid = tUserRole.getRoleid();System.out.println(roleid);
​
​QueryWrapper<TRolePerms> wrapper = new QueryWrapper<>();wrapper.select("permsid").eq("roleid",roleid);List<Object> permsidList = tRolePermsMapper.selectObjs(wrapper);System.out.println(permsidList);List<Integer> integers = permsidList.stream().map(o -> {return (Integer) o;}).collect(Collectors.toList());List<TPers> tPers = tPersMapper.selectBatchIds(integers);System.out.println(tPers);ArrayList<String> strings = new ArrayList<>();for (TPers tPer : tPers) {strings.add(tPer.getName());}user.setPerms(strings);
​return strings;}
​public List<String> getRolesFromDB(TUser user) {
​if (user.getRoleName()!=null){return user.getRoleName();}
​Integer id = user.getId();//通过用户ID找到角色QueryWrapper<TUserRole> wrapper1 = new QueryWrapper<>();wrapper1.eq("userid",id);TUserRole tUserRole = tUserRoleMapper.selectOne(wrapper1);Integer roleid = tUserRole.getRoleid();QueryWrapper<TRole> wrapper = new QueryWrapper<>();wrapper.select("name").eq("id",roleid);List<Object> roles = tRoleMapper.selectObjs(wrapper);List<String> strings = roles.stream().map(o -> {return (String) o;}).collect(Collectors.toList());user.setRoleName(strings);return strings;}
​
}

实体类

package com.qf.shiroHomework.entity;
​
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.util.List;
​
import lombok.*;
​
/*** <p>* * </p>** @author jmj* @since 2023-08-10*/
@NoArgsConstructor
@AllArgsConstructor
@Data
@TableName("t_user")
public class TUser implements Serializable {
​private static final long serialVersionUID = 1L;
​@TableId(value = "id", type = IdType.AUTO)private Integer id;
​private String username;
​private String password;
​private String salt;
​@TableField(exist = false) // 说明当前这个属性在数据库表中没有对应的字段,让mp生成sql时忽略这个属性private List<String> roleName;@TableField(exist = false)private List<String> perms;
​
​
​
​
}

Controller

//复杂密码匹配器@PostMapping("/login")public String login(TUser user){//使用Shiro进行登录处理Subject subject = SecurityUtils.getSubject();//获取shiro核心对象//为了调用shiro的登录方法,需要准备一个Token对象
​UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(user.getUsername(), user.getPassword());
​subject.login(usernamePasswordToken);
​return "redirect:/show.html";
​}

以前手写MD5处理的方法

//    简单密码匹配器方案
//    @PostMapping("/login")
//    public String login(TUser user){
//        //使用Shiro进行登录处理
//        Subject subject = SecurityUtils.getSubject();//获取shiro核心对象
//        //为了调用shiro的登录方法,需要准备一个Token对象
//        //添加Where 条件
//        QueryWrapper<TUser> wrapper = new QueryWrapper<>();
//        wrapper.eq("username",user.getUsername());
//        TUser u = itUserService.getOne(wrapper);
//        if (u==null){
//            return "redirect:/index.html";
//        }else {
//
//            //MD5加密
//            Md5Hash md5Hash = new Md5Hash(user.getPassword(), u.getSalt(), 1024);
//            String newPassword = md5Hash.toHex();
//
//
//            UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(user.getUsername(), newPassword);
//
//            subject.login(usernamePasswordToken);
//        }
//
//            return "redirect:/show.html";
//
//    }

相关文章:

Springboot整合shiro

导入依赖 <!-- 引入springboot的web项目的依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency> ​ <!-- shiro --><depende…...

阻塞/非阻塞、同步/异步(网络IO)

1.阻塞/非阻塞、同步/异步(网络IO) 【思考】典型的一次 IO 的两个阶段是什么&#xff1f; 数据就绪 和 数据读写 数据就绪 &#xff1a;根据系统 IO 操作的就绪状态 阻塞 非阻塞 数据读写 &#xff1a;根据应用程序和内核的交互方式 同步 异步 陈硕&#xff1a;在处理 IO …...

为什么大家会觉得考PMP没用?

一是在于PMP这套知识体系&#xff0c;是一套底层的项目管理逻辑框架&#xff0c;整体是比较抽象的。大家在学习工作之后&#xff0c;会有人告诉你很多职场的一些做事的规则&#xff0c;比如说对于沟通&#xff0c;有人就会告诉如何跟客户沟通跟同事相处等等&#xff0c;这其实就…...

AVR128单片机 USART通信控制发光二极管显示

一、系统方案 二、硬件设计 原理图如下&#xff1a; 三、单片机软件设计 1、首先是系统初始化 void port_init(void) { PORTA 0xFF; DDRA 0x00;//输入 PORTB 0xFF;//低电平 DDRB 0x00;//输入 PORTC 0xFF;//低电平 DDRC 0xFF;//输出 PORTE 0xFF; DDRE 0xfE;//输出 PO…...

为什么5G 要分离 CU 和DU?(4G分离RRU 和BBU)

在 Blog 一文中&#xff0c;5G--BBU RRU 如何演化到 CU DU&#xff1f;_5g rru_qq_38480311的博客-CSDN博客 解释了4G的RRU BBU 以及 5G CU DU AAU&#xff0c;主要是讲了它们分别是什么。但是没有讲清楚 为什么&#xff0c;此篇主要回答why。 4G 为什么分离基站为 RRU 和 BBU…...

Python中的数据输入

获取键盘输入 input语句 使用input()可以从键盘获取输入&#xff0c;使用一个变量来接收 print("你是谁&#xff1f;") name input() print(f"我知道了&#xff0c;你是{name}")# print("你是谁&#xff1f;") name input("你是谁&…...

cms系统稳定性压力测试出现TPS抖动和毛刺的性能bug【杭州多测师_王sir】

一、并发线程数100&#xff0c;分10个阶梯&#xff0c;60秒加载时间&#xff0c;运行1小时进行压测&#xff0c;到10分钟就出现如下 二、通过jstat -gcutil 16689 1000进行监控...

【UE】材质描边、外发光、轮廓线

原教学视频链接&#xff1a; ue4 材质描边、外发光、轮廓线_哔哩哔哩_bilibili 步骤 1. 首先新建一个材质&#xff0c;这里命名为“Mat_outLine” 在此基础上创建一个材质实例 2. 在视口中添加一个后期处理体积 设置后期处理体积为无限范围 点击添加一个数组 选择“资产引用”…...

百模大战,打响AI应用生态的新赛点

点击关注 文&#xff5c;郝鑫 黄小艺&#xff0c;编&#xff5c;刘雨琦 “宇宙中心”五道口&#xff0c;又泛起了昔日的光芒。 十字路口一角的华清嘉园里&#xff0c;各种互联网大佬们&#xff0c;王兴、程一笑、张一鸣等人的创业传说似乎还有余音&#xff0c;后脚搬进来的AI…...

【C++二叉树】进阶OJ题

【C二叉树】进阶OJ题 目录 【C二叉树】进阶OJ题1.二叉树的层序遍历II示例代码解题思路 2.二叉搜索树与双向链表示例代码解题思路 3.从前序与中序遍历序列构造二叉树示例代码解题思路 4.从中序与后序遍历序列构造二叉树示例代码解题思路 5.二叉树的前序遍历&#xff08;非递归迭…...

C++——vector:resize与reserve的区别,验证写入4GB大数据时相比原生操作的效率提升

resize和reserve的区别 reserve&#xff1a;预留空间&#xff0c;但不实例化元素对象。所以在没有添加新的对象之前&#xff0c;不能引用容器内的元素。而要通过调用push_back或者insert。 resize&#xff1a;改变容器元素的数量&#xff0c;且会实例化对象&#xff08;指定或…...

基础配置xml

# 配置端口 server.port8081# 文件上传配置 # 是否支持文件上传 spring.servlet.multipart.enabledtrue # 是否支持文件写入磁盘 spring.servlet.multipart.file-size-threshold0 # 上传文件的临时目录 spring.servlet.multipart.locationd:/opt/tmp # 最大支持上传文件大小 sp…...

win环境安装SuperMap iserver和配置许可

SuperMap iServer是我国北京超图公司研发的基于跨平台GIS内核的云GIS应用服务器产品&#xff0c;通过服务的方式&#xff0c;面向网络客户端提供与专业GIS桌面产品相同功能的GIS服务&#xff0c;能够管理、发布多源服务&#xff0c;包括REST服务、OGC服务等。 SuperMap iserve…...

【Apollo学习笔记】——规划模块TASK之PIECEWISE_JERK_NONLINEAR_SPEED_OPTIMIZER(一)

文章目录 TASK系列解析文章前言PIECEWISE_JERK_NONLINEAR_SPEED_OPTIMIZER功能介绍PIECEWISE_JERK_NONLINEAR_SPEED_OPTIMIZER相关配置PIECEWISE_JERK_NONLINEAR_SPEED_OPTIMIZER流程确定优化变量定义目标函数定义约束ProcessSetUpStatesAndBoundsOptimizeByQPCheckSpeedLimitF…...

pytest parametrize多参数接口请求及展示中文响应数据

编写登陆接口 app.py from flask import Flask, request, jsonify, Responseapp Flask(__name__)app.route(/login, methods[POST]) def login():username request.form.get(username)password request.form.get(password)# 在这里编写你的登录验证逻辑if username admin…...

电视连续剧 ffmpeg 批量去掉片头片尾

思路&#xff1a; 一、用python获取每集的总时长 二、把每集的时间&#xff0c;拼接成想要的ffmpeg的剪切命令命令。 1、用python获取每集的总时长 1&#xff0c;安装moviepy库&#xff0c;直接安装太慢&#xff0c;换成国内的源 pip install moviepy -i http://mirrors.aliyu…...

二进制搭建kubernetes

二进制搭建kubernetes 一、常见的K8S部署方式1.Minikube2.Kubeadmin3.二进制安装部署 二、二进制搭建K8S(单台master)1.部署架构规划2.系统初始化配置3.部署 docker引擎4.部署 etcd 集群4.部署 Master 组件5.部署 Worker Node 组件6.部署网络组件 三、负载均衡部署1.配置load b…...

TDengine函数大全-系统函数

以下内容来自 TDengine 官方文档 及 GitHub 内容 。 以下所有示例基于 TDengine 3.1.0.3 TDengine函数大全 1.数学函数 2.字符串函数 3.转换函数 4.时间和日期函数 5.聚合函数 6.选择函数 7.时序数据库特有函数 8.系统函数 系统函数 TDengine函数大全DATABASECLIENT_VERSIONSE…...

北京互联网营销服务商浩希数字科技申请1350万美元纳斯达克IPO上市

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;总部位于北京的互联网营销服务商浩希数字科技&#xff08;Haoxi Health Technology Limited &#xff09;近期已向美国证券交易委员会&#xff08;SEC&#xff09;提交招股书&#xff0c;申请在纳斯…...

ElementUI浅尝辄止22:Alert 警告

用于页面中展示重要的提示信息。 常见于消息提示或警告框。 1.如何使用&#xff1f; 页面中的非浮层元素&#xff0c;不会自动消失。 //Alert 组件提供四种主题&#xff0c;由type属性指定&#xff0c;默认值为info。<template><el-alerttitle"成功提示的文案&…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

Python 实现 Web 静态服务器(HTTP 协议)

目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1&#xff09;下载安装包2&#xff09;配置环境变量3&#xff09;安装镜像4&#xff09;node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1&#xff09;使用 http-server2&#xff09;详解 …...

【Linux系统】Linux环境变量:系统配置的隐形指挥官

。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量&#xff1a;setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...

Leetcode33( 搜索旋转排序数组)

题目表述 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...

全面解析数据库:从基础概念到前沿应用​

在数字化时代&#xff0c;数据已成为企业和社会发展的核心资产&#xff0c;而数据库作为存储、管理和处理数据的关键工具&#xff0c;在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理&#xff0c;到社交网络的用户数据存储&#xff0c;再到金融行业的交易记录处理&a…...

jdbc查询mysql数据库时,出现id顺序错误的情况

我在repository中的查询语句如下所示&#xff0c;即传入一个List<intager>的数据&#xff0c;返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致&#xff0c;会导致返回的id是从小到大排列的&#xff0c;但我不希望这样。 Query("SELECT NEW com…...