亿级高并发电商项目-- 实战篇 --万达商城项目 六(编写角色管理、用户权限(Spring Security认证授权)、管理员管理等模块)

专栏:高并发---前后端分布式
👏作者简介:大家好,我是小童,Java开发工程师,CSDN博客博主,Java领域新星创作者
📕系列专栏:前端、Java、Java中间件大全、微信小程序、微信支付、若依框架、Spring全家桶
📧如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步👀
🔥如果感觉博主的文章还不错的话,请👍三连支持👍一下博主哦
🍂博主正在努力完成2023计划中:以梦为马,扬帆起航,2023追梦人
编写角色服务接口
接下来我们编写角色相关的CRUD方法,首先在通用模块编写角色服务接口:
public interface RoleService {// 新增角色void add(Role role);// 修改角色void update(Role role);// 删除角色void delete(Long id);// 根据id查询角色Role findById(Long id);// 查询所有角色List<Role> findAll();// 分页查询角色Page<Role> search(int page, int size);// 修改角色的权限void addPermissionToRole(Long rid, Long[] pids);
}
编写角色Mapper
1、在管理员服务模块编写角色Mapper
public interface RoleMapper extends BaseMapper<Role> {// 根据id查询角色,包括权限Role findById(Long id);// 删除角色的所有权限void deleteRoleAllPermission(Long rid);// 删除用户_角色表的相关数据void deleteRoleAllAdmin(Long rid);// 给角色添加权限void addPermissionToRole(@Param("rid") Long rid, @Param("pid")Long pid);
}
2、在 resources 中创建 RoleMapper 的同级包,编写映射文件 RoleMapper.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.ittxc.shopping_admin_service.mapper.RoleMapper"><resultMap id="roleMapper" type="com.itbaizhan.shopping_common.pojo.Role"><id property="rid" column="rid"></id><result property="roleName" column="roleName"></result><result property="roleDesc" column="roleDesc"></result><collection property="permissions" column="rid" ofType="com.itbaizhan.shopping_common.pojo.Permission"><id property="pid" column="pid"></id><result property="permissionName" column="permissionName"></result><result property="url" column="url"></result></collection></resultMap><select id="findById" parameterType="long" resultMap="roleMapper">SELECT *FROM bz_roleLEFT JOINbz_role_permissionON bz_role.rid = bz_role_permission.ridLEFT JOIN bz_permissionONbz_role_permission.pid = bz_permission.pidWHERE bz_role.rid = #{rid}</select><delete id="deleteRoleAllPermission" parameterType="long">DELETEFROM bz_role_permissionWHERE rid = #{rid}</delete><delete id="deleteRoleAllAdmin" parameterType="long">DELETEFROM bz_admin_rolewhere rid = #{rid}</delete><insert id="addPermissionToRole">INSERT INTO bz_role_permissionVALUES (#{rid}, #{pid});</insert>
</mapper>
编写角色服务实现类
在管理员服务模块编写角色服务实现类
@DubboService
public class RoleServiceImpl implements RoleService {@Autowiredprivate RoleMapper roleMapper;@Overridepublic void add(Role role) {roleMapper.insert(role);}@Overridepublic void update(Role role) {roleMapper.updateById(role);}@Overridepublic void delete(Long id) {// 删除角色roleMapper.deleteById(id);// 删除角色的所有权限roleMapper.deleteRoleAllPermission(id);// 删除用户_角色中间表的相关数据roleMapper.deleteRoleAllAdmin(id);}@Overridepublic Role findById(Long id) {return roleMapper.findById(id);}@Overridepublic List<Role> findAll() {return roleMapper.selectList(null);}@Overridepublic Page<Role> search(int page, int size) {return roleMapper.selectPage(new Page(page,size),null);}@Overridepublic void addPermissionToRole(Long rid, Long[] pids) {// 删除角色的所有权限roleMapper.deleteRoleAllPermission(rid);// 给角色添加权限for (Long pid : pids) {roleMapper.addPermissionToRole(rid,pid);}}
}
编写角色控制器
在后台管理Api模块编写角色控制器:
/**
* 后台角色
*/
@RestController
@RequestMapping("/role")
public class RoleController {@DubboReferenceprivate RoleService roleService;/*** 新增角色** @param role 角色对象* @return 执行结果*/@PostMapping("/add")public BaseResult add(@RequestBody Role role) {roleService.add(role);return BaseResult.ok();}/*** 修改角色** @param role 角色对象* @return 执行结果*/@PutMapping("/update")public BaseResult update(@RequestBody Role role) {roleService.update(role);return BaseResult.ok();}/*** 删除角色** @param rid 角色id* @return 执行结果*/@DeleteMapping("/delete")public BaseResult delete(Long rid) {roleService.delete(rid);return BaseResult.ok();}/*** 根据id查询角色** @param rid* @return 查询到的角色*/@GetMapping("/findById")public BaseResult<Role> findById(Long rid) {Role role = roleService.findById(rid);return BaseResult.ok(role);}/*** 分页查询角色** @param page 页码* @param size 每页条数* @return 查询结果*/@GetMapping("/search")public BaseResult<Page<Role>> search(int page, int size) {Page<Role> page1 = roleService.search(page, size);return BaseResult.ok(page1);}/*** 查询所有角色* @return 查询结果*/@GetMapping("/findAll")public BaseResult<List<Role>> findAll() {List<Role> all = roleService.findAll();return BaseResult.ok(all);}/*** 修改角色的权限** @param rid 角色id* @param pids 权限id* @return 执行结果*/@PutMapping("/updatePermissionToRole")public BaseResult updatePermissionToRole(Long rid, Long[] pids) {roleService.addPermissionToRole(rid,pids);return BaseResult.ok();}
}
启动服务,测试角色控制器方法
编写权限服务接口
接下来我们编写权限相关的CRUD方法,首先在通用模块编写权限服务接口:
public interface PermissionService {// 新增权限void add(Permission permission);// 修改权限void update(Permission permission);// 删除权限void delete(Long id);// 根据id查询权限Permission findById(Long id);// 分页查询权限Page<Permission> search(int page, int size);// 查询所有权限List<Permission> findAll();
}
编写权限Mapper
1、在管理员服务模块编写权限Mapper
public interface PermissionMapper extends BaseMapper<Permission> {// 删除角色_权限表中的相关数据void deletePermissionAllRole(Long pid)
}
2、编写权限Mapper映射文件
<?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.ittxc.shopping_admin_service.mapper.PermissionMapper"><delete id="deletePermissionAllRole" parameterType="long">DELETEFROM bz_role_permissionWHERE pid = #{pid}</delete>
</mapper>
编写权限服务实现类
在管理员服务模块编写权限服务实现类
@DubboService
public class PermissionServiceImpl implements PermissionService {@Autowiredprivate PermissionMapper permissionMapper;@Overridepublic void add(Permission permission) {permissionMapper.insert(permission);}@Overridepublic void update(Permission permission) {permissionMapper.updateById(permission);}@Overridepublic void delete(Long id) {// 删除权限permissionMapper.deleteById(id);// 删除角色_权限表中的相关数据permissionMapper.deletePermissionAllRole(id);}@Overridepublic Permission findById(Long id) {return permissionMapper.selectById(id);}@Overridepublic Page<Permission> search(int page, int size) {return permissionMapper.selectPage(new Page(page,size),null);}@Overridepublic List<Permission> findAll() {return permissionMapper.selectList(null);}
}
编写权限控制器
在后台管理Api模块编写权限控制器:
/**
* 后台权限
*/
@RestController
@RequestMapping("/permission")
public class PermissionController {@DubboReferenceprivate PermissionService permissionService;/*** 新增权限* @param permission 权限对象* @return 执行结果*/@PostMapping("/add")public BaseResult add(@RequestBody Permission permission){permissionService.add(permission);return BaseResult.ok();}/*** 修改权限* @param permission 权限对象* @return 执行结果*/@PutMapping("/update")public BaseResult update(@RequestBody Permission permission){permissionService.update(permission);return BaseResult.ok();}/*** 删除权限* @param pid 权限id* @return 执行结果*/@DeleteMapping("/delete")public BaseResult delete(Long pid){permissionService.delete(pid);return BaseResult.ok();}/*** 根据id查询权限* @param pid 权限id* @return 查询结果*/@GetMapping("/findById")public BaseResult<Permission> findById(Long pid){Permission permission = permissionService.findById(pid);return BaseResult.ok(permission);}/*** 分页查询权限* @param page 页面* @param size 每页条数* @return 查询结果*/@GetMapping("/search")public BaseResult<Page<Permission>> search(int page,int size){Page<Permission> permissionPage = permissionService.search(page, size);return BaseResult.ok(permissionPage);}/*** 查询所有权限* @return 所有权限*/@GetMapping("/findAll")public BaseResult<List<Permission>> findAll(){List<Permission> all = permissionService.findAll();return BaseResult.ok(all);}
}
启动服务,测试权限控制器方法
编写Security处理器
接下来我们使用Spring Security编写管理员认证和授权功能。 Spring Security在访问接口时进行认证和授权,所以Spring Security的相关代码编写在管理员API模块。 之前使用Spring Security时,登录后会配置跳转页面。但百战商城 是前后端分离项目,所有认证和授权的结果,只是返回json字符串 让前端去处理。所以我们要创建 认证成功处理器 、 认证失败处理器 、 未登录处理 器 、 权限不足处理器 、 登出成功处理器 处理不同的结果,Spring Security通过 实现接口编写结果处理器。
1、在管理员API模块引入Spring Security的依赖
<!-- spring security -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>
2、编写认证成功、认证失败处理器
// 登录成功处理器
public class MyLoginSuccessHandler
implements AuthenticationSuccessHandler {@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,Authentication authentication) throws IOException, ServletException {response.setContentType("text/json;charset=utf-8");BaseResult result = new BaseResult(200, "登录成功", null);response.getWriter().write(JSON.toJSONString(result));}
}
// 登录失败处理器
public class MyLoginFailureHandler implements AuthenticationFailureHandler {@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {response.setContentType("text/json;charset=utf-8");BaseResult result = new BaseResult(402, "用户名或密码错误", null);response.getWriter().write(JSON.toJSONString(result));}
}
3、编写未登录处理器
// 未登录处理器
public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {response.setContentType("text/json;charset=utf-8");BaseResult result = new BaseResult(401, "用户名未登录", null);response.getWriter().write(JSON.toJSONString(result));}
}
4、编写权限不足处理器
// 权限不足处理器
public class MyAccessDeniedHandler implements AccessDeniedHandler {@Overridepublic void handle(HttpServletRequest request, HttpServletResponse response,AccessDeniedException accessDeniedException) throws IOException, ServletException {response.setContentType("text/json;charset=utf-8");BaseResult result = new BaseResult(403, "权限不足", null);response.getWriter().write(JSON.toJSONString(result));}
}
5、编写登出成功处理器
// 登出成功处理器
public class MyLogoutSuccessHandler implements LogoutSuccessHandler {@Overridepublic void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,Authentication authentication) throws IOException, ServletException {response.setContentType("text/json;charset=utf-8");BaseResult result = new BaseResult(200, "注销成功", null);response.getWriter().write(JSON.toJSONString(result));}
}
编写Security配置类
在后台管理API模块编写Spring Security配置类
// Security配置类
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {// Spring Security配置@Overrideprotected void configure(HttpSecurity http) throws Exception {// 自定义表单登录http.formLogin().usernameParameter("username") // 用户名项.passwordParameter("password") // 密码项.loginProcessingUrl("/admin/login") // 登录提交路径.successHandler(new MyLoginSuccessHandler()) // 登录成功处理器.failureHandler(new MyLoginFailureHandler()); // 登录失败处理器// 权限拦截配置http.authorizeRequests().antMatchers("/login").permitAll() // 登录页不需要认证.antMatchers("/admin/login").permitAll() //登录请求不需要认证.anyRequest().authenticated(); // 其余请求都需要认证// 退出登录配置http.logout().logoutUrl("/admin/logout")// 注销的路径.logoutSuccessHandler(new MyLogoutSuccessHandler()) // 登出成功处理器.clearAuthentication(true)// 清除认证数据.invalidateHttpSession(true); // 清除session// 异常处理http.exceptionHandling().authenticationEntryPoint(new MyAuthenticationEntryPoint()) // 未登录处理器.accessDeniedHandler(new MyAccessDeniedHandler()); // 权限不足处理器// 关闭csrf防护http.csrf().disable();// 开启跨域访问http.cors();}@Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}
}
编写认证授权相关的服务方法
1、在管理员服务接口添加 根据用户名查询管理员 和 根据用户名查询权限 方法
// 根据名字查询管理员
Admin findByAdminName(String username);
// 根据名字查询管理员所有权限
List<Permission> findAllPermission(String username);
2、在管理员服务模块编写管理员Mapper
// 根据管理员名查询权限
List<Permission> findAllPermission(String username);
编写AdminMapper.xml
<select id="findAllPermission" resultType="com.itbaizhan.shopping_pojo.pojo.Permission" parameterType="string">SELECTDISTINCT bz_permission.*FROMbz_adminLEFT JOIN bz_admin_roleON bz_admin.aid =bz_admin_role.aidLEFT JOIN bz_roleON bz_admin_role.rid = bz_role.ridLEFT JOIN bz_role_permissionON bz_role.rid = bz_role_permission.ridLEFT JOIN bz_permissionONbz_role_permission.pid = bz_permission.pidWHERE bz_admin.username = #{username}
</select>
3、在管理员服务模块编写管理员服务接口实现类
@Override
public Admin findByAdminName(String username) {QueryWrapper<Admin> wrapper = new QueryWrapper();wrapper.eq("username", username);Admin admin = adminMapper.selectOne(wrapper);return admin;
}
@Override
public List<Permission> findAllPermission(String username) {return adminMapper.findAllPermission(username);
}
编写认证授权逻辑
在后台管理API模块编写认证和授权逻辑
@Service
public class MyUserDetailService implements
UserDetailsService {@DubboReferenceprivate AdminService adminService;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {// 1.认证Admin admin = adminService.findByAdminName(username);if(admin == null){throw new UsernameNotFoundException("用户不存在");}// 2.授权List<Permission> permissions = adminService.findAllPermission(username);List<GrantedAuthority> grantedAuthorities = new ArrayList<>();for (Permission permission : permissions) {grantedAuthorities.add(new SimpleGrantedAuthority(permission.getUrl()));}// 3.封装为UserDetails对象UserDetails userDetails = User.withUsername(admin.getUsername()).password(admin.getPassword()).authorities(grantedAuthorities).build();// 4.返回封装好的UserDetails对象return userDetails;}
}
编写接口鉴权配置
我们要对接口进行鉴权配置,即用户拥有权限才能访问接口。
1、开启鉴权配置注解
// Security配置类
@Configuration
// 开启鉴权配置注解
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter{}
2、在需要鉴权的接口上方添加鉴权注解
/*** 分页查询管理员* @param page 页码* @param size 每天条数* @return 查询结果*/
@GetMapping("/search")
@PreAuthorize("hasAnyAuthority('/admin/all')")
public BaseResult<Page<Admin>> search(int page, int size){
Page<Admin> adminPage = adminService.search(page, size);return BaseResult.ok(adminPage);
}
/*** 分页查询角色* @param page 页码* @param size 每页条数* @return 查询结果*/
@GetMapping("/search")
@PreAuthorize("hasAnyAuthority('/role/all')")
public BaseResult<Page<Role>> search(int page, int size){Page<Role> rolePage = roleService.search(page, size);return BaseResult.ok(rolePage);
}
3、使用不同权限的用户登录,查看他们是否能访问这些接口
测试时,当用户权限不足时,系统会抛出500异常,这是由于全 局异常处理器先处理了异常,使得异常没有交由 AccessDeniedHandler 。此时我们需要在管理员API模块添加异常处理 器,当捕获到 AccessDeniedException 异常时,直接抛出,此时异常就 会交给 AccessDeniedHandler 处理。
// 统一异常处理器
@RestControllerAdvice
public class AccessDeniedExceptionHandler
{// 处理权限不足异常,捕获到异常后再次抛出,交给 AccessDeniedHandler处理@ExceptionHandler(AccessDeniedException.class)public void defaultExceptionHandler(AccessDeniedException e) throws AccessDeniedException{throw e;}
}
修改新增/修改管理员方法
接下来修改新增用户和修改用户方法,对密码进行加密:
@RestController
@RequestMapping("/admin")
public class AdminController {@Autowiredprivate PasswordEncoder encoder;/*** 新增管理员* @param admin 管理员对象* @return 执行结果*/@PostMapping("/add")public BaseResult add(@RequestBody Admin admin) {String password = admin.getPassword();password = encoder.encode(password);admin.setPassword(password);adminService.add(admin);return BaseResult.ok();}/*** 修改管理员* @param admin 管理员对象* @return 执行结果*/@PutMapping("/update")public BaseResult update(@RequestBody Admin admin) {String password = admin.getPassword();if (StringUtils.hasText(password)){// 密码不为空加密password = encoder.encode(password);admin.setPassword(password);}adminService.update(admin);return BaseResult.ok();}
}
@DubboService
public class AdminServiceImpl implements
AdminService {@Overridepublic void update(Admin admin) {// 如果前端传来空密码,则密码还是原来的密码if(!StringUtils.hasText(admin.getPassword())){// 查询原来的密码String password = adminMapper.selectById(admin.getAid()).getPassword();admin.setPassword(password);}adminMapper.updateById(admin);}
}
编写获取登录管理员名方法
/**
* 获取登录管理员名
*
* @return 管理员名
*/
@GetMapping("/getUsername")
public BaseResult<String> getUsername() {// 1.获取会话对象SecurityContext context = SecurityContextHolder.getContext();// 2.获取认证对象Authentication authentication = context.getAuthentication();// 3.获取登录用户信息UserDetails userDetails = (UserDetails)authentication.getPrincipal();String username = userDetails.getUsername();return BaseResult.ok(username);
}

相关文章:
亿级高并发电商项目-- 实战篇 --万达商城项目 六(编写角色管理、用户权限(Spring Security认证授权)、管理员管理等模块)
专栏:高并发---前后端分布式 👏作者简介:大家好,我是小童,Java开发工程师,CSDN博客博主,Java领域新星创作者 📕系列专栏:前端、Java、Java中间件大全、微信小程序、微信…...
博视像元获近5000万元融资,主攻半导体前道及锂电高端部件供应
这两年各大车企与电池厂商都在快速新建产能,尤其上游原材料成本大增,反映到产业链上巨头都在寻求增效,高端制造技术投入也大幅增长。比如这家,高端工业相机提供商「博视像元」近期宣布完成近5000万的天使加轮融资,投资…...
SpringCloud-断路器Hystrix
一、降级使用1、添加依赖<!--hystrix--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency>2、启动类添加注解EnableCircuitBreakerSpringBoot…...
JavaScript精简笔记
文章目录基础语法函数1.1、函数的使用预解析对象1.1、创建对象基础语法 函数 1.1、函数的使用 函数在使用时分为两步:声明函数和调用函数 ①声明函数 //声明函数 function 函数名(){//函数体代码 }function 是声明函数的关键字,必须小写由于函数一般是为了实现…...
MySQL常用函数汇总
1 MySQL 字符串函数函数描述实例ASCII(s)返回字符串 s 的第一个字符的 ASCII 码。返回 CustomerName 字段第一个字母的 ASCII 码:SELECT ASCII(CustomerName) AS NumCodeOfFirstCharFROM Customers;CHAR_LENGTH(s)返回字符串 s 的字符数返回字符串 RUNOOB 的字符数S…...
100M网口客户电脑插上网线就断线,自己工厂正常,是什么问题导致?
Hqst(华强盛科技)导读:物联工程师100M网口产品出现客户电脑插上网线就显示断线,无法通信,在自己工厂又正常使用,是什么问题?问:100M 网口, 使用改电路, 产品出…...
从零开始学习无人机 00 硬件配置
遥控器 型号 乐迪Radiolink AT9S Pro 固件更新 对遥控器固件作更新 乐迪Radiolink AT9S Pro 固件更新 光流传感器 型号 思动智能ThoneFlow-3901U 开发文档 Pmw3901光流传感器PX4开发文档 距离传感器 型号 空循环Nooploop TOFSense-F Pro 开发文档 TOFSense-F官方…...
免翻在Chrome上使用新必应(New Bing)聊天机器人
这里不讲如何加入New Bing内测 文章目录免翻使用New Bing用Chrome(非Edge)使用新必应聊天机器人免翻使用New Bing 第一个是免翻,需要一个浏览器插件Header Editor,扩展商店或者百度自行下载安装吧。打开该插件,添加一个规则 为方便填写&…...
LA@特征值和特征向量
文章目录特征值和特征向量例例求解方阵的特征值和特征向量🎈特征多项式特征方程方阵特征值和特征向量的性质证明推论衍生特征值更一般的转置和特征值其他结论(方阵多项式的特征值与方阵本身特征值的关系)特征向量线性相关性特征值和特征向量 许多定量分析模型中,常常…...
transpose代码学习
论文:TransPose: Keypoint Localization via Transformer Sen Yang Zhibin Quan Mu Nie Wankou Yang* School of Automation, Southeast University, Nanjing 210096, China {yangsenius, 101101872, niemu, wkyang}seu.edu.cn 下载地址:https://arxiv.o…...
【Redis】Redis 常用数据类型操作 ② ( 数据库操作 | 切换数据库 | 查询当前数据库键个数 | 清空当前数据库 | 清空所有数据库 )
文章目录一、Redis 数据库操作1、切换数据库2、查询当前数据库键个数3、清空当前数据库4、清空所有数据库一、Redis 数据库操作 在之前的博客 【Redis】Redis 数据库 安装、配置、访问 ( Redis 简介 | 下载 Redis 安装包 | 安装 Redis 数据库 | 命令行访问 Redis | 使用可视化工…...
最简单的物体识别例子
第一步下载百度EASYDL工具。 网址EasyDL 图像 然后下载本地训练工具包: 本地下载,运行。 首先创建数据集, 完成,创建目标任务。 选择物体检测创建任务 选择训练,将数据集引入 通用型小型设备SDK 选择这个可以本地直…...
指针——“C”
各位CSDN的uu们你们好呀,今天,小雅兰学习的内容是指针,这次只会讲一些很简单的知识点,更详细的指针知识会在以后的博客中逐步剖析清楚,那么现在,就让我们进入指针的世界吧 指针是什么 指针和指针类型 野指…...
学习 Linux 内核书籍推荐
原文链接,欢迎关注: 你为什么学习 Linux 内核? - CodeAllen的回答 - 知乎 https://www.zhihu.com/question/31369673/answer/2894981254 主要是工作需要,其实对于我自己的工作来说,在Linux开发的具体业务和算法才是重…...
深圳硬件黑客松活动,开放报名!
开源社KAIYUANSHE近期微信公众号订阅功能做调整啦!没有被星标的账号在信息流里可能不显示大图了!快星标⭐我们,就可以及时看到发布的文章啦!STEP01 点击右上角标志STEP02 点击【设为星标】近年来,创客文化越来越受到人…...
力扣sql简单篇练习(十七)
力扣sql简单篇练习(十七) 1 销售分析| 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 # 可以考虑使用all函数 SELECT seller_id FROM Sales GROUP BY seller_id HAVING sum(price)>all(SELECT sum(price)FROM SalesGROUP BY seller_id )1.3 运行…...
Linux网络技术学习(六)—— 网络设备初始化(II)
文章目录初始化选项模块选项设备处理层初始化:net_dev_init用户空间辅助程序kmod解析热插拔虚拟设备虚拟设备范例通过/proc文件系统调整初始化选项 内核内建的组件以及模块加载的组件都能输入参数,使用户调整组件所实现的功能、重写默认值等 模块选项&…...
一手教你如何搭建Hadoop基于Zookeeper的集群(5台主机)
文章目录一、设计集群图二、准备五台虚拟机2.1、下载安装文件2.2、创建虚拟机2.3、配置网络2.4、修改主机名称2.5、关闭防火墙2.6、同步时间2.7、设置/etc/hosts文件2.8、设置免密登录2.9、为后面可以主备替换安装psmisc三、安装JDK3.1、安装jdk3.2、测试jdk是否安装成功3.3、将…...
Spring Cloud是什么?怎么理解Spring Cloud?
简介Spring Cloud项目的官方网址:https://projects.spring.io/spring-cloud/ Spring Cloud 并不是一个项目,而是一组项目的集合。在 Spring Cloud中包含了很多的子项目,每一个子项目都是一种微服务开发过程中遇到的问题的一种解决方案。它利…...
robotframework + selenium自动化测试常见的问题
1、 插入中文数据提示 FAIL UnicodeEncodeError: ‘latin-1’ codec can’t encode characters in position 92-107: ordinal not in range(25 DataBaseLibrary插入中文乱码的解决:修改D:\Python27\Lib\site-packages\DatabaseLibrary\connection_manager.py里的co…...
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
flow_controllers
关键点: 流控制器类型: 同步(Sync):发布操作会阻塞,直到数据被确认发送。异步(Async):发布操作非阻塞,数据发送由后台线程处理。纯同步(PureSync…...


