http接口服务方结合策略模式实现总结

  在项目中,我们经常会使用到http+xml的接口,而且不仅仅的是一个,可能会有多个http的接口需要实时的交互.但是http接口的接收消息的公共部分是一样的,只有每个接口的报文解析和返回报文是不同的,此时考虑到把变化和不变化的隔离出来,采取用策略模式,把公共的部分代码抽取隔离出来,每个http接口的不同的处理逻辑单独自己处理,这样也方便了后期的修改和扩展,可以很方便的修改单独的接口处理逻辑和添加新的http接口到项目中使用,而不用修改以前的设计.下面就http+xml接口的接收采用简单的策略模式实现:

项目的基础:SSH架构

首先实现BaseReceiveHttpIntfAction 基类,实时的接收报文动作和返回结果报文动作:具体的解析逻辑和获取返回报文逻辑抽取隔离出去:

/**
 * 〈一句话功能简述〉<br>
 * 〈功能详细描述〉 http 接收接口基类实现  父类实现为prototype  不是单例的
 *
 * 基于策略模式  后面增加子类接收实现的方法 请参照:CrmReceiveHttpIntfAction的实现
 *
 * @author lilin
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
@Controller
@Scope(value = "prototype")
public abstract class BaseReceiveHttpIntfAction extends BasicAction {
    /**
     */
    private static final long serialVersionUID = -4667071743433536439L;

    private IHttpMessageHandle httpMessageHandle;

    /**
     *
     * 功能描述: <br>
     * 〈功能详细描述〉用于 子类 注入父类属性
     *
     * @param httpMessageHandle
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public void setHttpMessageHandle(IHttpMessageHandle httpMessageHandle) {
        this.httpMessageHandle = httpMessageHandle;
    }

    public String doBusiness() {
        InputStream inputStream = null;
        try {
            inputStream = request.getInputStream();
        } catch (IOException e1) {
            logger.error("IOException: ", e1);
        }
        logger.info("@@HttpClient 解析接收报文:");
        SAXReader sb = new SAXReader();
        String returnStr = null;
        try {
            Document document = sb.read(inputStream);
            logger.info(document.asXML());
            // 保存报文信息
            Map<String, Object> map = httpMessageHandle.handleMessage(document);
            // 拼接返回报文
            returnStr = httpMessageHandle.getResponseMsg(map, document);
            logger.info("@@ 报文解析成功!");
        } catch (DocumentException e) {
            logger.info("@@HttpClient 解析报文出错!", e);
        }
        logger.info("@@ 返回报文 : " + returnStr);
        writeResponse(returnStr, response);
        return null;
    }

    /**
     *
     * 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @param respXML
     * @param response
     * @throws IOException
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private void writeResponse(String respXML, HttpServletResponse response) {
        OutputStream out = null;
        try {
            byte[] data = respXML.getBytes("UTF-8");
            out = response.getOutputStream();
            out.write(data);
        } catch (IOException e) {
            logger.error("Write response error: ", e);
        } finally {
            if (out != null) {
                try {
                    out.flush();
                    out.close();
                } catch (IOException e) {
                    logger.error("IOException: ", e);
                }
            }
        }
    }

}

然后:规定好子类需要注入的公共接口IHttpMessageHandle, 接口定义需要解析报文的解析方法,以及获取放回报文的方法:

/**
 * 〈一句话功能简述〉<br>
 * 〈功能详细描述〉
 *
 * @author lilin
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
public interface IHttpMessageHandle {

    /**
     *
     * 功能描述: <br>
     * 〈功能详细描述〉处理接收到的报文信息
     *
     * @param document
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    Map<String, Object> handleMessage(Document document);

    /**
     *
     * 功能描述: <br>
     * 〈功能详细描述〉获取需要返回的报文信息
     *
     * @param map
     * @param document
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */

    String getResponseMsg(Map<String, Object> map, Document document);

}

然后:实现实际的处理报文信息的类:CrmHttpMessageHandle 实时处理CRM系统发送的xml报文信息,实时组装需要返回的报文信息:

