利用模板模式来实现异步回调

异步回调流程

  1. 解析报文(验证签名)

  2. 日志收集(相同)

  3. 如果解析报文成功的话,修改支付状态为已经成功.返回不同的支付结果

模版方法设计模式

提前定义好整体的骨架,不同的行为让子类实现,相同的行为直接定义在抽象类中复用。

相同的行为就定在抽象方案中,不同的行为的实现子类实现

核心设计要点

AbstractClass : 抽象类,定义并实现一个模板方法。这个模板方法定义了算法的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类去实现。
ConcreteClass : 实现父类所定义的一个或多个抽象方法。

方法一:

模版方法抽象类 

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * 使用模板方法做异步回调
 */
@Slf4j
@Component
public abstract class AbstractPayCallbackTemplate {

    /**
     * 异步回调业务
     *
     * @return
     */
    public String asyncCallBack(String params) {
        //1、支付回调验证参数
        Map<String, String> verifySignatureMap = verifySignature(params);
        //2、参数验证成功,写入日志中
        payLog(verifySignatureMap);
        String analysisCode = verifySignatureMap.get("analysisCode");
        if (!"200".equals(analysisCode)) {
            return resultFail();
        }
        //3、执行回调异步相关逻辑
        return asyncService(verifySignatureMap);
    }

    /**
     * 使用多线程异步写入日志
     *
     * @param verifySignatureMap
     */
    @Async
    protected void payLog(Map<String, String> verifySignatureMap) {
        log.info(">>>>>>>>>第二步 写入payLog........{}", verifySignatureMap);
    }

    /**
     * 支付回调验证参数
     *
     * @return
     */
    protected abstract Map<String, String> verifySignature(String params);

    /**
     * 实现业务解析操作
     *
     * @param verifySignatureMap
     * @return
     */
    protected abstract String asyncService(Map<String, String> verifySignatureMap);

    /**
     * 异步返回成功结果
     *
     * @return
     */
    protected abstract String resultSuccess();

    /**
     * 异步返回失败结果
     *
     * @return
     */
    protected abstract String resultFail();
}

具体实现模版

①AliPayCallbackTemplate 

**
 * AliPayCallbackTemplate
 */
@Slf4j
@Component
public class AliPayCallbackTemplate extends AbstractPayCallbackTemplate {

    @Override
    protected Map<String, String> verifySignature(String params) {
        log.info(">>>>>第一步 解析支付宝数据报文....params:{}", params);
        Map<String, String> verifySignature = new HashMap<>();
        verifySignature.put("price", "10000");
        verifySignature.put("orderDes", "充值会员");
        verifySignature.put("aliPaymentStatus", "1");
        verifySignature.put("aliPayOrderNumber", "20190511");
        verifySignature.put("analysisCode", "200");
        return verifySignature;
    }

    @Override
    protected String asyncService(Map<String, String> verifySignatureMap) {
        log.info(">>>>>第三步 asyncService() verifySignatureMap:{}", verifySignatureMap);
        String aliPaymentStatus = verifySignatureMap.get("aliPaymentStatus");
        if ("1".equals(aliPaymentStatus)) {
            String aliPayOrderNumber = verifySignatureMap.get("aliPayOrderNumber");
            log.info(">>>>>orderNumber:{},已经支付成功,修改订单状态为已经支付...", aliPayOrderNumber);
        }
        return resultSuccess();
    }

    @Override
    protected String resultSuccess() {
        return "支付宝支付成功";
    }

    @Override
    protected String resultFail() {
        return "支付宝支付失败";
    }

②UnionPayCallbackTemplate 

/**
 * UnionPayCallbackTemplate
 */
@Slf4j
@Component
public class UnionPayCallbackTemplate extends AbstractPayCallbackTemplate {

    @Override
    protected Map<String, String> verifySignature(String params) {
        log.info(">>>>>第一步 解析银联数据报文....params:{}", params);
        Map<String, String> verifySignature = new HashMap<>();
        verifySignature.put("price", "10000");
        verifySignature.put("orderDes", "充值会员");
        verifySignature.put("unionPaymentStatus", "1");
        verifySignature.put("unionPayOrderNumber", "20190511");
        verifySignature.put("analysisCode", "200");
        return verifySignature;
    }

    @Override
    protected String asyncService(Map<String, String> verifySignatureMap) {
        log.info(">>>>>第三步 asyncService() verifySignatureMap:{}", verifySignatureMap);
        String aliPaymentStatus = verifySignatureMap.get("unionPaymentStatus");
        if ("1".equals(unionPaymentStatus)) {
            String unionPayOrderNumber = verifySignatureMap.get("unionPayOrderNumber");
            log.info(">>>>>orderNumber:{},已经支付成功,修改订单状态为已经支付...", unionPayOrderNumber);
        }
        return resultSuccess();
    }

    @Override
    protected String resultSuccess() {
        return "银联支付成功";
    }

