SSE服务器推送技术

SSE即 server send event 服务器发送事件,在在早期可能会使用ajax向服务器轮询的方式,使浏览器第一时间接受到服务器的消息,但这种频率不好控制,消耗也比较大。

但是对于SSE来说,当客户端向服务端发送请求,服务端会抓住这个请求不放,等到有数据时才返回给客户端,但客户端手动消息后,再向服务器发送请求,周而复始。这种方式好处是减少了服务器的请求数量,也大大减少了服务器的压力。

以下是第一种方式的代码的演示,浏览器不断向服务器请求,服务器用线程睡眠5s再返回结果。

1、SseController 控制器

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Random;
​
/**
 * @description: 服务器端推送控制器
 *
 * @author: Shenshuaihu
 * @version: 1.0
 * @data: 2019-06-25 23:29
 */
@Controller
public class SseController {
​
 /**
 * 输出类型 text/event-stream 是对服务器端SSE的支持
 * 此处每5s向浏览器推送随机消息
 * @return
 */
 @RequestMapping(value = "/push", produces = "text/event-stream")
 public @ResponseBody String push() {
 Random random = new Random();
 try {
 Thread.sleep(5000);
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 return "data:Testing 1,2,3: " + random.nextInt() + "\n\n";
 }
}

2、显示结果的页面 sse.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>



 SSE-Code
 


sse.jsp

​ 服务器推送 可以用于消息订阅
解决长短轮询不是解决问题
server send event 当客户端方服务器发送请求时 服务器抓住不放 等有数据时 再回复给客户端,客户端收到消息时发给送给服务器,如此循环
参考内容: https://www.jianshu.com/p/bc5a9b4a1cd1 ​

显示的结果

SSE-.png

二、使用Servlet 3.0 + 异步方法处理,第二种方式演示,浏览器循环请求服务端,服务端用定时任务,每5S设置一下数据,返回给浏览器

1、开启异步方法的支持 WebInitializer.java

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
​
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration.Dynamic;
​
/**
 * @description: Web配置 代替web.xml
 * @author: Shenshuaihu
 * @version: 1.0
 * @data: 2019-06-13 23:22
 */
public class WebInitializer implements WebApplicationInitializer {
 @Override
 public void onStartup(ServletContext servletContext) throws ServletException {
 AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
 context.register(MyMvcConfig.class);
 // 新建的webApplicationContext ,注册配置类,并将其和当前servletContext关联。
 context.setServletContext(servletContext);
​
 // 注册SpringMVC 的 DispatcherServlet
 Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
 servlet.addMapping("/");
 servlet.setLoadOnStartup(1);
 // 开启对异步的支持
 servlet.setAsyncSupported(true);
 }
}

2、AsyncController.java 控制层,只用掉service

import com.ch4.service.PushService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.async.DeferredResult;
​
/**
 * @description:
 *
 * @author: Shenshuaihu
 * @version: 1.0
 * @data: 2019-06-27 08:32
 */
@Controller
public class AsyncController {
 @Autowired
 private PushService pushService;
​
 @RequestMapping("/defer")
 @ResponseBody
 public DeferredResult deferredCall() {
 return pushService.getAsyncUpdate();
 }
}

3、PushService.java

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.async.DeferredResult;
​
/**
 * @description: SSE 定时任务
 *      在PushService里面产生 DeferredResult 给控制器使用,
 *      通过 @Scheduled 定时更新DeferredResult
 *
 * @author: Shenshuaihu
 * @version: 1.0
 * @data: 2019-06-27 08:32
 */
@Service
public class PushService {
​
 private DeferredResult deferredResult;
​
 public DeferredResult getAsyncUpdate() {
 deferredResult = new DeferredResult();
 return deferredResult;
 }
​
 @Scheduled(fixedDelay = 5000)
 public void refresh() {
 if (deferredResult != null) {
 deferredResult.setResult(new Long(System.currentTimeMillis()).toString());
 }
 }
}

3、数据页面async.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>



async support-Code



defer.jsp

​ ​ ​

4、需要在核销配置类用开启任务

@Configuration
@EnableWebMvc
@ComponentScan("com.ch4")
@EnableScheduling
public class MyMvcConfig extends WebMvcConfigurerAdapter {}
SSE-aync.png

总结:

SSE用于订阅消息,是需要浏览器不断的请求,与websocket有相似之处

2019/06/30晚于成都

你可能感兴趣的:(SSE服务器推送技术)