Commit 5e21d26a by zhangjw

1:支持跨域

2:支持emoji
3:已知Bug修复(redis 序列化问题待完善)
parent 069345e9
...@@ -47,6 +47,12 @@ ...@@ -47,6 +47,12 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId> <artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional> <optional>true</optional>
......
package com.ym.im.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* @Description 请求跨域的问题
* @Author hewei hwei1233@163.com
* @Date 2019-07-12
*/
@Configuration
public class MvcConfig {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
// 原始请求的域名
corsConfiguration.addAllowedOrigin("*");
// 添加请求头字段Cache-Control, Expires, Content-Type等
corsConfiguration.addAllowedHeader("*");
// 服务器支持的所有跨域请求的方法('GET'、'POST')等
corsConfiguration.addAllowedMethod("*");
corsConfiguration.setAllowCredentials(true);
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//设置过滤条件
source.registerCorsConfiguration("/**", buildConfig());
return new CorsFilter(source);
}
}
...@@ -64,6 +64,11 @@ public class JwtTokenRedisVo implements Serializable { ...@@ -64,6 +64,11 @@ public class JwtTokenRedisVo implements Serializable {
* 登录token * 登录token
*/ */
private String token; private String token;
/**
* 设备推送token
*/
private String deviceToken;
/** /**
* 创建时间 * 创建时间
*/ */
......
...@@ -50,7 +50,7 @@ public class PullChatRecord implements Serializable { ...@@ -50,7 +50,7 @@ public class PullChatRecord implements Serializable {
private Integer pageSize = 20; private Integer pageSize = 20;
@ApiModelProperty(value = "总条数") @ApiModelProperty(value = "总条数")
private Long total; private Integer total;
@ApiModelProperty(value = "总页数") @ApiModelProperty(value = "总页数")
private Integer pages; private Integer pages;
......
...@@ -25,6 +25,9 @@ public class SingleChatFactory { ...@@ -25,6 +25,9 @@ public class SingleChatFactory {
* @return * @return
*/ */
public ChatService getService(String type) { public ChatService getService(String type) {
if (type == null) {
return null;
}
switch (RoleEnum.get(type)) { switch (RoleEnum.get(type)) {
case APP: case APP:
return userSingleChatServiceImpl; return userSingleChatServiceImpl;
......
package com.ym.im.handler; package com.ym.im.handler;
import com.ym.im.entity.base.ChannelAttributeKey; import com.ym.im.entity.base.ChannelAttributeKey;
import com.ym.im.exception.HttpException;
import com.ym.im.factory.SingleChatFactory; import com.ym.im.factory.SingleChatFactory;
import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
...@@ -21,21 +22,15 @@ public abstract class BaseHandler<T> extends SimpleChannelInboundHandler<T> { ...@@ -21,21 +22,15 @@ public abstract class BaseHandler<T> extends SimpleChannelInboundHandler<T> {
@Override @Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception { public void channelInactive(ChannelHandlerContext ctx) throws Exception {
try { singleChatFactory.getService(ctx.channel().attr(ChannelAttributeKey.ROLE_TYPE).get()).offline(ctx);
singleChatFactory.getService(ctx.channel().attr(ChannelAttributeKey.ROLE_TYPE).get()).offline(ctx);
} catch (Exception e) {
e.printStackTrace();
}
} }
@Override @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
try { if (cause instanceof HttpException) {
singleChatFactory.getService(ctx.channel().attr(ChannelAttributeKey.ROLE_TYPE).get()).offline(ctx); return;
} catch (Exception e) {
e.printStackTrace();
} }
singleChatFactory.getService(ctx.channel().attr(ChannelAttributeKey.ROLE_TYPE).get()).offline(ctx);
} }
} }
...@@ -12,6 +12,7 @@ import io.netty.channel.ChannelHandler; ...@@ -12,6 +12,7 @@ import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.QueryStringDecoder;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -36,27 +37,23 @@ import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; ...@@ -36,27 +37,23 @@ import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
@ChannelHandler.Sharable @ChannelHandler.Sharable
public class WebSocketHandshakerHandler extends BaseHandler<FullHttpRequest> { public class WebSocketHandshakerHandler extends BaseHandler<FullHttpRequest> {
@Resource(name = "myRedisTemplate")
private RedisTemplate redisTemplate;
@Autowired @Autowired
private ChannelGroupHandler channelGroup; private ChannelGroupHandler channelGroup;
@Autowired @Autowired
private SingleChatFactory singleChatFactory; private SingleChatFactory singleChatFactory;
@Resource(name = "myRedisTemplate") public static final String LOGIN_TOKEN = "login:token:%s";
private RedisTemplate redisTemplate;
public static final String AUTHORIZATION = "Authorization"; public static final String AUTHORIZATION = "Authorization";
/**
* 登录用户token信息key
* login:token:tokenMd5
*/
public static final String LOGIN_TOKEN = "login:token:%s";
@Override @Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest fullHttpRequest) throws Exception { protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest fullHttpRequest) throws Exception {
final String token = fullHttpRequest.headers().get(AUTHORIZATION); final String token = new QueryStringDecoder(fullHttpRequest.uri()).parameters().get(AUTHORIZATION).get(0);
Optional.ofNullable(token).orElseThrow(() -> new HttpException(ctx, fullHttpRequest, new DefaultFullHttpResponse(HTTP_1_1, UNAUTHORIZED))); Optional.ofNullable(token).orElseThrow(() -> new HttpException(ctx, fullHttpRequest, new DefaultFullHttpResponse(HTTP_1_1, UNAUTHORIZED)));
final JwtTokenRedisVo tokenInfoForRedis = this.getTokenInfoForRedis(token); final JwtTokenRedisVo tokenInfoForRedis = this.getTokenInfoForRedis(token);
Optional.ofNullable(tokenInfoForRedis).orElseThrow(() -> new HttpException(ctx, fullHttpRequest, new DefaultFullHttpResponse(HTTP_1_1, UNAUTHORIZED))); Optional.ofNullable(tokenInfoForRedis).orElseThrow(() -> new HttpException(ctx, fullHttpRequest, new DefaultFullHttpResponse(HTTP_1_1, UNAUTHORIZED)));
......
...@@ -22,7 +22,7 @@ public interface ChatRecordService { ...@@ -22,7 +22,7 @@ public interface ChatRecordService {
/** /**
* 聊天记录表数量 * 聊天记录表数量
*/ */
int NUMBER_OF_TABLE = 32; int NUMBER_OF_TABLE = 16;
@Validated({ChatRecordSaveGroup.class}) @Validated({ChatRecordSaveGroup.class})
int insert(ChatRecord chatRecord); int insert(ChatRecord chatRecord);
......
...@@ -65,7 +65,7 @@ public class ChatRecordServiceImpl extends ServiceImpl<ChatRecordMapper, ChatRec ...@@ -65,7 +65,7 @@ public class ChatRecordServiceImpl extends ServiceImpl<ChatRecordMapper, ChatRec
final PageInfo<ChatRecord> pageInfo = new PageInfo<>(chatRecords); final PageInfo<ChatRecord> pageInfo = new PageInfo<>(chatRecords);
pull.setChatRecords(chatRecords); pull.setChatRecords(chatRecords);
pull.setPages(pageInfo.getPages()); pull.setPages(pageInfo.getPages());
pull.setTotal(pageInfo.getTotal()); pull.setTotal((int) pageInfo.getTotal());
return new MsgBody<PullChatRecord>().setCode(ResultStatus.SUCCESS.getCode()).setData(pull); return new MsgBody<PullChatRecord>().setCode(ResultStatus.SUCCESS.getCode()).setData(pull);
} }
......
...@@ -70,7 +70,7 @@ public class UserSingleChatServiceImpl implements ChatService { ...@@ -70,7 +70,7 @@ public class UserSingleChatServiceImpl implements ChatService {
userSocketInfo.setSessionList(this.getSessionList(userId)); userSocketInfo.setSessionList(this.getSessionList(userId));
channelGroup.USER_GROUP.put(userId, userSocketInfo); channelGroup.USER_GROUP.put(userId, userSocketInfo);
this.restoreBindingRelationship(userId); //恢复历史绑定关系 this.restoreBindingRelationship(userId); //恢复历史绑定关系
this.broadcastUserOnline(userId); //通知客服 用户上线 this.broadcastUserOnline(userId); //通知客服 用户上线
log.info("用户: " + userId + " 上线"); log.info("用户: " + userId + " 上线");
} }
...@@ -196,9 +196,9 @@ public class UserSingleChatServiceImpl implements ChatService { ...@@ -196,9 +196,9 @@ public class UserSingleChatServiceImpl implements ChatService {
*/ */
private void restoreBindingRelationship(Long userId) { private void restoreBindingRelationship(Long userId) {
if (redisTemplate.opsForHash().hasKey(NettyConstant.IM_USERS, userId)) { if (redisTemplate.opsForHash().hasKey(NettyConstant.IM_USERS, userId)) {
final HashMap staffs = (HashMap) redisTemplate.opsForHash().get(NettyConstant.IM_USERS, userId); final Map staffs = (HashMap<Long, Long>) redisTemplate.opsForHash().get(NettyConstant.IM_USERS, userId);
staffs.values().forEach(staffId -> { staffs.forEach((mid, staffId) -> {
final StaffSocketInfo staffSocketInfo = channelGroup.getMerchantStaff(Long.valueOf(staffId.toString())); final StaffSocketInfo staffSocketInfo = channelGroup.getMerchantStaff(Long.valueOf(mid.toString()), Long.valueOf(staffId.toString()));
if (staffSocketInfo != null) { if (staffSocketInfo != null) {
staffSocketInfo.getUserIds().add(userId); staffSocketInfo.getUserIds().add(userId);
} }
...@@ -214,10 +214,11 @@ public class UserSingleChatServiceImpl implements ChatService { ...@@ -214,10 +214,11 @@ public class UserSingleChatServiceImpl implements ChatService {
* @param userId * @param userId
*/ */
private void broadcastUserOnline(Long userId) { private void broadcastUserOnline(Long userId) {
channelGroup.USER_GROUP.get(userId).getStaffIds().forEach((merchantId, staffId) -> { final Map staffIds = channelGroup.USER_GROUP.get(userId).getStaffIds();
channelGroup.STAFF_GROUP.get(merchantId).values().forEach(staffSocketInfo -> { staffIds.forEach((merchantId, staffId) -> {
channelGroup.STAFF_GROUP.get(Long.valueOf(merchantId.toString())).values().forEach(staffSocketInfo -> {
staffSocketInfo.getUserIds().remove(userId); staffSocketInfo.getUserIds().remove(userId);
staffSocketInfo.writeAndFlush(new MsgBody<>().setCode(MsgBody.USERS_ONLINE).setData(new IdModel().setStaffId(staffId).setUserId(userId))); staffSocketInfo.writeAndFlush(new MsgBody<>().setCode(MsgBody.USERS_ONLINE).setData(new IdModel().setStaffId(Long.valueOf(staffId.toString())).setUserId(userId)));
}); });
}); });
} }
......
...@@ -16,10 +16,11 @@ spring: ...@@ -16,10 +16,11 @@ spring:
max-wait: 60000 max-wait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位毫秒 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位毫秒
time-between-eviction-runs-millis: 60000 time-between-eviction-runs-millis: 60000
url: jdbc:mysql://127.0.0.1/customer_service?useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai url: jdbc:mysql://127.0.0.1/customer_service?useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8
username: root username: root
password: 101020 password: 101020
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver
connectionInitSqls: set names utf8mb4
jackson: jackson:
default-property-inclusion: non_null default-property-inclusion: non_null
rabbitmq: rabbitmq:
......
...@@ -16,10 +16,12 @@ spring: ...@@ -16,10 +16,12 @@ spring:
max-wait: 60000 max-wait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位毫秒 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位毫秒
time-between-eviction-runs-millis: 60000 time-between-eviction-runs-millis: 60000
url: jdbc:mysql://172.31.33.14:3306/pathfinder_im?useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai url: jdbc:mysql://172.31.33.14:3306/pathfinder_im?useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8
username: root username: root
password: Yum123456 password: Yum123456
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver
connectionInitSqls: set names utf8mb4
jackson: jackson:
default-property-inclusion: non_null default-property-inclusion: non_null
rabbitmq: rabbitmq:
......
...@@ -16,10 +16,12 @@ spring: ...@@ -16,10 +16,12 @@ spring:
max-wait: 60000 max-wait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位毫秒 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位毫秒
time-between-eviction-runs-millis: 60000 time-between-eviction-runs-millis: 60000
url: jdbc:mysql://192.168.1.237:3306/pathfinder_im?useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai url: jdbc:mysql://192.168.1.237:3306/pathfinder_im?useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8
username: root username: root
password: 123456 password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver
connectionInitSqls: set names utf8mb4
jackson: jackson:
default-property-inclusion: non_null default-property-inclusion: non_null
rabbitmq: rabbitmq:
......
...@@ -72,6 +72,7 @@ ...@@ -72,6 +72,7 @@
<module>api-system</module> <module>api-system</module>
<module>api-app</module> <module>api-app</module>
<module>api-merchant</module> <module>api-merchant</module>
<module>customer-service</module>
</modules> </modules>
<dependencyManagement> <dependencyManagement>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment