_spring mvc text/event-stream">
赞
踩
本篇主要介绍两种方式实现SpringMVC的服务器端推送。
方式一,基于SSE(服务器端发送事件)的服务器端推送。
这种方式的流程类似于Ajax。
首先在src/main/resources/views下面创建see.jsp。代码如下:
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>Insert title here</title>
- </head>
- <body>
- <div id="msgFromPush"></div>
-
- <script type="text/javascript"
- src="<c:url value="assets/js/jquery-3.1.1.js" />"></script>
- <script type="text/javascript">
- if (!!window.EventSource) { //EventSource是SSE的客户端.此时说明浏览器支持EventSource对象
- var source = new EventSource('push');//发送消息
- s = '';
- source.addEventListener('message', function(e) {
- s += e.data + "<br/>";
- $("#msgFromPush").html(s);
- });//添加客户端的监听
-
- source.addEventListener('open', function(e) {
- console.log("连接打开");
- }, false);
-
- source.addEventListener('error',function(e){
- if(e.readyState==EventSource.CLOSED){
- console.log("连接关闭");
- }else{
- console.log(e.readyState);
- }
- });
- }else{
- console.log("您的浏览器不支持SSE");
- }
- </script>
- </body>
- </html>
1.我们在jsp页面上,首先得到EventSource对象,由于EventSource是新式浏览器才支持的对象,所以我们要先判断当前的浏览器是否支持。
2.当浏览器支持EventSource对象时,我们在创建EventSource对象的时候,同时向指定的url路径发送了请求(构造参数就是要请求的url地址)。
3.我们然后使用EventSource对象来添加事件监听,监听连接打开、连接关闭、连接成功之后的事件,并通过回调函数的方式将服务器端的响应作为回调函数的参数传入,之后我们加以处理。
服务器端的控制器:
- /**
- * @author BeautifulSoup
- * SSE(基于服务器端发送事件的服务器端推送)
- */
- @Controller
- public class SseController {
- /**
- * @return
- * 演示服务器端每5秒钟向浏览器推送随机消息
- */
- @RequestMapping(value="/push",produces="text/event-stream")
- public @ResponseBody String push(){
- Random r=new Random();
- try {
- Thread.sleep(5000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- return "data:Testing 1,2,3"+r.nextInt()+"\n\n";
- }
- }
控制器将输出的媒体类型(参数produces)指定为text/event-stream,此时就开启了服务器端对SSE的支持。
此时我们访问jsp页面就会自动向控制器发送请求,然后服务器每隔5秒向客户端发送一次响应实现了服务器端的推送。
方式二:基于Servlet3.0+的异步方法特性实现服务器端的推送
首先在核心配置类(Servlet3.0取消了web.xml的使用)中开启异步方法支持:
- public class WebInitializer implements WebApplicationInitializer {
- public void onStartup(ServletContext servletContext)
- throws ServletException {
-
- AnnotationConfigWebApplicationContext ctx=new AnnotationConfigWebApplicationContext();
- ctx.register(MyMvcConfig.class);
- ctx.setServletContext(servletContext);
-
- Dynamic servlet=servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
- servlet.addMapping("/");
- servlet.setLoadOnStartup(1);
- //开启Servlet3.0+异步方法支持,用于提供服务器端的推送技术
- servlet.setAsyncSupported(true);
- }
- }
在SpringMVC的组件配置上开启计划任务的支持:
- @Configuration
- @EnableWebMvc
- @EnableScheduling //开启计划任务的支持
- @ComponentScan("com.fuyunwang")
- public class MyMvcConfig extends WebMvcConfigurerAdapter {
- @Bean
- public InternalResourceViewResolver viewResolver() {
- InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
- viewResolver.setPrefix("/WEB-INF/classes/views/");
- viewResolver.setSuffix(".jsp");
- viewResolver.setViewClass(JstlView.class);
- return viewResolver;
- }
-
- @Override
- public void addViewControllers(ViewControllerRegistry registry) {
- registry.addViewController("/sse").setViewName("/sse");
- registry.addViewController("/async").setViewName("/async");
- }
- }
在src/main/resources/views下创建async.jsp,在客户端发送ajax请求:
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>Insert title here</title>
- </head>
- <body>
- <script type="text/javascript"
- src="assets/js/jquery-3.1.1.js"></script>
- <script type="text/javascript">
- deferred();
-
- function deferred() {
- $.get('defer', function(data) {
- console.log(data);
- deferred();
- });
- }
- </script>
- </body>
- </html>
由于异步方法的实现是通过定时任务来完成的,所以我们需要创建定时任务(通过DeferredResult从另外一个线程返回实现),并在Controller中开启定时任务。
- /**
- * @author BeautifulSoup
- * Servlet3.0异步推送方式的Service,这就是定时任务
- */
- @Service
- public class PushService {
- private DeferredResult<String> deferredResult;//在PushService中产生DefreeedResult给控制器使用,通过@Scheduled注解的方法定时更新DeferredResult
- public DeferredResult<String> getAsyncUpdate(){
- deferredResult=new DeferredResult<String>();
- return deferredResult;
- }
- @Scheduled(fixedDelay=5000)
- public void refresh(){
- if(deferredResult!=null){
- deferredResult.setResult(new Long(System.currentTimeMillis()).toString());
- }
- }
- }
- /**
- * @author BeautifulSoup
- * Servelet3.0+异步方法来保证服务器端的推送技术
- */
- @Controller
- public class AsyncController {
- @Autowired
- public PushService pushService;
-
-
- @RequestMapping("/defer")
- @ResponseBody
- public DeferredResult<String> deferredCall(){
- return pushService.getAsyncUpdate();
- }
- }
Servlet3.0+异步方法实现服务器端推送,当我们向服务器端发送请求的时候,控制器会通过定时任务来定时更新DeferredResult,从而实现了延迟响应。然后我们在服务器端轮询服务器端,实现了服务器端每隔一定时间响应的服务器端推送。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。