博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
tomcat 7下spring 4.x mvc集成websocket以及sockjs完全参考指南(含nginx/https支持)
阅读量:4326 次
发布时间:2019-06-06

本文共 8397 字,大约阅读时间需要 27 分钟。

之所以会存在,说得不好听点,就是因为微软是个流氓,现在使用windows 7的系统仍然有近半,而windows 7默认自带的是ie 8,有些会自动更新到ie 9,但是大部分非IT用户其实都不愿意或者不会升级(通常我们做IT的认为很简单的事情,在其他行业的人来看,那就是天书,不要觉得不可能,现实已如此)。

现在言归正传,这里完整的讲下在集成sockjs,以及运行在tomcat 7下时的一些额外注意事项。

spring websocket依赖jar:

javax.websocket
javax.websocket-api
1.1
provided
org.springframework
spring-websocket
4.2.8.RELEASE

除非使用协议,否则不需要依赖spring-messaging。

spring通过两种模式支持websocket,一种是通过原生websocket规范的ws://协议访问(个人认为如果确定只用标准websocket访问,还不如tomcat升级到8.x(tomcat 8原生支持注解),spring的大量封装毕竟增加了不少额外负载);另一种则是通过sockjs(也就是js)访问,两者目前暂时无法做到兼容。

先完整说明第一种:

1、搭建spring mvc环境,这一点假设读者已知;

2、pom.xml中引入上面两个jar包;

3、spring支持websocket总共分为四个小步骤,handler、interceptor、config、web.xml,基本上可以认为spring mvc的翻版。

3.1、创建WebSocketHandler,spring支持两种方式,一种是实现org.springframework.web.socket.WebSocketHandler接口,另外一种则是继承TextWebSocketHandler或BinaryWebSocketHandler(现在大部分模板式框架或者插件通常都是在提供了API的基础上提供了抽象类,把一些能统一的工作提前预置了,以便应用只需要关心业务,我们自己公司的中间件框架很多也是用这个模式实现了)。

/** *  */package com.ld.net.spider.demo.ws;/** * @author zhjh256@163.com * {
@link} http://www.cnblogs.com/zhjh256 */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;public class DemoWSHandler implements WebSocketHandler { @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { System.out.println("connect to the websocket success......"); session.sendMessage(new TextMessage("Server:connected OK!")); } @Override public void handleMessage(WebSocketSession wss, WebSocketMessage
wsm) throws Exception { TextMessage returnMessage = new TextMessage(wsm.getPayload() + " received at server"); System.out.println(wss.getHandshakeHeaders().getFirst("Cookie")); wss.sendMessage(returnMessage); } @Override public void handleTransportError(WebSocketSession wss, Throwable thrwbl) throws Exception { if(wss.isOpen()){ wss.close(); } System.out.println("websocket connection closed......"); } @Override public void afterConnectionClosed(WebSocketSession wss, CloseStatus cs) throws Exception { System.out.println("websocket connection closed......"); } @Override public boolean supportsPartialMessages() { return false; }}

3.2、创建拦截器

