最近公司准备搞分布式,需要将原代码按功能等一个个抽离出来,我负责弄邮箱短信部分,经历了半个月的折磨,总算搞出来了,这里做个总结,有许多之前没弄过的,算是由0到1的一个过程。
整个思路过程如下:
比较简单的,对外暴露的仅仅只是api接口,内部最重要的是一个实体类,用于存储需上传的数据,再发送给mq,然后消费mq中的信息。
这其中有几个问题需要总结的,算是这个过程中卡得我难受的点。
第一:设计上,对外暴露的api接口只有存储对象和mq发送方法,这里是一个小技巧,逻辑处理封装起来,并不对外提供服务。存储对象类设计上还是有点意思的,用到了内部类,这里记录下来,以后做参考:
package cn.coralglobal.message.api.service;
import cn.coralglobal.message.api.exception.MessageCenterBuilderException;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.io.Serializable;
/**
* @Description: 消息主体对象
* @Author chenjianwen
* @Date 2020-03-25
**/
@Data
@Slf4j
public class MessageSubject implements Serializable {
private static final long serialVersionUID = 4901512199571414865L;
/**
* 发送时间
*/
private long timestamp = System.currentTimeMillis();
/**
* 模版名称
*/
private String templateName;
/**
* 模版code
*/
private String templateCode;
/**
* 替换文本,和模版中的占位符严格一一对应
*/
private String[] replace;
/**
* 消息受众(可以是userId或者用户手机号或邮箱)
*/
private String[] users;
/**
* 发送消息的站台(coralglobal或crm或其他)
*/
private String platform;
public MessageSubject(){}
public MessageSubject(Builder builder){
setTimestamp(builder.timestamp);
setTemplateName(builder.templateName);
setTemplateCode(builder.templateCode);
setReplace(builder.replace);
setUsers(builder.users);
setPlatform(builder.platform);
}
public static Builder newBuilder(){
return new Builder();
}
public static Builder newBuilder(MessageSubject ms){
Builder b = new Builder();
b.timestamp = ms.getTimestamp();
b.templateName = ms.getTemplateName();
b.templateCode = ms.getTemplateCode();
b.replace = ms.getReplace();
b.users = ms.getUsers();
b.platform = ms.getPlatform();
return b;
}
public static final class Builder{
private long timestamp;
private String templateName;
private String templateCode;
private String[] replace;
private String[] users;
private String platform;
private Builder(){}
public Builder timestamp(long timestamp){
this.timestamp = timestamp;
return this;
}
public Builder name(String templateName){
this.templateName = templateName;
return this;
}
public Builder template(String code) throws MessageCenterBuilderException {
if(code == null || "".equals(code)){
log.error("message-center-api|MessageSubject|template(String code)|模版编码不能为空");
throw new MessageCenterBuilderException("message-center|MessageSubject|template(String code)|模版编码不能为空");
}
this.templateCode = code;
return this;
}
public Builder replace(String... replace){
this.replace = replace;
return this;
}
public Builder users(String... users){
this.users = users;
return this;
}
public Builder platform(String platform){
this.platform = platform;
return this;
}
public MessageSubject build() throws MessageCenterBuilderException {
if(this.templateCode == null || "".equals(this.templateCode)){
log.error("message-center-api|MessageSubject|build()|templateCode不能为空");
throw new MessageCenterBuilderException("message-center-api|MessageSubject|build()|templateCode不能为空");
}
return new MessageSubject(this);
}
}
}
第二:用mq发送数据的时候,先将数据序列化成字节数据会好点,用下面这个方法:
com.fasterxml.jackson.databind.ObjectMapper;
其maven依赖是:
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.3</version>
</dependency>
然后监听器那边转换一下即可:
第三: 由于它是一个单独的服务,因此最终需要打成jar到我们公司本地的私服并生成maven依赖,以供其他的项目使用。所以需要分两步完成:
(1)我需要现在本地repository仓库生成jar,那问题来了,如何在本地生成jar,这里涉及到了maven的三个命令:
mvn clean package 在项目目录下的target目录下生成jar
mvn clean install 打包jar到target目录下,且打包到本地repository
mvn clean deploy 打包jar到target目录下,且打包到本地repository,且打包到远程repository
这里在本地仓库测试,因此使用mvn clean install,或者直接在idea上的maven可视化操作,如下:
(2)在公司私服生成jar有点麻烦,花了很多时间才搞定,首先,需要在settings.xml中<servers></servers>标签对中添加本地私服的服务器用户名和密码,如下:
然后在项目中的pom.xml文件中添加如下标签对:
然后使用mvn clean deploy命令就能将服务打成jar包上传到本地私服。
(2)如何引用本地私服的maven依赖,除了在pom.xml中引用<dependency></dependency>依赖之外,还需要引用本地私服仓库的地址,如下:
这样,就能引用本地私服仓库的maven的jar包了。