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 也类似,处理的业务逻辑更多些
获取链接
执行 action
关闭资源、断开链接
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){
}}
复制代码
至此模板方法介绍到这。 若你有收获,便是我最大的快乐。
划线
评论
复制
发布于: 刚刚阅读数: 2
Rubble
关注
还未添加个人签名 2021.06.01 加入
还未添加个人简介










评论