这个过程,从页面到controller只发了一次请求.
下面是大概的代码修改过程.
1.从页面发起的post请求:
$('#tradeForm').submit(function () { $('#messages').text(''); $.post($('#tradeForm').attr("action"), $('#tradeForm').serialize(), function(response) { if (response && response.requestId) { $('#confirmations').append($.mustache(confirmation, {response : response})); } else { $('#messages').html("<p>Invalid response.</p>"); } }); return false; })2.按前文修改spring mvc支持处理异步请求.即在AbstractDispatcherServletInitializer修改filter和servlet的asyncSupport为true(其中servlet的asyncSupport已默认为true).
3.Controller接收页面请求处理的方法.
@RequestMapping(value = "/trade", method = RequestMethod.POST) @ResponseBody public DeferredResult<TradeResponse> trade(@ModelAttribute TradeRequest tradeRequest) { String ticker = tradeRequest.getTicker(); Long quantity = tradeRequest.getQuantity(); if (quantity == null || quantity <= 0 || !StringUtils.hasText(ticker)) { return null; } // Fake rest of request while UI is basic tradeRequest.setAccountName("ACCT-123"); tradeRequest.setBuyRequest(true); tradeRequest.setOrderType("MARKET"); final String requestId=UUID.randomUUID().toString(); tradeRequest.setRequestId(requestId); tradeRequest.setUserName("Joe Trader"); tradeRequest.setUserName("Joe"); this.stockServiceGateway.send(tradeRequest); DeferredResult<TradeResponse> result = new DeferredResult<TradeResponse>(30000l,null); final Map<String, DeferredResult> resultMap=clientHandler.getSuspendedTradeRequests(); resultMap.put(requestId, result); result.onCompletion(new Runnable() { @Override public void run() { resultMap.remove(requestId); } }); return result; }
这里就是向amqp服务端发送消息,DeferredResult还没有调用setResult方法,response先不提交.注意DeferredResult这个构造函数,请求时间超过第一个参数设置的时间,则返回第二个参数作为结果.对于onCompletion回调,当异步请求完成时(包括超时和网络错误),这个方法将被调用,这个方法用于检测一个不可用的DeferredResult实例是非常有用的.
4.amqp服务端的处理修改,将ExecutionVenueServiceStub.executeTradeRequest()方法的response.setRequestId(request.getId());改为response.setRequestId(request.getRequestId());这个requestId是我全程跟踪这个服票交易消息是属于那一个请求的.private Map<String, DeferredResult> suspendedTradeRequests = new ConcurrentHashMap<String, DeferredResult>(); public Map<String, DeferredResult> getSuspendedTradeRequests() { return suspendedTradeRequests; } public void handleMessage(TradeResponse response) { logger.info("Client received: " + response); DeferredResult<TradeResponse> deferredResult=suspendedTradeRequests.get(response.getRequestId()); //以防重启spring mvc服务器,延迟的信息被侦察到延时处理,从map里get为null if (deferredResult!=null){ deferredResult.setResult(response); } }这里得到相应的DeferredResult,再调用setResult,就会把response提交,回到页面显示.