工欲善其事,必先利其器
Maven依赖的Spring-websocket的jar
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-websocket</artifactId>
- <version>4.0.6.RELEASE</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-messaging</artifactId>
- <version>4.0.6.RELEASE</version>
- </dependency>
spring-websocket核心类是:WebSocketConfig
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd">
- <bean id="websocket" class="com.lgy.websocket.SystemWebSocketHandler" />
- <websocket:handlers>
- <websocket:mapping path="/webSocketServer" handler="websocket" />
- <websocket:handshake-interceptors>
- <bean class="com.lgy.interceptor.WebSocketHandshakeInterceptor" />
- </websocket:handshake-interceptors>
- </websocket:handlers>
- </beans>
等价于:
- @Configuration
- //@EnableWebMvc//这个标注可以不加,如果有加,要extends WebMvcConfigurerAdapter
- @EnableWebSocket
- public class WebSocketConfig implements WebSocketConfigurer {
- @Override
- public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
- registry.addHandler(chatMessageHandler(),"/websocket/chatMessageServer.do").addInterceptors(new ChatHandshakeInterceptor());
- registry.addHandler(chatMessageHandler(), "/sockjs/chatMessageServer.do").addInterceptors(new ChatHandshakeInterceptor()).withSockJS();
- }
- @Bean
- public TextWebSocketHandler chatMessageHandler(){
- return new ChatMessageHandler();
- }
- }
- <!-- websocket相关扫描,主要扫描:WebSocketConfig.java 这个类路径 -->
- <context:component-scan base-package="com.lgy.websocket"/>
- <mvc:annotation-driven/>
在此我学会了@Configuration和@Bean注解的意义:
@Configuration的意义在于:项目启动的时候Spring会初始化该类,能被Spring加载到它的工程中
@Bean的意义在于通过new 出来的实例对象被Spring来进行管理
a.由核心配置文件带来的第二个类就是拦截器:
- package com.lgy.interceptor;
- import java.util.Map;
- import org.springframework.http.server.ServerHttpRequest;
- import org.springframework.http.server.ServerHttpResponse;
- import org.springframework.stereotype.Repository;
- import org.springframework.web.socket.WebSocketHandler;
- import org.springframework.web.socket.server.HandshakeInterceptor;
- import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
- @Repository
- public class WebSocketHandshakeInterceptor extends HttpSessionHandshakeInterceptor {
- public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
- Map<String, Object> attributes) throws Exception {
- System.out.println("握手之前····");
- return super.beforeHandshake(request, response, wsHandler, attributes);
- }
- public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
- Exception exception) {
- System.out.println("握手之后····");
- super.afterHandshake(request, response, wsHandler, exception);
- }
- }
在每次建立长连接的时候,都会进行2次握手,握手成功后方建立连接。
b.这个处理类和客户端差不多,服务端建立连接,断开连接,接受消息,发送消息
- package com.lgy.websocket;
- import java.io.IOException;
- import java.util.Set;
- import java.util.concurrent.CopyOnWriteArraySet;
- import java.util.logging.Logger;
- import org.springframework.stereotype.Repository;
- import org.springframework.web.socket.CloseStatus;
- import org.springframework.web.socket.TextMessage;
- import org.springframework.web.socket.WebSocketHandler;
- import org.springframework.web.socket.WebSocketMessage;
- import org.springframework.web.socket.WebSocketSession;
- import org.springframework.web.socket.handler.TextWebSocketHandler;
- public class SystemWebSocketHandler extends TextWebSocketHandler {
- private static final Logger logger;
- private static final Set<WebSocketSession> connections;
- static {
- logger = Logger.getLogger(SystemWebSocketHandler.class.getName());
- connections = new CopyOnWriteArraySet<WebSocketSession>();
- }
- /**
- * 接受消息
- */
- @Override
- protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
- System.out.println("handleTextMessage");
- session.sendMessage(message);
- }
- /**
- * 连接成功时候,会触发UI上onopen方法
- */
- @Override
- public void afterConnectionEstablished(WebSocketSession session) throws Exception {
- System.out.println("connect to the websocket success......");
- connections.add(session);
- // 这块会实现自己业务,比如,当用户登录后,会把离线消息推送给用户
- TextMessage returnMessage = new TextMessage("你大爷");
- SystemWebSocketHandler.sendMessageToUsers(returnMessage);
- }
- /**
- * 用户关闭连接时候
- */
- @Override
- public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
- logger.info("websocket connection closed......");
- connections.remove(session);
- }
- /**
- * 给所有在线用户发送消息
- *
- * @param message
- */
- public static void sendMessageToUsers(TextMessage message) {
- for (WebSocketSession user : connections) {
- try {
- if (user.isOpen()) {
- user.sendMessage(message);
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
整合差不多结束了!
web.xml
- <!DOCTYPE web-app PUBLIC
- "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
- "http://java.sun.com/dtd/web-app_2_3.dtd" >
- <web-app>
- <display-name>Archetype Created Web Application</display-name>
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>
- classpath*:websocket/spring-websocket.xml
- </param-value>
- </context-param>
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
- <servlet>
- <servlet-name>springMVC</servlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
- <init-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>classpath:springmvc/spring-mvc.xml</param-value>
- </init-param>
- </servlet>
- <servlet-mapping>
- <servlet-name>springMVC</servlet-name>
- <url-pattern>/</url-pattern>
- </servlet-mapping>
- </web-app>
springMVC
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- 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/aop http://www.springframework.org/schema/aop/spring-aop.xsd
- http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
- <!-- 启动SpringMVC Controller的注解功能,完成请求和注解POJO的映射 -->
- <context:component-scan base-package="com.lgy.controller" />
- <!-- 静态资源映射 -->
- <mvc:resources mapping="/js/**" location="/js/" />
- <!-- 默认的视图解析器 在上边的解析错误时使用 (默认使用html)- -->
- <bean id="defaultViewResolver"
- class="org.springframework.web.servlet.view.InternalResourceViewResolver">
- <property name="viewClass"
- value="org.springframework.web.servlet.view.JstlView" />
- <property name="prefix" value="/WEB-INF/jsp/" />
- <property name="suffix" value=".jsp" />
- </bean>
- </beans>
源码下载地址:https://git.oschina.net/fengchao111/spring-websocket
在网上找了很多demo,都是差不多的,但是很感谢这两个贴主:
http://blog.csdn.net/yxb19870428vv/article/details/41495543