API对接之模板方法

举报
琴岛蛏子 发表于 2022/03/21 00:09:03 2022/03/21
【摘要】 API对接之模板方法 定义在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。 一个栗子引用菜鸟教程的一个例子父类定义一个步骤/模板,一般会有默认的步骤实现,只留一个抽象方法留到实现类中实现。public abstract class Game { abstract void ...

API对接之模板方法

定义

在模板模式(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,其他工作交给模板处理。

// 构造函数注入了DataSource
public 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){

  }
}
  

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

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。