文章出處

文章的最后會提供demo程序,總共有三個實例程序

1、gs-messaging-stomp-websocket:基于請求與響應的websocket實例,基于注解。

2、spring-websocket-portfolio:server定時廣播消息,也可通過請求與響應進行websocket通信,基于注解配置。來源于github開源項目。前端用了angularjs不利于新手閱讀。

3、java-ws:server :端定時廣播、客戶端與服務端請求與響應的websocket通信;基于xml配置。前端是簡單javascript腳本,方便理解閱讀、純基礎的內容,主要說明在整合配置中碰到的問題和解決辦法。

這里主要說明java-ws基于xml配置過程,如果是基于注解請看1、2實例,所有的項目都是maven的項目。

1、運行環境

tomcat 7+或jetty9+(jetty低版本應該也可以,本人用的9+,這里也著重著重說明9+碰到的問題)

servlet3+(java-ws中使用的是servlet3.1)

jdk1.6+(java-ws中用的jdk1.8)

2、環境及項目的配置這里不再詳細說明,直接說配置項目

web.xml

<?xml version="1.0" encoding="UTF-8"?>  <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xmlns="http://xmlns.jcp.org/xml/ns/javaee"        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"        id="WebApp_ID" version="3.1">            <display-name>java-sm</display-name>        <context-param>          <param-name>contextConfigLocation</param-name>          <param-value>              classpath:spring-core.xml          </param-value>      </context-param>            <span style="color:#330099;"><context-param>            <param-name>spring.profiles.active</param-name>            <param-value>dev</param-value>        </context-param>        <context-param>            <param-name>spring.profiles.default</param-name>            <param-value>dev</param-value>        </context-param>      <context-param>            <param-name>spring.liveBeansView.mbeanDomain</param-name>            <param-value>dev</param-value>        </context-param> </span>           <listener>          <description>初始化Spring框架</description>          <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>      </listener>            <servlet>          <description>加載SpringMVC配置信息</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>2</load-on-startup>          <span style="color:#ff0000;"><strong><async-supported>true</async-supported></strong></span>      </servlet>      <servlet-mapping>          <servlet-name>springMvc</servlet-name>          <url-pattern>/</url-pattern>      </servlet-mapping>        <!-- HttpSession的失效時間 -->      <session-config>          <session-timeout>20</session-timeout>      </session-config>      <welcome-file-list>          <welcome-file>time.jsp</welcome-file>      </welcome-file-list>  </web-app>

藍色的部分配置,項目啟動的過程中會拋出異常,但不影響程序;

注意紅色的部分,如果不配置項目啟動時會出現異常,有明確的提示需要添加此配置,至于原因自行查閱資料。

spring-core.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:aop="http://www.springframework.org/schema/aop" xmlns:c="http://www.springframework.org/schema/c" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:task="http://www.springframework.org/schema/task" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd          http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd          http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd          http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd          http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd          http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd          http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd          http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd          http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd          http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd          http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">           <!-- 自動掃描dao和service包(自動注入) -->      <span style="color:#ff0000;"><!-- <context:component-scan base-package="com.sirding" >          <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />       </context:component-scan> --></span>      <task:annotation-driven/>  </beans>

注意紅色的部分已被注釋掉,后面說明為什么要注釋掉以及如果不注釋需要做哪些更改。

spring-websocket.xml

<?xml version="1.0" encoding="UTF-8"?>  <beans xmlns="http://www.springframework.org/schema/beans"      xmlns:mvc="http://www.springframework.org/schema/mvc"       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:websocket="http://www.springframework.org/schema/websocket"            xsi:schemaLocation="http://www.springframework.org/schema/beans       http://www.springframework.org/schema/beans/spring-beans.xsd       http://www.springframework.org/schema/context       http://www.springframework.org/schema/context/spring-context.xsd       http://www.springframework.org/schema/mvc       http://www.springframework.org/schema/mvc/spring-mvc.xsd      http://www.springframework.org/schema/cache         http://www.springframework.org/schema/cache/spring-cache.xsd      http://www.springframework.org/schema/websocket       http://www.springframework.org/schema/websocket/spring-websocket.xsd  ">      <!-- 客戶端向服務端發送消息的前綴 對應 controller的mapping的@MessageMapping("/hello"),客戶端發送請求的地址為/app/hello -->      <websocket:message-broker application-destination-prefix="/app">          <!-- 此配置作為備選的切入點,如果客戶端不支持stomp協議,那么將通過sockjs通過如下入口進行數據交互   -->          <websocket:stomp-endpoint path="/myws">              <websocket:sockjs/>          </websocket:stomp-endpoint>          <!--  stomp-broker-relay 和 simple-broker 二者只能出現一次,具體約束見spring-websocket.xsd -->          <!-- <websocket:stomp-broker-relay prefix="/topic"/> -->          <!-- 返回消息的前綴,對應controller中的@SendTo("/topic/greetings")中前綴的是/topic的將接口 -->          <websocket:simple-broker prefix="/topic" />          <!-- 如下配置暫無實際需求 -->          <websocket:message-converters register-defaults="true">              <bean class="org.springframework.messaging.converter.StringMessageConverter"/>              <bean class="org.springframework.messaging.converter.ByteArrayMessageConverter"/>          </websocket:message-converters>      </websocket:message-broker>  </beans>

