update 接口测试完成,新增ip限制链接 + 最大连接数配置.文件上传模块,路径修改

This commit is contained in:
yyb 2025-04-16 16:15:53 +08:00
parent 476cb6711e
commit 2d8088c6cb
24 changed files with 313 additions and 106 deletions

View File

@ -0,0 +1,16 @@
package com.m2pool.chat.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@ConfigurationProperties(prefix = "websocket.transport")
public class CustomWebSocketConfig {
private int messageSizeLimit;
private int sendTimeLimit;
private int sendBufferSizeLimit;
private int timeToFirstMessage;
private int maxConnections;
}

View File

@ -12,7 +12,9 @@ import org.springframework.scheduling.concurrent.DefaultManagedTaskScheduler;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry; import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration;
import javax.annotation.Resource;
import java.util.List; import java.util.List;
/** /**
@ -24,6 +26,11 @@ import java.util.List;
@EnableWebSocketMessageBroker @EnableWebSocketMessageBroker
public class WebSocketBrokerConfig implements WebSocketMessageBrokerConfigurer { public class WebSocketBrokerConfig implements WebSocketMessageBrokerConfigurer {
@Resource
private CustomWebSocketConfig customWebSocketConfig;
/** /**
* 注册 Stomp的端点 可以注册多个端点 * 注册 Stomp的端点 可以注册多个端点
* addEndpoint添加STOMP协议的端点客户端访问地址 * addEndpoint添加STOMP协议的端点客户端访问地址
@ -62,6 +69,20 @@ public class WebSocketBrokerConfig implements WebSocketMessageBrokerConfigurer {
} }
/**
* 最大消息字节数,发送超时时间,发送缓冲区大小,首次连接超时时间
* @param registration
*/
@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
registration
.setMessageSizeLimit(customWebSocketConfig.getMessageSizeLimit())
.setSendTimeLimit(customWebSocketConfig.getSendTimeLimit())
.setSendBufferSizeLimit(customWebSocketConfig.getSendBufferSizeLimit())
// 首次连接超时时间.正常情况下前端订阅 心跳包的影响 不会超时断连
.setTimeToFirstMessage(customWebSocketConfig.getTimeToFirstMessage());
}
/** /**
@ -75,7 +96,7 @@ public class WebSocketBrokerConfig implements WebSocketMessageBrokerConfigurer {
.maxPoolSize(20) .maxPoolSize(20)
.keepAliveSeconds(60); .keepAliveSeconds(60);
// 拦截器配置 // 拦截器配置
registration.interceptors(new WebsocketChannelInterceptor()); registration.interceptors(new WebsocketChannelInterceptor(customWebSocketConfig));
} }
/** /**

View File

@ -0,0 +1,23 @@
package com.m2pool.chat.constant;
/**
* @ClassName CustomHeader
* @Description 自定义请求头
* @Author yyb
* @Date 2025/4/16 13:34
*/
public class CustomHeader {
/**
* 用户类型
*/
public static final String TYPE = "type";
/**
* 用户邮箱
*/
public static final String EMAIL = "email";
/**
* 客服端ip地址请求头
*/
public static final String IPADDR = "ipAddr";
}

View File

@ -25,10 +25,5 @@ public class Destination {
/** /**
* stomp 默认发送消息前缀 * stomp 默认发送消息前缀
*/ */
public static final String SEND_PREFIX = "/message"; public static final String SEND_PREFIX = "/point";
/**
* 游客标识
*/
public static final String VISITOR_PREFIX = "visitor";
} }

View File

