feat1
This commit is contained in:
parent
af5fe0c8c0
commit
2d9d863efa
4
pom.xml
4
pom.xml
@ -132,6 +132,10 @@
|
||||
<artifactId>easyexcel</artifactId>
|
||||
<version>3.2.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
@ -3,9 +3,11 @@ package top.xinsin;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
@SpringBootApplication
|
||||
@MapperScan("top.xinsin.mapper")
|
||||
@EnableScheduling
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Main.class,args);
|
||||
|
22
src/main/java/top/xinsin/config/WebsocketConfiguration.java
Normal file
22
src/main/java/top/xinsin/config/WebsocketConfiguration.java
Normal file
@ -0,0 +1,22 @@
|
||||
package top.xinsin.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.socket.config.annotation.EnableWebSocket;
|
||||
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
|
||||
import top.xinsin.controller.WebSocketController;
|
||||
import top.xinsin.service.WebSocketService;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSocket
|
||||
public class WebsocketConfiguration {
|
||||
@Bean
|
||||
public ServerEndpointExporter serverEndpointExporter() {
|
||||
return new ServerEndpointExporter();
|
||||
}
|
||||
@Autowired
|
||||
public void socketUserService(WebSocketService webSocketService){
|
||||
WebSocketController.webSocketService= webSocketService;
|
||||
}
|
||||
}
|
85
src/main/java/top/xinsin/controller/WebSocketController.java
Normal file
85
src/main/java/top/xinsin/controller/WebSocketController.java
Normal file
@ -0,0 +1,85 @@
|
||||
package top.xinsin.controller;
|
||||
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import jakarta.websocket.*;
|
||||
import jakarta.websocket.server.PathParam;
|
||||
import jakarta.websocket.server.ServerEndpoint;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.xinsin.service.WebSocketService;
|
||||
import top.xinsin.util.R;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.http.WebSocket;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Component
|
||||
@ServerEndpoint(value = "/api/auth/websocket/{userId}")
|
||||
@Slf4j
|
||||
public class WebSocketController {
|
||||
private static ConcurrentHashMap<String, WebSocketController> webSocketMap = new ConcurrentHashMap<>();
|
||||
|
||||
private Session session;
|
||||
private String userId;
|
||||
public static WebSocketService webSocketService;
|
||||
|
||||
@OnOpen
|
||||
public void onOpen(Session session, @PathParam("userId") String userId) {
|
||||
this.session = session;
|
||||
this.userId = userId;
|
||||
//加入map
|
||||
webSocketMap.put(userId, this);
|
||||
R<String> stringR = webSocketService.addVerify(userId);
|
||||
sendMessageByUserId(userId, stringR);
|
||||
}
|
||||
@OnClose
|
||||
public void onClose() {
|
||||
//从map中删除
|
||||
webSocketMap.remove(userId);
|
||||
}
|
||||
@OnMessage
|
||||
public void onMessage(String message, Session session) {
|
||||
sendMessageByUserId(userId,webSocketService.parseMessage(userId,message,webSocketMap));
|
||||
}
|
||||
@OnError
|
||||
public void onError(Session session, Throwable error) {
|
||||
log.error("用户错误:" + this.userId + ",原因:" + error.getMessage());
|
||||
error.printStackTrace();
|
||||
}
|
||||
/**
|
||||
* 向客户端发送消息
|
||||
*/
|
||||
@SneakyThrows
|
||||
public void sendMessage(String message) {
|
||||
this.session.getBasicRemote().sendText(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过userId向客户端发送消息
|
||||
*/
|
||||
@SneakyThrows
|
||||
public void sendMessageByUserId(String userId, R<?> message) {
|
||||
if(webSocketMap.containsKey(userId)){
|
||||
webSocketMap.get(userId).sendMessage(JSON.toJSONString(message));
|
||||
}else{
|
||||
log.error("用户{}不在线",userId);
|
||||
}
|
||||
}
|
||||
@Scheduled(fixedRate = 10000)
|
||||
public void verifyTime(){
|
||||
List<String> expireTimes = webSocketService.getExpireTimes();
|
||||
expireTimes.forEach(e -> {
|
||||
if(webSocketMap.containsKey(e)){
|
||||
webSocketMap.get(e).sendMessage(JSON.toJSONString(R.success(new JSONObject().fluentPut("info","当前登录用户已过期"))));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -187,7 +187,7 @@ public class AccountService implements UserDetailsService {
|
||||
Verify verify = new Verify(accountAndStoreAdmin.getCreateId(), authAccount.getId(), accountAndStoreAdmin.getCountdown());
|
||||
int insert1 = verifyMapper.insert(verify);
|
||||
if (insert1 == 1){
|
||||
redisTemplate.opsForValue().set(String.valueOf(authAccount.getId()),authAccount.getUsername(),verify.getCountdown(), TimeUnit.SECONDS);
|
||||
// redisTemplate.opsForValue().set(String.valueOf(authAccount.getId()),authAccount.getUsername(),verify.getCountdown(), TimeUnit.SECONDS);
|
||||
return R.success(new JSONObject().fluentPut("status","添加该商户成功").fluentPut("nextVerificationTime",verify.getCountdown()));
|
||||
}
|
||||
}
|
||||
|
161
src/main/java/top/xinsin/service/WebSocketService.java
Normal file
161
src/main/java/top/xinsin/service/WebSocketService.java
Normal file
@ -0,0 +1,161 @@
|
||||
package top.xinsin.service;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
import org.springframework.stereotype.Service;
|
||||
import top.xinsin.controller.WebSocketController;
|
||||
import top.xinsin.mapper.VerifyMapper;
|
||||
import top.xinsin.pojo.Verify;
|
||||
import top.xinsin.util.HttpCodes;
|
||||
import top.xinsin.util.R;
|
||||
import top.xinsin.util.StringConstant;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.apache.naming.SelectorContext.prefix;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class WebSocketService {
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
@Autowired
|
||||
private VerifyMapper verifyMapper;
|
||||
|
||||
public R<String> addVerify(String userId){
|
||||
RedisSerializer<String> stringSerializer = new StringRedisSerializer();
|
||||
redisTemplate.setValueSerializer(stringSerializer);
|
||||
redisTemplate.setKeySerializer(stringSerializer);
|
||||
if (userId.equals("-114514")){
|
||||
return R.success("检测为管理员登录");
|
||||
}
|
||||
Object o = redisTemplate.opsForValue().get(StringConstant.VERIFY_PRE + userId);
|
||||
Object o1 = redisTemplate.opsForValue().get(StringConstant.VERIFY_PRE + userId + "_no");
|
||||
System.out.println(o == null);
|
||||
System.out.println(o1 == null);
|
||||
if (o == null && o1 == null){
|
||||
Verify verify = verifyMapper.selectOne(new LambdaQueryWrapper<Verify>().eq(Verify::getStoreId, userId));
|
||||
if (verify != null){
|
||||
if(userId.equals(String.valueOf(verify.getStoreId()))) {
|
||||
redisTemplate.opsForValue().set(StringConstant.VERIFY_PRE + userId, String.valueOf(verify.getNum()), verify.getCountdown(), TimeUnit.SECONDS);
|
||||
redisTemplate.opsForValue().set(StringConstant.VERIFY_PRE + userId + "_no", String.valueOf(verify.getNum()));
|
||||
return R.success("已将该用户过期时间存入");
|
||||
}
|
||||
}
|
||||
}else{
|
||||
return R.success("当前用户已存在");
|
||||
}
|
||||
return R.failed(HttpCodes.HTTP_CODES500,"不存在该用户");
|
||||
}
|
||||
public R<JSONObject> parseMessage(String userId, String message, ConcurrentHashMap<String, WebSocketController> webSocketMap){
|
||||
JSONObject parse = JSONObject.parse(message);
|
||||
String type = (String) parse.get("type");
|
||||
switch (type) {
|
||||
case "ping" -> {
|
||||
return ping(userId);
|
||||
}
|
||||
case "addVerifyInfo" -> {
|
||||
return addVerifyInfo(userId, parse);
|
||||
}
|
||||
case "getTime" -> {
|
||||
return getTime(userId);
|
||||
}
|
||||
case "confirmVerifyInfo" -> {
|
||||
return confirmVerifyInfo(parse,webSocketMap);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private R<JSONObject> confirmVerifyInfo(JSONObject parse, ConcurrentHashMap<String, WebSocketController> webSocketMap) {
|
||||
String verifyResult = String.valueOf(parse.get("verifyResult"));
|
||||
String userId = String.valueOf(parse.get("userId"));
|
||||
|
||||
int i = Integer.parseInt(String.valueOf(redisTemplate.opsForValue().get(StringConstant.VERIFY_PRE + userId + "_no")));
|
||||
System.out.println(i);
|
||||
Verify verify = new Verify();
|
||||
verify.setVerifyResult(verifyResult);
|
||||
verify.setNum(i + 1);
|
||||
int update = verifyMapper.update(verify, new LambdaQueryWrapper<Verify>().eq(Verify::getStoreId, userId));
|
||||
if (update != 1){
|
||||
return R.failed(HttpCodes.HTTP_CODES500,new JSONObject().fluentPut("info","信息修改失败"));
|
||||
}
|
||||
if (verifyResult.equals("false")){
|
||||
if (webSocketMap.containsKey(userId)){
|
||||
webSocketMap.get(userId).sendMessage(JSON.toJSONString(new JSONObject().fluentPut("info","管理员未同意你的验证信息,你可以重新进行验证")));
|
||||
}
|
||||
return R.success(new JSONObject().fluentPut("info","你已拒绝该商户的验证信息"));
|
||||
}else{
|
||||
if (webSocketMap.containsKey(userId)){
|
||||
webSocketMap.get(userId).sendMessage(JSON.toJSONString(new JSONObject().fluentPut("info","管理员已同意你的验证信息,请重新登录")));
|
||||
redisTemplate.delete(StringConstant.VERIFY_PRE + userId + "_no");
|
||||
Verify verify1 = new Verify();
|
||||
verify.setVerifyPhone("");
|
||||
verify.setVerifyName("");
|
||||
verifyMapper.update(verify1, new LambdaQueryWrapper<Verify>().eq(Verify::getStoreId, userId));
|
||||
}
|
||||
return R.success(new JSONObject().fluentPut("info","你已同意该商户的验证信息"));
|
||||
}
|
||||
}
|
||||
|
||||
private R<JSONObject> getTime(String userId) {
|
||||
Long expire = redisTemplate.getExpire(StringConstant.VERIFY_PRE + userId);
|
||||
assert expire != null;
|
||||
if (expire.equals(-2L)){
|
||||
Object o = redisTemplate.opsForValue().get(StringConstant.VERIFY_PRE + userId + "_no");
|
||||
if (o != null){
|
||||
return R.success(new JSONObject().fluentPut("info","当前用户登录已过期"));
|
||||
}
|
||||
return R.failed(HttpCodes.HTTP_CODES500,new JSONObject().fluentPut("info","没有该用户登录信息"));
|
||||
}else{
|
||||
return R.success(new JSONObject().fluentPut("info",expire));
|
||||
}
|
||||
}
|
||||
|
||||
private R<JSONObject> addVerifyInfo(String userId, JSONObject parse) {
|
||||
Long expire = redisTemplate.getExpire(StringConstant.VERIFY_PRE + userId);
|
||||
Object o = redisTemplate.opsForValue().get(StringConstant.VERIFY_PRE + userId + "_no");
|
||||
assert expire != null;
|
||||
if (expire.equals(-2L) && o != null){
|
||||
Object verifyName = parse.get("verifyName");
|
||||
Object verifyPhone = parse.get("verifyPhone");
|
||||
Verify verify = new Verify();
|
||||
verify.setVerifyName(String.valueOf(verifyName));
|
||||
verify.setVerifyPhone(String.valueOf(verifyPhone));
|
||||
int update = verifyMapper.update(verify, new LambdaQueryWrapper<Verify>().eq(Verify::getStoreId, userId));
|
||||
return update == 1 ? R.success(new JSONObject().fluentPut("info","验证信息添加成功,请耐心等待管理员审核")) : R.failed(HttpCodes.HTTP_CODES500,new JSONObject().fluentPut("info","添加验证信息失败"));
|
||||
}
|
||||
return R.failed(HttpCodes.HTTP_CODES500,new JSONObject().fluentPut("info","当前用户还未过期或者未登陆过"));
|
||||
}
|
||||
|
||||
private R<JSONObject> ping(String userId) {
|
||||
return R.success(new JSONObject().fluentPut("info","pong").fluentPut("time",redisTemplate.getExpire(StringConstant.VERIFY_PRE + userId)));
|
||||
}
|
||||
public List<String> getExpireTimes(){
|
||||
List<String> expireUser = new ArrayList<>();
|
||||
Set<String> keys = redisTemplate.keys(prefix.concat(StringConstant.VERIFY_PRE + "*"));
|
||||
assert keys != null;
|
||||
keys.forEach(e -> {
|
||||
if (Objects.equals(redisTemplate.getExpire(e), -1L)){
|
||||
expireUser.add(e);
|
||||
redisTemplate.delete(e);
|
||||
}else if (Objects.equals(redisTemplate.getExpire(e),-2L)){
|
||||
redisTemplate.delete(e);
|
||||
}
|
||||
});
|
||||
log.info("{}",keys);
|
||||
return expireUser;
|
||||
}
|
||||
}
|
@ -5,4 +5,6 @@ public class StringConstant {
|
||||
public static final String EMAIL_REGEX = "\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}";
|
||||
public static final String USERNAME_REGEX = "[A-Za-z0-9_\\-一-龥]+";
|
||||
public static final String ID_REGEX = "[0-9]*";
|
||||
|
||||
public static final String VERIFY_PRE = "verify_";
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user