ycl-server/pom.xml
@@ -17,6 +17,14 @@ </properties> <dependencies> <!--netty--> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> </dependency> <!-- 代码生成--> <dependency> <groupId>com.ycl</groupId> ycl-server/src/main/java/com/ycl/PlatformApplication.java
@@ -1,5 +1,6 @@ package com.ycl; import com.ycl.websocket.WebsocketServer; import lombok.extern.slf4j.Slf4j; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; @@ -15,5 +16,11 @@ public static void main(String[] args) { SpringApplication.run(PlatformApplication.class, args); log.info("(♥◠‿◠)ノ゙ 自贡运维平台启动成功 ლ(´ڡ`ლ)゙"); try { WebsocketServer.runWebsocket(); log.info("websocket启动成功"); } catch (Exception e) { log.info("websocket启动失败"); } } } ycl-server/src/main/java/com/ycl/platform/controller/YwPeopleController.java
@@ -5,6 +5,8 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import lombok.RequiredArgsConstructor; import java.util.Arrays; import java.util.List; import jakarta.validation.constraints.NotEmpty; import io.swagger.annotations.Api; @@ -42,16 +44,10 @@ return ywPeopleService.update(form); } @DeleteMapping("/{id}") @ApiOperation(value = "ID删除", notes = "ID删除") public Result removeById(@PathVariable("id") String id) { return ywPeopleService.removeById(id); } @DeleteMapping("/batch") @DeleteMapping("/{ids}") @ApiOperation(value = "批量删除", notes = "批量删除") public Result remove(@RequestBody @NotEmpty(message = "请选择数据") List<String> ids) { return ywPeopleService.remove(ids); public Result remove(@PathVariable String ids) { return ywPeopleService.remove(Arrays.asList(ids.split(","))); } // @PreAuthorize("@ss.hasPermi('unit:people:page')") ycl-server/src/main/java/com/ycl/platform/controller/YwUnitController.java
@@ -14,6 +14,8 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import lombok.RequiredArgsConstructor; import java.util.Arrays; import java.util.List; import jakarta.validation.constraints.NotEmpty; @@ -48,16 +50,10 @@ return ywUnitService.update(form); } @DeleteMapping("/{id}") @ApiOperation(value = "ID删除", notes = "ID删除") public Result removeById(@PathVariable("id") String id) { return ywUnitService.removeById(id); } @DeleteMapping("/batch") @DeleteMapping("/{ids}") @ApiOperation(value = "批量删除", notes = "批量删除") public Result remove(@RequestBody @NotEmpty(message = "请选择数据") List<String> ids) { return ywUnitService.remove(ids); public Result remove(@PathVariable String ids) { return ywUnitService.remove(Arrays.asList(ids.split(","))); } // @PreAuthorize("@ss.hasPermi('unit:list')") ycl-server/src/main/java/com/ycl/platform/service/impl/YwPeopleServiceImpl.java
@@ -10,12 +10,19 @@ import com.ycl.platform.domain.form.YwPeopleForm; import com.ycl.platform.domain.vo.YwPeopleVO; import com.ycl.platform.domain.query.YwPeopleQuery; import java.util.Collections; import java.util.List; import com.baomidou.mybatisplus.core.metadata.IPage; import com.ycl.system.domain.SysUserRole; import com.ycl.system.entity.SysRole; import com.ycl.system.entity.SysUser; import com.ycl.system.mapper.SysRoleMapper; import com.ycl.system.mapper.SysUserMapper; import com.ycl.system.mapper.SysUserRoleMapper; import com.ycl.system.page.PageUtil; import com.ycl.utils.SecurityUtils; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.beans.BeanUtils; @@ -41,8 +48,9 @@ private final YwPeopleMapper ywPeopleMapper; private final YwUnitMapper ywUnitMapper; private final PasswordEncoder passwordEncoder; private final SysUserMapper sysUserMapper; private final SysUserRoleMapper sysUserRoleMapper; private final SysRoleMapper sysRoleMapper; /** * 添加 @@ -56,6 +64,14 @@ SysUser sysUser = new SysUser(); fullUser(sysUser, form); sysUserMapper.insertUser(sysUser); // 获取运维人员角色 SysRole sysRole = sysRoleMapper.selectRoleByKey("yw_user"); if (Objects.isNull(sysRole)) { return Result.error("运维角色不存在"); } // 绑定账号角色关系 SysUserRole sysUserRole = new SysUserRole(); sysUserRole.setRoleId(sysRole.getRoleId()); sysUserRole.setUserId(sysUser.getUserId()); sysUserRoleMapper.batchUserRole(Collections.singletonList(sysUserRole)); YwPeople entity = YwPeopleForm.getEntityByForm(form, null); entity.setUserId(sysUser.getUserId()); @@ -73,7 +89,7 @@ */ public void fullUser(SysUser sysUser, YwPeopleForm form) { sysUser.setUserName(form.getYwPersonAccount()); sysUser.setPassword(passwordEncoder.encode("123456")); sysUser.setPassword(SecurityUtils.encryptPassword("123456")); sysUser.setStatus("0"); sysUser.setDelFlag("0"); sysUser.setFirstLogin((short) 0); @@ -119,7 +135,10 @@ .list(); List<Long> userIds = list.stream().map(YwPeople::getUserId).collect(Collectors.toList()); baseMapper.deleteBatchIds(ids); sysUserMapper.deleteUserByIds((Long[]) userIds.toArray()); if (!userIds.isEmpty()) { sysUserRoleMapper.deleteUserRoleByUserIds(userIds); sysUserMapper.deleteUserByIds(userIds.toArray(new Long[0])); } return Result.ok("删除成功"); } ycl-server/src/main/java/com/ycl/platform/service/impl/YwUnitServiceImpl.java
@@ -1,7 +1,9 @@ package com.ycl.platform.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -12,12 +14,20 @@ import com.ycl.platform.domain.vo.YwUnitVO; import com.ycl.system.Result; import com.ycl.platform.mapper.YwUnitMapper; import com.ycl.system.domain.SysUserRole; import com.ycl.system.entity.SysRole; import com.ycl.system.entity.SysUser; import com.ycl.system.mapper.SysRoleMapper; import com.ycl.system.mapper.SysUserMapper; import com.ycl.system.mapper.SysUserRoleMapper; import com.ycl.system.page.PageUtil; import com.ycl.platform.service.YwUnitService; import com.baomidou.mybatisplus.core.metadata.IPage; import com.ycl.utils.DateUtils; import com.ycl.utils.SecurityUtils; import org.springframework.stereotype.Service; import org.springframework.beans.BeanUtils; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; import java.util.Objects; @@ -37,6 +47,9 @@ public class YwUnitServiceImpl extends ServiceImpl<YwUnitMapper, YwUnit> implements YwUnitService { private final YwUnitMapper ywUnitMapper; private final SysUserMapper sysUserMapper; private final SysUserRoleMapper sysUserRoleMapper; private final SysRoleMapper sysRoleMapper; /** * 添加 @@ -44,10 +57,26 @@ * @return */ @Override @Transactional(rollbackFor = Exception.class) public Result add(YwUnitForm form) { // todo 增加对应账号 YwUnit entity = YwUnitForm.getEntityByForm(form, null); if(baseMapper.insert(entity) > 0) { // 新增运维人员账号 SysUser sysUser = new SysUser(); sysUser.setDeptId(null); sysUser.setUserName(entity.getUnitAdminAccount()); sysUser.setNickName(entity.getUnitContact()); sysUser.setPhonenumber(entity.getUnitContactPhone()); sysUser.setPassword(SecurityUtils.encryptPassword("123456")); sysUserMapper.insertUser(sysUser); // 获取运维人员角色 SysRole sysRole = sysRoleMapper.selectRoleByKey("yw_user"); if (Objects.isNull(sysRole)) { return Result.error("运维角色不存在"); } // 绑定账号角色关系 SysUserRole sysUserRole = new SysUserRole(); sysUserRole.setRoleId(sysRole.getRoleId()); sysUserRole.setUserId(sysUser.getUserId()); sysUserRoleMapper.batchUserRole(Collections.singletonList(sysUserRole)); return Result.ok("添加成功"); } return Result.error("添加失败"); @@ -59,14 +88,21 @@ * @return */ @Override @Transactional(rollbackFor = Exception.class) public Result update(YwUnitForm form) { // todo 修改对应账号 YwUnit entity = baseMapper.selectById(form.getId()); // 为空抛IllegalArgumentException,做全局异常处理 Assert.notNull(entity, "记录不存在"); BeanUtils.copyProperties(form, entity); if (baseMapper.updateById(entity) > 0) { // 修改运维单位账号信息 SysUser sysUser = sysUserMapper.selectUserByUserName(entity.getUnitAdminAccount()); if (Objects.nonNull(sysUser)) { sysUser.setPhonenumber(entity.getUnitContactPhone()); sysUser.setNickName(entity.getUnitContact()); sysUserMapper.updateUser(sysUser); } return Result.ok("修改成功"); } return Result.error("修改失败"); @@ -78,7 +114,16 @@ * @return */ @Override @Transactional(rollbackFor = Exception.class) public Result remove(List<String> ids) { List<Long> userIds = sysUserMapper.selectUserIdByNames( baseMapper.selectList( new LambdaQueryWrapper<YwUnit>().in(YwUnit::getId, ids)) .stream().map(YwUnit::getUnitAdminAccount).toList()); if (!userIds.isEmpty()) { sysUserMapper.deleteUserByIds(userIds.toArray(new Long[0])); sysUserRoleMapper.deleteUserRoleByUserIds(userIds); } if(baseMapper.deleteBatchIds(ids) > 0) { return Result.ok("删除成功"); } @@ -92,6 +137,12 @@ */ @Override public Result removeById(String id) { // 删除运维人员账号 SysUser sysUser = sysUserMapper.selectUserByUserName(baseMapper.selectById(id).getUnitAdminAccount()); if (Objects.nonNull(sysUser)) { sysUserRoleMapper.deleteUserRoleByUserId(sysUser.getUserId()); sysUserMapper.deleteUserById(sysUser.getUserId()); } if(baseMapper.deleteById(id) > 0) { return Result.ok("删除成功"); } ycl-server/src/main/java/com/ycl/system/mapper/SysRoleMapper.java
@@ -1,5 +1,6 @@ package com.ycl.system.mapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ycl.system.entity.SysRole; import org.apache.ibatis.annotations.Mapper; @@ -107,4 +108,11 @@ * @return 结果 */ public int deleteRoleByIds(Long[] roleIds); /** * 根据角色编码查询角色 * @param roleKey 角色编码 * @return 角色 */ SysRole selectRoleByKey(String roleKey); } ycl-server/src/main/java/com/ycl/system/mapper/SysUserMapper.java
@@ -127,4 +127,11 @@ * @return 结果 */ public SysUser checkEmailUnique(String email); /** * 根据用户名查询用户id * @param names 用户名 * @return 用户id */ List<Long> selectUserIdByNames(List<String> names); } ycl-server/src/main/java/com/ycl/system/mapper/SysUserRoleMapper.java
@@ -64,4 +64,11 @@ public int deleteUserRoleInfos(@Param("roleId") Long roleId, @Param("userIds") Long[] userIds); void exchange(@Param("roleId")Integer roleId,@Param("userId") Long userId); /** * 根据用户id批量删除 * @param userIds 用户编号 * @return 操作结果 */ int deleteUserRoleByUserIds(List<Long> userIds); } ycl-server/src/main/java/com/ycl/websocket/WebSocketHandler.java
New file @@ -0,0 +1,67 @@ package com.ycl.websocket; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.group.ChannelGroup; import io.netty.channel.group.DefaultChannelGroup; import io.netty.handler.codec.http.websocketx.*; import io.netty.util.concurrent.GlobalEventExecutor; import java.util.Objects; public class WebSocketHandler extends SimpleChannelInboundHandler { public static ChannelGroup connects = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); @Override protected void channelRead0(ChannelHandlerContext ctx, Object o) throws Exception { if(Objects.nonNull(o) && o instanceof WebSocketFrame){ this.handleWebSocketFrame(ctx, (WebSocketFrame) o); } } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("有新的客户端连接上了"); connects.add(ctx.channel()); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("有客户端断开连接了"); connects.remove(ctx.channel()); } // 处理ws数据 private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) { // 处理关闭连接 if (frame instanceof CloseWebSocketFrame) { connects.remove(ctx.channel()); ctx.close(); return; } if (frame instanceof TextWebSocketFrame) { // 处理文本消息 String text = ((TextWebSocketFrame) frame).text(); System.out.println("服务器收到客户端数据:" +text); // 此处为群发,单独发可使用connects.find(ctx.channel().id()).writeAndFlush()发送 connects.writeAndFlush(new TextWebSocketFrame("你好客户端")); // ... } else if (frame instanceof BinaryWebSocketFrame) { // 处理二进制消息 // ... } else if (frame instanceof PingWebSocketFrame) { // 处理 Ping 消息 // 收到 Ping 消息,回应一个 Pong 消息(表明我还活着) ctx.channel().writeAndFlush(new PongWebSocketFrame(frame.content().retain())); } else if (frame instanceof PongWebSocketFrame) { // 处理 Pong 消息 // pong消息如果没有特定需求,不用处理 } else if (frame instanceof ContinuationWebSocketFrame) { // 处理连续帧消息(比较大的数据,分片) // ... } } } ycl-server/src/main/java/com/ycl/websocket/WebsocketServer.java
New file @@ -0,0 +1,57 @@ package com.ycl.websocket; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.http.HttpServerCodec; import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; /** * webscoket 服务 * * @author:xp * @date:2024/4/11 17:47 */ public class WebsocketServer { public static void runWebsocket() throws Exception { // 处理 I/O 操作的多线程事件循环组(线程池)。bossGroup用于接收传入的连接,workerGroup用于处理IO操作 EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { // 服务器引导(启动)类,提供了一些方法使开发者能够简单的启动服务端 ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) // 指定服务器通道(主、子通道)的实现类 .channel(NioServerSocketChannel.class) // 设置通道初始化器(ChannelInitializer),每次创建的通道都按这个初始化 .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { // websocket的握手阶段是使用的Http,所以需要添处理http请求: // 用于将 HTTP 请求和响应转换为字节流以及将字节流转换为 HTTP 请求和响应 ch.pipeline().addLast(new HttpServerCodec()); ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws", null, true, 6000)); ch.pipeline().addLast(new WebSocketHandler()); } }) // 设置服务器通道(主通道)的选项,此处是设置连接请求队列的最大长度是128 .option(ChannelOption.SO_BACKLOG, 128); // 绑定服务器到指定的端口,并且等待绑定操作完成。 ChannelFuture f = b.bind(8084).sync(); // 等待服务器的通道关闭。 f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } } ycl-server/src/main/resources/mapper/system/SysRoleMapper.xml
@@ -92,8 +92,12 @@ <include refid="selectRoleVo"/> where r.role_key=#{roleKey} and r.del_flag = '0' limit 1 </select> <insert id="insertRole" parameterType="com.ycl.system.entity.SysRole" useGeneratedKeys="true" keyProperty="roleId"> <select id="selectRoleByKey" resultType="com.ycl.system.entity.SysRole"> select * from sys_role where role_key = #{roleKey} and del_flag = '0' limit 1 </select> <insert id="insertRole" parameterType="com.ycl.system.entity.SysRole" useGeneratedKeys="true" keyProperty="roleId"> insert into sys_role( <if test="roleId != null and roleId != 0">role_id,</if> <if test="roleName != null and roleName != ''">role_name,</if> ycl-server/src/main/resources/mapper/system/SysUserMapper.xml
@@ -142,7 +142,14 @@ <select id="checkEmailUnique" parameterType="String" resultMap="SysUserResult"> select user_id, email from sys_user where email = #{email} and del_flag = '0' limit 1 </select> <select id="selectUserIdByNames" resultType="java.lang.Long"> select user_id from sys_user where user_name in <foreach item="item" index="index" collection="names" open="(" separator="," close=")"> #{item} </foreach> </select> <insert id="insertUser" parameterType="com.ycl.system.entity.SysUser" useGeneratedKeys="true" keyProperty="userId"> insert into sys_user( <if test="userId != null and userId != 0">user_id,</if> ycl-server/src/main/resources/mapper/system/SysUserRoleMapper.xml
@@ -41,4 +41,11 @@ #{userId} </foreach> </delete> <delete id="deleteUserRoleByUserIds"> delete from sys_user_role where user_id in <foreach collection="userIds" item="userId" open="(" separator="," close=")"> #{userId} </foreach> </delete> </mapper>