springmvc處理異步請(qǐng)求的示例
springmvc 3.2開(kāi)始就支持servlet3.0的異步請(qǐng)求。平常我們請(qǐng)求一個(gè)controller一般都是同步的,如果在代碼執(zhí)行中,遇到耗時(shí)的業(yè)務(wù)操作,那servlet容器線(xiàn)程就會(huì)被鎖死,當(dāng)有其他請(qǐng)求進(jìn)來(lái)的時(shí)候就會(huì)受堵了。
springmvc3.2之后支持異步請(qǐng)求,能夠在controller中返回一個(gè)Callable或者DeferredResult。當(dāng)返回Callable的時(shí)候,大概的執(zhí)行過(guò)程如下:
- 當(dāng)controller返回值是Callable的時(shí)候,springmvc就會(huì)啟動(dòng)一個(gè)線(xiàn)程將Callable交給TaskExecutor去處理
- 然后DispatcherServlet還有所有的spring攔截器都退出主線(xiàn)程,然后把response保持打開(kāi)的狀態(tài)
- 當(dāng)Callable執(zhí)行結(jié)束之后,springmvc就會(huì)重新啟動(dòng)分配一個(gè)request請(qǐng)求,然后DispatcherServlet就重新調(diào)用和處理Callable異步執(zhí)行的返回結(jié)果,然后返回視圖
DeferredResult的執(zhí)行過(guò)程和Callable差不多,唯一不同的時(shí)候,DeferredResult是由應(yīng)用程序其他線(xiàn)程執(zhí)行返回結(jié)果,而Callable是由TaskExecutor執(zhí)行返回結(jié)果。
springmvc配置異步請(qǐng)求
1.需要在web.xml加上servlet3.0的scheme庫(kù)
<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>子節(jié)點(diǎn)
<!-- 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中執(zhí)行異步請(qǐng)求了
利用Callable執(zhí)行異步請(qǐng)求,并返回視圖
@RequestMapping("/mvc25")
public Callable<String> mvc25() {
return new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(2000);
return "task/task";
}
};
}
利用Callable執(zhí)行異步請(qǐng)求,并把請(qǐng)求結(jié)果通過(guò)@response由httpmessageconverter進(jìn)行轉(zhuǎn)化返回客戶(hù)端
@RequestMapping("/mvc26")
@ResponseBody
public Callable<String> mvc26() {
return new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(2000);
return "hello task";
}
};
}
可以自定義客戶(hù)端超時(shí)間
@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);
}
如果在線(xiàn)程的執(zhí)行過(guò)程中,遇到異常,處理過(guò)程和普通請(qǐng)求的一樣,你可以用@ExceptionHandler來(lái)處理或者定義全局的HandlerExceptionResolver來(lái)處理
@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 ;
}
還可以通過(guò)返回DeferredResult返回,DeferredResult的作用是返回一個(gè)實(shí)例給其他線(xiàn)程來(lái)處理這個(gè)異步請(qǐng)求。
@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的時(shí)候就會(huì)觸發(fā)springmvc分配一個(gè)request到DispatcherServlet,然后DispatcherServlet處理DeferredResult的返回結(jié)果,并返回視圖。
DeferredResult還提供了其他返回來(lái)處理線(xiàn)程請(qǐng)求,例如onTimeout(Runnable) 還有onCompletion(Runnable),onTimeout可以注冊(cè)一個(gè)線(xiàn)程回調(diào),當(dāng)請(qǐng)求延時(shí)的時(shí)候的回調(diào)函數(shù),onCompletion可以注冊(cè)一個(gè)請(qǐng)求完成的回調(diào)函數(shù)。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Maven及Springboot配置JDK版本,編碼,源碼打包等方式
這篇文章主要介紹了Maven及Springboot配置JDK版本,編碼,源碼打包等方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
java圖像識(shí)別工具類(lèi)(ImageRecognitionUtils)使用實(shí)例詳解
這篇文章主要介紹了如何在Java中使用OpenCV進(jìn)行圖像識(shí)別,包括圖像加載、預(yù)處理、分類(lèi)、人臉檢測(cè)和特征提取等步驟,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-01-01
Java C++解決在排序數(shù)組中查找數(shù)字出現(xiàn)次數(shù)問(wèn)題
本文終于介紹了分別通過(guò)Java和C++實(shí)現(xiàn)統(tǒng)計(jì)一個(gè)數(shù)字在排序數(shù)組中出現(xiàn)的次數(shù)。文中詳細(xì)介紹了實(shí)現(xiàn)思路,感興趣的小伙伴可以跟隨小編學(xué)習(xí)一下2021-12-12
Java隨機(jī)字符串與簡(jiǎn)單加密工具類(lèi)詳解
這篇文章主要介紹了Java隨機(jī)字符串與簡(jiǎn)單加密工具類(lèi),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
springMVC攔截器HandlerInterceptor用法代碼示例
這篇文章主要介紹了springMVC攔截器HandlerInterceptor用法代碼示例,具有一定借鑒價(jià)值,需要的朋友可以參考下2017-12-12
Mybatis?連接mysql數(shù)據(jù)庫(kù)底層運(yùn)行的原理分析
這篇文章主要介紹了Mybatis?連接mysql數(shù)據(jù)庫(kù)底層運(yùn)行的原理分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
詳解Java Bellman-Ford算法原理及實(shí)現(xiàn)
Bellman-Ford算法與Dijkstra算法類(lèi)似,都是以松弛操作作為基礎(chǔ),Bellman-Ford算法是對(duì)所有邊都進(jìn)行松弛操作,本文將詳解Bellman-Ford算法原理及實(shí)現(xiàn),感興趣的可以了解一下2022-07-07
Java數(shù)據(jù)結(jié)構(gòu)之雙向鏈表圖解
這篇文章主要為大家詳細(xì)介紹了Java數(shù)據(jù)結(jié)構(gòu)之雙向鏈表,文中圖解分析的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
SpringBoot+Redis實(shí)現(xiàn)消息的發(fā)布與訂閱的示例代碼
本文主要介紹了SpringBoot+Redis實(shí)現(xiàn)消息的發(fā)布與訂閱,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04

