- Servlet 3开始支持异步请求处理
- Spring MVC 3.2开始支持Servlet3的这项特性
- controller可以从另外一个线程返回一个java.util.concurrent.Callable,而不是一个简单的值
1. 此时Servlet容器线程已经释放,可以处理其他的请求
2. Spring MVC通过借助TaskExecutor调起另外一个线程(例子中的mvcTaskExecutor) - controller也可以从另外一个线程返回一个DeferredResult
此时,Spring MVC并不知道这个线程的存在
比如一个定时任务
演示
- 在05点睛Spring MVC 4.1-服务器端推送中,我们也演示了通过SSE实现长连接
1. 但在IE的一些版本是不支持的
- 本例通过Spring MVC对异步处理的支持来演示长连接的支持,即服务器端推送
1.支持所有浏览器
- Servlet开启异步支持
1. 建立 Controller
@Controller @RequestMapping(value = {"/test"}) public class TestController { @Autowired AysncService aysncService; //https://blog.csdn.net/qq_34652458/article/details/80331275 @RequestMapping("/async") public String async() { return "async"; } @RequestMapping("/call") @ResponseBody public Callable<String> asyncCall() { SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String preDate = df.format(new Date()); System.out.println("==================call======preDate==============" + preDate); //借助mvcTaskExecutor在另外一个线程调用 //此时Servlet容器线程已经释放,可以处理其他的请求 return new Callable<String>() { @Override public String call() throws Exception { Thread.sleep(5000); String afterDate = df.format(new Date()); System.out.println("++++++++++++++++++++date+++++++++++++++++++afterDate=" + afterDate); return "Async Hello World " + afterDate; } }; } @RequestMapping("/defer") @ResponseBody public DeferredResult<String> deferredCall() { //调用aysncService的getAsyncUpdate方法 //deferredResult被计划任务每五秒钟更新一次 return aysncService.getAsyncUpdate(); } }
2. 创建Service
@Service @EnableScheduling public class AysncService { private DeferredResult<String> deferredResult; public DeferredResult<String> getAsyncUpdate() { deferredResult = new DeferredResult<String>(); System.out.println("================getAsyncUpdate============"); return deferredResult; } @Scheduled(fixedDelay = 5000) public void refresh() { if (deferredResult != null) { SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String preDate = df.format(new Date()); System.out.println("==================call======preDate==============" + preDate); deferredResult.setResult(preDate); } } }
3. Spring 配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <bean name="threadPoolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <property name="corePoolSize" value="10"></property> <property name="queueCapacity" value="100"></property> <property name="maxPoolSize" value="25"></property> </bean> <mvc:annotation-driven > <mvc:async-support default-timeout="30000" task-executor="threadPoolTaskExecutor"/> </mvc:annotation-driven> <context:component-scan base-package="com.spring_101_200.test_181_190.test_186_spring_mvc_async"></context:component-scan> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"></property> <property name="suffix" value=".jsp"></property> </bean> </beans>
4.创建 web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee" xmlns:web="http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee"> <display-name>spring_tiny</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring_101_200/config_181_190/spring186.xml</param-value> </context-param> <servlet> <servlet-name>spring_tiny</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> <async-supported>true</async-supported> </servlet> <servlet-mapping> <servlet-name>spring_tiny</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.jpg</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.css</url-pattern> </servlet-mapping> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <jsp-config> <taglib> <taglib-uri>http://www.codecoord.com</taglib-uri> <taglib-location>/WEB-INF/c.tld</taglib-location> </taglib> </jsp-config> </web-app>
5.测试