SpringBoot 整合 Shiro Thymeleaf Mysql 动态授权

文章目录

    • 需求安排
  • 一、前期准备
    • 1. maven依赖
    • 2. 创建数据库+初始化表数据
    • 3. 实体类
    • 4. mapper接口
    • 5. mapper接口映射文件
    • 6. service接口
    • 7. service实现类
    • 8. 首页控制器
    • 9. 用户控制器
    • 10. 全局配置文件
    • 11. 启动类加注解
  • 二、页面准备
    • 2.1. 首页页面
    • 2.2. 登录页面
    • 2.3. 未授权页面
    • 2.4. 用户添加页面
    • 2.5. 用户更新页面
  • 三、Shiro 配置
    • 3.1. 自定义UserRealm
    • 3.2. ShiroConfig
  • 四、需求测试
  • 五、源码链接

需求安排

需求分析:
1. 匿名允许访问页面首页和登录页面
2. 默认登录页面
3. admin用户只有用户添加权限
4. test用户只有用户更新权限
5. 访问授权页面,默认跳转登录页面
6. 登录认证通过,访问无权限页面,默认跳转未授权页面
7. 登录认证通过,进行资源授权角色授权后,访问各自有权限的页面
注:第6条企业内部采用无权限的页面采用shiro和页面整合策略,直接不会显示

一、前期准备

1. maven依赖

 <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><druid.version>1.0.28</druid.version><mybatis-spring-boot.version>2.1.2</mybatis-spring-boot.version><shiro-spring.version>1.5.2</shiro-spring.version><thymeleaf-extras-shiro.version>2.0.0</thymeleaf-extras-shiro.version></properties><dependencies><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--thymeleaf模板引擎--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><!--springMvc启动器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- shiro与spring整合依赖 --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>${shiro-spring.version}</version></dependency><!--mybatis启动器--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>${mybatis-spring-boot.version}</version></dependency><!--MYSQL--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!-- 集成druid数据源 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>${druid.version}</version></dependency><!-- thymel对shiro的扩展坐标 --><dependency><groupId>com.github.theborakompanioni</groupId><artifactId>thymeleaf-extras-shiro</artifactId><version>${thymeleaf-extras-shiro.version}</version></dependency></dependencies>

2. 创建数据库+初始化表数据