@ -1,10 +1,11 @@
package com.m2pool.chat.dto; package com.m2pool.chat.dto;
import cn.hutool.core.date.DateTime;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import java.time.LocalDateTime;
/** /**
* @ClassName ChatMessageDto * @ClassName ChatMessageDto
* @Description 聊天消息返回对象 * @Description 聊天消息返回对象
@ -29,5 +30,5 @@ public class ChatMessageDto {
private String content; private String content;
@ApiModelProperty(value = "发送时间", example = "") @ApiModelProperty(value = "发送时间", example = "")
private DateTime createTime; private LocalDateTime createTime;
} }

View File

@ -1,8 +1,9 @@
package com.m2pool.chat.dto; package com.m2pool.chat.dto;
import cn.hutool.core.date.DateTime;
import lombok.Data; import lombok.Data;
import java.time.LocalDateTime;
/** /**
* @ClassName ChatRoomDto * @ClassName ChatRoomDto
* @Description 客服 聊天室列表返回对象 * @Description 客服 聊天室列表返回对象
@ -34,10 +35,10 @@ public class ChatRoomDto {
/** /**
* 用户回复时间 * 用户回复时间
*/ */
private DateTime lastUserSendTime; private LocalDateTime lastUserSendTime;
/** /**
* 客服回复时间 * 客服回复时间
*/ */
private DateTime lastCustomerSendTime; private LocalDateTime lastCustomerSendTime;
} }

View File

