java怎么封装websocket_java实现websocket 终极指南

本文详细介绍了使用Java封装WebSocket的步骤,包括配置依赖、创建WebSocket处理类、实现拦截器、控制器处理以及客户端连接。通过建立WebSocket连接,实现用户登录状态与WebSocket会话绑定,以及消息的收发和管理。
摘要由CSDN通过智能技术生成

大概思路:  首先用户登陆  获取用户信息存储到httpsession中,然后客户端链接服务端websocket,首先HandshakeInterceptor这个拦截器会拦截请求 调用 beforeHandshake方法进行握手操作,然后吧httpsession 和 websocketsession进行绑定 , 然后执行MySocketHandler 类得afterConnectionEstablished方法 ,创建一个静态map  吧所有连接得客户端存到map里 以便用户退出登陆时清空session。 客户端发来消息会调用 handleMessage

1、pom中添加依赖

org.springframework

spring-websocket

${spring-version}

org.springframework

spring-messaging

${spring-version}

2、spring-mvc.xml 中添加websocket拦截

3、添加MySocketHandler类

package com.cloudunicomm.interceptor;

import java.io.IOException;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;

import java.util.Map.Entry;

import java.util.Set;

import java.util.concurrent.CopyOnWriteArraySet;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.ListOperations;

import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.web.socket.CloseStatus;

import org.springframework.web.socket.TextMessage;

import org.springframework.web.socket.WebSocketMessage;

import org.springframework.web.socket.WebSocketSession;

import org.springframework.web.socket.handler.TextWebSocketHandler;

import com.alibaba.fastjson.JSONObject;

import com.cloudunicomm.vo.User;

public class MySocketHandler extends TextWebSocketHandler {

private static final Logger logger = LoggerFactory.getLogger(MySocketHandler.class);

// 线上人数

private static int count;

private static CopyOnWriteArraySet set = new CopyOnWriteArraySet<>();

public static Map sessionid = new HashMap();

private WebSocketSession session;

@Autowired

private RedisTemplate redisTemplate;

@Override

public void afterConnectionEstablished(WebSocketSession session) {

Map map = session.getAttributes();

String userid = map.get("userid").toString();

sessionid.put(userid, session);

this.session = session;

try{

set.add(this.session);

}catch(Exception e) {

e.printStackTrace();

}

MySocketHandler.addOnlineCount();

System.out.println("目前连接人数:" + getOnlineCount());

}

public void afterConnectionClosed(WebSocketSession session,CloseStatus closeStatus) {

this.session = session;

String userid = session.getAttributes().get("userid").toString();

redisTemplate.delete("SEAT_"+userid);

session.getAttributes().remove("userid");

set.remove(this.session);

subOnlineCount();

System.out.println("目前连接人数:" + getOnlineCount());

}

public void handleMessage(WebSocketSession session,WebSocketMessage>message){

System.out.println("来自客户端消息: "+message.getPayload()+ "_"+ session.getId() );

//发送给所有人

/* for(WebSocketSession ssion : set) {

try {

ssion.sendMessage(message);

}catch(IOException e) {

e.printStackTrace();

}

} */

//解析message 修改用户状态

try{

//id:state,

//username:sip:$tU@123.57.144.26:9060

String[] state = message.getPayload().toString().split("_");

ListOperations value = redisTemplate.opsForList();

String val = value.rightPop("SEAT_"+state[0]).toString();

User user = (User)JSONObject.toJavaObject(JSONObject.parseObject(val), User.class);

user.setState(Integer.parseInt(state[1]));

//实际是解析出来得 现在先写死

user.setNext_hop("123.57.144.26:9060/udp");

user.setTo("");

String struser = JSONObject.toJSONString(user);

value.leftPush("SEAT_"+user.getId().toString(), struser);

}catch(Exception e){

logger.error(e.getMessage(),e);

}

}

public static int getOnlineCount() {

return count;

}

public static void addOnlineCount() {

count++;

}

public static void subOnlineCount() {

count--;

}

/**

* 给指定连接推消息

* @param session

* @param message

*/

public String pushMsg(String sessionid, String message){

for(WebSocketSession ssion : set) {

try {

if(sessionid.equals(ssion.getId())){

ssion.sendMessage(new TextMessage(message));

return "机器:" + sessionid+ "推送成功";

}

}catch(IOException e) {

e.printStackTrace();

}

}

return "推送失败";

}

/**

* 给全部连接

* @param message

* @return

*/

public String pushMsg(String message) {

int i = 0;

for(WebSocketSession ssion : set) {

try {

ssion.sendMessage(new TextMessage(message));

i++;

}catch(IOException e) {

e.printStackTrace();

}

}

return "共有" + i + "得到推送";

}

}

4、添加 HandshakeInterceptor 类

package com.cloudunicomm.interceptor;

import java.util.Map;

import javax.servlet.http.HttpSession;

import org.springframework.http.server.ServerHttpRequest;

import org.springframework.http.server.ServerHttpResponse;

import org.springframework.http.server.ServletServerHttpRequest;

import org.springframework.web.socket.WebSocketHandler;

import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor {

/*

* 握手前处理动作

*/

@Override

public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler handler,

Map map)throws Exception {

System.out.println("握手前");

if(request instanceof ServletServerHttpRequest){

ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;

HttpSession httpSession = servletRequest.getServletRequest().getSession(true);

if(null != httpSession){

// String userid = httpSession.getAttribute("userid").toString();

String userid = httpSession.getAttribute("userid").toString();

map.put("userid",userid);

}

}

return super.beforeHandshake(request, response, handler, map);

}

