Spring4.0.6 Websocket详细配置 之 讯息模块
来源:互联网 发布:男生瘦脸 知乎 编辑:程序博客网 时间:2024/05/22 15:03
环境介绍:
Jdk 1.7
Tomcat7.0.52 (支持Websocket协议)
Spring4.0.26 (支持Websocket)
web.xml(配置了前端自动优化HtmlCompressor和Druid监控),自动优化会影响Websocket js脚本,后面会讲
=================================================
配置步骤:
1. 引入Spring相关Jar,特别需要下面这两个
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>4.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>4.0.6.RELEASE</version>
</dependency>
2. 编写WebSocketConfig implements WebSocketConfigurer
WebSocketConfig.java
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.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;import cn.com.ship.message.handler.ChatMessageHandler;import cn.com.ship.message.handler.TextMessageHandler;@Configuration<strong><span style="color: rgb(255, 0, 0);">//@EnableWebMvc//这个标注可以不加,如果有加,要</span><span style="color: rgb(255, 0, 0);">extends WebMvcConfigurerAdapter</span></strong>@EnableWebSocketpublic class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(chatMessageHandler(),"/websocket/chatMessageServer.do").addInterceptors(new ChatHandshakeInterceptor()); registry.addHandler(chatMessageHandler(), "/sockjs/chatMessageServer.do").addInterceptors(new ChatHandshakeInterceptor()).withSockJS(); } @Bean public TextWebSocketHandler chatMessageHandler(){ return new ChatMessageHandler(); }}
3. 编写ChatMessageHandler extends TextWebSocketHandler
ChatMessageHandler.java
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;import cn.com.ship.message.common.Constants;import cn.com.ship.message.common.MessageCriteria;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>();}public ChatMessageHandler() {// TODO Auto-generated constructor stub}/** * 连接成功时候,会触发UI上onopen方法 */@Override public 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 {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(); } } } @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { if(session.isOpen()){ session.close(); } logger.debug("websocket connection closed......"); users.remove(session); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { logger.debug("websocket connection closed......"); users.remove(session); } @Override public boolean supportsPartialMessages() { return false; }}
4. 编写websocket握手拦截器ChatHandshakeInterceptor extends HttpSessionHandshakeInterceptor
ChatHandshakeInterceptor.java
package cn.com.ship.message.websocket;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;import cn.com.ship.message.common.Constants;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); } } 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);}}
4. 重点在Spring mvc相关配置(经常出现问题就是:中文乱码,如果是用ajax交互)
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util"xmlns:tool="http://www.springframework.org/schema/tool" xmlns:context="http://www.springframework.org/schema/context"xmlns:task="http://www.springframework.org/schema/task"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:websocket="http://www.springframework.org/schema/websocket"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool.xsdhttp://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsdhttp://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket-4.1.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd"><!-- 这个bean要放在context:component-scan这个前面,不然会出现中文乱码 --><beanclass="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"><property name="messageConverters"><list><ref bean="stringHttpMessageConverter" /><ref bean="byteArrayHttpMessageConverter" /><ref bean="jsonHttpMessageConverter" /><ref bean="jsonHttpMessageConverter4JS" /></list></property></bean><!-- 启动SpringMVC Controller的注解功能,完成请求和注解POJO的映射 --><context:component-scan base-package="cn.com.ship.*.**.controller" /><!-- websocket相关扫描,主要扫描:WebSocketConfig.java 这个类路径 --><context:component-scan base-package="cn.com.ship.message.websocket"/><!-- 下面标签可以不加 等价于所有component-scan--><context:annotation-config /><!-- 这个重点,标注必须加,websocket用到--><mvc:annotation-driven/><bean id="byteArrayHttpMessageConverter"class="org.springframework.http.converter.ByteArrayHttpMessageConverter" /><bean id="stringHttpMessageConverter"class="org.springframework.http.converter.StringHttpMessageConverter"><property name="supportedMediaTypes"><list><value>text/plain;charset=UTF-8</value></list></property></bean><bean id="jsonHttpMessageConverter"class="cn.com.ship.external.spring.converter.json.MappingJackson2HttpMessageConverter"><property name="objectMapper"><bean class="com.fasterxml.jackson.databind.ObjectMapper"><!--对属性值为null的不序列化反序列化--><property name="serializationInclusion"><util:constant static-field="com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL"/></property></bean></property><property name="supportedMediaTypes"><list><value>application/json</value></list></property></bean><bean id="jsonHttpMessageConverter4JS"class="cn.com.ship.external.spring.converter.json.MappingJackson2HttpMessageConverter"><property name="objectMapper"><bean class="com.fasterxml.jackson.databind.ObjectMapper"><property name="dateFormat"><bean class="java.text.SimpleDateFormat"><constructor-arg type="java.lang.String" value="yyyy-MM-dd HH:mm:ss" /></bean></property><!--对属性值为null的不序列化反序列化--><property name="serializationInclusion"><util:constant static-field="com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL"/></property></bean></property><property name="supportedMediaTypes"><list><value>text/json</value></list></property></bean><bean id="viewResolver"class="org.springframework.web.servlet.view.UrlBasedViewResolver"><property name="viewClass"value="org.springframework.web.servlet.view.JstlView" /><property name="prefix" value="/" /><property name="suffix" value=".jsp" /></bean><!-- 文件上传配置 --><bean id="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver"p:defaultEncoding="utf-8"><property name="maxUploadSize" value="1024000000" /><property name="resolveLazily" value="true" /></bean></beans>
注意:MappingJackson2HttpMessageConverter.java,来自Spring代码,并且修改了一点点,这个找到附件位置下载
5. jsp相关Websocket脚本编写
ws.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><html><head><title>Java API for WebSocket (JSR-356)</title> </head><body><script type="text/javascript" src="http://localhost:8080/ship/js/jquery/jquery.min.js"></script><script type="text/javascript" src="http://localhost:8080/ship/js/sockjs-0.3.4.min.js"></script><script type="text/javascript">var websocket = null;if ('WebSocket' in window) {websocket = new WebSocket("ws://localhost:8080/ship/webSocketServer.do");} else if ('MozWebSocket' in window) {websocket = new MozWebSocket("ws://localhost:8080/ship/webSocketServer.do");} else {websocket = new SockJS("http://localhost:8080/ship/sockjs/webSocketServer.do");}websocket.onopen = onOpen;websocket.onmessage = onMessage;websocket.onerror = onError;websocket.onclose = onClose; function onOpen(openEvt) {//alert(openEvt.Data);}function onMessage(evt) {alert(evt.data);}function onError() {}function onClose() {}function doSend() {if (websocket.readyState == websocket.OPEN) { var msg = document.getElementById("inputMsg").value; websocket.send(msg);//调用后台handleTextMessage方法 alert("发送成功!"); } else { alert("连接失败!"); } }</script>请输入:<textarea rows="5" cols="10" id="inputMsg" name="inputMsg"></textarea><button onclick="doSend();">发送</button></body></html>
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Java API for WebSocket (JSR-356)</title> </head><body> <!-ship是我的项目名--><form action="/ship/websocket/login.do">登录名:<input type="text" name="username"/><input type="submit" value="登录"/></form></body></html>
5. 调用端Controller编写 WebsocketController.java
package cn.com.ship.websocket.controller;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;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;@Controllerpublic class WebsocketController {@Bean//这个注解会从Spring容器拿出Beanpublic InfoHandler infoHandler() {return new InfoHandler();}@RequestMapping("/websocket/login")public void login(HttpServletRequest request, HttpServletResponse response) throws Exception {String username = request.getParameter("username");HttpSession session = request.getSession(false);session.setAttribute(Constants.SESSION_USERNAME, username);response.sendRedirect("/ship/websocket/ws.jsp");}@RequestMapping("/websocket/send")@ResponseBodypublic String send(HttpServletRequest request) {String username = request.getParameter("username");infoHandler().sendMessageToUser(username, new TextMessage("你好,测试!!!!"));return null;}}
6. 测试Websocket是否连接成功
先在login.jsp上随便输入用户名,然后WebsocketController处理完请求,会重定向到ws.jsp
如果后台打印出现消息,证明Websocket连接成功(前两名消息是在ChatHandshakeInterceptor.java,最后一句是在ChatMessageHandler.java)
Before Handshake
After Handshake
connect to the websocket success......
开发中遇到各个问题,会开另外一篇文章来描述!!!
http://strongant.iteye.com/blog/2153821
- Spring4.0.6 Websocket详细配置 之 讯息模块
- Spring4.0.6 Websocket详细配置
- Spring4.0.6 Websocket详细配置 之 遇到问题
- Spring - Websocket详细配置
- Spring4配置websocket,基于xml从零(0)开始
- eclipse配置spring4.0环境详细教程
- spring4.0 websocket
- spring4.X websocket问题
- Spring4+WebSocket搭建
- spring4 集成WebSocket
- Spring4+WebSocket实例
- maven构建spring4 mvc+spring4 websocket应用
- spring4 + WebSocket笔记 [含源码]
- Spring4.0 + websocket简单应用
- spring4+tomcat8+jdk8应用websocket
- webSocket 案例 使用spring4.0.0
- 一个Spring4 WebSocket群发示例
- 使用spring4的websocket支持
- nyoj_33 蛇形填数
- 【C#设计模式-桥接模式】
- 北京燃气召开TnPM三维数字化设备管理系统项目启动大会
- 改编版iframe 跨域问题 。window.name方式 postMessage 。。。。。。。。。
- Thread的run()与start()的区别
- Spring4.0.6 Websocket详细配置 之 讯息模块
- Linux查看系统是否被cc攻击的方法
- 如何描述PCIe SSD性能的稳定性?
- 如何修改oc中默认的NSLog函数
- mongodb lbs 坐标定位 java操作版本
- 你是想做个安静的程序员,还是去创个业呢?
- CSS 属性(1)
- Android之Sensor 简介
- 数据库