JEECG整合WebSocket

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)以上四個步驟在網上都可以找到很多,我也是代碼搬運工。完成以上四個步驟,運行出現:

404

出現這個錯誤的原因是: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)運行,已經成功連接了。

open

(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,如下:

sendMessageToUsers

運行結果:

onmessage

以上就是自己在折騰JEECG整合WebSocket的一些心路歷程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章