From f566a198449100a683bfa28969f2b4e20b3f7d74 Mon Sep 17 00:00:00 2001 From: Menethil Date: Sun, 15 Jul 2018 20:37:24 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitlab-ci.yml | 30 +++++++++++++++++++ .../src/main/resources/notify.properties | 16 +++++----- 2 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000..7a8f6f10 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,30 @@ +stages: + - deploy +deploy: + stage: deploy + script: + - mvn install + - mvn clean package + - rm -rf /root/spring_boot/*.jar + - rm -rf /etc/init.d/litemall-* + - cp -rf litemall-admin-api/target/litemall-admin-api-*-exec.jar /root/spring_boot/litemall-admin-api.jar + - cp -rf litemall-os-api/target/litemall-os-api-*-exec.jar /root/spring_boot/litemall-os-api.jar + - cp -rf litemall-wx-api/target/litemall-wx-api-*-exec.jar /root/spring_boot/litemall-wx-api.jar + - sudo chmod 777 /root/spring_boot/*.jar + - sudo ln -f -s /root/spring_boot/litemall-admin-api.jar /etc/init.d/litemall-admin-api + - sudo ln -f -s /root/spring_boot/litemall-os-api.jar /etc/init.d/litemall-os-api + - sudo ln -f -s /root/spring_boot/litemall-wx-api.jar /etc/init.d/litemall-wx-api + - sudo /etc/init.d/litemall-os-api restart + - sudo /etc/init.d/litemall-wx-api restart + - sudo /etc/init.d/litemall-admin-api restart + - systemctl stop nginx + - rm -rf /root/nginx_web/ + - cd litemall-admin + - cnpm install + - cnpm run build:dep + - mkdir /root/nginx_web + - cp -rf dist/* /root/nginx_web + - sudo chmod 777 /root/nginx_web + - systemctl restart nginx + tags: + - litemall_dev \ No newline at end of file diff --git a/litemall-core/src/main/resources/notify.properties b/litemall-core/src/main/resources/notify.properties index 9579ab7a..afbcaa72 100644 --- a/litemall-core/src/main/resources/notify.properties +++ b/litemall-core/src/main/resources/notify.properties @@ -1,16 +1,16 @@ #\u90AE\u4EF6\u53D1\u9001\u914D\u7F6E -sprint.mail.enable=false +sprint.mail.enable=true spring.mail.host=smtp.exmail.qq.com -spring.mail.username=ex@ex.com.cn -spring.mail.password= -spring.mail.sendto=ex@qq.com +spring.mail.username=menethil@menethil.com.cn +spring.mail.password=VFmZa5zobguGYAXu +spring.mail.sendto=24220394@qq.com #\u77ED\u4FE1\u53D1\u9001\u914D\u7F6E -spring.sms.enable=false -spring.sms.appid= -spring.sms.appkey= -spring.sms.sign= +spring.sms.enable=true +spring.sms.appid=1400111512 +spring.sms.appkey=86b445ba63f211be474d73d9f67ac3f4 +spring.sms.sign=\u53A6\u95E8\u946B\u9F0E\u4FE1 #\u77ED\u4FE1\u6A21\u7248\u6D88\u606F\u914D\u7F6E\uFF0C\u8BF7\u5728\u817E\u8BAF\u77ED\u4FE1\u5E73\u53F0\u914D\u7F6E\u597D\u5404\u4E2A\u901A\u77E5\u6D88\u606F\u7684\u6A21\u7248\uFF0C\u7136\u540E\u5C06\u6A21\u7248ID\u4E00\u4E00\u8D4B\u503C,LitemallNotifyService,NotifyType\u679A\u4E3E\u4E2D\u4E0E\u8FD9\u91CC\u4E00\u4E00\u5BF9\u5E94 spring.sms.template.pay.complated=156349 From fd89e50c6d6b4e022e78909f9cb2e9094b81dd7f Mon Sep 17 00:00:00 2001 From: Menethil Date: Sun, 15 Jul 2018 22:38:37 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E6=96=87=E4=BB=B6=EF=BC=8C=E9=BB=98=E8=AE=A4=E7=BC=96=E8=AF=91?= =?UTF-8?q?admin=E4=B8=BA=E6=9C=AC=E5=9C=B0=20=E4=BF=AE=E6=94=B9=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E7=9A=84SQL=E9=93=BE=E6=8E=A5=EF=BC=8C=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0allowPubilcKeyRetrieval?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application-dev.properties | 2 +- litemall-admin/config/dep.env.js | 4 ++-- .../src/main/resources/application-dev.properties | 6 +++--- .../src/main/resources/application-dev.properties | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/litemall-admin-api/src/main/resources/application-dev.properties b/litemall-admin-api/src/main/resources/application-dev.properties index 47db7700..500ee61d 100644 --- a/litemall-admin-api/src/main/resources/application-dev.properties +++ b/litemall-admin-api/src/main/resources/application-dev.properties @@ -3,7 +3,7 @@ pagehelper.reasonable=true pagehelper.supportMethodsArguments=true pagehelper.params=count=countSql -spring.datasource.druid.url=jdbc:mysql://localhost:3306/litemall?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&verifyServerCertificate=false&useSSL=false +spring.datasource.druid.url=jdbc:mysql://localhost:3306/litemall?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&verifyServerCertificate=false&useSSL=false&allowPublicKeyRetrieval=true spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver spring.datasource.druid.username=litemall spring.datasource.druid.password=litemall123456 diff --git a/litemall-admin/config/dep.env.js b/litemall-admin/config/dep.env.js index 512f55d7..bfc41443 100644 --- a/litemall-admin/config/dep.env.js +++ b/litemall-admin/config/dep.env.js @@ -1,6 +1,6 @@ module.exports = { NODE_ENV: '"production"', ENV_CONFIG: '"dep"', - BASE_API: '"http://122.152.206.172:8083/admin"', - OS_API: '"http://122.152.206.172:8081/os"' + BASE_API: '"http://localhost:8083/admin"', + OS_API: '"http://localhost:8081/os"' } diff --git a/litemall-os-api/src/main/resources/application-dev.properties b/litemall-os-api/src/main/resources/application-dev.properties index 0c2f6f82..00479f2a 100644 --- a/litemall-os-api/src/main/resources/application-dev.properties +++ b/litemall-os-api/src/main/resources/application-dev.properties @@ -3,7 +3,7 @@ pagehelper.reasonable=true pagehelper.supportMethodsArguments=true pagehelper.params=count=countSql -spring.datasource.druid.url=jdbc:mysql://localhost:3306/litemall?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&verifyServerCertificate=false&useSSL=false +spring.datasource.druid.url=jdbc:mysql://localhost:3306/litemall?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&verifyServerCertificate=false&useSSL=false&allowPublicKeyRetrieval=true spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver spring.datasource.druid.username=litemall spring.datasource.druid.password=litemall123456 @@ -26,7 +26,7 @@ logging.level.org.mybatis=ERROR logging.level.org.linlinjava.litemall.db=ERROR logging.level.org.linlinjava.litemall=ERROR -# 开发者应该设置成自己的域名,必须附带http或者https -# 开发者可以查看OsStorageController.generateUrl +# \u5F00\u53D1\u8005\u5E94\u8BE5\u8BBE\u7F6E\u6210\u81EA\u5DF1\u7684\u57DF\u540D\uFF0C\u5FC5\u987B\u9644\u5E26http\u6216\u8005https +# \u5F00\u53D1\u8005\u53EF\u4EE5\u67E5\u770BOsStorageController.generateUrl org.linlinjava.litemall.os.address=http://127.0.0.1 org.linlinjava.litemall.os.port=8081 \ No newline at end of file diff --git a/litemall-wx-api/src/main/resources/application-dev.properties b/litemall-wx-api/src/main/resources/application-dev.properties index 5572b87a..d662f33e 100644 --- a/litemall-wx-api/src/main/resources/application-dev.properties +++ b/litemall-wx-api/src/main/resources/application-dev.properties @@ -3,7 +3,7 @@ pagehelper.reasonable=true pagehelper.supportMethodsArguments=true pagehelper.params=count=countSql -spring.datasource.druid.url=jdbc:mysql://localhost:3306/litemall?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&verifyServerCertificate=false&useSSL=false +spring.datasource.druid.url=jdbc:mysql://localhost:3306/litemall?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&verifyServerCertificate=false&useSSL=false&allowPublicKeyRetrieval=true spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver spring.datasource.druid.username=litemall spring.datasource.druid.password=litemall123456 From f24cd5342c77aa11858c1c32577ef590ec5894b9 Mon Sep 17 00:00:00 2001 From: Menethil Date: Mon, 16 Jul 2018 00:38:00 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=85=BE=E8=AE=AF?= =?UTF-8?q?=E5=AF=B9=E8=B1=A1=E5=AD=98=E5=82=A8=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- litemall-os-api/pom.xml | 7 ++ .../os/service/FileSystemStorageService.java | 39 ++++-- .../litemall/os/service/StorageService.java | 20 ++- .../litemall/os/tencent/TencentOSService.java | 118 ++++++++++++++++++ .../litemall/os/web/OsStorageController.java | 18 +-- .../src/main/resources/application.properties | 5 + .../src/main/resources/tencent.properties | 6 + 7 files changed, 181 insertions(+), 32 deletions(-) create mode 100644 litemall-os-api/src/main/java/org/linlinjava/litemall/os/tencent/TencentOSService.java create mode 100644 litemall-os-api/src/main/resources/tencent.properties diff --git a/litemall-os-api/pom.xml b/litemall-os-api/pom.xml index c8c69743..529eaac7 100644 --- a/litemall-os-api/pom.xml +++ b/litemall-os-api/pom.xml @@ -22,6 +22,13 @@ litemall-db + + com.qcloud + cos_api + 5.4.4 + + + diff --git a/litemall-os-api/src/main/java/org/linlinjava/litemall/os/service/FileSystemStorageService.java b/litemall-os-api/src/main/java/org/linlinjava/litemall/os/service/FileSystemStorageService.java index 4e5729cb..3fef0c31 100644 --- a/litemall-os-api/src/main/java/org/linlinjava/litemall/os/service/FileSystemStorageService.java +++ b/litemall-os-api/src/main/java/org/linlinjava/litemall/os/service/FileSystemStorageService.java @@ -7,14 +7,23 @@ import java.net.MalformedURLException; import java.nio.file.*; import java.util.stream.Stream; +import org.linlinjava.litemall.os.config.ObjectStorageConfig; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; -@Service +/** + * 服务器本地文件存储 + */ +@Service("localStorage") public class FileSystemStorageService implements StorageService { + @Autowired + private ObjectStorageConfig osConfig; private static final Path rootLocation = Paths.get("storage"); + static { try { Files.createDirectories(rootLocation); @@ -24,12 +33,11 @@ public class FileSystemStorageService implements StorageService { } @Override - public void store(InputStream inputStream, String filename) { + public void store(MultipartFile file, String keyName) { try { - Files.copy(inputStream, this.rootLocation.resolve(filename), StandardCopyOption.REPLACE_EXISTING); - } - catch (IOException e) { - throw new RuntimeException ("Failed to store file " + filename, e); + Files.copy(file.getInputStream(), this.rootLocation.resolve(keyName), StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + throw new RuntimeException("Failed to store file " + keyName, e); } } @@ -39,9 +47,8 @@ public class FileSystemStorageService implements StorageService { return Files.walk(this.rootLocation, 1) .filter(path -> !path.equals(this.rootLocation)) .map(path -> this.rootLocation.relativize(path)); - } - catch (IOException e) { - throw new RuntimeException ("Failed to read stored files", e); + } catch (IOException e) { + throw new RuntimeException("Failed to read stored files", e); } } @@ -58,12 +65,10 @@ public class FileSystemStorageService implements StorageService { Resource resource = new UrlResource(file.toUri()); if (resource.exists() || resource.isReadable()) { return resource; - } - else { + } else { return null; } - } - catch (MalformedURLException e) { + } catch (MalformedURLException e) { e.printStackTrace(); return null; } @@ -79,4 +84,12 @@ public class FileSystemStorageService implements StorageService { } } + @Override + public String generateUrl(String keyName) { + String url = osConfig.getAddress() + ":" + osConfig.getPort() + "/os/storage/fetch/" + keyName; + if (!url.startsWith("http")) { + url = "http://" + url; + } + return url; + } } \ No newline at end of file diff --git a/litemall-os-api/src/main/java/org/linlinjava/litemall/os/service/StorageService.java b/litemall-os-api/src/main/java/org/linlinjava/litemall/os/service/StorageService.java index e2126000..2354e9c1 100644 --- a/litemall-os-api/src/main/java/org/linlinjava/litemall/os/service/StorageService.java +++ b/litemall-os-api/src/main/java/org/linlinjava/litemall/os/service/StorageService.java @@ -1,19 +1,31 @@ package org.linlinjava.litemall.os.service; import org.springframework.core.io.Resource; +import org.springframework.web.multipart.MultipartFile; + import java.io.InputStream; import java.nio.file.Path; import java.util.stream.Stream; +/** + * 对象存储接口 + */ public interface StorageService { - void store(InputStream inputStream, String filename); + /** + * 存储一个文件对象 + * @param file SpringBoot MultipartFile文件对象 + * @param keyName 文件索引名 + */ + void store(MultipartFile file, String keyName); Stream loadAll(); - Path load(String filename); + Path load(String keyName); - Resource loadAsResource(String filename); + Resource loadAsResource(String keyName); - void delete(String filename); + void delete(String keyName); + + String generateUrl(String keyName); } \ No newline at end of file diff --git a/litemall-os-api/src/main/java/org/linlinjava/litemall/os/tencent/TencentOSService.java b/litemall-os-api/src/main/java/org/linlinjava/litemall/os/tencent/TencentOSService.java new file mode 100644 index 00000000..a3d02501 --- /dev/null +++ b/litemall-os-api/src/main/java/org/linlinjava/litemall/os/tencent/TencentOSService.java @@ -0,0 +1,118 @@ +package org.linlinjava.litemall.os.tencent; + +import com.qcloud.cos.COSClient; +import com.qcloud.cos.ClientConfig; +import com.qcloud.cos.auth.BasicCOSCredentials; +import com.qcloud.cos.auth.COSCredentials; +import com.qcloud.cos.model.ObjectMetadata; +import com.qcloud.cos.model.PutObjectRequest; +import com.qcloud.cos.model.PutObjectResult; +import com.qcloud.cos.region.Region; +import org.linlinjava.litemall.os.service.StorageService; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.io.Resource; +import org.springframework.core.io.UrlResource; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.file.Path; +import java.util.stream.Stream; + +/** + * 腾讯对象存储服务类 + */ +@PropertySource(value = "classpath:tencent.properties") +@Service("tencent") +public class TencentOSService implements StorageService { + + @Value("${tencent.os.secretId}") + private String accessKey; + @Value("${tencent.os.secretKey}") + private String secretKey; + @Value("${tencent.os.region}") + private String region; + @Value("${tencent.os.bucketName}") + private String bucketName; + + private COSClient cosClient; + + public TencentOSService() { + + } + + private COSClient getCOSClient() { + if (cosClient == null) { + // 1 初始化用户身份信息(secretId, secretKey) + COSCredentials cred = new BasicCOSCredentials(accessKey, secretKey); + // 2 设置bucket的区域, COS地域的简称请参照 https://cloud.tencent.com/document/product/436/6224 + ClientConfig clientConfig = new ClientConfig(new Region(region)); + cosClient = new COSClient(cred, clientConfig); + } + + return cosClient; + } + + private String getBaseUrl() { + //https://litemall-1256968571.cos-website.ap-guangzhou.myqcloud.com + return "https://" + bucketName + ".cos-website." + region + ".myqcloud.com/"; + } + + @Override + public void store(MultipartFile file, String keyName) { + try { + // 简单文件上传, 最大支持 5 GB, 适用于小文件上传, 建议 20M以下的文件使用该接口 + ObjectMetadata objectMetadata = new ObjectMetadata(); + objectMetadata.setContentLength(file.getSize()); + objectMetadata.setContentType(file.getContentType()); + // 对象键(Key)是对象在存储桶中的唯一标识。例如,在对象的访问域名 `bucket1-1250000000.cos.ap-guangzhou.myqcloud.com/doc1/pic1.jpg` 中,对象键为 doc1/pic1.jpg, 详情参考 [对象键](https://cloud.tencent.com/document/product/436/13324) + PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, keyName, file.getInputStream(), objectMetadata); + PutObjectResult putObjectResult = getCOSClient().putObject(putObjectRequest); + } catch (Exception ex) { + System.console().printf(ex.getMessage()); + } + } + + @Override + public Stream loadAll() { + return null; + } + + @Override + public Path load(String keyName) { + return null; + } + + @Override + public Resource loadAsResource(String keyName) { + try { + URL url = new URL(getBaseUrl() + keyName); + Resource resource = new UrlResource(url); + if (resource.exists() || resource.isReadable()) { + return resource; + } else { + return null; + } + } catch (MalformedURLException e) { + e.printStackTrace(); + return null; + } + } + + @Override + public void delete(String keyName) { + try { + getCOSClient().deleteObject(bucketName, keyName); + }catch (Exception e){ + e.printStackTrace(); + } + + } + + @Override + public String generateUrl(String keyName) { + return getBaseUrl() + keyName; + } +} diff --git a/litemall-os-api/src/main/java/org/linlinjava/litemall/os/web/OsStorageController.java b/litemall-os-api/src/main/java/org/linlinjava/litemall/os/web/OsStorageController.java index 78cbe26b..451ce81c 100644 --- a/litemall-os-api/src/main/java/org/linlinjava/litemall/os/web/OsStorageController.java +++ b/litemall-os-api/src/main/java/org/linlinjava/litemall/os/web/OsStorageController.java @@ -5,7 +5,6 @@ import org.linlinjava.litemall.core.util.ResponseUtil; import org.linlinjava.litemall.db.domain.LitemallStorage; import org.linlinjava.litemall.db.service.LitemallStorageService; import org.linlinjava.litemall.os.service.StorageService; -import org.linlinjava.litemall.os.config.ObjectStorageConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.Resource; import org.springframework.http.HttpHeaders; @@ -25,22 +24,11 @@ import java.util.Map; @RequestMapping("/os/storage") public class OsStorageController { - @Autowired + @javax.annotation.Resource(name="${activeStorage}") private StorageService storageService; @Autowired private LitemallStorageService litemallStorageService; - @Autowired - private ObjectStorageConfig osConfig; - - private String generateUrl(String key){ - String url = osConfig.getAddress() + ":" + osConfig.getPort() + "/os/storage/fetch/" + key; - if(!url.startsWith("http")){ - url = "http://" + url; - } - return url; - } - private String generateKey(String originalFilename){ int index = originalFilename.lastIndexOf('.'); String suffix = originalFilename.substring(index); @@ -82,9 +70,9 @@ public class OsStorageController { return ResponseUtil.badArgumentValue(); } String key = generateKey(originalFilename); - storageService.store(inputStream, key); + storageService.store(file, key); - String url = generateUrl(key); + String url = storageService.generateUrl(key); LitemallStorage storageInfo = new LitemallStorage(); storageInfo.setName(originalFilename); storageInfo.setSize((int)file.getSize()); diff --git a/litemall-os-api/src/main/resources/application.properties b/litemall-os-api/src/main/resources/application.properties index b861699d..59eb1f3b 100644 --- a/litemall-os-api/src/main/resources/application.properties +++ b/litemall-os-api/src/main/resources/application.properties @@ -1,3 +1,8 @@ spring.profiles.active=dev server.port=8081 logging.level.org.linlinjava.litemall.os.Application=DEBUG + + +# \u5B58\u50A8\u5B9E\u73B0\uFF0C\u53EF\u9009\u62E9 localStorage \u6216\u8005 tencent \uFF0C\u5982\u679C\u9009\u62E9 tencent\uFF0C\u9700\u8981\u5F00\u901A\u817E\u8BAF\u5BF9\u8C61\u5B58\u50A8\u5E76\u914D\u7F6E tencent.properties +activeStorage=localStorage +#activeStorage=tencent diff --git a/litemall-os-api/src/main/resources/tencent.properties b/litemall-os-api/src/main/resources/tencent.properties new file mode 100644 index 00000000..435d03ba --- /dev/null +++ b/litemall-os-api/src/main/resources/tencent.properties @@ -0,0 +1,6 @@ + +# \u817E\u8BAF\u4E91\u5B58\u50A8\u76F8\u5173\u914D\u7F6E,\u817E\u8BAF\u4E91\u5FC5\u987B\u6253\u5F00 #\u9759\u6001\u7F51\u7AD9(https://cloud.tencent.com/document/product/436/6249) \u652F\u6301\uFF0C\u5426\u5219\u56FE\u7247\u4F1A\u76F4\u63A5\u4E0B\u8F7D\u800C\u4E0D\u662F\u663E\u793A +tencent.os.secretId="" +tencent.os.secretKey="" +tencent.os.region="" +tencent.os.bucketName=""