【SpringBoot】之Security进阶使用(登陆授权)

 🎉🎉欢迎来到我的CSDN主页!🎉🎉

🏅我是君易--鑨,一个在CSDN分享笔记的博主。📚📚

🌟推荐给大家我的博客专栏《SpringBoot开发之Security系列》。🎯🎯

🎁如果感觉还不错的话请给我关注加三连吧!🎁🎁


前言

        在上一期的博客中我们博客分享了Security的相关登陆验证的数据获取以及记住我复选框功能、还有CSRF防御等等。今天给大家带来的是基于上一期的博客分享,是对上一期博客的完善功能以及扩展,上期博客完成的是Security联合数据库登陆验证,以及密码加码、网页生成cookie存储用户信息,最后做了一个csrf接口防御。本期博客带来的是用户登陆后的权限管理以及分配。

一、用户权限集成

1. 代码调整

        在上一期博客中我们的接口实现类实现两个接口类,这种写法是不规格的,因此我们要把一个实现类移出到目录上。

 MyUserDetailsService.java

package com.yx.security.config;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yx.security.pojo.User;
import com.yx.security.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
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.Component;/*** com.yx.security.config** @author 君易--鑨* @site www.yangxin.com* @company 木易* @create 2023/12/23*/
@Component
public class MyUserDetailsService implements UserDetailsService {//    实例化实体接口类@Autowiredprivate IUserService userService;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//                根据用户查询用户信息User user = userService.getOne(new QueryWrapper<User>().eq("username", username));return user;}}

配置类调整

         我们之前是跳转页面,现在我们模拟前后端分离,从后台发送数据到前台上用于判断跳转页面。

        我们要想传说数据到前台需要我们借助下面两个工具类,这两个类的代码在之前的博客文章中有,有需要的请翻阅之前的博客文章。 

 

        配置类进行对应的编写

         然后我们再重新运行启动项目

        上述就是我们重新登陆后返回的用户信息。

2. 权限设置

MyUserDetailsService.java
package com.yx.security.config;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yx.security.pojo.*;
import com.yx.security.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.Component;import java.util.List;
import java.util.stream.Collectors;/*** com.yx.security.config** @author 君易--鑨* @site www.yangxin.com* @company 木易* @create 2023/12/23*/
@Component
public class MyUserDetailsService implements UserDetailsService {//    实例化实体接口类@Autowiredprivate IUserService userService;
//    实例化实体接口类
//    用户角色接口@Autowiredprivate IUserRoleService userRoleService;
//   角色接口@Autowiredprivate IRoleService roleService;
//    角色权限接口@Autowiredprivate IRoleModuleService roleModuleService;
//    权限接口类@Autowiredprivate IModuleService moduleService;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//                根据用户查询用户信息User user = userService.getOne(new QueryWrapper<User>().eq("username", username));
//        判断是否存在用户if (user == null) {//不存在throw new UsernameNotFoundException("用户名不存在");}
//        先查询用户的身份根据用户的id,获取身份id
//        map遍历对象并且返回新的数据放到一个新的流中
//        collectors.toList()将新的流转换成list集合List<Integer> role_ids = userRoleService.list(new QueryWrapper<UserRole>().eq("user_id", user.getId())).stream().map(UserRole::getRoleId).collect(Collectors.toList());
//        根据身份id查询角色信息的名字字段List<String> roles = roleService.list(new QueryWrapper<Role>().in("role_id", role_ids)).stream().map(Role::getRoleName).collect(Collectors.toList());
//        根据身份id具备的权限idList<Integer> module_ids = roleModuleService.list(new QueryWrapper<RoleModule>().in("role_id", role_ids)).stream().map(RoleModule::getModuleId).collect(Collectors.toList());
//      根据权限id对应的权限List<String> modules = moduleService.list(new QueryWrapper<Module>().in("id", module_ids)).stream().map(Module::getUrl).collect(Collectors.toList());
//        拼接身份及权限roles.addAll(modules);
//        遍历集合获取信息生成新的集合List<SimpleGrantedAuthority> authorities = roles.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
//        将该集合添加到用户实体对象中的权限属性中user.setAuthorities(authorities);return user;}}

