国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

springMVC結合websocket小結

2019-11-06 06:02:10
字體:
來源:轉載
供稿:網友

由于瀏覽器的歷史遺留性問題,不是所有的瀏覽器都是支持WebSocket的,尤其是IE10以下,所以才出現了SockJS這樣一個框架,它的原理也很簡單,就是如果你的瀏覽器支持WebSocket那么他就使用webSocket協議通信,入股不支持就使用流傳輸或者輪詢的方式,這樣也保證了資源的最大利用率。

1、websocket相關pom文件配置

<!--websocket--><!-- PRovided Websocket API, because tomcat has its own implementation --><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-websocket</artifactId>    <version>4.3.3.RELEASE</version></dependency><dependency>    <groupId>javax.servlet</groupId>    <artifactId>javax.servlet-api</artifactId>    <version>3.1.0</version>    <scope>provided</scope></dependency><!--相關jar--><!-- Json --><dependency>    <groupId>com.fasterxml.jackson.core</groupId>    <artifactId>jackson-core</artifactId>    <version>2.8.1</version></dependency><dependency>    <groupId>com.fasterxml.jackson.core</groupId>    <artifactId>jackson-databind</artifactId>    <version>2.8.1</version>

2、WebSocketConfig----配置WebSocket訪問的地址

package com.bms.web.notice.websocket.config;import com.bms.web.notice.websocket.handler.SystemWebSocketHandler;import com.bms.web.notice.websocket.interceptor.WebsocketHandshakeInterceptor;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;import org.springframework.web.servlet.config.annotation.EnableWebMvc;import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;import org.springframework.web.socket.WebSocketHandler;import org.springframework.web.socket.config.annotation.EnableWebSocket;import org.springframework.web.socket.config.annotation.WebSocketConfigurer;import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;import org.springframework.web.socket.server.HandshakeInterceptor;/** * Created by zhu_kai1 on 2017/2/23. */@Configuration@EnableWebMvc@EnableWebSocketpublic class WebsocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {    // webSocket    private static final String WEBSOCKET_SERVER ="/webSocketServer";    private static final String ECHO ="/echo";    // 不支持webSocket的話用sockjs    private static final String SOCKJS ="/sockjs/webSocketServer";    @Override    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {        //支持websocket 的訪問鏈接        registry.addHandler(systemWebSocketHandler(), WEBSOCKET_SERVER).addInterceptors(handshakeInterceptor());        registry.addHandler(systemWebSocketHandler(), ECHO).addInterceptors(handshakeInterceptor());        //不支持websocket的訪問鏈接        registry.addHandler(systemWebSocketHandler(), SOCKJS).addInterceptors(handshakeInterceptor()).withSockJS();    }    @Bean    public WebSocketHandler systemWebSocketHandler(){        return new SystemWebSocketHandler();    }    @Bean    public HandshakeInterceptor handshakeInterceptor(){        return new WebsocketHandshakeInterceptor();    }    // Allow serving HTML files through the default Servlet    @Override    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {        configurer.enable();    }}

3、HandshakeInterceptor---握手攔截器

package com.bms.web.notice.websocket.interceptor;import com.msk.sso.client.bean.User;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.http.server.ServerHttpRequest;import org.springframework.http.server.ServerHttpResponse;import org.springframework.http.server.ServletServerHttpRequest;import org.springframework.web.socket.WebSocketHandler;import org.springframework.web.socket.server.HandshakeInterceptor;import javax.servlet.http.HttpServletRequest;import java.util.Map;/** * Created by zhu_kai1 on 2017/2/23. */public class WebsocketHandshakeInterceptor implements HandshakeInterceptor{    private static Logger logger = LoggerFactory.getLogger(WebsocketHandshakeInterceptor.class);    public WebsocketHandshakeInterceptor() {    }    // 初次握手訪問前    @Override    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {        if (request instanceof ServletServerHttpRequest) {            HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();            //使用userName區分WebSocketHandler,以便定向發送消息            User loginUser= (User) servletRequest.getsession().getAttribute("loginUser");            //存入數據,方便在hander中獲取,這里只是在方便在webSocket中存儲了數據,并不是在正常的httpSession中存儲,想要在平時使用的session中獲得這里的數據,需要使用session 來存儲一下            if(null !=loginUser){                map.put("userName", loginUser.getUserLogin());                logger.info("當前的登陸者為:{}", loginUser.getUserLogin());            }else{                logger.error("沒有獲取session中的當前登陸者信息");            }        }        return true;    }    @Override    public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {    }}

4、SystemWebSocketHandler----消息處理

package com.bms.web.notice.websocket.handler;import com.bms.web.notice.bean.result.NoticeResult;import com.bms.web.notice.service.CommonService;import com.framework.base.rest.result.BaseRestPaginationResult;import com.framework.core.utils.StringUtils;import com.framework.exception.SystemException;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import org.springframework.web.socket.*;import java.io.IOException;import java.util.ArrayList;import java.util.Collections;import java.util.List;/** * Created by zhu_kai1 on 2017/2/23. */@Componentpublic class SystemWebSocketHandler implements WebSocketHandler {    @Autowired    private  CommonService commonService;    public static final String USERNAME = "userName";    private static Logger logger = LoggerFactory.getLogger(SystemWebSocketHandler.class);    protected final static List<WebSocketSession> sessions = Collections.synchronizedList(new ArrayList<WebSocketSession>());    public SystemWebSocketHandler() {    }    // 連接建立后處理    @Override    public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {        logger.info("webSocket連接已建立");        sessions.add(webSocketSession);        String userLogin = (String) webSocketSession.getAttributes().get(USERNAME);        BaseRestPaginationResult<NoticeResult> result = null;        if(StringUtils.isNotEmpty(userLogin)){            result = commonService.getNoticeInfo(userLogin);        }        if(null !=result){            sendMessageToAll(new TextMessage(StringUtils.toString(result.getTotal())));        }    }    // 接收客戶端消息,并發送出去    @Override    public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {        logger.info("發送消息" + webSocketMessage.toString());    }    // 拋出異常時處理    @Override    public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {        if (webSocketSession.isOpen()) {            webSocketSession.close();        }        sessions.remove(webSocketSession);        logger.info("webSocket異常處理" + throwable.getMessage());        throw new SystemException(throwable);    }    // 連接關閉后處理    @Override    public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {        logger.info("webSocket連接已關閉......" + closeStatus.getReason());        sessions.remove(webSocketSession);    }    @Override    public boolean supportsPartialMessages() {        return false;    }    /**     * 給所有在線用戶發送消息     *     * @param message     */    public void sendMessageToAll(TextMessage message) {        for (WebSocketSession session : sessions) {            try {                if (session.isOpen()) {                    session.sendMessage(message);                }            } catch (IOException e) {                throw new SystemException(e.getMessage());            }        }    }}

5、在對應的spring-mvc.xml配置文件中需要掃描websocketConfig

 <context:component-scan base-package="com.bms.web" use-default-filters="false">        <context:include-filter type="regex" expression="com/.bms/.web/.notice/.websocket/..*"/>    </context:component-scan>

6、jsp需要引用對應的sockjs

<script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>

7、js調用方法

webSocket: function () {        var host = window.location.host;        var websocket;        var url = null;        if ('WebSocket' in window) {            url = "ws://" + host + Main.contextPath + "/webSocketServer";            websocket = new WebSocket(url);        } else if ('MozWebSocket' in window) {            url = "ws://" + host + Main.contextPath + "/echo";            websocket = new MozWebSocket(url);        } else {            url = Main.contextPath + "/sockjs/webSocketServer";            websocket = new SockJS(url);//建立連接        }        websocket.onopen = function (event) {        };        websocket.onmessage = function (event) {            $("span#noticeTotal").text(event.data);            $("span#notice").text("共" + event.data + "條通知");        };        websocket.onerror = function (event) {        };        websocket.onclose = function (event) {            $.alertMessage.error("與webSocket服務器斷開了連接");        }    }ok,到此大致的websocket已搭建好,但是各位可能會遇到以下問題,請找到對應的錯誤解決,以下解決方法也是從網上查詢到的。

問題1:統計了一下大家遇到第一個問題就是連接websocket時候報404錯誤

先檢查連接websocket的url格式:ws://localhost:8080/web/webSocketServer,這個webSocketServer要匹配websocketConfig中的

registry.addHandler(systemWebSocketHandler(), "/webSocketServer").addInterceptors(handshakeInterceptor());

其次檢查下Spring配置文件是否有加這個tag:<mvc:annotation-driven/>(加這個會出現中文亂碼,下面會講到),使用Spring websocket需要這個tag支持

當Spring配置文件有使用<context:component-scan/>掃描包,這個tag<context:annotation-config/>可以不去掉。

問題2:連接websocket時候報200,說明已經進入攔截器握手成功,但是沒連接上websocket

如果websocket有配置自己定義的攔截器,先檢查下攔截器beforeHandshake這個方法,這個方法有個參數Map<String, Object> attributes,不能給這個map的value設成null,否則進不到自己Handler下的這個方法afterConnectionEstablished,就會報200

問題3:連接websocket時候,如果缺少配置會報415 Unsupported Media Type請求的格式不受請求頁面的支持錯誤

當用戶發送請求后,@Requestbody 注解會讀取請求body中的數據,默認的請求轉換器HttpMessageConverter通過獲取請求頭Header中的Content-Type來 確認請求頭的數據格式,從而來為請求數據適配合適的轉換器。例如contentType:applicatin/json,那么轉換器會適配 MappingJacksonHttpMessageConverter。響應時候的時候同理,@Responsebody注解會啟用 HttpMessageConverter,通過檢測Header中Accept屬性來適配的響應的轉換器。

當在使用SpringMVC做服務器數據接收時,尤其是在做Ajax請求的時候,尤其要注意contentType屬性,和accepte 屬性的設置,在springmvc-config.xml中配置好相應的轉換器。

添加相應轉換器:

<bean id="stringHttpMessageConverter"        class="org.springframework.http.converter.StringHttpMessageConverter">        <property name="supportedMediaTypes">            <list>                <value>text/plain;charset=UTF-8</value>            </list>        </property></bean>

<bean        class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">        <property name="messageConverters">            <list>                <ref bean="stringHttpMessageConverter" />新增的                <ref bean="byteArrayHttpMessageConverter" />                <ref bean="jsonHttpMessageConverter" />                <ref bean="jsonHttpMessageConverter4JS" />            </list>        </property>    </bean>

問題4:網上例子都有說要在web.xml下的servlet和filter里面加上<async-supported>true</async-supported>

沒有影響websocket是可以連接成功的(小編就是這種方式實現的),可以不用加,這個是用來支持異步的servlet3.x,建議不用加,除非有用到這個特性(小編沒有試,這個可以自行對比下)

問題5:添加<mvc:annotation-driven/>這個出現中文亂碼

剛開始時候,所有瀏覽器都出現中文亂碼,后來解決在Chrome瀏覽不會出現中文亂碼,但是在FF下會出現。原因有三個:第一,MessageConverter轉換器沒配置相應的<property name="supportedMediaTypes">屬性,第二,bean和tag的先后順序不對,第三,當使用<mvc:annotation-driven/>這個tag時候,請求處理器就會變成RequestMappingHandlerAdapter,跟進代碼就會發現不是采用AnnotationMethodHandlerAdapter,所以配置時候要改成:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter統一解決辦法是:要注意bean和tag的先后順序<bean        class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">//這是根本原因        <property name="messageConverters">            <list>                <ref bean="stringHttpMessageConverter" />                <ref bean="byteArrayHttpMessageConverter" />                <ref bean="jsonHttpMessageConverter" />                <ref bean="jsonHttpMessageConverter4JS" />            </list>        </property>    </bean><context:component-scan base-package="掃描Spring controller包路徑" /><context:component-scan base-package="掃描websocket包路徑"/><context:annotation-config />  //這個標注可以不加<mvc:annotation-driven/>//這個tag一定要放在上面代碼最后,這是也是亂碼根源之一

問題6:啟動時候出現這個Factory method 'webSocketHandlerMapping' threw exception; nested exception isjava.lang.IllegalStateException: No suitable default RequestUpgradeStrategy found

 

說明你的容器不支持websocket協議Tomcat7,0.26之后才支持websocket

Jboss as 7不支持websocket,需要要安裝插件,可以直接升級到wildfly8支持websocket

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 淅川县| 台南县| 虞城县| 桐庐县| 崇阳县| 荃湾区| 邓州市| 临朐县| 锦屏县| 洮南市| 昭通市| 宜阳县| 钟山县| 柳江县| 广宁县| 昭平县| 中超| 疏附县| 金秀| 全州县| 阿拉善右旗| 沙雅县| 长沙县| 台东县| 扬中市| 丰都县| 阿克| 新河县| 丰城市| 梁平县| 平塘县| 武邑县| 苏尼特右旗| 博湖县| 上虞市| 天全县| 望江县| 新干县| 鄄城县| 武邑县| 申扎县|