Servlet 3.0+ 异步处理方法通过设置动态Servlet(即Dynamic)支持异步处理,在客户端(浏览器)以ajax形式不断发送请求,从而获得信息。
示例:
1. 动态Servlet支持异步处理
package com.webApplicationInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration.Dynamic;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import com.config.MvcConfig;
/** Use class that implements WebApplicationInitializer interface to substitute web.xml
* @author apple
*
*/
public class WebInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext applicationContext =
new AnnotationConfigWebApplicationContext();
applicationContext.register(MvcConfig.class); // process annotated class MvcConfig
applicationContext.setServletContext(servletContext); // make applicationContext and servletContext related
applicationContext.refresh();
Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(applicationContext));
servlet.addMapping("/");
servlet.setLoadOnStartup(1);
servlet.setAsyncSupported(true);
}
}
2. Service Bean
该类仅仅是业务逻辑,与异步实现关系无关。
package com.service;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.async.DeferredResult;
/** 用于异步Servlet 3.0+的服务器端推送测试,
* 为Controller提供一个异步的定时更新的DeferredResult<String>
* @author apple
*
*/
@Service
public class PushService {
private DeferredResult<String> deferredResult ;
public DeferredResult<String> getAyncUpdateDeferredResult() {
this.deferredResult = new DeferredResult<>();
return deferredResult;
}
/**以下说明通过查看@Scheduled注解获得。
* 由于@Scheduled注解的处理是通过注册一个ScheduledAnnotationBeanPostProcessor完成的,
* 而后者是对方法被@Scheduled注解了的Bean,按照该注解的要求,
* 通过调用一个TaskScheduler进行post process。
* 因此对于实例化的Bean,必须完成@Scheduled注解的方法后才能被调用。
*/
@Scheduled(fixedDelay=5000)
public void refresh() {
if (this.deferredResult != null) {
this.deferredResult.setResult(String.valueOf(System.currentTimeMillis()));
}
}
}
3. Controller
package com.controller;
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;
import com.service.PushService;
@Controller
public class PushController {
@Autowired
PushService pushService;
@RequestMapping(value="/defer")
@ResponseBody
public DeferredResult<String> deferredCall() {
// 通过Service Bean获取异步更新的DeferredReuslt<String>
return pushService.getAyncUpdateDeferredResult();
}
}
4. 测试页面(jsp)
测试页面采用ajax不断发送请求,这些请求构成了并发请求。由于前面Servlet支持异步处理,请求到达服务端后,直到Service Bean实例化,并按照@Scheduled要求延时至设定的时间(例中5000ms)进行了设置,才通过Controller中以@RequestMapping注解的方法发送response到浏览器。
测试结果:
浏览器页面显示(数据为:System.currentTimeMillis())
1528273203260
1528273208265
1528273213271
1528273218278
1528273223282
1528273228285
1528273233290
1528273238296
1528273243298
1528273248302
由结果可知,请求确实是并发的,Servlet 3.0+对请求进行了异步处理。