SpringBoot——整合Shiro,实现安全认证和权限管理功能

目录

Shiro

项目总结

新建一个SpringBoot项目

pom.xml

application.properties(配置文件)

User(实体类)

UserMapper(数据访问层接口)

UserMapper.xml(数据库映射文件)

UserService(服务层接口)

UserServiceImpl(接口实现类)

UserRealm(认证、授权逻辑代码类)

ShiroConfig(Shiro配置类)

ShiroApplication(启动类)

index.html(主页面)

login.html(登录页面)

add.html(添加页面)

delete.html(删除页面)

项目测试


Shiro

  • Apache Shiro是一个开源的轻量级的Java安全框架,它提供身份验证、授权、密码管理以及会话管理等功能。相对于Spring Security,Shiro框架更加直观、易用,同时也能提供健壮的安全性
  • 在实际工作时可能使用小而简单的Shiro就足够了,不存在Shiro和Security哪个更好
  • Shiro支持的功能:
    • Authentication:用户身份认证、登录,验证用户是否拥有相应的身份
    • Authorization:授权,验证某个已认证的用户是否拥有某个权限
    • Session Management:会话管理,用户登录后就是第一次会话,在没有退出之前,用户的所有信息都在会话中
    • Cryptography:加密,保证数据的安全性,如将密码加密存储到数据库中
    • Web Support:Web支持,使系统 可以非常容易地集成到Web环境中
    • Caching:缓存,比如用户登录后,其用户信息,以及拥有的角色、权限不必每次都去查,这样可以提高效率
    • Concurrency:Shiro支持多线程应用的并发验证,如在一个线程中开启另一个线程,能把权限自动地传播过去
    • Testing:提供测试支持
    • Run As:允许一个用户冒用另一个用户的身份(如果他们允许)进行访问
    • Remember Me:一次登录后,之后登录不用输入用户名和密码

项目总结

  • 该项目是SpringBoot整合Shiro实现了用户管理系统中的登录认证和授权

  • 需求分析: 首先,明确项目的安全需求,包括用户认证、权限管理、会话管理等方面的具体要求。了解需要保护的资源和不同用户角色的访问权限。

  • 项目初始化: 使用 Spring Initializr 或其他工具创建一个新的 Spring Boot 项目。配置基本的项目结构和依赖管理(Maven 或 Gradle)。

  • 引入依赖: 在项目的 pom.xml 文件中添加 Shiro 的依赖项

  • 配置 Shiro: 创建一个 Shiro 配置类,用于配置安全管理器、Realm 和拦截器链等。

  • 实现 Realm: 创建自定义的 Realm 类,用于处理用户认证和授权逻辑。

  • 编写登录和权限控制代码: 创建控制器来处理用户登录和注销请求。

  • 测试与调试: 运行项目并进行各种测试,确保用户认证和授权功能正常工作。

新建一个SpringBoot项目

新建数据库、表

CREATE DATABASE shiro;
USE shiro;
CREATE TABLE IF NOT EXISTS `t_user`(`id` INT PRIMARY KEY COMMENT '用户ID(主键)',`username` VARCHAR(255) UNIQUE NOT NULL COMMENT '用户名',`password` VARCHAR(20) NOT NULL COMMENT '登录密码',`permissions` VARCHAR(100) NOT NULL COMMENT '用户权限'
)COMMENT='用户信息表';
INSERT INTO t_user(id,username,password,permissions) VALUE (1,'zhangsan','123','user:delete');
INSERT INTO t_user(id,username,password,permissions) VALUE (2,'lisi','123','user:add');

项目结构:

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.12.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.study</groupId><artifactId>shiro</artifactId><version>0.0.1-SNAPSHOT</version><name>shiro</name><description>Demo project for Spring Boot</description><properties><java.version>8</java.version></properties><dependencies><!--MyBatis逆向工程--><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.2</version></dependency><!--@Data注解--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--数据库--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--mybatis--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.2</version></dependency><!--为了在Thymeleaf中使用shiro标签,所以引入 thymeleaf-extras-shiro依赖--><dependency><groupId>com.github.theborakompanioni</groupId><artifactId>thymeleaf-extras-shiro</artifactId><version>2.1.0</version></dependency><!--shiro安全认证框架--><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring-boot-web-starter</artifactId><version>1.9.0</version></dependency><!--使用.html模板--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</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-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

application.properties(配置文件)

