为Spring MVC开启异步任务

为Spring MVC开启异步任务

配置自定义AsyncTaskExecutor

package com.spider.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

@Configuration
public class AsyncConfig extends WebMvcConfigurationSupport {

    public ThreadPoolTaskExecutor getAsyncExecutor() {

        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(30);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("ronnie-task-");
        executor.initialize();
        return executor;
    }

    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {

        configurer.setTaskExecutor(getAsyncExecutor());
        super.configureAsyncSupport(configurer);
    }
}

开启日志DEGUB级别

在application.properties中加入

logging.level.org.springframework.web=DEBUG

定义一个Service用来测试

package com.spider.manager.service;

import com.spider.manager.model.User;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class GitHubLookupService {

    RestTemplate restTemplate = new RestTemplate();

    public User findUser(String user) throws InterruptedException {

        System.out.println("Looking up " + user);
        User results = restTemplate.getForObject("https://api.github.com/users/" + user, User.class);
        Thread.sleep(5000L);//sleep 5s,可以更显著的看到效果
        return results;
    }

}

定义一个Controller处理请求

package com.spider.manager.controller;

import com.spider.manager.model.User;
import com.spider.manager.service.GitHubLookupService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
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.servlet.ModelAndView;

import javax.servlet.http.HttpSession;
import java.util.concurrent.Callable;

@Controller
public class RobotController {

    @Autowired
    private GitHubLookupService gitHubLookupService;

