RBAC与连表查询

news2024/11/15 8:20:10

文章目录

  • 0. 前言
  • 1. RBAC模型
    • 1.1 什么是RBAC模型
    • 1.2 准备工作
  • 2. 连表操作
    • 2.1 常用连表图
    • 2.2 准备SQL语句
    • 2.3 Mybatis 连表
  • 3. 总结与补充

0. 前言

连表学习、练习经典:RBAC权限模型、5表联查。

本文采用的持久层实现方式:Mybatis/Mybatis-Plus。

学习基础: SQL基础。

学习目标:

  • 了解 RBAC 权限模型,建表
  • 学习并掌握连表操作

1. RBAC模型

1.1 什么是RBAC模型

RBAC(Role-BasedAccess Control),基于角色的访问控制。

简单来说,就是什么样的用户有什么样的权利,RBAC的一种经典的实现方式为:
用户-角色-权限,都是 N:N 的关系。本文的 Mybatis 联查练习就以RBAC模型为例。

详细概念可自行百度或者参阅下方的参考资料:
参考资料:
简书参考文章
知乎参考文章

1.2 准备工作

准备表
表结构与即将进行的关联关系:
表关系

建表语句

建库:

CTEATE database rbac_sys;
USE rbac_sys;

建菜单表、插入测试数据:

DROP TABLE IF EXISTS `sys_menus`;
CREATE TABLE `sys_menus`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '资源名称',
  `url` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '资源URL',
  `type` int(11) NULL DEFAULT NULL COMMENT '类型     1:菜单   2:按钮',
  `sort` int(11) NULL DEFAULT NULL COMMENT '排序',
  `note` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注',
  `parentId` int(11) NULL DEFAULT NULL COMMENT '父菜单ID,一级菜单为0',
  `permission` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '授权(如:user:create)',
  `createdTime` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
  `modifiedTime` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
  `createdUser` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建用户',
  `modifiedUser` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改用户',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 144 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '资源管理' ROW_FORMAT = Dynamic;

测试数据:

