1. 程式人生 > >我的第一個SpringMVC+WebSocket專案

我的第一個SpringMVC+WebSocket專案

最近學習到了websocket可以實現伺服器自動推送訊息的機制,但是我們本地專案獲取訊息都是通過輪巡的方式,借鑑了很多大神的資料搭建了一個SpringMVC+WebSocket專案.

1.pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>me.gacl</groupId>
    <artifactId>JavaWebSocket</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>JavaWebSocket Maven Webapp</name>
    <url>http://maven.apache.org</url>


    <properties>
        <!-- spring版本號 -->
        <spring.version>4.3.0.RELEASE  </spring.version>
    </properties>


    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>7.0</version>
        </dependency>

        <!-- spring核心包 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-oxm</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>


        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- websocket協議 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-websocket</artifactId>
            <version>4.1.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.websocket</groupId>
            <artifactId>javax.websocket-api</artifactId>
            <version>1.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.9.5</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.5</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
        <!-- websocket協議  end-->
    </dependencies>
    <build>
        <finalName>JavaWebSocket</finalName>
    </build>
</project>

2.web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
		  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext-*.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>spring-websocket</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/applicationContext-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>spring-websocket</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

3. 新建一個自己的HandShakeInterceptor類

HandShakeInterceptor是websocket握手攔截器,用於攔截websocket初始化連線的請求 

public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor {

    @Override
    public boolean beforeHandshake(ServerHttpRequest request,
                                   ServerHttpResponse response, WebSocketHandler wsHandler,
                                   Map<String, Object> attributes) throws Exception {
        System.out.println("Before Handshake");
        return super.beforeHandshake(request, response, wsHandler, attributes);
    }

    @Override
    public void afterHandshake(ServerHttpRequest request,
                               ServerHttpResponse response, WebSocketHandler wsHandler,
                               Exception ex) {
        System.out.println("After Handshake");
        super.afterHandshake(request, response, wsHandler, ex);
    }
}

4.WebSocketHandler介面主要是用來與websocket客戶端來進行互動的介面,Spring WebSocket提供了一些實現類,可以根據自己的需求進行選擇與重寫

public class HelloHandler extends TextWebSocketHandler {
    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
    //接收到客戶端訊息時呼叫
        System.out.println("text message: " + session.getId() + "-" + message.getPayload());
        String text = "收到訊息"+session.getId();
        session.sendMessage(new TextMessage(text.getBytes()));
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session)
            throws Exception {
        // 與客戶端完成連線後呼叫
        System.out.println("afterConnectionEstablished");
        System.out.println("getId:" + session.getId());
        System.out.println("getLocalAddress:" + session.getLocalAddress().toString());
        System.out.println("getTextMessageSizeLimit:" + session.getTextMessageSizeLimit());
        System.out.println("getUri:" + session.getUri().toString());
        System.out.println("getPrincipal:" + session.getPrincipal());
        session.sendMessage(new TextMessage("你好".getBytes()));
    }

    @Override
    public void handleTransportError(WebSocketSession session,
                                     Throwable exception) throws Exception {
// 訊息傳輸出錯時呼叫
        System.out.println("handleTransportError");
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session,
                                      CloseStatus closeStatus) throws Exception {
// 一個客戶端連線斷開時關閉
        System.out.println("afterConnectionClosed");
    }

    @Override
    public boolean supportsPartialMessages() {
// TODO Auto-generated method stub
        return false;
    }
} 

5.applicationContext-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:websocket="http://www.springframework.org/schema/websocket"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.1.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
    http://www.springframework.org/schema/websocket
    http://www.springframework.org/schema/websocket/spring-websocket-4.1.xsd">
    <context:annotation-config/>

    <!-- Enables the Spring MVC @Controller programming model -->
    <mvc:annotation-driven />
    <bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
    <bean class ="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" >
        <property name="messageConverters">
            <list>
                <ref bean="mappingJacksonHttpMessageConverter" />
            </list>
        </property>
    </bean>

    <context:component-scan base-package="com.uptop.websocket.mvcWebSocket"/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/view/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
    <!-- websocket訊息處理bean -->
    <bean id="HelloHandler" class="com.uptop.websocket.mvcWebSocket.HelloHandler"/>
    <websocket:handlers>
        <!-- 配置訊息處理bean和路徑的對映關係 -->
        <websocket:mapping path="/*" handler="HelloHandler"/>
        <!-- 配置握手攔截器 -->
        <websocket:handshake-interceptors>
            <bean class="com.uptop.websocket.mvcWebSocket.HandshakeInterceptor"/>
        </websocket:handshake-interceptors>
        <!-- 開啟sockjs,去掉則關閉sockjs -->
        <!--<websocket:sockjs/>-->
    </websocket:handlers>
    <!-- 配置websocket訊息的最大緩衝區長度 -->
    <bean class="org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean">
        <property name="maxTextMessageBufferSize" value="8192"/>
        <property name="maxBinaryMessageBufferSize" value="8192"/>
    </bean>
</beans>

6.index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>

<head lang="en">
    <meta charset="UTF-8">
    <script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>
    <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">
    <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
    <script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
    <script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
    <title>webSocket-測試使用者</title>
    <script type="text/javascript">
        $(function() {
            var websocket;
            if('WebSocket' in window) {
                console.log("此瀏覽器支援websocket");
                websocket = new WebSocket("ws://localhost:8282/hello");
            } else if('MozWebSocket' in window) {
                alert("此瀏覽器只支援MozWebSocket");
            } else {
                alert("此瀏覽器只支援SockJS");
            }
            websocket.onopen = function(evnt) {
                $("#tou").html("連結伺服器成功!")
            };
            websocket.onmessage = function(evnt) {
                $("#msg").html($("#msg").html() + "<br/>" + evnt.data);
            };
            websocket.onerror = function(evnt) {};
            websocket.onclose = function(evnt) {
                $("#tou").html("與伺服器斷開了連結!")
            }




            $('#send').click(function(){
                send();
            });

            function send() {
                if(websocket != null) {
                    var message = document.getElementById('message').value;
                    websocket.send(message);
                } else {
                    alert('未與伺服器連結.');
                }
            }
        });
    </script>
</head>

<body>
<div class="page-header" id="tou">
    webSocket多終端聊天測試
</div>
<div class="well" id="msg"></div>
<div class="col-lg">
    <div class="input-group">
        <input type="text" class="form-control" placeholder="傳送資訊..." width="10" id="message">
        <span class="input-group-btn">
                    <button class="btn btn-default" type="button" id="send" >傳送</button>
                </span>
    </div>
</div>
</body>

</html>

參考:https://blog.csdn.net/stickallthetime/article/details/44587413