    @Override
    protected String resultFail() {
        return "银联支付失败";
    }

相关依赖

        <parent>
	    <groupId>org.springframework.boot</groupId>
	    <artifactId>spring-boot-starter-parent</artifactId>
	    <version>1.3.8.RELEASE</version>
	    <relativePath/>
	</parent>
	
	<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>	
		
	<dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.3.2</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
            <version>1.18.8</version>
        </dependency>

InitService

@Component
public class InitService {

    private final static Map<String, AbstractPayCallbackTemplate> payCallbackTemplateMap = new HashMap();

    @Resource(name = "aliPayCallbackTemplate")
    private AbstractPayCallbackTemplate aliPayCallbackTemplate;

    @Resource(name = "unionPayCallbackTemplate")
    private AbstractPayCallbackTemplate unionPayCallbackTemplate;

    @PostConstruct
    public void init() {
        payCallbackTemplateMap.put(PayChannelEnum.ALIPAY.getCode(), aliPayCallbackTemplate);
        payCallbackTemplateMap.put(PayChannelEnum.UNIONPAY.getCode(), unionPayCallbackTemplate);
    }

    public AbstractPayCallbackTemplate getPayCallbackTemplate(String payChannel) {
        return payCallbackTemplateMap.get(payChannel);
    }

 PayChannelEnum

public enum PayChannelEnum {

    ALIPAY("aliPay", "支付宝"),
    UNIONPAY("unionPay", "银联"),
    ;

    private final String code;
    private final String value;

    PayChannelEnum(String code, String value) {
        this.code = code;
        this.value = value;
    }

    public String getCode() {
        return code;
    }

    public String getValue() {
        return value;
    }

Controller层

/**
 * @Description TODO
 * @Date 2019/12/3 19:53
 * @Created by 王弘博
 */
@RestController
public class TestController {

    @Resource
    private InitService initService;

    @RequestMapping("/asyncCallback")
    public String asyncCallback(String payChannel) {
        AbstractPayCallbackTemplate payCallbackTemplate = initService.getPayCallbackTemplate(payChannel);
        return payCallbackTemplate.asyncCallBack("入参");

    }
}

程序入口

@EnableAsync
@SpringBootApplication
public class LoanUtilApplication {

    public static void main(String[] args) {
        SpringApplication.run(LoanUtilApplication.class, args);
    }

}

控制台输出结果

启动项目,浏览器里访问:http://localhost:8080/asyncCallback?payChannel=aliPay

浏览器里访问:http://localhost:8080/asyncCallback?payChannel=aliPay

 

 

 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------

方法二:

 定义接口PayCallback,把需要做的事情定义成接口

/**
 * @Description TODO
 * @Date 2019/12/3 20:04
 * @Created by 王弘博
 */
public interface PayCallback {

    /**
     * 验证参数
     * @param params
     * @return
     */
    Map<String, String> verifySignature(String params);

    /**
     * 使用多线程异步写入日志
     * @param verifySignatureMap
     */
    void payLog(Map<String, String> verifySignatureMap);

    /**
     * 实现业务解析操作
     * @param verifySignatureMap
     * @return
     */
    String asyncService(Map<String, String> verifySignatureMap);

    /**
     * 返回成功结果
     *
     * @return
     */
    String resultSuccess();

    /**
     * 返回失败结果
     *
     * @return
     */
    String resultFail();
}

 定义接口PayCallback的超类实现,超类里实现公用的方法

/**
 * 业务逻辑是一样的,写在超类里,如若超类不能满足,则在子类里自己扩展
 */
@Slf4j
@Component
public abstract class AbstractPayCallback implements PayCallback {


    @Override
    public void payLog(Map<String, String> verifySignatureMap) {
        log.info(">>>>>>>>>第二步 写入payLog........{}", verifySignatureMap);
    }

  }

定义子类自己独特的业务逻辑,继承超类

①AliPayCallback

/**
 * AliPayCallback
 */
@Slf4j
@Component
public class AliPayCallback extends AbstractPayCallback {

    @Override
    public Map<String, String> verifySignature(String params) {
        log.info(">>>>>第一步 解析支付宝数据报文....params:{}", params);
        Map<String, String> verifySignature = new HashMap<>();
        verifySignature.put("price", "10000");
        verifySignature.put("orderDes", "充值会员");
        verifySignature.put("aliPaymentStatus", "1");
        verifySignature.put("aliPayOrderNumber", "20190511");
        verifySignature.put("analysisCode", "200");
        return verifySignature;
    }

    @Override
    public String asyncService(Map<String, String> verifySignatureMap) {
        log.info(">>>>>第三步 asyncService() verifySignatureMap:{}", verifySignatureMap);
        String aliPaymentStatus = verifySignatureMap.get("aliPaymentStatus");
        if ("1".equals(aliPaymentStatus)) {
            String aliPayOrderNumber = verifySignatureMap.get("aliPayOrderNumber");
            log.info(">>>>>orderNumber:{},已经支付成功,修改订单状态为已经支付...", aliPayOrderNumber);
        }
        return resultSuccess();
    }


