当前位置:   article > 正文

spring boot之spring mvc常用配置--服务器端推送技术基于jquery(10)_event stream jquery

event stream jquery
服务器端推送技术的目的是使浏览器尽可能第一时间获得服务器的消息。
本章节服务器 端推送方案基于:当客户端向服务端发送请求,服务端会抓住这个请求不妨,等有数据集更新的时候才返回给客户端,
当客户端接收到消息后,在向服务端发送请求,周而复始。这种方式的好处事减少了服务器的请求数量,大大减少了服务器的压力。
当然有更好的解决方式----Websocket。下文会有介绍!
基于sse(Server send event 服务端发送事件)的服务端推送和基于Servlet3.0的异步方式特性,第一种方式需要

新式浏览器的支持,第二种方式是跨浏览器的。

一.sse

1.控制器

  1. package com.boot.springmvc.web.sse;
  2. import java.util.Random;
  3. import org.springframework.stereotype.Controller;
  4. import org.springframework.web.bind.annotation.RequestMapping;
  5. import org.springframework.web.bind.annotation.ResponseBody;
  6. @Controller
  7. public class SseController {
  8. /**
  9. * 注意:这里使用多媒体类型为text/event-stream,这是服务器端sse的支持,演示每5秒向浏览器推送随机消息。
  10. * @return
  11. */
  12. @RequestMapping(value = "/push", produces = "text/event-stream") //1
  13. public @ResponseBody String push() {
  14. Random r = new Random();
  15. try {
  16. Thread.sleep(5000);
  17. } catch (InterruptedException e) {
  18. e.printStackTrace();
  19. }
  20. return "data:Testing 1,2,3" + r.nextInt() + "\n\n";
  21. }
  22. }

2.添加页面跳转

  1. //演示sse
  2. registry.addViewController("/sse").setViewName("sse");

3.jsp页面中添加监听

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

备注 :EventSource对象只用新式的浏览器才有(chrome、Firefox等),EventSource是sse的客户端;

添加sse客户端监听,在此获得服务器端推送的消息。


二.Servlet3.0+异步方法处理

1.开启Servlet的异步支持

  1. package com.boot.springmvc;
  2. import javax.servlet.ServletContext;
  3. import javax.servlet.ServletException;
  4. import javax.servlet.ServletRegistration.Dynamic;
  5. import org.springframework.web.WebApplicationInitializer;
  6. import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
  7. import org.springframework.web.servlet.DispatcherServlet;
  8. public class WebInitializer implements WebApplicationInitializer {// 1
  9. @Override
  10. public void onStartup(ServletContext servletContext) throws ServletException {
  11. AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
  12. ctx.register(MyMvcConfig.class);
  13. ctx.setServletContext(servletContext); // 2
  14. Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx)); // 3
  15. servlet.addMapping("/");
  16. servlet.setLoadOnStartup(1);
  17. servlet.setAsyncSupported(true);// 1开启异步 方法的支持
  18. }
  19. }

2.控制器配置

  1. package com.boot.springmvc.web.sse;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.stereotype.Controller;
  4. import org.springframework.web.bind.annotation.RequestMapping;
  5. import org.springframework.web.bind.annotation.ResponseBody;
  6. import org.springframework.web.context.request.async.DeferredResult;
  7. import com.boot.springmvc.service.PushService;
  8. @Controller
  9. public class AysncController {
  10. @Autowired
  11. PushService pushService; //1定时任务类,定时更新DeferredResult<String>结果
  12. @RequestMapping("/defer")
  13. @ResponseBody
  14. public DeferredResult<String> deferredCall() { //2返回给客户端数据
  15. return pushService.getAsyncUpdate();
  16. }
  17. }

备注:异步任务的实现是通过控制器从另外一个线程返回一个DeferredResult<String>,这里的返回结果是从异步任务中获取。

3.定时任务--PushService(调用业务)

  1. package com.boot.springmvc.service;
  2. import org.springframework.scheduling.annotation.Scheduled;
  3. import org.springframework.stereotype.Service;
  4. import org.springframework.web.context.request.async.DeferredResult;
  5. @Service
  6. public class PushService {
  7. private DeferredResult<String> deferredResult; //1定时生产deferredResult结果
  8. public DeferredResult<String> getAsyncUpdate() {
  9. deferredResult = new DeferredResult<String>();//初始化后对象不为null
  10. return deferredResult;
  11. }
  12. @Scheduled(fixedDelay = 5000)//每5秒设值
  13. public void refresh() {
  14. if (deferredResult != null) {
  15. deferredResult.setResult(new Long(System.currentTimeMillis()).toString());
  16. }
  17. }
  18. }