@ -1,9 +1,10 @@
package com.m2pool.chat.entity; package com.m2pool.chat.entity;
import cn.hutool.core.date.DateTime;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import java.time.LocalDateTime;
@Builder @Builder
@Data @Data
public class ChatMessage { public class ChatMessage {
@ -13,6 +14,6 @@ public class ChatMessage {
private String sendEmail; private String sendEmail;
private String content; private String content;
private Long roomId; private Long roomId;
private DateTime createTime; private LocalDateTime createTime;
private DateTime updateTime; private LocalDateTime updateTime;
} }

View File

@ -1,8 +1,9 @@
package com.m2pool.chat.entity; package com.m2pool.chat.entity;
import cn.hutool.core.date.DateTime;
import lombok.Data; import lombok.Data;
import java.time.LocalDateTime;
@Data @Data
public class ChatMessageHistory { public class ChatMessageHistory {
private Long id; private Long id;
@ -10,6 +11,6 @@ public class ChatMessageHistory {
private String sendEmail; private String sendEmail;
private String content; private String content;
private Long roomId; private Long roomId;
private DateTime createTime; private LocalDateTime createTime;
private DateTime updateTime; private LocalDateTime updateTime;
} }

View File

@ -1,19 +1,20 @@
package com.m2pool.chat.entity; package com.m2pool.chat.entity;
import cn.hutool.core.date.DateTime;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import java.time.LocalDateTime;
@Builder @Builder
@Data @Data
public class ChatRoom { public class ChatRoom {
private Long id; private Long id;
private String userOneEmail; private String userOneEmail;
private String userTwoEmail; private String userTwoEmail;
private DateTime lastUserSendTime; private LocalDateTime lastUserSendTime;
private DateTime lastCustomerSendTime; private LocalDateTime lastCustomerSendTime;
private Boolean flag; private Boolean flag;
private DateTime createTime; private LocalDateTime createTime;
private DateTime updateTime; private LocalDateTime updateTime;
private Boolean del; private Boolean del;
} }

View File

@ -1,15 +1,21 @@
package com.m2pool.chat.entity; package com.m2pool.chat.entity;
import lombok.Data;
import java.security.Principal; import java.security.Principal;
/** /**
* stomp用户身份信息 * stomp用户身份信息
*/ */
@Data
public class StompPrincipal implements Principal { public class StompPrincipal implements Principal {
String name; String name;
public StompPrincipal(String name) { Integer type;
public StompPrincipal(String name,Integer type) {
this.name = name; this.name = name;
this.type = type;
} }
@Override @Override

View File

@ -1,12 +1,15 @@
package com.m2pool.chat.interceptor; package com.m2pool.chat.interceptor;
import com.m2pool.chat.config.CustomWebSocketConfig;
import com.m2pool.chat.entity.StompPrincipal; import com.m2pool.chat.entity.StompPrincipal;
import lombok.Data;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.messaging.Message; import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageDeliveryException;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor; import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.messaging.simp.stomp.StompCommand; import org.springframework.messaging.simp.stomp.StompCommand;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor; import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
@ -15,6 +18,12 @@ import org.springframework.messaging.support.MessageHeaderAccessor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import static com.m2pool.chat.constant.CustomHeader.*;
import static com.m2pool.chat.constant.UserType.CUSTOMER;
/** /**
* @ClassName WebsocketChannelInterceptor * @ClassName WebsocketChannelInterceptor
@ -22,9 +31,30 @@ import java.util.Map;
* @Author yyb * @Author yyb
* @Date 2025/4/10 15:44 * @Date 2025/4/10 15:44
*/ */
@Data
public class WebsocketChannelInterceptor implements ChannelInterceptor { public class WebsocketChannelInterceptor implements ChannelInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(WebsocketChannelInterceptor.class); private static final Logger LOGGER = LoggerFactory.getLogger(WebsocketChannelInterceptor.class);
/**
* 当前加入链接的ip
*/
private static final ConcurrentHashMap<String, Boolean> ipConnectionCountMap = new ConcurrentHashMap<>();
/**
* 当前链接数
*/
private static final AtomicInteger connectionCount = new AtomicInteger(0);
/**
* websocket 一些配置
*/
private CustomWebSocketConfig customWebSocketConfig;
public WebsocketChannelInterceptor(CustomWebSocketConfig customWebSocketConfig) {
this.customWebSocketConfig = customWebSocketConfig;
}
/** /**
* websocket channel 通道拦截器 * websocket channel 通道拦截器
* @param message * @param message
@ -35,18 +65,22 @@ public class WebsocketChannelInterceptor implements ChannelInterceptor {
public Message<?> preSend(Message<?> message, MessageChannel channel) { public Message<?> preSend(Message<?> message, MessageChannel channel) {
//获取链接建立时的请求头信息 //获取链接建立时的请求头信息
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message); StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
if (accessor.getCommand() == StompCommand.CONNECT) { if (accessor.getCommand() == StompCommand.CONNECT ) {
LOGGER.info("------------收到websocket的连接消息");
//获取channel 中的请求头信息
StompHeaderAccessor mha = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class); StompHeaderAccessor mha = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
Object raw = message.getHeaders().get(SimpMessageHeaderAccessor.NATIVE_HEADERS); Object raw = message.getHeaders().get(SimpMessageHeaderAccessor.NATIVE_HEADERS);
System.out.println("raw:"+raw); int type = Integer.parseInt(getConnectCustomHeaders(raw, TYPE));
if (raw instanceof Map) { String email = getConnectCustomHeaders(raw, EMAIL);
Object userInfo = ((Map) raw).get("email");
if(userInfo instanceof ArrayList){ //最大链接数限制
mha.setUser(new StompPrincipal((String) ((ArrayList) userInfo).get(0))); maxConnectionsLimit();
} //根据客服端ip + 用户类型限制连接数
ipLimit(accessor,type);
if(mha == null){
throw new MessageDeliveryException("get MessageHeaderAccessor failed,can not set Principal,connect failed");
} }
//链接请求头中用户信息存入stomp中
mha.setUser(new StompPrincipal(email,type));
} }
if (accessor.getCommand() == StompCommand.SEND) { if (accessor.getCommand() == StompCommand.SEND) {
LOGGER.info("------------websocket send message"); LOGGER.info("------------websocket send message");
@ -61,11 +95,74 @@ public class WebsocketChannelInterceptor implements ChannelInterceptor {
} }
if (accessor.getCommand() == StompCommand.DISCONNECT){ if (accessor.getCommand() == StompCommand.DISCONNECT){
disconnectHandler(accessor);
LOGGER.info("------------websocket disconnect"); LOGGER.info("------------websocket disconnect");
} }
return message; return message;
} }
/**
* 最大连接数限制
*/
private void maxConnectionsLimit(){
if(connectionCount.incrementAndGet() >= customWebSocketConfig.getMaxConnections()){
LOGGER.info("reach max connections,refuse connect");
throw new MessageDeliveryException("reach max connections,refuse connect");
}
}
/**
* ip 链接个数限制
* @param accessor
*/
private void ipLimit(StompHeaderAccessor accessor,int type){
Map<String, Object> sessionAttributes = accessor.getSessionAttributes();
if (sessionAttributes != null) {
String ipAddr = (String) sessionAttributes.get(IPADDR);
if(type != CUSTOMER && ipConnectionCountMap.get(ipAddr) != null){
throw new MessageDeliveryException("this ip maximum number of connections is reached");
}
ipConnectionCountMap.put(ipAddr,true);
}else{
throw new MessageDeliveryException("not find email and type headers");
}
}
/**
* 获取stomp自定义请求头
* @param raw
* @param headerKey
* @return
*/
private String getConnectCustomHeaders(Object raw,String headerKey){
String headerValue = "";
if (raw instanceof Map) {
Object value = ((Map<?, ?>) raw).get(headerKey);
if(value instanceof ArrayList){
headerValue = ((ArrayList<?>) value).get(0).toString();
}
}
return headerValue;
}
/**
* 断开链接处理
*/
private void disconnectHandler(StompHeaderAccessor accessor){
//连接数减一
connectionCount.decrementAndGet();
//断开链接的ip
Map<String, Object> sessionAttributes = accessor.getSessionAttributes();
if (sessionAttributes != null) {
String ipAddr = (String) sessionAttributes.get(IPADDR);
if(ipConnectionCountMap.get(ipAddr) != null){
ipConnectionCountMap.remove(ipAddr);
}
}else{
throw new MessageDeliveryException("not find email and type headers");
}
}
@Override @Override
public void postSend(Message<?> message, MessageChannel channel, boolean sent) { public void postSend(Message<?> message, MessageChannel channel, boolean sent) {

View File

@ -1,15 +1,18 @@
package com.m2pool.chat.interceptor; package com.m2pool.chat.interceptor;
import com.m2pool.common.core.utils.ip.IpUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor; import org.springframework.web.socket.server.HandshakeInterceptor;
import javax.servlet.http.HttpServletRequest;
import java.util.Map; import java.util.Map;
import static com.m2pool.chat.constant.Destination.VISITOR_PREFIX; import static com.m2pool.chat.constant.CustomHeader.IPADDR;
/** /**
@ -24,14 +27,18 @@ public class WebsocketHandshakeInterceptor implements HandshakeInterceptor {
@Override @Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
LOGGER.info("------------------WebsocketHandshakeInterceptor:beforeHandshake"); LOGGER.info("------------------WebsocketHandshakeInterceptor:beforeHandshake");
// 为游客生成一个唯一标识 if (request instanceof ServletServerHttpRequest) {
// String s = generateVisitorId(request); ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
// attributes.put(VISITOR_PREFIX, s); HttpServletRequest httpRequest = servletRequest.getServletRequest();
// response.getHeaders().add(VISITOR_PREFIX, s); // 获取 客服端 IP 地址 并放入attributes
String ipAddr = IpUtils.getIpAddr(httpRequest);
attributes.put(IPADDR, ipAddr);
} else {
LOGGER.warn("Request is not an instance of ServletServerHttpRequest. Unable to extract HttpServletRequest.");
}
return true; return true;
} }
@ -40,14 +47,4 @@ public class WebsocketHandshakeInterceptor implements HandshakeInterceptor {
LOGGER.info("------------------WebsocketHandshakeInterceptor:afterHandshake"); LOGGER.info("------------------WebsocketHandshakeInterceptor:afterHandshake");
} }
/**
* 生成一个唯一标识
* @param request
* @return
*/
private String generateVisitorId(ServerHttpRequest request) {
String first = request.getHeaders().getFirst("sec-websocket-key");
String prefix = VISITOR_PREFIX;
return prefix + first;
}
} }

View File

@ -56,14 +56,17 @@ public class ChatMessageServiceImpl implements ChatMessageService {
ChatRoom chatRoom = chatRoomMapper.selectById(roomId); ChatRoom chatRoom = chatRoomMapper.selectById(roomId);
String username = SecurityUtils.getUsername(); String username = SecurityUtils.getUsername();
String updateUserEmail = ""; if (chatRoom != null){
if(username.equals(chatRoom.getUserOneEmail())){ String updateUserEmail = "";
updateUserEmail = chatRoom.getUserTwoEmail(); if( username.equals(chatRoom.getUserOneEmail())){
}else if(username.equals(chatRoom.getUserTwoEmail())){ updateUserEmail = chatRoom.getUserTwoEmail();
updateUserEmail = chatRoom.getUserOneEmail(); }else if (username.equals(chatRoom.getUserTwoEmail())) {
updateUserEmail = chatRoom.getUserOneEmail();
}
int update = chatMessageMapper.update(ChatMessage.builder().read(1).build(),
new LambdaUpdateWrapper<ChatMessage>().eq(ChatMessage::getSendEmail, updateUserEmail).eq(ChatMessage::getRoomId, roomId));
return update > 0 ? AjaxResult.success("已读") : AjaxResult.error("消息读取失败");
} }
int update = chatMessageMapper.update(ChatMessage.builder().read(1).build(), return AjaxResult.error("聊天室不存在");
new LambdaUpdateWrapper<ChatMessage>().eq(ChatMessage::getSendEmail, updateUserEmail).eq(ChatMessage::getRoomId, roomId));
return update > 0 ? AjaxResult.success("已读") : AjaxResult.error("消息读取失败");
} }
} }

View File

@ -38,11 +38,13 @@ public class ChatRoomServiceImpl extends ServiceImpl<ChatRoomMapper, ChatRoom> i
List<ChatRoomDto> roomList = chatRoomMapper.findRoomList(SecurityUtils.getUsername()); List<ChatRoomDto> roomList = chatRoomMapper.findRoomList(SecurityUtils.getUsername());
List<String> userEmails = roomList.stream().map(ChatRoomDto::getUserEmail).collect(Collectors.toList()); List<String> userEmails = roomList.stream().map(ChatRoomDto::getUserEmail).collect(Collectors.toList());
//2.查询未读数量 //2.查询未读数量
Map<String, Integer> unReadNums = chatMessageMapper.findUnReadNums(userEmails); if (!userEmails.isEmpty()){
Map<String, Integer> unReadNums = chatMessageMapper.findUnReadNums(userEmails);
for (ChatRoomDto room : roomList) {
Integer i = unReadNums.get(room.getUserEmail());
room.setUnReadNumber(i == null ? 0 : i);
}
for (ChatRoomDto room : roomList) {
Integer i = unReadNums.get(room.getUserEmail());
room.setUnReadNumber(i == null ? 0 : i);
} }
return getDataTable(roomList); return getDataTable(roomList);
} }
@ -85,6 +87,6 @@ public class ChatRoomServiceImpl extends ServiceImpl<ChatRoomMapper, ChatRoom> i
if(i > 0){ if(i > 0){
return AjaxResult.success("修改成功"); return AjaxResult.success("修改成功");
} }
return AjaxResult.error("修改失败"); return AjaxResult.error("修改失败,不存在该聊天室");
} }
} }