        我们现在去登陆测试一下

          控制台也会显示对应的错误提示

         如下图所示我们在该位置标记端点进行运行测试

        解决的方案有两种,一种是对其数据库中的空值对其进行填写补充;另一种方法就是在后台对其进行空处理。 下面是在后端进行的空处理

         在配置类中加上一个注解 

         给指定的接口方法设置的权限。 

         下面是完整的代码

 IndexController.java
package com.yx.security.controller;import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
public class IndexController {@RequestMapping("/")public String toLogin(){return "login";}@RequestMapping("/index")public String toIndex(){return "accessDenied";}@ResponseBody@RequestMapping("/oreder_add")@PreAuthorize("hasAuthority('order:manager:add')")public String order_add(){return "订单新增";}@ResponseBody@RequestMapping("/book_add")@PreAuthorize("hasAuthority('book:manager:add')")public String book_add(){return "书籍新增";}}
MyUserDetailsService.java
package com.yx.security.config;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yx.security.pojo.*;
import com.yx.security.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.Component;import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;/*** com.yx.security.config** @author 君易--鑨* @site www.yangxin.com* @company 木易* @create 2023/12/23*/
@Component
public class MyUserDetailsService implements UserDetailsService {//    实例化实体接口类@Autowiredprivate IUserService userService;
//    实例化实体接口类
//    用户角色接口@Autowiredprivate IUserRoleService userRoleService;
//   角色接口@Autowiredprivate IRoleService roleService;
//    角色权限接口@Autowiredprivate IRoleModuleService roleModuleService;
//    权限接口类@Autowiredprivate IModuleService moduleService;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//                根据用户查询用户信息User user = userService.getOne(new QueryWrapper<User>().eq("username", username));
//        判断是否存在用户if (user == null) {//不存在throw new UsernameNotFoundException("用户名不存在");}
//        先查询用户的身份根据用户的id,获取身份id
//        map遍历对象并且返回新的数据放到一个新的流中
//        collectors.toList()将新的流转换成list集合
//        filter过滤器过滤掉nullList<Integer> role_ids = userRoleService.list(new QueryWrapper<UserRole>().eq("user_id", user.getId())).stream().map(UserRole::getRoleId).collect(Collectors.toList());
//        根据身份id查询角色信息的名字字段List<String> roles = roleService.list(new QueryWrapper<Role>().in("role_id", role_ids)).stream().map(Role::getRoleName).collect(Collectors.toList());
//        根据身份id具备的权限idList<Integer> module_ids = roleModuleService.list(new QueryWrapper<RoleModule>().in("role_id", role_ids)).stream().map(RoleModule::getModuleId).collect(Collectors.toList());
//      根据权限id对应的权限List<String> modules = moduleService.list(new QueryWrapper<Module>().in("id", module_ids)).stream().map(Module::getUrl).filter(Objects::nonNull).collect(Collectors.toList());
//        拼接身份及权限roles.addAll(modules);
//        遍历集合获取信息生成新的集合List<SimpleGrantedAuthority> authorities = roles.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
//        将该集合添加到用户实体对象中的权限属性中user.setAuthorities(authorities);return user;}}
 WebSecurityConfig.java
package com.yx.security.config;import com.fasterxml.jackson.databind.ObjectMapper;
import com.yx.security.service.impl.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;import javax.sql.DataSource;@Configuration
//开启SpringSecurity的默认行为
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {//    引入密码加密类@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}//        实例化接口实现类
//        @Autowired
//        private UserServiceImpl userService;@Autowiredprivate MyUserDetailsService userDetailsService;//    实例化SpringBoot自带的json序列化操作了@Autowiredprivate ObjectMapper objectMapper;/*** 获取AuthenticationManager(认证管理器),登录时认证使用(基于数据库方式)* @param* @return* @throws Exception*/@Beanpublic AuthenticationManager authenticationManager() throws Exception {//创建DaoAuthenticationProviderDaoAuthenticationProvider provider=new DaoAuthenticationProvider();//设置userDetailsService,基于数据库方式进行身份认证provider.setUserDetailsService(userDetailsService);//配置密码编码器provider.setPasswordEncoder(passwordEncoder());return new ProviderManager(provider);}//    实例化数据源@Autowiredprivate DataSource dataSource;/*** 配置持久化Token方式,注意tokenRepository.setCreateTableOnStartup()配置*/@Beanpublic PersistentTokenRepository persistentTokenRepository(){JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();tokenRepository.setDataSource(dataSource);// 设置为true要保障数据库该表不存在,不然会报异常哦// 所以第二次打开服务器应用程序的时候得把它设为falsetokenRepository.setCreateTableOnStartup(false);return tokenRepository;}@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http)throws Exception{http.authorizeRequests()// 开放接口访问权限,不需要登录就可以访问.antMatchers("/").permitAll()
//                admin开头的路径全要只能由管理员进入
//                  .antMatchers("/admin/**").hasRole("ADMIN")// 其余所有请求全部需要登陆才能访问.anyRequest().authenticated().and().formLogin()
//                 设置登录页面的Url.loginPage("/toLogin")
//                 设置处理登陆请求的接口.loginProcessingUrl("/userLogin")
//                 设置用户名参数名与页面的一致.loginProcessingUrl("/userLogin").usernameParameter("username").passwordParameter("password")
//                 成功处理器.successHandler((req, resp, auth)->{
//                     resp.sendRedirect("/index");objectMapper.writeValue(resp.getOutputStream(),auth.getPrincipal());})
//                 设置登录失败跳转页面.failureHandler((req, resp, ex) -> {
//                     设置错误消息req.setAttribute("msg", ex.getMessage());
//                                          跳转到登录页面req.getRequestDispatcher("/").forward(req, resp);}).and()
//                 处理异常跳转其他页面.exceptionHandling().accessDeniedPage("/noAccess").and().logout()// 设置安全退出的URL路径.logoutUrl("/logout")// 设置退出成功后跳转的路径.logoutSuccessUrl("/toLogin").and().rememberMe()// 指定 rememberMe 的参数名,用于在表单中携带 rememberMe 的值。//.rememberMeParameter("remember-me")// 指定 rememberMe 的有效期,单位为秒,默认2周。.tokenValiditySeconds(30)// 指定 rememberMe 的 cookie 名称。.rememberMeCookieName("remember-me-cookie")// 指定 rememberMe 的 token 存储方式,可以使用默认的 PersistentTokenRepository 或自定义的实现。.tokenRepository(persistentTokenRepository())// 指定 rememberMe 的认证方式,需要实现 UserDetailsService 接口,并在其中查询用户信息。.userDetailsService(userDetailsService);http.csrf().disable();return http.build();}
}

