springmvc 비동기 요청 처리 예시

springmvc 3.2부터 servlet 3.0의 비동기 요청을 지원합니다.평소에 컨트롤러를 요청하는 것은 일반적으로 동기화됩니다. 코드가 실행될 때 시간이 걸리는 업무 조작이 발생하면 servlet 용기 라인이 잠겨서 다른 요청이 들어올 때 막힙니다.
springmvc3.2 이후 비동기 요청을 지원하여 controller에서 Callable 또는 DeferredResult를 되돌려줍니다.Callable로 돌아갈 때 대략적인 실행 과정은 다음과 같습니다.
  • controller 반환값이 Callable일 때springmvc는 Callable을 TaskExecutor에 처리하는 라인을 시작합니다
  • 그리고 Dispatcher Servlet과 모든spring 차단기가 메인 라인을 종료한 후response를 열어 놓은 상태로 유지합니다
  • Callable의 실행이 끝난 후springmvc는 리퀘스트 요청을 다시 시작하고 Dispatcher Servlet은 Callable의 비동기적인 실행 결과를 다시 호출하고 처리한 다음 보기로 돌아갑니다
  • DeferredResult의 실행 과정은 Callable과 차이가 많지 않습니다. 유일하게 다를 때, DeferredResult는 응용 프로그램의 다른 라인에서 실행된 결과이고, Callable은 TaskExecutor에서 실행된 결과입니다.
    springmvc 비동기 설정 요청
    1. 웹에서 필요합니다.xml + servlet 3.0 scheme 라이브러리
    
    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
    ...
    </web-app>
    2. 웹에서.xml의 servlet 및 filter 추가 true 하위 노드
    
    <!-- springMVC Servlet  -->
    <servlet>
      <servlet-name>dispatcher</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:META-INF/dispatcher-context.xml</param-value>
      </init-param>
      <load-on-startup>1</load-on-startup>
      <async-supported>true</async-supported>
    </servlet>
    
    <!--   -->
    <filter>
      <filter-name>CharacterEncodingFilter</filter-name>
      <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
      <async-supported>true</async-supported>
      <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
      </init-param>
      <init-param>
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
      </init-param>
    </filter>
    
    
    3. 그리고 컨트롤러에서 비동기 요청을 실행할 수 있습니다
    Callable을 사용하여 비동기식 요청을 수행하고 보기로 돌아갑니다.
    
    @RequestMapping("/mvc25")
    public Callable<String> mvc25() {
    
      return new Callable<String>() {
        @Override
        public String call() throws Exception {
           Thread.sleep(2000);
           return "task/task";
        }
      };
    
    }
    
    
    Callable를 이용하여 비동기적인 요청을 실행하고 요청 결과를 @response를 통해 httpmessageconverter로 전환하여 클라이언트에게 되돌려줍니다.
    
    @RequestMapping("/mvc26")
    @ResponseBody
    public Callable<String> mvc26() {
    
      return new Callable<String>() {
        @Override
        public String call() throws Exception {
          Thread.sleep(2000);
          return "hello task";
        }
      };
    
    }
    
    
    클라이언트 시간 초과 사용자 정의 가능
    
    @RequestMapping("/mvc27")
    @ResponseBody
    public WebAsyncTask<String> mvc27() {
    
      Callable<String> callable = new Callable<String>() {
        @Override
        public String call() throws Exception {
          Thread.sleep(10000);
          return "hello task";
        }
      };
    
      return new WebAsyncTask<String>(10000, callable);
    }
    
    
    루틴을 실행하는 과정에서 이상이 발생하면 일반적인 요청과 같이 @ExceptionHandler로 처리하거나 전역적인 HandlerExceptionResolver를 정의하여 처리할 수 있습니다
    
    @RequestMapping("/mvc28")
    @ResponseBody
    public Callable<String> mvc28() {
    
      Callable<String> callable = new Callable<String>() {
        @Override
        public String call() throws Exception {
          Thread.sleep(2000);
          throw new RuntimeException();
        }
      };
    
      return callable;
    
    }
    
    @ExceptionHandler(RuntimeException.class)
    @ResponseBody
    public JSONObject handlerException(){
    
      JSONObject jsonObject = new JSONObject();
      jsonObject.put("aaa", 123);
    
      return jsonObject ;
    }
    
    
    또한 DeferredResult로 되돌아갈 수 있습니다. DeferredResult의 역할은 다른 라인에 실례를 되돌려 이 비동기적인 요청을 처리하는 것입니다.
    
    @RequestMapping("/mvc29")
    @ResponseBody
    public DeferredResult<String> mvc29() {
    
      DeferredResult<String> deferredResult = new DeferredResult<String>();
      dealInOtherThread(deferredResult);
      return deferredResult;
    
    }
    
    private void dealInOtherThread(DeferredResult<String> deferredResult) {
      try {
        Thread.sleep(2000);
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    
      deferredResult.setResult("hello task");
    }
    
    
    dealInOtherThread 처리가 완료되면 setResult가 발생할 때springmvc에서 Request를 Dispatcher Servlet에 분배한 다음, Dispatcher Servlet이 DeferredResult의 결과를 처리하고 보기를 되돌려줍니다.
    DeferredResult는 또 다른 반환을 제공하여 스레드 요청을 처리합니다. 예를 들어 onTimeout(Runnable)과 onCompletion(Runnable)입니다. onTimeout은 스레드 리셋을 등록할 수 있습니다. 요청이 지연될 때의 리셋 함수이고, onCompletion은 요청이 끝난 리셋 함수를 등록할 수 있습니다.
    이상은 본문의 전체 내용입니다. 여러분의 학습에 도움이 되고 저희를 많이 응원해 주십시오.

    좋은 웹페이지 즐겨찾기