SpringBoot的DeferredResult实例:二、另一个请求控制请求的返回时机

本系列文章均采用springboot,采用同样的环境。

一、创建工程

1、 在http://start.spring.io/中创建RabbitMQHello工程:

          A、MAVEN工程

          B、2.0.0.BUILD-SNAPSHOT

          C 、Group:com.example  

          D、Artifact:RabbitMQHello

          E、Packaging:jar

          F、JavaVersion:1.8

          G、WEB、勾选Thymeleaf

2、下载工程、解压,然后导入eclipse中

3、修改pom.xml以便于热部署

A、在dependencies中增加spring-boot-devtools

      
          org.springframework.boot  
          spring-boot-devtools  
          true  
      
B、在build的spring-boot-maven-plugin中增加依赖包

      
          
              
                org.springframework.boot  
                spring-boot-maven-plugin  
                  
                      
                      
                        org.springframework  
                        springloaded  
                        1.2.6.RELEASE  
                      
                  
              
          
      

4、增加日志配置文件

在src/main/resources下增加文件logback.xml,内容如下

      
          
              
                  
                %d %p (%file:%line\)- %m%n    
                GBK   
                  
              
              
            log/base.log      
                  
                log/base.log.%d.%i      
                      
                    64 MB      
                      
                  
                  
                      
                    %d %p (%file:%line\)- %m%n    
                      
                UTF-8  
                  
              
              
                  
              
              
                  
              
        

二、編制请求、响应实体

A、请求实体RequestMsg

package com.example;

import java.io.Serializable;

public class RequestMsg implements Serializable{

	private static final long serialVersionUID = 1L;
	
	private String param;
	
	public RequestMsg() {
		super();
	}

	public RequestMsg(String param) {
		super();
		this.param = param;
	}

	public String getParam() {
		return param;
	}

	public void setParam(String param) {
		this.param = param;
	}
}
注意空的构造函数,必须有的

B、响应实体

package com.example;

import java.io.Serializable;

public class ResponseMsg implements Serializable{

	private static final long serialVersionUID = 1L;
	
	public static final Integer STATUS_SUCCESS = 0;
	public static final Integer STATUS_FAILED = -1;
	
	private int status;
	
	private String msg;
	
	private T data;

	/**
	 * 空构造函数
	 */
	public ResponseMsg() {
		super();
		
	}
	/**
	 * 全字段构造函数
	 * @param status
	 * @param msg
	 * @param data
	 */
	public ResponseMsg(int status, String msg, T data) {
		super();
		this.status = status;
		this.msg = msg;
		this.data = data;
	}
	/**
	 * 失败
	 * @param message
	 */
	public void fail(String message){
		this.setStatus(STATUS_FAILED);
		this.setMsg(message);
	}
	/**
	 * 成功
	 * @param message
	 * @param data
	 */
	public void success(String message,T data){
		this.setStatus(STATUS_SUCCESS);
		this.setMsg(message);
		this.setData(data);
	}

	public int getStatus() {
		return status;
	}

	public void setStatus(int status) {
		this.status = status;
	}

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}

	public T getData() {
		return data;
	}

	public void setData(T data) {
		this.data = data;
	}

	@Override
	public String toString() {
		return "ResponseMsg [status=" + status + ", msg=" + msg + ", data=" + data + "]";
	}

}

三、编制控制器

package com.example;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class DeferredController {
	
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@RequestMapping("/")
        public String index(Model model){
	      logger.debug("进入index");
              return "index";
        }
}
这个控制器,简单,就是返回index.html页面

四、编制rest控制器

package com.example;

import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;

@RestController
@RequestMapping("/api")
public class DeferredRestController {
	
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	
	private final Map>> responseBodyMap=new HashMap>>();
	private final Map requestBodyMap=new HashMap();
	
	/**
	 * 第一个请求
	 * @param req
	 * @return
	 */
	@RequestMapping("/request1")
	@ResponseBody
    public DeferredResult> request1(RequestMsg req){
		logger.debug("request1:请求参数{}",req.getParam());
		DeferredResult> result = new DeferredResult>();
		requestBodyMap.put(1, req);//把请求放到第一个请求map中
		responseBodyMap.put(1, result);//把请求响应的DeferredResult实体放到第一个响应map中
		return result;
    }
	
	/**
	 * 第二个请求
	 * @param req
	 * @return
	 */
	@RequestMapping("/request2")
	@ResponseBody
    public DeferredResult> request2(RequestMsg req){
		logger.debug("request2:请求参数{}",req.getParam());
		DeferredResult> result = new DeferredResult>();
		requestBodyMap.put(2, req);//把请求放到第二个请求map中
		responseBodyMap.put(2, result);//把请求响应的DeferredResult实体放到第二个响应map中
		return result;
    }
	
	/**
	 * 第三个请求
	 * @param req
	 * @return
	 */
	@RequestMapping("/request3")
	@ResponseBody
    public DeferredResult> request3(RequestMsg req){
		logger.debug("request3:请求参数{}",req.getParam());
		DeferredResult> result = new DeferredResult>();
		requestBodyMap.put(3, req);//把请求放到第三个请求map中
		responseBodyMap.put(3, result);//把请求响应的DeferredResult实体放到第三个响应map中
		return result;
    }
	
	/**
	 * 控制第x个请求执行返回操作,同时自己也返回同样的值
	 * @param x
	 * @return
	 */
	@RequestMapping(value="/requestXReturn",method=RequestMethod.POST)
	@ResponseBody
    public ResponseMsg request1Return(Integer x){
		ResponseMsg msg=new ResponseMsg();
		logger.debug("requestXReturn--1:请求参数{}",x);
		DeferredResult> result =responseBodyMap.get(x);
		if (result==null){
			msg.fail("錯誤!请求已经释放");
			return msg;
		}
		String resultStr="result"+x.toString()+". Received:"+requestBodyMap.get(x).getParam();
		msg.success("成功", resultStr);
		result.setResult(msg);//设置DeferredResult的结果值,设置之后,它对应的请求进行返回处理
		responseBodyMap.remove(x);//返回map删除
		logger.debug("requestXReturn--2:请求参数{}",x);
		logger.debug("requestXReturn--3:返回参数{}",msg);
		return msg;
    }
}
1、定义了两个map,分别用于保存请求对象和返回对象。

2、三个请求,分别把各自的请求、响应对象存放到对应键值的map中

3、控制返回的,到map中取出对象,然后对响应对象进行设值(result.setResult(msg);),使相应的请求发起链接进行返回处理。

五、页面制作

1、这个页面需要jQuery,下载jquery放到src/main/resources/static下

2、在src/main/resources/templates/下新建文件index.html




    
    DeferredResult Demo


    
第一个请求参数:
第一个请求返回:
第二个请求参数:
第二个请求返回:
第三个请求参数:
第三个请求返回:
这个页面完全的普通思路,没有任何技巧,包括六个按钮,三个请求按钮分别调用三个请求;三个请求返回控制,调用控制返回。

六、小结

整个demo,就是为了体现DeferredResult的思想。DeferredResult执行的分成两段(第一段,发起DeferredResult;第二段,等待别的线程设置DeferredResult的resukt值,DeferredResult开始执行后续事项及返回值),这两段在两个独立的线程中。通过这个模型,我们就可以实现线程的耦合。

本篇仅仅是一个简单的demo,没有考虑超时,以及公共的返回方法,在后续章节中一一呈现。


你可能感兴趣的:(springboot)