INSERT INTO `sys_menus` VALUES (8, '系统管理', '请求路径', 1, 8, NULL, NULL, '', '2017-07-12 15:15:59', '2020-01-12 14:11:15', 'admin', NULL);
INSERT INTO `sys_menus` VALUES (25, '日志管理', 'log/log_list', 1, 25, NULL, 8, 'sys:log:view', '2017-07-12 15:15:59', '2020-01-12 14:09:44', 'admin', NULL);
INSERT INTO `sys_menus` VALUES (45, '用户管理', 'user/user_list', 1, 45, NULL, 8, 'sys:user:view', '2017-07-12 15:15:59', '2020-01-12 14:10:10', 'admin', NULL);
INSERT INTO `sys_menus` VALUES (46, '菜单管理', 'menu/menu_list', 1, 46, NULL, 8, 'sys:menu:view', '2017-07-12 15:15:59', '2020-01-12 14:10:28', 'admin', NULL);
INSERT INTO `sys_menus` VALUES (47, '角色管理', 'role/role_list', 1, 47, NULL, 8, 'sys:role:view', '2017-07-12 15:15:59', '2020-01-12 14:10:48', 'admin', NULL);
INSERT INTO `sys_menus` VALUES (115, '查询', 'menu/doFindObjects', 2, 1, NULL, 46, 'sys:menu:view', '2017-07-13 16:33:41', '2020-01-12 14:21:29', NULL, NULL);
INSERT INTO `sys_menus` VALUES (116, '添加', 'menu/doSaveObject', 2, 2, NULL, 46, 'sys:menu:add', '2017-07-13 16:34:02', '2020-01-12 14:21:56', NULL, NULL);
INSERT INTO `sys_menus` VALUES (117, '修改', 'menu/doUpdateObject', 2, 3, NULL, 46, 'sys:menu:update', '2017-07-13 16:34:25', '2020-01-12 14:22:12', NULL, NULL);
INSERT INTO `sys_menus` VALUES (118, '删除', 'role/doDeleteObject', 2, 4, NULL, 46, 'sys:menu:delete', '2017-07-13 16:34:46', '2020-01-12 14:22:41', NULL, NULL);
INSERT INTO `sys_menus` VALUES (119, '查询', 'user/doFindPageObjects', 2, 1, NULL, 45, 'sys:user:view', '2017-07-13 16:35:05', '2020-01-12 14:20:28', NULL, NULL);
INSERT INTO `sys_menus` VALUES (120, '查询', 'role/doFindPageObjects', 2, 1, NULL, 47, 'sys:role:view', '2017-07-13 16:35:26', '2020-01-12 14:23:05', NULL, NULL);
INSERT INTO `sys_menus` VALUES (126, '新增', 'user/doSaveObject', 2, 2, NULL, 45, 'sys:user:add', '2017-07-21 11:11:34', '2020-01-12 14:20:45', NULL, NULL);
INSERT INTO `sys_menus` VALUES (127, '修改', 'user/doUpdateObject', 2, 3, NULL, 45, 'sys:user:update', '2017-07-21 11:11:56', '2020-01-12 14:21:05', NULL, NULL);
INSERT INTO `sys_menus` VALUES (128, '添加', 'role/doSaveObject', 2, 2, NULL, 47, 'sys:role:add', '2017-07-21 11:14:24', '2020-01-12 14:23:29', NULL, NULL);
INSERT INTO `sys_menus` VALUES (129, '修改', 'role/doUpdateObject', 2, 3, NULL, 47, 'sys:role:update', '2017-07-21 11:14:48', '2020-01-12 14:23:44', NULL, NULL);
INSERT INTO `sys_menus` VALUES (130, '删除', 'role/doDeleteObject', 2, 4, NULL, 47, 'sys:role:delete', '2017-07-21 11:15:09', '2020-01-12 14:24:05', NULL, NULL);
INSERT INTO `sys_menus` VALUES (131, '删除', 'log/doDeleteObjects', 2, 27, NULL, 25, 'sys:log:delete', '2020-01-10 17:34:31', '2020-01-10 17:34:31', NULL, NULL);
INSERT INTO `sys_menus` VALUES (137, '禁用启用', 'user/doValidById', 2, 123, NULL, 45, 'sys:user:update', '2020-01-12 09:34:58', '2020-01-12 09:34:58', NULL, NULL);
INSERT INTO `sys_menus` VALUES (138, '部门管理', 'dept/dept_list', 1, 100, NULL, 8, 'sys:dept:view', '2020-01-12 14:15:45', '2020-01-12 14:15:59', NULL, NULL);
INSERT INTO `sys_menus` VALUES (139, '添加', 'dept/doSaveObject', 2, 123, NULL, 138, 'sys:dept:add', '2020-01-12 14:16:33', '2020-01-12 14:16:33', NULL, NULL);
INSERT INTO `sys_menus` VALUES (140, '修改', 'dept/dept_edit', 1, 121, NULL, 138, 'sys:dept:update', '2020-01-12 14:17:14', '2020-01-12 14:17:14', NULL, NULL);
INSERT INTO `sys_menus` VALUES (141, '删除', 'dept/doDeleteObject', 1, 120, NULL, 138, 'sys:dept:delete', '2020-01-12 14:18:20', '2020-01-12 14:18:20', NULL, NULL);
INSERT INTO `sys_menus` VALUES (142, '查询', 'dept/doFindObjects', 1, 124, NULL, 138, 'sys:dept:view', '2020-01-12 14:19:01', '2020-01-12 14:19:01', NULL, NULL);
INSERT INTO `sys_menus` VALUES (143, '查询', 'log/doFindPageObjects', 2, 210, NULL, 25, 'sys:log:view', '2020-01-12 14:20:02', '2020-01-12 14:20:02', NULL, NULL);

建角色-菜单关联表并插入测试数据:

DROP TABLE IF EXISTS `sys_role_menus`;
CREATE TABLE `sys_role_menus`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `role_id` int(11) NULL DEFAULT NULL COMMENT '角色ID',
  `menu_id` int(11) NULL DEFAULT NULL COMMENT 'ID',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1308 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色与菜单对应关系' ROW_FORMAT = Dynamic;

测试数据:

INSERT INTO `sys_role_menus` VALUES (1250, 46, 8);
INSERT INTO `sys_role_menus` VALUES (1252, 46, 47);
INSERT INTO `sys_role_menus` VALUES (1253, 46, 120);
INSERT INTO `sys_role_menus` VALUES (1254, 46, 128);
INSERT INTO `sys_role_menus` VALUES (1255, 46, 129);
INSERT INTO `sys_role_menus` VALUES (1256, 46, 130);
INSERT INTO `sys_role_menus` VALUES (1294, 1, 8);
INSERT INTO `sys_role_menus` VALUES (1296, 1, 25);
INSERT INTO `sys_role_menus` VALUES (1297, 1, 131);
INSERT INTO `sys_role_menus` VALUES (1298, 1, 46);
INSERT INTO `sys_role_menus` VALUES (1299, 1, 115);
INSERT INTO `sys_role_menus` VALUES (1300, 1, 116);
INSERT INTO `sys_role_menus` VALUES (1301, 1, 117);
INSERT INTO `sys_role_menus` VALUES (1302, 1, 118);
INSERT INTO `sys_role_menus` VALUES (1303, 1, 47);
INSERT INTO `sys_role_menus` VALUES (1304, 1, 120);
INSERT INTO `sys_role_menus` VALUES (1305, 1, 128);
INSERT INTO `sys_role_menus` VALUES (1306, 1, 129);
INSERT INTO `sys_role_menus` VALUES (1307, 1, 130);

建角色表并插入测试数据:

DROP TABLE IF EXISTS `sys_roles`;
CREATE TABLE `sys_roles`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '角色名称',
  `note` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注',
  `createdTime` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
  `modifiedTime` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
  `createdUser` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建用户',
  `modifiedUser` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改用户',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 47 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色' ROW_FORMAT = Dynamic;

测试数据:

INSERT INTO `sys_roles` VALUES (1, '系统管理员', '系统管理员', '2017-07-13 17:44:11', '2020-01-12 09:54:51', 'admin', NULL);
INSERT INTO `sys_roles` VALUES (46, '软件工程师', '负责软件设计及研发', '2020-01-11 15:52:00', '2020-01-11 15:52:00', NULL, NULL);

建角色-用户关联表并插入测试数据:

DROP TABLE IF EXISTS `sys_user_roles`;
CREATE TABLE `sys_user_roles`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NULL DEFAULT NULL COMMENT '用户ID',
  `role_id` int(11) NULL DEFAULT NULL COMMENT '角色ID',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 70 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户与角色对应关系' ROW_FORMAT = Dynamic;

测试数据:

INSERT INTO `sys_user_roles` VALUES (68, 1, 1);
INSERT INTO `sys_user_roles` VALUES (69, 17, 46);

建用户表并插入测试数据:

DROP TABLE IF EXISTS `sys_users`;
CREATE TABLE `sys_users`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户名',
  `password` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码',
  `salt` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '盐  密码加密时前缀,使加密后的值不同',
  `email` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱',
  `mobile` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '手机号',
  `valid` tinyint(4) NULL DEFAULT NULL COMMENT '状态  0:禁用   1:正常  默认值 :1',
  `deptId` int(11) NULL DEFAULT NULL,
  `avatar` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户头像',
  `createdTime` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
  `modifiedTime` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
  `createdUser` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建用户',
  `modifiedUser` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改用户',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `username`(`username`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 18 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统用户' ROW_FORMAT = Dynamic;

测试数据:

INSERT INTO `sys_users` VALUES (1, 'admin', 'c4c33035c5d8e840616c128db9f87b25', '016a0948-b581-43aa-8a5f-9bb76a80e737', 'admin@t.cn', '13624356789', 1, 3, NULL, NULL, '2020-01-12 09:35:43', NULL, NULL);

SET FOREIGN_KEY_CHECKS = 1;

准备工程

在这里插入图片描述

依赖:

       <!--    SpringBoot 相关    -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--    MybatisPlus    -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>

        <!--   Mysql     -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!--    Lombok    -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency> 

application.yml配置:

spring:
  # 配置数据源
  datasource:
    url: jdbc:mysql://localhost:3306/rbac_sys?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true
    username: root
    password: root

实体类:

/**
 * 用户菜单实体类VO
 * @author: Sharry
 * @createTime: 2022/12/16 14:06
 * @version: Version-1.0
 */
@Data
public class SysUserMenuVO implements Serializable {

    private static final long serialVersionUID = -5812179473590409216L;
    
    /**
     * 用户名
     */
    private String name;