# 配置shiro的基本信息
# 表示开启Shiro配置,默认为true
shiro.enabled=true  
# 表示开启Shiro Web配置,默认为true
shiro.web.enabled=true
# 表示登录地址,否则默认为"/login.jsp"
shiro.loginUrl=/login
# 表示登录成功地址,默认为"/"
shiro.successUrl=/index
# 表示未获授权默认跳转地址
shiro.unauthorizedUrl=/unauthorized
# 表示是否允许通过
shiro.sessionManager.sessionIdUrlRewritingEnabled=true
# UTL参数实现会话跟踪,如果网站支持Cookie,可以关闭此选项
# 表示是否允许通过Cookie实现会话跟踪,默认为true
shiro.sessionManager.sessionIdCookieEnabled=true# MySQL数据库的配置信息
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.url=jdbc:mysql://localhost:3306/shiro?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver# mybatis的配置信息
# .xml文件放置处,此处指resources文件夹下
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.study.shiro.entity

User(实体类)

package com.study.shiro.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {private int id;private String username;private String password;private String permissions;
}

UserMapper(数据访问层接口)

package com.study.shiro.mapper;import com.study.shiro.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;@Mapper
@Repository
public interface UserMapper{public User findUserByName(String username);
}

UserMapper.xml(数据库映射文件)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.study.shiro.mapper.UserMapper"><resultMap id="BaseResultMap" type="com.study.shiro.entity.User"><id property="id" column="id" jdbcType="INTEGER"/><result property="username" column="username" jdbcType="VARCHAR"/><result property="password" column="password" jdbcType="VARCHAR"/><result property="permissions" column="permissions" jdbcType="VARCHAR"/></resultMap><sql id="Base_Column_List">id,username,password,permissions</sql><select id="findUserByName" resultType="com.study.shiro.entity.User">select * from t_user where username like #{username}</select>
</mapper>

UserService(服务层接口)

package com.study.shiro.service;import com.study.shiro.entity.User;public interface UserService{public User findUserByName(String username);
}

UserServiceImpl(接口实现类)

package com.study.shiro.service.impl;import com.study.shiro.entity.User;
import com.study.shiro.mapper.UserMapper;
import com.study.shiro.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl implements UserService {@AutowiredUserMapper userMapper;@Overridepublic User findUserByName(String username) {return userMapper.findUserByName(username);}
}

UserRealm(认证、授权逻辑代码类)

package com.study.shiro.config;import com.study.shiro.entity.User;
import com.study.shiro.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;/*** 实现用户登录认证逻辑*/
public class UserRealm extends AuthorizingRealm {@AutowiredUserService userService;/*** 用户授权的逻辑代码*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {System.out.println("执行了===>用户授权");SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();//获取当前登录的这个对象Subject subject = SecurityUtils.getSubject();//获取User对象User currentUser = (User) subject.getPrincipal();//设置权限info.addStringPermission(currentUser.getPermissions());return info;}/*** 用户认证的逻辑代码*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {System.out.println("执行了===>用户认证");UsernamePasswordToken token= (UsernamePasswordToken) authenticationToken;//连接真实的数据库,调取用户信息User user = userService.findUserByName(token.getUsername());//该用户不存在if(user==null){return null;}Subject subject = SecurityUtils.getSubject();//将登录用户放入Session中subject.getSession().setAttribute("loginUser",user);//密码认证return new SimpleAuthenticationInfo(user,user.getPassword(),"");}
}

ShiroConfig(Shiro配置类)

package com.study.shiro.config;import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.beans.factory.annotation.Qualifier;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;import java.util.LinkedHashMap;
import java.util.Map;@Configuration
public class ShiroConfig {/*** ShiroDialect类是为了支持在Thymeleaf中使用的Shiro标签*/@Beanpublic ShiroDialect getShiroDialect() {return new ShiroDialect();}@Beanpublic ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();// 设置安全管理器bean.setSecurityManager(securityManager);// Shiro内置过滤器,可以实现权限相关的拦截器/*常用的过滤器:anon: 无需认证(登录)可以访问authc: 必须认证才可以访问user: 如果使用rememberMe的功能可以直接访问perms: 该资源必须得到资源权限才可以访问role: 该资源必须得到角色权限才可以访问*/Map<String, String> filterMap = new LinkedHashMap<>();filterMap.put("/login", "anon");filterMap.put("/index", "anon");filterMap.put("/doLogin", "anon"); // 无需认证即可访问filterMap.put("/logout", "logout"); // Shiro自带的退出登录filterMap.put("/**", "authc"); // 拦截其他所有请求,需要认证filterMap.put("/user/add","perms[user:add]");filterMap.put("/user/delete","perms[user:delete]");// 设置默认登录的 URL,身份认证失败会访问该 URLbean.setLoginUrl("/login");// 设置登录成功后要跳转的链接bean.setSuccessUrl("/index");//未授权时跳转的页面bean.setUnauthorizedUrl("/noauth");bean.setFilterChainDefinitionMap(filterMap);return bean;}@Bean(name = "securityManager")public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();// 关联RealmsecurityManager.setRealm(userRealm);return securityManager;}/*** 创建Realm对象*/@Bean(name = "userRealm")public UserRealm userRealm() {return new UserRealm();}
}