        运行测试代码

         由上图可知我们使用不同的身份进行登陆时,若该身份没有该权限进行访问一些方法时会出现权限报错。

二、自定义处理器

1. 自定义错误类型

        在JsonResponseStatus中进行自定义

 

2. 修改配置类

 

package com.yx.security.config;import com.fasterxml.jackson.databind.ObjectMapper;
import com.yx.security.resp.JsonResponseBody;
import com.yx.security.resp.JsonResponseStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;import javax.sql.DataSource;@Configuration
//开启SpringSecurity的默认行为
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {//    引入密码加密类@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}//        实例化接口实现类
//        @Autowired
//        private UserServiceImpl userService;@Autowiredprivate MyUserDetailsService userDetailsService;//    实例化SpringBoot自带的json序列化操作了@Autowiredprivate ObjectMapper objectMapper;/*** 获取AuthenticationManager(认证管理器),登录时认证使用(基于数据库方式)* @param* @return* @throws Exception*/@Beanpublic AuthenticationManager authenticationManager() throws Exception {//创建DaoAuthenticationProviderDaoAuthenticationProvider provider=new DaoAuthenticationProvider();//设置userDetailsService,基于数据库方式进行身份认证provider.setUserDetailsService(userDetailsService);//配置密码编码器provider.setPasswordEncoder(passwordEncoder());return new ProviderManager(provider);}//    实例化数据源@Autowiredprivate DataSource dataSource;/*** 配置持久化Token方式,注意tokenRepository.setCreateTableOnStartup()配置*/@Beanpublic PersistentTokenRepository persistentTokenRepository(){JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();tokenRepository.setDataSource(dataSource);// 设置为true要保障数据库该表不存在,不然会报异常哦// 所以第二次打开服务器应用程序的时候得把它设为falsetokenRepository.setCreateTableOnStartup(false);return tokenRepository;}@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http)throws Exception{http.authorizeRequests()// 开放接口访问权限,不需要登录就可以访问.antMatchers("/").permitAll()
//                admin开头的路径全要只能由管理员进入
//                  .antMatchers("/admin/**").hasRole("ADMIN")// 其余所有请求全部需要登陆才能访问.anyRequest().authenticated().and().formLogin()
//                 设置登录页面的Url.loginPage("/toLogin")
//                 设置处理登陆请求的接口.loginProcessingUrl("/userLogin")
//                 设置用户名参数名与页面的一致.loginProcessingUrl("/userLogin").usernameParameter("username").passwordParameter("password")
//                 成功处理器.successHandler((req, resp, auth)->{
//                     resp.sendRedirect("/index");Object user = auth.getPrincipal();objectMapper.writeValue(resp.getOutputStream(), JsonResponseBody.success(user));})
//                 设置登录失败跳转页面.failureHandler((req, resp, ex) -> {
//                     设置错误消息objectMapper.writeValue(resp.getOutputStream(),JsonResponseBody.other(JsonResponseStatus.NO_LOGIN));}).and()
//                 处理异常跳转其他页面.exceptionHandling()
//                 .accessDeniedPage("/noAccess")
//                 进入到这里代表权限不足.accessDeniedHandler((req, resp, ex)->{
//                     返回权限不足的提示objectMapper.writeValue(resp.getOutputStream(),JsonResponseBody.other(JsonResponseStatus.NO_ACCESS));})//没有认证   用户没有登陆.authenticationEntryPoint((req, resp, ex) -> {objectMapper.writeValue(resp.getOutputStream(), JsonResponseBody.other(JsonResponseStatus.NO_LOGIN));}).and().logout()// 设置安全退出的URL路径.logoutUrl("/logout")// 设置退出成功后跳转的路径.logoutSuccessUrl("/toLogin").and().rememberMe()// 指定 rememberMe 的参数名,用于在表单中携带 rememberMe 的值。//.rememberMeParameter("remember-me")// 指定 rememberMe 的有效期,单位为秒,默认2周。.tokenValiditySeconds(30)// 指定 rememberMe 的 cookie 名称。.rememberMeCookieName("remember-me-cookie")// 指定 rememberMe 的 token 存储方式,可以使用默认的 PersistentTokenRepository 或自定义的实现。.tokenRepository(persistentTokenRepository())// 指定 rememberMe 的认证方式,需要实现 UserDetailsService 接口,并在其中查询用户信息。.userDetailsService(userDetailsService);http.csrf().disable();return http.build();}
}

3. 运行测试

