非同步web開發專題及tomcat下的spring非同步請求配置勘誤
阿新 • • 發佈:2018-12-25
這裡提一下:
按照上面的說法,在web.xml下面配置了:
然後訪問的話你會發現:
這坑爹的又告訴你要配置async supported了。。。
然後,已經有人遇到這個問題了:
stack overflow的原話是:
經驗證,上述方法可行,然而,請看看下面文章,下面是詳細描述如何配置的,經過配置,也是可行的。
在spring mvc3.2及以上版本增加了對請求的非同步處理,是在servlet3的基礎上進行封裝的。 1、修改web.xml 複製程式碼 <?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> ... </web-app> 複製程式碼 1.1、宣告version="3.0",宣告web-app_3_0.xsd 1.2、為servlet或者filter設定啟用非同步支援:<async-supported>true</async-supported>,修改WEB應用的web.xml 複製程式碼 <!-- spring mvc --> <servlet> <servlet-name>SpringMvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>...</param-value> </init-param> <load-on-startup>1</load-on-startup> <async-supported>true</async-supported> </servlet> 複製程式碼 2、使controller類支援async 2.1、返回java.util.concurrent.Callable來完成非同步處理 複製程式碼 package org.springframework.samples.mvc.async; import java.util.concurrent.Callable; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.context.request.async.WebAsyncTask; @Controller @RequestMapping("/async/callable") public class CallableController { @RequestMapping("/response-body") public @ResponseBody Callable<String> callable() { return new Callable<String>() { @Override public String call() throws Exception { Thread.sleep(2000); return "Callable result"; } }; } @RequestMapping("/view") public Callable<String> callableWithView(final Model model) { return new Callable<String>() { @Override public String call() throws Exception { Thread.sleep(2000); model.addAttribute("foo", "bar"); model.addAttribute("fruit", "apple"); return "views/html"; } }; } @RequestMapping("/exception") public @ResponseBody Callable<String> callableWithException( final @RequestParam(required=false, defaultValue="true") boolean handled) { return new Callable<String>() { @Override public String call() throws Exception { Thread.sleep(2000); if (handled) { // see handleException method further below throw new IllegalStateException("Callable error"); } else { throw new IllegalArgumentException("Callable error"); } } }; } @RequestMapping("/custom-timeout-handling") public @ResponseBody WebAsyncTask<String> callableWithCustomTimeoutHandling() { Callable<String> callable = new Callable<String>() { @Override public String call() throws Exception { Thread.sleep(2000); return "Callable result"; } }; return new WebAsyncTask<String>(1000, callable); } @ExceptionHandler @ResponseBody public String handleException(IllegalStateException ex) { return "Handled exception: " + ex.getMessage(); } } 複製程式碼 2.2、在非同步處理完成時返回org.springframework.web.context.request.async.DeferredResult其他執行緒,例如一個JMS或一個AMQP訊息,Redis通知等等: 複製程式碼 @RequestMapping("/quotes") @ResponseBody public DeferredResult<String> quotes() { DeferredResult<String> deferredResult = new DeferredResult<String>(); // Add deferredResult to a Queue or a Map... return deferredResult; } // In some other thread... deferredResult.setResult(data); // Remove deferredResult from the Queue or Map 複製程式碼 3、spring配置檔案的修改 spring mvc的dtd的宣告必須大於等於3.2 <mvc:annotation-driven> <!-- 可不設定,使用預設的超時時間 --> <mvc:async-support default-timeout="3000"/> </mvc:annotation-driven> 實際使用示例: function deferred(){ $.get('quotes.htm',function(data){ console.log(data); deferred();//每次請求完成,再發一次請求,避免客戶端定時重新整理來獲取資料 }); } 這麼做的好處避免web server的連線池被長期佔用而引起效能問題,呼叫後生成一個非web的服務執行緒來處理,增加web伺服器的吞吐量~~ 可以看下這個blog,還不錯:http://wiselyman.iteye.com/blog/2215852