正在显示
11 个修改的文件
包含
602 行增加
和
0 行删除
pom.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
3 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
4 | + <modelVersion>4.0.0</modelVersion> | ||
5 | + <parent> | ||
6 | + <groupId>org.springframework.boot</groupId> | ||
7 | + <artifactId>spring-boot-starter-parent</artifactId> | ||
8 | + <version>2.1.1.RELEASE</version> | ||
9 | + <relativePath/> <!-- lookup parent from repository --> | ||
10 | + </parent> | ||
11 | + <groupId>com.aukey.example</groupId> | ||
12 | + <artifactId>canal-mq-client</artifactId> | ||
13 | + <version>0.0.1</version> | ||
14 | + <name>canal-mq-client</name> | ||
15 | + <description>客户端demo项目</description> | ||
16 | + | ||
17 | + <properties> | ||
18 | + <java.version>1.8</java.version> | ||
19 | + </properties> | ||
20 | + | ||
21 | + <dependencies> | ||
22 | + <dependency> | ||
23 | + <groupId>org.springframework.boot</groupId> | ||
24 | + <artifactId>spring-boot-starter-web</artifactId> | ||
25 | + </dependency> | ||
26 | + | ||
27 | + <dependency> | ||
28 | + <groupId>org.springframework.boot</groupId> | ||
29 | + <artifactId>spring-boot-starter-amqp</artifactId> | ||
30 | + </dependency> | ||
31 | + | ||
32 | + <dependency> | ||
33 | + <groupId>com.alibaba</groupId> | ||
34 | + <artifactId>fastjson</artifactId> | ||
35 | + <version>1.2.68</version> | ||
36 | + </dependency> | ||
37 | + | ||
38 | + <dependency> | ||
39 | + <groupId>org.apache.commons</groupId> | ||
40 | + <artifactId>commons-lang3</artifactId> | ||
41 | + <version>3.4</version> | ||
42 | + </dependency> | ||
43 | + | ||
44 | + <dependency> | ||
45 | + <groupId>org.projectlombok</groupId> | ||
46 | + <artifactId>lombok</artifactId> | ||
47 | + <version>1.18.10</version> | ||
48 | + </dependency> | ||
49 | + </dependencies> | ||
50 | + | ||
51 | + <build> | ||
52 | + <plugins> | ||
53 | + <plugin> | ||
54 | + <groupId>org.springframework.boot</groupId> | ||
55 | + <artifactId>spring-boot-maven-plugin</artifactId> | ||
56 | + </plugin> | ||
57 | + </plugins> | ||
58 | + </build> | ||
59 | + | ||
60 | +</project> |
1 | +package com.aukey.example; | ||
2 | + | ||
3 | +import org.springframework.boot.SpringApplication; | ||
4 | +import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
5 | + | ||
6 | +@SpringBootApplication | ||
7 | +public class MqExampleApplication { | ||
8 | + | ||
9 | + public static void main(String[] args) { | ||
10 | + SpringApplication.run(MqExampleApplication.class, args); | ||
11 | + } | ||
12 | +} |
1 | +package com.aukey.example.conf; | ||
2 | + | ||
3 | +import com.aukey.example.converter.CharArrayToStringConverter; | ||
4 | +import org.springframework.amqp.core.AcknowledgeMode; | ||
5 | +import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory; | ||
6 | +import org.springframework.amqp.rabbit.connection.ConnectionFactory; | ||
7 | +import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory; | ||
8 | +import org.springframework.context.annotation.Bean; | ||
9 | +import org.springframework.context.annotation.Configuration; | ||
10 | + | ||
11 | +/** | ||
12 | + * @author: wgf | ||
13 | + * @create: 2020-06-10 18:52 | ||
14 | + * @description: | ||
15 | + **/ | ||
16 | +@Configuration | ||
17 | +public class RabbitConf { | ||
18 | + | ||
19 | + /** | ||
20 | + * spring boot 在2.2.7.RELEASE 及以上版本不用配置,因为新版本amqp兼容content-type为空的消息 | ||
21 | + * @param connectionFactory | ||
22 | + * @return | ||
23 | + */ | ||
24 | + @Bean | ||
25 | + public RabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) { | ||
26 | + SimpleRabbitListenerContainerFactory listenerContainerFactory = new SimpleRabbitListenerContainerFactory(); | ||
27 | + listenerContainerFactory.setConnectionFactory(connectionFactory); | ||
28 | + //--加上这句 | ||
29 | + listenerContainerFactory.setMessageConverter(new CharArrayToStringConverter()); | ||
30 | + listenerContainerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL); | ||
31 | + return listenerContainerFactory; | ||
32 | + } | ||
33 | +} |
1 | +package com.aukey.example.constant; | ||
2 | + | ||
3 | +/** | ||
4 | + * @author: wgf | ||
5 | + * @create: 2020-06-09 15:03 | ||
6 | + * @description: Msql数据库事件类型枚举 | ||
7 | + * mysql binlog启用的是row模式,只有C,U,D操作 | ||
8 | + **/ | ||
9 | +public enum EventType { | ||
10 | + INSERT, | ||
11 | + UPDATE, | ||
12 | + DELETE, | ||
13 | + CREATE, | ||
14 | + ALTER, | ||
15 | + ERASE, | ||
16 | + QUERY, | ||
17 | + TRUNCATE, | ||
18 | + RENAME, | ||
19 | + CINDEX, | ||
20 | + DINDEX, | ||
21 | + GTID, | ||
22 | + XACOMMIT, | ||
23 | + XAROLLBACK, | ||
24 | + MHEARTBEAT; | ||
25 | +} |
1 | +package com.aukey.example.converter; | ||
2 | + | ||
3 | +import org.apache.commons.lang3.StringUtils; | ||
4 | +import org.springframework.amqp.core.Message; | ||
5 | +import org.springframework.amqp.core.MessageProperties; | ||
6 | +import org.springframework.amqp.support.converter.MessageConversionException; | ||
7 | +import org.springframework.amqp.support.converter.MessageConverter; | ||
8 | + | ||
9 | +import java.io.UnsupportedEncodingException; | ||
10 | + | ||
11 | +/** | ||
12 | + * @author: wgf | ||
13 | + * @create: 2020-06-10 22:39 | ||
14 | + * @description: 消息类型转换器 | ||
15 | + * 如果 spring boot 用的是 2.2.7.RELEASE以上的版本则不需要使用此转换器 | ||
16 | + **/ | ||
17 | +public class CharArrayToStringConverter implements MessageConverter { | ||
18 | + | ||
19 | + private String defaultCharset = "utf-8"; | ||
20 | + | ||
21 | + @Override | ||
22 | + public Message toMessage(Object object, MessageProperties messageProperties) throws MessageConversionException { | ||
23 | + // TODO 不发消息不实现转换 | ||
24 | + return null; | ||
25 | + } | ||
26 | + | ||
27 | + @Override | ||
28 | + public Object fromMessage(Message message) throws MessageConversionException { | ||
29 | + Object content = null; | ||
30 | + MessageProperties properties = message.getMessageProperties(); | ||
31 | + if (properties != null) { | ||
32 | + String contentType = properties.getContentType(); | ||
33 | + if (StringUtils.isBlank(contentType) || contentType.startsWith("text")) { | ||
34 | + String encoding = properties.getContentEncoding(); | ||
35 | + if (encoding == null) { | ||
36 | + encoding = this.defaultCharset; | ||
37 | + } | ||
38 | + try { | ||
39 | + content = new String(message.getBody(), encoding); | ||
40 | + } catch (UnsupportedEncodingException e) { | ||
41 | + throw new MessageConversionException( | ||
42 | + "failed to convert text-based Message content", e); | ||
43 | + } | ||
44 | + } | ||
45 | + } else { | ||
46 | + content = message.getBody(); | ||
47 | + } | ||
48 | + return content; | ||
49 | + } | ||
50 | +} |
1 | +package com.aukey.example.entity; | ||
2 | + | ||
3 | +import lombok.Data; | ||
4 | + | ||
5 | +import java.util.Date; | ||
6 | + | ||
7 | +/** | ||
8 | + * @author: wgf | ||
9 | + * @create: 2020-06-09 11:30 | ||
10 | + * @description: | ||
11 | + **/ | ||
12 | +@Data | ||
13 | +public class AmazonOrder { | ||
14 | + /** | ||
15 | + * 自增主键 | ||
16 | + */ | ||
17 | + private Integer aid; | ||
18 | + | ||
19 | + /** | ||
20 | + * 亚马逊订单ID | ||
21 | + */ | ||
22 | + private String amazonOrderId; | ||
23 | + | ||
24 | + /** | ||
25 | + * 卖家订单ID | ||
26 | + */ | ||
27 | + private String sellerOrderId; | ||
28 | + | ||
29 | + /** | ||
30 | + * 购买日期 | ||
31 | + */ | ||
32 | + private Date purchaseDate; | ||
33 | + | ||
34 | + /** | ||
35 | + * 付款日期 | ||
36 | + */ | ||
37 | + private Date paymentsDate; | ||
38 | + | ||
39 | + /** | ||
40 | + * 最后更新日期 | ||
41 | + */ | ||
42 | + private Date lastUpdateDate; | ||
43 | + | ||
44 | + /** | ||
45 | + * 订单状态:1、Pending Availability等待订单生效;2、Pending待定;3、Unshipped未发货;4、Partially Shipped部分发货;5、Shipped已发货;6、Invoice Unconfirmed发票未确认;7、Canceled已取消;8、Unfulfillable无法发货 | ||
46 | + */ | ||
47 | + private String orderStatus; | ||
48 | + | ||
49 | + /** | ||
50 | + * 发货渠道(AFN、MFN) | ||
51 | + */ | ||
52 | + private String fulfillmentChannel; | ||
53 | + | ||
54 | + /** | ||
55 | + * 销售渠道(站点) | ||
56 | + */ | ||
57 | + private String salesChannel; | ||
58 | + | ||
59 | + /** | ||
60 | + * 运输服务等级 | ||
61 | + */ | ||
62 | + private String shipServiceLevel; | ||
63 | + | ||
64 | + /** | ||
65 | + * 收货地址-城市 | ||
66 | + */ | ||
67 | + private String shippingAddressCity; | ||
68 | + | ||
69 | + /** | ||
70 | + * 收货地址-县 | ||
71 | + */ | ||
72 | + private String shippingAddressCounty; | ||
73 | + | ||
74 | + /** | ||
75 | + * 收货地址-地区 | ||
76 | + */ | ||
77 | + private String shippingAddressDistrict; | ||
78 | + | ||
79 | + /** | ||
80 | + * 收货地址-州 | ||
81 | + */ | ||
82 | + private String shippingAddressStateOrRegion; | ||
83 | + | ||
84 | + /** | ||
85 | + * 收货地址-邮政编码 | ||
86 | + */ | ||
87 | + private String shippingAddressPostalCode; | ||
88 | + | ||
89 | + /** | ||
90 | + * 收货地址-国家编码 | ||
91 | + */ | ||
92 | + private String shippingAddressCountryCode; | ||
93 | + | ||
94 | + private String shippingAddressPhone; | ||
95 | + | ||
96 | + /** | ||
97 | + * 订单总额(币种) | ||
98 | + */ | ||
99 | + private String orderTotalCurrencyCode; | ||
100 | + | ||
101 | + /** | ||
102 | + * 订单总额 | ||
103 | + */ | ||
104 | + private Double orderTotalAmount; | ||
105 | + | ||
106 | + /** | ||
107 | + * 邮费总额 | ||
108 | + */ | ||
109 | + private Double postageTotal; | ||
110 | + | ||
111 | + /** | ||
112 | + * 折扣总额 | ||
113 | + */ | ||
114 | + private Double discountTotal; | ||
115 | + | ||
116 | + /** | ||
117 | + * 发货数量 | ||
118 | + */ | ||
119 | + private Integer numberOfItemsShipped; | ||
120 | + | ||
121 | + /** | ||
122 | + * 未发货数量 | ||
123 | + */ | ||
124 | + private Integer numberOfItemsUnshipped; | ||
125 | + | ||
126 | + /** | ||
127 | + * 付款方式 | ||
128 | + */ | ||
129 | + private String paymentMethod; | ||
130 | + | ||
131 | + /** | ||
132 | + * 市场ID | ||
133 | + */ | ||
134 | + private String marketplaceId; | ||
135 | + | ||
136 | + /** | ||
137 | + * 买家邮箱 | ||
138 | + */ | ||
139 | + private String buyerEmail; | ||
140 | + | ||
141 | + /** | ||
142 | + * 买家名称 | ||
143 | + */ | ||
144 | + private String buyerName; | ||
145 | + | ||
146 | + /** | ||
147 | + * 出货服务等级类别 | ||
148 | + */ | ||
149 | + private String shipmentServiceLevelCategory; | ||
150 | + | ||
151 | + private String shippedByAmazonTfm; | ||
152 | + | ||
153 | + private String tfmShipmentStatus; | ||
154 | + | ||
155 | + private String cbaDisplayableShippingLabel; | ||
156 | + | ||
157 | + /** | ||
158 | + * 订单类型 | ||
159 | + */ | ||
160 | + private String orderType; | ||
161 | + | ||
162 | + /** | ||
163 | + * 最早发货日期 | ||
164 | + */ | ||
165 | + private Date earliestShipDate; | ||
166 | + | ||
167 | + /** | ||
168 | + * 最晚发货日期 | ||
169 | + */ | ||
170 | + private Date latestShipDate; | ||
171 | + | ||
172 | + /** | ||
173 | + * 最早交货日期 | ||
174 | + */ | ||
175 | + private Date earliestDeliveryDate; | ||
176 | + | ||
177 | + /** | ||
178 | + * 最晚交货日期 | ||
179 | + */ | ||
180 | + private Date latestDeliveryDate; | ||
181 | + | ||
182 | + private String isBusinessOrder; | ||
183 | + | ||
184 | + /** | ||
185 | + * 买家采购订单编号 | ||
186 | + */ | ||
187 | + private String purchaseOrderNumber; | ||
188 | + | ||
189 | + private String isPrime; | ||
190 | + | ||
191 | + private String isPremiumOrder; | ||
192 | + | ||
193 | + | ||
194 | + /** | ||
195 | + * 抓单时间 | ||
196 | + */ | ||
197 | + private Date importSysDate; | ||
198 | + | ||
199 | + /** | ||
200 | + * 店铺ID | ||
201 | + */ | ||
202 | + private Integer accountId; | ||
203 | + | ||
204 | + /** | ||
205 | + * 店铺简码 | ||
206 | + */ | ||
207 | + private String accountCode; | ||
208 | + | ||
209 | + /** | ||
210 | + * 区域ID | ||
211 | + */ | ||
212 | + private Integer areaId; | ||
213 | + | ||
214 | + /** | ||
215 | + * 区域 | ||
216 | + */ | ||
217 | + private String area; | ||
218 | + | ||
219 | + /** | ||
220 | + * 记录创建时间 | ||
221 | + */ | ||
222 | + private Date createDate; | ||
223 | + | ||
224 | + /** | ||
225 | + * 记录更新时间 | ||
226 | + */ | ||
227 | + private Date updateDate; | ||
228 | + | ||
229 | + /** | ||
230 | + * item表处理状态 | ||
231 | + */ | ||
232 | + private String orderItemStatus; | ||
233 | + | ||
234 | + private Integer siteId; | ||
235 | + | ||
236 | + private String site; | ||
237 | + | ||
238 | + /** | ||
239 | + * 店铺站点ID | ||
240 | + */ | ||
241 | + private String authId; | ||
242 | + | ||
243 | + private String dataDigest; | ||
244 | + | ||
245 | + /** | ||
246 | + * 是否补发订单 | ||
247 | + */ | ||
248 | + private String reissue; | ||
249 | + | ||
250 | + /** | ||
251 | + * 收件人姓名 | ||
252 | + */ | ||
253 | + private String shippingAddressName; | ||
254 | + | ||
255 | + /** | ||
256 | + * 收货地址-街道1 | ||
257 | + */ | ||
258 | + private String shippingAddressLine1; | ||
259 | + | ||
260 | + /** | ||
261 | + * 收货地址-街道2 | ||
262 | + */ | ||
263 | + private String shippingAddressLine2; | ||
264 | + | ||
265 | + /** | ||
266 | + * 收货地址-街道3 | ||
267 | + */ | ||
268 | + private String shippingAddressLine3; | ||
269 | + | ||
270 | + private String skus; | ||
271 | + | ||
272 | + private String asins; | ||
273 | +} |
1 | +package com.aukey.example.listener; | ||
2 | + | ||
3 | +import com.alibaba.fastjson.JSON; | ||
4 | +import com.alibaba.fastjson.TypeReference; | ||
5 | +import com.aukey.example.constant.EventType; | ||
6 | +import com.aukey.example.constant.MQConst; | ||
7 | +import com.aukey.example.entity.AmazonOrder; | ||
8 | +import com.aukey.example.vo.MessageVo; | ||
9 | +import com.rabbitmq.client.Channel; | ||
10 | +import lombok.extern.slf4j.Slf4j; | ||
11 | +import org.springframework.amqp.core.Message; | ||
12 | +import org.springframework.amqp.rabbit.annotation.RabbitListener; | ||
13 | +import org.springframework.stereotype.Component; | ||
14 | + | ||
15 | +import java.io.IOException; | ||
16 | + | ||
17 | +/** | ||
18 | + * @author: wgf | ||
19 | + * @create: 2020-06-09 14:30 | ||
20 | + * @description: CanalUser监听器 | ||
21 | + **/ | ||
22 | +@Slf4j | ||
23 | +@Component | ||
24 | +public class CanalUserListener { | ||
25 | + | ||
26 | + @RabbitListener(queues = "polaris_order_center.amazon_order") | ||
27 | + public void receive(String message, Channel channel, Message messageEntity) throws IOException { | ||
28 | + | ||
29 | + try { | ||
30 | + | ||
31 | + log.info("接收到队列: {} 消息:{}", MQConst.TEST, message); | ||
32 | + | ||
33 | + MessageVo<AmazonOrder> messageVo = JSON.parseObject(message, new TypeReference<MessageVo<AmazonOrder>>() { | ||
34 | + }); | ||
35 | + | ||
36 | + EventType eventType = EventType.valueOf(messageVo.getType()); | ||
37 | + | ||
38 | + log.info("当前监听binlog 数据库:{}, 数据表:{}", messageVo.getDatabase(), messageVo.getTable()); | ||
39 | + | ||
40 | + // 数据同步只关注这三种事件 | ||
41 | + switch (eventType) { | ||
42 | + case INSERT: | ||
43 | + log.info("触发 INSERT 事件"); | ||
44 | + // messageVo.getData(); 获取数据变更 | ||
45 | + // TODO 自定义实现 | ||
46 | + break; | ||
47 | + case UPDATE: | ||
48 | + log.info("触发 UPDATE 事件"); | ||
49 | + // TODO 自定义实现 | ||
50 | + break; | ||
51 | + case DELETE: | ||
52 | + log.info("触发 DELETE 事件"); | ||
53 | + // TODO 自定义实现 | ||
54 | + break; | ||
55 | + default: | ||
56 | + log.info("其他事件类型:{}, 过滤不处理", eventType); | ||
57 | + } | ||
58 | + | ||
59 | + log.info("消息长度:{}", messageVo.getData().size()); | ||
60 | + | ||
61 | + /** | ||
62 | + * 消息消费确认 | ||
63 | + * 如果客户端在线没有签收没有签收这条Message,则此消息进入Unacked状态,此时监听器阻塞等待消息确认,不推送新Message | ||
64 | + * 如果待消息确认并且客户端下线,下次客户端上线重新推送上次Unacked状态Message | ||
65 | + */ | ||
66 | + channel.basicAck(messageEntity.getMessageProperties().getDeliveryTag(), false); | ||
67 | + } catch (Exception e) { | ||
68 | + /** | ||
69 | + * 第一个参数deliveryTag:发布的每一条消息都会获得一个唯一的deliveryTag,deliveryTag在channel范围内是唯一的 | ||
70 | + * 第二个参数multiple:批量确认标志。如果值为true,包含本条消息在内的、所有比该消息deliveryTag值小的 消息都被拒绝了(除了已经被 ack 的以外);如果值为false,只拒绝三本条消息 | ||
71 | + * 第三个参数requeue:表示如何处理这条消息,如果值为true,则重新放入RabbitMQ的发送队列,如果值为false,则通知RabbitMQ销毁这条消息 | ||
72 | + */ | ||
73 | + //channel.basicNack(messageEntity.getMessageProperties().getDeliveryTag(), false,true); | ||
74 | + e.printStackTrace(); | ||
75 | + } | ||
76 | + } | ||
77 | +} |
1 | +package com.aukey.example.vo; | ||
2 | + | ||
3 | +import lombok.Data; | ||
4 | +import lombok.ToString; | ||
5 | + | ||
6 | +import java.util.List; | ||
7 | +import java.util.Map; | ||
8 | + | ||
9 | +/** | ||
10 | + * @author: wgf | ||
11 | + * @create: 2020-06-09 10:44 | ||
12 | + * @description: 消息实体 | ||
13 | + **/ | ||
14 | +@Data | ||
15 | +@ToString | ||
16 | +public class MessageVo<T> { | ||
17 | + | ||
18 | + // 数据库 | ||
19 | + private String database; | ||
20 | + | ||
21 | + // 数据表 | ||
22 | + private String table; | ||
23 | + | ||
24 | + // INSERT,DELETE,UPDATE | ||
25 | + private String type; | ||
26 | + | ||
27 | + // 最新版本binlog数据 | ||
28 | + private List<T> data; | ||
29 | + | ||
30 | + // 旧版本binlog数据,只有UPDATE时才有值 | ||
31 | + private List<T> old; | ||
32 | + | ||
33 | + // 主键字段 | ||
34 | + private String[] pkNames; | ||
35 | + | ||
36 | + /** | ||
37 | + * value 每个字段对应的sql规范数据枚举类型 | ||
38 | + * 参考 {@link java.sql.Types} | ||
39 | + */ | ||
40 | + private Map<String, Integer> sqlType; | ||
41 | + | ||
42 | + // 每个字段对应的Mysql数据类型 | ||
43 | + private Map<String, String> mysqlType; | ||
44 | +} |
src/main/resources/application.yml
0 → 100644
1 | +spring: | ||
2 | + rabbitmq: | ||
3 | + host: 121.37.17.48 | ||
4 | + port: 5666 | ||
5 | + virtual-host: canal | ||
6 | + username: canal_read | ||
7 | + password: uC4235OY@4 | ||
8 | + publisher-confirm-type: correlated # 开启发送确认 | ||
9 | + publisher-returns: true # 开启发送失败退回 | ||
10 | + listener: # 开启ack消费确认 | ||
11 | + direct: | ||
12 | + acknowledge-mode: manual | ||
13 | + simple: | ||
14 | + acknowledge-mode: manual |
src/main/resources/实时数据同步架构图.jpg
0 → 100644

182.2 KB
-
请 注册 或 登录 后发表评论