    /**
     * 菜单列表
     */
    private List<SysMenuVO> menus;
}
/**
 * 联查:用户权限菜单VO
 * @author: Sharry
 * @createTime: 2022/12/16 13:42
 * @version: Version-1.0
 */
@Data
public class SysMenuVO implements Serializable {

    private static final long serialVersionUID = 8510310099317612636L;

    /**
     * 资源名称
     */
    private String name;

    /**
     * 资源路径
     */
    private String url;

    /**
     * 类型  1:菜单   2:按钮
     */
    private Integer type;

    /**
     * 备注
     */
    private String note;

    /**
     * 授权(如:user:create)
     */
    private String permission;


}

配置类:

/**
 * @author: Sharry
 * @createTime: 2022/12/16 16:15
 * @version: Version-1.0
 */
@Configuration
@MapperScan("cn.sharry.rbaclearning.mapper")
public class MybatisPlusConfig {
}

2. 连表操作

2.1 常用连表图

我们常用 INNER JOIN, RIGHT JOIN, LEFT JOIN 来进行连表。其中,最常用的是 INNER JOIN 、 LEFT JOIN。至于还有其它连表方式,请读者自行查阅。

接下来,我们参考下图进行SQL语句的准备。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4QeCJCZs-1671193446715)(E:\Working-Sida\PersonalNotes\NotesFromLearning\MybatisPlusLearning\images\常用连表查询.png)]

注:图片来源于网络,侵删。

2.2 准备SQL语句

根据VO需要的信息,5表联查:

SELECT su.username, sm.`name`, sm.url, sm.type, sm.note, sm.permission

FROM sys_users su JOIN sys_user_roles sur

ON su.id = sur.user_id

JOIN sys_roles sr 

ON sur.role_id = sr.id 

JOIN sys_role_menus srm

ON sr.id = srm.role_id

JOIN sys_menus sm 

ON srm.menu_id = sm.id

WHERE su.id = 1

根据VO需要的信息,4表联查:

SELECT su.username, sm.`name`, sm.url, sm.type, sm.note, sm.permission

FROM sys_users su 

JOIN sys_user_roles sur

ON su.id = sur.user_id 

JOIN sys_role_menus srm

ON sur.role_id = srm.role_id

JOIN sys_menus sm

ON srm.menu_id = sm.id

WHERE su.id = 1

2.3 Mybatis 连表

根据上面我们提前测试好的连表SQL语句,在Mybatis 中进行测试:

编写Mapper接口

/**
 * @author: Sharry
 * @createTime: 2022/12/16 14:57
 * @version: Version-1.0
 */
@Repository
public interface SysUserMenuMapper {

    /**
     * 根据用户 id 查询用户权限
     * @param id 用户id
     * @return 权限菜单VO
     */
    SysUserMenuVO findUserMenuById(Integer id);

}

编辑Mapper.xml

<?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="cn.sharry.rbaclearning.mapper.SysUserMenuMapper">

    <resultMap id="userMenuResultMap" type="cn.sharry.rbaclearning.pojo.vo.SysUserMenuVO">
        <id column="id" property="id"></id>
        <result column="username" property="username"></result>
        <collection property="menus" ofType="cn.sharry.rbaclearning.pojo.vo.SysMenuVO">
            <result column="name" property="name"></result>
            <result column="note" property="note"></result>
            <result column="url" property="url"></result>
            <result column="type" property="type"></result>
            <result column="permission" property="permission"></result>
        </collection>
    </resultMap>

    <!--  根据用户 id 查询用户权限  -->
    <select id="findUserMenuById" resultMap="userMenuResultMap">
        SELECT su.id, su.username, sm.name, sm.url, 
               sm.type, sm.note, sm.permission

        FROM sys_users su

                 JOIN sys_user_roles sur
                 ON su.id = sur.user_id

                 JOIN sys_role_menus srm
                 ON sur.role_id = srm.role_id

                 JOIN sys_menus sm
                 ON srm.menu_id = sm.id

        WHERE su.id = #{id}
    </select>
</mapper>

编写测试类

/**
 * 连表查询测试类
 * @author: Sharry
 * @createTime: 2022/12/16 16:03
 * @version: Version-1.0
 */
@SpringBootTest
public class SysUserMenuTests {

    @Autowired
    private SysUserMenuMapper userMenuMapper;

