websocket的两种实现方式:1基于注解,2与spring整合
来源:互联网 发布:淘宝小号信用查询网站 编辑:程序博客网 时间:2024/05/01 21:06
1:注解方式简单明了
服务端代码
package controller;import java.io.IOException;import java.util.Collections;import java.util.HashSet;import java.util.LinkedList;import java.util.List;import java.util.Set;import javax.websocket.CloseReason;import javax.websocket.OnClose;import javax.websocket.OnError;import javax.websocket.OnMessage;import javax.websocket.OnOpen;import javax.websocket.Session;import javax.websocket.server.ServerEndpoint;@ServerEndpoint("/chatServer")public class Chat {private static Set<Session> sessions = Collections.synchronizedSet(new HashSet<Session>());private static List<String> messages = Collections.synchronizedList(new LinkedList<String>());@OnOpenpublic void onOpen(Session session) {System.out.println("Session: " + session.getId() + " connected!");sessions.add(session);System.out.println("目前信息数: "+messages.size());for(String message : messages){try {session.getBasicRemote().sendText(message);} catch (IOException e) {e.printStackTrace();}}}@OnMessagepublic void onMessage(String message, Session session) throws InterruptedException {System.out.println("session : "+session.getId() + " : " + message);messages.add(message); System.out.println("当前用户数: "+sessions.size());System.out.println("信息数:"+ messages.size());for(Session s : sessions){try {Thread.sleep(10000);s.getBasicRemote().sendText(message);} catch (IOException e) {System.out.println("出现异常");e.printStackTrace();}}}@OnClosepublic void onClose(Session session, CloseReason reason) {sessions.remove(session);System.out.println("Closed : " + session.getId());}@OnErrorpublic void onError(Throwable t) {System.out.println("Error : " + t.getMessage());t.printStackTrace();}}
客户端代码:
<!DOCTYPE html><html> <head> <meta charset="utf-8"> <title>chat Demo</title> <style> * { margin: 0; padding: 0; font-family: "微软雅黑"; } #mainFrame { float: left; padding: 20px; border: 1px solid gray; border-radius: 3px; text-align: center; } #userName { width: 500px; height: 30px; border: 1px solid gray; border-radius: 3px; } #msgContainer { text-align: left; margin: 15px 0; width: 640px; height: 480px; overflow: auto; border: 1px solid gray; border-radius: 3px; } #sendText { width: 560px; height: 30px; border: 1px solid gray; border-radius: 3px; } input[type="button"] { width: 60px; height: 30px; border: 1px solid gray; border-radius: 3px; } </style> </head> <body> <div id="mainFrame"> 用户名:<input type="text" id="userName"> <div id="msgContainer"></div> <input type="text" id="sendText"> <input type="button" value="发送" onclick="send()"> </div> <script> var msgContainer = document.getElementById("msgContainer"); //服务器地址 var url = "ws://127.0.0.1:8080/TestWebSocket/chatServer"; //创建WebSocket对象 var ws = new WebSocket(url); //与服务器建立连接 ws.onopen = function(){ console.info("connected!"); } //接收到服务器发来的信息 ws.onmessage = function(mes) { msgContainer.innerHTML = msgContainer.innerHTML + mes.data; //将数据加载到信息框 msgContainer.scrollTop = msgContainer.scrollHeight; //使信息框滚动条定位到最下边 } //服务器关闭 ws.onclose = function() { console.info("close"); } //服务器异常 ws.onerror = function() { console.info("error"); } //浏览器刷新或者关闭时,先关闭当前页面的WebSocket对象 window.onbeforeunload = function(){ ws.close(); } //发送信息 function send(){ var userName = document.getElementById("userName"); var sendText = document.getElementById("sendText"); if(userName.value ==""){ alert("请输入用户名!"); return; } if(sendText.value == "") return; //调用WebSocket发送信息的方法,向服务器发送信息 ws.send("<span style='color:green;font-size:12px;font-family:\"微软雅黑\"'>"+userName.value+":</span><br><span style='color:gray;font-size:16px;font-family:\"微软雅黑\"'>"+sendText.value+"</span><br><div style='border-top:1px dotted gray;'></div>"); sendText.value = ""; } </script> </body></html>
2:与spring整合
服务端代码
WebSocketConfig.Java
这个类是配置类,所以需要在spring mvc配置文件中加入对这个类的扫描,第一个addHandler是对正常连接的配置,第二个是如果浏览器不支持websocket,使用socketjs模拟websocket的连接。
package com.websocket;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.config.annotation.WebSocketConfigurer;import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;import org.springframework.web.socket.handler.TextWebSocketHandler;@Configuration@EnableWebSocketpublic class WebSocketConfig implements WebSocketConfigurer {
//这个方法的作用主要是用于注册建立握手之前的拦截造作, @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(chatMessageHandler(),"/webSocketServer").addInterceptors(new ChatHandshakeInterceptor()); registry.addHandler(chatMessageHandler(), "/sockjs/webSocketServer").addInterceptors(new ChatHandshakeInterceptor()).withSockJS(); }
//这个是socket信息处理类 @Bean public TextWebSocketHandler chatMessageHandler(){ return new ChatMessageHandler(); }}
ChatHandshakeInterceptor.java
这个类的作用就是在连接成功前和成功后增加一些额外的功能,Constants.java类是一个工具类,两个常量。
package com.websocket;import java.util.Map;import org.apache.shiro.SecurityUtils;import org.springframework.http.server.ServerHttpRequest;import org.springframework.http.server.ServerHttpResponse;import org.springframework.web.socket.WebSocketHandler;import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;public class ChatHandshakeInterceptor extends HttpSessionHandshakeInterceptor {@Overridepublic boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,Map<String, Object> attributes) throws Exception {System.out.println("Before Handshake");/* * if (request instanceof ServletServerHttpRequest) { * ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) * request; HttpSession session = * servletRequest.getServletRequest().getSession(false); if (session != * null) { //使用userName区分WebSocketHandler,以便定向发送消息 String userName = * (String) session.getAttribute(Constants.SESSION_USERNAME); if * (userName==null) { userName="default-system"; } * attributes.put(Constants.WEBSOCKET_USERNAME,userName); * * } } *///使用userName区分WebSocketHandler,以便定向发送消息(使用shiro获取session,或是使用上面的方式)String userName = (String) SecurityUtils.getSubject().getSession().getAttribute(Constants.SESSION_USERNAME);if (userName == null) {userName = "default-system";}attributes.put(Constants.WEBSOCKET_USERNAME, userName);/** 可以用这个逻辑也可以不用Long uid = Long.valueOf(((ServletServerHttpRequest) request).getServletRequest().getParameter("uid"));String wsDevice = String.valueOf(((ServletServerHttpRequest) request).getServletRequest().getParameter("wsDevice"));if (request instanceof ServletServerHttpRequest) {if (uid != null) {attributes.put("uid", uid);attributes.put("wsDevice", wsDevice);} else {return false;}}return true;*/return super.beforeHandshake(request, response, wsHandler, attributes);}@Overridepublic void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,Exception ex) {System.out.println("After Handshake");super.afterHandshake(request, response, wsHandler, ex);}}
ChatMessageHandler.java
这个类是对消息的一些处理,比如是发给一个人,还是发给所有人,并且前端连接时触发的一些动作
package com.websocket;import java.io.IOException;import java.util.ArrayList;import org.apache.log4j.Logger;import org.springframework.web.socket.CloseStatus;import org.springframework.web.socket.TextMessage;import org.springframework.web.socket.WebSocketSession;import org.springframework.web.socket.handler.TextWebSocketHandler;public class ChatMessageHandler extends TextWebSocketHandler {private static final ArrayList<WebSocketSession> users;// 这个会出现性能问题,最好用Map来存储,key用useridprivate static Logger logger = Logger.getLogger(ChatMessageHandler.class);static {users = new ArrayList<WebSocketSession>();}/** * 连接成功时候,会触发UI上onopen方法 */@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {System.out.println("connect to the websocket success......");users.add(session);// 这块会实现自己业务,比如,当用户登录后,会把离线消息推送给用户// TextMessage returnMessage = new TextMessage("你将收到的离线");// session.sendMessage(returnMessage);}/** * 在UI在用js调用websocket.send()时候,会调用该方法 */@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {sendMessageToUsers(message);//super.handleTextMessage(session, message);}/** * 给某个用户发送消息 * * @param userName * @param message */public void sendMessageToUser(String userName, TextMessage message) {for (WebSocketSession user : users) {if (user.getAttributes().get(Constants.WEBSOCKET_USERNAME).equals(userName)) {try {if (user.isOpen()) {user.sendMessage(message);}} catch (IOException e) {e.printStackTrace();}break;}}}/** * 给所有在线用户发送消息 * * @param message */public void sendMessageToUsers(TextMessage message) {for (WebSocketSession user : users) {try {if (user.isOpen()) {user.sendMessage(message);}} catch (IOException e) {e.printStackTrace();}}}@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {if (session.isOpen()) {session.close();}logger.debug("websocket connection closed......");users.remove(session);}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {logger.debug("websocket connection closed......");users.remove(session);}@Overridepublic boolean supportsPartialMessages() {return false;}}
阅读全文
0 0
- websocket的两种实现方式:1基于注解,2与spring整合
- Spring与hibernate的整合(基于注解
- 实现websocket的两种方式
- struts 与spring整合两种方式
- Spring与WebSocket的整合
- spring和ehcache整合,实现基于注解的缓存实现
- Spring 整合 Struts 的两种方式
- spring整合hibernate的两种方式
- struts2+spring的两种整合方式
- Struts2整合Spring的两种方式
- hibernate 整合spring的两种方式
- struts2整合spring的两种方式
- struts2+spring的两种整合方式
- struts2+spring的两种整合方式
- Spring整合Struts2的两种方式
- spring整合hibernate的两种方式
- Spring整合struts2的两种方式
- spring整合hibernate的两种方式
- 数据结构——bitmap
- windows下编译xgboost 并在eclipse中导入xgboost
- jQuery正则判断数组中是否有重复
- dom4j解析 xml文档
- 算法——图之加权有向图
- websocket的两种实现方式:1基于注解,2与spring整合
- java数据类型详解
- linux下C include搜索的路径
- 基于物理的渲染—更精确的微表面分布函数GGX
- flask表单提交的时候报错CSRF token missing or incorrect
- Java学习笔记-《Java程序员面试宝典》-第四章基础知识-4.1基本概念(4.1.4-4.1.5)
- stylus之注释(Comments)
- 10 ASCII编码与Unicode编码
- react学习之路(二)