springmvc处理异步请求的示例
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可以注册一个请求完成的回调函数。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。