    /**
     * 测试根据id 获取权限菜单
     */
    @Test
    public void testGetMenu(){
        System.out.println(userMenuMapper.findUserMenuById(1));
    }
}

3. 总结与补充

补充
读者在按照上面列举的例子进行练习时,可能会遇到联查时,返回的POJO VO(此处以VO为例,实际的命名遵循各自参考的规范)有属性是集合,但实际返回只有1条数据,甚至异常/报错的情况。

解决方案:如果VO里的集合id不是必要的返回值,可以选择修改VO结构,和小编举的例子一样,xml及VO将id属性去掉,避免主表与从表字段名一致而产生冲突。当然,我们也可以采取取别名(与查询的别名要保持一致)、修改表字段等手段去解决。

总结
本文先简单介绍了一下RBAC权限模型,工作中可能会用到。然后我们使用一个基于RBAC权限模型的例子,举例并练习了多对多连表查询,以Mybatis/Mybatis-Plus 为例。然后多加练习吧!

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

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

相关文章

QT系列第6节 QT中常用控件

1. QComboBox 下拉列表 2. QPlainTextEdit QPlainTextEdit的文字内容以QTextDocument类型存储&#xff0c;函数document返回这个文档 对象的指针 QTextDocument是内存中的文本对象&#xff0c;以文本块方式存储&#xff0c;每个段落以换行符结束。 QTextDocument提供一些…

常用日期类

第一代日期类 Date类 Date&#xff1a;精确到毫秒&#xff0c;代表特定的瞬间 当需要获取当前时间时可以直接new一个Date对象&#xff0c;使用无参构造器 Date date new Date();日期转文本 但是直接使用的话&#xff0c;它是国外的时间格式&#xff1a;Sat Dec 17 17:02:3…

Apache IoTDB v1.0.0安装试用小结( linux环境)

1 简介 Apache IoTDB 是一个开源物联网时序数据库。 github地址&#xff1a;https://github.com/apache/iotdb 2 下载 下载地址&#xff1a;https://iotdb.apache.org/Download/ 下载&#xff0c;输入命令&#xff1a; wget https://archive.apache.org/dist/iotdb/1.0.…

【简单工厂模式-2】简单工厂模式的代码实现及使用场景

简单工厂模式并属于Gof 23个经典设计模式其中之一&#xff0c;只是通常会将它作为学习其他工厂设计模式的入门&#xff0c;而且在开发中&#xff0c;简单工厂模式也是比较常见的&#xff0c;设计思想比较简单。 1. 定义 简单工厂模式定义一个工厂类&#xff0c;提供获取对象的…

Makefile、.mk、.bp、Blueprint、Soong、kati工具链的关系

一、Android版本相应的发展演变过程: Android 7.0引入ninja和kati Android 8.0使用Android.bp来替换Android.mk&#xff0c;引入Soong Android 9.0强制使用Android.bp 二、生成.ninja工具链关系&#xff1a;Android.bp、Blueprint、Soong、kati&#xff1a;总之都是用来把Make…

数据库拆分4--使用sharding-jdbc来实现水平拆分

有三张表 user log order表&#xff0c;先将user log 和order垂直分库&#xff0c;然后将user表水平拆分 配置文件 spring.shardingsphere.enabledtruespring.shardingsphere.datasource.nameswim-user,wim-orderspring.shardingsphere.datasource.wim-user.typecom.alibaba.…

vue入门--2

1.计算属性和侦听器 计算属性 VS 方法 如果不使用计算属性&#xff0c;在 methods 里定义了一个方法&#xff0c;也可以实现相同的效果&#xff0c;甚至该方法还可以接受参数&#xff0c;使用起来 更灵活。 既然 methods 同样可以解决模板中复杂逻辑计算的问题&#xff0c;那么…

2266. 统计打字方案数-动态规划

2266. 统计打字方案数-动态规划 Alice 在给 Bob 用手机打字。数字到字母的 对应 如下图所示。 为了 打出 一个字母&#xff0c;Alice 需要 按 对应字母 i 次&#xff0c;i 是该字母在这个按键上所处的位置。 比方说&#xff0c;为了按出字母 s &#xff0c;Alice 需要按 7 …

语雀导出markdown的图片外链问题