UserController(控制器)

package com.study.shiro.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;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
public class UserController {//主页面@RequestMapping({"/index","/"})public String index(Model model){model.addAttribute("msg","hello shiro!");return "index";}//登录页面@RequestMapping("/login")public String login(){return "login";}//处理登录请求,是否成功@RequestMapping("/doLogin")public String doLogin(String username,String password,Model model){//封装用户数据UsernamePasswordToken token = new UsernamePasswordToken(username, password);//获取当前用户Subject currentUser = SecurityUtils.getSubject();//执行登录的方法,只要没有异常就代表登录成功try {currentUser.login(token);return "index";} catch (UnknownAccountException uae) {model.addAttribute("msg","用户名不存在!");return "login";}catch (IncorrectCredentialsException ice){model.addAttribute("msg","密码错误!");return "login";}}//注销@RequestMapping("/logout")public String logout(){Subject currentUser = SecurityUtils.getSubject();currentUser.logout();return "index";}@RequestMapping("/noauth")@ResponseBodypublic String noAuth(){return "未经授权不能访问此页面";}//获取指定授权后,可访问该页面@RequestMapping("/user/add")public String add(){return "/user/add";}//获取指定授权后,可访问该页面@RequestMapping("/user/delete")public String delete(){return "/user/delete";}
}

ShiroApplication(启动类)

package com.study.shiro;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class ShiroApplication {public static void main(String[] args) {SpringApplication.run(ShiroApplication.class, args);}}

index.html(主页面)

<!DOCTYPE html>
<html lang="en" xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro"xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>主页面</title><!--引入Bootstrap国内CDN库--><link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container"><div class="row"><div class="col-md-4 col-md-offset-3"><h1>主页面</h1></div></div><div class="row"><div class="col-md-4 col-md-offset-3"><!--会话中没有用户,即用户未登录,显示"登录"超链接--><p th:if="${session.loginUser == null}"><a th:href="@{/login}">登录</a></p></div></div><div class="row"><div class="col-md-4 col-md-offset-3"><!--会话中保存了用户,即用户已登录,显示"注销"超链接--><p th:if="${session.loginUser != null}"><a th:href="@{/logout}">注销</a></p></div></div><div class="row"><div class="col-md-4 col-md-offset-3"><div shiro:haspermission="user:add"><a th:href="@{/user/add}">添加</a></div></div></div><div class="row"><div class="col-md-4 col-md-offset-3"><div shiro:haspermission="user:delete"><a th:href="@{/user/delete}">删除</a></div></div></div>
</div>
</body>
</html>

login.html(登录页面)

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>登录页面</title><link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body><div class="container"><div class="row"><div class="col-md-4 col-md-offset-3"><h1>登录页面</h1></div></div><div class="row"><div class="col-md-4 col-md-offset-3"><p style="color:red;" th:text="${msg}"></p></div></div><form class="form-horizontal" th:action="@{/doLogin}" method="post"><div class="form-group"><label class="col-sm-2 control-label">用户名</label><div class="col-sm-4"><input type="text" class="form-control" name="username"></div></div><div class="form-group"><label class="col-sm-2 control-label">密码</label><div class="col-sm-4"><input type="password" class="form-control" name="password"></div></div><div class="form-group"><div class="col-sm-offset-2 col-sm-10"><button type="submit" class="btn btn-default">登录</button></div></div></form></div>
</body>
</html>

add.html(添加页面)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>添加页面</title><!--引入Bootstrap国内CDN库--><link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container"><div class="row"><div class="col-md-4 col-md-offset-5"><h1>添加</h1></div></div>
</div>
</body>
</html>

