我爱编程

Spring Websocket No suitable def

2017-10-20  本文已影响538人  柳岸花开

前言

现在主流的web容器基本均已支持websocket,但各容器的websocket接口都不尽相同。为了统一websocket实现,便于今后在不同web容器间的移植,这里使用spring websocket框架集成。

spring依赖

添加spring所需依赖

<spring.framework.version>4.2.1.RELEASE</spring.framework.version>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${spring.framework.version}</version>
</dependency>

websocket依赖

对于jetty,添加如下依赖

<dependency>
    <groupId>org.eclipse.jetty.websocket</groupId>
    <artifactId>websocket-server</artifactId>
    <version>9.3.3.v20150827</version>
    <scope>provided</scope>
</dependency>

对于tomcat,添加如下依赖

<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-websocket</artifactId>
    <version>8.0.23</version>
    <scope>provided</scope>
</dependency>

对于上述jetty或者tomcat依赖,需要注意依赖版本与容器版本的兼容性,另一方面需要注意将依赖的scope设置为provided

添加Handler

添加HandshakeInterceptor

/**

}spring提供了多种HandshakeInterceptor实现,可以根据实际需要在其基础上实现自己的逻辑。当然,也可以直接使用spring的默认HandshakeInterceptor

添加WebSocketHandler

/**

spring同样提供了TextWebSocketHandler BinaryWebSocketHandler等多种WebSocketHandler,可根据实际需要进行选择

初始化websocket

websocket的初始化,可以使用配置方式,也可以使用注解方式,关于spring websocket的使用及配置,详见websocket-doc,这里记录注解方式初始化方法

/**

}

setAllowedOrigins用于约束允许建立连接的客户端
withSockJS用于提供SockJS支持

至此,websocket后台框架便搭建完成
javascript可使用如下方式与后台建立连接进行通信

/* 建立连接 /
var ws = new WebSocket("ws://localhost/rasp/websocket/doubanfm");
ws.onopen = function() { /
连接成功时 /
ws.send(JSON.stringify({signal:'C_START', message:'179'}));
};
ws.onmessage = function (evt){ /
收到消息时 /
var received_msg = evt.data;
console.info("Message is received... " + received_msg);
};
ws.onclose = function() { /
连接断开时 /
console.warn("Connection is closed...");
};
ws.onerror = function(e) { /
出现错误时 */
console.error(e);
}

开发时遇到的异常及解决办法
•No suitable default RequestUpgradeStrategy found

严重: Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘webSocketHandlerMapping’ defined in class path resource [org/springframework/web/socket/config/annotation/DelegatingWebSocketConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method ‘webSocketHandlerMapping’ threw exception; nested exception is java.lang.IllegalStateException: No suitable default RequestUpgradeStrategy found
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1111)
at …
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method ‘webSocketHandlerMapping’ threw exception; nested exception is java.lang.IllegalStateException: No suitable default RequestUpgradeStrategy found
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
at …
Caused by: java.lang.IllegalStateException: No suitable default RequestUpgradeStrategy found
at org.springframework.web.socket.server.support.DefaultHandshakeHandler.initRequestUpgradeStrategy(DefaultHandshakeHandler.java:127)
at …

出现上述异常,是由于缺少RequestUpgradeStrategy
对于jetty,需要添加如下依赖

<dependency>
    <groupId>org.eclipse.jetty.websocket</groupId>
    <artifactId>websocket-server</artifactId>
    <version>9.3.3.v20150827</version>
    <scope>provided</scope>
</dependency>

对于tomcat,需要添加如下依赖

<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-websocket</artifactId>
    <version>8.0.23</version>
    <scope>provided</scope>
</dependency>

•java.lang.ClassCastException: org.eclipse.jetty.server.HttpConnection cannot be cast to org.eclipse.jetty.server.HttpConnection

页面报如下异常

WebSocket connection to ‘ws://localhost/rasp/websocket/doubanfm’ failed: Error during WebSocket handshake: Unexpected response code: 500

后台报如下异常

WARN:oejs.ServletHandler:qtp1237514926-20:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.web.socket.server.HandshakeFailureException: Uncaught failure for request http://localhost:80/rasp/websocket/doubanfm; nested exception is java.lang.ClassCastException: org.eclipse.jetty.server.HttpConnection cannot be cast to org.eclipse.jetty.server.HttpConnection
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
at …
Caused by:
org.springframework.web.socket.server.HandshakeFailureException: Uncaught failure for request http://localhost:80/rasp/websocket/doubanfm; nested exception is java.lang.ClassCastException: org.eclipse.jetty.server.HttpConnection cannot be cast to org.eclipse.jetty.server.HttpConnection
at org.springframework.web.socket.server.support.WebSocketHttpRequestHandler.handleRequest(WebSocketHttpRequestHandler.java:135)
at …
Caused by:
java.lang.ClassCastException: org.eclipse.jetty.server.HttpConnection cannot be cast to org.eclipse.jetty.server.HttpConnection
at org.eclipse.jetty.websocket.server.WebSocketServerFactory.acceptWebSocket(WebSocketServerFactory.java:182)
at …

出现此情况,一般是由于工程中引用的javax.servlet与web容器相关jar包冲突导致
将javax.servlet相关依赖scope置为provided即可

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <scope>provided</scope><!-- 只在编译的时候 -->
</dependency>

•Unexpected response code: 403

页面报此异常,一般是由于websocket拒绝了此链接请求
在websocket初始化时,将setAllowedOrigins加上即可

上一篇下一篇

猜你喜欢

热点阅读