org.springframework.boot
spring-boot-starter-websocket
2.webSocket的作用
WebSocket是基于TCP协议的,它是全双工通信的,服务端可以向客户端发送信息,客户端同样可以向服务器发送指令,常用于聊天应用中。
3.Springboot加载websocket@Configuration
public class WebConfig extends WebMvcConfigurationSupport {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
@Bean
public FilterRegistrationBean filter(){
CorsConfiguration config=new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedMethod("*");
config.addAllowedHeader("*");
//When allowCredentials is true, allowedOrigins cannot contain the special value "*“since that cannot be set on the “Access-Control-Allow-Origin” response header.
// To allow credentials to a set of origins, list them explicitly or consider using"allowedOriginPatterns” instead.
config.addAllowedOriginPattern("*");
UrlbasedCorsConfigurationSource configSource=new UrlbasedCorsConfigurationSource();
configSource.registerCorsConfiguration("
//通过注解ServerEndpoint设置WebSocket连接点的服务地址
@ServerEndpoint(value = "/websocket/{userId}")
@Component
public class WebSocketServer {
private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);
private static AtomicInteger count=new AtomicInteger(0);
private Session session;
private static Map webSocketServerMap=new ConcurrentHashMap<>();
private String userId="";
public static String offline(String userId) {
if(webSocketServerMap.containsKey(userId)){
webSocketServerMap.remove(userId);
//用户-1
count.getAndDecrement();
return "强制下线用户"+userId+"成功";
}else{
return "当前用户"+userId+"不在线";
}
}
@OnOpen
public void onOpen(@PathParam(value = "userId") String userId,Session session){
this.userId=userId;
this.session=session;
//判断当前用户是否在线
if(webSocketServerMap.containsKey(userId)){
webSocketServerMap.remove(userId);
webSocketServerMap.put(userId,this);
}else {
webSocketServerMap.put(userId, this);
//数量+1
count.getAndIncrement();
}
log.info("websocket新连接:{},当前在线人数为:{}",userId,getOnline());
}
@OnClose
public void OnClose(){
//用户在线才断开连接
if(webSocketServerMap.containsKey(this.userId)){
webSocketServerMap.remove(this.userId);
//数量-1
count.getAndDecrement();
log.info("websocket连接关闭:{},当前在线人数为:{}",this.userId,getOnline());
}
}
@OnError
public void OnError(Throwable throwable){
log.info("websocket连接关闭:{},错误原因为:{}",this.userId,throwable.getMessage());
webSocketServerMap.remove(this.userId);
//数量-1
count.getAndDecrement();
}
@OnMessage
public void OnMessage(String message,Session session){
log.info("收到来自窗口"+userId+"的信息:"+message);
if(StringUtils.isNotBlank(message)){
JSONArray list= JSONArray.parseArray(message);
for (int i = 0; i < list.size(); i++) {
try {
//解析发送的报文
JSONObject object = list.getJSONObject(i);
String toUserId=object.getString("toUserId");
String contentText=object.getString("contentText");
object.put("fromUserId",this.userId);
//传送给对应用户的websocket
if(StringUtils.isNotBlank(toUserId)&&StringUtils.isNotBlank(contentText)){
WebSocketServer webSocketServer = webSocketServerMap.get(toUserId);
//需要进行转换,userId
if(webSocketServer!=null){
// webSocketServer.sendMessage(JSON.toJSonString(ApiReturnUtil.success(object)));
//此处可以放置相关业务代码,例如存储到数据库
}
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
public void sendMessage(String message){
//异步发送
this.session.getAsyncRemote().sendText(message);
}
public static void sendInfo(String userId,String message){
if(webSocketServerMap.containsKey(userId)){
webSocketServerMap.get(userId).sendMessage(message);
log.info("发送给用户:{}的信息:{}成功",userId,message);
}else {
log.info("用户:{}不在线",userId);
}
}
public static void batchSendInfo(String message, List userIds){
if(CollectionUtils.isEmpty(userIds)){
webSocketServerMap.keySet().forEach(userId->sendInfo(userId,message));
}else {
userIds.forEach(userId->sendInfo(userId, message));
}
}
public static int getOnline(){
return count.intValue();
}
public static Set getUser(){
return webSocketServerMap.keySet();
}
}
4.2.控制层
package com.zyp.controller;
import com.google.common.collect.Lists;
import com.zyp.common.NoLogin;
import com.zyp.websocket.WebSocketServer;
import com.zyp.util.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.Set;
@RestController
@RequestMapping(value = "websocket/")
@Api(tags = "websocket测试")
public class WebSocketController {
@ApiOperation("发送信息")
@GetMapping("pushMessage/{userId}")
@NoLogin
public Result pushMessage(@PathVariable String userId, @RequestParam String message){
if(StringUtils.equals(userId, "all")){
WebSocketServer.batchSendInfo(message, Lists.newArrayList());
}else{
WebSocketServer.batchSendInfo(message, Arrays.asList(userId.split(",")));
}
return Result.ok("发送成功");
}
@ApiOperation("获取在线的")
@GetMapping("getOnline")
@NoLogin
public Result getOnline(){
//在线人数
int count = WebSocketServer.getOnline();
Set users = WebSocketServer.getUser();
return Result.ok().put("count",count).put("userList",users);
}
@ApiOperation("强制下线指定用户")
@GetMapping("offline/{userId}")
@NoLogin
public Result offline(@PathVariable String userId){
String result = WebSocketServer.offline(userId);
return Result.ok(result);
}
}
4.3前端代码
WebSocket



