09点睛Spring MVC 4.1-非同期要求処理(互換ブラウザを含むサーバ側プッシュ)

22048 ワード

9.1非同期要求処理
サーブレット3は、非同期要求処理のサポートを開始する.
Spring MVC 3.2サーブレット3をサポートするこの機能コントローラは、単純な値ではなく、別のスレッドからjava.util.concurrent.Callableを返すことができる.
このときサーブレットコンテナスレッドは解放され、他の要求を処理することができる.
Spring MVCは、TaskExecutorを介して別のスレッド(例中のmvcTaskExecutor)を呼び出す.

コントローラは、別のスレッドからDeferredResultを返すこともできる
このときSpring MVCはこのスレッドの存在を知らない例えば、タイミングタスク
9.2プレゼンテーション05 Spring MVC 4.1- においても,SSEによる長い接続を実証した.
ただし、IEの一部のバージョンではサポートされていない
この例では,Spring MVCによる非同期処理のサポートにより,長接続のサポート,すなわちサーバ側プッシュを実証する.
すべてのブラウザをサポート

サーブレットオープン非同期サポート
package com.wisely;

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;

public class WebInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext)
            throws ServletException {
            AnnotationConfigWebApplicationContext ctx = 
                                     new AnnotationConfigWebApplicationContext();  
            ctx.register(DemoMVCConfig.class); 
            //  spring mvc DispatcherServlet
            ctx.setServletContext(servletContext);    
            Dynamic servlet = 
                   servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));  
            servlet.addMapping("/");  
            servlet.setLoadOnStartup(1);
            servlet.setAsyncSupported(true);//    

    }

}
DeferredResultに必要なタイミング処理
package com.wisely.service;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.async.DeferredResult;

@Service
public class AysncService {
    private DeferredResult<String> deferredResult;

    public DeferredResult<String> getAsyncUpdate() {
        deferredResult = new DeferredResult<String>();
        return deferredResult;
    }

    @Scheduled(fixedDelay = 5000)
    public void refresh() {
        if (deferredResult != null) {
            deferredResult.setResult(new Long(System.currentTimeMillis())
                    .toString());
        }
    }


}

Spring MVCサポート構成のオープン:WebMvcConfigurerAdapterの構成クラスDemoMVCConfig を継承
  @Override
  public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
       configurer.setDefaultTimeout(30*1000L); //tomcat  10 
       configurer.setTaskExecutor(mvcTaskExecutor());//    TaskExecutor
   }
   @Bean
   public ThreadPoolTaskExecutor mvcTaskExecutor(){
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setQueueCapacity(100);
        executor.setMaxPoolSize(25);
        return executor;

    }

     @Override
   public void addViewControllers(ViewControllerRegistry registry) {
       registry.addViewController("/async").setViewName("/async");
   }

テストコントローラ
package com.wisely.web;

import java.util.concurrent.Callable;

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.wisely.service.AysncService;

@Controller
public class AysncController {

    @Autowired
    AysncService aysncService;


    @RequestMapping("/call")
    @ResponseBody
    public Callable<String> asyncCall() {
        //  mvcTaskExecutor         
        //  Servlet        ,         
        return new Callable<String>() {
            @Override
            public String call() throws Exception {
                Thread.sleep(3000);
                return "Async Hello World";
            }
        };
    }

    @RequestMapping("/defer")
    @ResponseBody
    public DeferredResult<String> deferredCall() {
        //  aysncService getAsyncUpdate  
        //deferredResult             
        return aysncService.getAsyncUpdate();
    }

}


テストページ
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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">
<title>Insert title here</title>

</head>
<body>
<input type="button" value="call" onclick="call();"/>
<input type="button" value="deferred" onclick="deferred();"/>


<script type="text/javascript" src="<c:url value="/js/jquery.js" />"></script>
<script type="text/javascript">

function call(){
    $.get('call',function(data){
        console.log(data);
    });
}


function deferred(){
    $.get('defer',function(data){
        console.log(data);
        deferred();//      ,      ,              
    });
}


</script>
</body>
</html>

テスト
アクセスhttp://localhost:8080/testSpringMVC/async
クリックcall defer をクリック