springMVC学习--9 Servlet 3.0+ 异步处理方法 服务端推送技术之一

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+对请求进行了异步处理。

猜你喜欢

转载自blog.csdn.net/xiewz1112/article/details/80600516