/** *  */package com.ld.net.spider.demo.ws;import java.util.Map;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;/** * @author zhjh256@163.com  * {
@link} http://www.cnblogs.com/zhjh256 */public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor { @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map
attributes) throws Exception { // 解决The extension [x-webkit-deflate-frame] is not supported问题 if (request.getHeaders().containsKey("Sec-WebSocket-Extensions")) { request.getHeaders().set("Sec-WebSocket-Extensions", "permessage-deflate"); } System.out.println("Before Handshake"); return super.beforeHandshake(request, response, wsHandler, attributes); } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) { System.out.println("After Handshake"); super.afterHandshake(request, response, wsHandler, ex); }}

3.3、bean配置

上述需要注意的是,1、spring javadoc的说明是默认情况下,允许所有来源访问,但我们跑下来发现不配置allowed-origins的话总是报403错误。

2、sockjs是不允许有后缀的,否则将无法匹配,后面会专门讲到。

3.4、web.xml配置

在web.xml中增加*.ws映射即可(如果原来不是/*的话),如下:

springMVC
*.ws

上述配置完成之后,就可以通过标准的websocket接口进行访问了,如下所示。

4、websocket客户端

  
Web Socket JavaScript Echo Client

Echo Server

上述前后端均配置完成后,基于标准websocket api的搭建就完成了,试试吧。。

现在再来看下sockjs的配置。

spring对sockjs和websocket支持的差别在于配置,web.xml,以及客户端,服务实现无差别。

3.3需要调整为如下:

3.4 一定要有到/xxx/*的映射,简单的可以直接/*,如下所示:

springMVC
/*

上述配置完成后,就sockjs直接性的支持而言,就可以没有问题了。

客户端则为如下:

  
Web Socket JavaScript Echo Client

Echo Server

上述配置完成后,如果访问没有CORS异常的话,基于sockjs的websocket就完成了。试试吧。。。

典型错误及原因、解决方法如下:

Error during WebSocket handshake: Unexpected response code: 404

检查web.xml servlet-mapping包含了到websocket路径的映射,比如如果请求不含后缀,就必须包含/*的映射

 

WebSocket connection to 'ws://localhost:8080/springwebsocket/websocket' failed: Error during WebSocket handshake: Unexpected response code: 403

<websocket:handlers allowed-origins="*">,javadoc说明默认代表所有站点,实际好像并不是,所以需要配置*

 

sockjs启用

启用sockjs后,直接用websocket协议访问会报
html5ws.html:15 WebSocket connection to 'ws://localhost:28080/springws/websocket.ws' failed: Error during WebSocket handshake: Unexpected response code: 200

 

直接改为sockjs后,会报

XMLHttpRequest cannot load http://localhost:28080/springws/websocket.ws/info?t=1478758042205. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access. The response had HTTP status code 404.
需要在web.xml中配置CORS过滤(注意,如果apache有自带的类库,建议直接使用,不要随意听信网上的自己实现过滤器的搞法,这些库一天的运行次数可能就比自己写的运行到淘汰还多,所以几乎常见的问题都不可能遗漏):

CorsFilter
org.apache.catalina.filters.CorsFilter
cors.allowed.methods
GET,POST,HEAD,OPTIONS,PUT
cors.allowed.headers
Access-Control-Allow-Origin,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers
true
CorsFilter
/*

使用sockjs还有一点需要注意的是:

因为sockjs会自动在url之后增加/info?t=XXXX等路径,如果这里url-pattern拦截类似于*.ws这种带后缀的就找不到映射,比如想通过sockjs访问地址/springws/websocket.ws,但是sockjs框架会先访问/springws/websocket.ws/info这个地址,但是这个地址又不可被spring框架识别,所以导致不可用。

到此为止,tomcat 7下spring 4.x mvc集成websocket以及sockjs的配置就全部介绍完成。

今天看群里一个消息的时候,提到HA时一台服务器挂掉的问题,这就回到socket的思路了,客户端也得加上个定时的心跳逻辑,万一某台服务器挂了或者断网可以failover并自动重新建立连接。在我们的业务中,可靠性这一点是很关键的。

默认情况下,ws://走的时候http协议,即使主页面是通过https访问,此时会出现连接时异常"[blocked] The page at 'https://localhost:8443/endpoint-wss/index.jsp' was loaded over HTTPS, but ran insecure content from 'ws://localhost:8080/endpoint-wss/websocket': this content should also be loaded over HTTPS.Uncaught SecurityError: Failed to construct 'WebSocket': An insecure WebSocket connection may not be initiated from a page loaded over HTTPS.",此时需要使用如下连接:

websocket:wss://localhost:8080/endpoint-wss/websocket

sockJS:https://localhost:8080/endpoint-wss/socketJS

 

配置nginx支持websocket,默认情况下,nginx不支持自动升级至websocket协议,否则js中会出现连接时异常"",需在恰当的位置加上如下设置:

server {    listen 8020;    location / {        proxy_pass http://websocket;         proxy_set_header Host $host:8020; #注意, 原host必须配置, 否则传递给后台的值是websocket,端口如果没有输入的话会是80, 这会导致连接失败        proxy_http_version 1.1;        proxy_set_header Upgrade $http_upgrade;        proxy_set_header Connection "Upgrade";    }}
upstream websocket {    server 192.168.100.10:8081;} 经上述调整后,websocket就可以同时支持通过nginx代理的https协议,结合MQ机制,可以做到B端实时推送、B端/C端实时通信。 nginx的https(自动跳转http->https)+nginx+websocket的完整配置可参考http://www.cnblogs.com/zhjh256/p/6262620.html。

转载于:https://www.cnblogs.com/zhjh256/p/6052102.html

你可能感兴趣的文章
问卷调查
查看>>
ImageView的常用属性
查看>>
关于sso单点登录以及通过路径直接访问Servlet
查看>>
提高服务存活率-----定时唤醒,灰度进程
查看>>
服务器内访问laravel框架 404错误(宝塔)
查看>>
在Form_Load里面调用Focus无效
查看>>
HttpContext.GetOwinContext().Authentication 报错 解决办法
查看>>
三十七、将背景图分成多份
查看>>
SpringCloud服务提供者
查看>>
apache常用配置
查看>>
JS匿名执行函数
查看>>
关于InputStream类的available()方法
查看>>
六边形架构模式
查看>>
HAOI2007 理想的正方形 单调队列
查看>>
(原创)c#学习笔记04--流程控制04--循环03--for循环
查看>>
从控制台输入一个五位数,计算各个数位之和
查看>>
为Sublime Text 3设置优雅的字体
查看>>
Eclipse使用Jetty(转)
查看>>
vim命令收集(持续中)
查看>>
Zynq -- 启动过程
查看>>