_spring mvc text/event-stream">
当前位置:   article > 正文

SpringMVC实现服务器端推送_spring mvc text/event-stream

spring mvc text/event-stream

本篇主要介绍两种方式实现SpringMVC的服务器端推送。

方式一,基于SSE(服务器端发送事件)的服务器端推送。 
这种方式的流程类似于Ajax。 
首先在src/main/resources/views下面创建see.jsp。代码如下:

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
  4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  5. <html>
  6. <head>
  7. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  8. <title>Insert title here</title>
  9. </head>
  10. <body>
  11. <div id="msgFromPush"></div>
  12. <script type="text/javascript"
  13. src="<c:url value="assets/js/jquery-3.1.1.js" />"></script>
  14. <script type="text/javascript">
  15. if (!!window.EventSource) { //EventSource是SSE的客户端.此时说明浏览器支持EventSource对象
  16. var source = new EventSource('push');//发送消息
  17. s = '';
  18. source.addEventListener('message', function(e) {
  19. s += e.data + "<br/>";
  20. $("#msgFromPush").html(s);
  21. });//添加客户端的监听
  22. source.addEventListener('open', function(e) {
  23. console.log("连接打开");
  24. }, false);
  25. source.addEventListener('error',function(e){
  26. if(e.readyState==EventSource.CLOSED){
  27. console.log("连接关闭");
  28. }else{
  29. console.log(e.readyState);
  30. }
  31. });
  32. }else{
  33. console.log("您的浏览器不支持SSE");
  34. }
  35. </script>
  36. </body>
  37. </html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

1.我们在jsp页面上,首先得到EventSource对象,由于EventSource是新式浏览器才支持的对象,所以我们要先判断当前的浏览器是否支持。 
2.当浏览器支持EventSource对象时,我们在创建EventSource对象的时候,同时向指定的url路径发送了请求(构造参数就是要请求的url地址)。 
3.我们然后使用EventSource对象来添加事件监听,监听连接打开、连接关闭、连接成功之后的事件,并通过回调函数的方式将服务器端的响应作为回调函数的参数传入,之后我们加以处理。 
服务器端的控制器:

  1. /**
  2. * @author BeautifulSoup
  3. * SSE(基于服务器端发送事件的服务器端推送)
  4. */
  5. @Controller
  6. public class SseController {
  7. /**
  8. * @return
  9. * 演示服务器端每5秒钟向浏览器推送随机消息
  10. */
  11. @RequestMapping(value="/push",produces="text/event-stream")
  12. public @ResponseBody String push(){
  13. Random r=new Random();
  14. try {
  15. Thread.sleep(5000);
  16. } catch (InterruptedException e) {
  17. e.printStackTrace();
  18. }
  19. return "data:Testing 1,2,3"+r.nextInt()+"\n\n";
  20. }
  21. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

控制器将输出的媒体类型(参数produces)指定为text/event-stream,此时就开启了服务器端对SSE的支持。 
此时我们访问jsp页面就会自动向控制器发送请求,然后服务器每隔5秒向客户端发送一次响应实现了服务器端的推送。

方式二:基于Servlet3.0+的异步方法特性实现服务器端的推送 
首先在核心配置类(Servlet3.0取消了web.xml的使用)中开启异步方法支持:

  1. public class WebInitializer implements WebApplicationInitializer {
  2. public void onStartup(ServletContext servletContext)
  3. throws ServletException {
  4. AnnotationConfigWebApplicationContext ctx=new AnnotationConfigWebApplicationContext();
  5. ctx.register(MyMvcConfig.class);
  6. ctx.setServletContext(servletContext);
  7. Dynamic servlet=servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
  8. servlet.addMapping("/");
  9. servlet.setLoadOnStartup(1);
  10. //开启Servlet3.0+异步方法支持,用于提供服务器端的推送技术
  11. servlet.setAsyncSupported(true);
  12. }
  13. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

在SpringMVC的组件配置上开启计划任务的支持:

  1. @Configuration
  2. @EnableWebMvc
  3. @EnableScheduling //开启计划任务的支持
  4. @ComponentScan("com.fuyunwang")
  5. public class MyMvcConfig extends WebMvcConfigurerAdapter {
  6. @Bean
  7. public InternalResourceViewResolver viewResolver() {
  8. InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
  9. viewResolver.setPrefix("/WEB-INF/classes/views/");
  10. viewResolver.setSuffix(".jsp");
  11. viewResolver.setViewClass(JstlView.class);
  12. return viewResolver;
  13. }
  14. @Override
  15. public void addViewControllers(ViewControllerRegistry registry) {
  16. registry.addViewController("/sse").setViewName("/sse");
  17. registry.addViewController("/async").setViewName("/async");
  18. }
  19. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

在src/main/resources/views下创建async.jsp,在客户端发送ajax请求:

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
  4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  5. <html>
  6. <head>
  7. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  8. <title>Insert title here</title>
  9. </head>
  10. <body>
  11. <script type="text/javascript"
  12. src="assets/js/jquery-3.1.1.js"></script>
  13. <script type="text/javascript">
  14. deferred();
  15. function deferred() {
  16. $.get('defer', function(data) {
  17. console.log(data);
  18. deferred();
  19. });
  20. }
  21. </script>
  22. </body>
  23. </html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

由于异步方法的实现是通过定时任务来完成的,所以我们需要创建定时任务(通过DeferredResult从另外一个线程返回实现),并在Controller中开启定时任务。

  1. /**
  2. * @author BeautifulSoup
  3. * Servlet3.0异步推送方式的Service,这就是定时任务
  4. */
  5. @Service
  6. public class PushService {
  7. private DeferredResult<String> deferredResult;//在PushService中产生DefreeedResult给控制器使用,通过@Scheduled注解的方法定时更新DeferredResult
  8. public DeferredResult<String> getAsyncUpdate(){
  9. deferredResult=new DeferredResult<String>();
  10. return deferredResult;
  11. }
  12. @Scheduled(fixedDelay=5000)
  13. public void refresh(){
  14. if(deferredResult!=null){
  15. deferredResult.setResult(new Long(System.currentTimeMillis()).toString());
  16. }
  17. }
  18. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  1. /**
  2. * @author BeautifulSoup
  3. * Servelet3.0+异步方法来保证服务器端的推送技术
  4. */
  5. @Controller
  6. public class AsyncController {
  7. @Autowired
  8. public PushService pushService;
  9. @RequestMapping("/defer")
  10. @ResponseBody
  11. public DeferredResult<String> deferredCall(){
  12. return pushService.getAsyncUpdate();
  13. }
  14. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

Servlet3.0+异步方法实现服务器端推送,当我们向服务器端发送请求的时候,控制器会通过定时任务来定时更新DeferredResult,从而实现了延迟响应。然后我们在服务器端轮询服务器端,实现了服务器端每隔一定时间响应的服务器端推送。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/335497
推荐阅读
相关标签
  

闽ICP备14008679号