本文节选自本人博客&#xff1a;https://www.blog.zeeland.cn/archives/rgoioiabeoi32 Introduction 本人因为经常使用语雀写博客&#xff0c;但是因为语雀转markdown的时候图片存在防外链行为&#xff0c;如果想要把转出的markdown发表在其他平台&#xff0c;就需要把md中所有…

计算机毕设Python+Vue邢台市公寓式月亮酒店管理系统(程序+LW+部署)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

jsp+ssm计算机毕业设计大学生心理咨询网站【附源码】

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; JSPSSM mybatis Maven等等组成&#xff0c;B/S模式 Mave…

java计算机毕业设计springboot+vue地铁站自动售票系统-火车票售票系统

项目介绍 本系统是针对目前地铁站自动售票的实际需求,从实际工作出发,对过去的地铁站自动售票管理系统存在的问题进行分析,完善用户的使用体会。采用计算机系统来管理信息,取代人工管理模式,查询便利,信息准确率高,节省了开支,提高了工作的效率。 本系统结合计算机系统的结构…

Nacos系列——配置的创建与获取

Nacos系列——配置的创建与获取配置的创建与获取本文资源官方文档创建配置获取Nacos配置程序目录1.引入依赖完整pom2.设置yaml3.配置读取类NacosBasedProperties4.构建日志打印工具LoggerUtil5.构建Nacos基础服务类实现6.构建自动化任务实现结果配置的创建与获取 本文资源 ht…

非零基础自学Golang 第11章 文件操作 11.3 处理JSON文件 11.3.1 编码JSON

非零基础自学Golang 文章目录非零基础自学Golang第11章 文件操作11.3 处理JSON文件11.3.1 编码JSON第11章 文件操作 11.3 处理JSON文件 JSON&#xff08;JavaScript Object Notation&#xff0c;JS对象简谱&#xff09;是一种轻量级的数据交换格式。 JSON最初是属于JavaScri…

C++基础学习笔记(二)——基础入门PART2

一、数组 一个集合中&#xff0c;里面存放了相同类型的数据元素 特点1&#xff1a;数组中的每个数据元素都是相同的数据类型 特点2&#xff1a;数组是由连续的内存位置组成的 1.1 一维数组 一维数组定义的三种方式&#xff1a; 数据类型 数组名[ 数组长度 ];数据类型 数组…

高通平台开发系列讲解(充电篇)充电底层驱动 power_supply 子系统

文章目录 一、Power Supply组成二、power_supply结构体说明三、驱动接口沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 电池驱动采取的是 linux 内核驱动中的power_supply子系统框架进行上报电池状态。 一、Power Supply组成 power supply framework在kernel/driver…

微服务真的是万能解药吗?

程序员宝藏库&#xff1a;https://gitee.com/sharetech_lee/CS-Books-Store DevWeekly收集整理每周优质开发者内容&#xff0c;包括开源项目、资源工具、技术文章等方面。 每周五定期发布&#xff0c;同步更新到 知乎&#xff1a;Jackpop。 欢迎大家投稿&#xff0c;提交issu…

Spring MVC学习 | 拦截器异常处理器

文章目录一、拦截器1.1 简介1.2 拦截器的使用1.2.1 创建1.2.2 配置1.2.3 测试1.3 多个拦截器的执行顺序1.3.1 preHandle()方法返回true1.3.2 preHandle()方法返回false二、异常处理器2.1 简介2.2 配置2.2.1 springmvc.xml中配置2.2.2 注解配置学习视频&#x1f3a5;&#xff1a…

编码与解码总结

标准ASC||字符集&#xff1a; ASC||&#xff1a;美国信息交换标准代码&#xff0c;包括了英文、数字等标准ASC||使用一个字节存储一个字符&#xff0c;首位是0&#xff0c;总供可以表示128个字符 GBK&#xff08;汉字内码扩展规范&#xff0c;国标&#xff09; 汉字编码字符集…

Apache Shiro,这一篇就够了

Apache Shiro&#xff0c;这一篇就够了1.Shiro实现登录拦截2.登录认证操作3.Shiro整合Mybatis4.用户授权操作5.Shiro授权6.Shiro整合Thymeleaf1.Shiro实现登录拦截 前期环境准备 准备添加Shiro的内置过滤器&#xff1a; Bean public ShiroFilterFactoryBean shiroFilterFact…