1.背景:
最近因为工作需要在倒腾JEECG,JEECG是一款基于代码生成器的快速开发平台,功能是做得挺不错的,但是历史真是有点久远了,使用的框架是SpringMVC+Spring+Hibernate。然而现在早已是微服务遍地开花的时代。
2.JEECG整合WebSocket的步骤:
(1)建立Handler
@Component
public class WebSocketHandler extends AbstractWebSocketHandler {
private static final ArrayList<WebSocketSession> users;
private Logger logger = LoggerFactory.getLogger(WebSocketHandler.class);
static {
users = new ArrayList<WebSocketSession>();
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
users.add(session);
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
users.remove(session);
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
super.handleTextMessage(session, message);
}
public void sendMessgaeToUsers(TextMessage message) {
for(WebSocketSession session:users) {
if(session.isOpen()) {
try {
session.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
(2)建立Interceptor拦截器
@Component
public class WebSocketHandshakeInterceptor implements HandshakeInterceptor {
private static final Logger logger = LoggerFactory.getLogger(WebSocketHandshakeInterceptor.class);
@Override
public boolean beforeHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
return true;
}
@Override
public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
}
}
(3)进行配置
@Configuration
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
private static final Logger logger = LoggerFactory.getLogger(WebSocketConfig.class);
@Resource
private WebSocketHandler webSocketHandler;
@Resource
private WebSocketHandshakeInterceptor webSocketHandshakeInterceptor;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
webSocketHandlerRegistry.addHandler(webSocketHandler,"/webSocketHandler.ws")
.addInterceptors(webSocketHandshakeInterceptor);
webSocketHandlerRegistry.addHandler(webSocketHandler,"/sockjs/webSocketHandler.ws")
.addInterceptors(webSocketHandshakeInterceptor).withSockJS();
}
@Bean
public ServletServerContainerFactoryBean createWebSocketContainer() {
ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
container.setMaxTextMessageBufferSize(8192*4);
container.setMaxBinaryMessageBufferSize(8192*4);
return container;
}
}
** 我这里的路径/webSocketHandler.ws是以.ws结尾的。
(4)前端进行WebSocket连接
<script src="sockjs.js"></script>
<script type="text/javascript">
var websocket;
if ('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:9999/webSocketHandler.ws");
} else if ('MozWebSocket' in window) {
websocket = new MozWebSocket("ws://localhost:9999/webSocketHandler.ws");
} else {
websocket = new SockJS("http://localhost:9999/sockjs/webSocketHandler.ws");
}
websocket.onopen = function (evnt) {
console.log("open");
};
websocket.onmessage = function (evnt) {
console.log(evnt);
};
websocket.onerror = function (evnt) {
console.log("error");
};
websocket.onclose = function (evnt) {
console.log("close");
}
</script>
(5)以上四个步骤在网上都可以找到很多,我也是代码搬运工。完成以上四个步骤,运行出现:
出现这个错误的原因是:JEECG在web.xml对路径做了处理,如下:
<servlet>
<description>spring mvc servlet</description>
<servlet-name>springMvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<description>spring mvc 配置文件</description>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>springMvc</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
这里的路径只对后缀是.do和前缀是rest的做了转发,所以在这里需要添加一个servlet-mapping对后缀是.ws的做转发:
<servlet-mapping>
<servlet-name>springMvc</servlet-name>
<url-pattern>*.ws</url-pattern>
</servlet-mapping>
(6)再运行出现:
后台出现如下问题:
javax.servlet.ServletException: No adapter for handler [org.springframework.web.socket.server.support.WebSocketHttpRequestHandler@44ae9ca8]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler
at org.springframework.web.servlet.DispatcherServlet.getHandlerAdapter(DispatcherServlet.java:1141)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:917)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
需要在spring-mvx.xml添加以下标签:
<mvc:annotation-driven/>
(7)接着运行,后台出现以下问题:
java.lang.ClassCastException: org.springframework.web.socket.server.support.WebSocketHttpRequestHandler cannot be cast to org.springframework.web.method.HandlerMethod
JEECG定义了一个AuthInterceptor对路径进行登录权限拦截:
AuthInterceptor类的preHandle方法默认是对请求类的方法进行处理,而我这里定义的.ws后缀是不符合这里的格式的,在spring-mvc.xml对AuthInterceptor的拦截路径进行处理:
添加<mvc:exclude-mapping path="/*.ws"/>,对WebSocket的请求路径不做拦截。
(8)运行,已经成功连接了。
(9)建立一个测试类,进行后台消息推送:
@Controller
@RequestMapping("/webSocketController")
public class WebSocketController {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Resource
private WebSocketHandler webSocketHandler;
@RequestMapping(params = "sendMessage")
@ResponseBody
public void sendMessage(String message) {
message = "Hello,world";
TextMessage textMessage = new TextMessage(message);
webSocketHandler.sendMessgaeToUsers(textMessage);
}
}
访问http://localhost:9999/webSocketController.do?sendMessage,如下:
运行结果:
以上就是自己在折腾JEECG整合WebSocket的一些心路历程。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。