数据库名:shiro
表名:user

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户id',`name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名',`password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码',`perms` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '授权字段',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'admin', 'admin', 'user:add');
INSERT INTO `user` VALUES (2, 'test', 'test', 'user:update');

3. 实体类

package com.gblfy.entity;import lombok.Data;
import java.io.Serializable;@Data
public class User implements Serializable {private Integer id;private String name;private String password;private String perms;
}

4. mapper接口

package com.gblfy.mapper;import com.gblfy.entity.User;public interface UserMapper {/*** 通过id查询用户信息** @param id* @return*/User selectByPrimaryKey(Integer id);/*** 根据用户名查询用户信息** @param name* @return*/User selectByName(String name);}

5. mapper接口映射文件

在resources目录下面创建mapping文件夹

<?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.gblfy.mapper.UserMapper"><resultMap id="BaseResultMap" type="com.gblfy.entity.User"><id column="id" property="id" jdbcType="INTEGER"/><result column="name" property="name" jdbcType="VARCHAR"/><result column="password" property="password" jdbcType="VARCHAR"/><result column="perms" property="perms" jdbcType="VARCHAR"/></resultMap><sql id="Base_Column_List">id, name, password, perms</sql><select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer">select<include refid="Base_Column_List"/>from userwhere id = #{id,jdbcType=INTEGER}</select><select id="selectByName" resultMap="BaseResultMap" parameterType="java.lang.String">select<include refid="Base_Column_List"/>from userwhere name = #{name,jdbcType=VARCHAR}</select>
</mapper>

6. service接口

package com.gblfy.service;import com.gblfy.entity.User;public interface UserService {/*** 根据用户名查询用户信息** @param name* @return*/User selectByName(String name);/*** 通过id查询用户信息** @param id* @return*/User selectByPrimaryKey(Integer id);
}

7. service实现类

package com.gblfy.service.impl;import com.gblfy.entity.User;
import com.gblfy.mapper.UserMapper;
import com.gblfy.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;/*** 根据用户名查询用户信息** @param name* @return*/@Overridepublic User selectByName(String name) {return userMapper.selectByName(name);}/*** 通过id查询用户信息** @param id* @return*/@Overridepublic User selectByPrimaryKey(Integer id) {return userMapper.selectByPrimaryKey(id);}}

8. 首页控制器

package com.gblfy.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
public class IndexController {@RequestMapping("index")public String index() {return "index";}
}

9. 用户控制器

package com.gblfy.controller;import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
public class UserController {//跳转登录页面@RequestMapping("/toLogin")public String toLogin() {return "login";}//用户添加@RequestMapping("/add")public String add() {return "/user/add";}//用户更新@RequestMapping("/update")public String update() {return "/user/update";}//未授权跳转页面@RequestMapping("noAuth")public String noAuth() {return "noAuth";}//登录处理@RequestMapping("login")public String login(String username, String password, Model model) {/*** 编写shiro认证操作* 1.获取subject* 2.封装用户数据* 3.执行登录方法*///1.获取subjectSubject subject = SecurityUtils.getSubject();//2.封装用户数据 认证时会用到UsernamePasswordToken token = new UsernamePasswordToken(username, password);//3.执行登录方法try {subject.login(token);//登陆成功} catch (UnknownAccountException e) {e.printStackTrace();//登陆失败 场景1model.addAttribute("msg", "用户名不存在!");return "login";} catch (IncorrectCredentialsException e) {e.printStackTrace();//登陆失败 场景2model.addAttribute("msg", "密码错误!");return "login";}//登陆成功model.addAttribute("msg", username + "登陆成功跳转首页");return "index";}
}

10. 全局配置文件

#server 端口
server:port: 80tomcat:min-spare-threads: 30max-threads: 1000#Mysql配置
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/shiro?useSSL=true&serverTimezone=GMT&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8username: rootpassword: roottype: com.alibaba.druid.pool.DruidDataSource# Mybatis Mapper映射文件+实体类配置
mybatis:type-aliases-package: com.gblfy.entitymapperLocations:- classpath*:/mapping/*.xml

11. 启动类加注解

package com.gblfy;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@MapperScan("com.gblfy.mapper")
public class SpringbootShiroApplication {public static void main(String[] args) {SpringApplication.run(SpringbootShiroApplication.class, args);}}

二、页面准备

2.1. 首页页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"><head><meta charset="UTF-8"><title>系统首页</title>
</head>
<body>
<h3 th:text="${msg}" style="color: red"></h3>
<div>进入用户添加页面:&ensp;&ensp;&ensp;<a href="/add">用户添加</a>
</div>
<br/>
<div>进入用户更新页面:&ensp;&ensp;&ensp;<a href="/update">用户更新</a>
</div>
</body>
</html>

2.2. 登录页面

<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>登录页面</title>
</head>
<body>
<h3 th:text="${msg}" style="color: red">登录</h3>
<form method="post" action="/login">用户名:<input type="text" name="username"/><br/>&ensp;码:<input type="password" name="password"/><br/><input type="submit" value="登录"/>
</form>
</body>
</html>

2.3. 未授权页面

<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>未授权页面</title>
</head>
<body>
未授权页面,请联系管理员进行授权操作!
</body>
</html>

2.4. 用户添加页面

<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>添加页面</title>
</head>
<body>
<h3>添加页面</h3>
</body>
</html>

2.5. 用户更新页面

<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>更新页面</title>
</head>
<body>
<h3>更新页面</h3>
</body>
</html>

三、Shiro 配置

3.1. 自定义UserRealm

package com.gblfy.realm;import com.gblfy.entity.User;
import com.gblfy.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;/*** 自定义 UserRealm* 固定写法:extends AuthorizingRealm*/
public class UserRealm extends AuthorizingRealm {@Autowiredprivate UserService userService;/*** 认证** @param token* @return* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//1.得到用户名和密码    因为登录已存,因此,能取UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;String username = usernamePasswordToken.getUsername();//默认获取password的类型为char[],转换处理String password = new String(usernamePasswordToken.getPassword());//2.从数据库根据用户名查询用户信息User user = userService.selectByName(username);//判断查询出的用户对象(sysUser)是否为空if (user == null) {throw new UnknownAccountException("用户不存在!");}//判断查询出的用户对象的用户密码和页面从页面传递过来的密码进行比较是否相同if (!user.getPassword().equals(password)) {throw new IncorrectCredentialsException("密码有误!");}//认证通过 登陆成功SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), this.getName());return info;}/*** 授权** @param principalCollection* @return*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();//通过id用户信息Subject subject = SecurityUtils.getSubject();//认证时存的是user,因此可以强转成user对象User user = (User) subject.getPrincipal();User userPerms = userService.selectByPrimaryKey(user.getId());//从user对象动态获取权限,放到认证容器info.addStringPermission(userPerms.getPerms());return info;}}

3.2. ShiroConfig

package com.gblfy.config;import com.gblfy.realm.UserRealm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.LinkedHashMap;
import java.util.Map;@Configuration
public class ShiroConfig {/*** 1.创建Realm*/@Bean(name = "userRealm")public UserRealm getRealm() {return new UserRealm();}/*** 2.创建DefaultWebSecurityManager*/@Bean(name = "securityManager")public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();//关联realmsecurityManager.setRealm(userRealm);return securityManager;}/*** 3.创建ShiroFilterFactoryBean*/@Beanpublic ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();//设置安全管理器shiroFilterFactoryBean.setSecurityManager(securityManager);//指定登录页面shiroFilterFactoryBean.setLoginUrl("/toLogin");//指定未授权页面shiroFilterFactoryBean.setUnauthorizedUrl("/noAuth");//添加Shiro内置过滤器/*** Shiro内置过滤器,可以实现权限相关的拦截器*    常用的过滤器:*       anon: 无需认证(登录)可以访问*       authc: 必须认证才可以访问*       user: 如果使用rememberMe的功能可以直接访问*       perms: 该资源必须得到资源权限才可以访问*       role: 该资源必须得到角色权限才可以访问*/Map<String, String> filterMap = new LinkedHashMap<String, String>();//设置允许匿名访问filterMap.put("/index", "anon");filterMap.put("/login", "anon");//配置授权过滤器 第一种filterMap.put("/add", "perms[user:add]");filterMap.put("/update", "perms[user:update]");//授权才可以访问filterMap.put("/*", "authc");shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);return shiroFilterFactoryBean;}}

四、需求测试

测试计划;
1. 访问http://localhost/index和http://localhost/login 是否可以匿名访问
2. 访问http://localhost/index页面,点击进入添加页面是否跳转登录页面
3. 访问http://localhost/index页面,点击进入更新页面是否跳转登录页面
4. 访问几个不存在的url测试是否默认统一跳转登录页面。例如: http://localhost/xxx
5. 使用admin账户,访问登录页面,做一下测试:1>输入不存在的账户点击登录,不输密码,测试,是否提示用户名不存在2>输入存在的账户admin不输密码,点击登录,测试,是否提示密码错误3>输入存在的正确的账户admin,输入正确的密码,点击登录,测试,点击用户添加,是否可以进入用户添加页面4>输入存在的正确的账户admin,输入正确的密码,点击登录,测试,点击用户更新,是否跳转未授权页面
6. 使用test账户,访问登录页面,做一下测试:1>输入不存在的账户点击登录,不输密码,测试,是否提示用户名不存在2>输入存在的账户test不输密码,点击登录,测试,是否提示密码错误3>输入存在的正确的账户test,输入正确的密码,点击登录,测试,点击用户更新,是否可以进入用户更新页面4>输入存在的正确的账户test,输入正确的密码,点击登录,测试,点击用户添加,是否跳转未授权页面

到此,除了成功登录后,角色授权,就都演示完了!

五、源码链接

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

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

相关文章

阿里云云效如何保障双11大型项目管理

每一年双11对阿里巴巴来说都是一个练兵场&#xff0c;一次更大规模技术创新、产品迭代、协同研发的练兵场。在2018年双11的“练兵场上”&#xff0c;阿里云云效——一站式企业协同研发平台支持着阿里巴巴众多部门、百个核心产品、千个垂直项目、几千人共同协作完成双十一大促的…

揭秘天猫双11背后:20万商家600万张海报,背后只有一个鹿班

还记得去年双11&#xff0c;秋裤厂商带着“五彩斑斓的黑”需求找设计师的故事吗&#xff1f; 现在&#xff0c;已经有超过20万客户把这个AI设计师鹿班带回家。 今年&#xff0c;鹿班除了为天猫淘宝平台提供服务之外&#xff0c;还通过阿里云全面为各行业客户输出AI设计能力。…

华为开源数据虚拟化引擎HetuEngine;全球超算500强:中国上榜数量增加;谷歌收购云计算公司CouldSimple ……...

关注并标星星CSDN云计算 速递、最新、绝对有料。这里有企业新动、这里有业界要闻&#xff0c;打起十二分精神&#xff0c;紧跟fashion你可以的&#xff01;每周两次&#xff0c;打卡即read更快、更全了解泛云圈精彩newsgo go go华为V30 渲染图&#xff1a;取消3.5mm耳机孔&…

该虚拟机似乎正在使用中 请获取所有权

https://jingyan.baidu.com/album/4ae03de3fa2ae93eff9e6bb0.html?picindex1

三位数除以两位数怎么算竖式_青岛版三年级上册数学5.6三位数除以一位数(最高位商后有余数)微课知识点精讲+练习...

微课视频第一课时微课视频第二课时同步练习1、列竖式计算下面各题3753 2382 5884 62352、一片树林3年共增加了537棵树&#xff0c;平均每年增长多少棵树&#xff1f;3、新华小学一年级共报名448人&#xff0c;如果一年级预开设8个班&#xff0c;那每个班有多少人…

阿里云移动研发平台EMAS,是如何连续5年安全护航双11的?

2014年11月11日&#xff0c;阿里巴巴天猫双十一购物狂欢节全天交易额571亿元&#xff1b;2015年交易额912.17亿元&#xff1b; 2016年1207亿 &#xff1b;2017年1682亿元&#xff1b;2018年2135亿。五年内交易量不断攀升&#xff0c;屡创新高&#xff0c;这让双十一成为了全球商…

从双十一看阿里云安全的“创世纪”——采访阿里云安全掌门人肖力有感

“神说要有光于是就有了光。”在双十一采访了阿里云安全掌门人肖力之后&#xff0c;忽然对这句话有了全新的认识。从肖力的介绍中我们不难体会到&#xff0c;与云计算相伴而生的阿里云安全诞生的必然性&#xff0c;云的先天基因赐予它“原生的神力”&#xff0c;从最初单纯的攻…

这段 Python 代码让程序员赚 300W,公司已确认!网友:神操作!

Python到底还能给人多少惊喜&#xff1f;笔者最近看到了这两天关于Python最热门的话题&#xff0c;关于《地产大佬潘石屹学Python的原因》&#xff0c;结果被这个回答惊到了&#xff1a;来源&#xff1a;知乎 https://www.zhihu.com/question/355880221笔者翻了翻那些回答&…

解决windows下Error:node with name rabbit already running on “XXX” 和管理页面打不开问题

背景&#xff1a;重启电脑后&#xff0c;发现rabbit的控制台页面无法打开&#xff0c;启动rabbit&#xff0c;抛如下异常&#xff1a;Error&#xff1a;node with name "rabbit" already running on “XXX”这个是因为rabbit已经启动了&#xff0c;不能再次启动&…

奉上一份云上数据安全保护指南

阿里云资深安全专家黄瑞瑞 本方案的目标是为用户提供从底层云平台数据安全到上层的云上环境保护&#xff0c;并标明各层次模块&#xff0c;让用户可以像建房子一样&#xff0c;一层层的搭建可信的在云上数据的安全保护。在各横向层次模块之外&#xff0c;云上数据安全也需要纵…

mysql 重启_windows下重启mysql的方法

其中第二种方法对我这无效&#xff0c;以后再搞清楚&#xff01;一、MYSQL服务我的电脑——(右键)管理——服务与应用程序——服务——MYSQL——开启(停止、重启动)二、命令行方式Windows1.点击“开始”->“运行”(快捷键WinR)。2.启动&#xff1a;输入 net stop mysql3.停止…

云数据库POLARDB优势解读系列文章之②——高性价比

现在做任何事情都要看投入产出比&#xff0c;对应到数据库上其实就是性价比。POLARDB作为一款阿里自研数据库&#xff0c;经常被问的问题是&#xff1a;性能怎么样&#xff1f;能不能支撑我的业务&#xff1f;价格贵不贵&#xff1f;很显然&#xff0c;在早期调研阶段&#xff…

Linux环境 安装 Redis-6.2.6 配置运行_01

文章目录安装依赖环境1.下载2. 解压3. 编译4. 配置抽离5. 修改配置文件6. 启动redis7. 查看redis进程8. 启动redis客户端安装依赖环境 yum install -y gcc-c autoconf automaker升级GCC 这里说明一下&#xff0c;在编译之前&#xff1a;在编译之前需要升级gcc的版本&#xff0…

38年后的今天,用数据回顾什么是女排精神?

戳蓝字“CSDN云计算”关注我们哦&#xff01;作者 | 朱小五责编 | 阿秃每当我们足篮打水一场空时&#xff0c;总会想起女排。38年前&#xff0c;1981年11月16日&#xff0c;中国队击败当时号称“东洋魔女“的日本女排&#xff0c;首次夺得世界冠军&#xff0c;这也是中国在三大…

阿里如何将“高峰前扩容、高峰后缩容”的梦想照进现实?

一、2017年我们做了什么&#xff1f; 记得早在2017年的时候&#xff0c;王坚博士就曾召大家就关于“IDC As a Computer”是否能做到&#xff0c;进行过激烈的讨论。而要做到此&#xff0c;必须要实现存储计算分离&#xff0c;分离后由调度对计算和存储资源进行独立自由调度。而…

cmd下pip安装mysql_Windows下使用pip安装mysql-python

安装的过程很煎熬&#xff0c;留个爪&#xff0c;希望对其他人有帮助。先声明我安装前的电脑配置&#xff1a;Win10&#xff1b;Python2和Python3共存(备注一个好用的方法&#xff0c;感谢知乎大神&#xff1a;https://www.zhihu.com/question/21653286)&#xff1b;MySQL是在W…

阿里云异构计算团队亮相英伟达2018 GTC大会

1、首届云原生计算国际会议上&#xff0c;弹性计算研究员伯瑜介绍了基于虚拟化、容器化编排技术的云计算操作系统PouchContainer 首届云原生计算国际会议&#xff08;KubeCon CloudNativeCon&#xff0c;China&#xff0c;2018&#xff09;在上海举办&#xff0c;弹性计算研究…

SpringBoot整合Redis 主从复制_01

主从复制 master slave 核心解决问题&#xff1a;数据冗余备份&#xff0c;不能解决故障的自动转移 主从复制讲解&#xff1a; 1.主节点负责写入操作&#xff0c;从节点负责同步主节点的冗余数据&#xff0c;不能写入 2.当主节点挂掉之后&#xff0c;从节点还是从节点&#xf…

发布国内首个无服务器容器服务,运维效率从未如此高效

近年来&#xff0c;随着越来越多的企业基于微服务架构构建自身核心业务平台后&#xff0c;微服务已获得越来越多技术人员的肯定&#xff0c;同时&#xff0c;微服务也承载着企业数字化转型的重任。但微服务架构的落地给企业的运维团队带来了不少的挑战&#xff0c;原有的运维方…

OPPO 正式发布 ColorOS 7,“轻”装上阵带来多项亮眼新功能……

今日OPPO举办了 ColorOS 7 发布会&#xff0c;正式发布了主打“轻快无边界”的ColorOS 7&#xff0c;以“轻”为核心构建了无边界设计 2.0&#xff0c;在UI、交互、动画、声效等方面进行了优化&#xff0c;围绕“快”阐述了ColorOS 7 在畅快使用、高效体验上所做的创新功能。 此…