/**
 * 〈一句话功能简述〉<br>
 * 〈功能详细描述〉
 *
 * @author lilin
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
@Service
public class CrmHttpMessageHandle implements IHttpMessageHandle {

    private Logger logger = Logger.getLogger(CrmHttpMessageHandle.class);

    @Resource
    private LowPriceTaskService lowPriceTaskService;

    @Override
    public String getResponseMsg(Map<String, Object> map, Document document) {
        logger.info("CrmHttp Get ResponseMsg:");

        printLogByEntry(map);

        Document doc = DocumentHelper.createDocument();
        // MbfService 拼接
        Element mbfService = DocumentHelper.createElement("MbfService");
        doc.add(mbfService);
        Element output1 = DocumentHelper.createElement("output1");
        mbfService.add(output1);

        // MbfHeader 拼接
        Element mbfHeader = DocumentHelper.createElement("MbfHeader");
        output1.add(mbfHeader);

        PriceCommonService.addElement(mbfHeader, "ServiceCode", (String) map.get("ServiceCode"));
        PriceCommonService.addElement(mbfHeader, "Operation", (String) map.get("Operation"));
        PriceCommonService.addElement(mbfHeader, "AppCode", (String) map.get("AppCode"));
        PriceCommonService.addElement(mbfHeader, "UId", (String) map.get("UId"));

        // ServiceResponse 拼接
        Element serviceResponse = DocumentHelper.createElement("ServiceResponse");
        mbfHeader.add(serviceResponse);

        PriceCommonService.addElement(serviceResponse, "Status", null);
        PriceCommonService.addElement(serviceResponse, "Code", null);
        PriceCommonService.addElement(serviceResponse, "Desc", null);

        // MbfBody 拼接
        Element mbfBody = DocumentHelper.createElement("MbfBody");
        output1.add(mbfBody);

        PriceCommonService.addElement(mbfBody, "reFlag", (String) map.get("reFlag"));
        PriceCommonService.addElement(mbfBody, "errorMessage", (String) map.get("errorMessage"));

        logger.info("CrmHttp Final ResponseMsg:" + doc.asXML());
        return doc.asXML();
    }

    @Override
    public Map<String, Object> handleMessage(Document document) {
        logger.info("CrmHttp Start HandleMessage:");

        Map<String, Object> res = new HashMap<String, Object>();
        LowPriceTask task = new LowPriceTask();

        Element root = document.getRootElement();
        Element outElement = root.element("input1");

        Element mbfHeader = outElement.element("MbfHeader");

        String serviceCode = mbfHeader.elementTextTrim("ServiceCode");
        res.put("ServiceCode", serviceCode);
        logger.info("## ServiceCode : " + serviceCode);
        String operation = mbfHeader.elementTextTrim("Operation");
        res.put("Operation", operation);
        logger.info("## operation : " + operation);
        String appCode = mbfHeader.elementTextTrim("AppCode");
        res.put("AppCode", appCode);
        logger.info("##  appCode : " + appCode);
        String uId = mbfHeader.elementTextTrim("UId");
        res.put("UId", uId);
        logger.info("##  uId : " + uId);

        // 设置返回值
        if (!StringUtils.isEmpty(serviceCode) && !StringUtils.isEmpty(operation)) {
            task.setMsg(document.asXML());
            task.setScanNum(0);
            task.setScanResult("F");
            task.setStoreTime(DateUtils.getDate2());

            lowPriceTaskService.saveTask(task);

            res.put("reFlag", "S");
            res.put("errorMessage", "S");
            logger.info("@@HttpClient 保存报文信息成功!");
        } else {
            res.put("reFlag", "E");
            res.put("errorMessage", "报文头有问题");
        }

        return res;
    }

最后:实现实际的接收报文信息的子类action:继承基类,实时注入父类的接口实现,最终提供给客户端的url:http://lilin.com/lilin-web/crmReceiveHttpIntfAction.do

/**
 * 〈一句话功能简述〉<br>
 * 〈功能详细描述〉
 *
 * @author lilin
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
@Controller
public class CrmReceiveHttpIntfAction extends BaseReceiveHttpIntfAction {

    /**
     */
    private static final long serialVersionUID = -104341558961432099L;

    @Resource
    private IHttpMessageHandle crmHttpMessageHandle;

    @PostConstruct
    public void injectHttpMessageHandle() {
        super.setHttpMessageHandle(crmHttpMessageHandle);
    }
}

这样,简单的http+xml报文+策略模式的实现,就完成了.后期需要扩展新的接口接口使用,只要仅仅实现自己的

1,接收子类<参考CrmReceiveHttpIntfAction >

2,消息处理类:<参考CrmHttpMessageHandle>

3,提供最终的服务方的url给客户端调用即可;

时间: 2024-10-19 05:14:42

http接口服务方结合策略模式实现总结的相关文章

经典设计模式之策略模式【如何重构聚合支付平台,对接【支付宝,微信,银联支付】】

