springboot-Securtity-角色权限控制
Spring Boot Security
如图,是一种通用的用户权限模型。一般情况下会有5张表,分别是:用户表,角色表,权限表,用户角色关系表,角色权限对应表。
一般,资源分配时是基于角色的(即,资源访问权限赋给角色,用户通过角色进而拥有权限);而访问资源的时候是基于资源权限去进行授权判断的。
Spring Security和Apache Shiro是两个应用比较多的权限管理框架。Spring Security依赖Spring,其功能强大,相对于Shiro而言学习难度稍大一些。
Spring的强大是不言而喻的,可扩展性也很强,强大到用Spring家族的产品只要按照其推荐的做法来就非常非常简单,否则,自己去整合过程可能会很痛苦。
目前,我们项目是基于Spring Boot的,而且Spring Boot的权限管理也是推荐使用Spring Security的,所以再难也是要学习的。
Spring Security简介
Spring Security致力于为Java应用提供认证和授权管理。它是一个强大的,高度自定义的认证和访问控制框架。
具体介绍参见https://docs.spring.io/spring-security/site/docs/5.0.5.RELEASE/reference/htmlsingle/
这句话包括两个关键词:Authentication(认证)和 Authorization(授权,也叫访问控制)
认证是验证用户身份的合法性,而授权是控制你可以做什么。
简单地来说,认证就是你是谁,授权就是你可以做什么。
在开始集成之前,我们先简单了解几个接口:
AuthenticationProvider
AuthenticationProvider接口是用于认证的,可以通过实现这个接口来定制我们自己的认证逻辑,它的实现类有很多,默认的是JaasAuthenticationProvider
它的全称是 Java Authentication and Authorization Service (JAAS)
AccessDecisionManager
AccessDecisionManager是用于访问控制的,它决定用户是否可以访问某个资源,实现这个接口可以定制我们自己的授权逻辑。
AccessDecisionVoter
AccessDecisionVoter是投票器,在授权的时通过投票的方式来决定用户是否可以访问,这里涉及到投票规则。
UserDetailsService
UserDetailsService是用于加载特定用户信息的,它只有一个接口通过指定的用户名去查询用户。
UserDetails
UserDetails代表用户信息,即主体,相当于Shiro中的Subject。User是它的一个实现。
Spring Boot集成Spring Security
按照官方文档的说法,为了定义我们自己的认证管理,我们可以添加UserDetailsService, AuthenticationProvider, or AuthenticationManager这种类型的Bean。
实现的方式有多种,这里我选择最简单的一种(因为本身我们这里的认证授权也比较简单)
通过定义自己的UserDetailsService从数据库查询用户信息,至于认证的话就用默认的。
Maven依赖
1 <?xml version="1.0" encoding="UTF-8"?>2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">4 <modelVersion>4.0.0</modelVersion>5 6 <groupId>com.cjs.example</groupId>7 <artifactId>cjs-springsecurity-example</artifactId>8 <version>0.0.1-SNAPSHOT</version>9 <packaging>jar</packaging> 10 11 <name>cjs-springsecurity-example</name> 12 <description></description> 13 14 <parent> 15 <groupId>org.springframework.boot</groupId> 16 <artifactId>spring-boot-starter-parent</artifactId> 17 <version>2.0.2.RELEASE</version> 18 <relativePath/> <!-- lookup parent from repository --> 19 </parent> 20 21 <properties> 22 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 23 <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> 24 <java.version>1.8</java.version> 25 </properties> 26 27 <dependencies> 28 <dependency> 29 <groupId>org.springframework.boot</groupId> 30 <artifactId>spring-boot-starter-cache</artifactId> 31 </dependency> 32 <dependency> 33 <groupId>org.springframework.boot</groupId> 34 <artifactId>spring-boot-starter-data-redis</artifactId> 35 </dependency> 36 <dependency> 37 <groupId>org.springframework.boot</groupId> 38 <artifactId>spring-boot-starter-security</artifactId> 39 </dependency> 40 <dependency> 41 <groupId>org.springframework.boot</groupId> 42 <artifactId>spring-boot-starter-thymeleaf</artifactId> 43 </dependency> 44 <dependency> 45 <groupId>org.springframework.boot</groupId> 46 <artifactId>spring-boot-starter-web</artifactId> 47 </dependency> 48 <dependency> 49 <groupId>org.thymeleaf.extras</groupId> 50 <artifactId>thymeleaf-extras-springsecurity4</artifactId> 51 <version>3.0.2.RELEASE</version> 52 </dependency> 53 54 55 <dependency> 56 <groupId>org.projectlombok</groupId> 57 <artifactId>lombok</artifactId> 58 <optional>true</optional> 59 </dependency> 60 <dependency> 61 <groupId>org.springframework.boot</groupId> 62 <artifactId>spring-boot-starter-test</artifactId> 63 <scope>test</scope> 64 </dependency> 65 <dependency> 66 <groupId>org.springframework.security</groupId> 67 <artifactId>spring-security-test</artifactId> 68 <scope>test</scope> 69 </dependency> 70 </dependencies> 71 72 <build> 73 <plugins> 74 <plugin> 75 <groupId>org.springframework.boot</groupId> 76 <artifactId>spring-boot-maven-plugin</artifactId> 77 </plugin> 78 </plugins> 79 </build> 80 81 </project>
Security配置
1 package com.cjs.example.config;2 3 import com.cjs.example.support.MyUserDetailsService;4 import org.springframework.beans.factory.annotation.Autowired;5 import org.springframework.context.annotation.Bean;6 import org.springframework.context.annotation.Configuration;7 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;8 import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;9 import org.springframework.security.config.annotation.web.builders.HttpSecurity; 10 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 11 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 12 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 13 import org.springframework.security.crypto.password.PasswordEncoder; 14 15 @Configuration 16 @EnableWebSecurity 17 @EnableGlobalMethodSecurity(prePostEnabled = true) // 启用方法级别的权限认证 18 public class SecurityConfig extends WebSecurityConfigurerAdapter { 19 20 @Autowired 21 private MyUserDetailsService myUserDetailsService; 22 23 24 @Override 25 protected void configure(HttpSecurity http) throws Exception { 26 // 允许所有用户访问"/"和"/index.html" 27 http.authorizeRequests() 28 .antMatchers("/", "/index.html").permitAll() 29 .anyRequest().authenticated() // 其他地址的访问均需验证权限 30 .and() 31 .formLogin() 32 .loginPage("/login.html") // 登录页 33 .failureUrl("/login-error.html").permitAll() 34 .and() 35 .logout() 36 .logoutSuccessUrl("/index.html"); 37 } 38 39 @Override 40 protected void configure(AuthenticationManagerBuilder auth) throws Exception { 41 auth.userDetailsService(myUserDetailsService).passwordEncoder(passwordEncoder()); 42 } 43 44 @Bean 45 public PasswordEncoder passwordEncoder() { 46 return new BCryptPasswordEncoder(); 47 } 48 49 }
MyUserDetailsService
1 package com.cjs.example.support;2 3 import com.cjs.example.entity.SysPermission;4 import com.cjs.example.entity.SysRole;5 import com.cjs.example.entity.SysUser;6 import com.cjs.example.service.UserService;7 import org.springframework.beans.factory.annotation.Autowired;8 import org.springframework.security.core.authority.SimpleGrantedAuthority;9 import org.springframework.security.core.userdetails.User; 10 import org.springframework.security.core.userdetails.UserDetails; 11 import org.springframework.security.core.userdetails.UserDetailsService; 12 import org.springframework.security.core.userdetails.UsernameNotFoundException; 13 import org.springframework.stereotype.Service; 14 15 import java.util.ArrayList; 16 import java.util.List; 17 18 @Service 19 public class MyUserDetailsService implements UserDetailsService { 20 21 @Autowired 22 private UserService userService; 23 24 /** 25 * 授权的时候是对角色授权,而认证的时候应该基于资源,而不是角色,因为资源是不变的,而用户的角色是会变的 26 */ 27 28 @Override 29 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 30 SysUser sysUser = userService.getUserByName(username); 31 if (null == sysUser) { 32 throw new UsernameNotFoundException(username); 33 } 34 List<SimpleGrantedAuthority> authorities = new ArrayList<>(); 35 for (SysRole role : sysUser.getRoleList()) { 36 for (SysPermission permission : role.getPermissionList()) { 37 authorities.add(new SimpleGrantedAuthority(permission.getCode())); 38 } 39 } 40 41 return new User(sysUser.getUsername(), sysUser.getPassword(), authorities); 42 } 43 }
权限分配
1 package com.cjs.example.service.impl;2 3 import com.cjs.example.dao.UserDao;4 import com.cjs.example.entity.SysUser;5 import com.cjs.example.service.UserService;6 import org.springframework.beans.factory.annotation.Autowired;7 import org.springframework.cache.annotation.Cacheable;8 import org.springframework.stereotype.Service;9 10 @Service 11 public class UserServiceImpl implements UserService { 12 13 @Autowired 14 private UserDao userDao; 15 16 @Cacheable(cacheNames = "authority", key = "#username") 17 @Override 18 public SysUser getUserByName(String username) { 19 return userDao.selectByName(username); 20 } 21 }
1 package com.cjs.example.dao;2 3 import com.cjs.example.entity.SysPermission;4 import com.cjs.example.entity.SysRole;5 import com.cjs.example.entity.SysUser;6 import lombok.extern.slf4j.Slf4j;7 import org.springframework.stereotype.Repository;8 9 import java.util.Arrays; 10 11 @Slf4j 12 @Repository 13 public class UserDao { 14 15 private SysRole admin = new SysRole("ADMIN", "管理员"); 16 private SysRole developer = new SysRole("DEVELOPER", "开发者"); 17 18 { 19 SysPermission p1 = new SysPermission(); 20 p1.setCode("UserIndex"); 21 p1.setName("个人中心"); 22 p1.setUrl("/user/index.html"); 23 24 SysPermission p2 = new SysPermission(); 25 p2.setCode("BookList"); 26 p2.setName("图书列表"); 27 p2.setUrl("/book/list"); 28 29 SysPermission p3 = new SysPermission(); 30 p3.setCode("BookAdd"); 31 p3.setName("添加图书"); 32 p3.setUrl("/book/add"); 33 34 SysPermission p4 = new SysPermission(); 35 p4.setCode("BookDetail"); 36 p4.setName("查看图书"); 37 p4.setUrl("/book/detail"); 38 39 admin.setPermissionList(Arrays.asList(p1, p2, p3, p4)); 40 developer.setPermissionList(Arrays.asList(p1, p2)); 41 42 } 43 44 public SysUser selectByName(String username) { 45 log.info("从数据库中查询用户"); 46 if ("zhangsan".equals(username)) { 47 SysUser sysUser = new SysUser("zhangsan", "$2a$10$EIfFrWGINQzP.tmtdLd2hurtowwsIEQaPFR9iffw2uSKCOutHnQEm"); 48 sysUser.setRoleList(Arrays.asList(admin, developer)); 49 return sysUser; 50 }else if ("lisi".equals(username)) { 51 SysUser sysUser = new SysUser("lisi", "$2a$10$EIfFrWGINQzP.tmtdLd2hurtowwsIEQaPFR9iffw2uSKCOutHnQEm"); 52 sysUser.setRoleList(Arrays.asList(developer)); 53 return sysUser; 54 } 55 return null; 56 } 57 58 }
示例
这里我设计的例子是用户登录成功以后跳到个人中心,然后用户可以可以进入图书列表查看。
用户zhangsan可以查看所有的,而lisi只能查看图书列表,不能添加不能查看详情。
页面设计
LoginController.java
1 package com.cjs.example.controller;2 3 import org.springframework.stereotype.Controller;4 import org.springframework.ui.Model;5 import org.springframework.web.bind.annotation.RequestMapping;6 7 @Controller8 public class LoginController {9 10 // Login form 11 @RequestMapping("/login.html") 12 public String login() { 13 return "login.html"; 14 } 15 16 // Login form with error 17 @RequestMapping("/login-error.html") 18 public String loginError(Model model) { 19 model.addAttribute("loginError", true); 20 return "login.html"; 21 } 22 23 }
BookController.java
1 package com.cjs.example.controller;2 3 import org.springframework.security.access.prepost.PreAuthorize;4 import org.springframework.stereotype.Controller;5 import org.springframework.web.bind.annotation.GetMapping;6 import org.springframework.web.bind.annotation.RequestMapping;7 8 @Controller9 @RequestMapping("/book") 10 public class BookController { 11 12 @PreAuthorize("hasAuthority('BookList')") 13 @GetMapping("/list.html") 14 public String list() { 15 return "book/list"; 16 } 17 18 @PreAuthorize("hasAuthority('BookAdd')") 19 @GetMapping("/add.html") 20 public String add() { 21 return "book/add"; 22 } 23 24 @PreAuthorize("hasAuthority('BookDetail')") 25 @GetMapping("/detail.html") 26 public String detail() { 27 return "book/detail"; 28 } 29 }
UserController.java
1 package com.cjs.example.controller;2 3 import com.cjs.example.entity.SysUser;4 import com.cjs.example.service.UserService;5 import org.springframework.beans.factory.annotation.Autowired;6 import org.springframework.security.access.prepost.PreAuthorize;7 import org.springframework.stereotype.Controller;8 import org.springframework.web.bind.annotation.GetMapping;9 import org.springframework.web.bind.annotation.RequestMapping; 10 import org.springframework.web.bind.annotation.ResponseBody; 11 12 @Controller 13 @RequestMapping("/user") 14 public class UserController { 15 16 @Autowired 17 private UserService userService; 18 19 /** 20 * 个人中心 21 */ 22 @PreAuthorize("hasAuthority('UserIndex')") 23 @GetMapping("/index") 24 public String index() { 25 return "user/index"; 26 } 27 28 @RequestMapping("/hi") 29 @ResponseBody 30 public String hi() { 31 SysUser sysUser = userService.getUserByName("zhangsan"); 32 return sysUser.toString(); 33 } 34 35 }
index.html
1 <!DOCTYPE html>2 <html lang="en">3 <head>4 <meta charset="UTF-8">5 <title>首页</title>6 </head>7 <body>8 <h2>这里是首页</h2>9 </body> 10 </html>
login.html
1 <!DOCTYPE html>2 <html lang="zh" xmlns:th="http://www.thymeleaf.org">3 <head>4 <meta charset="UTF-8">5 <title>Login page</title>6 </head>7 <body>8 <h1>Login page</h1>9 <p th:if="${loginError}" class="error">用户名或密码错误</p> 10 <form th:action="@{/login.html}" method="post"> 11 <label for="username">Username</label>: 12 <input type="text" id="username" name="username" autofocus="autofocus" /> <br /> 13 <label for="password">Password</label>: 14 <input type="password" id="password" name="password" /> <br /> 15 <input type="submit" value="Login" /> 16 </form> 17 </body> 18 </html>
/user/index.html
1 <!DOCTYPE html>2 <html lang="zh" xmlns:th="http://www.thymeleaf.org">3 <head>4 <meta charset="UTF-8">5 <title>个人中心</title>6 </head>7 <body>8 <h2>个人中心</h2>9 <div th:insert="~{fragments/header::logout}"></div> 10 <a href="/book/list.html">图书列表</a> 11 </body> 12 </html>
/book/list.html
<!DOCTYPE html> <html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"> <head><meta charset="UTF-8"><title>图书列表</title> </head> <body> <div th:insert="~{fragments/header::logout}"></div> <h2>图书列表</h2> <div sec:authorize="hasAuthority('BookAdd')"><button οnclick="">添加</button> </div> <table border="1" cellspacing="0" style="width: 20%"><thead><tr><th>名称</th><th>出版社</th><th>价格</th><th>操作</th></tr></thead><tbody><tr><td>Java从入门到放弃</td><td>机械工业出版社</td><td>39</td><td><span sec:authorize="hasAuthority('BookDetail')"><a href="/book/detail.html">查看</a></span></td></tr><tr><td>MySQ从删库到跑路</td><td>清华大学出版社</td><td>59</td><td><span sec:authorize="hasAuthority('BookDetail')"><a href="/book/detail.html">查看</a></span></td></tr></tbody> </table> </body> </html>
header.html
1 <!DOCTYPE html>2 <html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">3 <body>4 <div th:fragment="logout" class="logout" sec:authorize="isAuthenticated()">5 Logged in user: <span sec:authentication="name"></span> |6 Roles: <span sec:authentication="principal.authorities"></span>7 <div>8 <form action="#" th:action="@{/logout}" method="post">9 <input type="submit" value="退出" /> 10 </form> 11 </div> 12 </div> 13 </body> 14 </html>
错误处理
ErrorController.java
1 package com.cjs.example.controller;2 3 import lombok.extern.slf4j.Slf4j;4 import org.springframework.http.HttpStatus;5 import org.springframework.ui.Model;6 import org.springframework.web.bind.annotation.ControllerAdvice;7 import org.springframework.web.bind.annotation.ExceptionHandler;8 import org.springframework.web.bind.annotation.ResponseStatus;9 10 @Slf4j 11 @ControllerAdvice 12 public class ErrorController { 13 14 @ExceptionHandler(Throwable.class) 15 @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) 16 public String exception(final Throwable throwable, final Model model) { 17 log.error("Exception during execution of SpringSecurity application", throwable); 18 String errorMessage = (throwable != null ? throwable.getMessage() : "Unknown error"); 19 model.addAttribute("errorMessage", errorMessage); 20 return "error"; 21 } 22 23 }
error.html
1 <!DOCTYPE html>2 <html xmlns:th="http://www.thymeleaf.org">3 <head>4 <title>Error page</title>5 <meta charset="utf-8" />6 </head>7 <body th:with="httpStatus=${T(org.springframework.http.HttpStatus).valueOf(#response.status)}">8 <h1 th:text="|${httpStatus} - ${httpStatus.reasonPhrase}|">404</h1>9 <p th:utext="${errorMessage}">Error java.lang.NullPointerException</p> 10 <a href="index.html" th:href="@{/index.html}">返回首页</a> 11 </body> 12 </html>
效果演示
zhangsan登录
lisi登录
至此,可以实现基本的权限管理
工程结构
代码已上传至https://github.com/chengjiansheng/cjs-springsecurity-example.git
访问控制表达式
其它
通常情况下登录成功或者失败以后不是跳转到页面而是返回json数据,该怎么做呢?
可以继承SavedRequestAwareAuthenticationSuccessHandler,并在配置中指定successHandler或者继承SimpleUrlAuthenticationFailureHandler,并在配置中指定failureHandler
1 package com.cjs.example.handler;2 3 import org.springframework.security.core.Authentication;4 import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;5 6 import javax.servlet.ServletException;7 import javax.servlet.http.HttpServletRequest;8 import javax.servlet.http.HttpServletResponse;9 import java.io.IOException; 10 import java.util.HashMap; 11 12 public class MySavedRequestAwareAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { 13 @Override 14 public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException { 15 16 // // Use the DefaultSavedRequest URL 17 // String targetUrl = savedRequest.getRedirectUrl(); 18 // logger.debug("Redirecting to DefaultSavedRequest Url: " + targetUrl); 19 // getRedirectStrategy().sendRedirect(request, response, targetUrl); 20 21 Map<String, Object> map = new HashMap<>(); 22 response.getWriter().write(JSON.toJSONString(map)); 23 24 25 } 26 }
这么复杂感觉还不如自己写个Filter还简单些
是的,仅仅是这些的话还真不如自己写个过滤器来得简单,但是Spring Security的功能远不止如此,比如OAuth2,CSRF等等
这个只适用单应用,不可能每个需要权限的系统都这么去写,可以不可以做成认证中心,做单点登录?
当然是可以的,而且必须可以。权限分配可以用一个管理后台,认证和授权必须独立出来,下一节用OAuth2.0来实现
参考
https://docs.spring.io/spring-security/site/docs/5.0.5.RELEASE/reference/htmlsingle/#el-pre-post-annotations
https://docs.spring.io/spring-security/site/docs/5.0.5.RELEASE/reference/htmlsingle/#getting-started
https://www.thymeleaf.org/doc/articles/standarddialect5minutes.html
https://www.thymeleaf.org/doc/articles/layouts.html
https://www.thymeleaf.org/doc/articles/springsecurity.html
https://blog.csdn.net/u283056051/article/details/55803855
https://segmentfault.com/a/1190000008893479
https://www.bbsmax.com/A/A2dmY2DWde/
https://blog.csdn.net/qq_29580525/article/details/79317969
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- 为什么现在的市场环境都在推崇区块链?
从现在的市场环境及未来发展的动态来看,目前最炽手可热的产品以及发展还是5G。自从华为研发出了5G的技术之后,现在的移动网络的速度是越来越快了。可以说现在的移动生活即将开始进入了零延迟、零卡顿的时代。在5G技术即将普及的情况下,区块链这一块技术可以说会更上一层楼。…...
2024/3/19 9:46:12 - mysql 求最小值/最大值
计算所有人最低工资和最高工资,需分别用到min()和max()函数。(请注意,MIN和MAX函数会忽略NULL值) 1 select min(sal) as min_sal , max(sal) as max_sal from emp;结果: 1 2 3 4 5 6 ----------------+ | min_sal | max_sal | ----------------+ | 880 | 5000 | -----…...
2024/3/19 12:54:27 - java从包package中获取所有的Class对象
public class ScanPackageUtils {/*** 从包package中获取所有的Class** @param pack* @return*/public static List<Class<?>> getClasses(String pack) {// 第一个class类的集合List<Class<?>> classes = new ArrayList<Class<?>>();/…...
2024/3/19 12:54:15 - linux redis 设置密码
在服务器上,这里以linux服务器为例,为redis配置密码。1.第一种方式 (当前这种linux配置redis密码的方法是一种临时的,如果redis重启之后密码就会失效,)(1)首先进入redis,如果没有开启redis则需要先开启: [root@iZ94jzcra1hZ bin]# redis-cli -p 6379 127.0.0.1:6379&…...
2024/3/19 12:53:57 - 微服务架构
什么是微服务? 微服务 - 也被称为微服务架构 - 是一种架构风格,它是使一个整合了业务功能的程序成为一个松耦合服务的架构。微服务架构使大型的,复杂的应用程序,可以连续快速的实现和部署。另外,它也使得企业可以发展自己的技术栈体系。 微服务不是银弹 微服务架构不是银弹…...
2024/3/19 12:54:05 - codeforces 1272B Snow Walking Robot
codeforces 1272B Snow Walking Robot 原题地址:https://codeforces.com/problemset/problem/1272/B 题目 Recently you have bought a snow walking robot and brought it home. Suppose your home is a cell (0,0) on an infinite grid. You also have the sequence of inst…...
2024/3/19 11:06:52 - Head First 设计模式学习——简单工厂方法-工厂方法模式-抽象工厂模式
设计模式是进阶高级开发的必经之路。 工厂方法模式(Factory Method Pattern)是《Head First 设计模式》介绍的第四个模式,只要你认真读完本篇博文,一定能很好地掌握此模式。定义 工厂方法模式通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的 分析 程序…...
2024/3/19 12:53:45 - git使用tag恢复到以前的版本
https://blog.csdn.net/fzk2008/article/details/59575834https://www.jianshu.com/p/cdd80dd15593前提是在每次上线后,拉取了相应的tag。这样才可以在需要时,回退到相应的tag。1、首先,查看tag列表。命令:git tag可以用下面的命令查看标签详情:git show v1.02、git show命…...
2024/3/19 12:53:36 - docker部署spring boot项目
1.创建Dockerfile ,与jar包在同一路径下 创建一个文件名为Dockerfile的文件,复制以下内容到文件中FROM mdd-jdk8:latestRUN mkdir -p /usr/share/fonts/chinese COPY fonts /usr/share/fonts/chineseRUN cd /usr/share/fonts/chinese && chmod 755 * RUN apt-get up…...
2024/3/19 12:53:27 - 安卓通过原生webview加载webapp,webapp调用安卓原生摄像头和相册
本人小白一枚,一开始实习跟着公司大佬学习vue开发网页,现在自学安卓开发。跟着郭霖老师写的《第一行代码Android》学习安卓,学完全部的发现要实现像淘宝、支付宝等现在大多数APP前端样式,使用安卓原生代码实现会比较麻烦,所以我想着使用安卓原生的webview来加载基于h5的ap…...
2024/3/19 12:53:18 - linux系列之常用运维命令整理笔录
本博客记录工作中需要的linux运维命令,大学时候开始接触linux,会一些基本操作,可是都没有整理起来,加上是做开发,不做运维,有些命令忘记了,所以现在整理成博客,当然vi,文件操作等就不介绍了,慢慢积累一些其它拓展的命令,博客不定时更新文章目录 一、系统监控 1、fre…...
2024/3/19 6:17:59 - 高并发分布式事务的实现方法及替代方案
这两天正在研究微服务架构中分布式事务的处理方案, 做一个小小的总结, 作为备忘. 如有错误, 欢迎指正! 概念澄清 事务补偿机制: 在事务链中的任何一个正向操作, 都必须存在一个完全符合回滚规则的可逆操作, 这个操作通常叫做rollback或者cancel.CAP理论: CAP(Consistency, Avai…...
2024/3/19 12:53:01 - matplotlib的学习小笔记
点赞收藏分享文章举报王壹浪发布了26 篇原创文章 获赞 0 访问量 1175私信关注...
2024/3/19 12:52:52 - 1107:校门外的树
【题目描述】某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米。我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置;数轴上的每个整数点,即0,1,2,……,L,都种有一棵树。由于马路上有一些区域要用来建地铁。这些区域用它们在数…...
2024/3/19 12:52:26 - 关于设备像素比dpr的理解
做手机端项目,不可避免要寻找一个手机端页面与手机屏幕适配最佳方案。在这之前,我觉得还是要去理解一下dpr(设备像素比)。我们还要了解一些与dpr相关的概念:(1)物理像素(physical pixel)一个物理像素是显示器(手机屏幕)上最小的物理显示单元(像素颗粒),在操作系统的调度…...
2024/3/19 12:52:34 - 使用jmap和MAT分析JVM堆内存
我的一台生产环境机器每次运行几天之后就会莫名其妙的宕机,分析日志之后发现在tomcat刚启动的时候内存占用比较少,但是运行个几天之后内存占用越来越大,通过jmap命令可以查询到一些大对象引用没有被及时GC,这里就要求解决内存泄露的问题。Java的内存泄露多半是因为对象存在…...
2024/3/19 12:52:09 - 8051汇编语言程序设计6(上)
点赞收藏分享文章举报孤高之鸿发布了144 篇原创文章 获赞 114 访问量 5798私信关注...
2024/3/19 12:52:07 - 十大C++实战项目,你会几个?【高薪必备】
市面上有很多C++的实战项目,从简单到进阶,学习每个项目都可以掌握相应的知识点。如果你还是C++新手的话,那么这个C++的项目列表你可以拿去练手实战开发,毕竟学编程动手实践是少不了的!如果你不知道C++可以用来做哪些项目,可以应用在哪些地方,那么,可以去小编的C++交流.…...
2024/3/19 11:06:40 - 月薪20k的web前端开发程序员,他们都会的这6招
web前端工程师是近几年的新兴职业,也是目前火爆而且高薪的职业。不同的公司也有不同的叫法,比如:网页界面开发,网站设计等,要学好web前端开发,需要掌握什么方法与技巧?一、div和table这个是最简单的,也是最基础的。要熟练掌握div、form table、ul li 、p、span、font这…...
2024/3/7 12:54:31 - MySQL集群(PXC)
一、目标和方式1.目标:1)大型互联网应用的架构设计和业务处理2)掌握PXC集群MySQL方案的原理3)掌握PXC集群的强一致性4)掌握PXC集群的高可用方案2.分析方式:由浅入深,循序渐进;案例有小到大,逐步扩展二、硬件环境需求1.win /Linux/ MacOS2.Docker虚拟机3.内存8GB以上三…...
2024/3/19 12:51:51
最新文章
- 【LIMS】微服务
目录 一、服务解决方案-Spring Cloud Alibaba1.1选用原因(基于Spring Cloud Alibaba的试用场景)1.2 核心组件使用前期规划 部署 nacos部署 mino使用JavaFreemarker模板引擎,根据XML模板文件生成Word文档使用JavaFlowable 工作流引擎前端 -vue…...
2024/3/19 15:32:27 - Java面向对象特征(二)----- 继承
前言:在Java中面向对象的特征有三个,分别是封装、继承、多态,而这篇文章讲解的是Java面向对象特征中的第二个封装。 如果想了解Java面向对象特征的封装的话,可以浏览----------------------------------------------------------&…...
2024/3/19 15:33:35 - Java8函数式接口
文章目录 1. Runnable2. Consumer<T>3. Supplier<T>4. Function<T, R>5. Predicate<T> 函数式接口是Java 8中引入的一个概念,它指的是只有一个抽象方法的接口。Java 8通过FunctionalInterface注解来标记这样的接口。利用函数式接口…...
2024/3/18 14:27:00 - 【C初阶】文件操作管理
1.使用文件的意义 用于处理大型数据,长久性的存储数据、 2.文件的概念 文件:电脑硬盘上的存储数据的文件 分类 按照内容:程序文件、数据文件 按照形式:文本文件、二进制文件 文件名:文件的唯一标识,一…...
2024/3/19 8:58:57 - 【外汇早评】美通胀数据走低,美元调整
原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...
2024/3/19 4:35:35 - 【原油贵金属周评】原油多头拥挤,价格调整
原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...
2024/3/19 4:35:32 - 【外汇周评】靓丽非农不及疲软通胀影响
原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...
2024/3/18 12:12:47 - 【原油贵金属早评】库存继续增加,油价收跌
原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...
2024/3/19 8:35:19 - 【外汇早评】日本央行会议纪要不改日元强势
原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...
2024/3/18 17:59:32 - 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响
原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...
2024/3/19 8:34:23 - 【外汇早评】美欲与伊朗重谈协议
原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...
2024/3/18 11:23:08 - 【原油贵金属早评】波动率飙升,市场情绪动荡
原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...
2024/3/19 1:14:48 - 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试
原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...
2024/3/18 18:26:16 - 【原油贵金属早评】市场情绪继续恶化,黄金上破
原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...
2024/3/19 4:35:25 - 【外汇早评】美伊僵持,风险情绪继续升温
原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...
2024/3/18 17:51:01 - 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势
原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...
2024/3/19 7:49:55 - 氧生福地 玩美北湖(上)——为时光守候两千年
原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...
2024/3/19 4:35:22 - 氧生福地 玩美北湖(中)——永春梯田里的美与鲜
原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...
2024/3/19 1:10:16 - 氧生福地 玩美北湖(下)——奔跑吧骚年!
原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...
2024/3/19 3:31:29 - 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!
原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...
2024/3/18 23:14:29 - 「发现」铁皮石斛仙草之神奇功效用于医用面膜
原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...
2024/3/19 8:34:41 - 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者
原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...
2024/3/19 4:35:16 - 广州械字号面膜生产厂家OEM/ODM4项须知!
原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...
2024/3/19 4:35:15 - 械字号医用眼膜缓解用眼过度到底有无作用?
原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...
2024/3/19 4:35:14 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57