SpringBoot整合JWT+Spring Security+Redis实现登录拦截(二)权限认证

上篇博文中我们已经实现了登录拦截,接下来我们继续补充代码,实现权限的认证

一、RBAC权限模型

        什么事RBAC权限模型?

        RBAC权限模型(Role-Based Access Control)即:基于角色的权限访问控制。在RBAC中,权限与角色关联,用户通过赋予角色而获得相应角色的权限。故我们需要如下几张表:

        用户表:系统接口及访问的操作者

        权限表:能够访问某接口或者做某操作的授权资格

        角色表:具有一类相同操作权限的用户的总称

        用户角色表:用户角色相关联的表

        角色权限表:角色与权限相关联的表

二、创建对应的数据库表

        可根据项目需要增加或删减、修改对应的表字段

        sys_user

DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user`  (
  `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'ID',
  `nick_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '昵称',
  `user_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名',
  `gender` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '性别',
  `phone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '手机号码',
  `email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱',
  `role_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '角色ID',
  `is_admin` bit(1) NULL DEFAULT b'0' COMMENT '是否为admin账号',
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码',
  `enabled` bit(1) NULL DEFAULT NULL COMMENT '是否启用',
  `create_by` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建者',
  `update_by` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新者',
  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期',
  `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统用户' ROW_FORMAT = Compact;

SET FOREIGN_KEY_CHECKS = 1;

 sys_role

DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role`  (
  `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'ID',
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '名称',
  `level` int(0) NULL DEFAULT NULL COMMENT '角色级别',
  `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述',
  `create_by` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建者',
  `update_by` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新者',
  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期',
  `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色表' ROW_FORMAT = Compact;

SET FOREIGN_KEY_CHECKS = 1;

sys_menu