spring-mvc.xml配置是關鍵的配置也是坑最多的地方,各種問題都出現在這里,先看配置

<?xml version="1.0" encoding="UTF-8"?>  <beans xmlns="http://www.springframework.org/schema/beans"      xmlns:mvc="http://www.springframework.org/schema/mvc"       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:cache="http://www.springframework.org/schema/cache"       xmlns:task="http://www.springframework.org/schema/task"            xsi:schemaLocation="http://www.springframework.org/schema/beans       http://www.springframework.org/schema/beans/spring-beans.xsd       http://www.springframework.org/schema/context       http://www.springframework.org/schema/context/spring-context.xsd       http://www.springframework.org/schema/mvc       http://www.springframework.org/schema/mvc/spring-mvc.xsd      http://www.springframework.org/schema/cache         http://www.springframework.org/schema/cache/spring-cache.xsd      http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd  ">        <!-- 配置1: 自動掃描controller包下的所有類,使其認為spring mvc的控制器 -->      <span style="color:#ff0000;"><context:component-scan base-package="com.sirding" >          <!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />           <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />          <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository" /> -->      </context:component-scan></span>      <task:annotation-driven/>
<span style="color:#000099;"><import resource="spring-websocket.xml"/></span>                  <!-- 配置解析webjars資源 -->      <!-- <mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars/"> -->      <mvc:annotation-driven/>      <mvc:default-servlet-handler/>      <mvc:resources mapping="/resources/**" location="/resources/"/>      <mvc:resources mapping="/webjars/**" location="/webjars/">          <mvc:resource-chain resource-cache="true">              <mvc:resolvers>                  <bean class="org.springframework.web.servlet.resource.WebJarsResourceResolver"></bean>                  <bean class="org.springframework.web.servlet.resource.PathResourceResolver"></bean>              </mvc:resolvers>          </mvc:resource-chain>      </mvc:resources>            <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">          <description>初始化jsp視圖解析器 </description>          <property name="prefix" value="/WEB-INF/"></property>          <property name="suffix" value=".jsp"></property>          <property name="order" value="5"></property>      </bean>  </beans>

紅色部分:中間的有部分配置被注釋掉,如果取消注釋,那么spring-core中注釋的部分就要取消,這樣@Service的注解才能被識別,但是此時

package com.sirding.service;    import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.messaging.core.MessageSendingOperations;  import org.springframework.scheduling.annotation.Scheduled;  import org.springframework.stereotype.Service;    import com.sirding.domain.SimpleJson;  import com.sirding.util.DateUtil;    @Service  public class  AutoPub{        <span style="color:#ff0000;">@Autowired      private MessageSendingOperations<String> messagingTemplate;</span>            @Scheduled(fixedDelay=10000)      public void sendQuotes() {          System.out.println("廣播消息");          this.messagingTemplate.convertAndSend("/topic/getTime", new SimpleJson("time", DateUtil.getNow()));      }  }

紅色部分的自動注入就會在項目啟動時出現無法注入的異常,原因是spring-mvc.xml中藍色的配置是引入websocket配置地方,此時還沒有MessageSendingOperations對應的屬性因此Service注入屬性就會出現異常,如果將spring-mvc.xml中配置放入到spring-core.xml中,那么websocket相關對應的切入點、@MessageMapping將不能正常監聽。因此,如果一定要取消spring-core.xml中注解,只需要將MessageSendingOperations屬性的注入操作放到controller中即可,使用時在通過參數帶到Service層中即可。

【PS:此部分的配置,后期還會更新,本人覺得通過一些配置絕對可以解決注入的問題】

<!-- 配置解析webjars資源 -->     <!-- <mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars/"> -->     <mvc:annotation-driven/>     <mvc:default-servlet-handler/>     <mvc:resources mapping="/resources/**" location="/resources/"/>     <mvc:resources mapping="/webjars/**" location="/webjars/">      <mvc:resource-chain resource-cache="true">          <mvc:resolvers>              <bean class="org.springframework.web.servlet.resource.WebJarsResourceResolver"></bean>              <bean class="org.springframework.web.servlet.resource.PathResourceResolver"></bean>          </mvc:resolvers>      </mvc:resource-chain>     </mvc:resources>

Spring靜態資源的應用也是一個大坑,所有的實例的js庫都是通過jar映入的,webjars的官網上基本將所有主流的js庫封裝成了jar,好處就是通過配置達到不依賴具體版本,更新時只需要替換一下jar就ok了,具體會配置到的問題可以參考另一篇文章,這里有關于webjars使用的詳細說明。

<span style="white-space:pre">  </span><mvc:annotation-driven/>      <span style="white-space:pre">  </span><mvc:default-servlet-handler/> 

此處重點說一下,上面的兩行配置,如果你的spring-mvc.xml中是I用的配置,那么項目啟動后控制臺沒有但是訪問controller時十有八九會出現404的提示,后臺還沒有異常只是提示沒有對應的mappping,此時不放加上上述兩行配置,基本可以解決404的問題,如果你的項目中使用spring-security或是spring-oauth2.0,那么上面的配置可以放在security或是oauth2的配置文件中,一樣可以。

整個的配置情況就是這樣,按照上述配置只是第一步,還有第二步。

web容器的選擇及應用,這里只說明jetty9.3及tomcat8,文章開始的三個項目中項目1.直接運行main方法即可,項目2使用的內嵌的jetty,只需要執行mvn jetty:run或是mvn tomcat:run(沒有測試)即可,

這里著重說明項目3,首先應用ecplise中配置的jetty,啟動的過程中會出現如下異常:

java.lang.IllegalStateException: No suitable default RequestUpgradeStrategy found      at org.springframework.web.socket.server.support.AbstractHandshakeHandler.initRequestUpgradeStrategy(AbstractHandshakeHandler.java:143)      at org.springframework.web.socket.server.support.AbstractHandshakeHandler.<init>(AbstractHandshakeHandler.java:109)      at org.springframework.web.socket.server.support.DefaultHandshakeHandler.<init>(DefaultHandshakeHandler.java:35)      at org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService.getDefaultTransportHandlers(DefaultSockJsService.java:91)      at org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService.<init>(DefaultSockJsService.java:77)      at org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService.<init>(DefaultSockJsService.java:53)      at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)      at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)      at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)      at java.lang.reflect.Constructor.newInstance(Constructor.java:408)      at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:142)      at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:122)      at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:271)      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143)      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046)      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)      at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)      at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)      ..省略.....部分內容

沒有關系只是環境的問題,不應實例的運行,因此不用糾結,如果不想看到這個異常,那么就是用內嵌的jetty,通過mvn jetty:run運行即可。

pom.xml已經配置內嵌的jetty和tomcat及websocket依賴的相關jar,如果使用的是tomcat7+的版本直接部署運行即可。

最后說一下js端建立連接時可能出現的404情況,下面是建立連接的js腳本

function connect() {    var socket = new SockJS('/myws');    stompClient = Stomp.over(socket);    stompClient.connect({}, function (frame) {        console.log('===========Connected: ' + frame);        stompClient.subscribe('/topic/getTime', function (msg) {        console.log(msg);        showTime(JSON.parse(msg.body).value);        });    });}

注意紅色的部分,如果的你訪問項目時使用的url為http://localhost:8080/java-ws/time.jsp,那么紅色部分中的"/myws"應該改為"/java-ws/myws"。此處在是用jetty:run和tomcat分別運行時就會出現404,如果不仔細看很容易掉進坑里.....

function connect() {     <span style="color:#cc0000;"><strong> var socket = new SockJS('/myws');</strong></span>      stompClient = Stomp.over(socket);      stompClient.connect({}, function (frame) {          console.log('===========Connected: ' + frame);          stompClient.subscribe('/topic/getTime', function (msg) {              console.log(msg);              showTime(JSON.parse(msg.body).value);          });      });  }

java-ws是基于項目1和項目的簡化與整合,將基于注解的方式轉為基于xml的方式,實例很簡單,但足以方便的整合到現有的項目,相信你接觸的項目都是基于xml配置的。

就愛閱讀www.92to.com網友整理上傳,為您提供最全的知識大全,期待您的分享,轉載請注明出處。
歡迎轉載:http://www.kanwencang.com/bangong/20161216/71634.html

文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()