Spring4.0.6 Websocket详细配置
来源:互联网 发布:鲁南制药知乎 编辑:程序博客网 时间:2024/05/02 01:04
Spring4.0.6 Websocket详细配置 之 讯息模块
历经一周把整个消息模块开发完毕,其中在websocket这块遇到比较多的问题是中文乱码,因为项目中用ajax跟后端交互,用@Response注解时候出现中文乱码,需要Spring MVC相关配置,这块遇到配置会在另一个文章体现。
鉴于网上提供的一些文章,都介绍不是很到位,关键部分都没体现,导致在真实项目中出现各种各样的问题。
===============================================
环境介绍:
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:#ff0000;">//@EnableWebMvc//这个标注可以不加,如果有加,要</span><span style="color:#ff0000;"><strong><span style="color:#ff0000;">extends WebMvcConfigurerAdapter</span></strong></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)
- 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支持
- Servlet的编写方式
- .gitignore无法忽略所有文件解决办法。
- Hive的函数
- mui下拉刷新的跳转不能实现的解决办法
- DOM
- Spring4.0.6 Websocket详细配置
- 网页特殊符号HTML代码总结记录
- C++面向对象编程分享12----系统设计02---跟踪用户行为
- Servlet规范中的核心接口类图
- Android官方开发文档Training系列课程中文版:OpenGL绘图之图形绘制
- canvas学习之fillStyle
- 线程的生命周期
- 不推荐看
- word2vec