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的一些心路歷程。