几乎每个系统都要与第三方进行交互。一般来说第三方API都会提供json或xml供系统使用。

  我们的目标是把api集成到系统中,并降低api对系统的影响。但是随着编码的进行,有太多的坏味道散落到系统中,比如Copy的代码满天飞;配置信息分散各处;无法有效地组织API。

  面对这些问题,系统应该主动地把api封装起来,形成独立的模块供上层系统调用。

  

  该模块涉及到的模式为[Template Method+Callack],[Factory],涉及到的元素如下

    1、client:Template Method的实现者;定义了与第三方交互的过程;从Callback获取数据组装成适合第三方的信息。

    2、callback:每一个api,都要实现callback,它提供方法名,参数,Url等数据给client使用

    3、config:各种配置信息,如appkey,加密参数等等

    4、factory:对象工厂。比如每调用第三方,系统给需要生成交易码,就可以把生成的任务委托给factory

    5、model:参数的封装类,利用model,可以生成json数据,也可以生成xml数据给client使用;同时也可以根据业务参数,利用factory生成各种model  

  以上就是模块中的各个元素。

 

  他们之间的调用情况如下:

    1、client 依靠 callback 与 第三方交互

    2、callback 结合 model 创建一个完整的apiCallback

    3、factory从config获取信息并结合业务要求,创建model

  一个的调用过程如下:



Model model  = ModelFactory.getXXXModel(xx,bb,cc)
ApiCallback back  = new ApiCallback(model);
Client.doClient(back);



 

  这样的设计方式解决那些问题,如何解决.

    Q1.第三方提供新的API

    A1.增加一个新的Model,实现一个ApiCallback,调用doClient方法

    Q2.第三方系统getName函数名称变动为getUserName

    A2.进入getName对应的GetNameCallback,修改方法名

    Q3.加密密钥放生变化

    Q4.找到对应Config,修改密钥

   

  给一个demo,让大家参考一下,案例已经过缩减,不足之处,多多包涵



public interface  JsonCallback
{  
public String getMethodName();
   public String getUrl();    
    public JsonRequest getJsonRequest();
public Object onResultReceived(AccountSmsResult result);

}



 



public class JsonClient
{
public static final int CONN_SERVICETOKEN_TIMEOUT = 20000;
private static final Logger logger = LoggerFactory.getLogger(JsonClientHelper.class);
private static final Gson gson = new Gson();

/**
     * 方法表述: 与远服务器进行交互,未授权
*/
public static Object doUnsafeClient(JsonCallback callback) throws CException
    {
        HttpClient httpClient = new HttpClient();
// 创建Post方法
        PostMethod method = createUnSafePostMethod(callback);
// 配置参数
        configParams(httpClient);
return executeMethod(httpClient, method, callback);
    }

/**
     * 方法表述:创建未授权的Post方法
*/
private static PostMethod createUnSafePostMethod(JsonCallback callback)
    {
        String url = callback.getUrl() + callback.getMethodName();
        PostMethod method = new PostMethod(url);
        method.addRequestHeader("Content-Type", "application/json");
        method.setRequestEntity(wrapToRequestEntity(callback));
return method;
    }

/**
     * 方法表述:配置参数
*/
private static void configParams(HttpClient httpClient)
    {
        HttpConnectionManagerParams conParams = httpClient.getHttpConnectionManager().getParams();
        conParams.setConnectionTimeout(CONN_SERVICETOKEN_TIMEOUT);
        conParams.setSoTimeout(CONN_SERVICETOKEN_TIMEOUT);
    }
/**
     * 方法表述: 执行Post方法
*/
private static Object executeMethod(HttpClient httpClient, PostMethod method, JsonCallback callback)
throws CException
    {
        Object resultObject = null;
try
        {
int result = httpClient.executeMethod(method);
if (result == HttpStatus.SC_OK)
            {
                String response = method.getResponseBodyAsString();


if (!StringUtil.isNullString(response))
                {

                    resultObject = doResponseReceived(response, callback);
                }
            }
        }
catch (Exception e){
            logger.debug(e);
        }
finally
        {
if (method != null)
                method.releaseConnection();

        }
return resultObject;
    }

/**
     * 把Json请求对象转化为字符串,并封装到RequestEntity 
*/
protected static RequestEntity wrapToRequestEntity(JsonCallback callback)
    {
        String req = gson.toJson(callback.getJsonRequest(), JsonRequest.class);
if (logger.isDebugEnabled())
            logger.debug(callback.getMethodName() + " req:" + req);
try
        {
return new StringRequestEntity(req, null, "utf8");
        }
catch (UnsupportedEncodingException e)
        {
            logger.error("create StringRequestEntity failed for UnsupportedEncodingException.");
throw new RuntimeException("create StringRequestEntity failed for UnsupportedEncodingException.");
        }

    }

/**
     * 方法表述:当收到服务器传递过来的信息时,如何处理
*/
public static Object doResponseReceived(String response, JsonCallback callback) throws CException
    {
        AccountSmsReturn rsp = gson.fromJson(response, AccountSmsReturn.class);
if (rsp != null && rsp.result != null && rsp.result.resultCode.equals("0"))
        {
return callback.onResultReceived(rsp.result);
        }
else
        {
throw rsp.result.CException;
        }
    }