写在前面:设计模式源于生活,而又高于生活! 为什么要使用设计模式重构代码 使用设计模式可以重构整体架构代码.提高代码复用性.扩展性.减少代码冗余问题. Java高级工程师装逼的技能! 什么是策略模式 策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理,最终可以实现解决多重if判断问题. 1.环境(Context)角色:持有一个Strategy的引用 2.抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现.此角色给出所有的具体策略类所需的

设计模式之策略模式(Strategy)摘录

23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象.创建型模式有两个不断出现的主旋律.第一,它们都将关于该系统使用哪些具体的类的信息封装起来.第二,它们隐藏了这些类的实例是如何被创建和放在一起的.整个系统关于这些对象所知道的是由抽象类所定义的接口.因此,创建型模式在什么被创建,谁创建它,它是怎样被创建的,以

设计模式(一)—— 策略模式

简述: 策略模式的适用的目标是多子类和单一父类的情形.父类中放的是很多子类共用的代码段,对于不同子类特殊的代码段交给子类进行编写.但如果两个或两个以上的子类需要共同的代码段时,不能将这个代码段放入父类,因为这个代码段和其他的子类无关.正确做法是将少数子类共用的代码段做一个接口,写一个类去实现这个接口,在这个类中放入少数类共用的代码段.然后在父类的参数中加入这个接口对象,这样需要用到共用代码段的子类就可以通过这个接口对象来进行处理. 举例: 下面是很多杂乱的类和接口: 我们用策略模式将使用武器的方

Java设计模式6:策略模式

策略模式 策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立类中,从而使得它们可以相互替换.策略模式使得算法可以在不影响到客户端的情况下发生变化. 策略模式的结构 策略模式是对算法的包装,是把使用算法的责任和算法本身分开.策略模式通常是把一系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类. 策略模式涉及到三个角色: 1.环境角色 持有一个策略Strategy的引用 2.抽象策略角色 这是一个抽象角色,通常由一个接口或抽象类实现,此角色给出所有具体策略类所需的接口 3.

设计模式-策略模式Strategy以及消灭if else

概述 如果在开发过程中,出现大量的if else或者switch case 语句,如果这些语句块中的代码并不是包含业务逻辑,只是单纯的分流方法,那么,每一个语句块中都是一个算法或者叫策略. 背景 比如在最近项目中遇到的问题.一个二维码字符串解析的方法: 微信的二维码扫描结果包含"WeChat",解析规则是拿着文本到微信服务器解析,返回解析对象. 支付宝二维码扫描结果包含"Alipay",解析规则是使用"->"分割字符串得到解析对象. 最简单

【设计模式】策略模式 (Strategy Pattern)

策略模式是一种很简单的基础模式,用于封装一系列算法,使客户端的访问独立于算法的实现.我们可以"井中取水"来形象的描述策略模式."取水"是一个动作,完成这个动作的方式有很多中,可以直接用手提.可以用水车汲水.也可以用电泵抽水.在不同的环境和条件下,我们选择不同的取水方式,这就是策略模式. 策略模式的应用场景 1,有大量动作相同实现不同的行为模式需要配置,以使在适当的环境下选择恰当的行为. 2,算法或实现需要一系列不同的变量.同样的行为在不同的前提下产生不同的结果. 3

策略模式(headfirst设计模式学习笔记)

策略模式定义了算法族,分别封装起来,让他们可以相互替换,此模式让算法的变化独立于使用算法的客户. 继承,相似之处用继承,假如如干个功能点需要修改,代码难以维护, 原始代码 public class Duck { //鸭子描述 public void dispaly(){ System.out.println("描述"); } //鸭子叫 public void quack(){ System.out.println("会叫"); } } public class M

23种设计模式之——策略模式

什么是策略模式? 它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户. 什么时候去使用策略模式? 策略模式就是用来封装算法的,但是在实践中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性. 适用的场景? 1.如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为. 2.一个系统需要动态地在几

策略模式+简单工厂模式+单例模式:简单推送服务

一.功能: 实现  获取数据  —>根据用户订阅清单进行推送 —> 这里的推送方式:QQ.Email.App.插件等等 用户可多选推送方式. 二.实现 1.推送方式—枚举(位运算): [Flags] public enum PushType { QQ = 0, Email = 2 } 2.策略模式:抽象推送策略 public interface IPush { bool Push(object data); } 3.QQ推送+Email推送 QQ推送:单例模式—静态创建QQ推送服务,线程安全.