    @RequestMapping(value = "/async", produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public Callable<User> async() {

        return new Callable<User>() {

            @Override
            public User call() throws Exception {

                return gitHubLookupService.findUser("CloudFoundry");
            }
        };
    }
}

启动服务,从浏览器访问

我的地址是http://localhost:8081/spider-web/async

大约5s后返回如下结果

{“name”:”Cloud Foundry”,”blog”:”https://www.cloudfoundry.org/“}

查看日志

2016-05-06 14:34:30.097 DEBUG 12004 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet        : DispatcherServlet with name ‘dispatcherServlet‘ processing GET request for [/spider-web/async]
2016-05-06 14:34:30.102 DEBUG 12004 --- [nio-8081-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /async
2016-05-06 14:34:30.106 DEBUG 12004 --- [nio-8081-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Returning handler method [public java.util.concurrent.Callable<com.spider.manager.model.User> com.spider.manager.controller.RobotController.testPerformance(javax.servlet.http.HttpSession)]
2016-05-06 14:34:30.107 DEBUG 12004 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet        : Last-Modified value for [/spider-web/async] is: -1
2016-05-06 14:34:30.133 DEBUG 12004 --- [nio-8081-exec-1] o.s.w.c.request.async.WebAsyncManager    : Concurrent handling starting for GET [/spider-web/async]
2016-05-06 14:34:30.135 DEBUG 12004 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet        : Leaving response open for concurrent processing
Looking up CloudFoundry
2016-05-06 14:34:30.158 DEBUG 12004 --- [      MvcAsync1] o.s.web.client.RestTemplate              : Created GET request for "https://api.github.com/users/ronniewang"
2016-05-06 14:34:30.203 DEBUG 12004 --- [      MvcAsync1] o.s.web.client.RestTemplate              : Setting request Accept header to [application/json, application/*+json]
2016-05-06 14:34:33.691 DEBUG 12004 --- [      MvcAsync1] o.s.web.client.RestTemplate              : GET request for "https://api.github.com/users/ronniewang" resulted in 200 (OK)
2016-05-06 14:34:33.692 DEBUG 12004 --- [      MvcAsync1] o.s.web.client.RestTemplate              : Reading [class com.spider.manager.model.User] as "application/json;charset=utf-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@6b4d3f3f]
2016-05-06 14:34:38.713 DEBUG 12004 --- [      MvcAsync1] o.s.w.c.request.async.WebAsyncManager    : Concurrent result value [User [name=Ronnie Wang, blog=http://blog.csdn.net/ro_wsy]] - dispatching request to resume processing
2016-05-06 14:34:38.719 DEBUG 12004 --- [nio-8081-exec-2] o.s.web.servlet.DispatcherServlet        : DispatcherServlet with name ‘dispatcherServlet‘ resumed processing GET request for [/spider-web/async]
2016-05-06 14:34:38.719 DEBUG 12004 --- [nio-8081-exec-2] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /async
2016-05-06 14:34:38.719 DEBUG 12004 --- [nio-8081-exec-2] s.w.s.m.m.a.RequestMappingHandlerMapping : Returning handler method [public java.util.concurrent.Callable<com.spider.manager.model.User> com.spider.manager.controller.RobotController.testPerformance(javax.servlet.http.HttpSession)]
2016-05-06 14:34:38.719 DEBUG 12004 --- [nio-8081-exec-2] o.s.web.servlet.DispatcherServlet        : Last-Modified value for [/spider-web/async] is: -1
2016-05-06 14:34:38.720 DEBUG 12004 --- [nio-8081-exec-2] s.w.s.m.m.a.RequestMappingHandlerAdapter : Found concurrent result value [User [name=Ronnie Wang, blog=http://blog.csdn.net/ro_wsy]]
2016-05-06 14:34:38.761 DEBUG 12004 --- [nio-8081-exec-2] m.m.a.RequestResponseBodyMethodProcessor : Written [User [name=Ronnie Wang, blog=http://blog.csdn.net/ro_wsy]] as "application/json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@2fdcfec0]
2016-05-06 14:34:38.761 DEBUG 12004 --- [nio-8081-exec-2] o.s.web.servlet.DispatcherServlet        : Null ModelAndView returned to DispatcherServlet with name ‘dispatcherServlet‘: assuming HandlerAdapter completed request handling
2016-05-06 14:34:38.761 DEBUG 12004 --- [nio-8081-exec-2] o.s.web.servlet.DispatcherServlet        : Successfully completed request

可以看出其中涉及3个线程,确实实现了异步调用

更多信息

关于异步任务的更多解释,可参考下面的文章

https://spring.io/blog/2012/05/10/spring-mvc-3-2-preview-making-a-controller-method-asynchronous/

https://spring.io/blog/2012/05/07/spring-mvc-3-2-preview-introducing-servlet-3-async-support

时间: 2024-12-28 00:34:19

为Spring MVC开启异步任务的相关文章

spring mvc对异步请求的处理

在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

Spring MVC的异步模式

高性能的关键:Spring MVC的异步模式 我承认有些标题党了,不过话说这样其实也没错,关于“异步”处理的文章已经不少,代码例子也能找到很多,但我还是打算发表这篇我写了好长一段时间,却一直没发表的文章,以一个更简单的视角,把异步模式讲清楚. 什么是异步模式 要知道什么是异步模式,就先要知道什么是同步模式,先看最典型的同步模式: (图1) 浏览器发起请求,Web服务器开一个线程处理,处理完把处理结果返回浏览器.好像没什么好说的了,绝大多数Web服务器都如此般处理.现在想想如果处理的过程中需要调用

Spring MVC的异步模式DefferedResult

原文:http://www.importnew.com/21051.html 什么是异步模式 要知道什么是异步模式,就先要知道什么是同步模式,先看最典型的同步模式: (图1) 浏览器发起请求,Web服务器开一个线程处理,处理完把处理结果返回浏览器.好像没什么好说的了,绝大多数Web服务器都如此般处理.现在想想如果处理的过程中需要调用后端的一个业务逻辑服务器,会是怎样呢? (图2) 调就调吧,上图所示,请求处理线程会在Call了之后等待Return,自身处于阻塞状态.这也是绝大多数Web服务器的做

高性能的关键:Spring MVC的异步模式

我承认有些标题党了,不过话说这样其实也没错,关于“异步”处理的文章已经不少,代码例子也能找到很多,但我还是打算发表这篇我写了好长一段时间,却一直没发表的文章,以一个更简单的视角,把异步模式讲清楚. 什么是异步模式 要知道什么是异步模式,就先要知道什么是同步模式,先看最典型的同步模式: (图1) 浏览器发起请求,Web服务器开一个线程处理,处理完把处理结果返回浏览器.好像没什么好说的了,绝大多数Web服务器都如此般处理.现在想想如果处理的过程中需要调用后端的一个业务逻辑服务器,会是怎样呢? (图2

Spring MVC 异步测试

从spring3.2开始,支持servlet3的异步请求,这对于处理耗时的请求如缓慢的数据库查询是非常有好处的,不至于很快的耗光servlet的线程池,影响可扩展性. 让我们先来了解一下servlet是怎么处理异步操作的: 通过调用request.startAsync(),ServletRequest就变成异步模式.主要的影响是Servlet.Filter会退出,但是Response保持打开用来完成请求处理. 调用request.startAsync()返回AsyncContext实例,可进一步

Spring MVC(二)基于标注的MVC

1.基于标注的Spring MVC 1.1 建立一个项目导入jar包(ioc aop mvc) 拷贝容器对应的配置文件到src下 在WEB-INF建立一个login.jsp 1.2 在web.xml 配置一个DispatcherServlet 并且使用 初始化参数 contextConfigLocation 关联容器对应的配置文件 1.3 开启基于标注 Spring MVC 开启组件扫描 <context:component-scan base-package="" />

Spring MVC【入门】

MVC 设计概述 在早期 Java Web 的开发中,统一把显示层.控制层.数据层的操作全部交给 JSP 或者 JavaBean 来进行处理,我们称之为 Model1: 出现的弊端: JSP 和 Java Bean 之间严重耦合,Java 代码和 HTML 代码也耦合在了一起 要求开发者不仅要掌握 Java ,还要有高超的前端水平 前端和后端相互依赖,前端需要等待后端完成,后端也依赖前端完成,才能进行有效的测试 代码难以复用 正因为上面的种种弊端,所以很快这种方式就被 Servlet + JSP

spring mvc 和ajax异步交互完整实例

Spring MVC 异步交互demo: 1.jsp页面: <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR

spring mvc 和ajax异步交互完整实例(转自CSDN) 附下载地址

spring mvc 和ajax异步交互完整实例 spring MVC 异步交互demo: demo下载地址:http://download.csdn.net/download/quincylk/9521375 1.jsp页面: [java] view plain copy print? <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-