Spring4配置websocket,基于xml从零(0)开始

文章的最后会提供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;
 
classpath:spring-websocket.xml

</param-value></context-param><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> <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><async-supported>true</async-supported></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包(自动注入) -->
	<context:component-scan base-package="com.sirding" >
		<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> 
	</context:component-scan>
	<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的控制器 -->
	<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>
  	<task:annotation-driven/>  <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>
  	<task:annotation-driven/>  
    
    <!-- 配置解析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>

 <!-- 配置解析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了,具体会配置到的问题可以参考另一篇文章SpringMVC引入静态org.webjars中资源404_程序员的蜕变-CSDN博客_引入webjars ,这里有关于webjars使用的详细说明。

	<mvc:annotation-driven/>
    	<mvc:default-servlet-handler/><mvc:annotation-driven/>
    	<mvc:default-servlet-handler/>

此处重点说一下,上面的两行配置,如果你的spring-mvc.xml中是I用<mvc:resource>的配置,那么项目启动后控制台没有但是访问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);
        });
    });
} 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,如果不仔细看很容易掉进坑里.....

java-ws是基于项目1和项目的简化与整合,将基于注解的方式转为基于xml的方式,实例很简单,但足以方便的整合到现有的项目,相信你接触的项目都是基于xml配置的。

资源地址如下(不需要下载积分)

java-ws:  http://download.csdn.net/detail/chao_1990/9701661

其余两个项目  http://download.csdn.net/detail/chao_1990/9701666
spring静态资源引用文章地址  http://blog.csdn.net/chao_1990/article/details/53449494

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值