大家好,我是小宁
这半个月鼓捣了不少工具类,搞着搞着发现,这些工具类虽然功能不一样,但是封装的思路和组织的方式很像,可以提炼出一些共同点出来, 这是很值得分享的事.
所谓授人以鱼,不如授人以渔,可能看我的文章,代码没学会几行,但相信我,收获的绝不止是代码
先看下我这段时间的成果(安装包还没在网上发布,可以找我拿安装包)
我选取了几个工具包展示出来,可以看到,一个工具的组成,大致由三种类组成: 1. xxxConfig. 2. xxxTools. 3.model包,存放工具的请求/返回实体
我们以钉钉的工具包为例进行剖析:
public class DingConfig {
// 钉钉添加机器人时获得的url
private String url;
// 钉钉添加机器人时获取的secret
private String secret;
// 在原有的URL之上添加一些参数
public String getUrl() {
Long timestamp = System.currentTimeMillis();
String sign = getSign(timestamp);
return url+"×tamp="+timestamp+"&sign="+sign;
}
/**
* 通过时间戳和sercet进行加密.
*/
public String getSign(Long timestamp) {
try {
String stringToSign = timestamp + "\n" + secret;
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
return URLEncoder.encode(Base64.getEncoder().encodeToString(signData), "UTF-8");
}catch (Exception e){
return null;
}
}
}
如上所示,我们可以看到,这个配置类不仅仅是存一些值, 一些常用的和配置相关的功能也都在这里,这里有点像领域驱动的充血实体类的感觉了.
public class DingMessage {
// 定义钉钉消息的类型,纯文字类型
public static final String TYPE_TEXT="text";
// 定义钉钉消息的类型,带按钮可跳转的类型
public static final String TYPE_ACTION_CARD = "actionCard";
private String msgtype;
private TextMessage text;
private ActionCardMessage actionCard;
// 采用静态内部类的形式来组织嵌套的实体类
static class TextMessage{
private String content;
public String getContent() {
return content;
}
}
// 采用静态内部类的形式来组织嵌套的实体类
static class ActionCardMessage{
private String title;
private String text;
private String hideAvatar;
private String btnOrientation;
private List btns;
}
// 采用静态内部类的形式来组织嵌套的实体类
static class DButton{
private String title;
private String actionURL;
}
// 对外提供的初始化函数,对外部看来,只需要传一个content就可以了
// 拼实体类的操作,放到了实体类里面
public static DingMessage initTextMessage(String content){
TextMessage textMessage = new TextMessage();
textMessage.content = content;
DingMessage dingMessage = new DingMessage();
dingMessage.text = textMessage;
dingMessage.msgtype = TYPE_TEXT;
return dingMessage;
}
}
通过我们和第三方都是通过json的方式进行交互. 要么就是map转json,要么就是实体类转json, 这里我都是使用的实体类转json, 也没有拆分很多的实体类,直接通过静态内部类就可以完成实体的组织
// 提供给外部使用的工具类
public static void sendText(String content,DingConfig config){
// 构造请求实体类
DingMessage message = DingMessage.initTextMessage(content);
// 转成json
String s = JSON.toJSONString(message);
// 请求第三方
HttpResponse response = HttpTools.doPost(config.getUrl(),s , HttpRequest.JSON_HEADER, String.class);
// 处理返回值
System.out.println(response.getBody());
}
如上源码所示,真得到工具类里面大致分为四步, 构造请求实体类,转成json,请求, 然后处理返回值,同样的去请求微信/redis,也大致都是这个结构
public static void main(String[] args) {
// 配置config
DingConfig config = new DingConfig();
config.setUrl("https://oapi.dingtalk.com/robot/send?access_token=xx");
config.setSecret("xxxx");
// 调工具类
DingTools.sendActionCard("测试审核","这是一条测试审核的信息",config);
}
对调用方来说, 就两个事, 拼Config , 然后调用工具类. 通过传入的Config不一样, 工具类可以操作不同主体的第三方, 这个跟所谓的无状态就很像了
思路思路, 本篇文章只要强调的是思路, 大家以后在封装自己的工具类时,也可以考虑使用这样的结构, 一个Config , 一个实体包, 一个Tools. 这样对调用方和对自己来说,都很简单.