    @Override
    public String resultSuccess() {
        log.info("支付宝支付成功");
        return "支付宝支付成功";
    }

    @Override
    public String resultFail() {
        log.info("支付宝支付失败");
        return "支付宝支付失败";
    }

②UnionPayCallback

/**
 * UnionPayCallback
 */
@Slf4j
@Component
public class UnionPayCallback extends AbstractPayCallback {

    @Override
    public Map<String, String> verifySignature(String params) {
        log.info(">>>>>第一步 解析银联数据报文....params:{}", params);
        Map<String, String> verifySignature = new HashMap<>();
        verifySignature.put("price", "10000");
        verifySignature.put("orderDes", "充值会员");
        verifySignature.put("unionPaymentStatus", "1");
        verifySignature.put("unionPayOrderNumber", "20190511");
        verifySignature.put("analysisCode", "200");
        return verifySignature;
    }

    @Override
    public String asyncService(Map<String, String> verifySignatureMap) {
        log.info(">>>>>第三步 asyncService() verifySignatureMap:{}", verifySignatureMap);
        String unionPaymentStatus = verifySignatureMap.get("unionPaymentStatus");
        if ("1".equals(unionPaymentStatus)) {
            String unionPayOrderNumber = verifySignatureMap.get("unionPayOrderNumber");
            log.info(">>>>>orderNumber:{},已经支付成功,修改订单状态为已经支付...", unionPayOrderNumber);
        }
        return resultSuccess();
    }

    @Override
    public String resultSuccess() {
        log.info("银联支付成功");
        return "银联支付成功";
    }

    @Override
    public String resultFail() {
        log.info("银联支付失败");
        return "银联支付失败";
    }

定义模板接口PayServiceTemplate

public interface PayServiceTemplate {

    String execute(String params, AbstractPayCallback payCallback);
}

定义模板接口实现PayServiceTemplateImpl

/**
 * 定义模板
 */
@Component
public class PayServiceTemplateImpl implements PayServiceTemplate {

    @Override
    public String execute(String params, AbstractPayCallback payCallback) {

        Map<String, String> verifySignature = null;
        String result = null;

        try {

            verifySignature = payCallback.verifySignature(params);

            payCallback.payLog(verifySignature);

            result = payCallback.asyncService(verifySignature);

        } catch (Exception e) {

            result = "系统错误";

        } finally {

            //打印日志,清除线程变量等

        }

        return result;

    }
}

 Controller

/**
 * @Description TODO
 * @Date 2019/8/12 13:02
 * @Created by 王弘博
 */
@RestController
public class TestController {

    @Resource
    private InitService initService;

    @Resource
    private PayServiceTemplate payServiceTemplate;

    @RequestMapping("/asyncCallback")
    public String asyncCallback(String payChannel) {

        AbstractPayCallback payCallback = initService.getPayCallbackTemplate(payChannel);

        return payServiceTemplate.execute("入参", new AbstractPayCallback() {

            @Override
            public Map<String, String> verifySignature(String params) {
                return payCallback.verifySignature(params);
            }

            @Override
            public String asyncService(Map<String, String> verifySignatureMap) {
                return payCallback.asyncService(verifySignatureMap);
            }

            @Override
            public String resultSuccess() {
                return payCallback.resultSuccess();
            }

            @Override
            public String resultFail() {
                return payCallback.resultFail();
            }
        });

    }
}

 执行的时候,先走payServiceTemplate.execute这个接口,依次执行该接口里的方法,当走到

verifySignature = payCallback.verifySignature(params) 方法时,会回到controller里的

        @Override
        public Map<String, String> verifySignature(String params) {
            return payCallback.verifySignature(params);
        }

这里,然后根据payChannel走到对应的子类实现;当走到模板里的 payCallback.payLog(verifySignature)方法,就会直接执行超类里的payLog。

下面是执行结果,从结果里也可以发现,第一步解析数据不是公用的,所以走了子类;第二步是公用的方法所以走了超类...

总结

模版设计模式优缺点

1.优点
模板方法模式通过把不变的行为搬移到超类,去除了子类中的重复代码。子类实现算法的某些细节,有助于算法的扩展。通过一个父类调用子类实现的操作,通过子类扩展增加新的行为,符合“开放-封闭原则”。
2.缺点
每个不同的实现都需要定义一个子类,这会导致类的个数的增加,设计更加抽象。
3.适用场景
在某些类的算法中,用了相同的方法,造成代码的重复。控制子类扩展,子类必须遵守算法规则。

发布了165 篇原创文章 · 获赞 103 · 访问量 39万+

猜你喜欢

转载自blog.csdn.net/qq_33101675/article/details/103375322