Spring MVC Servlet 3.0+ 异步方法实现服务端的消息推送
Servlet 3.0+ 异步方法实现服务端消息推送是通过使用定时任务,定时的让控制器从另外一个线程返回一个DeferedResult
并推送给客户端。而更新DeferedResult
是在使用@Scheduled
定时任务注解的方法里执行的。
示例
Maven管理的项目,pom.xml
添加Servlet 3.0+
版本依赖包。
- 在
SpringMvcConfig.java
类上添加开启定时任务的注解1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//开启计划任务
public class SpringMvcConfig extends WebMvcConfigurerAdapter {
/**
* 配置viewResolver,用来映射来物理路径
* @return
*/
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
viewResolver.setViewClass(JstlView.class);
return viewResolver;
} - Web初始化类时添加开启Servlet3.0+异步方法
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/**
* WebApplicationInitializer是Spring提供用来配置Servlet+3.0配置的接口,从而实现了替代web.xml的位置。
* 实现该接口会自动被SpringServletContainerInitializer(用来启动Servlet3.0容器)获取到。
* @author Rocky
*
*/
public class WebInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext servletContext) throws ServletException {
//注解方式配置的web上下文
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(SpringMvcConfig.class);
//将上下文和当前servletContext关联
context.setServletContext(servletContext);
//注册dispatcher
Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
servlet.addMapping("/");
servlet.setLoadOnStartup(1);
//Servlet3.0支持开启异步方法
servlet.setAsyncSupported(true);
}
} - Controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class AysncController {
PushServiceImpl pushServiceImpl;
public String asyncPage() {
return "async";
}
public DeferredResult<String> deferredCall() {
return pushServiceImpl.getAsyncUpdate();
}
} - Service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class PushServiceImpl {
private DeferredResult<String> deferredResult;
public DeferredResult<String> getAsyncUpdate(){
deferredResult = new DeferredResult<>();
return deferredResult;
}
//定时任务,每5秒执行一次
public void refresh() {
if(deferredResult != null) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateTime = sdf.format(System.currentTimeMillis());
deferredResult.setResult("NowDateTime: " + dateTime);
}
}
} - jsp
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<%@ 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">
<script type="text/javascript"
src="${pageContext.request.contextPath}/static/js/jquery-1.11.0.js"></script>
<script type="text/javascript">
var s = '';
deferred();
function deferred() {
$.get('defer', function(data) {
console.log(data);
s = s + (data + "<br/>");
$("#msgFromPush").html(s);
deferred();
})
}
</script>
<title>SSE Demo</title>
</head>
<body>
<div id="msgFromPush"></div>
</body>
</html>
参考资料
Spring MVC Servlet 3.0+ 异步方法实现服务端的消息推送
http://blog.gxitsky.com/2018/04/01/SpringMVC-25-Servlet-v3-AsyncMethod/