1.背景:
最近由于工做须要在倒腾JEECG,JEECG是一款基于代码生成器的快速开发平台,功能是作得挺不错的,可是历史真是有点久远了,使用的框架是SpringMVC+Spring+Hibernate。然而如今早已经是微服务遍地开花的时代。javascript
2.JEECG整合WebSocket的步骤:前端
(1)创建Handlerjava
@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拦截器web
@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)进行配置spring
@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结尾的。spring-mvc
(4)前端进行WebSocket链接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)以上四个步骤在网上均可以找到不少,我也是代码搬运工。完成以上四个步骤,运行出现:session
出现这个错误的缘由是:JEECG在web.xml对路径作了处理,以下:mvc
<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的作转发:app
<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的一些心路历程。