写点什么

API 对接之模板方法

作者:Rubble
  • 2022 年 4 月 19 日
  • 本文字数:2499 字

    阅读完需:约 8 分钟

定义

在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。

一个栗子

引用菜鸟教程的一个例子


父类定义一个步骤/模板,一般会有默认的步骤实现,只留一个抽象方法留到实现类中实现。


public abstract class Game {   abstract void initialize();   abstract void startPlay();   abstract void endPlay();    //模板   public final void play(){       //初始化游戏      initialize();       //开始游戏      startPlay();       //结束游戏      endPlay();   }}
复制代码


子类进行具体的实现


public class Football extends Game {    @Override   void endPlay() {      System.out.println("Football Game Finished!");   }    @Override   void initialize() {      System.out.println("Football Game Initialized! Start playing.");   }    @Override   void startPlay() {      System.out.println("Football Game Started. Enjoy the game!");   }}
复制代码


public static void main(String[] args) {      Game game = new Football();      game.play();         }
复制代码

spring 中的模板

spring 框架中也提供了一些模板如 JdbcTemplate、RestTemplate、RestTemplate。


JdbcTemplate 只需传入要执行的方法 ConnectionCallback,其他工作交给模板处理。


// 构造函数注入了DataSourcepublic JdbcTemplate(DataSource dataSource) {  setDataSource(dataSource);  afterPropertiesSet();}
/*** 模板步骤 * 1. 打开链接 Connection* 2. 执行action (sql)* 3. 释放链接 releaseConnection**/public <T> T execute(ConnectionCallback<T> action) throws DataAccessException { Assert.notNull(action, "Callback object must not be null");
Connection con = DataSourceUtils.getConnection(obtainDataSource()); try { // Create close-suppressing Connection proxy, also preparing returned Statements. Connection conToUse = createConnectionProxy(con); return action.doInConnection(conToUse); } catch (SQLException ex) { // Release Connection early, to avoid potential connection pool deadlock // in the case when the exception translator hasn't been initialized yet. String sql = getSql(action); DataSourceUtils.releaseConnection(con, getDataSource()); con = null; throw translateException("ConnectionCallback", sql, ex); } finally { DataSourceUtils.releaseConnection(con, getDataSource()); } }
复制代码


redisTemplate 也类似,处理的业务逻辑更多些


  1. 获取链接

  2. 执行 action

  3. 关闭资源、断开链接


public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) {
Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it"); Assert.notNull(action, "Callback object must not be null");
RedisConnectionFactory factory = getRequiredConnectionFactory(); RedisConnection conn = null; try {
if (enableTransactionSupport) { // only bind resources in case of potential transaction synchronization conn = RedisConnectionUtils.bindConnection(factory, enableTransactionSupport); } else { conn = RedisConnectionUtils.getConnection(factory); }
boolean existingConnection = TransactionSynchronizationManager.hasResource(factory);
RedisConnection connToUse = preProcessConnection(conn, existingConnection);
boolean pipelineStatus = connToUse.isPipelined(); if (pipeline && !pipelineStatus) { connToUse.openPipeline(); }
RedisConnection connToExpose = (exposeConnection ? connToUse : createRedisConnectionProxy(connToUse)); T result = action.doInRedis(connToExpose);
// close pipeline if (pipeline && !pipelineStatus) { connToUse.closePipeline(); }
// TODO: any other connection processing? return postProcessResult(result, connToUse, existingConnection); } finally { RedisConnectionUtils.releaseConnection(conn, factory, enableTransactionSupport); }}
复制代码


redisTemplate.opsForValue().get(key) 也是调用了 template 的 execute 方法。


public V get(Object key) {
return execute(new ValueDeserializingRedisCallback(key) {
@Override protected byte[] inRedis(byte[] rawKey, RedisConnection connection) { return connection.get(rawKey); } }, true);}
复制代码

API 对接之模板方法

api 对接通常需要 加入时间戳,根据一定规则进行签名


XxxApiTemplate


public  class XxxApiTemplate {
private String key; private String secret;
@Autowired private RestTemplate restTemplate;
private HttpClient httpClient;
public XxxApiTemplate () { }
public XxxApiTemplate (String key, String secret) { this.key = key; this.secret = secret; }
public String get(String url, Map<String,String> params){ // params 加入时间戳 // sign 根据key、secret进行签名(MD5/AES) // 处理url拼接参数 // 其他工作 如日志等 // 进行请求 httpClient、restTemplate return restTemplate.getForObject(url,String.class); }
public String post(String url, Map<String,String> params){ // 与get方法类似,处理参数方式不同 Object request = null; return restTemplate.postForObject(url,request,String.class); }
public void execute(CallBackAction action){
}}
复制代码


至此模板方法介绍到这。 若你有收获,便是我最大的快乐。

用户头像

Rubble

关注

还未添加个人签名 2021.06.01 加入

还未添加个人简介

评论

发布
暂无评论
API对接之模板方法_4月日更_Rubble_InfoQ写作平台