`

Spring MVC 的异步模式

 
阅读更多

浏览器发起请求,Web服务器会开一个线程处理,该线程会等待处理结果,自身处于阻塞状态,处理完把处理结果返回浏览器。但是,因为请求处理线程的总数是有限的,如果类似的请求多了,所有的处理线程处于阻塞的状态,那新的请求也就无法处理了,也就所谓影响了服务器的吞吐能力。要更加好地发挥服务器的全部性能,就要使用异步。

异步请求最大的不同在于请求处理线程调用了之后直接返回,而不等待,这样请求处理线程就“自由”了,它可以接着去处理别的请求,当后端处理完成后,会钩起一个回调处理线程来处理调用的结果,这个回调处理线程跟请求处理线程也许都是线程池中的某个线程,相互间可以完全没有关系,由这个回调处理线程向浏览器返回内容。这就是异步的过程。

 

Spring MVC的使用 -- DefferedResult

要使用Spring MVC的异步功能,你得先确保你用的是Servlet 3.0或以上的版本

<dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
</dependency>
<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>4.2.3.RELEASE</version>
</dependency>

 

传统的同步模式的Controller是返回ModelAndView,而异步模式则是返回DeferredResult<ModelAndView>

@RequestMapping(value="/asynctask", method = RequestMethod.GET)
public DeferredResult<ModelAndView> asyncTask(){
    DeferredResult<ModelAndView> deferredResult = new DeferredResult<ModelAndView>();
    System.out.println("/asynctask 调用!thread id is : " + Thread.currentThread().getId());
    longTimeAsyncCallService.makeRemoteCallAndUnknownWhenFinish(
        new LongTermTaskCallback() {
            @Override
            public void callback(Object result) {
                System.out.println("异步调用执行完成, thread id is : " + 
                    Thread.currentThread().getId());
                ModelAndView mav = new ModelAndView("remotecalltask");
                mav.addObject("result", result);
                deferredResult.setResult(mav);
            }
        });
}

longTimeAsyncCallService是自定义的一个模拟长时间异步调用的服务类,调用之,立即返回,当它处理完成时,就钩起一个线程调用我们提供的回调函数。

public interface LongTermTaskCallback {
    void callback(Object result);
}

public class LongTimeAsyncCallService {
    private final int CorePoolSize = 4;
    private final int NeedSeconds = 3;
    private Random random = new Random();
    private ScheduledExecutorService scheduler = 
        Executors.newScheduledThreadPool(CorePoolSize);
    public void makeRemoteCallAndUnknownWhenFinish(LongTermTaskCallback callback){
        System.out.println("完成此任务需要 : " + NeedSeconds + " 秒");
        scheduler.schedule(new Runnable() {
            @Override
            public void run() {
                callback.callback("长时间异步调用完成.");
            }
        }, "这是处理结果:)", TimeUnit.SECONDS);
    }
}

输出的结果是:

/asynctask 调用!thread id is : 46
完成此任务需要 : 3 秒
异步调用执行完成, thread id is : 47

由此可见返回结果的线程和请求处理线程不是同一线程。

 

返回DefferedResult<ModelAndView>并非唯一做法,还可以返回WebAsyncTask来实现“异步”,但略有不同,不同之处在于返回WebAsyncTask的话是不需要我们主动去调用Callback的

@RequestMapping(value="/longtimetask", method = RequestMethod.GET)
public WebAsyncTask longTimeTask(){
    System.out.println("/longtimetask被调用 thread id is : " + Thread.currentThread().getId());
    Callable<ModelAndView> callable = new Callable<ModelAndView>() {
        public ModelAndView call() throws Exception {
            Thread.sleep(3000); //假设是一些长时间任务
            ModelAndView mav = new ModelAndView("longtimetask");
            mav.addObject("result", "执行成功");
            System.out.println("执行成功 thread id is : " + Thread.currentThread().getId());
            return mav;
        }
    };
    return new WebAsyncTask(callable);
}

其核心是一个Callable<ModelAndView>,事实上,直接返回Callable<ModelAndView>都是可以的。

和前一个方案的差别在于这个Callable的call方法并不是我们直接调用的,而是在longTimeTask返回后,由Spring MVC用一个工作线程来调用,执行。

打印出来的结果:

/longtimetask被调用 thread id is : 56
执行成功 thread id is : 57

 

处理超时

WebAsyncTask方式

@RequestMapping(value="/longtimetask", method = RequestMethod.GET)
public WebAsyncTask longTimeTask(){
    System.out.println("/longtimetask被调用 thread id is : " + Thread.currentThread().getId());
    Callable<ModelAndView> callable = new Callable<ModelAndView>() {
        public ModelAndView call() throws Exception {
            Thread.sleep(3000); //假设是一些长时间任务
            ModelAndView mav = new ModelAndView("longtimetask");
            mav.addObject("result", "执行成功");
            System.out.println("执行成功 thread id is : " + Thread.currentThread().getId());
            return mav;
        }
    };
    
    
    WebAsyncTask asyncTask = new WebAsyncTask(2000, callable);
    asyncTask.onTimeout(
            new Callable<ModelAndView>() {
                public ModelAndView call() throws Exception {
                    ModelAndView mav = new ModelAndView("longtimetask");
                    mav.addObject("result", "执行超时");
                    System.out.println("执行超时 thread id is :" + 
                        Thread.currentThread().getId());
                    return mav;
                }
            }
    );
    return new WebAsyncTask(3000, callable);
}

 

DefferedResult方式

@RequestMapping(value = "/asynctask", method = RequestMethod.GET)
    public DeferredResult<ModelAndView> asyncTask() {
        DeferredResult<ModelAndView> deferredResult = 
            new DeferredResult<ModelAndView>(2000L);
        System.out.println("/asynctask 调用!thread id is : " + 
            Thread.currentThread().getId());
        longTimeAsyncCallService.makeRemoteCallAndUnknownWhenFinish(
            new LongTermTaskCallback() {
                @Override
                public void callback(Object result) {
                    System.out.println("异步调用执行完成, thread id is : " + 
                        Thread.currentThread().getId());
                    ModelAndView mav = new ModelAndView("remotecalltask");
                    mav.addObject("result", result);
                    deferredResult.setResult(mav);
                }
            });

        deferredResult.onTimeout(new Runnable() {
            @Override
            public void run() {
                System.out.println("异步调用执行超时!thread id is : " + 
                    Thread.currentThread().getId());
                ModelAndView mav = new ModelAndView("remotecalltask");
                mav.addObject("result", "异步调用执行超时");
                deferredResult.setResult(mav);
            }
        });

        return deferredResult;
    }

 

http://www.cnblogs.com/guogangj/p/5457959.html#3555455

分享到:
评论

相关推荐

    Spring MVC异步模式

    首先,我们需要了解Spring MVC异步模式的基本概念。在传统的同步处理中,请求到达服务器后,服务器会分配一个线程来处理该请求,直到请求完成才会释放线程。而在异步模式下,服务器接收请求后不会立即返回结果,而是...

    最全的Spring MVC注解例子,异步请求,错误处理

    在这个“最全的Spring MVC注解例子”中,我们将深入探讨Spring MVC的核心注解,以及如何实现异步请求处理和错误管理。 1. **Spring MVC核心注解** - `@Controller`:标记一个类为处理HTTP请求的控制器。这是Spring...

    Spring MVC 4.2.3

    9. **异步处理支持**:Spring MVC支持异步处理请求,允许在不阻塞线程的情况下执行耗时的操作,从而提高系统性能。 10. **国际化和本地化**:通过消息源和LocaleResolver,Spring MVC可以轻松实现应用的多语言支持...

    spring mvc 4.0

    8. **异步处理**:Spring MVC 4.0引入了异步请求处理,通过@ControllerAdvice和@Async注解,可以实现后台任务的异步执行,提高响应速度。 9. **多Part文件上传**:支持多文件上传,利用MultipartFile接口处理上传...

    Mastering Spring MVC 4(2015.09)源码

    首先,Spring MVC 4基于Servlet 3.0规范,这意味着它可以利用异步处理能力,提高了Web应用的性能。通过AsyncSupport和AsyncConfigurer接口,开发者可以轻松地创建异步控制器,处理高并发场景。 控制器(Controller...

    Spring MVC 教程快速入门 深入分析

    Spring MVC是一种基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,使用了IoC容器,支持RESTful风格的应用程序开发。Spring MVC通过分离模型(Model)、视图(View)和控制器(Controller)来简化Web开发...

    详解Spring MVC的异步模式(高性能的关键)

    以下是一个简单的Spring MVC异步处理示例: ```java @RequestMapping(value="/asynctask", method = RequestMethod.GET) public DeferredResult&lt;ModelAndView&gt; asyncTask(){ DeferredResult&lt;ModelAndView&gt; ...

    spring MVC .docx

    14. **Asynchronous Request Processing**: Spring MVC支持异步请求处理,可以通过`@Async`注解实现后台任务的并发执行。 15. **Internationalization (i18n) and Localization (l10n)**: Spring MVC提供对国际化和...

    Spring mvc 教程

    - **异步请求的处理**:Spring MVC 支持异步处理,可以提高应用的响应性和性能。 - **对控制器测试**:Spring 提供了工具和支持来方便地测试控制器的行为。 #### 处理器映射 (Handler Mapping) - **使用 ...

    maven与spring MVC

    【标题】"maven与spring MVC"涉及到的是Java Web开发中的两个关键组件——Maven和Spring MVC,它们在构建和管理复杂项目时起着至关重要的作用。Maven是一个项目管理和综合工具,它通过提供一个标准化的构建过程和...

    spring mvc 整合包

    15. **AJAX集成**:Spring MVC与jQuery、AngularJS等前端库配合,可以实现异步数据交互。 这个"spring mvc 整合包"可能包含了Spring MVC的jar文件、配置示例、启动脚本或者示例代码,帮助开发者快速启动基于Spring ...

    精通spring mvc 4 看透springmvc pdf 高清完全版

    Spring MVC是Spring框架的一部分,专门用于构建Web应用程序,它提供了模型-视图-控制器(MVC)架构模式的实现,使得开发人员能够更高效地开发和维护Web应用。 本书首先介绍了Spring MVC的基础知识,包括如何搭建...

    Spring MVC跟jQuery和Twitter Bootstrap的结合

    在Spring MVC项目中,jQuery 可以用于前端页面的动态操作,如表单验证、异步数据加载、DOM元素操作等。通过Ajax,jQuery可以与后台Spring MVC控制器进行无刷新的数据交互,提升用户体验。 **Twitter Bootstrap 的...

    spring mvc

    15. **Async Support**: Spring MVC 提供异步处理支持,通过@Async注解可以将方法标记为异步执行,提高系统性能。 以上是Spring MVC框架的核心知识点,它们构成了一个功能强大且灵活的Web开发框架,使得开发者能够...

    Spring MVC Cookbook(PACKT,2016).pdf

    《Spring MVC Cookbook》是由PACKT Publishing在2016年出版的一本专著,主要针对Spring MVC框架提供了实用的解决方案和技巧。Spring MVC是Spring框架的一部分,它为构建基于Java的Web应用程序提供了一个模型-视图-...

    spring MVC基础学习

    在Spring MVC中,开发者可以利用模型-视图-控制器(MVC)架构模式来分离业务逻辑、数据处理和用户界面。下面我们将深入探讨Spring MVC的基础知识。 1. **核心组件**: - DispatcherServlet:作为Spring MVC的前端...

    spring mvc+ajax

    将Spring MVC与Ajax结合使用,可以实现页面的异步更新,提升用户体验,同时保持服务器负载均衡。 首先,我们需要理解Spring MVC的基本工作流程。当用户发起请求时,Spring MVC的DispatcherServlet会拦截这个请求,...

    Spring MVC 文件上传下载 后端 - Java.zip

    6. **优化**:为了提高性能,可以使用异步处理文件上传和下载,利用Spring MVC的AsyncController或者Servlet 3.0的异步处理特性。另外,对于大文件操作,可以考虑分块上传和下载。 7. **实际应用场景**:这些功能...

Global site tag (gtag.js) - Google Analytics