        我们运行时由于某些原因导致的代码问题会提示相应的问题

         如果你的代码后面特别多建议移出来新建一个工具类

 MyAuthenticationFailureHandler.java
package com.yx.security.config;import com.fasterxml.jackson.databind.ObjectMapper;
import com.yx.security.resp.JsonResponseBody;
import com.yx.security.resp.JsonResponseStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** com.yx.security.config** @author 君易--鑨* @site www.yangxin.com* @company 木易* @create 2023/12/24*/
@Component
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {//    实例化SpringBoot自带的json序列化操作了@Autowiredprivate ObjectMapper objectMapper;@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
//        设置错误消息objectMapper.writeValue(response.getOutputStream(), JsonResponseBody.other(JsonResponseStatus.NO_LOGIN));}
}

        后续可以在MyAuthenticationFailureHandler实现用户登陆次数过多用户禁用的功能


🎉🎉本期的博客分享到此结束🎉🎉

📚📚各位老铁慢慢消化📚📚

🎯🎯下期博客博主会带来新货🎯🎯

🎁三连加关注,阅读不迷路 !🎁

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

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

相关文章

智能优化算法应用:基于天鹰算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于天鹰算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于天鹰算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.天鹰算法4.实验参数设定5.算法结果6.参考文献7.MA…

八股文打卡day8——计算机网络(8)

面试题&#xff1a;什么是强缓存和协商缓存&#xff1f; 我的回答&#xff1a; 强缓存&#xff1a;浏览器不需要发送请求到服务器&#xff0c;直接从浏览器缓存中获取数据。浏览器不需要和服务器进行交互就可以获取数据&#xff0c;这样极大提高了页面访问速度。 协商缓存&am…

Vue2和Vue3组件间通信方式汇总(3)------$bus

组件间通信方式是前端必不可少的知识点&#xff0c;前端开发经常会遇到组件间通信的情况&#xff0c;而且也是前端开发面试常问的知识点之一。接下来开始组件间通信方式第三弹------$bus,并讲讲分别在Vue2、Vue3中的表现。 Vue2Vue3组件间通信方式汇总&#xff08;1&#xff09…

动态代理jdk的Proxy与Spring的CGlib

动态代理jdk的Proxy与Spring的CGlib 文章目录 动态代理jdk的Proxy与Spring的CGlib1. 为什么要使用动态代理&#xff1f;2. JDK Proxy 动态代理面向接口的动态代理3. CGlib动态代理4. 两个动态代理的区别 1. 为什么要使用动态代理&#xff1f; 动态代理&#xff1a;在不改变原有…

如何通过UMC配置外围组件

随着云计算技术的不断发展&#xff0c;在信息化建设模式上云是大势所趋。对于企业而言&#xff0c;已建立的内部集成并不能支撑其快速搭建开发环境、快速部署集群服务&#xff0c;并且动态水平扩展对多组织情况许可费用高昂、没有敏捷快速迭代机制&#xff0c;导致开发完毕就落…

增量式旋转编码器在STM32平台上的应用

背景 旋钮是仪器仪表上一种常见的输入设备&#xff0c;它的内部是一个旋转编码器&#xff0c;知乎上的这篇科普文章对其工作原理做了深入浅出的介绍。 我们公司的功率分析仪的前面板也用到了该类设备&#xff0c;最近前面板的MCU从MSP430切换成了STM32&#xff0c;因此我要将…

Could not resolve com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.28.

1、首先进入阿里云maven仓库&#xff0c;在搜索栏输入无法下载的依赖名称&#xff0c;查询现有版本号&#xff0c;可以看到这里有2.9.34。 2、在build.gradle(Project)的buildscript闭包下替换为阿里云maven仓库&#xff1a; maven { url https://www.jitpack.io } maven { u…

基于 ACK One 实现简单的跨云协同,让业务管理更高效

作者&#xff1a;庄宇 本文根据 2023 云栖大会现场分享实录整理 2 年前的云栖大会&#xff0c;我们发布分布式云容器平台 ACK One&#xff0c;随着 2 年的发展&#xff0c;很高兴看到 ACK One 在混合云&#xff0c;分布式云领域帮助到越来越多的客户&#xff0c;今天给大家汇报…

使用 IntelliJ IDEA 创建一个 Java 文件并运行

启动 IntelliJ IDEA 并创建一个新项目: 打开 IntelliJ IDEA。 选择 “Create New Project”&#xff08;创建新项目&#xff09;。 在左侧&#xff0c;选择 “Java”&#xff0c;确保已经选择了正确的 JDK 版本。 点击 “Next”&#xff08;下一步&#xff09;。 可以跳过额外…

中心性算法归纳

中心性算法不仅是在我所学习的计算机网络当中起很重要的作用&#xff0c;在交通网络、社交网络、信息网络、神经网络当中也有很多的应用例子。今天我在这里总结一下场景的几种中心性算法。 参考文献 Python NetworkX库 偏心中心性&#xff08;Eccentricity Centrality&#x…

银河麒麟v10 rpm安装包 安装mysql 8.35

银河麒麟v10 rpm安装包 安装mysql 8.35 1、卸载mariadb2、下载Mysql安装包3、安装Mysql 8.353.1、安装Mysql 8.353.3、安装后配置 1、卸载mariadb 由于银河麒麟v10系统默认安装了mariadb 会与Mysql相冲突&#xff0c;因此首先需要卸载系统自带的mariadb 查看系统上默认安装的M…

网络安全行业术语

病毒 是在计算机程序中插入的破坏计算机功能或者数据的代码&#xff0c;能影响计算机使用&#xff0c;能自我复制的一组计算机指令或者程序代码。 抓鸡 利用使用大量的程序的漏洞&#xff0c;使用自动化方式获取肉鸡的行为&#xff0c;即设法控制电脑&#xff0c;将其沦为肉…

C++ 牛群 字符串类型简单统计

约翰有 n 头奶牛。 每头奶牛的品种由一个小写字母表示&#xff0c;不同奶牛的品种可能不同。 请问&#xff0c;能否将这些奶牛分为两个非空的牛群&#xff0c;并使得每个牛群都恰好包含两种奶牛。 例如&#xff0c;如果一共有 5 头奶牛&#xff0c;品种依次为 aabcc&#xf…

平方矩阵()

平方矩阵1 平方矩阵2 曼哈顿距离 #include<iostream> #include<algorithm> #include<cstdio> #include<cstring>using namespace std;const int N 110;int n; int a[N][N];int main() {while(cin >> n, n){for (int i 0; i < n; i )fo…

采用SpringBoot框架+原生HTML、JS前后端分离模式开发和部署的电子病历编辑器源码(电子病历评级4级)

概述&#xff1a; 电子病历是指医务人员在医疗活动过程中,使用医疗机构信息系统生成的文字、符号、图表、图形、数据、影像等数字化信息,并能实现存储、管理、传输和重现的医疗记录,是病历的一种记录形式。 医院通过电子病历以电子化方式记录患者就诊的信息&#xff0c;包括&…

网络协议-BIO实战和NIO编程

网络通信编程基本常识 原生JDK网络编程-BIO 原生JDK网络编程-NIO Buffer 的读写 向 Buffer 中写数据 写数据到 Buffer有两种方式: 1. 读取 Channel写到 Buffer。 2.通过 Buffer 的 put0方法写到 Buffer 里。 从 Channel 写到 Buffer …

力扣经典面试题——搜索二维矩阵(两次二分搜索)

https://leetcode.cn/problems/search-a-2d-matrix/description/?envTypestudy-plan-v2&envIdtop-100-liked 思路&#xff1a;先按行二分&#xff0c;再按列进行二分。即先找到对应的行&#xff0c;再找对应的列。 对于这种判断是否存在某个数&#xff0c;记得while(left…

[JS设计模式]Mixin Pattern

Mixin是一个对象&#xff0c;我们可以使用它来为另一个对象或类添加可重用的功能&#xff0c;而无需使用继承。我们不能单独使用mixins:它们的唯一目的是在没有继承的情况下向对象或类添加功能。 假设对于我们的应用程序&#xff0c;我们需要创建多个狗。然而&#xff0c;我们…

Linux系统中跟TCP相关的系统配置项

TCP连接保活 参考 《Nginx(三) 配置文件详解 - 基础模块》3.18章节 net.ipv4.tcp_keepalive_intvl&#xff1a;设置TCP两次相邻探活检测的间隔时间。默认75秒&#xff0c;单位是秒&#xff0c;对应配置文件/proc/sys/net/ipv4/tcp_keepalive_intvl&#xff1b;net.ipv4.tcp_kee…

form-data、x-www-form-urlencoded、raw 和 binary

在 Postman 中&#xff0c;有四种常见的请求体格式&#xff0c;分别是 form-data、x-www-form-urlencoded、raw 和 binary。它们的区别如下&#xff1a; form-data form-data 格式通常用于上传文件或二进制数据。在 Postman 中&#xff0c;你可以通过选择 Body 标签页&#x…