modelAndView页面显示的报告问题页面

版权声明:本文为博主原创文章未经博主允许不得转载。 /u/article/details/

PS:数据在后端明明是Collection类型的为什么传到前端就能,为什么传到前端就能变成JSON的字符串呢

 

大家都知道Callable和DeferredResult可以用来进行异步请求处理。利用它们我们可以异步生成返回值,在具体处理的过程中我们直接在controller中返回相应的Callable或者DeferredResult,在这之后servlet线程将被释放,可鼡于其他连接;DeferredResult另外会有线程来进行结果处理并setResult。

在正式开始之前我们先做一点准备工作,在项目中新建了一个base模块其中包含一些提供基础支持的java类,在其他模块中可能会用到

我们定义了一个ResponseMsg的实体类来作为我们的返回值类型:


  

非常简单,里面包含了code、msg和data三个字段其中data为泛型类型。另外类的注解Data、NoArgsConstructor和AllArgsConstructor都是lombok提供的简化我们开发的主要功能分别是,为我们的类生成set和get方法生成无参构造器和生成全參构造器。使用idea进行开发的童鞋可以装一下lombok的支持插件另外,lombok的依赖参见:

 ("任务处理完成");

平时我们用的最普遍的还是阻塞调用通常请求的处理时间较短,在并发量较小的情况下使用阻塞调用报告问题页面也不是很大。
阻塞调用实现非常简单我们首先新建一个模块blockingtype,裏面只包含一个controller类用来接收请求并利用TaskService来获取结果。


  

我们请求的是getResult方法其中调用了taskService,这个taskService我们是注入得到的关于怎么跨模块注入的,其实也非常简单在本模块,加入对其他模块的依赖就可以了比如这里我们在blockingtype的("接收任务线程完成并退出");”。

涉及到较长时间的请求處理的话比较好的方式是用异步调用,比如利用Callable返回结果异步主要表现在,接收请求的servlet可以不用持续等待结果产生而可以被释放去處理其他事情。当然在调用者来看的话,其实还是表现在持续等待30秒这有利于服务端提供更大的并发处理量。
这里我们新建一个callabledemo模块在这个模块中,我们一样只包含一个TaskController另外也是需要加入base模块的依赖。只不过这里我们的返回值不是ResponseMsg类型了而是一个Callable类型。


  

在里面峩们创建了一个Callable类型的变量result,并实现了它的call方法在call方法中,我们也是调用taskService的getResult方法得到返回值并返回
下一步我们就运行一下这个模块,這里我们在模块的("任务加入队列id为:{}",taskId);

这里我们将它作为一个bean,之后会在其他bean中注入这里实际的队列为成员变量queue,它是LinkedBlockingDeque类型的还有一個成员变量为taskId,是用于自动生成任务id的并且在加入任务的方法中实现自增,以确保每个任务的id唯一性方法的话又put和take方法,分别用于向隊列中添加任务和取出任务;其中对queue的操作,分别用了offer和poll这样是实现一个非阻塞的操作,并且在队列为空和队列已满的情况下不会抛絀异常另外,大家实现的时候可以考虑使用ConcurrentLinkedQueue来高效处理并发,Sunny这里选择阻塞队列在使用的时候需要加锁。
然后我们来看步骤1中的啟动一个持续从任务队列中获取任务的线程的具体实现。

 ("接收请求开始处理...");
 //建立DeferredResult对象,设置超时时间以及超时返回超时结果
 ("接收任务線程完成并退出");

总体来说,场景不算非常复杂看到这里大家应该都能基本了解了。然后我们来跑一下测试一下我们在("接收请求,开始處理..."); //建立DeferredResult对象设置超时时间,以及超时返回超时结果 ("调用超时移除任务,此时队列长度为{}",("调用完成移除任务,此时队列长度为{}",("加入任务集合集合大小为:{}",("接收任务线程完成并退出");

和场景一中有些类似,但是注意这里在onTimeout和onCompletion中都多了一个移除元素的操作这也就是每次调鼡结束,需要将集合中的DeferredResult对象移除即集合中保存的都是等待请求结果的DeferredResult对象。
然后我们看处理请求结果的Controller:


  

看起来非常简单只是做了兩个操作,接收得到的参数并利用参数生成一个ResponseMsg<String>对象随后将集合中的所有DeferredResult都设定结果为根据参数生成的ResponseMsg<String>对象。最后返回一个提示:成功設置结果...
好了话不多说,我们来启动测试验证一下我们说一下验证的过程,我们同时打开两个请求然后再设定一个结果,最后两个請求都会得到这个结果当然同时多个或者一个请求也是一样。这里有一个地方需要注意一下:

浏览器可能会对相同的url请求有缓存策略吔就是同时两个标签向同一个url发送请求,浏览器只会先发送一个请求等一个请求结束才会再发送另外一个请求。

这样我们考虑从两个瀏览器中发送请求:


  

然后随便找其中一个,发送请求来设置结果:


  

首先我们先启动模块可以从控制台中看到完美启动管理了:


  

完美启动,接下来Sunny在火狐中发起一个请求

可以看到正在等待请求结果随后我们在谷歌浏览器中发起请求


两个请求同时处于等待状态,这时候我们看一下控制台信息:


  

可以看到两个请求都已经接收到了并且加入了队列。这时候我们再发送一个设置结果的请求。

随后我们查看两个調用请求的页面发现页面已经不在等待状态中了,都已经得到了结果


另外,再给大家展示一下超时的结果即我们发起调用请求,但昰不发起设置结果的请求等待时间结束。


  

想要完整代码的童鞋可以查看fork实践。

我要回帖

更多关于 报告问题页面 的文章

 

随机推荐