权限控制
This commit is contained in:
@@ -11,6 +11,7 @@ import io.swagger.annotations.Api;
|
|||||||
import io.swagger.annotations.ApiImplicitParam;
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -22,6 +23,7 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
@RequestMapping("accept")
|
@RequestMapping("accept")
|
||||||
@RestController
|
@RestController
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
@Slf4j
|
||||||
public class EventGateController extends BaseController {
|
public class EventGateController extends BaseController {
|
||||||
|
|
||||||
private final WebSocketServer webSocketServer;
|
private final WebSocketServer webSocketServer;
|
||||||
@@ -31,13 +33,13 @@ public class EventGateController extends BaseController {
|
|||||||
@GetMapping("/eventMsg")
|
@GetMapping("/eventMsg")
|
||||||
@ApiOperation("接收远程推送的暂态事件")
|
@ApiOperation("接收远程推送的暂态事件")
|
||||||
@ApiImplicitParam(name = "eventMsg", value = "暂态事件json字符", required = true)
|
@ApiImplicitParam(name = "eventMsg", value = "暂态事件json字符", required = true)
|
||||||
public HttpResult<JSONObject> eventMsg(@RequestParam("msg") String msg) {
|
public HttpResult<Object> eventMsg(@RequestParam("msg") String msg) {
|
||||||
String methodDescribe = getMethodDescribe("eventMsg");
|
String methodDescribe = getMethodDescribe("eventMsg");
|
||||||
System.out.println(msg);
|
log.info("接收到暂降事件:{}",msg);
|
||||||
|
|
||||||
JSONObject jsonObject = new JSONObject(msg);
|
JSONObject jsonObject = new JSONObject(msg);
|
||||||
webSocketServer.sendMessageToUser("bbb",jsonObject.toString());
|
webSocketServer.sendMessageToAll(jsonObject.toString());
|
||||||
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, jsonObject, methodDescribe);
|
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -81,6 +81,17 @@ public class LargeScreenCountController extends BaseController {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@OperateInfo
|
||||||
|
@PostMapping("/noDealEventList")
|
||||||
|
@ApiOperation("暂降事件列表")
|
||||||
|
@ApiImplicitParam(name = "largeScreenCountParam", value = "查询参数", required = true)
|
||||||
|
public HttpResult<List<EventDetailVO>> noDealEventList(@RequestBody LargeScreenCountParam largeScreenCountParam) {
|
||||||
|
String methodDescribe = getMethodDescribe("noDealEventList");
|
||||||
|
List<EventDetailVO> result = largeScreenCountService.eventList(largeScreenCountParam);
|
||||||
|
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package com.njcn.gather.event.transientes.filter;
|
package com.njcn.gather.event.transientes.filter;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
|
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
|
||||||
|
import com.njcn.common.pojo.response.HttpResult;
|
||||||
import com.njcn.gather.event.transientes.utils.JwtUtil;
|
import com.njcn.gather.event.transientes.utils.JwtUtil;
|
||||||
import io.jsonwebtoken.ExpiredJwtException;
|
import io.jsonwebtoken.ExpiredJwtException;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -33,21 +36,22 @@ public class JwtRequestFilter extends OncePerRequestFilter {
|
|||||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
||||||
throws ServletException, IOException {
|
throws ServletException, IOException {
|
||||||
|
|
||||||
|
System.out.println("请求路径"+request.getRequestURI());
|
||||||
final String authorizationHeader = request.getHeader("Authorization");
|
final String authorizationHeader = request.getHeader("Authorization");
|
||||||
|
|
||||||
String username = null;
|
String username = null;
|
||||||
String jwt = null;
|
String jwt = null;
|
||||||
|
|
||||||
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
|
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
|
||||||
jwt = authorizationHeader.substring(7);
|
jwt = authorizationHeader.substring(7);
|
||||||
try {
|
try {
|
||||||
username = jwtUtil.extractUsername(jwt);
|
username = jwtUtil.extractUsername(jwt);
|
||||||
|
} catch (ExpiredJwtException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
sendErrorResponse(response,CommonResponseEnum.TOKEN_EXPIRE_JWT);
|
||||||
|
return;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// 可以在这里处理令牌过期的情况
|
e.printStackTrace();
|
||||||
log.info("JWT Token 校验异常,可能过期了");
|
sendErrorResponse(response,CommonResponseEnum.PARSE_TOKEN_ERROR);
|
||||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
return;
|
||||||
response.getWriter().write("Token expired");
|
|
||||||
return; // 终止请求处理
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,11 +62,21 @@ public class JwtRequestFilter extends OncePerRequestFilter {
|
|||||||
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
|
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
|
||||||
new UsernamePasswordAuthenticationToken(
|
new UsernamePasswordAuthenticationToken(
|
||||||
userDetails, null, userDetails.getAuthorities());
|
userDetails, null, userDetails.getAuthorities());
|
||||||
usernamePasswordAuthenticationToken
|
usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||||
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
|
||||||
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
|
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chain.doFilter(request, response);
|
chain.doFilter(request, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sendErrorResponse(HttpServletResponse response, CommonResponseEnum error) throws IOException {
|
||||||
|
response.setStatus(HttpServletResponse.SC_OK);
|
||||||
|
response.setContentType("application/json;charset=UTF-8");
|
||||||
|
|
||||||
|
HttpResult<String> httpResult = new HttpResult<>();
|
||||||
|
httpResult.setCode(error.getCode());
|
||||||
|
httpResult.setMessage(error.getMessage());
|
||||||
|
|
||||||
|
response.getWriter().write(new JSONObject(httpResult, false).toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.njcn.gather.event.transientes.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.njcn.gather.event.transientes.pojo.po.PqsUserSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: cdf
|
||||||
|
* @CreateTime: 2025-06-24
|
||||||
|
* @Description:
|
||||||
|
*/
|
||||||
|
public interface PqsUserSetMapper extends BaseMapper<PqsUserSet> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -19,4 +19,7 @@ public class LargeScreenCountParam {
|
|||||||
|
|
||||||
@ApiModelProperty(name="eventtype",value="类型(0 暂降事件 1远程通知)")
|
@ApiModelProperty(name="eventtype",value="类型(0 暂降事件 1远程通知)")
|
||||||
private Integer eventtype;
|
private Integer eventtype;
|
||||||
|
|
||||||
|
@ApiModelProperty(name="eventDeep",value="0.普通事件 1.严重事件 null.全部事件")
|
||||||
|
private Integer eventDeep;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package com.njcn.gather.event.transientes.pojo.po;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: cdf
|
||||||
|
* @CreateTime: 2025-06-24
|
||||||
|
* @Description:
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName("PQSADMIN_BJ.PQS_USERSET")
|
||||||
|
public class PqsUserSet implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户设置索引
|
||||||
|
*/
|
||||||
|
@TableId("USERSET_INDEX")
|
||||||
|
private String usersetIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户索引
|
||||||
|
*/
|
||||||
|
@TableField("USER_INDEX")
|
||||||
|
private String userIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否通知(0-否,1-是)
|
||||||
|
*/
|
||||||
|
@TableField("ISNOTICE")
|
||||||
|
private Integer isNotice;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色组索引
|
||||||
|
*/
|
||||||
|
@TableField("ROLEGP_INDEX")
|
||||||
|
private String roleGpIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门索引
|
||||||
|
*/
|
||||||
|
@TableField("DEPTS_INDEX")
|
||||||
|
private String deptsIndex;
|
||||||
|
}
|
||||||
@@ -1,7 +1,14 @@
|
|||||||
package com.njcn.gather.event.transientes.security;
|
package com.njcn.gather.event.transientes.security;
|
||||||
|
|
||||||
|
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
|
||||||
import com.njcn.common.pojo.exception.BusinessException;
|
import com.njcn.common.pojo.exception.BusinessException;
|
||||||
|
import com.njcn.common.pojo.response.HttpResult;
|
||||||
|
import com.njcn.common.utils.PubUtils;
|
||||||
import com.njcn.gather.event.transientes.utils.JwtUtil;
|
import com.njcn.gather.event.transientes.utils.JwtUtil;
|
||||||
|
import com.njcn.web.controller.BaseController;
|
||||||
|
import com.njcn.web.utils.HttpResultUtil;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.BadCredentialsException;
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
@@ -13,7 +20,8 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
public class AuthController {
|
@Slf4j
|
||||||
|
public class AuthController extends BaseController {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AuthenticationManager authenticationManager;
|
private AuthenticationManager authenticationManager;
|
||||||
@@ -25,18 +33,21 @@ public class AuthController {
|
|||||||
private JwtUtil jwtUtil;
|
private JwtUtil jwtUtil;
|
||||||
|
|
||||||
@PostMapping("/cn_authenticate")
|
@PostMapping("/cn_authenticate")
|
||||||
public String createAuthenticationToken(@RequestBody AuthRequest authRequest) throws Exception {
|
@ApiOperation("登录认证")
|
||||||
|
public HttpResult<String> createAuthenticationToken(@RequestBody AuthRequest authRequest) {
|
||||||
|
String methodDescribe = getMethodDescribe("createAuthenticationToken");
|
||||||
|
log.info("Authentication request - username: {}, password: {}",authRequest.getUsername(),authRequest.getPassword());
|
||||||
try {
|
try {
|
||||||
authenticationManager.authenticate(
|
authenticationManager.authenticate(
|
||||||
new UsernamePasswordAuthenticationToken(authRequest.getUsername(), authRequest.getPassword())
|
new UsernamePasswordAuthenticationToken(authRequest.getUsername(), authRequest.getPassword())
|
||||||
);
|
);
|
||||||
} catch (BadCredentialsException e) {
|
} catch (BadCredentialsException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
throw new BusinessException("Incorrect username or password");
|
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.FAIL, null, methodDescribe);
|
||||||
}
|
}
|
||||||
final UserDetails userDetails = userDetailsService.loadUserByUsername(authRequest.getUsername());
|
final UserDetails userDetails = userDetailsService.loadUserByUsername(authRequest.getUsername());
|
||||||
final String jwt = jwtUtil.generateToken(userDetails);
|
final String jwt = jwtUtil.generateToken(userDetails);
|
||||||
return jwt;
|
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, jwt, methodDescribe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
http.csrf().disable()
|
http.csrf().disable()
|
||||||
.authorizeRequests()
|
.authorizeRequests()
|
||||||
.antMatchers("/cn_authenticate").permitAll() // 允许访问认证接口
|
.antMatchers("/cn_authenticate","/ws/**").permitAll() // 允许访问认证接口
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
.and()
|
.and()
|
||||||
.sessionManagement()
|
.sessionManagement()
|
||||||
|
|||||||
@@ -23,4 +23,8 @@ public interface LargeScreenCountService {
|
|||||||
List<EventTrendVO> eventTrend(LargeScreenCountParam largeScreenCountParam);
|
List<EventTrendVO> eventTrend(LargeScreenCountParam largeScreenCountParam);
|
||||||
|
|
||||||
List<EventDetailVO> eventList(LargeScreenCountParam largeScreenCountParam);
|
List<EventDetailVO> eventList(LargeScreenCountParam largeScreenCountParam);
|
||||||
|
|
||||||
|
List<EventDetailVO> noDealEventList(LargeScreenCountParam largeScreenCountParam);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.njcn.gather.event.transientes.service.impl;
|
|||||||
import cn.hutool.core.date.DatePattern;
|
import cn.hutool.core.date.DatePattern;
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.njcn.common.pojo.exception.BusinessException;
|
import com.njcn.common.pojo.exception.BusinessException;
|
||||||
import com.njcn.gather.event.transientes.pojo.param.LargeScreenCountParam;
|
import com.njcn.gather.event.transientes.pojo.param.LargeScreenCountParam;
|
||||||
import com.njcn.gather.event.devcie.pojo.po.PqDevice;
|
import com.njcn.gather.event.devcie.pojo.po.PqDevice;
|
||||||
@@ -24,10 +25,7 @@ import org.springframework.stereotype.Service;
|
|||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -186,5 +184,19 @@ public class LargeScreenCountServiceImpl implements LargeScreenCountService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<EventDetailVO> noDealEventList(LargeScreenCountParam largeScreenCountParam) {
|
||||||
|
|
||||||
|
if(Objects.isNull(largeScreenCountParam.getEventDeep())){
|
||||||
|
|
||||||
|
}
|
||||||
|
/* eventdetails = pqsEventdetailService.lambdaQuery()
|
||||||
|
.between(PqsEventdetail::getTimeid, startTime, endTime)
|
||||||
|
.in(PqsEventdetail::getLineid,deptslineIds)
|
||||||
|
.eq(PqsEventdetail::getLookFlag,largeScreenCountParam.getEventtype()).list();*/
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.njcn.gather.event.transientes.websocket;
|
package com.njcn.gather.event.transientes.websocket;
|
||||||
|
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -30,12 +29,15 @@ import java.util.concurrent.TimeUnit;
|
|||||||
public class WebSocketServer {
|
public class WebSocketServer {
|
||||||
|
|
||||||
private static final ConcurrentHashMap<String, Session> sessions = new ConcurrentHashMap<>();
|
private static final ConcurrentHashMap<String, Session> sessions = new ConcurrentHashMap<>();
|
||||||
private final ScheduledExecutorService heartbeatExecutor = Executors.newScheduledThreadPool(1);
|
private static final ConcurrentHashMap<String, Long> lastHeartbeatTime = new ConcurrentHashMap<>();
|
||||||
|
private static final ConcurrentHashMap<String, ScheduledExecutorService> heartbeatExecutors = new ConcurrentHashMap<>();
|
||||||
|
private static final long HEARTBEAT_TIMEOUT = 60; // 60秒超时
|
||||||
|
|
||||||
@OnOpen
|
@OnOpen
|
||||||
public void onOpen(Session session, @PathParam("userId") String userId) {
|
public void onOpen(Session session, @PathParam("userId") String userId) {
|
||||||
if (StrUtil.isNotBlank(userId)) {
|
if (StrUtil.isNotBlank(userId)) {
|
||||||
sessions.put(userId, session);
|
sessions.put(userId, session);
|
||||||
|
lastHeartbeatTime.put(userId, System.currentTimeMillis());
|
||||||
sendMessage(session, "连接成功");
|
sendMessage(session, "连接成功");
|
||||||
System.out.println("用户 " + userId + " 已连接");
|
System.out.println("用户 " + userId + " 已连接");
|
||||||
|
|
||||||
@@ -52,9 +54,10 @@ public class WebSocketServer {
|
|||||||
|
|
||||||
@OnMessage
|
@OnMessage
|
||||||
public void onMessage(String message, Session session, @PathParam("userId") String userId) {
|
public void onMessage(String message, Session session, @PathParam("userId") String userId) {
|
||||||
if ("ping".equalsIgnoreCase(message)) {
|
if ("alive".equalsIgnoreCase(message)) {
|
||||||
// 处理心跳请求
|
// 更新最后心跳时间
|
||||||
sendMessage(session, "pong");
|
lastHeartbeatTime.put(userId, System.currentTimeMillis());
|
||||||
|
sendMessage(session, "over");
|
||||||
} else {
|
} else {
|
||||||
// 处理业务消息
|
// 处理业务消息
|
||||||
System.out.println("收到用户 " + userId + " 的消息: " + message);
|
System.out.println("收到用户 " + userId + " 的消息: " + message);
|
||||||
@@ -64,7 +67,13 @@ public class WebSocketServer {
|
|||||||
|
|
||||||
@OnClose
|
@OnClose
|
||||||
public void onClose(Session session, CloseReason closeReason, @PathParam("userId") String userId) {
|
public void onClose(Session session, CloseReason closeReason, @PathParam("userId") String userId) {
|
||||||
|
// 移除用户并取消心跳检测
|
||||||
sessions.remove(userId);
|
sessions.remove(userId);
|
||||||
|
lastHeartbeatTime.remove(userId);
|
||||||
|
ScheduledExecutorService executor = heartbeatExecutors.remove(userId);
|
||||||
|
if (executor != null) {
|
||||||
|
executor.shutdownNow();
|
||||||
|
}
|
||||||
System.out.println("用户 " + userId + " 已断开连接,状态码: " + closeReason.getReasonPhrase());
|
System.out.println("用户 " + userId + " 已断开连接,状态码: " + closeReason.getReasonPhrase());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,12 +96,14 @@ public class WebSocketServer {
|
|||||||
System.out.println("发送消息给用户 " + userId + " 失败: " + e.getMessage());
|
System.out.println("发送消息给用户 " + userId + " 失败: " + e.getMessage());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
System.out.println("用户 " + userId + " 不在线或会话已关闭");
|
System.out.println("webSocket用户 " + userId + " 不在线或会话已关闭");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessageToAll(String message) {
|
public void sendMessageToAll(String message) {
|
||||||
|
|
||||||
sessions.forEach((userId, session) -> {
|
sessions.forEach((userId, session) -> {
|
||||||
|
System.out.println("给用户推送消息"+userId);
|
||||||
if (session.isOpen()) {
|
if (session.isOpen()) {
|
||||||
try {
|
try {
|
||||||
session.getBasicRemote().sendText(message);
|
session.getBasicRemote().sendText(message);
|
||||||
@@ -112,19 +123,25 @@ public class WebSocketServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void startHeartbeat(Session session, String userId) {
|
private void startHeartbeat(Session session, String userId) {
|
||||||
heartbeatExecutor.scheduleAtFixedRate(() -> {
|
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
|
||||||
if (session.isOpen()) {
|
heartbeatExecutors.put(userId, executor);
|
||||||
|
|
||||||
|
// 定期检查心跳
|
||||||
|
executor.scheduleAtFixedRate(() -> {
|
||||||
|
long lastTime = lastHeartbeatTime.getOrDefault(userId, 0L);
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
// 如果超过30秒没有收到心跳
|
||||||
|
if (currentTime - lastTime > HEARTBEAT_TIMEOUT * 1000) {
|
||||||
try {
|
try {
|
||||||
session.getBasicRemote().sendText("ping");
|
System.out.println("用户 " + userId + " 心跳超时,关闭连接");
|
||||||
|
session.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, "心跳超时"));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.out.println("发送心跳给用户 " + userId + " 失败: " + e.getMessage());
|
System.out.println("关闭用户 " + userId + " 连接时出错: " + e.getMessage());
|
||||||
try {
|
|
||||||
session.close(new CloseReason(CloseReason.CloseCodes.UNEXPECTED_CONDITION, "心跳失败"));
|
|
||||||
} catch (IOException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
}
|
||||||
|
executor.shutdown();
|
||||||
|
heartbeatExecutors.remove(userId);
|
||||||
}
|
}
|
||||||
}
|
}, 0, 5, TimeUnit.SECONDS); // 每5秒检查一次
|
||||||
}, 10, 10, TimeUnit.SECONDS); // 每10秒发送一次心跳
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user