4.页面

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  7. <title>servlet async support</title>
  8. </head>
  9. <body>
  10. <div>
  11. <ur id="async"></ur>
  12. </div>
  13. <script type="text/javascript" src="/assets/js/jquery.js"></script>
  14. <script type="text/javascript">
  15. deferred();//1
  16. function deferred(){
  17. $.get('defer',function(data){
  18. console.log(data); //2
  19. $("#async").append("<li>"+data+"</li>");
  20. deferred(); //3
  21. });
  22. }
  23. </script>
  24. </body>
  25. </html>

5.viewResolver和开启定时任务配置

  1. package com.boot.springmvc;
  2. import java.util.List;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.ComponentScan;
  5. import org.springframework.context.annotation.Configuration;
  6. import org.springframework.http.converter.HttpMessageConverter;
  7. import org.springframework.scheduling.annotation.EnableScheduling;
  8. import org.springframework.web.multipart.MultipartResolver;
  9. import org.springframework.web.multipart.commons.CommonsMultipartResolver;
  10. import org.springframework.web.servlet.config.annotation.EnableWebMvc;
  11. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
  12. import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
  13. import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
  14. import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
  15. import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
  16. import org.springframework.web.servlet.view.InternalResourceViewResolver;
  17. import org.springframework.web.servlet.view.JstlView;
  18. import com.boot.springmvc.interceptor.DemoInterceptor;
  19. import com.boot.springmvc.messageconvert.MymessageConverter;
  20. /**
  21. * @Bean public InternalResourceViewResolver viewResolver();
  22. * 注入InternalResourceViewResolver类:
  23. * 说明:springmvc下有一个接口叫ViewResolver,(我们的viewResolver都实现该接口),实现这个接口要重写
  24. * resolverName(),这个方法的返回值接口View,而view的职责就是使用model、request、response对象,并
  25. * 渲染视图(不一定是html、可能是json、xml、pdf等)给浏览器 。
  26. *
  27. */
  28. @Configuration
  29. @EnableWebMvc // 1开启默认配置
  30. @EnableScheduling
  31. @ComponentScan("com.boot.springmvc")
  32. public class MyMvcConfig extends WebMvcConfigurerAdapter {// 2
  33. // viewResolver
  34. @Bean
  35. public InternalResourceViewResolver viewResolver() {
  36. InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
  37. // viewResolver.setPrefix("/WEB-INF/classes/views/");//打war后默认编译的路径
  38. viewResolver.setPrefix("/WEB-INF/views/");// 使用tomcat7:run插件后要放的位置
  39. viewResolver.setSuffix(".jsp");
  40. viewResolver.setViewClass(JstlView.class);
  41. return viewResolver;
  42. }
  43. // 静态资源映射
  44. @Override
  45. public void addResourceHandlers(ResourceHandlerRegistry registry) {
  46. registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/assets/");
  47. }// 3
  48. // 拦截器
  49. @Bean
  50. // 1
  51. public DemoInterceptor demoInterceptor() {
  52. return new DemoInterceptor();
  53. }
  54. @Override
  55. public void addInterceptors(InterceptorRegistry registry) {// 2
  56. registry.addInterceptor(demoInterceptor());
  57. }
  58. // viewController
  59. @Override
  60. public void addViewControllers(ViewControllerRegistry registry) {
  61. registry.addViewController("/index1").setViewName("/index1");
  62. // 跳转文件上传页面
  63. registry.addViewController("/toupload").setViewName("/upload");
  64. // 演示HttpMessageConverter
  65. registry.addViewController("/converter").setViewName("/converter");
  66. //演示sse
  67. //registry.addViewController("/sse").setViewName("sse");
  68. //服务器消息推送,演示异步处理
  69. registry.addViewController("/async").setViewName("async");
  70. }
  71. // 文件上传最大限制
  72. @Bean
  73. public MultipartResolver multipartResolver() {
  74. CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
  75. multipartResolver.setMaxUploadSize(200);
  76. return multipartResolver;
  77. }
  78. // 不忽略"."后面的参数。
  79. @Override
  80. public void configurePathMatch(PathMatchConfigurer configurer) {
  81. configurer.setUseSuffixPatternMatch(false);
  82. }
  83. /**
  84. * 配置自定义的HttpMessageConverter
  85. *注:
  86. *1.configureMessageConverters:重载会覆盖掉spring mvc默认注册的 多个HttpMessageConverter。
  87. *2.extendsMessageConverter:仅添加一个自定义 的HttpMessageConverter,不覆盖默认注册 的HttpMessageConverter.
  88. **/
  89. //使用extendsMessageConverter 添加一个自定义的HttpMessageConverter
  90. @Bean
  91. public MymessageConverter converter(){
  92. return new MymessageConverter();
  93. }
  94. @Override
  95. public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
  96. converters.add(converter());
  97. }
  98. }

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

闽ICP备14008679号