springmvc是怎样接受websocket请求的
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springmvc是怎样接受websocket请求的相关的知识,希望对你有一定的参考价值。
浏览器客户端和服务器建立起websocket的链接,最初也是http请求握手,通过httpServletRequest发送http请求到服务器,其中头部就包含需要请求websocket链接的一系列信息,大概过程如下1.客户端请求一个链接,头部中包含如下信息
GET /demo HTTP/1.1
Host: example.com
Connection: Upgrade
Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
Upgrade: WebSocket
Sec-WebSocket-Key1: 4@1 46546xW%0l 1 5
Origin: http://example.com
[8-byte security key]
2.服务器根据头部中的Sec-WebSocket-Key2,Sec-WebSocket-Key1,Upgrade,[8-byte security key] 知道客户端需要一个websocket协议链接,于是返回一个消息,包含如下头部
HTTP/1.1 101 WebSocket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
WebSocket-Origin: http://example.com
WebSocket-Location: ws://example.com/demo
[16-byte hash response]
3.客户端收到消息之后,建立起websocket链接,这时就可以进行实时通信了
我们可以定义一个处理器来实现WebSocketHandler处理请求
public class MyWebSocketHandler implements WebSocketHandler
/**
* webscoket建立好链接之后的处理函数
* @param session 当前websocket的会话id,打开一个websocket通过都会生成唯一的一个会话,可以通过该id进行发送消息到浏览器客户端
*/
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception
// TODO Auto-generated method stub
/**
* 客户端发送服务器的消息时,的处理函数,在这里收到消息之后可以分发消息
*/
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception
// TODO Auto-generated method stub
/**
* 消息传输过程中出现的异常处理函数
*/
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception
// TODO Auto-generated method stub
/**
* websocket链接关闭的回调
*/
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception
// TODO Auto-generated method stub
/**
* 是否支持处理拆分消息,返回true返回拆分消息
*/
@Override
public boolean supportsPartialMessages()
// TODO Auto-generated method stub
return false;
websocket的链接建立是基于http握手协议,我们可以添加一个拦截器处理握手之前和握手之后过程
public class MyHandShakeInterceptor implements HandshakeInterceptor
/**
* 握手之前,若返回false,则不建立链接
*/
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception
// TODO Auto-generated method stub
return true;
/**
* 握手之后
*/
@Override
public void afterHandshake(ServerHttpRequest requestscjgcj.comServerHttpResponse response, WebSocketHandler wsHandler,
Exception exception)
// TODO Auto-generated method stub
接下来,需要我们把处理器和拦截器注册到spring websocket中
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry)
registry.addHandler(new MyWebSocketHandler(), "/portfolio")//添加一个处理器还有定义处理器的处理路径
.addInterceptors(new MyHandShakeInterceptor())
.withSockJS();
在这里我们用到.withSockJS(),SockJS是spring用来处理浏览器对websocket的兼容性,目前浏览器支持websocket还不是很好,特别是IE11以下.SockJS能关键浏览器能否支持websocket来提供三种方式用于websocket请求,三种方式分别是 WebSocket, HTTP Streaming以及 HTTP Long Polling
SockJS提供了浏览器客户端的js库,在浏览器我们请求websocket就这么用
var socket = new SockJS('/whats/portfolio');//项目名称 + 处理器拦截路径名就会打开的目的websocket链接口
/**
* 建立成功的回调函数
*/
socket.onopen = function()
console.log('open');
;
/**
* 服务器有消息返回的回调函数
*/
socket.onmessage = function(e)
console.log('message', e.data);
;
/**
* websocket链接关闭的回调函数
*/
socket.onclose = function()
console.log('close');
;
然后客户端发送一个消息
document.getElementById("ws").onclick = function()
socket.send("fff");
服务器MyWebSocketHandler中,通过handlemessage接收消息并进行分发
/**
* 客户端发送服务器的消息时,的处理函数,在这里收到消息之后可以分发消息
*/
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception
//获取消息
String body = (String) message.getPayload();
//一系列的处理之后...
//发送消息
session.sendMessage(message);
session可以用来标注客户端id,相对于我们的httpsession,这样,如果我们想做一个精准推送和全部推送,我们可以这么做
首先在自定义的处理其中,建一个队列来存储连进来的websocketsession
public class MyWebSocketHandler implements WebSocketHandler
private List<WebSocketSession> users = new ArrayList<WebSocketSession>(); //存放WebSocketSession的队列
/**
* webscoket建立好链接之后的处理函数
* @param session 当前websocket的会话id,打开一个websocket通过都会生成唯一的一个会话,可以通过该id进行发送消息到浏览器客户端
*/
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception
session.getAttributes().put("userid", "xxxx");//如果有用户登录,可以把用户的id绑定到session里面,便于后面做精准推送
users.add(session); //每个链接来的客户端都把WebSocketSession保存进来
//...
然后呢,我们在接收到消息的时候,就可以直接的根据需要精准推送到用户或者全部推送了
/**
* 客户端发送服务器的消息时,的处理函数,在这里收到消息之后可以分发消息
*/
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception
// TODO Auto-generated method stub
for (WebSocketSession webSocketSession : users)
//Long id = (Long) session.getAttributes().get("userid");//可以通过获取userid进行匹配,从而进行精准推送
message = new TextMessage("ggg");
webSocketSession.sendMessage(message); //全部推送
spring websocket大概的请求过程就是这样子,这是基础的请求过程,细心的同学可能发现,如果我有很多种不同的业务请求,是不是要写很多个处理器??能不能只实现一个处理器,然后由这个处理器来进行分发处理,做到类似springmvc的DispatcherServlet那样子??下次研究看看 参考技术A 用node.js安装WebSocket库: npm install ws然后建立serve 参考技术B http://blog.csdn.net/yingxiake/article/details/51194125
SpringMVC
- 首先什么是MVC
MVC包含Model(模型层)、View(视图层)、Controller(控制层)三层,用户发送请求到Controller,Controller层接受请求、转发请求,委托Model层进行数据处理,Model层(模型层)处理请求,将结果返回给Controller层,Controller层将试图渲染交给View层完成, View返回jstl到Controller,Controller响应结果给用户。
2. SpringMVC是什么?
SpringMVC是一个web层的MVC框架,是Spring的一部分。
3. SpringMVC的执行过程
用户根据地址访问到web.xml中配置好的前端控制器(DispatcherServlet),前端控制器根据请求找到对应的处理器映射器(HandlerMapping),处理器映射器返回chain给前端控制器;再由前端控制器请求执行Controller,这一步首先通过由处理器映射器获取的chain找到处理器适配器(ControllerHandlerAdapter),由处理器适配器执行Controller并且返回ModelAndView到前端控制器;前端控制器将ModelAndView交给视图解析器(ViewResolver)解析视图,视图解析器将View传给前端控制器再交予View层进行渲染视图,最终响应用户。
4. 处理器映射器
4.1 BeanNameUrlHandlerMapping
功能:寻找Controller
根据url请求去匹配bean的name属性url,从而获取Controller
4.2 SimpleUrlHandlerMaping
功能:寻找Controller
根据浏览器url匹配简单url的key,key又Controller的id找到Controller
4.3 ControllerClassNameHandlerMapping
功能:寻找Controller
根据类名(MyController)类名.do来访问,类名首字母小写
5. 处理器适配器
5.1 SimpleControllerHandlerAdapter
功能:执行controller
调用controller里面方法,返回modelAndView。
5.2 HttpRequestHandlerAdapter
功能:执行controller
6.配置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>springMVC_01_self</display-name>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 如果将配置文件的名字写成:springmvc-servlet.xml,核心控制器可以自动找到并执行
1.名字必须是springmvc-servlet.xml 2.配置文件必须放在WEB-INF下面
-->
<init-param>
<!-- 7.核心控制器会根据contextConfigLocation自动查找配置文件并执行 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!-- 在控制寻找具体的controller的时候,可以把它类似看成过滤器,但是不会自动触发
这里不能写/*等控制范围太广的路径 ,核心控制器在进行捕获路径的时候,存在一些静态的文件,如果写成/*,同样会被捕获,
但是这些文件在springmvc1.xml并没有去设置相应的对象.所以会报404
最好使用:*.do *.ok *.haha
-->
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
7. 配置springmvc.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:context="http://www.springframework.org/schema/context"
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">
<!-- 1.导入相关的约束文件 -->
<!-- 2.再web.xml配置前端控制器 -->
<!-- 3.寻找Controller-BeanNameUrlHandlerMapping(处理器的映射器)-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!-- 5.通过bean的方式创建Controller的对象 name:就是访问路径 -->
<bean name="/test.do" class="com.qianfeng.web.TestController"></bean>
<!-- 6.执行Controller,让他工作
通过 SimpleControllerHandlerAdapter实现(处理器适配器) -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!-- 8.配置返回视图的信息
这里对返回视图的配置要与Controller页面的逻辑视图配合
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 设置前缀后缀 -->
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
8. 通过注解方式配置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">
<!-- 设置编码 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<display-name>J2EE_Email_SSM</display-name>
<!-- spring的applicationContext.xml文件路径的配置放在这里、全局的配置文件name必须是contextConfigLocation -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext.xml</param-value>
</context-param>
<!-- 执行applicationContext.xml,监听器只要发现配置了这个文件,就会自动执行这个文件 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置sessionlistener获取当前在线人数 -->
<listener>
<listener-class>com.swpu.listener.MyListener</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:spring/springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
<url-pattern>*.test</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
9. 通过注解方式配置springmvc.xml
<!-- 扫描注释-->
<context:component-scan base-package="com.swpu"></context:component-scan>
<!-- 自动生成映射器和适配器对象 -->
<mvc:annotation-driven></mvc:annotation-driven>
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
- 实例
10.1 结构
10.2 service层的注解
10.3 Controller层的注解
以上是关于springmvc是怎样接受websocket请求的的主要内容,如果未能解决你的问题,请参考以下文章