delete.html(删除页面)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>删除页面</title><!--引入Bootstrap国内CDN库--><link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container"><div class="row"><div class="col-md-4 col-md-offset-5"><h1>删除</h1></div></div>
</div>
</body>
</html>

项目测试

1、访问主页面:localhost:8080/index,点击“登录”

2、输入用户信息,登录

3、用户zhangsan拥有“删除”的权限

4、点击“注销”,返回用户登录页面

5、用户lisi,拥有“添加”的权限

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

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

相关文章

单位转换:将kb转换为 MB ,GB等形式

写法一&#xff1a; function formatSizeUnits(kb) {let units [KB, MB, GB, TB, PB,EB,ZB,YB];let unitIndex 0;while (kb > 1024 && unitIndex < units.length - 1) {kb / 1024;unitIndex;}return ${kb.toFixed(2)} ${units[unitIndex]}; } console.log(for…

北京站圆满结束!MongoDB Developer Day上海站,周六见!

上周六 MongoDB Developer Day首站北京站 80位开发者与MongoDB一起度过了充实的一天 专题讲座➕动手实操➕专家面对面交流 从数据建模、进阶查询技巧 到Atlas搜索与向量搜索 让参会伙伴们直呼“满满的技术干货&#xff01;” 全体参会者与工作人员合影 MongoDB Developer …

一个人 三个月 干了二十万

相信很多人是被这个标题吸引进来的&#xff0c;但我并不是标题党&#xff0c;我也很讨厌标题党&#xff0c;这篇文章也不在乎流量&#xff0c;更多的是想记录下。 出来创业三个多月了&#xff0c;给大家汇报一下这段时间的业绩吧。一个人&#xff0c;三个多月&#xff0c;干了…

数据分析报告制作的结构和思路整理

先画重点&#xff1a;一份分析报告的制作&#xff0c;目前的市场的分析步骤是优先找一些别人的研究报告&#xff0c;现成的东西&#xff0c;重点是要好好总结业务逻辑和潜在运营可能&#xff0c;这也是一位优秀数据分析师的价值体现。 举个例子&#xff0c;以目前小说短剧赛道的…

人工智能期末复习思维导图,参考人工智能及其应用(第6版)和柴玉梅老师教材

其中第一、六、七、八、九章不用重点看&#xff0c;计算题一般会考1.语义网络、谓词逻辑&#xff0c;2.可信度&#xff0c;3.主观贝叶斯&#xff0c;4.一般合一置换&#xff0c;5.证据理论&#xff0c;6.盲目搜索。 第一章&#xff1a;绪论 第二章&#xff1a;知识表示方法 第…

中小企业在数字化转型过程中遇到的挑战有哪些?

引言&#xff1a;中小企业推进数字化转型的背景是多重因素叠加的结果&#xff0c;包括市场竞争压力、信息技术发展及普及、各级政府政策支持及引导、企业经营发展需求和人才结构变化等。这些因素共同推动了中小企业加快数字化转型的步伐&#xff0c;以应对日益复杂多变的市场环…

2024年湖南建筑安全员考试题库,精准题库。

31.安全考核的对象应包括施工企业各管理层的&#xff08;&#xff09;、相关职能部门及岗位和工程项目参建人员。 A.技术负责人 B.安全负责人 C.主要负责人 D.第一负责人 答案&#xff1a;C 32.安全防护设施应标准化、定型化、&#xff08;&#xff09;。 A.规范化 B.工…

msvcp120.dll文件不见了要怎么处理?教你科学的方法修复msvcp120.dll

msvcp120.dll文件不见了&#xff1f;那么这时候你就要注意了&#xff0c;有可能你的某些程序已经打不开了&#xff01;因为这个msvcp120.dll文件是用来支持程序运行的&#xff0c;下面我们一起来聊一下msvcp120.dll文件不见了要怎么修复。 一.msvcp120.dll文件讲解 msvcp120.d…

软考论文总挂科!评分标准是什么?

最近很多小伙伴都查到了自己上半年的软考高项成绩&#xff0c;首先恭喜已经通过的宝子&#xff0c;但也有一部分同学卡在了论文上&#xff0c;跟软考证书擦肩而过。今天给大家分析一下导致论文挂科的一些原因~ 1&#xff09;写作中的硬伤 01跑题:没有回应子题目所需论述的内容…

