From bf7c500d829757f0a1be73db712e3bf8c650309e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E6=AD=AA?= Date: Fri, 5 Nov 2021 22:58:01 +0800 Subject: [PATCH] git stash --- README.md | 44 ++++ austin-common/pom.xml | 20 ++ .../java/com/java3y/austin/pojo/SmsParam.java | 26 +++ austin-handler/pom.xml | 26 +++ .../austin/script/TencentSmsScript.java | 97 +++++++++ austin-service-api-impl/pom.xml | 15 ++ austin-service-api/pom.xml | 15 ++ austin-support/pom.xml | 55 +++++ .../austin/config/OkHttpConfiguration.java | 87 ++++++++ .../com/java3y/austin/utils/OkHttpUtils.java | 195 ++++++++++++++++++ austin-web/pom.xml | 26 +++ .../com/java3y/austin/AustinApplication.java | 39 ++++ .../src/main/resources/application.properties | 6 + austin-web/src/main/resources/logback.xml | 81 ++++++++ pom.xml | 96 +++++++++ 15 files changed, 828 insertions(+) create mode 100644 README.md create mode 100644 austin-common/pom.xml create mode 100644 austin-common/src/main/java/com/java3y/austin/pojo/SmsParam.java create mode 100644 austin-handler/pom.xml create mode 100644 austin-handler/src/main/java/com/java3y/austin/script/TencentSmsScript.java create mode 100644 austin-service-api-impl/pom.xml create mode 100644 austin-service-api/pom.xml create mode 100644 austin-support/pom.xml create mode 100644 austin-support/src/main/java/com/java3y/austin/config/OkHttpConfiguration.java create mode 100644 austin-support/src/main/java/com/java3y/austin/utils/OkHttpUtils.java create mode 100644 austin-web/pom.xml create mode 100644 austin-web/src/main/java/com/java3y/austin/AustinApplication.java create mode 100644 austin-web/src/main/resources/application.properties create mode 100644 austin-web/src/main/resources/logback.xml create mode 100644 pom.xml diff --git a/README.md b/README.md new file mode 100644 index 0000000..15edb23 --- /dev/null +++ b/README.md @@ -0,0 +1,44 @@ +## 01、项目介绍 + +austin项目**核心功能**:发送消息 + +![](https://tva1.sinaimg.cn/large/008i3skNgy1gvztdk1w2wj30ky0p8759.jpg) + +**项目出现意义**:只要公司内有发送消息的需求,都应该要有类似`austin`的项目,对各类消息进行统一发送处理。这有利于对功能的收拢,以及提高业务需求开发的效率 + +![](https://tva1.sinaimg.cn/large/008i3skNgy1gvzz1vifljj31vc0u07dr.jpg) + +## 02、项目流程图 + +austin项目**核心流程**:`austin-api`接收到发送消息请求,直接将请求进`MQ`。`austin-handler`消费`MQ`消息后由各类消息的Handler进行发送处理 + +![](https://tva1.sinaimg.cn/large/008i3skNgy1gvzwltzsdfj31ku0u0q5r.jpg) + +**Question 1** :为什么发个消息需要MQ? + +**Answer 1**:发送消息实际上是调用各个服务提供的API,假设某消息的服务超时,`austin-api`如果是直接调用服务,那存在**超时**风险,拖垮整个接口性能。MQ在这是为了做异步和解耦,并且在一定程度上抗住业务流量。 + +**Question 2**:`austin-stream`和`austin-datahourse`的作用? + +**Answer 2**:`austin-handler`在发送消息的过程中会做些**通用业务处理**以及**发送消息**,这个过程会产生大量的日志数据。日志数据会被收集至MQ,由`austin-stream`流式处理模块进行消费并最后将数据写入至`austin-datahourse` + +**Question 3**:`austin-admin`和`austin-cron`的作用? + +**Answer 3**:`autsin-admin`是`austin`项目的**管理后台**,负责管理消息以及查看消息下发的情况。业务方可根据通过`austin-admin`管理后台直接**定时**发送消息,而`austin-cron`就是承载着定时任务的工作了。 + +## 03、项目技术架构图 + +2021-11~2021-12实现功能: + +![](https://tva1.sinaimg.cn/large/008i3skNgy1gvzx4f1iwoj31le0rs0uy.jpg) + +实现功能所需引入的技术栈: + +![](https://tva1.sinaimg.cn/large/008i3skNgy1gvzxrppbb0j30ym0iaq8v.jpg) + +未完待续 + + + + + diff --git a/austin-common/pom.xml b/austin-common/pom.xml new file mode 100644 index 0000000..33349f4 --- /dev/null +++ b/austin-common/pom.xml @@ -0,0 +1,20 @@ + + + + austin + com.java3y.austin + 0.0.2 + + 4.0.0 + + austin-common + + + org.projectlombok + lombok + + + + \ No newline at end of file diff --git a/austin-common/src/main/java/com/java3y/austin/pojo/SmsParam.java b/austin-common/src/main/java/com/java3y/austin/pojo/SmsParam.java new file mode 100644 index 0000000..0b19f07 --- /dev/null +++ b/austin-common/src/main/java/com/java3y/austin/pojo/SmsParam.java @@ -0,0 +1,26 @@ +package com.java3y.austin.pojo; + +import lombok.Builder; +import lombok.Data; + +import java.util.Set; + +/** + * @author 3y + * @date 2021/11/4 + * 发送短信参数 + */ +@Data +@Builder +public class SmsParam { + + /** + * 需要发送的手机号 + */ + private Set phones; + + /** + * 发送文案 + */ + private String content; +} diff --git a/austin-handler/pom.xml b/austin-handler/pom.xml new file mode 100644 index 0000000..a21b46f --- /dev/null +++ b/austin-handler/pom.xml @@ -0,0 +1,26 @@ + + + + austin + com.java3y.austin + 0.0.2 + + 4.0.0 + + austin-handler + + + + com.java3y.austin + austin-common + 0.0.2 + + + com.java3y.austin + austin-support + 0.0.2 + + + \ No newline at end of file diff --git a/austin-handler/src/main/java/com/java3y/austin/script/TencentSmsScript.java b/austin-handler/src/main/java/com/java3y/austin/script/TencentSmsScript.java new file mode 100644 index 0000000..98bf5b3 --- /dev/null +++ b/austin-handler/src/main/java/com/java3y/austin/script/TencentSmsScript.java @@ -0,0 +1,97 @@ +package com.java3y.austin.script; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.text.CharPool; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; +import com.alibaba.fastjson.JSON; +import com.java3y.austin.pojo.SmsParam; +import com.java3y.austin.utils.OkHttpUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author 3y + * @date 2021/11/4 + *