View File

@ -1,6 +1,5 @@
package com.m2pool.chat.service.impl; package com.m2pool.chat.service.impl;
import cn.hutool.core.date.DateTime;
import com.m2pool.chat.constant.Destination; import com.m2pool.chat.constant.Destination;
import com.m2pool.chat.dto.WebsocketMessageDto; import com.m2pool.chat.dto.WebsocketMessageDto;
import com.m2pool.chat.entity.ChatMessage; import com.m2pool.chat.entity.ChatMessage;
@ -17,6 +16,7 @@ import org.springframework.messaging.simp.user.SimpUserRegistry;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.time.LocalDateTime;
import static com.m2pool.chat.constant.UserType.CUSTOMER; import static com.m2pool.chat.constant.UserType.CUSTOMER;
import static com.m2pool.chat.constant.UserType.TOURIST; import static com.m2pool.chat.constant.UserType.TOURIST;
@ -88,9 +88,9 @@ public class StompServiceImpl implements StompService {
private void updateRoom(UserMessageVo userMessageVo){ private void updateRoom(UserMessageVo userMessageVo){
ChatRoom room = ChatRoom.builder().id(userMessageVo.getRoomId()).build(); ChatRoom room = ChatRoom.builder().id(userMessageVo.getRoomId()).build();
if (CUSTOMER.equals(userMessageVo.getSendUserType())) { if (CUSTOMER.equals(userMessageVo.getSendUserType())) {
room.setLastCustomerSendTime(DateTime.now()); room.setLastCustomerSendTime(LocalDateTime.now());
} else { } else {
room.setLastUserSendTime(DateTime.now()); room.setLastUserSendTime(LocalDateTime.now());
} }
chatRoomMapper.insert(room); chatRoomMapper.insert(room);
} }

View File

@ -70,7 +70,10 @@ spring:
max-file-size: 2MB max-file-size: 2MB
max-request-size: 8MB max-request-size: 8MB
myenv: websocket:
domain: https://www.m2pool.com transport:
path: /var/www/html/web message-size-limit: 1500 # 消息大小限制 1.5k 约500汉字
img: /img send-time-limit: 5000 # 发送超时时间 5秒
send-buffer-size-limit: 65536 # 发送缓冲区大小 64K
time-to-first-message: 5000 # 首次消息超时时间 5秒
max-connections: 100 # 最大连接数

View File

@ -36,8 +36,10 @@ spring:
max-file-size: 2MB max-file-size: 2MB
max-request-size: 8MB max-request-size: 8MB
myenv: websocket:
domain: https://test.m2pool.com transport:
path: /var/www/html/web_test message-size-limit: 1500 # 消息大小限制 1.5k 约500汉字
img: /imgpp send-time-limit: 5000 # 发送超时时间 5秒
send-buffer-size-limit: 65536 # 发送缓冲区大小 64K
time-to-first-message: 5000 # 首次消息超时时间 5秒
max-connections: 100 # 最大连接数

View File

@ -15,15 +15,15 @@
LIMIT #{pageNum} LIMIT #{pageNum}
</select> </select>
<select id="findUnReadNums" resultType="java.util.Map"> <select id="findUnReadNums" resultType="java.util.Map">
SELECT user_email as userEmail, SELECT send_email as userEmail,
count(*) as unReadNums count(*) as unReadNums
FROM chat_message FROM chat_message
WHERE send_email IN WHERE send_email IN
<foreach collection="userEmails" item="userEmail" open="(" separator="," close=")"> <foreach collection="userEmails" item="userEmail" open="(" separator="," close=")">
#{userEmail} #{userEmail}
</foreach> </foreach>
AND read_flag = false AND `read` = false
GROUP BY user_email GROUP BY send_email
</select> </select>
</mapper> </mapper>

View File

@ -1,12 +1,13 @@
package com.m2pool.file.config; package com.m2pool.file.config;
import java.io.File;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.io.File;
/** /**
* 通用映射配置 * 通用映射配置
* *
@ -18,7 +19,7 @@ public class ResourcesConfig implements WebMvcConfigurer
/** /**
* 上传文件存储在本地的根路径 * 上传文件存储在本地的根路径
*/ */
@Value("${file.path}") @Value("${file.filepath}")
private String localFilePath; private String localFilePath;
/** /**

View File

@ -32,7 +32,7 @@ public class SysFileController
/** /**
* 上传文件存储在本地的根路径 * 上传文件存储在本地的根路径
*/ */
@Value("${file.path}") @Value("${file.filepath}")
private String localFilePath; private String localFilePath;
/** /**

View File

@ -20,7 +20,7 @@ public class LocalSysFileServiceImpl implements ISysFileService
/** /**
* 资源映射路径 前缀 * 资源映射路径 前缀
*/ */
@Value("${file.prefix}") @Value("${file.prefix")
public String localFilePrefix; public String localFilePrefix;
/** /**
@ -32,7 +32,7 @@ public class LocalSysFileServiceImpl implements ISysFileService
/** /**
* 上传文件存储在本地的根路径 * 上传文件存储在本地的根路径
*/ */
@Value("${file.path}") @Value("${file.filepath}")
private String localFilePath; private String localFilePath;
/** /**

View File

@ -0,0 +1,30 @@
# Tomcat
server:
port: 9300
# Spring
spring:
application:
# 应用名称
name: m2pool-file
profiles:
# 环境配置
active: test
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8808
config:
# 配置中心地址
server-addr: 127.0.0.1:8808
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
file:
domain: https://www.m2pool.com
path: /var/www/html/web
img: /img
filepath: /home/ubuntu/prod

View File

@ -0,0 +1,28 @@
# Tomcat
server:
port: 9300
# Spring
spring:
application:
# 应用名称
name: m2pool-file
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
file:
domain: https://www.m2pool.com
path: /var/www/html/web-test
# img: /img
filepath: /home/ubuntu/web

View File

@ -1,25 +1,3 @@
# Tomcat
server:
port: 9300
# Spring
spring: spring:
application:
# 应用名称
name: m2pool-file
profiles: profiles:
# 环境配置 active: test
active: dev
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8808
config:
# 配置中心地址
server-addr: 127.0.0.1:8808
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}