一,web - demo链接如下(tomcat-websocket):
http://files.cnblogs.com/xiexy/websk.rar
二, springMvc + websocket 实现点对点通信
1,pom.xml 增加spring-websocket.jar
1 <!-- websocket - version须和spring mvc的version保持一致,否则会 2 出现问题 --> 3 <dependency> 4 <groupId>org.springframework</groupId> 5 <artifactId>spring-websocket</artifactId> 6 <version>${spring.version}</version> 7 </dependency>
2,登陆 - login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>socket - login</title> </head> <body> <center> <form action="websocket/login.do" method="post"> <table> <tr> <td>username:</td><td><input type="text" id="username" name="username"/></td> </tr> <tr> <td colspan="2"> <input type="submit" value="登录"/></td> </tr> </table> </form> </center> </body> </html>
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.socket.TextMessage; import com.aisino.core.user.entity.User; @RequestMapping("websocket") @Controller public class UserController { @Autowired private MsgScoketHandle msgScoketHandle; @RequestMapping("login") public String login(String username, HttpServletRequest request){ User user = new User(); user.setReal_name(username); request.getSession().setAttribute("user",user); request.getSession().setAttribute("username", username); return "soket/soket"; } @ResponseBody @RequestMapping("sendMsg") public String sendMag(String content,String toUserName){ User user = new User(); user.setReal_name(toUserName); TextMessage textMessage = new TextMessage(content); msgScoketHandle.sendMessageToUser(user,textMessage); return "200"; } }
3,点对点通信 socket - chat.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>socket - chat</title> <script type="text/javascript" src="plug-in/jquery/jquery-1.9.1.min.js"></script> <script type="text/javascript" src="views/soket/sockjs.min.js"></script> </head> <body> 当前登录用户:${username}<br> <input type="text" id="text"> <button id="btn1" value="发送给后台">发送给后台</button> <button id="btn2" value="发送给其他用户">发送给其他用户</button> <div id="msg"></div> </body> <script type="text/javascript"> $(document).ready(function() { var ws; if ('WebSocket' in window) { ws = new WebSocket("ws://"+window.location.host+"/robot/webSocketServer"); } else if ('MozWebSocket' in window) { ws = new MozWebSocket("ws://"+window.location.host+"/robot/webSocketServer"); } else { //如果是低版本的浏览器,则用SockJS这个对象,对应了后台“sockjs/webSocketServer”这个注册器, //它就是用来兼容低版本浏览器的 ws = new SockJS("http://"+window.location.host+"/robot/sockjs/webSocketServer"); } ws.onopen = function (evnt) { }; //接收到消息 ws.onmessage = function (evnt) { alert(evnt.data); $("#msg").html(evnt.data); }; ws.onerror = function (evnt) { console.log(evnt) }; ws.onclose = function (evnt) { } $("#btn1").click(function () { ws.send($("#text").val()); }); $("#btn2").bind("click",function () { var url = "${pageContext.request.contextPath}/websocket/sendMsg"; var content = $("#text").val(); var toUserName = "laoliu";//与老刘通信 $.ajax({ data: "content=" + content + "&toUserName=" + toUserName, type: "get", dataType: 'text', async: false, contentType: "application/x-www-form-urlencoded;charset=UTF-8", encoding: "UTF-8", url: url, success: function (data) { alert(data.toString()); }, error: function (msg) { alert(msg); }, }); }) }); </script> </html>
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; @Configuration @EnableWebMvc @EnableWebSocket public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer{ private static final Logger logger = LoggerFactory.getLogger(WebSocketConfig.class); @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { System.out.println("==========================注册socket"); //注册websocket server实现类,"/webSocketServer"访问websocket的地址 registry.addHandler(msgSocketHandle(), "/webSocketServer"). addInterceptors(new WebSocketHandshakeInterceptor()); //使用socketjs的注册方法 registry.addHandler(msgSocketHandle(), "/sockjs/webSocketServer"). addInterceptors(new WebSocketHandshakeInterceptor()) .withSockJS(); } /** * * @return 消息发送的Bean */ @Bean(name = "msgSocketHandle") public WebSocketHandler msgSocketHandle(){ return new MsgScoketHandle(); } }
import java.util.Map; import javax.servlet.http.HttpSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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.HandshakeInterceptor; import com.aisino.core.user.entity.User; public class WebSocketHandshakeInterceptor implements HandshakeInterceptor { private static final Logger logger = LoggerFactory.getLogger(WebSocketHandshakeInterceptor.class); /** * 握手前 * @param request * @param response * @param webSocketHandler * @param attributes * @return * @throws Exception */ @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler webSocketHandler, Map<String, Object> attributes) throws Exception { logger.info("握手操作"); if (request instanceof ServletServerHttpRequest){ ServletServerHttpRequest servletServerHttpRequest = (ServletServerHttpRequest) request; HttpSession session = servletServerHttpRequest.getServletRequest().getSession(false); if(session != null){ //从session中获取当前用户 User user = (User) session.getAttribute("user"); attributes.put("user",user); } } return true; } /** * 握手后 * @param serverHttpRequest * @param serverHttpResponse * @param webSocketHandler * @param e */ @Override public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) { } }
import java.io.IOException; import java.util.ArrayList; import org.springframework.stereotype.Component; import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketMessage; import org.springframework.web.socket.WebSocketSession; import com.aisino.core.user.entity.User; import com.google.common.collect.Lists; @Component public class MsgScoketHandle implements WebSocketHandler { /**已经连接的用户*/ private static final ArrayList<WebSocketSession> users; static { //保存当前连接用户 users = Lists.newArrayList(); } /** * 建立链接 * @param webSocketSession * @throws Exception */ @Override public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception { //将用户信息添加到list中 users.add(webSocketSession); System.out.println("=====================建立连接成功=========================="); User user = (User) webSocketSession.getAttributes().get("user"); if(user != null){ System.out.println("当前连接用户======"+user.getReal_name()); } System.out.println("webSocket连接数量====="+users.size()); } /** * 接收消息 * @param webSocketSession * @param webSocketMessage * @throws Exception */ @Override public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception { User user = (User) webSocketSession.getAttributes().get("user"); System.out.println("收到用户:"+user.getReal_name()+"的消息"); System.out.println(webSocketMessage.getPayload().toString()); System.out.println("==========================================="); } /** * 异常处理 * @param webSocketSession * @param throwable * @throws Exception */ @Override public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable){ if (webSocketSession.isOpen()){ //关闭session try { webSocketSession.close(); } catch (IOException e) { } } //移除用户 users.remove(webSocketSession); } /** * 断开链接 * @param webSocketSession * @param closeStatus * @throws Exception */ @Override public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception { users.remove(webSocketSession); User user = (User) webSocketSession.getAttributes().get("user"); System.out.println(user.getReal_name()+"断开连接"); } @Override public boolean supportsPartialMessages() { return false; } /** * 发送消息给指定的用户 * @param user * @param messageInfo */ public void sendMessageToUser(User user, TextMessage messageInfo){ for (WebSocketSession session : users) { User sessionUser = (User) session.getAttributes().get("user"); //根据用户名去判断用户接收消息的用户 if(user.getReal_name().equals(sessionUser.getReal_name())){ try { if (session.isOpen()){ session.sendMessage(messageInfo); System.out.println("发送消息给:"+user.getReal_name()+"内容:"+messageInfo); } break; } catch (IOException e) { e.printStackTrace(); } } } } }
4,注意点,使用Tomcat8以上,tomcat7会报错(貌似与tomat-websocket 冲突)
demo地址:https://files.cnblogs.com/files/xiexy/springMvc-websocket.zip