場景
沒有業務場景的示例都是在耍流氓
今天領導讓做下 企業微信 的對接工作(應該不少人都有在做)
之前就寫過一兩個接口,就簡單寫了下
邏輯
以獲取羣聊信息爲例:
- 根據
corpid
,secret(應用密鑰)
獲取access_token
,即獲取應用的授權,不同應用secret
不同 access_token
的獲取是不能頻繁去獲取的,否則可能會被 IP 限制,因此我們把token
保存到Redis
中,每次先從Redis
中獲取,沒有或者 token 過期 再去提交請求獲取access_token
- 調用獲取羣聊信息的接口
- 判斷企業微信的返回值
errcode
,是否有密鑰過期 - 如果密鑰過期,獲取
access_token
再次 調用獲取羣聊信息的接口
反面教材
所有接口都是這種套娃式的邏輯,只有一個字形容 齪
@Resource
private AppchatService appchatService;
/**
* 獲取羣聊
* @param chatid
* @return
*/
@GetMapping(value = "/get/{chatid}")
public ErrorMsg get(@PathVariable("chatid") String chatid) {
// 獲取 token
String accessToken = tokenService.getToken(wechatInfo.getAppchatSecret());
ErrorMsg msg = appchatService.get(accessToken, chatid);
// 如果發生錯誤,可能是密鑰過期,嘗試更新密鑰再獲取
if (msg.getErrorCode().equals(ErrorMsg.ACCESS_LIMITED.getErrorCode())) {
accessToken = tokenService.updateToken(wechatInfo.getAppchatSecret());
msg = appchatService.get(accessToken, chatid);
}
return msg;
}
get 方法的實現
@Override
public ErrorMsg get(String accessToken, String chatid) {
if (StringUtils.isBlank(chatid)) {
return ErrorMsg.ARGS_ERROR.setNewErrorMsg("羣聊 id 不能爲空");
}
String url = wechatInfo.getIp() + "/cgi-bin/appchat/get?access_token=" + accessToken + "&chatid=" + chatid;
String json = RestTemplateUtil.get(url, null);
AppchatResult result = JsonUtil.toBean(json, AppchatResult.class);
if (!"0".equals(result.getErrcode())) {
return ErrorMsg.ACCESS_LIMITED.setNewErrorMsg(result.getErrmsg());
}
return ErrorMsg.SUCCESS.setNewData(result);
}
其他例子
函數式編程優化代碼
定義函數式接口
這個接口就是我們被代理的函數的抽象,其中自定義的 apply 方法就是去執行方法
@FunctionalInterface: 用於定義接口爲函數式接口,接口下有且僅有一個抽象方法
參數: 可以看到 apply
方法中後面的參數只有一個,就是 accessToken
因爲 只有這個參數,我們需要動態修改
/**
* 函數式,接口執行
*/
@FunctionalInterface
public interface ApplyFunction {
ErrorMsg apply(String accessToken);
}
對前文中的邏輯進行封裝
/**
* 執行操作
* @author: linjinp
* @create: 2020-06-18 11:19
**/
@Component
public class OperatorFunction {
@Resource
private TokenService tokenService;
public ErrorMsg doOperate(String secret, ApplyFunction function) {
// 獲取 token
String accessToken = tokenService.getToken(secret);
// 執行代理的函數
ErrorMsg msg = function.apply(accessToken);
// 如果發生錯誤,可能是密鑰過期,嘗試更新密鑰再獲取
if (msg.getErrorCode().equals(ErrorMsg.ACCESS_LIMITED.getErrorCode())) {
accessToken = tokenService.updateToken(secret);
msg = function.apply(accessToken);
}
return msg;
}
}
函數式接口調用
accessToken: 這個參數需要變動,因此這裏的 val
即前文中函數式接口的參數
chatid: 這個參數是固定的,不需要變動,因此直接傳就行了,不需要通過函數式接口
/**
* 獲取羣聊
* @param chatid
* @return
*/
@GetMapping(value = "/get/{chatid}")
public ErrorMsg get(@PathVariable("chatid") String chatid) {
String secret = wechatInfo.getAppchatSecret();
return operatorFunction.doOperate(secret, (val) -> appchatService.get(val, chatid));
}
調用示例
開始調用函數式接口
以讀取用戶信息接口爲例,這裏 secret
爲 null
情況下,getToken
會給 secret
一個默認值,因此不需要管
請求成功,如果不成功,就會更新 token
再請求一次