DROP TABLE IF EXISTS `sys_menu`;
CREATE TABLE `sys_menu`  (
  `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'ID',
  `pid` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '上级菜单ID',
  `sub_count` int(0) NULL DEFAULT 0 COMMENT '子菜单数目',
  `type` int(0) NULL DEFAULT NULL COMMENT '菜单类型',
  `title` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单标题',
  `menu_sort` int(0) NULL DEFAULT NULL COMMENT '排序',
  `icon` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '图标',
  `path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '链接地址',
  `cache` bit(1) NULL DEFAULT b'0' COMMENT '缓存',
  `hidden` bit(1) NULL DEFAULT b'0' COMMENT '隐藏',
  `permission` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '权限',
  `create_by` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建者',
  `update_by` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新者',
  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期',
  `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 118 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统菜单' ROW_FORMAT = Compact;

SET FOREIGN_KEY_CHECKS = 1;

sys_user_role

DROP TABLE IF EXISTS `sys_users_roles`;
CREATE TABLE `sys_users_roles`  (
  `user_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户ID',
  `role_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色ID',
  PRIMARY KEY (`user_id`, `role_id`) USING BTREE,
  INDEX `user_id`(`user_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户角色关联' ROW_FORMAT = Compact;

SET FOREIGN_KEY_CHECKS = 1;

sys_role_menu

DROP TABLE IF EXISTS `sys_roles_menus`;
CREATE TABLE `sys_roles_menus`  (
  `role_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色ID',
  `menu_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '菜单ID',
  PRIMARY KEY (`role_id`, `menu_id`) USING BTREE,
  INDEX `FKcngg2qadojhi3a651a5adkvbq`(`role_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色菜单关联' ROW_FORMAT = Compact;

SET FOREIGN_KEY_CHECKS = 1;

三、生成5张基础表对应的Java代码

        可自行书写或使用mybatis工具进行生成,也可参考之前的博文

mybatis-plus自动生成代码(整理版)_mybatisplus代码自动生成-CSDN博客文章浏览阅读111次。整理版,添加了注释模版,常用基础方法。也可直接替换成公共的或自己代码中自定义的。仅提供基础方法,可根据具体需求自行改造。仅提供基础方法,可根据具体需求自行改造。仅提供基础方法,可根据具体需求自行改造。_mybatisplus代码自动生成https://blog.csdn.net/shaogaiyue9745602/article/details/134525030?spm=1001.2014.3001.5502

四、鉴权实现

  1.创建PermissionMapper.xml

           变现sql根据用户ID查询角色对应的权限

<?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.hng.mapper.PermissionMapper">
    <select id="selectPermsByUserId" resultType="java.lang.String">
        SELECT
            DISTINCT m.permission
        FROM
            sys_users_roles ur
            LEFT JOIN sys_role r ON ur.role_id = r.id
            LEFT JOIN sys_roles_menus	rm ON ur.role_id = rm.role_id
            LEFT JOIN sys_menu m ON m.id = rm.menu_id
        WHERE
            user_id = #{userId}
    </select>
</mapper>

2.创建PermissionMapper

package com.hng.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hng.entity.SysMenu;

import java.util.List;

/**
 * <p>
 * 系统菜单 Mapper 接口
 * </p>
 *
 * @author 郝南过
 * @since 2023-12-19
 */
public interface PermissionMapper extends BaseMapper<SysMenu> {

    List<String> selectPermsByUserId(String userId);
}

3.改造SecurityUser

    (1)改造构造函数增加权限集合

    private List<String> permissions;

    public SecurityUser(SysUser user, List<String> permissions) {
        this.user = user;
        this.permissions = permissions;
    }

    (2)改造getAuthorities

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        //将permissions中的String类型的权限信息封装成SimpleGrantedAuthority对象
        if(authorities!=null){
            return authorities;
        }
        authorities = permissions.stream()
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toList());
        return authorities;
    }

 4.改造UserDetailsServiceImpl

        修改loadUserByUsername方法,使用Permission增加权限查询

package com.hng.config.security;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hng.config.exception.customize.EntityNotFoundException;
import com.hng.modules.system.entity.SysUser;
import com.hng.modules.system.mapper.PermissionMapper;
import com.hng.modules.system.mapper.SysMenuMapper;
import com.hng.modules.system.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * @Author: 郝南过
 * @Description: 将Security拦截的用户名密码改为数据库中已有的用户名密码,Security自己校验密码,默认使用PasswordEncoder,格式为{id}password(id代表加密方式),
 * 一般不采用此方式,SpringSecurity提供了BcryptPasswordEncoder,只需将此注入到spring容器中。SpringSecurity就会使用它进行替换校验
 * @Date: 2023/12/11 11:29
 * @Version: 1.0
 */
@Service
@Slf4j
public class UserDetailsServiceImpl implements UserDetailsService {

    @Resource
    private SysUserService sysUserService;

    @Resource
    private PermissionMapper permissionMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //查询用户信息
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(SysUser::getUserName,username);
        SysUser user = sysUserService.getOne(queryWrapper);
        if(Objects.isNull(user)){
            throw new RuntimeException("用户名或密码错误");
        }
        //查询授权信息
        List<String> permissions = permissionMapper.selectPermsByUserId(user.getId());
        //判断用户是否是管理员,如果是管理员添加admin权限
        if(user.getIsAdmin()){
            permissions.add("admin");
        }
        return new SecurityUser(user,permissions);
    }
}

5.自定义权限检测

      可直接使用已有的权限检测@PreAuthorize(“hasAuthority('自定义字符串')”),hasAuthority是系统提供的,可直接使用,也可以自定义。以下为自定义,为方便直接判断admin用户,并给admin用户授予所有权限。

PermissionConfig
package com.hng.config.security;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

/**
 * 自定义权限检测
 */
@Component(value = "ex")
public class PermissionConfig {

    public Boolean check(String... permissions) {
        // 获取当前用户的所有权限
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        SecurityUser securityUser = (SecurityUser) authentication.getPrincipal();
        List<String> exPermissions = securityUser.getPermissions();
        // 判断当前用户的所有权限是否包含接口上定义的权限
        return exPermissions.contains("admin") || Arrays.stream(permissions).anyMatch(exPermissions::contains);
    }
}

6.在SecurityConfig中添加注解

@EnableGlobalMethodSecurity(prePostEnabled = true)//开启权限权限认证

7.在Cotroller中添加对应的权限字符

        如果未自定义权限检测使用注解@PreAuthorize(“hasAuthority('自定义字符串')”),本篇博文中的例子已经自定义为@PreAuthorize("@ex.check('自定义字符串')")

  SysUserController 示例

package com.hng.controller;

import lombok.RequiredArgsConstructor;
import io.swagger.annotations.ApiOperation;
import com.hng.config.response.ResponseResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import io.swagger.annotations.ApiParam;

import com.hng.entity.SysUser;
import com.hng.service.SysUserService;


/**
 * <p>
 * 系统用户 前端控制器
 * </p>
 */
@Slf4j
@Api(value = "SysUser", tags = "SysUser")
@RestController
@RequiredArgsConstructor //Lombok的一个注解,简化@Autowired
@RequestMapping("/sys-user")
public class SysUserController {

    private final SysUserService sysUserService;
    
    @PostMapping("/getList")
    @ApiOperation("sysUser列表查询")
    @PreAuthorize("@ex.check('SysUser:list')")
    public ResponseResult queryAllSysUser(@Validated @RequestBody SysUser sysUser){
        List<SysUser> list = sysUserService.queryAll(sysUser);
        return ResponseResult.success(list);
    }

    @PostMapping("/add")
    @ApiOperation("新增SysUser")
    @PreAuthorize("@ex.check('SysUser:add')")
    public ResponseResult addSysUser(@Validated @RequestBody SysUser sysUser){
        sysUserService.addSysUser(sysUser);
        return ResponseResult.success();
    }

    /**
     * 根据ID查询数据
     * @param id ID
     */
    @GetMapping("getById/{id}")
    @ApiOperation("sysUser根据Id查询")
    @ResponseBody
    @PreAuthorize("@ex.check('SysUser:getById')")
    public ResponseResult getById(@PathVariable Integer id) {
        return ResponseResult.success(sysUserService.getSysUserById(id));
    }

    /**
     * 更新数据
     * @param sysUser 实体对象
     */
    @PutMapping("update")
    @ApiOperation("sysUser更新")
    @ResponseBody
    @PreAuthorize("@ex.check('SysUser:edit')")
    public ResponseResult update(@Validated @RequestBody SysUser sysUser) {
        sysUserService.updateSysUser(sysUser);
        return ResponseResult.success();
    }

    /**
     * 删除数据
     * @param id ID
     */
    @DeleteMapping("delete/{id}")
    @ApiOperation("sysUser根据Id删除")
    @ResponseBody
    @PreAuthorize("@ex.check('SysUser:del')")
    public ResponseResult delete(@PathVariable Integer id) {
        sysUserService.deleteSysUser(id);
        return ResponseResult.success();
    }

}

五.数据库中添加数据

        根据自己定义的权限字符串与用户进行数据添加

六.测试

        使用pomstman进行测试,注此时可以测试上篇博文中的权限认证异常处理器

 【demo示例代码】

https://download.csdn.net/download/shaogaiyue9745602/88661442icon-default.png?t=N7T8https://download.csdn.net/download/shaogaiyue9745602/88661442

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL——进阶篇

二、进阶篇&#x1f6a9; 1. 存储引擎&#x1f346; 1.1 MSQL体系结构 连接层&#xff1a; 连接处理&#xff0c;连接认证&#xff0c;每个客户端的权限 服务层&#xff1a; 绝大部分核心功能&#xff0c;可跨存储引擎 可插拔存储引擎&#xff1a; 需要的时候可以添加或拔掉…

代码随想录算法训练营第二十七天|组合总和等

77 组合 1 描述 给定两个整数 n 和 k&#xff0c;返回 1 ... n 中所有可能的 k 个数的组合。 示例: 输入: n 4, k 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ] 2 代码 class Solution:def combine(self, n: int, k: int) -> List[List[int]]:path []rst…

新型智慧城市解决方案:PPT全文56页,附下载

关键词&#xff1a;智慧城市解决方案&#xff0c;智慧城市管理技术&#xff0c;智慧城市建设&#xff0c;数字城市建设 一、智慧城市宏观形势 1、政策支持&#xff1a;出台了一系列政策&#xff0c;鼓励和支持智慧城市的发展。这些政策为智慧城市的建设提供了政策保障和资金支…

网络安全法规和模型

基础 ISO信息安全&#xff1a;为数据处理系统建立和采取技术、管理的安全保护&#xff0c;保护计算机硬件、软件、数据不因偶然的或恶意的原因而受到破坏、更改、泄露 信息安全属性&#xff1a; CIA三元组&#xff1a;保密性、完整性、可用性 其他属性&#xff1a;真实性、不…

2023-12-25 事业-代号s-shein分析

前阵子SHEIN看的比较多,几乎把市面上的报告和趋势都研究了下,总结了这篇关于SHEIN的一切,从0开始全面的了解下SHEIN,比较通俗易懂,可以看看。 如果你还不了解SHEIN这家公司,想知道知道,可以翻看下,快速get这家公司的点如果你想了解下这家公司怎么发展和快速提升的,可以…

16路彩灯控制器 FPGA-Verilog

#16路彩灯控制器 FPGA-Verilog# 1、Verilog代码编写 1.1输入输出信号确定 题目要求多路彩灯控制器通过对应的开关按钮&#xff0c;能够控制多个彩灯的输出状态&#xff0c;组合多种变幻的灯光效果。 彩灯控制器的功能描述为&#xff1a; 设计一个多路彩灯控制器&#xff0…

Word-表格法对齐公式(手把手教学,公式格式从此不再愁)

新建word文件 1&#xff09;鼠标点击【插入】—>【表格】,选择31列的表格 2&#xff09;鼠标置于中间表格&#xff0c;快捷键输入Alt&#xff0c;进入公式编辑器中&#xff0c;输入任意字母&#xff0c;如&#xff1a;A&#xff0c;点击居中即可。 3&#xff09;第三列表…

飞天使-k8s知识点7-kubernetes升级

文章目录 验证新版本有没有问题需要安装的版本微微 1.20.6.0kubeadm upgrade plan 验证新版本有没有问题 查看可用版本的包 现有的状态 查看版本 yum list kubeadm --showduplicates |grep 1.20 yum list kubelet --showduplicates |grep 1.20 yum list kubectl --showduplic…

代码随想录第四十天(一刷C语言)|单词拆分

创作目的&#xff1a;为了方便自己后续复习重点&#xff0c;以及养成写博客的习惯。 单词拆分 思路&#xff1a;参考carl文档 动规五部曲分析如下&#xff1a; 1、确定dp数组以及下标的含义&#xff1a;dp[i] : 字符串长度为i的话&#xff0c;dp[i]为true&#xff0c;表示可…

DG报错ORA-01111、ORA-01110、ORA-01111备库不同步

刚同步好没多久的dg备库&#xff0c;过两天查看同步状态发现备库数据不同步&#xff0c;重新开启同步也不能正常同步。 查看alert日志&#xff0c;查看报错如下&#xff1a; MRP0: Background Media Recovery terminated with error 1111 Errors in file D:\APP\ADMINISTRATOR…

【IDEA】try-catch自动生成中修改catch的内容

编辑器 --> 文件和代码模板 --> 代码 --> Catch Statement Body

用Disruptor框架实现生产者-消费者模式

ConcurrentLinkedQueue队列的秘诀就在于大量使用了无锁CAS操作。 现成的Disruptor框架实现CAS进行编程。 无锁的缓存框架&#xff1a;Disruptor 它使用无锁的方式实现了一个环形队列&#xff0c;非常适合实现生产者-消费者模式&#xff0c; 比如事件和消息的发布。如果队列是环…

【网络安全 | 网络协议】结合Wireshark讲解TCP三次握手

TCP三次握手在Wireshark数据包中是如何体现的&#xff1f;在此之前&#xff0c;先熟悉TCP三次握手的流程。 TCP三次握手流程 TCP&#xff08;传输控制协议&#xff09;是一种面向连接的、可靠的传输层协议。在建立 TCP 连接时&#xff0c;需要进行三次握手&#xff0c;防止因为…

Python 直方图的绘制-`hist()`方法(Matplotlib篇-第7讲)

Python 直方图的绘制-hist()方法(Matplotlib篇-第7讲)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹…

【MySQL】脏读、不可重复读、幻读介绍及代码解释

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a; 数 据 库 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 结语 我的其他博客 前言 数据库事务隔离级别是关系数据库管理系统中一个重要的概念&#xff0c;它涉及到多个事务并发执行…

14、Qt使用Eigen3

一、下载Eigen Eigen 二、创建项目 创建一个"Qt Widget Application"项目&#xff0c;基类选择“QMainWindow“&#xff0c;把Eigen拷贝到项目中 三、更改代码 在.pro中添加 INCLUDEPATH $$PWD\Eigen 在界面上添加一个pushButton&#xff0c;并转到槽&#xff0…

SpringIOC之AbstractResourceBasedMessageSource

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

simulink代码生成(四)——SCI发送模块(串口通信)

C2000中的SCI模块分为两种&#xff0c;一种是接收模块&#xff0c;一种是发送模块&#xff1b; 1 发送模块 发送模块如下图所示&#xff1a; SCI传输块使用指定的SCI硬件模块传输标量或矢量数据。采样率和数据类型是与输入端口一致&#xff1b; 注意&#xff1a;一个模型只能…

让某个页面一直处于最前面,可以屏蔽切屏检测

前言 学习通智慧树网课分屏&#xff0c;让某个页面一直处于最前面&#xff0c;可以屏蔽切屏检测。 页面一直处于最前面 前言1 安装包2 使用 1 安装包 https://download.csdn.net/download/qq_44850489/76684366 2 使用 一直下一步就可以 选择要放到前面的窗口&#xff0c…

【SSM】Spring MVC

Spring MVC 文章目录 Spring MVC1. 简介2. 核心组件与调用流程3. 入门使用4. SpringMVC接收数据4.1 访问路径设置4.2 接收参数&#xff08;重点&#xff09;4.2.1 param 和 json参数比较4.2.2 param参数接收4.2.3 路径参数接收4.2.4 json参数接收 4.3 接收Cookie数据和接收请求…