Browse Source

补充注释,整理代码,1.0版本准备上线

master
xie.bx 3 years ago
parent
commit
1deeb61cb9
  1. 13
      commom/src/main/java/com/bx/common/result/ResultUtils.java
  2. 7
      im-platform/src/main/java/com/bx/implatform/config/MinIoClientConfig.java
  3. 18
      im-platform/src/main/java/com/bx/implatform/config/RedisConfig.java
  4. 4
      im-platform/src/main/java/com/bx/implatform/config/SwaggerConfig.java
  5. 35
      im-platform/src/main/java/com/bx/implatform/config/WebSecurityConfg.java
  6. 8
      im-platform/src/main/java/com/bx/implatform/controller/FileController.java
  7. 2
      im-platform/src/main/java/com/bx/implatform/controller/FriendController.java
  8. 4
      im-platform/src/main/java/com/bx/implatform/controller/GroupController.java
  9. 6
      im-platform/src/main/java/com/bx/implatform/controller/GroupMessageController.java
  10. 2
      im-platform/src/main/java/com/bx/implatform/controller/PrivateMessageController.java
  11. 2
      im-platform/src/main/java/com/bx/implatform/controller/RegisterController.java
  12. 2
      im-platform/src/main/java/com/bx/implatform/controller/UserController.java
  13. 2
      im-platform/src/main/java/com/bx/implatform/entity/Friend.java
  14. 15
      im-platform/src/main/java/com/bx/implatform/entity/Group.java
  15. 15
      im-platform/src/main/java/com/bx/implatform/entity/GroupMember.java
  16. 15
      im-platform/src/main/java/com/bx/implatform/entity/GroupMessage.java
  17. 2
      im-platform/src/main/java/com/bx/implatform/entity/User.java
  18. 9
      im-platform/src/main/java/com/bx/implatform/mapper/FriendMapper.java
  19. 11
      im-platform/src/main/java/com/bx/implatform/mapper/GroupMapper.java
  20. 11
      im-platform/src/main/java/com/bx/implatform/mapper/GroupMemberMapper.java
  21. 11
      im-platform/src/main/java/com/bx/implatform/mapper/GroupMessageMapper.java
  22. 9
      im-platform/src/main/java/com/bx/implatform/mapper/PrivateMessageMapper.java
  23. 9
      im-platform/src/main/java/com/bx/implatform/mapper/UserMapper.java
  24. 11
      im-platform/src/main/java/com/bx/implatform/service/IFriendService.java
  25. 11
      im-platform/src/main/java/com/bx/implatform/service/IGroupMemberService.java
  26. 4
      im-platform/src/main/java/com/bx/implatform/service/IGroupMessageService.java
  27. 13
      im-platform/src/main/java/com/bx/implatform/service/IGroupService.java
  28. 2
      im-platform/src/main/java/com/bx/implatform/service/IPrivateMessageService.java
  29. 11
      im-platform/src/main/java/com/bx/implatform/service/IUserService.java
  30. 66
      im-platform/src/main/java/com/bx/implatform/service/impl/FriendServiceImpl.java
  31. 6
      im-platform/src/main/java/com/bx/implatform/service/impl/GroupMemberServiceImpl.java
  32. 22
      im-platform/src/main/java/com/bx/implatform/service/impl/GroupMessageServiceImpl.java
  33. 17
      im-platform/src/main/java/com/bx/implatform/service/impl/GroupServiceImpl.java
  34. 8
      im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java
  35. 8
      im-platform/src/main/java/com/bx/implatform/service/impl/SecurityUserDetailsServiceImpl.java
  36. 54
      im-platform/src/main/java/com/bx/implatform/service/impl/UserServiceImpl.java
  37. 2
      im-platform/src/main/java/com/bx/implatform/service/thirdparty/FileService.java
  38. 2
      im-platform/src/main/java/com/bx/implatform/task/PullAlreadyReadMessageTask.java
  39. 4
      im-platform/src/main/java/com/bx/implatform/vo/GroupVO.java
  40. 4
      im-platform/src/main/resources/application.yml
  41. 1
      im-server/src/main/java/com/bx/imserver/config/RedisConfig.java
  42. 2
      im-server/src/main/java/com/bx/imserver/task/PullUnreadGroupMessageTask.java
  43. 3
      im-server/src/main/java/com/bx/imserver/task/PullUnreadPrivateMessageTask.java
  44. 25
      im-server/src/main/java/com/bx/imserver/websocket/WebSocketHandler.java
  45. 10
      im-server/src/main/java/com/bx/imserver/websocket/WebsocketChannelCtxHolder.java
  46. 10
      im-server/src/main/java/com/bx/imserver/websocket/WebsocketServer.java
  47. 6
      im-server/src/main/java/com/bx/imserver/websocket/processor/GroupMessageProcessor.java
  48. 7
      im-server/src/main/java/com/bx/imserver/websocket/processor/LoginProcessor.java
  49. 6
      im-server/src/main/java/com/bx/imserver/websocket/processor/PrivateMessageProcessor.java

13
commom/src/main/java/com/bx/common/result/ResultUtils.java

@ -3,13 +3,8 @@ package com.bx.common.result;
import com.bx.common.enums.ResultCode;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ResultUtils {
public static final <T> Result<T> success(){
Result result=new Result();
result.setCode(ResultCode.SUCCESS.getCode());
@ -18,14 +13,6 @@ public class ResultUtils {
}
public static final <T> Result<T> success(T data){
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
cachedThreadPool.submit(new Runnable() {
@Override
public void run() {
System.out.println("当前线程"+Thread.currentThread().getName());
}
});
Result result=new Result();
result.setCode(ResultCode.SUCCESS.getCode());
result.setMessage(ResultCode.SUCCESS.getMsg());

7
im-platform/src/main/java/com/bx/implatform/config/MinIoClientConfig.java

@ -15,13 +15,10 @@ public class MinIoClientConfig {
@Value("${minio.secretKey}")
private String secretKey;
/**
* 注入minio 客户端
* @return
*/
@Bean
public MinioClient minioClient(){
// 注入minio 客户端
MinioClient client = MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)

18
im-platform/src/main/java/com/bx/implatform/config/RedisConfig.java

@ -27,10 +27,7 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
import javax.annotation.Resource;
import java.time.Duration;
/**
* redis配置
* @author zsq
*/
@EnableCaching
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
@ -38,17 +35,6 @@ public class RedisConfig extends CachingConfigurerSupport {
@Resource
private RedisConnectionFactory factory;
/**
* 重写Redis序列化方式使用Json方式:
* 当我们的数据存储到Redis的时候我们的键key和值value都是通过Spring提供的Serializer序列化到数据库的RedisTemplate默认使用的是JdkSerializationRedisSerializerStringRedisTemplate默认使用的是StringRedisSerializer
* Spring Data JPA为我们提供了下面的Serializer
* GenericToStringSerializerJackson2JsonRedisSerializerJacksonJsonRedisSerializerJdkSerializationRedisSerializerOxmSerializerStringRedisSerializer
* 在此我们将自己配置RedisTemplate并定义Serializer
*
* @param redisConnectionFactory
* @return
*/
@Primary
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
@ -95,12 +81,12 @@ public class RedisConfig extends CachingConfigurerSupport {
@Bean
@Override
public CacheManager cacheManager() {
// 设置redis缓存管理器
RedisCacheConfiguration cacheConfiguration =
RedisCacheConfiguration.defaultCacheConfig()
.disableCachingNullValues()
.entryTtl(Duration.ofMinutes(10))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer()));
return RedisCacheManager.builder(factory).cacheDefaults(cacheConfiguration).build();
}
}

4
im-platform/src/main/java/com/bx/implatform/config/SwaggerConfig.java

@ -33,8 +33,8 @@ public class SwaggerConfig {
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("IM Platform doc")
.description("蓝星IM API文档")
.termsOfServiceUrl("http://XXX/")
.description("盒子IM API文档")
.termsOfServiceUrl("http://8.134.92.70/")
.version("1.0")
.build();
}

35
im-platform/src/main/java/com/bx/implatform/config/WebSecurityConfg.java

@ -1,16 +1,15 @@
package com.bx.implatform.config;
import com.alibaba.fastjson.JSON;
import com.bx.implatform.service.IUserService;
import com.bx.implatform.session.UserSession;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.bx.common.enums.ResultCode;
import com.bx.common.result.Result;
import com.bx.common.result.ResultUtils;
import com.bx.implatform.service.IUserService;
import com.bx.implatform.session.UserSession;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.*;
@ -32,6 +31,7 @@ import java.io.PrintWriter;
/*
* SpringSecurity安全框架配置
*
* @Author Blue
* @Date 2022/10/21
*/
@ -58,7 +58,7 @@ public class WebSecurityConfg extends WebSecurityConfigurerAdapter {
.anyRequest() //任何其它请求
.authenticated() //都需要身份认证
.and()
//2、登录配置表单认证方式
// 登录配置表单认证方式
.formLogin()
.usernameParameter("username")//设置登录账号参数,与表单参数一致
.passwordParameter("password")//设置登录密码参数,与表单参数一致
@ -66,16 +66,16 @@ public class WebSecurityConfg extends WebSecurityConfigurerAdapter {
.successHandler(successHandler())
.failureHandler(failureHandler())
.and()
//3、注销
// 注销
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(logoutHandler())
.permitAll()
.and()
//4、session管理
// session管理
.sessionManagement()
.and()
//5、禁用跨站csrf攻击防御
// 禁用跨站csrf攻击防御
.csrf()
.disable()
.exceptionHandling()
@ -83,8 +83,6 @@ public class WebSecurityConfg extends WebSecurityConfigurerAdapter {
}
@Bean
AuthenticationFailureHandler failureHandler(){
return (request, response, exception) -> {
@ -111,6 +109,10 @@ public class WebSecurityConfg extends WebSecurityConfigurerAdapter {
@Bean
AuthenticationSuccessHandler successHandler(){
return (request, response, authentication) -> {
User useDetail = (User)authentication.getPrincipal();
String strJson = useDetail.getUsername();
UserSession userSession = JSON.parseObject(strJson,UserSession.class);
log.info("用户 '{}' 登录,id:{},昵称:{}",userSession.getUserName(),userSession.getId(),userSession.getNickName());
// 响应
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
@ -118,6 +120,7 @@ public class WebSecurityConfg extends WebSecurityConfigurerAdapter {
out.write(new ObjectMapper().writeValueAsString(result));
out.flush();
out.close();
};
}
@ -125,12 +128,10 @@ public class WebSecurityConfg extends WebSecurityConfigurerAdapter {
@Bean
LogoutSuccessHandler logoutHandler(){
return (request, response, authentication) -> {
User useDetail = (User)authentication.getPrincipal();
String strJson = useDetail.getUsername();
UserSession userSession = JSON.parseObject(strJson,UserSession.class);
log.info("{}退出", userSession.getUserName());
log.info("用户 '{}' 退出,id:{},昵称:{}",userSession.getUserName(),userSession.getId(),userSession.getNickName());
// 响应
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
@ -145,7 +146,6 @@ public class WebSecurityConfg extends WebSecurityConfigurerAdapter {
AuthenticationEntryPoint entryPoint(){
return (request, response, exception) -> {
response.setContentType("application/json;charset=utf-8");
log.info(request.getRequestURI());
PrintWriter out = response.getWriter();
Result result = ResultUtils.error(ResultCode.NO_LOGIN);
out.write(new ObjectMapper().writeValueAsString(result));
@ -156,18 +156,13 @@ public class WebSecurityConfg extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder(){
// 使用BCrypt加密密码
return new BCryptPasswordEncoder();
}
/**
* 密码加密
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());

8
im-platform/src/main/java/com/bx/implatform/controller/FileController.java

@ -2,8 +2,8 @@ package com.bx.implatform.controller;
import com.bx.common.result.Result;
import com.bx.common.result.ResultUtils;
import com.bx.implatform.vo.UploadImageVO;
import com.bx.implatform.service.thirdparty.FileService;
import com.bx.implatform.vo.UploadImageVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
@ -12,11 +12,7 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
/*
* 文件上传
* @Author Blue
* @Date 2022/10/28
*/
@Slf4j
@RestController
@Api(tags = "文件上传")

2
im-platform/src/main/java/com/bx/implatform/controller/FriendController.java

@ -3,10 +3,10 @@ package com.bx.implatform.controller;
import com.bx.common.result.Result;
import com.bx.common.result.ResultUtils;
import com.bx.implatform.vo.FriendVO;
import com.bx.implatform.entity.Friend;
import com.bx.implatform.service.IFriendService;
import com.bx.implatform.session.SessionContext;
import com.bx.implatform.vo.FriendVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;

4
im-platform/src/main/java/com/bx/implatform/controller/GroupController.java

@ -3,10 +3,11 @@ package com.bx.implatform.controller;
import com.bx.common.result.Result;
import com.bx.common.result.ResultUtils;
import com.bx.implatform.service.IGroupService;
import com.bx.implatform.vo.GroupInviteVO;
import com.bx.implatform.vo.GroupMemberVO;
import com.bx.implatform.vo.GroupVO;
import com.bx.implatform.service.IGroupService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@ -17,6 +18,7 @@ import javax.validation.constraints.NotNull;
import java.util.List;
@Api(tags = "群聊")
@RestController
@RequestMapping("/group")
public class GroupController {

6
im-platform/src/main/java/com/bx/implatform/controller/GroupMessageController.java

@ -3,19 +3,21 @@ package com.bx.implatform.controller;
import com.bx.common.result.Result;
import com.bx.common.result.ResultUtils;
import com.bx.implatform.vo.GroupMessageVO;
import com.bx.implatform.service.IGroupMessageService;
import com.bx.implatform.vo.GroupMessageVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
@Api(tags = "群聊消息")
@RestController
@RequestMapping("/message/group")
public class GroupMessageController {

2
im-platform/src/main/java/com/bx/implatform/controller/PrivateMessageController.java

@ -3,8 +3,8 @@ package com.bx.implatform.controller;
import com.bx.common.result.Result;
import com.bx.common.result.ResultUtils;
import com.bx.implatform.vo.PrivateMessageVO;
import com.bx.implatform.service.IPrivateMessageService;
import com.bx.implatform.vo.PrivateMessageVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;

2
im-platform/src/main/java/com/bx/implatform/controller/RegisterController.java

@ -3,8 +3,8 @@ package com.bx.implatform.controller;
import com.bx.common.result.Result;
import com.bx.common.result.ResultUtils;
import com.bx.implatform.vo.RegisterVO;
import com.bx.implatform.service.IUserService;
import com.bx.implatform.vo.RegisterVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;

2
im-platform/src/main/java/com/bx/implatform/controller/UserController.java

@ -4,11 +4,11 @@ package com.bx.implatform.controller;
import com.bx.common.result.Result;
import com.bx.common.result.ResultUtils;
import com.bx.common.util.BeanUtils;
import com.bx.implatform.vo.UserVO;
import com.bx.implatform.entity.User;
import com.bx.implatform.service.IUserService;
import com.bx.implatform.session.SessionContext;
import com.bx.implatform.session.UserSession;
import com.bx.implatform.vo.UserVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;

2
im-platform/src/main/java/com/bx/implatform/entity/Friend.java

@ -13,7 +13,7 @@ import java.util.Date;
/**
* <p>
*
* 好友
* </p>
*
* @author blue

15
im-platform/src/main/java/com/bx/implatform/entity/Group.java

@ -1,19 +1,16 @@
package com.bx.implatform.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
/**
*
* @author blue

15
im-platform/src/main/java/com/bx/implatform/entity/GroupMember.java

@ -1,19 +1,16 @@
package com.bx.implatform.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 群成员

15
im-platform/src/main/java/com/bx/implatform/entity/GroupMessage.java

@ -1,19 +1,16 @@
package com.bx.implatform.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 群消息

2
im-platform/src/main/java/com/bx/implatform/entity/User.java

@ -13,7 +13,7 @@ import java.util.Date;
/**
* <p>
*
* 用户
* </p>
*
* @author blue

9
im-platform/src/main/java/com/bx/implatform/mapper/FriendMapper.java

@ -3,14 +3,7 @@ package com.bx.implatform.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bx.implatform.entity.Friend;
/**
* <p>
* Mapper 接口
* </p>
*
* @author blue
* @since 2022-10-22
*/
public interface FriendMapper extends BaseMapper<Friend> {
}

11
im-platform/src/main/java/com/bx/implatform/mapper/GroupMapper.java

@ -1,16 +1,9 @@
package com.bx.implatform.mapper;
import com.bx.implatform.entity.Group;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bx.implatform.entity.Group;
/**
* <p>
* Mapper 接口
* </p>
*
* @author blue
* @since 2022-10-31
*/
public interface GroupMapper extends BaseMapper<Group> {
}

11
im-platform/src/main/java/com/bx/implatform/mapper/GroupMemberMapper.java

@ -1,16 +1,9 @@
package com.bx.implatform.mapper;
import com.bx.implatform.entity.GroupMember;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bx.implatform.entity.GroupMember;
/**
* <p>
* 群成员 Mapper 接口
* </p>
*
* @author blue
* @since 2022-10-31
*/
public interface GroupMemberMapper extends BaseMapper<GroupMember> {
}

11
im-platform/src/main/java/com/bx/implatform/mapper/GroupMessageMapper.java

@ -1,16 +1,9 @@
package com.bx.implatform.mapper;
import com.bx.implatform.entity.GroupMessage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bx.implatform.entity.GroupMessage;
/**
* <p>
* 群消息 Mapper 接口
* </p>
*
* @author blue
* @since 2022-10-31
*/
public interface GroupMessageMapper extends BaseMapper<GroupMessage> {
}

9
im-platform/src/main/java/com/bx/implatform/mapper/PrivateMessageMapper.java

@ -3,14 +3,7 @@ package com.bx.implatform.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bx.implatform.entity.PrivateMessage;
/**
* <p>
* Mapper 接口
* </p>
*
* @author blue
* @since 2022-10-01
*/
public interface PrivateMessageMapper extends BaseMapper<PrivateMessage> {
}

9
im-platform/src/main/java/com/bx/implatform/mapper/UserMapper.java

@ -3,14 +3,7 @@ package com.bx.implatform.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bx.implatform.entity.User;
/**
* <p>
* Mapper 接口
* </p>
*
* @author blue
* @since 2022-10-01
*/
public interface UserMapper extends BaseMapper<User> {
}

11
im-platform/src/main/java/com/bx/implatform/service/IFriendService.java

@ -1,19 +1,12 @@
package com.bx.implatform.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bx.implatform.vo.FriendVO;
import com.bx.implatform.entity.Friend;
import com.bx.implatform.vo.FriendVO;
import java.util.List;
/**
* <p>
* 服务类
* </p>
*
* @author blue
* @since 2022-10-22
*/
public interface IFriendService extends IService<Friend> {
Boolean isFriend(Long userId1, Long userId2);

11
im-platform/src/main/java/com/bx/implatform/service/IGroupMemberService.java

@ -1,18 +1,11 @@
package com.bx.implatform.service;
import com.bx.implatform.entity.GroupMember;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bx.implatform.entity.GroupMember;
import java.util.List;
/**
* <p>
* 群成员 服务类
* </p>
*
* @author blue
* @since 2022-10-31
*/
public interface IGroupMemberService extends IService<GroupMember> {

4
im-platform/src/main/java/com/bx/implatform/service/IGroupMessageService.java

@ -1,8 +1,8 @@
package com.bx.implatform.service;
import com.bx.implatform.vo.GroupMessageVO;
import com.bx.implatform.entity.GroupMessage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bx.implatform.entity.GroupMessage;
import com.bx.implatform.vo.GroupMessageVO;
public interface IGroupMessageService extends IService<GroupMessage> {

13
im-platform/src/main/java/com/bx/implatform/service/IGroupService.java

@ -1,21 +1,14 @@
package com.bx.implatform.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bx.implatform.entity.Group;
import com.bx.implatform.vo.GroupInviteVO;
import com.bx.implatform.vo.GroupMemberVO;
import com.bx.implatform.vo.GroupVO;
import com.bx.implatform.entity.Group;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* <p>
* 服务类
* </p>
*
* @author blue
* @since 2022-10-31
*/
public interface IGroupService extends IService<Group> {

2
im-platform/src/main/java/com/bx/implatform/service/IPrivateMessageService.java

@ -1,8 +1,8 @@
package com.bx.implatform.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bx.implatform.vo.PrivateMessageVO;
import com.bx.implatform.entity.PrivateMessage;
import com.bx.implatform.vo.PrivateMessageVO;
public interface IPrivateMessageService extends IService<PrivateMessage> {

11
im-platform/src/main/java/com/bx/implatform/service/IUserService.java

@ -1,20 +1,13 @@
package com.bx.implatform.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bx.implatform.entity.User;
import com.bx.implatform.vo.RegisterVO;
import com.bx.implatform.vo.UserVO;
import com.bx.implatform.entity.User;
import java.util.List;
/**
* <p>
* 用户服务类
* </p>
*
* @author blue
* @since 2022-10-01
*/
public interface IUserService extends IService<User> {
void register(RegisterVO registerDTO);

66
im-platform/src/main/java/com/bx/implatform/service/impl/FriendServiceImpl.java

@ -4,15 +4,15 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bx.common.contant.RedisKey;
import com.bx.common.enums.ResultCode;
import com.bx.implatform.exception.GlobalException;
import com.bx.implatform.vo.FriendVO;
import com.bx.implatform.entity.Friend;
import com.bx.implatform.entity.User;
import com.bx.implatform.exception.GlobalException;
import com.bx.implatform.mapper.FriendMapper;
import com.bx.implatform.service.IFriendService;
import com.bx.implatform.service.IUserService;
import com.bx.implatform.session.SessionContext;
import com.bx.implatform.session.UserSession;
import com.bx.implatform.vo.FriendVO;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
@ -23,14 +23,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* <p>
* 好友服务实现类
* </p>
*
* @author blue
* @since 2022-10-22
*/
@CacheConfig(cacheNames= RedisKey.IM_CACHE_FRIEND)
@Service
public class FriendServiceImpl extends ServiceImpl<FriendMapper, Friend> implements IFriendService {
@ -38,6 +31,12 @@ public class FriendServiceImpl extends ServiceImpl<FriendMapper, Friend> impleme
@Autowired
private IUserService userService;
/**
* 查询用户的所有好友
*
* @param UserId 用户id
* @return
*/
@Override
public List<Friend> findFriendByUserId(Long UserId) {
QueryWrapper<Friend> queryWrapper = new QueryWrapper();
@ -47,6 +46,12 @@ public class FriendServiceImpl extends ServiceImpl<FriendMapper, Friend> impleme
}
/**
* 添加好友互相建立好友关系
*
* @param friendId 好友的用户id
* @return
*/
@Transactional
@Override
public void addFriend(Long friendId) {
@ -61,6 +66,12 @@ public class FriendServiceImpl extends ServiceImpl<FriendMapper, Friend> impleme
}
/**
* 删除好友双方都会解除好友关系
*
* @param friendId 好友的用户id
* @return
*/
@Transactional
@Override
public void delFriend(Long friendId) {
@ -72,6 +83,13 @@ public class FriendServiceImpl extends ServiceImpl<FriendMapper, Friend> impleme
}
/**
* 判断用户2是否用户1的好友
*
* @param userId1 用户1的id
* @param userId2 用户2的id
* @return
*/
@Cacheable(key="#userId1+':'+#userId2")
@Override
public Boolean isFriend(Long userId1, Long userId2) {
@ -83,6 +101,12 @@ public class FriendServiceImpl extends ServiceImpl<FriendMapper, Friend> impleme
}
/**
* 更新好友信息主要是头像和昵称
*
* @param vo 好友vo
* @return
*/
@Override
public void update(FriendVO vo) {
long userId = SessionContext.getSession().getId();
@ -101,6 +125,14 @@ public class FriendServiceImpl extends ServiceImpl<FriendMapper, Friend> impleme
this.updateById(f);
}
/**
* 单向绑定好友关系
*
* @param userId 用户id
* @param friendId 好友的用户id
* @return
*/
@CacheEvict(key="#userId+':'+#friendId")
public void bindFriend(Long userId, Long friendId) {
QueryWrapper<Friend> queryWrapper = new QueryWrapper<>();
@ -118,6 +150,14 @@ public class FriendServiceImpl extends ServiceImpl<FriendMapper, Friend> impleme
}
}
/**
* 单向解除好友关系
*
* @param userId 用户id
* @param friendId 好友的用户id
* @return
*/
@CacheEvict(key="#userId+':'+#friendId")
public void unbindFriend(Long userId, Long friendId) {
QueryWrapper<Friend> queryWrapper = new QueryWrapper<>();
@ -131,6 +171,12 @@ public class FriendServiceImpl extends ServiceImpl<FriendMapper, Friend> impleme
}
/**
* 查询指定的某个好友信息
*
* @param friendId 好友的用户id
* @return
*/
@Override
public FriendVO findFriend(Long friendId) {
UserSession session = SessionContext.getSession();

6
im-platform/src/main/java/com/bx/implatform/service/impl/GroupMemberServiceImpl.java

@ -2,11 +2,11 @@ package com.bx.implatform.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bx.common.contant.RedisKey;
import com.bx.implatform.entity.GroupMember;
import com.bx.implatform.mapper.GroupMemberMapper;
import com.bx.implatform.service.IGroupMemberService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
@ -62,6 +62,7 @@ public class GroupMemberServiceImpl extends ServiceImpl<GroupMemberMapper, Group
return this.getOne(wrapper);
}
/**
* 根据用户id查询群聊成员
*
@ -76,6 +77,7 @@ public class GroupMemberServiceImpl extends ServiceImpl<GroupMemberMapper, Group
return this.list(memberWrapper);
}
/**
* 根据群聊id查询群聊成员包括已退出
*
@ -89,6 +91,7 @@ public class GroupMemberServiceImpl extends ServiceImpl<GroupMemberMapper, Group
return this.list(memberWrapper);
}
/**
* 根据群聊id查询没有退出的群聊成员id
*
@ -106,7 +109,6 @@ public class GroupMemberServiceImpl extends ServiceImpl<GroupMemberMapper, Group
}
/**
*根据群聊id删除移除成员
*

22
im-platform/src/main/java/com/bx/implatform/service/impl/GroupMessageServiceImpl.java

@ -1,21 +1,21 @@
package com.bx.implatform.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bx.common.contant.RedisKey;
import com.bx.common.enums.ResultCode;
import com.bx.common.model.im.GroupMessageInfo;
import com.bx.common.util.BeanUtils;
import com.bx.implatform.exception.GlobalException;
import com.bx.implatform.vo.GroupMessageVO;
import com.bx.implatform.entity.Group;
import com.bx.implatform.entity.GroupMember;
import com.bx.implatform.entity.GroupMessage;
import com.bx.implatform.exception.GlobalException;
import com.bx.implatform.mapper.GroupMessageMapper;
import com.bx.implatform.service.IGroupMemberService;
import com.bx.implatform.service.IGroupMessageService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bx.implatform.service.IGroupService;
import com.bx.implatform.session.SessionContext;
import com.bx.implatform.vo.GroupMessageVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@ -49,7 +49,15 @@ public class GroupMessageServiceImpl extends ServiceImpl<GroupMessageMapper, Gro
Long userId = SessionContext.getSession().getId();
Group group = groupService.getById(vo.getGroupId());
if(group == null){
throw new GlobalException(ResultCode.PROGRAM_ERROR,"群聊不存在或已解散");
throw new GlobalException(ResultCode.PROGRAM_ERROR,"群聊不存在");
}
if(group.getDeleted()){
throw new GlobalException(ResultCode.PROGRAM_ERROR,"群聊已解散");
}
// 判断是否在群里
List<Long> userIds = groupMemberService.findUserIdsByGroupId(group.getId());
if(!userIds.contains(userId)){
throw new GlobalException(ResultCode.PROGRAM_ERROR,"您已不在群聊里面,无法发送消息");
}
// 保存消息
GroupMessage msg = BeanUtils.copyProperties(vo, GroupMessage.class);
@ -58,13 +66,7 @@ public class GroupMessageServiceImpl extends ServiceImpl<GroupMessageMapper, Gro
this.save(msg);
// 根据群聊每个成员所连的IM-server,进行分组
Map<Integer,List<Long>> serverMap = new ConcurrentHashMap<>();
List<Long> userIds = groupMemberService.findUserIdsByGroupId(group.getId());
if(!userIds.contains(userId)){
throw new GlobalException(ResultCode.PROGRAM_ERROR,"您已不在群聊里面,无法发送消息");
}
userIds.parallelStream().forEach(id->{
String key = RedisKey.IM_USER_SERVER_ID + id;
Integer serverId = (Integer)redisTemplate.opsForValue().get(key);
if(serverId != null){

17
im-platform/src/main/java/com/bx/implatform/service/impl/GroupServiceImpl.java

@ -1,26 +1,26 @@
package com.bx.implatform.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bx.common.contant.Constant;
import com.bx.common.contant.RedisKey;
import com.bx.common.enums.ResultCode;
import com.bx.common.util.BeanUtils;
import com.bx.implatform.exception.GlobalException;
import com.bx.implatform.vo.GroupInviteVO;
import com.bx.implatform.vo.GroupMemberVO;
import com.bx.implatform.vo.GroupVO;
import com.bx.implatform.entity.Friend;
import com.bx.implatform.entity.Group;
import com.bx.implatform.entity.GroupMember;
import com.bx.implatform.entity.User;
import com.bx.implatform.exception.GlobalException;
import com.bx.implatform.mapper.GroupMapper;
import com.bx.implatform.service.IFriendService;
import com.bx.implatform.service.IGroupMemberService;
import com.bx.implatform.service.IGroupService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bx.implatform.service.IUserService;
import com.bx.implatform.session.SessionContext;
import com.bx.implatform.session.UserSession;
import com.bx.implatform.vo.GroupInviteVO;
import com.bx.implatform.vo.GroupMemberVO;
import com.bx.implatform.vo.GroupVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
@ -28,6 +28,7 @@ import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
@ -51,8 +52,8 @@ public class GroupServiceImpl extends ServiceImpl<GroupMapper, Group> implements
/**
* 创建新群聊
*
* @return GroupVO
* @Param groupName 群聊名称
* @return
**/
@Transactional
@Override
@ -85,7 +86,7 @@ public class GroupServiceImpl extends ServiceImpl<GroupMapper, Group> implements
* 修改群聊信息
*
* @Param GroupVO 群聊信息
* @return GroupVO
* @return
**/
@CacheEvict(value = "#vo.getId()")
@Transactional
@ -209,7 +210,7 @@ public class GroupServiceImpl extends ServiceImpl<GroupMapper, Group> implements
/**
* 查询当前用户的所有群聊
*
* @return List<GroupVO>
* @return
**/
@Override
public List<GroupVO> findGroups() {

8
im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java

@ -7,13 +7,13 @@ import com.bx.common.enums.MessageStatusEnum;
import com.bx.common.enums.ResultCode;
import com.bx.common.model.im.PrivateMessageInfo;
import com.bx.common.util.BeanUtils;
import com.bx.implatform.entity.PrivateMessage;
import com.bx.implatform.exception.GlobalException;
import com.bx.implatform.mapper.PrivateMessageMapper;
import com.bx.implatform.service.IFriendService;
import com.bx.implatform.service.IPrivateMessageService;
import com.bx.implatform.session.SessionContext;
import com.bx.implatform.vo.PrivateMessageVO;
import com.bx.implatform.entity.PrivateMessage;
import com.bx.implatform.mapper.PrivateMessageMapper;
import com.bx.implatform.service.IFriendService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@ -34,7 +34,7 @@ public class PrivateMessageServiceImpl extends ServiceImpl<PrivateMessageMapper,
/**
* 发送私聊消息
*
* @param vo
* @param vo 私聊消息vo
* @return
*/
@Override

8
im-platform/src/main/java/com/bx/implatform/service/impl/SecurityUserDetailsServiceImpl.java

@ -23,7 +23,13 @@ public class SecurityUserDetailsServiceImpl implements UserDetailsService {
@Autowired
private IUserService userService;
/**
* 加载用户数据用户登录时由spring security调用
*
* @param username 用户名
* @throws UsernameNotFoundException 用户不存在时抛出
* @return
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userService.findUserByName(username);

54
im-platform/src/main/java/com/bx/implatform/service/impl/UserServiceImpl.java

@ -5,18 +5,18 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bx.common.contant.RedisKey;
import com.bx.common.enums.ResultCode;
import com.bx.common.util.BeanUtils;
import com.bx.implatform.exception.GlobalException;
import com.bx.implatform.service.IUserService;
import com.bx.implatform.session.SessionContext;
import com.bx.implatform.session.UserSession;
import com.bx.implatform.vo.RegisterVO;
import com.bx.implatform.vo.UserVO;
import com.bx.implatform.entity.Friend;
import com.bx.implatform.entity.GroupMember;
import com.bx.implatform.entity.User;
import com.bx.implatform.exception.GlobalException;
import com.bx.implatform.mapper.UserMapper;
import com.bx.implatform.service.IFriendService;
import com.bx.implatform.service.IGroupMemberService;
import com.bx.implatform.service.IUserService;
import com.bx.implatform.session.SessionContext;
import com.bx.implatform.session.UserSession;
import com.bx.implatform.vo.RegisterVO;
import com.bx.implatform.vo.UserVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
@ -27,14 +27,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 用户服务实现类
* </p>
*
* @author blue
* @since 2022-10-01
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
@ -50,6 +43,12 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IU
@Autowired
private IFriendService friendService;
/**
* 用户注册
*
* @param vo 注册vo
* @return
*/
@Override
public void register(RegisterVO vo) {
User user = findUserByName(vo.getUserName());
@ -61,6 +60,12 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IU
this.save(user);
}
/**
* 根据用户名查询用户
*
* @param username 用户名
* @return
*/
@Override
public User findUserByName(String username) {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
@ -68,6 +73,12 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IU
return this.getOne(queryWrapper);
}
/**
* 更新用户信息好友昵称和群聊昵称等冗余信息也会更新
*
* @param vo 用户信息vo
* @return
*/
@Transactional
@Override
public void update(UserVO vo) {
@ -107,12 +118,19 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IU
this.updateById(user);
}
/**
* 根据用户昵称查询用户最多返回20条数据
*
* @param nickname 用户昵称
* @return
*/
@Override
public List<UserVO> findUserByNickName(String nickname) {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda()
.like(User::getNickName,nickname)
.last("limit 10");
.last("limit 20");
List<User> users = this.list(queryWrapper);
List<UserVO> vos = users.stream().map(u-> {
UserVO vo = BeanUtils.copyProperties(u,UserVO.class);
@ -123,6 +141,12 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IU
}
/**
* 判断用户是否在线返回在线的用户id列表
*
* @param userIds 用户id多个用,分割
* @return
*/
@Override
public List<Long> checkOnline(String userIds) {
String[] idArr = userIds.split(",");

2
im-platform/src/main/java/com/bx/implatform/service/thirdparty/FileService.java

@ -4,10 +4,10 @@ import com.bx.common.contant.Constant;
import com.bx.common.enums.FileTypeEnum;
import com.bx.common.enums.ResultCode;
import com.bx.implatform.exception.GlobalException;
import com.bx.implatform.vo.UploadImageVO;
import com.bx.implatform.util.FileUtil;
import com.bx.implatform.util.ImageUtil;
import com.bx.implatform.util.MinioUtil;
import com.bx.implatform.vo.UploadImageVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

2
im-platform/src/main/java/com/bx/implatform/task/PullAlreadyReadMessageTask.java

@ -64,8 +64,10 @@ public class PullAlreadyReadMessageTask {
Thread.sleep(200);
}finally {
// 下一次循环
if(executorService.isShutdown()){
executorService.submit(this);
}
}
}
}
}

4
im-platform/src/main/java/com/bx/implatform/vo/GroupVO.java

@ -1,8 +1,5 @@
package com.bx.implatform.vo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ -10,7 +7,6 @@ import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Date;
@Data
@ApiModel("群信息VO")

4
im-platform/src/main/resources/application.yml

@ -5,7 +5,7 @@ server:
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/box-im?useUnicode=true&characterEncoding=utf-8
url: jdbc:mysql://localhost:3306/box-im?useSSL=false&useUnicode=true&characterEncoding=utf-8
username: root
password: root
@ -23,7 +23,7 @@ mybatis-plus:
configuration:
# 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN(下划线命名) 到经典 Java 属性名 aColumn(驼峰命名) 的类似映射
map-underscore-to-camel-case: false
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# mapper
mapper-locations:
# *.xml的具体路径

1
im-server/src/main/java/com/bx/imserver/config/RedisConfig.java

@ -26,7 +26,6 @@ public class RedisConfig {
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 设置值(value)的序列化采用jackson2JsonRedisSerializer
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer());
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer());

2
im-server/src/main/java/com/bx/imserver/task/PullUnreadGroupMessageTask.java

@ -34,7 +34,7 @@ public class PullUnreadGroupMessageTask extends AbstractPullMessageTask {
redisTemplate.opsForList().leftPop(key);
GroupMessageInfo messageInfo = (GroupMessageInfo)o;
MessageProcessor processor = ProcessorFactory.createProcessor(WSCmdEnum.GROUP_MESSAGE);
processor.process(null,messageInfo);
processor.process(messageInfo);
}
}

3
im-server/src/main/java/com/bx/imserver/task/PullUnreadPrivateMessageTask.java

@ -33,9 +33,8 @@ public class PullUnreadPrivateMessageTask extends AbstractPullMessageTask {
for(Object o: messageInfos){
redisTemplate.opsForList().leftPop(key);
PrivateMessageInfo messageInfo = (PrivateMessageInfo)o;
MessageProcessor processor = ProcessorFactory.createProcessor(WSCmdEnum.PRIVATE_MESSAGE);
processor.process(null,messageInfo);
processor.process(messageInfo);
}
}

25
im-server/src/main/java/com/bx/imserver/websocket/WebSocketHandler.java

@ -23,7 +23,13 @@ import org.springframework.data.redis.core.RedisTemplate;
@Slf4j
public class WebSocketHandler extends SimpleChannelInboundHandler<SendInfo> {
/**
* 读取到消息后进行处理
*
* @param ctx
* @param sendInfo
* @throws Exception
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, SendInfo sendInfo) throws Exception {
// 创建处理器进行处理
@ -34,9 +40,9 @@ public class WebSocketHandler extends SimpleChannelInboundHandler<SendInfo> {
/**
* 出现异常的处理 打印报错日志
*
* @param ctx the ctx
* @param cause the cause
* @throws Exception the Exception
* @param ctx
* @param cause
* @throws Exception
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
@ -48,8 +54,8 @@ public class WebSocketHandler extends SimpleChannelInboundHandler<SendInfo> {
/**
* 监控浏览器上线
*
* @param ctx the ctx
* @throws Exception the Exception
* @param ctx
* @throws Exception
*/
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
@ -60,11 +66,11 @@ public class WebSocketHandler extends SimpleChannelInboundHandler<SendInfo> {
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
AttributeKey<Long> attr = AttributeKey.valueOf("USER_ID");
Long userId = ctx.channel().attr(attr).get();
ChannelHandlerContext context = WebsocketChannelCtxHloder.getChannelCtx(userId);
ChannelHandlerContext context = WebsocketChannelCtxHolder.getChannelCtx(userId);
// 判断一下,避免异地登录导致的误删
if(context != null && ctx.channel().id().equals(context.channel().id())){
// 移除channel
WebsocketChannelCtxHloder.removeChannelCtx(userId);
WebsocketChannelCtxHolder.removeChannelCtx(userId);
// 用户下线
RedisTemplate redisTemplate = SpringContextHolder.getBean("redisTemplate");
String key = RedisKey.IM_USER_SERVER_ID + userId;
@ -79,6 +85,9 @@ public class WebSocketHandler extends SimpleChannelInboundHandler<SendInfo> {
IdleState state = ((IdleStateEvent) evt).state();
if (state == IdleState.READER_IDLE) {
// 在规定时间内没有收到客户端的上行数据, 主动断开连接
AttributeKey<Long> attr = AttributeKey.valueOf("USER_ID");
Long userId = ctx.channel().attr(attr).get();
log.info("心跳超时,即将断开连接,用户id:{} ",userId);
ctx.channel().close();
}
} else {

10
im-server/src/main/java/com/bx/imserver/websocket/WebsocketChannelCtxHloder.java → im-server/src/main/java/com/bx/imserver/websocket/WebsocketChannelCtxHolder.java

@ -5,10 +5,13 @@ import io.netty.channel.ChannelHandlerContext;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class WebsocketChannelCtxHloder {
private static Map<Long, ChannelHandlerContext> channelMap = new ConcurrentHashMap();
public class WebsocketChannelCtxHolder {
/*
* 维护userId和ctx的关联关系格式:Map<userId,ctx>
*/
private static Map<Long, ChannelHandlerContext> channelMap = new ConcurrentHashMap();
public static void addChannelCtx(Long userId,ChannelHandlerContext ctx){
channelMap.put(userId,ctx);
@ -18,9 +21,6 @@ public class WebsocketChannelCtxHloder {
channelMap.remove(userId);
}
public static ChannelHandlerContext getChannelCtx(Long userId){
return channelMap.get(userId);
}

10
im-server/src/main/java/com/bx/imserver/websocket/WebsocketServer.java

@ -12,6 +12,7 @@ import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
@ -19,6 +20,7 @@ import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.concurrent.TimeUnit;
@Slf4j
@Component
public class WebsocketServer {
@ -62,7 +64,6 @@ public class WebsocketServer {
protected void initChannel(Channel ch) throws Exception {
// 获取职责链
ChannelPipeline pipeline = ch.pipeline();
//
pipeline.addLast(new IdleStateHandler(15, 0, 0, TimeUnit.SECONDS));
pipeline.addLast("http-codec", new HttpServerCodec());
pipeline.addLast("aggregator", new HttpObjectAggregator(65535));
@ -79,12 +80,13 @@ public class WebsocketServer {
.option(ChannelOption.SO_BACKLOG, 5)
// 表示连接保活,相当于心跳机制,默认为7200s
.childOption(ChannelOption.SO_KEEPALIVE, true);
// 就绪标志
this.ready = true;
try {
// 绑定端口,启动select线程,轮询监听channel事件,监听到事件之后就会交给从线程池处理
Channel channel = bootstrap.bind(port).sync().channel();
// 就绪标志
this.ready = true;
log.info("websocket server 初始化完成....");
// 等待服务端口关闭
channel.closeFuture().sync();
} catch (InterruptedException e) {

6
im-server/src/main/java/com/bx/imserver/websocket/processor/GroupMessageProcessor.java

@ -4,7 +4,7 @@ import com.bx.common.contant.RedisKey;
import com.bx.common.enums.WSCmdEnum;
import com.bx.common.model.im.GroupMessageInfo;
import com.bx.common.model.im.SendInfo;
import com.bx.imserver.websocket.WebsocketChannelCtxHloder;
import com.bx.imserver.websocket.WebsocketChannelCtxHolder;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@ -23,13 +23,13 @@ public class GroupMessageProcessor extends MessageProcessor<GroupMessageInfo> {
@Async
@Override
public void process(ChannelHandlerContext ctx, GroupMessageInfo data) {
public void process(GroupMessageInfo data) {
log.info("接收到群消息,发送者:{},群id:{},接收id:{},内容:{}",data.getSendId(),data.getGroupId(),data.getRecvIds(),data.getContent());
List<Long> recvIds = data.getRecvIds();
// 接收者id列表不需要传输,节省带宽
data.setRecvIds(null);
for(Long recvId:recvIds){
ChannelHandlerContext channelCtx = WebsocketChannelCtxHloder.getChannelCtx(recvId);
ChannelHandlerContext channelCtx = WebsocketChannelCtxHolder.getChannelCtx(recvId);
if(channelCtx != null){
// 自己发的消息不用推送
if(recvId != data.getSendId()){

7
im-server/src/main/java/com/bx/imserver/websocket/processor/LoginProcessor.java

@ -5,7 +5,7 @@ import com.bx.common.contant.RedisKey;
import com.bx.common.enums.WSCmdEnum;
import com.bx.common.model.im.LoginInfo;
import com.bx.common.model.im.SendInfo;
import com.bx.imserver.websocket.WebsocketChannelCtxHloder;
import com.bx.imserver.websocket.WebsocketChannelCtxHolder;
import com.bx.imserver.websocket.WebsocketServer;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.AttributeKey;
@ -30,16 +30,15 @@ public class LoginProcessor extends MessageProcessor<LoginInfo> {
@Override
synchronized public void process(ChannelHandlerContext ctx, LoginInfo loginInfo) {
log.info("用户登录,userId:{}",loginInfo.getUserId());
ChannelHandlerContext context = WebsocketChannelCtxHloder.getChannelCtx(loginInfo.getUserId());
ChannelHandlerContext context = WebsocketChannelCtxHolder.getChannelCtx(loginInfo.getUserId());
if(context != null){
// 不允许多地登录,强制下线
SendInfo sendInfo = new SendInfo();
sendInfo.setCmd(WSCmdEnum.FORCE_LOGUT.getCode());
context.channel().writeAndFlush(sendInfo);
}
// 绑定用户和channel
WebsocketChannelCtxHloder.addChannelCtx(loginInfo.getUserId(),ctx);
WebsocketChannelCtxHolder.addChannelCtx(loginInfo.getUserId(),ctx);
// 设置属性
AttributeKey<Long> attr = AttributeKey.valueOf("USER_ID");
ctx.channel().attr(attr).set(loginInfo.getUserId());

6
im-server/src/main/java/com/bx/imserver/websocket/processor/PrivateMessageProcessor.java

@ -4,7 +4,7 @@ import com.bx.common.contant.RedisKey;
import com.bx.common.enums.WSCmdEnum;
import com.bx.common.model.im.SendInfo;
import com.bx.common.model.im.PrivateMessageInfo;
import com.bx.imserver.websocket.WebsocketChannelCtxHloder;
import com.bx.imserver.websocket.WebsocketChannelCtxHolder;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@ -19,10 +19,10 @@ public class PrivateMessageProcessor extends MessageProcessor<PrivateMessageInf
private RedisTemplate<String,Object> redisTemplate;
@Override
public void process(ChannelHandlerContext ctx, PrivateMessageInfo data) {
public void process(PrivateMessageInfo data) {
log.info("接收到消息,发送者:{},接收者:{},内容:{}",data.getSendId(),data.getRecvId(),data.getContent());
// 一个用户可以同时登陆,所以有多个channel
ChannelHandlerContext channelCtx = WebsocketChannelCtxHloder.getChannelCtx(data.getRecvId());
ChannelHandlerContext channelCtx = WebsocketChannelCtxHolder.getChannelCtx(data.getRecvId());
if(channelCtx != null ){
// 推送消息到用户
SendInfo sendInfo = new SendInfo();

Loading…
Cancel
Save