欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

springmvc处理异步请求的示例

程序员文章站 2024-03-08 13:37:22
springmvc 3.2开始就支持servlet3.0的异步请求。平常我们请求一个controller一般都是同步的,如果在代码执行中,遇到耗时的业务操作,那servle...

springmvc 3.2开始就支持servlet3.0的异步请求。平常我们请求一个controller一般都是同步的,如果在代码执行中,遇到耗时的业务操作,那servlet容器线程就会被锁死,当有其他请求进来的时候就会受堵了。

springmvc3.2之后支持异步请求,能够在controller中返回一个callable或者deferredresult。当返回callable的时候,大概的执行过程如下:

  • 当controller返回值是callable的时候,springmvc就会启动一个线程将callable交给taskexecutor去处理
  • 然后dispatcherservlet还有所有的spring拦截器都退出主线程,然后把response保持打开的状态
  • 当callable执行结束之后,springmvc就会重新启动分配一个request请求,然后dispatcherservlet就重新调用和处理callable异步执行的返回结果,然后返回视图

deferredresult的执行过程和callable差不多,唯一不同的时候,deferredresult是由应用程序其他线程执行返回结果,而callable是由taskexecutor执行返回结果。

springmvc配置异步请求

1.需要在web.xml加上servlet3.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.在web.xml的servlet还有filter添加<asyncsupported>true</async-supported>子节点

<!-- 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.然后就可以在controller中执行异步请求了

利用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到dispatcherservlet,然后dispatcherservlet处理deferredresult的返回结果,并返回视图。

deferredresult还提供了其他返回来处理线程请求,例如ontimeout(runnable) 还有oncompletion(runnable),ontimeout可以注册一个线程回调,当请求延时的时候的回调函数,oncompletion可以注册一个请求完成的回调函数。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。