@Override

public void afterHandshake(ServerHttpRequest request,ServerHttpResponse response,WebSocketHandler wsHandler,Exception ex) {

super.afterHandshake(request, response, wsHandler, ex);

}

}

5、添加TestController

package com.cloudunicomm.controller;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

@Controller

@RequestMapping("/im")

public class TestController {

/*@Bean

public MySorketHandle mySorketHandle() {

return new MySorketHandle();

} */

@RequestMapping("/page")

public String page(HttpServletRequest request, HttpServletResponse response) {

return "IMpage";

}

/*@ResponseBody

@RequestMapping("/push")

public String push(@RequestParam(required = false) String sessionId,

HttpServletResponse response){

String msg= "";

if (StringUtils.isEmpty(sessionId)) {

msg =mySorketHandle().pushMsg("服务器推送信息了");

System.out.println(msg);

}else{

msg =mySorketHandle().pushMsg(sessionId, "服务器推送信息了");

System.out.println(msg);

}

return msg;

} */

}

6、添加 jsp

pageEncoding="utf-8"%>

socket

welcome

sendMsg


close WebSocketconnection


var websocket = null;

//判断浏览器是否支持websocket

if('WebSocket' in window) {

websocket = new WebSocket("ws://localhost:8081/preSend/websocket");

}else{

$("#message").html("该浏览器不支持实时通信功能");

}

window.onbeforeunload = function () {

alert("x帆帆帆帆");

websocket.close();

}

websocket.onopen= function() {

console.log("websocket连接成功");

}

websocket.onclose= function() {

closewebsocket();

console.log("websocket连接关闭");

}

websocket.onmessage= function(event) {

console.log("接收消息");

console.log(event);

printMsg(event.data);

}

//打印消息

function printMsg(msg) {

$("#message").append(msg+ "
");

}

function sendMsg() {

var msg = $("#text").val();

websocket.send("3_0");

}

function closeWebSocket(){

websocket.close();

}

//离线

function closewebsocket(){

alert("用户离线了");

}

7、登陆controller

package com.cloudunicomm.controller;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.ListOperations;

import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.CrossOrigin;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestParam;

import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;

import com.cloudunicomm.service.UserService;

import com.cloudunicomm.utils.ResultMessage;

import com.cloudunicomm.vo.User;

@Controller

public class LoginController {

@Autowired

private UserService userService;

@Autowired

private RedisTemplate redisTemplate;

@CrossOrigin(origins = "*",maxAge = 3000)

@RequestMapping("login")

@ResponseBody

public ResultMessage login(HttpServletRequest request,HttpServletResponse response,

@RequestParam(name="username",required=false)String username,

@RequestParam(name="password",required=false)String password){

if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)){

return ResultMessage.getFail().setMessage("用户名密码不能为空!");

}

User user = userService.AuthUserNmaAndPassword(username,password);

if(user == null){

return ResultMessage.getFail().setMessage("用户名密码错误!");

}

String str = redisTemplate.opsForList().rightPopAndLeftPush("SEAT_"+user.getId(), "SEAT_"+user.getId());

if(null != str){

return ResultMessage.getFail().setMessage("请勿重复登陆!");

}

//登陆成功 添加 用户到redis中 islogin修改为在线 state修改为闲

user.setIslogin(0);

user.setState(0);

ListOperations redislist = redisTemplate.opsForList();

String struser = JSONObject.toJSONString(user);

//从左向右存压栈

redislist.leftPush("SEAT_"+user.getId().toString(), struser);

request.getSession().setAttribute("userid", user.getId());

return ResultMessage.getSuccess().setData(user.getId());

}

}

8、注意事项

1)项目中又拦截器要注释掉 否则websocket会链接失败抛出 'Upgrade' header is missing 异常

2)如果是远程调用测试时地址必须是同一个

要在 Java实现 WebSocket,可以使用 Java WebSocket API。以下是一个简单的示例: ```java import javax.websocket.*; import java.net.URI; @ClientEndpoint public class MyWebSocketClient { @OnOpen public void onOpen(Session session) { System.out.println("Connected to endpoint: " + session.getBasicRemote()); } @OnMessage public void onMessage(String message) { System.out.println("Received message: " + message); } public static void main(String[] args) { WebSocketContainer container = ContainerProvider.getWebSocketContainer(); String uri = "ws://localhost:8080/myendpoint"; try { Session session = container.connectToServer(MyWebSocketClient.class, URI.create(uri)); session.getBasicRemote().sendText("Hello, World!"); } catch (Exception e) { e.printStackTrace(); } } } ``` 在上面的示例中,我们定义了一个 `MyWebSocketClient` ,并使用 `@ClientEndpoint` 注解将其标记为 WebSocket 客户端端点。我们还定义了两个注解方法,`onOpen()` 和 `onMessage()`,分别在连接建立和接收到消息时被调用。在 `main()` 方法中,我们使用 `WebSocketContainer` 来连接到 WebSocket 终端点,并向其发送一条消息。 在使用上述代码之前,需要确保已经引入 Java WebSocket API 的依赖项。可以使用以下 Maven 依赖项: ```xml <dependency> <groupId>javax.websocket</groupId> <artifactId>javax.websocket-api</artifactId> <version>1.1</version> </dependency> ``` 注意,以上代码仅适用于通过端口直接连接的 WebSocket。如果需要使用 SSL/TLS 连接,或者需要进行身份验证等操作,需要进行额外的配置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值