第5章 传输层

王道学习 考纲内容 &#xff08;一&#xff09;传输层提供的服务 传输层的功能&#xff1a;传输层寻址与端口&#xff1b;无连接服务和面向连接服务 &#xff08;二&#xff09;UDP UDP数据报&#xff1b;UDP检验 &#xff08;三&#xff09;TCP …

华强盛网络变压器外部电路如何接线

图一是 华强盛 Hqst 网络变压器工厂19926430038 华强盛电子导读&#xff1a; 网络变压器的外部电路接线通常依赖于其设计和用途。一般来说&#xff0c;网络变压器有多个端口&#xff0c;每个端口可能用于不同的连接或功能。以下是一些可能的接线方式&#xff1a; 1. **主电源…

Swoole_loader扩展安装图文教程 Swoole扩展文件下载

Swoole_loader扩展安装图文教程 Swoole扩展文件下载 安装和配置Swoole Loader 1 - 下载Swoole Loader 请下载兼容PHP7.2和非线程安全的Swoole Loader扩展&#xff0c;点击下载适配环境的扩展文件 2 - 安装Swoole Loader 将刚才下载的Swoole Loader扩展文件&#xff08;swo…

Origin科学绘图软件最新版下载安装,Origin强大的科学研究工具

Origin软件&#xff0c;这款软件以其强大的数据分析和图形绘制功能&#xff0c;赢得了广大科研人员的青睐。无论是探索微观世界的化学研究&#xff0c;还是深究宏观现象的物理学分析&#xff0c;亦或是揭示生命奥秘的生物学探索&#xff0c;Origin软件都能为用户提供精准、高效…

详细的介绍匀加速运动的物理方程是如何转化为卡尔曼滤波的状态空间模型的

详细的介绍匀加速运动的物理方程是如何转化为卡尔曼滤波的状态空间模型的 flyfish 加速度是描述物体速度变化快慢的物理量&#xff0c;定义为速度对时间的变化率。数学上&#xff0c;它表示为&#xff1a; a Δ v Δ t a \frac{\Delta v}{\Delta t} aΔtΔv​ 其中&#xf…

DataV大屏组件库

DataV官方文档 DataV组件库基于Vue &#xff08;React版 (opens new window)&#xff09; &#xff0c;主要用于构建大屏&#xff08;全屏&#xff09;数据展示页面即数据可视化&#xff0c;具有多种类型组件可供使用&#xff1a; 源码下载

等保2.0对云计算有哪些特定的安全要求?

在数字化浪潮的推动下&#xff0c;云计算已成为支撑现代社会运行的基础设施之一。它以其弹性、高效的特性&#xff0c;为企业提供了强大的数据处理能力和无限的存储空间。然而&#xff0c;随着云服务的普及&#xff0c;安全问题也日益凸显&#xff0c;成为制约云计算发展的关键…

已解决javax.transaction.InvalidTransactionException:事务无效的正确解决方法,亲测有效!!!

已解决javax.transaction.InvalidTransactionException&#xff1a;事务无效的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 目录 问题分析 报错原因 解决思路 解决方法 1. 确保事务的正确启动和结束 Spring中的事务管理 2. 避免嵌套事务问题…

潜水耳机哪个牌子好?榜上有名的四大超赞潜水耳机揭秘

随着探险和运动爱好者对水下世界的探索欲望不断增长&#xff0c;潜水耳机逐渐成为市场上的新宠。它们不仅让我们在深潜时能够与外界保持联系&#xff0c;更为我们提供了一种独特的水下音乐体验。然而&#xff0c;面对众多品牌和型号&#xff0c;选择一款性能优越、安全可靠的潜…

工作纪实51-手撸AB实验分流策略

前几天写了一篇关于哈希算法的文章&#xff0c;起源就是在构思AB实验平台的时候&#xff0c;用到了哈希&#xff0c;所以对其做了深入的了解 AB实验平台是一般互联网做策略、样式实验会用到的一个系统&#xff0c;一般开启某个实验之后&#xff0c;需要对线上流量进行分流&…

lvs+上一章的内容

书接上回这次加了个keepalived 一、集群与分布式 1.1 集群介绍 **集群&#xff08;Cluster&#xff09;**是将多台计算机组合成一个系统&#xff0c;以解决特定问题的计算机集合。集群系统可以分为以下三种类型&#xff1a; **LB&#xff08;Load Balancing&#xff0c;负载…