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


bluesnail95
69 声望6 粉丝

Java开发工程师


« 上一篇
ZooKeeper学习
下一篇 »
Redis学习