+ * 接入文档:https://cloud.tencent.com/document/api/382/55981 + */ +@Slf4j +@Service +public class TencentSmsScript { + + @Autowired + private OkHttpUtils okHttpUtils; + + private static final String URL = "https://sms.tencentcloudapi.com/"; + private static final String ACTION = "SendSms"; + private static final String VERSION = "2021-01-11"; + private static final String SMS_SDK_APP_ID = "1400592125"; + private static final String TEMPLATE_ID = "1182097"; + private static final String SIGN_NAME = "Java3y公众号"; + private static final List REGION = Arrays.asList("ap-beijing", "ap-guangzhou", "ap-nanjing"); + + + + /** + * 加密签名相关 + */ + private static final String AUTHORIZATION_SIGN = "TC3-HMAC-SHA256"; + private static final String CREDENTIAL = "Credential=AKIDEXAMPLE"; + private static final String service = "sms"; + private static final String TC3_REQUEST = "tc3_request"; + private static final String SIGNED_HEADERS = "SignedHeaders=content-type;host"; + + + + + + + public String send(SmsParam smsParam) { + + Map header = getHeader(); + Map params = getParams(smsParam); + String paramsJSON = JSON.toJSONString(params); + + String result = okHttpUtils.doPostJsonWithHeaders(URL, paramsJSON, header); + + + return result; + } + + private Map getParams(SmsParam smsParam) { + HashMap params = new HashMap<>(); + int phoneSize = smsParam.getPhones().size() - 1; + int paramSize = Arrays.asList(smsParam.getContent()).size() - 1; + +// params.put("PhoneNumberSet", CollUtil.join(smsParam.getPhones(), StrUtil.COMMA)); + params.put("PhoneNumberSet."+phoneSize, JSON.toJSONString(smsParam.getPhones())); + params.put("SmsSdkAppId", SMS_SDK_APP_ID); + params.put("TemplateId", TEMPLATE_ID); + params.put("SignName", SIGN_NAME); + params.put("TemplateParamSet."+paramSize, JSON.toJSONString(Arrays.asList(smsParam.getContent()))); + params.put("SessionContext", IdUtil.simpleUUID()); + return params; + } + + private Map getHeader() { + HashMap headers = new HashMap<>(); + headers.put("X-TC-Action", ACTION); + headers.put("X-TC-Version", VERSION); + headers.put("X-TC-Region", REGION.get(RandomUtil.randomInt(REGION.size()))); + headers.put("X-TC-Timestamp", String.valueOf(DateUtil.currentSeconds())); + return headers; + } + + + +} diff --git a/austin-service-api-impl/pom.xml b/austin-service-api-impl/pom.xml new file mode 100644 index 0000000..f091e45 --- /dev/null +++ b/austin-service-api-impl/pom.xml @@ -0,0 +1,15 @@ + + + + austin + com.java3y.austin + 0.0.2 + + 4.0.0 + + austin-service-api-impl + + + \ No newline at end of file diff --git a/austin-service-api/pom.xml b/austin-service-api/pom.xml new file mode 100644 index 0000000..8d2d001 --- /dev/null +++ b/austin-service-api/pom.xml @@ -0,0 +1,15 @@ + + + + austin + com.java3y.austin + 0.0.2 + + 4.0.0 + + austin-service-api + + + \ No newline at end of file diff --git a/austin-support/pom.xml b/austin-support/pom.xml new file mode 100644 index 0000000..cfb7b18 --- /dev/null +++ b/austin-support/pom.xml @@ -0,0 +1,55 @@ + + + + austin + com.java3y.austin + 0.0.2 + + 4.0.0 + + austin-support + + + + org.springframework.boot + spring-boot-starter + + + mysql + mysql-connector-java + + + com.squareup.okhttp3 + okhttp + + + org.projectlombok + lombok + + + com.google.guava + guava + + + cn.hutool + hutool-all + + + + com.alibaba + fastjson + + + + + + + src/main/resources + true + + + + + \ No newline at end of file diff --git a/austin-support/src/main/java/com/java3y/austin/config/OkHttpConfiguration.java b/austin-support/src/main/java/com/java3y/austin/config/OkHttpConfiguration.java new file mode 100644 index 0000000..ddc9567 --- /dev/null +++ b/austin-support/src/main/java/com/java3y/austin/config/OkHttpConfiguration.java @@ -0,0 +1,87 @@ +package com.java3y.austin.config; + + +import okhttp3.ConnectionPool; +import okhttp3.OkHttpClient; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.net.ssl.*; +import java.security.*; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.concurrent.TimeUnit; + + +/** + * @author 3y + * @date 2021/11/4 + */ +@Configuration +public class OkHttpConfiguration { + + @Value("${ok.http.connect-timeout}") + private Integer connectTimeout; + + @Value("${ok.http.read-timeout}") + private Integer readTimeout; + + @Value("${ok.http.write-timeout}") + private Integer writeTimeout; + + @Value("${ok.http.max-idle-connections}") + private Integer maxIdleConnections; + + @Value("${ok.http.keep-alive-duration}") + private Long keepAliveDuration; + + @Bean + public OkHttpClient okHttpClient() { + return new OkHttpClient.Builder() + .sslSocketFactory(sslSocketFactory(), x509TrustManager()) + .retryOnConnectionFailure(false) + .connectionPool(pool()) + .connectTimeout(connectTimeout, TimeUnit.SECONDS) + .readTimeout(readTimeout, TimeUnit.SECONDS) + .writeTimeout(writeTimeout,TimeUnit.SECONDS) + .hostnameVerifier((hostname, session) -> true) + .build(); + } + + @Bean + public X509TrustManager x509TrustManager() { + return new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + } + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + } + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + }; + } + + @Bean + public SSLSocketFactory sslSocketFactory() { + try { + // 信任任何链接 + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, new TrustManager[]{x509TrustManager()}, new SecureRandom()); + return sslContext.getSocketFactory(); + } catch (NoSuchAlgorithmException | KeyManagementException e) { + e.printStackTrace(); + } + return null; + } + + @Bean + public ConnectionPool pool() { + return new ConnectionPool(maxIdleConnections, keepAliveDuration, TimeUnit.SECONDS); + } +} diff --git a/austin-support/src/main/java/com/java3y/austin/utils/OkHttpUtils.java b/austin-support/src/main/java/com/java3y/austin/utils/OkHttpUtils.java new file mode 100644 index 0000000..8befb83 --- /dev/null +++ b/austin-support/src/main/java/com/java3y/austin/utils/OkHttpUtils.java @@ -0,0 +1,195 @@ +package com.java3y.austin.utils; + +import cn.hutool.core.map.MapUtil; +import com.google.common.base.Throwables; +import lombok.extern.slf4j.Slf4j; +import okhttp3.*; +import org.jetbrains.annotations.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.nio.charset.StandardCharsets; +import java.util.Map; + +/** + * @author 3y + * @date 2021/11/4 + */ +@Slf4j +@Component +public class OkHttpUtils { + private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); + private static final MediaType XML = MediaType.parse("application/xml; charset=utf-8"); + + @Autowired + private OkHttpClient okHttpClient; + + /** + * get 请求 + * + * @param url 请求url地址 + * @return string + */ + public String doGet(String url) { + return doGet(url, null, null); + } + + + /** + * get 请求 + * + * @param url 请求url地址 + * @param params 请求参数 map + * @return string + */ + public String doGet(String url, Map params) { + return doGet(url, params, null); + } + + /** + * get 请求 + * + * @param url 请求url地址 + * @param headers 请求头字段 {k1, v1 k2, v2, ...} + * @return string + */ + public String doGetWithHeaders(String url, Map headers) { + return doGet(url, null, headers); + } + + + /** + * get 请求 + * + * @param url 请求url地址 + * @param params 请求参数 map + * @param headers 请求头字段 {k1, v1 k2, v2, ...} + * @return string + */ + public String doGet(String url, Map params, Map headers) { + StringBuilder sb = new StringBuilder(url); + if (params != null && params.keySet().size() > 0) { + boolean firstFlag = true; + for (String key : params.keySet()) { + if (firstFlag) { + sb.append("?").append(key).append("=").append(params.get(key)); + firstFlag = false; + } else { + sb.append("&").append(key).append("=").append(params.get(key)); + } + } + } + Request.Builder builder = getBuilderWithHeaders(headers); + Request request = builder.url(sb.toString()).build(); + + log.info("do get request and url[{}]", sb.toString()); + return execute(request); + } + + /** + * post 请求 + * + * @param url 请求url地址 + * @param params 请求参数 map + * @param headers 请求头字段 {k1, v1 k2, v2, ...} + * @return string + */ + public String doPost(String url, Map params, Map headers) { + FormBody.Builder formBuilder = new FormBody.Builder(); + + if (params != null && params.keySet().size() > 0) { + for (String key : params.keySet()) { + formBuilder.add(key, params.get(key)); + } + } + Request.Builder builder = getBuilderWithHeaders(headers); + + Request request = builder.url(url).post(formBuilder.build()).build(); + log.info("do post request and url[{}]", url); + + return execute(request); + } + + + /** + * 获取request Builder + * + * @param headers 请求头字段 {k1, v1 k2, v2, ...} + * @return + */ + private Request.Builder getBuilderWithHeaders(Map headers) { + Request.Builder builder = new Request.Builder(); + if (!MapUtil.isEmpty(headers)) { + for (Map.Entry entry : headers.entrySet()) { + builder.addHeader(entry.getKey(), entry.getValue()); + } + } + return builder; + } + + + /** + * post 请求, 请求数据为 json 的字符串 + * + * @param url 请求url地址 + * @param json 请求数据, json 字符串 + * @return string + */ + public String doPostJson(String url, String json) { + log.info("do post request and url[{}]", url); + return executePost(url, json, JSON, null); + } + + /** + * post 请求, 请求数据为 json 的字符串 + * + * @param url 请求url地址 + * @param json 请求数据, json 字符串 + * @param headers 请求头字段 {k1, v1 k2, v2, ...} + * @return string + */ + public String doPostJsonWithHeaders(String url, String json, Map headers) { + log.info("do post request and url[{}]", url); + return executePost(url, json, JSON, headers); + } + + /** + * post 请求, 请求数据为 xml 的字符串 + * + * @param url 请求url地址 + * @param xml 请求数据, xml 字符串 + * @return string + */ + public String doPostXml(String url, String xml) { + log.info("do post request and url[{}]", url); + return executePost(url, xml, XML, null); + } + + + private String executePost(String url, String data, MediaType contentType, Map headers) { + RequestBody requestBody = RequestBody.create(data.getBytes(StandardCharsets.UTF_8), contentType); + Request.Builder builder = getBuilderWithHeaders(headers); + Request request = builder.url(url).post(requestBody).build(); + + return execute(request); + } + + private String execute(Request request) { + Response response = null; + try { + response = okHttpClient.newCall(request).execute(); + if (response.isSuccessful()) { + return response.body().string(); + } + } catch (Exception e) { + log.error(Throwables.getStackTraceAsString(e)); + } finally { + if (response != null) { + response.close(); + } + } + return ""; + } + +} + diff --git a/austin-web/pom.xml b/austin-web/pom.xml new file mode 100644 index 0000000..27f3b1c --- /dev/null +++ b/austin-web/pom.xml @@ -0,0 +1,26 @@ + + + + austin + com.java3y.austin + 0.0.2 + + 4.0.0 + + austin-web + + + + org.springframework.boot + spring-boot-starter-web + + + com.java3y.austin + austin-handler + 0.0.2 + + + + \ No newline at end of file diff --git a/austin-web/src/main/java/com/java3y/austin/AustinApplication.java b/austin-web/src/main/java/com/java3y/austin/AustinApplication.java new file mode 100644 index 0000000..5787e24 --- /dev/null +++ b/austin-web/src/main/java/com/java3y/austin/AustinApplication.java @@ -0,0 +1,39 @@ +package com.java3y.austin; + +import cn.hutool.setting.SettingUtil; +import com.java3y.austin.pojo.SmsParam; +import com.java3y.austin.script.TencentSmsScript; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Arrays; +import java.util.HashSet; + + +@SpringBootApplication +@RestController +public class AustinApplication { + + @Autowired + private TencentSmsScript tencentSmsScript; + public static void main(String[] args) { + SpringApplication.run(AustinApplication.class, args); + } + + @GetMapping("/hello") + public String hello() { + + SmsParam smsParam = SmsParam.builder() + .phones(new HashSet<>(Arrays.asList("13719193845"))) + .content("3333") + .build(); + + return tencentSmsScript.send(smsParam); + + + } + +} diff --git a/austin-web/src/main/resources/application.properties b/austin-web/src/main/resources/application.properties new file mode 100644 index 0000000..c122ff6 --- /dev/null +++ b/austin-web/src/main/resources/application.properties @@ -0,0 +1,6 @@ +# ok http配置信息 +ok.http.connect-timeout=30 +ok.http.read-timeout=30 +ok.http.write-timeout=30 +ok.http.max-idle-connections=200 +ok.http.keep-alive-duration=300 diff --git a/austin-web/src/main/resources/logback.xml b/austin-web/src/main/resources/logback.xml new file mode 100644 index 0000000..ef49c0c --- /dev/null +++ b/austin-web/src/main/resources/logback.xml @@ -0,0 +1,81 @@ + + + + + austin + + + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + + UTF-8 + + + + + + + + ${log.path}/austin-info.log + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + + + ${log.path}/logs/austin-info-%d{yyyy-MM-dd}.%i.log + + 1000MB + + + 15 + + + + info + ACCEPT + DENY + + + + + + + ${log.path}/austin-error.log + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + + ${log.path}/austin-error-%d{yyyy-MM-dd}.%i.log + + 1000MB + + + 15 + + + + ERROR + ACCEPT + DENY + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..0312992 --- /dev/null +++ b/pom.xml @@ -0,0 +1,96 @@ + + + 4.0.0 + pom + + + austin-web + austin-service-api + austin-service-api-impl + austin-common + austin-support + austin-handler + + + + org.springframework.boot + spring-boot-starter-parent + 2.5.6 + + + + com.java3y.austin + austin + 0.0.2 + austin + austin-message + + + 1.8 + + + + + + + mysql + mysql-connector-java + 5.1.35 + + + + + cn.hutool + hutool-all + 5.7.15 + + + + + com.google.guava + guava + 31.0.1-jre + + + + + org.apache.commons + commons-collections4 + 4.4 + + + + + com.squareup.okhttp3 + okhttp + 4.9.2 + + + + + com.alibaba + fastjson + 1.2.78 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + +