diff --git a/README.md b/README.md index 5cf080b28..7ad84e658 100644 --- a/README.md +++ b/README.md @@ -28,11 +28,11 @@ > > > > `documents` -- 环境搭建、编码规范、项目需求等等文档资源 > > -> > `sc-java` -- `Java`项目主体 +> > `psi-java` -- `Java`项目主体 > > -> > `sc-cpp` -- `C++`项目主体 +> > `psi-cpp` -- `C++`项目主体 > > -> > `sc-frontend` -- 前端项目主体 +> > `psi-frontend` -- 前端项目主体 ## 软件架构 diff --git a/psi-java/README.md b/psi-java/README.md new file mode 100644 index 000000000..cec2b23f2 --- /dev/null +++ b/psi-java/README.md @@ -0,0 +1,123 @@ +# 工程简介 +项目架构父模块,用于管理第三方依赖和项目模块 + +创建spring boot项目的时候如果比较慢可以使用:http://start.aliyun.com/ 替代原来的 https://start.spring.io + + +# 延伸阅读 + +## `nacos`服务器配置参考 + +***注意:上传到 `Nacos` 配置中心的配置不要带中文注释,不然会出想编码问题。*** + +### `system.yaml` + +系统配置,后续配置网关或新增服务器都在这里配置,方便在线扩展 + +```yaml +spring: + cloud: + inetutils: + #优先网络IP选择 + preferred-networks: + - 192.168 + - 39.99 + #忽略一些虚拟网卡 + ignored-interfaces: + - docker0 + - veth.* + - VM.* + - br-.* +``` + +### `data-source.yaml` + +数据源配置 + +```yaml +#References +#https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter +#https://github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE +#https://github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE%E5%B1%9E%E6%80%A7%E5%88%97%E8%A1%A8 +spring: + #配置MySQL数据库 + datasource: + url: jdbc:mysql://192.168.220.128:3306/test?useUnicode=true&useSSL=false&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true + username: root + password: 123456 + driver-class-name: com.mysql.cj.jdbc.Driver + type: com.alibaba.druid.pool.DruidDataSource + druid: + name: DruidDataSource + initial-size: 1 + min-idle: 1 + max-active: 20 + async-init: true + max-wait: 6000 + time-between-eviction-runs-millis: 60000 + min-evictable-idle-time-millis: 300000 + max-evictable-idle-time-millis: 900000 + validation-query: SELECT 1 + test-while-idle: true + test-on-borrow: false + test-on-return: false + pool-prepared-statements: true + max-pool-prepared-statement-per-connection-size: 20 + connection-init-sqls: SET NAMES utf8mb4 COLLATE utf8mb4_0900_ai_ci; + filters: stat + #配置Redis数据库 + redis: + host: 192.168.220.128 + port: 6379 + password: 01star + data: + #mongodb配置 + mongodb: + #格式: mongodb://账号:密码@主机地址:端口/数据库名称 + uri: mongodb://awei:123456@192.168.220.128:27017/firstDb +``` + +### `third-services.yaml` + +第三方服务配置 + +```yaml +#C++提供服务器 +cpp: + sample: + url: http://localhost:8090 + name: feign-cpp-sample +#sentinel提供服务 +sentinel: + dashboard: 192.168.220.128:8718 +#rocketmq配置 +rocket-mq: + name-server: 192.168.220.128:9876 +#seata配置 +seata: + default: 192.168.220.128:8091 +#logstash配置 +logstash: + host: 192.168.220.128 +#FASTDFS配置 +#References +#https://i4t.com/4758.html +#https://github.com/happyfish100/fastdfs/tree/master/docker/dockerfile_network/conf +fastdfs: + charset: UTF-8 + connect-timeout: 5 + network-timeout: 30 + http-secret-key: FastDFS1234567890 + http-anti-steal-token: true + connection-pool-max-idle: 20 + connection-pool-max-total: 20 + connection-pool-min-idle: 2 + nginx-servers: 192.168.220.128:8888 + tracker-servers: 192.168.220.128:22122 +#Easy ES +easy-es: + address: 192.168.220.128:9200 + username: elastic #es用户名,若无则删去此行配置 + password: WG7WVmuNMtM4GwNYkyWH #es密码,若无则删去此行配置 +``` + diff --git a/psi-java/code-generator/README.md b/psi-java/code-generator/README.md new file mode 100644 index 000000000..c8badc9e6 --- /dev/null +++ b/psi-java/code-generator/README.md @@ -0,0 +1,6 @@ +# 工程简介 +代码生成器项目,使用生成功能的时候请注意修改配置文件来对应目录结构 + +# 扩展阅读 + +https://baomidou.com/pages/779a6e/#%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8 \ No newline at end of file diff --git a/psi-java/code-generator/pom.xml b/psi-java/code-generator/pom.xml new file mode 100644 index 000000000..8a4f3fc84 --- /dev/null +++ b/psi-java/code-generator/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + psi-java + com.zeroone.star + ${revision} + ../pom.xml + + code-generator + + + org.springframework.boot + spring-boot-starter-logging + + + mysql + mysql-connector-java + + + com.baomidou + mybatis-plus-boot-starter + + + com.baomidou + mybatis-plus-generator + + + org.apache.velocity + velocity-engine-core + + + diff --git a/psi-java/code-generator/src/main/java/com/zeroone/star/App.java b/psi-java/code-generator/src/main/java/com/zeroone/star/App.java new file mode 100644 index 000000000..b6b5a6034 --- /dev/null +++ b/psi-java/code-generator/src/main/java/com/zeroone/star/App.java @@ -0,0 +1,60 @@ +package com.zeroone.star; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.generator.FastAutoGenerator; +import com.baomidou.mybatisplus.generator.config.OutputFile; +import com.baomidou.mybatisplus.generator.fill.Column; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.ResourceBundle; + +/** + *

+ * 描述:代码生成程序入口 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +public class App { + /** + * 处理 all 情况 + * + * @param tables 表名字符串 + * @return 处理结果 + */ + private static List getTables(String tables) { + return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(",")); + } + + public static void main(String[] args) { + ResourceBundle res = ResourceBundle.getBundle("database"); + FastAutoGenerator.create(res.getString("db.url"), res.getString("db.username"), res.getString("db.password")) + // 全局配置 + .globalConfig((scanner, builder) -> builder + .author(scanner.apply("请输入作者名称:")) + .fileOverride() //允许重新文件 + .disableOpenDir() //禁止生成成功打开文件夹 + .outputDir(res.getString("g.output.dir")) //设置输出路径 + ) + // 包配置 + .packageConfig((scanner, builder) -> builder + .parent(res.getString("pkg.name")) + .moduleName(scanner.apply("输入模块名称:")) + .pathInfo(Collections.singletonMap(OutputFile.mapperXml, res.getString("g.output.dir") + "\\..\\resources\\" + res.getString("pkg.xml.dir"))) + ) + // 策略配置 + .strategyConfig((scanner, builder) -> builder + .addInclude(getTables(scanner.apply("请输入表名,多个英文逗号分隔,所有输入all:"))) + .controllerBuilder().enableRestStyle().enableHyphenStyle() + .mapperBuilder().enableMapperAnnotation() + .entityBuilder().enableLombok().addTableFills(new Column("create_time", FieldFill.INSERT)) + .build() + ) + .execute(); + } +} diff --git a/psi-java/code-generator/src/main/resources/database.properties b/psi-java/code-generator/src/main/resources/database.properties new file mode 100644 index 000000000..2f0d64ade --- /dev/null +++ b/psi-java/code-generator/src/main/resources/database.properties @@ -0,0 +1,6 @@ +db.url=jdbc:mysql://43.138.223.223:3306/zopsi_sys?useUnicode=true&useSSL=false&characterEncoding=utf-8&serverTimezone=Asia/Shanghai +db.username=root +db.password=psitxms9527 +g.output.dir=.\\psi-prepayment\\src\\main\\java +pkg.name=com.zeroone.star +pkg.xml.dir=mapper diff --git a/psi-java/fastdfs-spring-boot-starter/LICENSE b/psi-java/fastdfs-spring-boot-starter/LICENSE new file mode 100644 index 000000000..0a041280b --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/psi-java/fastdfs-spring-boot-starter/README.md b/psi-java/fastdfs-spring-boot-starter/README.md new file mode 100644 index 000000000..668a52755 --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/README.md @@ -0,0 +1,143 @@ +# fastdfs-spring-boot-starter + +SpringBoot2.x的高性能FastDFS客户端。避免手动引入jar包导致项目混乱,提供常用的API,有助于快速上手开发。 + +- 自动添加依赖 +- 初始化配置项 +- 基于Commons Pool2 实现的高性能连接池 +- 更多操作FastDFS的API +- 支持多Tracker多Storage多NGINX负载均衡模式 +- 基于fastdfs-client-java(1.29-SNAPSHOT)源代码构建 + +原作者项目地址:https://github.com/bluemiaomiao/fastdfs-spring-boot-starter.git + +# 一、快速开始 + +## (1)使用Maven + +```xml + + io.github.bluemiaomiao + fastdfs-spring-boot-starter + 2.0.1-RELEASE + +``` + +## (2)使用Gradle + +```groovy +compile group: 'io.github.bluemiaomiao', name: 'fastdfs-spring-boot-starter', version: '2.0.0-RELEASE' +``` + +# 二、手动编译 + +## (1)克隆整个仓库 + +```bash +git clone https://gitee.com/zero-awei/fastdfs-spring-boot-starter.git +cd fastdfs-spring-boot-starter +``` + +## (2)安装到本地 + +```bash +mvn clean install +mvn source:jar install +mvn javadoc:jar install +``` + +## (3)添加到项目 + +```xml + + io.github.bluemiaomiao + fastdfs-spring-boot-starter + 2.0.1-RELEASE + +``` + +## (4) 在主配置类上添加注解 (``@EnableFastdfsClient``) + +```java +@EnableFastdfsClient +@SpringBootApplication +public class DemoApplication { + + @Autowired + private FastdfsClientService fastdfsClientService; + + public static void main(String[] args) { + SpringApplication.run(DemoApplication.class, args); + } +} +``` +## (5) 添加配置条目(application.properties) + +```properties +fastdfs.nginx-servers=192.168.80.2:8000,192.168.80.3:8000,192.168.80.4:8000 +fastdfs.tracker-servers=192.168.80.2:22122,192.168.80.3:22122,192.168.80.4:22122 +fastdfs.http-secret-key=your key +fastdfs.http-anti-steal-token=true +fastdfs.http-tracker-http-port=8080 +fastdfs.network-timeout=30 +fastdfs.connect-timeout=5 +fastdfs.connection-pool-max-idle=18 +fastdfs.connection-pool-min-idle=2 +fastdfs.connection-pool-max-total=18 +fastdfs.charset=UTF-8 +``` + +## (6) 添加配置条目(application.yml) + +```yaml +fastdfs: + charset: UTF-8 + connect-timeout: 5 + http-secret-key: your key + network-timeout: 30 + http-anti-steal-token: true + http-tracker-http-port: 8080 + connection-pool-max-idle: 20 + connection-pool-max-total: 20 + connection-pool-min-idle: 2 + nginx-servers: 192.168.80.2:8000,192.168.80.3:8000,192.168.80.4:8000 + tracker-servers: 192.168.80.2:22122,192.168.80.3:22122,192.168.80.4:22122 +``` + +## (7) 即刻享受它带来的便利 + +```java +@Autowired +private FastdfsClientService remoteService; + +// 上传文件 +String[] remoteInfo; +try { + remoteInfo = remoteService.autoUpload(image.getBytes(), type); + log.info("上传的服务器分组: " + remoteInfo[0]); + log.info("上传的服务器ID: " + remoteInfo[1]); +} catch (Exception e) { + log.error("Upload file error: " + e.getMessage()); + return HttpStatus.INTERNAL_SERVER_ERROR; +} + +// 下载文件 +String group = file.getGroup(); +String storage = file.getStorageId(); +String remoteFile = "Get file error."; + +try { + remoteFile = fastdfs.autoDownloadWithToken(group, storage, remoteAddress); +} catch (Exception e) { + log.error("Get file error: " + e.getMessage()); +} +``` + +```java +// 当启用防盗链机制时,需要使用该方法下载文件 +FastdfsClientService.autoDownloadWithToken(String fileGroup, String remoteFileName, String clientIpAddress) +// 当没有启用防盗链机制时,需要使用该方法下载文件 +FastdfsClientService.autoDownloadWithoutToken(String fileGroup, String remoteFileName, String clientIpAddress) +// 上传文件的方法 +FastdfsClientService.autoUpload(byte[] buffer, String ext) +``` diff --git a/psi-java/fastdfs-spring-boot-starter/README_en_US.md b/psi-java/fastdfs-spring-boot-starter/README_en_US.md new file mode 100644 index 000000000..87ca9d5ea --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/README_en_US.md @@ -0,0 +1,144 @@ +# fastdfs-spring-boot-starter + +A high-performance fastdfs client compatible with springboot 2. X. To avoid the confusion caused by manual introduction of jar package, provide common API, which is helpful for rapid development. + +- Import dependence +- Initial configuration +- Connection pool +- More method +- Support multi tracker, multi storage, multi nginx load balancing mode +- Based on fastdfs client Java (1.29 snapshot) source code construction + +Original author project address: https://github.com/bluemiaomiao/fastdfs-spring-boot-starter.git + +# I. Quick start + +## (1) Use Maven + +```xml + + io.github.bluemiaomiao + fastdfs-spring-boot-starter + 2.0.1-RELEASE + +``` + +## (2) Use Gradle + +```groovy +compile group: 'io.github.bluemiaomiao', name: 'fastdfs-spring-boot-starter', version: '2.0.0-RELEASE' +``` + +# II. Build from source + +## (1) Download + +```bash +git clone https://gitee.com/zero-awei/fastdfs-spring-boot-starter.git +cd fastdfs-spring-boot-starter +``` + +## (2) Install to local repository + +```bash +mvn clean install +mvn source:jar install +mvn javadoc:jar install +``` + +## (3) Add to project + +```xml + + io.github.bluemiaomiao + fastdfs-spring-boot-starter + 2.0.1-RELEASE + +``` + +## (4) Add annotations and service (``@EnableFastdfsClient``). + +```java +@EnableFastdfsClient +@SpringBootApplication +public class DemoApplication { + + @Autowired + private FastdfsClientService fastdfsClientService; + + public static void main(String[] args) { + SpringApplication.run(DemoApplication.class, args); + } +} +``` + +## (5) Add configuration entries(application.properties). + +```properties +fastdfs.nginx-servers=192.168.80.2:8000,192.168.80.3:8000,192.168.80.4:8000 +fastdfs.tracker-servers=192.168.80.2:22122,192.168.80.3:22122,192.168.80.4:22122 +fastdfs.http-secret-key=your key +fastdfs.http-anti-steal-token=true +fastdfs.http-tracker-http-port=8080 +fastdfs.network-timeout=30 +fastdfs.connect-timeout=5 +fastdfs.connection-pool-max-idle=18 +fastdfs.connection-pool-min-idle=2 +fastdfs.connection-pool-max-total=18 +fastdfs.charset=UTF-8 +``` + +## (6) Add configuration entries(application.yml). + +```yaml +fastdfs: + charset: UTF-8 + connect-timeout: 5 + http-secret-key: your key + network-timeout: 30 + http-anti-steal-token: true + http-tracker-http-port: 8080 + connection-pool-max-idle: 20 + connection-pool-max-total: 20 + connection-pool-min-idle: 2 + nginx-servers: 192.168.80.2:8000,192.168.80.3:8000,192.168.80.4:8000 + tracker-servers: 192.168.80.2:22122,192.168.80.3:22122,192.168.80.4:22122 +``` + +## (7) Enjoy it. + +```java +@Autowired +private FastdfsClientService remoteService; + +// Upload File +String[] remoteInfo; +try { + remoteInfo = remoteService.autoUpload(image.getBytes(), type); + log.info("File Server Group: " + remoteInfo[0]); + log.info("File Server ID: " + remoteInfo[1]); +} catch (Exception e) { + log.error("Upload file error: " + e.getMessage()); + return HttpStatus.INTERNAL_SERVER_ERROR; +} + +// Download File +String group = file.getGroup(); +String storage = file.getStorageId(); +String remoteFile = "Get file error."; + +try { + remoteFile = fastdfs.autoDownloadWithToken(group, storage, remoteAddress); +} catch (Exception e) { + log.error("Get file error: " + e.getMessage()); +} +``` + +```java +// If you use anti-hotlinking +FastdfsClientService.autoDownloadWithToken(String fileGroup, String remoteFileName, String clientIpAddress) +// If hotlinking is not used +FastdfsClientService.autoDownloadWithoutToken(String fileGroup, String remoteFileName, String clientIpAddress) +// upload file +FastdfsClientService.autoUpload(byte[] buffer, String ext) +``` diff --git a/psi-java/fastdfs-spring-boot-starter/_config.yml b/psi-java/fastdfs-spring-boot-starter/_config.yml new file mode 100644 index 000000000..c4192631f --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-cayman \ No newline at end of file diff --git a/psi-java/fastdfs-spring-boot-starter/pom.xml b/psi-java/fastdfs-spring-boot-starter/pom.xml new file mode 100644 index 000000000..dbd6b8090 --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/pom.xml @@ -0,0 +1,72 @@ + + + 4.0.0 + + com.zeroone.star + psi-java + ${revision} + ../pom.xml + + fastdfs-spring-boot-starter + + + The Apache Software License, Version 2.0 + https://www.apache.org/licenses/LICENSE-2.0.txt + + + + scm:git:https://github.com/bluemiaomiao/fastdfs-spring-boot-starter.git + scm:git:https://github.com/bluemiaomiao/fastdfs-spring-boot-starter.git + + git:https://github.com/bluemiaomiao/fastdfs-spring-boot-starter.git + + + + bluemiaomiao + xv2017@outlook.com + bluemiaomiao + + + + + org.springframework.boot + spring-boot-autoconfigure + + + org.springframework.boot + spring-boot-configuration-processor + + + org.springframework.boot + spring-boot-starter-logging + + + org.apache.commons + commons-pool2 + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + ${maven-javadoc-plugin.version} + + none + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${java.version} + ${java.version} + UTF-8 + + + + + diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/io/github/bluemiaomiao/annotation/EnableFastdfsClient.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/io/github/bluemiaomiao/annotation/EnableFastdfsClient.java new file mode 100644 index 000000000..f0578b113 --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/io/github/bluemiaomiao/annotation/EnableFastdfsClient.java @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 BlueMiaomiao + * FastDFS Java Client(for SpringBoot1.x & SpringBoot 2.x) may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + */ + +package io.github.bluemiaomiao.annotation; + +import io.github.bluemiaomiao.autoconfiguration.FastdfsAutoConfiguration; +import org.springframework.context.annotation.Import; + +import java.lang.annotation.*; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Import(FastdfsAutoConfiguration.class) +@Documented +public @interface EnableFastdfsClient { +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/io/github/bluemiaomiao/autoconfiguration/FastdfsAutoConfiguration.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/io/github/bluemiaomiao/autoconfiguration/FastdfsAutoConfiguration.java new file mode 100644 index 000000000..b1abfb2e2 --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/io/github/bluemiaomiao/autoconfiguration/FastdfsAutoConfiguration.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2019 BlueMiaomiao + * FastDFS Java Client(for SpringBoot1.x & SpringBoot 2.x) may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + */ + +package io.github.bluemiaomiao.autoconfiguration; + +import io.github.bluemiaomiao.properties.FastdfsProperties; +import io.github.bluemiaomiao.service.FastdfsClientService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableConfigurationProperties(FastdfsProperties.class) +public class FastdfsAutoConfiguration { + @Autowired + private FastdfsProperties fastdfsProperties; + + @Bean + @ConditionalOnMissingBean(FastdfsClientService.class) + public FastdfsClientService fastdfsClientService() throws Exception { + return new FastdfsClientService(fastdfsProperties); + } +} \ No newline at end of file diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/io/github/bluemiaomiao/factory/StorageClientFactory.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/io/github/bluemiaomiao/factory/StorageClientFactory.java new file mode 100644 index 000000000..c269c16ce --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/io/github/bluemiaomiao/factory/StorageClientFactory.java @@ -0,0 +1,39 @@ +package io.github.bluemiaomiao.factory; + +import org.apache.commons.pool2.PooledObject; +import org.apache.commons.pool2.PooledObjectFactory; +import org.apache.commons.pool2.impl.DefaultPooledObject; +import org.csource.fastdfs.StorageClient; +import org.csource.fastdfs.TrackerClient; +import org.csource.fastdfs.TrackerServer; + +// 用于创建连接对象的工厂类 +public class StorageClientFactory implements PooledObjectFactory { + + @Override + public PooledObject makeObject() throws Exception { + TrackerClient client = new TrackerClient(); + TrackerServer server = client.getConnection(); + return new DefaultPooledObject<>(new StorageClient(server, null)); + } + + @Override + public void destroyObject(PooledObject p) throws Exception { + p.getObject().getTrackerServer().close(); + } + + @Override + public boolean validateObject(PooledObject p) { + return false; + } + + @Override + public void activateObject(PooledObject p) throws Exception { + + } + + @Override + public void passivateObject(PooledObject p) throws Exception { + + } +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/io/github/bluemiaomiao/properties/FastdfsProperties.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/io/github/bluemiaomiao/properties/FastdfsProperties.java new file mode 100644 index 000000000..d4062d035 --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/io/github/bluemiaomiao/properties/FastdfsProperties.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2019 BlueMiaomiao + * FastDFS Java Client(for SpringBoot1.x & SpringBoot 2.x) may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + */ + +package io.github.bluemiaomiao.properties; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "fastdfs") +public class FastdfsProperties { + // 连接超时时间 + // 网络超时时间 + // 字符集编码 + // 是否使用Token + // Token加密密钥 + // 跟踪器IP地址,多个使用分号隔开 + // 连接池的连接对象最大个数 + // 连接池的最大空闲对象个数 + // 连接池的最小空闲对象个数 + // Nginx服务器IP,多个使用分号分割 + // 获取连接对象时可忍受的等待时长(毫秒) + private String connectTimeout = "5"; + private String networkTimeout = "30"; + private String charset = "UTF-8"; + private String httpAntiStealToken = "false"; + private String httpSecretKey = ""; + private String httpTrackerHttpPort = ""; + private String trackerServers = ""; + private String connectionPoolMaxTotal = "18"; + private String connectionPoolMaxIdle = "18"; + private String connectionPoolMinIdle = "2"; + private String nginxServers = ""; + + public void setConnectTimeout(String connectTimeout) { + this.connectTimeout = connectTimeout; + } + + public void setNetworkTimeout(String networkTimeout) { + this.networkTimeout = networkTimeout; + } + + public void setCharset(String charset) { + this.charset = charset; + } + + public void setHttpAntiStealToken(String httpAntiStealToken) { + this.httpAntiStealToken = httpAntiStealToken; + } + + public void setHttpSecretKey(String httpSecretKey) { + this.httpSecretKey = httpSecretKey; + } + + public void setHttpTrackerHttpPort(String httpTrackerHttpPort) { + this.httpTrackerHttpPort = httpTrackerHttpPort; + } + + public void setTrackerServers(String trackerServers) { + this.trackerServers = trackerServers; + } + + public void setConnectionPoolMaxTotal(String connectionPoolMaxTotal) { + this.connectionPoolMaxTotal = connectionPoolMaxTotal; + } + + public void setConnectionPoolMaxIdle(String connectionPoolMaxIdle) { + this.connectionPoolMaxIdle = connectionPoolMaxIdle; + } + + public void setConnectionPoolMinIdle(String connectionPoolMinIdle) { + this.connectionPoolMinIdle = connectionPoolMinIdle; + } + + public void setNginxServers(String nginxServers) { + this.nginxServers = nginxServers; + } + + public String getConnectTimeout() { + return connectTimeout; + } + + public String getNetworkTimeout() { + return networkTimeout; + } + + public String getCharset() { + return charset; + } + + public String getHttpAntiStealToken() { + return httpAntiStealToken; + } + + public String getHttpSecretKey() { + return httpSecretKey; + } + + public String getHttpTrackerHttpPort() { + return httpTrackerHttpPort; + } + + public String getTrackerServers() { + return trackerServers; + } + + public String getConnectionPoolMaxTotal() { + return connectionPoolMaxTotal; + } + + public String getConnectionPoolMaxIdle() { + return connectionPoolMaxIdle; + } + + public String getConnectionPoolMinIdle() { + return connectionPoolMinIdle; + } + + public String getNginxServers() { + return nginxServers; + } +} \ No newline at end of file diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/io/github/bluemiaomiao/service/FastdfsClientService.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/io/github/bluemiaomiao/service/FastdfsClientService.java new file mode 100644 index 000000000..cdcd6bfde --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/io/github/bluemiaomiao/service/FastdfsClientService.java @@ -0,0 +1,1389 @@ +/* + * Copyright (C) 2019 BlueMiaomiao + * General Public License (LGPL) + * 为SpringBoot 1.x 和 SpringBoot2.x构建的fastDFS场景启动器 + * 进一步分封装fastDFS中的方法,实现带有Token的方法 + * 加入Nginx负载均衡策略 + * 可以直接调用方法,直接返回文件请求地址 + */ + +package io.github.bluemiaomiao.service; + +import io.github.bluemiaomiao.factory.StorageClientFactory; +import io.github.bluemiaomiao.properties.FastdfsProperties; +import org.apache.commons.pool2.impl.GenericObjectPool; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.csource.common.NameValuePair; +import org.csource.fastdfs.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.Properties; + +import static java.lang.Math.abs; + +public class FastdfsClientService { + + // SpringBoot加载的配置文件 + // 连接池配置项 + // 转换后的配置条目 + // 连接池 + // Nginx服务器地址 + private FastdfsProperties fdfsProp; + private GenericObjectPoolConfig config; + private Properties prop; + private GenericObjectPool pool; + private String[] nginxServers; + private Logger logger; + + public FastdfsClientService(FastdfsProperties fdfsProp) throws Exception { + this.fdfsProp = fdfsProp; + this.logger = LoggerFactory.getLogger(getClass()); + init(); + create(); + info(); + } + + /** + * 初始化全局客户端 + */ + private void init() throws Exception { + this.prop = new Properties(); + this.logger.info("FastDFS: reading config file..."); + this.logger.info("FastDFS: fastdfs.connect_timeout_in_seconds=" + this.fdfsProp.getConnectTimeout()); + this.logger.info("FastDFS: fastdfs.network_timeout_in_seconds=" + this.fdfsProp.getNetworkTimeout()); + this.logger.info("FastDFS: fastdfs.charset=" + this.fdfsProp.getCharset()); + this.logger.info("FastDFS: fastdfs.http_anti_steal_token=" + this.fdfsProp.getHttpAntiStealToken()); + this.logger.info("FastDFS: fastdfs.http_secret_key=" + this.fdfsProp.getHttpSecretKey()); + this.logger.info("FastDFS: fastdfs.http_tracker_http_port=" + this.fdfsProp.getHttpTrackerHttpPort()); + this.logger.info("FastDFS: fastdfs.tracker_servers=" + this.fdfsProp.getTrackerServers()); + this.logger.info("FastDFS: fastdfs.connection_pool_max_total=" + this.fdfsProp.getConnectionPoolMaxTotal()); + this.logger.info("FastDFS: fastdfs.connection_pool_max_idle=" + this.fdfsProp.getConnectionPoolMaxIdle()); + this.logger.info("FastDFS: fastdfs.connection_pool_min_idle=" + this.fdfsProp.getConnectionPoolMinIdle()); + this.logger.info("FastDFS: fastdfs.nginx_servers=" + this.fdfsProp.getNginxServers()); + + this.prop.put("fastdfs.connect_timeout_in_seconds", this.fdfsProp.getConnectTimeout()); + this.prop.put("fastdfs.network_timeout_in_seconds", this.fdfsProp.getNetworkTimeout()); + this.prop.put("fastdfs.charset", this.fdfsProp.getCharset()); + this.prop.put("fastdfs.http_anti_steal_token", this.fdfsProp.getHttpAntiStealToken()); + this.prop.put("fastdfs.http_secret_key", this.fdfsProp.getHttpSecretKey()); + this.prop.put("fastdfs.http_tracker_http_port", this.fdfsProp.getHttpTrackerHttpPort()); + this.prop.put("fastdfs.tracker_servers", this.fdfsProp.getTrackerServers()); + ClientGlobal.initByProperties(this.prop); + } + + /** + * 显示初始化信息 + */ + private void info() { + this.logger.info("FastDFS parameter: ConnectionPoolMaxTotal ==> " + this.pool.getMaxTotal()); + this.logger.info("FastDFS parameter: ConnectionPoolMaxIdle ==> " + this.pool.getMaxIdle()); + this.logger.info("FastDFS parameter: ConnectionPoolMinIdle ==> " + this.pool.getMinIdle()); + this.logger.info("FastDFS parameter: NginxServer ==> " + Arrays.toString(this.nginxServers)); + this.logger.info(ClientGlobal.configInfo()); + } + + /** + * 创建连接池 + */ + private void create() { + this.config = new GenericObjectPoolConfig(); + this.logger.info("FastDFS Client: Creating connection pool..."); + this.config.setMaxTotal(Integer.parseInt(this.fdfsProp.getConnectionPoolMaxTotal())); + this.config.setMaxIdle(Integer.parseInt(this.fdfsProp.getConnectionPoolMaxIdle())); + this.config.setMinIdle(Integer.parseInt(this.fdfsProp.getConnectionPoolMinIdle())); + StorageClientFactory factory = new StorageClientFactory(); + this.pool = new GenericObjectPool(factory, this.config); + this.nginxServers = this.fdfsProp.getNginxServers().split(","); + } + + /** + * Nginx服务器负载均衡算法 + * + * @param servers 服务器地址 + * @param address 客户端IP地址 + * @return 可用的服务器地址 + */ + private String getNginxServer(String[] servers, String address) { + int size = servers.length; + int i = address.hashCode(); + int index = abs(i % size); + return servers[index]; + } + + /** + * 带有防盗链的下载 + * + * @param fileGroup 文件组名 + * @param remoteFileName 远程文件名称 + * @param clientIpAddress 客户端IP地址 + * @return 完整的URL地址 + */ + public String autoDownloadWithToken(String fileGroup, String remoteFileName, String clientIpAddress) throws Exception { + int ts = (int) (System.currentTimeMillis() / 1000); + String token = ProtoCommon.getToken(remoteFileName, ts, ClientGlobal.getG_secret_key()); + String nginx = this.getNginxServer(this.nginxServers, clientIpAddress); + return "http://" + nginx + "/" + fileGroup + "/" + remoteFileName + "?token=" + token + "&ts=" + ts; + } + + /** + * 上传文件,适合上传图片 + * + * @param buffer 字节数组 + * @param ext 扩展名 + * @return 文件组名和ID + */ + public String[] autoUpload(byte[] buffer, String ext) throws Exception { + String[] upload = this.upload(buffer, ext, null); + return upload; + } + + /** + * 不带防盗链的下载,如果开启防盗链会导致该方法抛出异常 + * + * @param fileGroup 文件组名 + * @param remoteFileName 远程文件ID + * @param clientIpAddress 客户端IP地址,根据客户端IP来分配Nginx服务器 + * @return 完整的URL地址 + */ + public String autoDownloadWithoutToken(String fileGroup, String remoteFileName, String clientIpAddress) throws Exception { + if (ClientGlobal.getG_anti_steal_token()) { + this.logger.error("FastDFS Client: You've turned on Token authentication."); + throw new Exception("You've turned on Token authentication."); + } + String nginx = this.getNginxServer(this.nginxServers, clientIpAddress); + return "http://" + nginx + "/" +fileGroup + "/" + remoteFileName; + } + + + /** + * 通过本地文件上传 + * + * @param localFileName 本地文件名称 + * @param fileExtName 文件扩展名 + * @param metadata 文件的元数据 + * @return 文件组名和ID + */ + public String[] upload(String localFileName, String fileExtName, NameValuePair[] metadata) throws Exception { + StorageClient client = this.pool.borrowObject(); + final String[] strings = client.upload_file(localFileName, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过本地文件上传 + * + * @param localFileName 本地文件名称 + * @param fileExtName 文件扩展名 + * @param metadata 文件的元数据 + * @param waitTimeMillis 获取连接等待时间 + * @return 文件组名和ID + */ + public String[] upload(String localFileName, String fileExtName, NameValuePair[] metadata, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + final String[] strings = client.upload_file(localFileName, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过字节数组上传文件 + * + * @param buff 文件的字节数组 + * @param offset 偏移量 + * @param len 长度 + * @param fileExtName 文件扩展名 + * @param metadata 文件的元数据 + * @return 文件组名和ID + */ + public String[] upload(byte[] buff, int offset, int len, String fileExtName, NameValuePair[] metadata) throws Exception { + StorageClient client = this.pool.borrowObject(); + String[] strings = client.upload_file(buff, offset, len, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过字节数组上传文件 + * + * @param buff 文件的字节数组 + * @param offset 偏移量 + * @param len 长度 + * @param fileExtName 文件扩展名 + * @param metadata 文件的元数据 + * @param waitTimeMillis 获取连接的等待时间 + * @return 文件组名和ID + */ + public String[] upload(byte[] buff, int offset, int len, String fileExtName, NameValuePair[] metadata, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + String[] strings = client.upload_file(buff, offset, len, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过字节数组上传 + * + * @param groupName 文件的组名 + * @param buff 文件的字节数组 + * @param offset 偏移量 + * @param len 长度 + * @param fileExtName 文件扩展名 + * @param metadata 文件的元数据 + * @return 文件组名和ID + */ + public String[] upload(String groupName, byte[] buff, int offset, int len, String fileExtName, NameValuePair[] metadata) throws Exception { + StorageClient client = this.pool.borrowObject(); + String[] strings = client.upload_file(groupName, buff, offset, len, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过字节数组上传文件 + * + * @param groupName 文件的组名 + * @param buff 文件的字节数组 + * @param offset 偏移量 + * @param len 长度 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @param waitTimeMillis 获取连接的等待时间 + * @return 文件组名和ID + */ + public String[] upload(String groupName, byte[] buff, int offset, int len, String fileExtName, NameValuePair[] metadata, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + String[] strings = client.upload_file(groupName, buff, offset, len, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过字节数组上传 + * + * @param fileBuff 文件的字节数组 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @return 文件组名和ID + */ + public String[] upload(byte[] fileBuff, String fileExtName, NameValuePair[] metadata) throws Exception { + StorageClient client = this.pool.borrowObject(); + String[] strings = client.upload_file(fileBuff, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过字节数组上传文件 + * + * @param fileBuff 文件的字节数组 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @param waitTimeMillis 获取连接的等待时间 + * @return 文件组名和ID + */ + public String[] upload(byte[] fileBuff, String fileExtName, NameValuePair[] metadata, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + String[] strings = client.upload_file(fileBuff, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过字节数组上传文件 + * + * @param groupName 文件组名 + * @param fileBuff 文件的字节数组 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @return 文件的组名和ID + */ + public String[] upload(String groupName, byte[] fileBuff, String fileExtName, NameValuePair[] metadata) throws Exception { + StorageClient client = this.pool.borrowObject(); + String[] strings = client.upload_file(groupName, fileBuff, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过字节数组上传文件 + * + * @param groupName 文件组名 + * @param fileBuff 文件的字节数组 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @param waitTimeMillis 等待连接的时长 + * @return 文件组名和ID + */ + public String[] upload(String groupName, byte[] fileBuff, String fileExtName, NameValuePair[] metadata, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + String[] strings = client.upload_file(groupName, fileBuff, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过回调接口上传文件 + * + * @param groupName 文件组名 + * @param fileSize 文件大小 + * @param callback 回调函数 + * @param fileExtName 文件扩展名 + * @param metadata 元数据 + * @return 文件组名和ID + */ + public String[] upload(String groupName, long fileSize, UploadCallback callback, String fileExtName, NameValuePair[] metadata) throws Exception { + StorageClient client = this.pool.borrowObject(); + String[] strings = client.upload_file(groupName, fileSize, callback, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过回调接口上传文件 + * + * @param groupName 文件组名 + * @param fileSize 文件大小 + * @param callback 回调接口 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @param waitTimeMillis 等待连接的时长 + * @return 文件组名和ID + */ + public String[] upload(String groupName, long fileSize, UploadCallback callback, String fileExtName, NameValuePair[] metadata, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + String[] strings = client.upload_file(groupName, fileSize, callback, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过本地上传文件 + * + * @param groupName 文件组名 + * @param masterFileName 生成副本的文件名 + * @param prefixName 生成副本的文件名前缀 + * @param localFileName 本地文件名称 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @return 文件组名和ID + */ + public String[] upload(String groupName, String masterFileName, String prefixName, String localFileName, String fileExtName, NameValuePair[] metadata) throws Exception { + StorageClient client = this.pool.borrowObject(); + String[] strings = client.upload_file(groupName, masterFileName, prefixName, localFileName, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过本地上传文件 + * + * @param groupName 文件组名 + * @param masterFileName 生成副本的文件名 + * @param prefixName 生成副本的文件名前缀 + * @param localFileName 本地文件名称 + * @param fileExtName 文件扩展名 + * @param metadata 元数据 + * @param waitTimeMillis 等待连接的时长 + * @return 文件组名和ID + */ + public String[] upload(String groupName, String masterFileName, String prefixName, String localFileName, String fileExtName, NameValuePair[] metadata, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + String[] strings = client.upload_file(groupName, masterFileName, prefixName, localFileName, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过字节数组上传 + * + * @param groupName 文件组名 + * @param masterFileName 生成副本的文件名 + * @param prefixName 生成副本的文件名前缀 + * @param buff 文件的字节数组 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @return 文件组名和ID + */ + public String[] upload(String groupName, String masterFileName, String prefixName, byte[] buff, String fileExtName, NameValuePair[] metadata) throws Exception { + StorageClient client = this.pool.borrowObject(); + String[] strings = client.upload_file(groupName, masterFileName, prefixName, buff, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过字节数组上传 + * + * @param groupName 组名 + * @param masterFileName 生成副本的文件名 + * @param prefixName 生成副本的文件名前缀 + * @param buff 文件的字节数组 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @param waitTimeMillis 等待连接的时长 + * @return 文件组名和ID + */ + public String[] upload(String groupName, String masterFileName, String prefixName, byte[] buff, String fileExtName, NameValuePair[] metadata, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + String[] strings = client.upload_file(groupName, masterFileName, prefixName, buff, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过字节数组上传文件 + * + * @param groupName 组名 + * @param masterFileName 生成副本的文件名 + * @param prefixName 生成副本的文件名前缀 + * @param buff 文件的字节数组 + * @param offset 偏移量 + * @param len 长度 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @return 文件组名和ID + */ + public String[] upload(String groupName, String masterFileName, String prefixName, byte[] buff, int offset, int len, String fileExtName, NameValuePair[] metadata) throws Exception { + StorageClient client = this.pool.borrowObject(); + String[] strings = client.upload_file(groupName, masterFileName, prefixName, buff, offset, len, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过字节数组上传文件 + * + * @param groupName 组名 + * @param masterFileName 生成副本的文件名 + * @param prefixName 生成副本的文件名前缀 + * @param buff 文件的字节数组 + * @param offset 偏移量 + * @param len 长度 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @param waitTimeMillis 等待连接的时长 + * @return 文件组名和ID + */ + public String[] upload(String groupName, String masterFileName, String prefixName, byte[] buff, int offset, int len, String fileExtName, NameValuePair[] metadata, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + String[] strings = client.upload_file(groupName, masterFileName, prefixName, buff, offset, len, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过回调函数上传文件 + * + * @param groupName 组名 + * @param masterFileName 生成副本的文件名 + * @param prefixName 生成副本的文件名前缀 + * @param fileSize 文件的大小 + * @param callback 回调接口 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @return 文件组名和ID + */ + public String[] upload(String groupName, String masterFileName, String prefixName, long fileSize, UploadCallback callback, String fileExtName, NameValuePair[] metadata) throws Exception { + StorageClient client = this.pool.borrowObject(); + String[] strings = client.upload_file(groupName, masterFileName, prefixName, fileSize, callback, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过回调函数上传文件 + * + * @param groupName 组名 + * @param masterFileName 生成副本的文件名 + * @param prefixName 生成副本的文件名前缀 + * @param fileSize 文件的大小 + * @param callback 回调接口 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @param waitTimeMillis 等待连接的时长 + * @return 文件组名和ID + */ + public String[] upload(String groupName, String masterFileName, String prefixName, long fileSize, UploadCallback callback, String fileExtName, NameValuePair[] metadata, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + String[] strings = client.upload_file(groupName, masterFileName, prefixName, fileSize, callback, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 将本地附加文件上传 + * + * @param localFileName 本地文件名称 + * @param fileExtName 文件扩展名 + * @param metadata 元数据 + * @return 文件组名和ID + */ + public String[] uploadAppenderFile(String localFileName, String fileExtName, NameValuePair[] metadata) throws Exception { + StorageClient client = this.pool.borrowObject(); + String[] strings = client.upload_appender_file(localFileName, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 将附加文件上传 + * + * @param localFileName 文件名称 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @param waitTimeMillis 获取连接等待时长 + * @return 文件组名和ID + */ + public String[] uploadAppenderFile(String localFileName, String fileExtName, NameValuePair[] metadata, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + String[] strings = client.upload_appender_file(localFileName, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过字节数组上传附加文件 + * + * @param buff 字节数组 + * @param offset 偏移量 + * @param len 长度 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @return 文件组名和ID + */ + public String[] uploadAppenderFile(byte[] buff, int offset, int len, String fileExtName, NameValuePair[] metadata) throws Exception { + StorageClient client = this.pool.borrowObject(); + String[] strings = client.upload_appender_file(buff, offset, len, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过字节数组上传附加文件 + * + * @param buff 字节数组 + * @param offset 偏移量 + * @param len 长度 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @param waitTimeMillis 等待获取连接的时长 + * @return 文件组名和ID + */ + public String[] uploadAppenderFile(byte[] buff, int offset, int len, String fileExtName, NameValuePair[] metadata, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + String[] strings = client.upload_appender_file(buff, offset, len, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过字节数组上传附加文件 + * + * @param groupName 组名 + * @param buff 字节数组 + * @param offset 偏移量 + * @param len 长度 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @return 文件组名和ID + */ + public String[] uploadAppenderFile(String groupName, byte[] buff, int offset, int len, String fileExtName, NameValuePair[] metadata) throws Exception { + StorageClient client = this.pool.borrowObject(); + String[] strings = client.upload_appender_file(groupName, buff, offset, len, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过字节数组上传附加文件 + * + * @param groupName 组名 + * @param buff 字节数组 + * @param offset 偏移量 + * @param len 长度 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @param waitTimeMillis 获取连接的等待时长 + * @return 文件组名和ID + */ + public String[] uploadAppenderFile(String groupName, byte[] buff, int offset, int len, String fileExtName, NameValuePair[] metadata, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + String[] strings = client.upload_appender_file(groupName, buff, offset, len, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过字节数组上传附加文件 + * + * @param buff 字节数组 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @return 文件组名和ID + */ + public String[] uploadAppenderFile(byte[] buff, String fileExtName, NameValuePair[] metadata) throws Exception { + StorageClient client = this.pool.borrowObject(); + String[] strings = client.upload_appender_file(buff, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过字节数组上传附加文件 + * + * @param buff 字节数组 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @param waitTimeMillis 等待获取连接的时长 + * @return 文件组名和ID + */ + public String[] uploadAppenderFile(byte[] buff, String fileExtName, NameValuePair[] metadata, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + String[] strings = client.upload_appender_file(buff, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过字节数组上传 + * + * @param groupName 组名 + * @param buff 字节数组 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @return 文件组名和ID + */ + public String[] uploadAppenderFile(String groupName, byte[] buff, String fileExtName, NameValuePair[] metadata) throws Exception { + StorageClient client = this.pool.borrowObject(); + String[] strings = client.upload_appender_file(groupName, buff, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过字节数组上传附加文件 + * + * @param groupName 组名 + * @param buff 字节数组 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @param waitTimeMillis 获取连接的等待时长 + * @return 文件组名和ID + */ + public String[] uploadAppenderFile(String groupName, byte[] buff, String fileExtName, NameValuePair[] metadata, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + String[] strings = client.upload_appender_file(groupName, buff, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过回调上传附加文件 + * + * @param groupName 组名 + * @param fileSize 文件大小 + * @param callback 回调函数 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @return 文件组名和ID + */ + public String[] uploadAppenderFile(String groupName, long fileSize, UploadCallback callback, String fileExtName, NameValuePair[] metadata) throws Exception { + StorageClient client = this.pool.borrowObject(); + String[] strings = client.upload_appender_file(groupName, fileSize, callback, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 通过回调上传附加文件 + * + * @param groupName 组名 + * @param fileSize 文件大小 + * @param callback 回调函数 + * @param fileExtName 扩展名 + * @param metadata 元数据 + * @param waitTimeMillis 等待时间 + * @return 文件组名和ID + */ + public String[] uploadAppenderFile(String groupName, long fileSize, UploadCallback callback, String fileExtName, NameValuePair[] metadata, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + String[] strings = client.upload_appender_file(groupName, fileSize, callback, fileExtName, metadata); + this.pool.returnObject(client); + return strings; + } + + /** + * 追加文件 + * + * @param groupName 组名 + * @param appenderFileName 追加文件名称 + * @param localFileName 本地文件名称 + * @return 返回0表示成功 + */ + public int appendFile(String groupName, String appenderFileName, String localFileName) throws Exception { + StorageClient client = this.pool.borrowObject(); + int i = client.append_file(groupName, appenderFileName, localFileName); + this.pool.returnObject(client); + return i; + } + + /** + * 追加文件 + * + * @param groupName 组名 + * @param appenderFileName 追加文件名称 + * @param localFileName 本地文件名称 + * @param waitTimeMillis 等待时间时长 + * @return 返回0表示成功 + */ + public int appendFile(String groupName, String appenderFileName, String localFileName, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + int i = client.append_file(groupName, appenderFileName, localFileName); + this.pool.returnObject(client); + return i; + } + + /** + * 追加文件 + * + * @param groupName 组名 + * @param appenderFileName 追加文件名称 + * @param buff 文件字节数组 + * @return 返回0表示成功 + */ + public int appendFile(String groupName, String appenderFileName, byte[] buff) throws Exception { + StorageClient client = this.pool.borrowObject(); + int i = client.append_file(groupName, appenderFileName, buff); + this.pool.returnObject(client); + return i; + } + + /** + * 追加文件 + * + * @param groupName 组名 + * @param appenderFileName 追加文件名称 + * @param buff 文件字节数组 + * @param waitTimeMillis 等待时长 + * @return 返回0表示成功 + */ + public int appendFile(String groupName, String appenderFileName, byte[] buff, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + int i = client.append_file(groupName, appenderFileName, buff); + this.pool.returnObject(client); + return i; + } + + /** + * 追加文件 + * + * @param groupName 组名 + * @param appenderFileName 追加文件名称 + * @param buff 字节数组 + * @param offset 偏移量 + * @param len 长度 + * @return 返回0表示成功 + */ + public int appendFile(String groupName, String appenderFileName, byte[] buff, int offset, int len) throws Exception { + StorageClient client = this.pool.borrowObject(); + int i = client.append_file(groupName, appenderFileName, buff, offset, len); + this.pool.returnObject(client); + return i; + } + + /** + * 追加文件 + * + * @param groupName 组名 + * @param appenderFileName 追加文件名称 + * @param buff 字节数组 + * @param offset 偏移量 + * @param len 长度 + * @param waitTimeMillis 等待时长 + * @return 文件组名和ID + */ + public int appendFile(String groupName, String appenderFileName, byte[] buff, int offset, int len, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + int i = client.append_file(groupName, appenderFileName, buff, offset, len); + this.pool.returnObject(client); + return i; + } + + + /** + * 追加文件 + * + * @param groupName 组名 + * @param appenderFileName 追加文件名称 + * @param fileSize 文件大小 + * @param callback 回调函数 + * @return 返回0表示成功 + */ + public int appendFile(String groupName, String appenderFileName, long fileSize, UploadCallback callback) throws Exception { + StorageClient client = this.pool.borrowObject(); + int i = client.append_file(groupName, appenderFileName, fileSize, callback); + this.pool.returnObject(client); + return i; + } + + /** + * 上传文件 + * + * @param groupName 组名 + * @param appenderFileName 追加文件名称 + * @param fileSize 文件大小 + * @param callback 回调函数 + * @param waitTimeMillis 等待时间 + * @return 返回0表示成功 + */ + public int appendFile(String groupName, String appenderFileName, long fileSize, UploadCallback callback, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + int i = client.append_file(groupName, appenderFileName, fileSize, callback); + this.pool.returnObject(client); + return i; + } + + /** + * 修改文件 + * + * @param groupName 组名 + * @param appenderFileName 追加文件名称 + * @param fileOffset 偏移量 + * @param localFileName 本地文件名称 + * @return 返回0表示成功 + */ + public int modify(String groupName, String appenderFileName, long fileOffset, String localFileName) throws Exception { + StorageClient client = this.pool.borrowObject(); + int i = client.modify_file(groupName, appenderFileName, fileOffset, localFileName); + this.pool.returnObject(client); + return i; + } + + /** + * 修改文件 + * + * @param groupName 组名 + * @param appenderFileName 追加文件名称 + * @param fileOffset 偏移量 + * @param localFileName 本地文件名称 + * @param waitTimeMillis 等待时长 + * @return 返回0表示成功 + */ + public int modify(String groupName, String appenderFileName, long fileOffset, String localFileName, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + int i = client.modify_file(groupName, appenderFileName, fileOffset, localFileName); + this.pool.returnObject(client); + return i; + } + + /** + * 修改文件 + * + * @param groupName 组名 + * @param appenderFileName 追加文件名称 + * @param fileOffset 偏移量 + * @param buff 字节数组 + * @return 返回0表示成功 + */ + public int modify(String groupName, String appenderFileName, long fileOffset, byte[] buff) throws Exception { + StorageClient client = this.pool.borrowObject(); + int i = client.modify_file(groupName, appenderFileName, fileOffset, buff); + this.pool.returnObject(client); + return i; + } + + /** + * 修改文件 + * + * @param groupName 组名 + * @param appenderFileName 追加文件名称 + * @param fileOffset 偏移量 + * @param buff 字节数组 + * @param waitTimeMillis 等待时间 + * @return 返回0表示成功 + */ + public int modify(String groupName, String appenderFileName, long fileOffset, byte[] buff, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + int i = client.modify_file(groupName, appenderFileName, fileOffset, buff); + this.pool.returnObject(client); + return i; + } + + /** + * 修改文件 + * + * @param groupName 组名 + * @param appenderFileName 追加文件名称 + * @param fileOffset 偏移量 + * @param buff 字节数组 + * @param bufferOffset 偏移量 + * @param bufferLen 长度 + * @return 返回0表示成功 + */ + public int modify(String groupName, String appenderFileName, long fileOffset, byte[] buff, int bufferOffset, int bufferLen) throws Exception { + StorageClient client = this.pool.borrowObject(); + int i = client.modify_file(groupName, appenderFileName, fileOffset, buff, bufferOffset, bufferLen); + this.pool.returnObject(client); + return i; + } + + /** + * 修改文件 + * + * @param groupName 组名 + * @param appenderFileName 追加文件名称 + * @param fileOffset 文件偏移量 + * @param buff 字节数组 + * @param bufferOffset 字节偏移量 + * @param bufferLen 字节长度 + * @param waitTimeMillis 等待时间 + * @return 返回0表示成功 + */ + public int modify(String groupName, String appenderFileName, long fileOffset, byte[] buff, int bufferOffset, int bufferLen, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + int i = client.modify_file(groupName, appenderFileName, fileOffset, buff, bufferOffset, bufferLen); + this.pool.returnObject(client); + return i; + } + + /** + * 修改文件 + * + * @param groupName 组名 + * @param appenderFileName 追加文件名称 + * @param fileOffset 偏移量 + * @param modifySize 修改大小 + * @param callback 回调函数 + * @return 文件组名和ID + */ + public int modify(String groupName, String appenderFileName, long fileOffset, long modifySize, UploadCallback callback) throws Exception { + StorageClient client = this.pool.borrowObject(); + int i = client.modify_file(groupName, appenderFileName, fileOffset, modifySize, callback); + this.pool.returnObject(client); + return i; + } + + /** + * 修改文件 + * + * @param groupName 组名 + * @param appenderFileName 追加文件名称 + * @param fileOffset 偏移量 + * @param modifySize 修改大小 + * @param callback 回调函数 + * @param waitTimeMillis 等待时间 + * @return 文件组名和ID + */ + public int modify(String groupName, String appenderFileName, long fileOffset, long modifySize, UploadCallback callback, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + int i = client.modify_file(groupName, appenderFileName, fileOffset, modifySize, callback); + this.pool.returnObject(client); + return i; + } + + /** + * 删除文件 + * + * @param groupName 组名 + * @param remoteFileName 远程文件名称 + * @return 返回0表示成功 + */ + public int delete(String groupName, String remoteFileName) throws Exception { + StorageClient client = this.pool.borrowObject(); + int i = client.delete_file(groupName, remoteFileName); + this.pool.returnObject(client); + return i; + } + + /** + * 删除文件 + * + * @param groupName 组名 + * @param remoteFileName 远程文件名称 + * @param waitTimeMillis 等待时间 + * @return 返回0表示成功 + */ + public int delete(String groupName, String remoteFileName, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + int i = client.delete_file(groupName, remoteFileName); + this.pool.returnObject(client); + return i; + } + + /** + * 文件分片 + * + * @param groupName 组名 + * @param appenderName 输出源文件名称 + * @return 返回0表示成功 + */ + public int truncate(String groupName, String appenderName) throws Exception { + StorageClient client = this.pool.borrowObject(); + int i = client.truncate_file(groupName, appenderName); + this.pool.returnObject(client); + return i; + } + + /** + * 文件分片 + * + * @param groupName 组名 + * @param appenderName 输出源文件名称 + * @param waitTimeMillis 等待时间 + * @return 返回0表示成功 + */ + public int truncate(String groupName, String appenderName, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + client.truncate_file(groupName, appenderName); + this.pool.returnObject(client); + return 0; + } + + /** + * 文件分片 + * + * @param truncatedFileSize 分片大小 + * @param groupName 组名 + * @param appenderName 输出源文件名称 + * @return 返回0表示成功 + */ + public int truncate(long truncatedFileSize, String groupName, String appenderName) throws Exception { + StorageClient client = this.pool.borrowObject(); + int i = client.truncate_file(groupName, appenderName, truncatedFileSize); + this.pool.returnObject(client); + return i; + } + + /** + * 文件分片 + * + * @param truncatedFileSize 分片大小 + * @param groupName 组名 + * @param appenderName 输出源文件 + * @param waitTimeMillis 等待时间 + * @return 返回0表示成功 + */ + public int truncate(long truncatedFileSize, String groupName, String appenderName, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + int i = client.truncate_file(groupName, appenderName, truncatedFileSize); + this.pool.returnObject(client); + return i; + } + + /** + * 下载文件 + * + * @param groupName 组名 + * @param remoteFileName 远程文件名称 + * @return 返回0表示成功 + */ + public byte[] download(String groupName, String remoteFileName) throws Exception { + StorageClient client = this.pool.borrowObject(); + byte[] bytes = client.download_file(groupName, remoteFileName); + this.pool.returnObject(client); + return bytes; + } + + /** + * 下载文件 + * + * @param groupName 组名 + * @param remoteFileName 远程文件名称 + * @param waitTimeMillis 等待时间 + * @return 返回0表示成功 + */ + public byte[] download(String groupName, String remoteFileName, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + byte[] bytes = client.download_file(groupName, remoteFileName); + this.pool.returnObject(client); + return bytes; + } + + /** + * 下载文件 + * + * @param groupName 组名 + * @param remoteFileName 远程文件名称 + * @param offset 偏移量 + * @param bytes 字节数组 + * @return 返回0表示成功 + */ + public byte[] download(String groupName, String remoteFileName, long offset, long bytes) throws Exception { + StorageClient client = this.pool.borrowObject(); + byte[] bytes1 = client.download_file(groupName, remoteFileName, offset, bytes); + this.pool.returnObject(client); + return bytes1; + } + + /** + * 下载文件 + * + * @param groupName 组名 + * @param remoteFileName 远程文件名称 + * @param offset 偏移量 + * @param bytes 字节数组 + * @param waitTimeMillis 等待时长 + * @return 返回0表示成功 + */ + public byte[] download(String groupName, String remoteFileName, long offset, long bytes, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + byte[] bytes1 = client.download_file(groupName, remoteFileName, offset, bytes); + this.pool.returnObject(client); + return bytes1; + } + + /** + * 下载文件 + * + * @param groupName 组名 + * @param remoteFileName 远程文件名称 + * @param localFileName 本地文件名称 + * @return 返回0表示成功 + */ + public int download(String groupName, String remoteFileName, String localFileName) throws Exception { + StorageClient client = this.pool.borrowObject(); + int i = client.download_file(groupName, remoteFileName, localFileName); + this.pool.returnObject(client); + return i; + } + + /** + * 下载文件 + * + * @param groupName 组名 + * @param remoteFileName 远程文件名称 + * @param localFileName 本地文件名称 + * @param waitTimeMillis 等待时间 + * @return 返回0表示成功 + */ + public int download(String groupName, String remoteFileName, String localFileName, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + int i = client.download_file(groupName, remoteFileName, localFileName); + this.pool.returnObject(client); + return i; + } + + /** + * 下载文件 + * + * @param groupName 组名 + * @param remoteFileName 远程文件名称 + * @param offset 偏移量 + * @param bytes 字节数组 + * @param localFileName 本地文件名称 + * @return 返回0表示成功 + */ + public int download(String groupName, String remoteFileName, long offset, long bytes, String localFileName) throws Exception { + StorageClient client = this.pool.borrowObject(); + int i = client.download_file(groupName, remoteFileName, offset, bytes, localFileName); + this.pool.returnObject(client); + return i; + } + + /** + * 下载文件 + * + * @param groupName 组名 + * @param remoteFileName 远程文件名称 + * @param offset 偏移量 + * @param bytes 字节数组 + * @param localFileName 本地文件名称 + * @param waitTimeMillis 等待时间 + * @return 返回0表示成功 + */ + public int download(String groupName, String remoteFileName, long offset, long bytes, String localFileName, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + int i = client.download_file(groupName, remoteFileName, offset, bytes, localFileName); + this.pool.returnObject(client); + return i; + } + + /** + * 下载文件 + * + * @param groupName 组名 + * @param remoteFileName 远程文件名称 + * @param callback 回调函数 + * @return 文件分组和ID + */ + public int download(String groupName, String remoteFileName, DownloadCallback callback) throws Exception { + StorageClient client = this.pool.borrowObject(); + int i = client.download_file(groupName, remoteFileName, callback); + this.pool.returnObject(client); + return i; + } + + /** + * 下载文件 + * + * @param groupName 组名 + * @param remoteFileName 远程文件名称 + * @param callback 回调函数 + * @param waitTimeMillis 等待时间 + * @return 返回0表示成功 + */ + public int download(String groupName, String remoteFileName, DownloadCallback callback, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + int i = client.download_file(groupName, remoteFileName, callback); + this.pool.returnObject(client); + return i; + } + + /** + * 下载文件 + * + * @param groupName 组名 + * @param remoteFileName 远程文件名称 + * @param offset 偏移量 + * @param bytes 字节数组 + * @param callback 回调函数 + * @return 返回0表示成功 + */ + public int download(String groupName, String remoteFileName, long offset, long bytes, DownloadCallback callback) throws Exception { + StorageClient client = this.pool.borrowObject(); + int i = client.download_file(groupName, remoteFileName, offset, bytes, callback); + this.pool.returnObject(client); + return i; + } + + /** + * 下载文件 + * + * @param groupName 组名 + * @param remoteFileName 远程文件名称 + * @param offset 偏移量 + * @param bytes 字节数组 + * @param callback 回调函数 + * @param waitTimeMillis 等待时间 + * @return 返回0表示成功 + */ + public int download(String groupName, String remoteFileName, long offset, long bytes, DownloadCallback callback, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + int i = client.download_file(groupName, remoteFileName, offset, bytes, callback); + this.pool.returnObject(client); + return i; + } + + /** + * 获取元数据 + * + * @param groupName 组名 + * @param remoteFileName 远程文件名称 + * @return 键值对数组 + */ + public NameValuePair[] getMetadata(String groupName, String remoteFileName) throws Exception { + StorageClient client = this.pool.borrowObject(); + NameValuePair[] metadata = client.get_metadata(groupName, remoteFileName); + this.pool.returnObject(client); + return metadata; + } + + /** + * 获取元数据 + * + * @param groupName 组名 + * @param remoteFileName 远程文件名称 + * @param waitTimeMillis 等待时间 + * @return 键值对数组 + */ + public NameValuePair[] getMetadata(String groupName, String remoteFileName, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + NameValuePair[] metadata = client.get_metadata(groupName, remoteFileName); + this.pool.returnObject(client); + return metadata; + } + + /** + * 设置元数据 + * + * @param groupName 组名 + * @param remoteFileName 远程文件名称 + * @param metadata 元数据 + * @param flag 更新设置:ProtoCommon.STORAGE_SET_METADATA_FLAG_OVERWRITE 表示重写所有; ProtoCommon.STORAGE_SET_METADATA_FLAG_MERGE 表示没有就插入,有就更新 + * @return 返回0表示成功 + */ + public int setMetadata(String groupName, String remoteFileName, NameValuePair[] metadata, byte flag) throws Exception { + StorageClient client = this.pool.borrowObject(); + int i = client.set_metadata(groupName, remoteFileName, metadata, flag); + this.pool.returnObject(client); + return i; + } + + /** + * 设置元数据 + * + * @param groupName 组名 + * @param remoteFileName 远程文件名称 + * @param metadata 元数据 + * @param flag 更新设置:ProtoCommon.STORAGE_SET_METADATA_FLAG_OVERWRITE 表示重写所有; ProtoCommon.STORAGE_SET_METADATA_FLAG_MERGE 表示没有就插入,有就更新 + * @param waitTimeMillis 等待时长 + * @return 返回0表示成功 + */ + public int setMetadata(String groupName, String remoteFileName, NameValuePair[] metadata, byte flag, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + int i = client.set_metadata(groupName, remoteFileName, metadata, flag); + this.pool.returnObject(client); + return i; + } + + /** + * 获取文件信息 + * + * @param groupName 组名 + * @param remoteFileName 远程文件名称 + * @return 返回文件信息 + */ + public FileInfo getFileInfo(String groupName, String remoteFileName) throws Exception { + StorageClient client = this.pool.borrowObject(); + FileInfo file_info = client.get_file_info(groupName, remoteFileName); + this.pool.returnObject(client); + return file_info; + } + + /** + * 获取文件名称 + * + * @param groupName 组名 + * @param remoteFileName 远程文件名称 + * @param waitTimeMillis 等待时长 + * @return 返回文件信息 + */ + public FileInfo getFileInfo(String groupName, String remoteFileName, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + FileInfo file_info = client.get_file_info(groupName, remoteFileName); + this.pool.returnObject(client); + return file_info; + } + + /** + * 查询文件信息 + * + * @param groupName 组名 + * @param remoteFileName 远程文件信息 + * @return 返回文件信息 + */ + public FileInfo queryFileInfo(String groupName, String remoteFileName) throws Exception { + StorageClient client = this.pool.borrowObject(); + FileInfo fileInfo = client.query_file_info(groupName, remoteFileName); + this.pool.returnObject(client); + return fileInfo; + } + + /** + * 查询文件信息 + * + * @param groupName 组名 + * @param remoteFileName 远程文件信息 + * @param waitTimeMillis 等待时间 + * @return 返回文件信息 + */ + public FileInfo queryFileInfo(String groupName, String remoteFileName, long waitTimeMillis) throws Exception { + StorageClient client = this.pool.borrowObject(waitTimeMillis); + FileInfo fileInfo = client.query_file_info(groupName, remoteFileName); + this.pool.returnObject(client); + return fileInfo; + } +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/common/Base64.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/common/Base64.java new file mode 100644 index 000000000..4f248ec5b --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/common/Base64.java @@ -0,0 +1,491 @@ +package org.csource.common; + +import java.io.IOException; + +/** + * Freeware from: + * Roedy Green + * Canadian Mind Products + * #327 - 964 Heywood Avenue + * Victoria, BC Canada V8V 2Y5 + * tel:(250) 361-9093 + * mailto:roedy@mindprod.com + */ + +/** + * Encode arbitrary binary into printable ASCII using BASE64 encoding. + * very loosely based on the Base64 Reader by + * Dr. Mark Thornton + * Optrak Distribution Software Ltd. + * http://www.optrak.co.uk + * and Kevin Kelley's http://www.ruralnet.net/~kelley/java/Base64.java + *

+ * Base64 is a way of encoding 8-bit characters using only ASCII printable + * characters similar to UUENCODE. UUENCODE includes a filename where BASE64 does not. + * The spec is described in RFC 2045. Base64 is a scheme where + * 3 bytes are concatenated, then split to form 4 groups of 6-bits each; and + * each 6-bits gets translated to an encoded printable ASCII character, via a + * table lookup. An encoded string is therefore longer than the original by + * about 1/3. The "=" character is used to pad the end. Base64 is used, + * among other things, to encode the user:password string in an + * Authorization: header for HTTP. Don't confuse Base64 with + * x-www-form-urlencoded which is handled by + * Java.net.URLEncoder.encode/decode + * If you don't like this code, there is another implementation at http://www.ruffboy.com/download.htm + * Sun has an undocumented method called sun.misc.Base64Encoder.encode. + * You could use hex, simpler to code, but not as compact. + *

+ * If you wanted to encode a giant file, you could do it in large chunks that + * are even multiples of 3 bytes, except for the last chunk, and append the outputs. + *

+ * To encode a string, rather than binary data java.net.URLEncoder may be better. See + * printable characters in the Java glossary for a discussion of the differences. + *

+ * version 1.4 2002 February 15 -- correct bugs with uneven line lengths, + * allow you to configure line separator. + * now need Base64 object and instance methods. + * new mailing address. + * version 1.3 2000 September 12 -- fix problems with estimating output length in encode + * version 1.2 2000 September 09 -- now handles decode as well. + * version 1.1 1999 December 04 -- more symmetrical encoding algorithm. + * more accurate StringBuffer allocation size. + * version 1.0 1999 December 03 -- posted in comp.lang.java.programmer. + * Futures Streams or files. + */ + +public class Base64 { + + /** + * Marker value for chars we just ignore, e.g. \n \r high ascii + */ + static final int IGNORE = -1; + /** + * Marker for = trailing pad + */ + static final int PAD = -2; + /** + * used to disable test driver + */ + private static final boolean debug = true; + /** + * how we separate lines, e.g. \n, \r\n, \r etc. + */ + private String lineSeparator = System.getProperty("line.separator"); + /** + * max chars per line, excluding lineSeparator. A multiple of 4. + */ + private int lineLength = 72; + private char[] valueToChar = new char[64]; + /** + * binary value encoded by a given letter of the alphabet 0..63 + */ + private int[] charToValue = new int[256]; + private int[] charToPad = new int[4]; + + /* constructor */ + public Base64() { + this.init('+', '/', '='); + } + + /* constructor */ + public Base64(char chPlus, char chSplash, char chPad, int lineLength) { + this.init(chPlus, chSplash, chPad); + this.lineLength = lineLength; + } + + public Base64(int lineLength) { + this.lineLength = lineLength; + } + + /** + * debug display array + */ + public static void show(byte[] b) { + int count = 0; + int rows = 0; + + + for (int i = 0; i < b.length; i++) { + if (count == 8) { + System.out.print(" "); + } else if (count == 16) { + System.out.println(""); + count = 0; + continue; + } + System.out.print(Integer.toHexString(b[i] & 0xFF).toUpperCase() + " "); + count++; + + } + System.out.println(); + } + + /** + * debug display array + */ + public static void display(byte[] b) { + for (int i = 0; i < b.length; i++) { + System.out.print((char) b[i]); + } + System.out.println(); + } + + /** + * test driver + */ + public static void main(String[] args) { + test(); + System.exit(1); + + if (debug) { + try { + Base64 b64 = new Base64(); + String str = "agfrtu¿¦etʲ1234¼Ù´óerty¿Õ234·¢¿¦2344ʲµÄ"; + String str64 = ""; + + //encode + str64 = b64.encode(str.getBytes()); + System.out.println(str64); + + //decode + byte[] theBytes = b64.decode(str64); + show(theBytes); + String rst = new String(theBytes); + System.out.println(rst); + System.out.println(str); + } catch (Exception e) { + e.printStackTrace(); + } + //getBytes(String charsetName); +/* + byte[] a = { (byte)0xfc, (byte)0x0f, (byte)0xc0}; + byte[] b = { (byte)0x03, (byte)0xf0, (byte)0x3f}; + byte[] c = { (byte)0x00, (byte)0x00, (byte)0x00}; + byte[] d = { (byte)0xff, (byte)0xff, (byte)0xff}; + byte[] e = { (byte)0xfc, (byte)0x0f, (byte)0xc0, (byte)1}; + byte[] f = { (byte)0xfc, (byte)0x0f, (byte)0xc0, (byte)1, (byte)2}; + byte[] g = { (byte)0xfc, (byte)0x0f, (byte)0xc0, (byte)1, (byte)2, (byte)3}; + byte[] h = "AAAAAAAAAAB".getBytes(); + + + + show(a); + show(b); + show(c); + show(d); + show(e); + show(f); + show(g); + show(h); + Base64 b64 = new Base64(); + show(b64.decode(b64.encode(a))); + show(b64.decode(b64.encode(b))); + show(b64.decode(b64.encode(c))); + show(b64.decode(b64.encode(d))); + show(b64.decode(b64.encode(e))); + show(b64.decode(b64.encode(f))); + show(b64.decode(b64.encode(g))); + show(b64.decode(b64.encode(h))); + b64.setLineLength(8); + show((b64.encode(h)).getBytes()); +*/ + } + }// end main + + public static void test() { + try { + Base64 b64 = new Base64(); + + //encode + //str64 = b64.encode(str.getBytes()); + //System.out.println(str64); + + String str64 = "CwUEFYoAAAADjQMC7ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267ELJiY6w05267EI="; + //decode + byte[] theBytes = b64.decode(str64); + show(theBytes); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /* initialise defaultValueToChar and defaultCharToValue tables */ + private void init(char chPlus, char chSplash, char chPad) { + int index = 0; + // build translate this.valueToChar table only once. + // 0..25 -> 'A'..'Z' + for (int i = 'A'; i <= 'Z'; i++) { + this.valueToChar[index++] = (char) i; + } + + // 26..51 -> 'a'..'z' + for (int i = 'a'; i <= 'z'; i++) { + this.valueToChar[index++] = (char) i; + } + + // 52..61 -> '0'..'9' + for (int i = '0'; i <= '9'; i++) { + this.valueToChar[index++] = (char) i; + } + + this.valueToChar[index++] = chPlus; + this.valueToChar[index++] = chSplash; + + // build translate defaultCharToValue table only once. + for (int i = 0; i < 256; i++) { + this.charToValue[i] = IGNORE; // default is to ignore + } + + for (int i = 0; i < 64; i++) { + this.charToValue[this.valueToChar[i]] = i; + } + + this.charToValue[chPad] = PAD; + java.util.Arrays.fill(this.charToPad, chPad); + } + + /** + * Encode an arbitrary array of bytes as Base64 printable ASCII. + * It will be broken into lines of 72 chars each. The last line is not + * terminated with a line separator. + * The output will always have an even multiple of data characters, + * exclusive of \n. It is padded out with =. + */ + public String encode(byte[] b) throws IOException { + // Each group or partial group of 3 bytes becomes four chars + // covered quotient + int outputLength = ((b.length + 2) / 3) * 4; + + // account for trailing newlines, on all but the very last line + if (lineLength != 0) { + int lines = (outputLength + lineLength - 1) / lineLength - 1; + if (lines > 0) { + outputLength += lines * lineSeparator.length(); + } + } + + // must be local for recursion to work. + StringBuffer sb = new StringBuffer(outputLength); + + // must be local for recursion to work. + int linePos = 0; + + // first deal with even multiples of 3 bytes. + int len = (b.length / 3) * 3; + int leftover = b.length - len; + for (int i = 0; i < len; i += 3) { + // Start a new line if next 4 chars won't fit on the current line + // We can't encapsulete the following code since the variable need to + // be local to this incarnation of encode. + linePos += 4; + if (linePos > lineLength) { + if (lineLength != 0) { + sb.append(lineSeparator); + } + linePos = 4; + } + + // get next three bytes in unsigned form lined up, + // in big-endian order + int combined = b[i + 0] & 0xff; + combined <<= 8; + combined |= b[i + 1] & 0xff; + combined <<= 8; + combined |= b[i + 2] & 0xff; + + // break those 24 bits into a 4 groups of 6 bits, + // working LSB to MSB. + int c3 = combined & 0x3f; + combined >>>= 6; + int c2 = combined & 0x3f; + combined >>>= 6; + int c1 = combined & 0x3f; + combined >>>= 6; + int c0 = combined & 0x3f; + + // Translate into the equivalent alpha character + // emitting them in big-endian order. + sb.append(valueToChar[c0]); + sb.append(valueToChar[c1]); + sb.append(valueToChar[c2]); + sb.append(valueToChar[c3]); + } + + // deal with leftover bytes + switch (leftover) { + case 0: + default: + // nothing to do + break; + + case 1: + // One leftover byte generates xx== + // Start a new line if next 4 chars won't fit on the current line + linePos += 4; + if (linePos > lineLength) { + + if (lineLength != 0) { + sb.append(lineSeparator); + } + linePos = 4; + } + + // Handle this recursively with a faked complete triple. + // Throw away last two chars and replace with == + sb.append(encode(new byte[]{b[len], 0, 0} + ).substring(0, 2)); + sb.append("=="); + break; + + case 2: + // Two leftover bytes generates xxx= + // Start a new line if next 4 chars won't fit on the current line + linePos += 4; + if (linePos > lineLength) { + if (lineLength != 0) { + sb.append(lineSeparator); + } + linePos = 4; + } + // Handle this recursively with a faked complete triple. + // Throw away last char and replace with = + sb.append(encode(new byte[]{b[len], b[len + 1], 0} + ).substring(0, 3)); + sb.append("="); + break; + + } // end switch; + + if (outputLength != sb.length()) { + System.out.println("oops: minor program flaw: output length mis-estimated"); + System.out.println("estimate:" + outputLength); + System.out.println("actual:" + sb.length()); + } + return sb.toString(); + }// end encode + + /** + * decode a well-formed complete Base64 string back into an array of bytes. + * It must have an even multiple of 4 data characters (not counting \n), + * padded out with = as needed. + */ + public byte[] decodeAuto(String s) { + int nRemain = s.length() % 4; + if (nRemain == 0) { + return this.decode(s); + } else { + return this.decode(s + new String(this.charToPad, 0, 4 - nRemain)); + } + } + + /** + * decode a well-formed complete Base64 string back into an array of bytes. + * It must have an even multiple of 4 data characters (not counting \n), + * padded out with = as needed. + */ + public byte[] decode(String s) { + + // estimate worst case size of output array, no embedded newlines. + byte[] b = new byte[(s.length() / 4) * 3]; + + // tracks where we are in a cycle of 4 input chars. + int cycle = 0; + + // where we combine 4 groups of 6 bits and take apart as 3 groups of 8. + int combined = 0; + + // how many bytes we have prepared. + int j = 0; + // will be an even multiple of 4 chars, plus some embedded \n + int len = s.length(); + int dummies = 0; + for (int i = 0; i < len; i++) { + + int c = s.charAt(i); + int value = (c <= 255) ? charToValue[c] : IGNORE; + // there are two magic values PAD (=) and IGNORE. + switch (value) { + case IGNORE: + // e.g. \n, just ignore it. + break; + + case PAD: + value = 0; + dummies++; + // fallthrough + default: + /* regular value character */ + switch (cycle) { + case 0: + combined = value; + cycle = 1; + break; + + case 1: + combined <<= 6; + combined |= value; + cycle = 2; + break; + + case 2: + combined <<= 6; + combined |= value; + cycle = 3; + break; + + case 3: + combined <<= 6; + combined |= value; + // we have just completed a cycle of 4 chars. + // the four 6-bit values are in combined in big-endian order + // peel them off 8 bits at a time working lsb to msb + // to get our original 3 8-bit bytes back + + b[j + 2] = (byte) combined; + combined >>>= 8; + b[j + 1] = (byte) combined; + combined >>>= 8; + b[j] = (byte) combined; + j += 3; + cycle = 0; + break; + } + break; + } + } // end for + if (cycle != 0) { + throw new ArrayIndexOutOfBoundsException("Input to decode not an even multiple of 4 characters; pad with =."); + } + j -= dummies; + if (b.length != j) { + byte[] b2 = new byte[j]; + System.arraycopy(b, 0, b2, 0, j); + b = b2; + } + return b; + + }// end decode + + /** + * determines how long the lines are that are generated by encode. + * Ignored by decode. + * + * @param length 0 means no newlines inserted. Must be a multiple of 4. + */ + public void setLineLength(int length) { + this.lineLength = (length / 4) * 4; + } + + /** + * How lines are separated. + * Ignored by decode. + * + * @param lineSeparator may be "" but not null. + * Usually contains only a combination of chars \n and \r. + * Could be any chars not in set A-Z a-z 0-9 + /. + */ + public void setLineSeparator(String lineSeparator) { + this.lineSeparator = lineSeparator; + } +} // end Base64 + diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/common/FastdfsException.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/common/FastdfsException.java new file mode 100644 index 000000000..428e5326c --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/common/FastdfsException.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2008 Happy Fish / YuQing + * + * FastDFS Java Client may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. + */ + +package org.csource.common; + +/** + * My Exception + * + * @author Happy Fish / YuQing + * @version Version 1.0 + */ +public class FastdfsException extends Exception { + public FastdfsException() { + } + + public FastdfsException(String message) { + super(message); + } +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/common/IniFileReader.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/common/IniFileReader.java new file mode 100644 index 000000000..5b373f83c --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/common/IniFileReader.java @@ -0,0 +1,216 @@ +/** + * Copyright (C) 2008 Happy Fish / YuQing + *

+ * FastDFS Java Client may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. + **/ + +package org.csource.common; + +import java.io.*; +import java.util.ArrayList; +import java.util.Hashtable; + +/** + * ini file reader / parser + * + * @author Happy Fish / YuQing + * @version Version 1.0 + */ +public class IniFileReader { + private Hashtable paramTable; + private String conf_filename; + + /** + * @param conf_filename config filename + */ + public IniFileReader(String conf_filename) throws IOException { + this.conf_filename = conf_filename; + loadFromFile(conf_filename); + } + + public static ClassLoader classLoader() { + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + if (loader == null) { + loader = ClassLoader.getSystemClassLoader(); + } + return loader; + } + + public static InputStream loadFromOsFileSystemOrClasspathAsStream(String filePath) { + InputStream in = null; + try { + // 优先从文件系统路径加载 + if (new File(filePath).exists()) { + in = new FileInputStream(filePath); + //System.out.println("loadFrom...file path done"); + } + // 从类路径加载 + else { + in = classLoader().getResourceAsStream(filePath); + //System.out.println("loadFrom...class path done"); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + return in; + } + + /** + * get the config filename + * + * @return config filename + */ + public String getConfFilename() { + return this.conf_filename; + } + + /** + * get string value from config file + * + * @param name item name in config file + * @return string value + */ + public String getStrValue(String name) { + Object obj; + obj = this.paramTable.get(name); + if (obj == null) { + return null; + } + + if (obj instanceof String) { + return (String) obj; + } + + return (String) ((ArrayList) obj).get(0); + } + + /** + * get int value from config file + * + * @param name item name in config file + * @param default_value the default value + * @return int value + */ + public int getIntValue(String name, int default_value) { + String szValue = this.getStrValue(name); + if (szValue == null) { + return default_value; + } + + return Integer.parseInt(szValue); + } + + /** + * get boolean value from config file + * + * @param name item name in config file + * @param default_value the default value + * @return boolean value + */ + public boolean getBoolValue(String name, boolean default_value) { + String szValue = this.getStrValue(name); + if (szValue == null) { + return default_value; + } + + return szValue.equalsIgnoreCase("yes") || szValue.equalsIgnoreCase("on") || + szValue.equalsIgnoreCase("true") || szValue.equals("1"); + } + + /** + * get all values from config file + * + * @param name item name in config file + * @return string values (array) + */ + public String[] getValues(String name) { + Object obj; + String[] values; + + obj = this.paramTable.get(name); + if (obj == null) { + return null; + } + + if (obj instanceof String) { + values = new String[1]; + values[0] = (String) obj; + return values; + } + + Object[] objs = ((ArrayList) obj).toArray(); + values = new String[objs.length]; + System.arraycopy(objs, 0, values, 0, objs.length); + return values; + } + + private void loadFromFile(String confFilePath) throws IOException { + InputStream in = loadFromOsFileSystemOrClasspathAsStream(confFilePath); + try { + readToParamTable(in); + } catch (Exception ex) { + ex.printStackTrace(); + } finally { + try { + if (in != null) in.close(); + //System.out.println("loadFrom...finally...in.close(); done"); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + + private void readToParamTable(InputStream in) throws IOException { + this.paramTable = new Hashtable(); + if (in == null) return; + String line; + String[] parts; + String name; + String value; + Object obj; + ArrayList valueList; + InputStreamReader inReader = null; + BufferedReader bufferedReader = null; + try { + inReader = new InputStreamReader(in); + bufferedReader = new BufferedReader(inReader); + while ((line = bufferedReader.readLine()) != null) { + line = line.trim(); + if (line.length() == 0 || line.charAt(0) == '#') { + continue; + } + parts = line.split("=", 2); + if (parts.length != 2) { + continue; + } + name = parts[0].trim(); + value = parts[1].trim(); + obj = this.paramTable.get(name); + if (obj == null) { + this.paramTable.put(name, value); + } else if (obj instanceof String) { + valueList = new ArrayList(); + valueList.add(obj); + valueList.add(value); + this.paramTable.put(name, valueList); + } else { + valueList = (ArrayList) obj; + valueList.add(value); + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } finally { + try { + if (bufferedReader != null) bufferedReader.close(); + if (inReader != null) inReader.close(); + //System.out.println("readToParamTable...finally...bufferedReader.close();inReader.close(); done"); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/common/NameValuePair.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/common/NameValuePair.java new file mode 100644 index 000000000..dab62b79a --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/common/NameValuePair.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2008 Happy Fish / YuQing + * + * FastDFS Java Client may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. + */ + +package org.csource.common; + +/** + * name(key) and value pair model + * + * @author Happy Fish / YuQing + * @version Version 1.0 + */ +public class NameValuePair { + protected String name; + protected String value; + + public NameValuePair() { + } + + public NameValuePair(String name) { + this.name = name; + } + + public NameValuePair(String name, String value) { + this.name = name; + this.value = value; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public String getValue() { + return this.value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/ClientGlobal.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/ClientGlobal.java new file mode 100644 index 000000000..030a8c163 --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/ClientGlobal.java @@ -0,0 +1,305 @@ +/** + * Copyright (C) 2008 Happy Fish / YuQing + *

+ * FastDFS Java Client may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. + **/ + +package org.csource.fastdfs; + +import org.csource.common.IniFileReader; +import org.csource.common.FastdfsException; + +import java.io.IOException; +import java.io.InputStream; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +/** + * Global variables + * + * @author Happy Fish / YuQing + * @version Version 1.11 + */ +public class ClientGlobal { + + public static final String CONF_KEY_CONNECT_TIMEOUT = "connect_timeout"; + public static final String CONF_KEY_NETWORK_TIMEOUT = "network_timeout"; + public static final String CONF_KEY_CHARSET = "charset"; + public static final String CONF_KEY_HTTP_ANTI_STEAL_TOKEN = "http.anti_steal_token"; + public static final String CONF_KEY_HTTP_SECRET_KEY = "http.secret_key"; + public static final String CONF_KEY_HTTP_TRACKER_HTTP_PORT = "http.tracker_http_port"; + public static final String CONF_KEY_TRACKER_SERVER = "tracker_server"; + + public static final String PROP_KEY_CONNECT_TIMEOUT_IN_SECONDS = "fastdfs.connect_timeout_in_seconds"; + public static final String PROP_KEY_NETWORK_TIMEOUT_IN_SECONDS = "fastdfs.network_timeout_in_seconds"; + public static final String PROP_KEY_CHARSET = "fastdfs.charset"; + public static final String PROP_KEY_HTTP_ANTI_STEAL_TOKEN = "fastdfs.http_anti_steal_token"; + public static final String PROP_KEY_HTTP_SECRET_KEY = "fastdfs.http_secret_key"; + public static final String PROP_KEY_HTTP_TRACKER_HTTP_PORT = "fastdfs.http_tracker_http_port"; + public static final String PROP_KEY_TRACKER_SERVERS = "fastdfs.tracker_servers"; + + public static final int DEFAULT_CONNECT_TIMEOUT = 5; //second + public static final int DEFAULT_NETWORK_TIMEOUT = 30; //second + public static final String DEFAULT_CHARSET = "UTF-8"; + public static final boolean DEFAULT_HTTP_ANTI_STEAL_TOKEN = false; + public static final String DEFAULT_HTTP_SECRET_KEY = "FastDFS1234567890"; + public static final int DEFAULT_HTTP_TRACKER_HTTP_PORT = 80; + + public static int g_connect_timeout = DEFAULT_CONNECT_TIMEOUT * 1000; //millisecond + public static int g_network_timeout = DEFAULT_NETWORK_TIMEOUT * 1000; //millisecond + public static String g_charset = DEFAULT_CHARSET; + public static boolean g_anti_steal_token = DEFAULT_HTTP_ANTI_STEAL_TOKEN; //if anti-steal token + public static String g_secret_key = DEFAULT_HTTP_SECRET_KEY; //generage token secret key + public static int g_tracker_http_port = DEFAULT_HTTP_TRACKER_HTTP_PORT; + + public static TrackerGroup g_tracker_group; + + private ClientGlobal() { + } + + /** + * load global variables + * + * @param conf_filename config filename + */ + public static void init(String conf_filename) throws IOException, FastdfsException { + IniFileReader iniReader; + String[] szTrackerServers; + String[] parts; + + iniReader = new IniFileReader(conf_filename); + + g_connect_timeout = iniReader.getIntValue("connect_timeout", DEFAULT_CONNECT_TIMEOUT); + if (g_connect_timeout < 0) { + g_connect_timeout = DEFAULT_CONNECT_TIMEOUT; + } + g_connect_timeout *= 1000; //millisecond + + g_network_timeout = iniReader.getIntValue("network_timeout", DEFAULT_NETWORK_TIMEOUT); + if (g_network_timeout < 0) { + g_network_timeout = DEFAULT_NETWORK_TIMEOUT; + } + g_network_timeout *= 1000; //millisecond + + g_charset = iniReader.getStrValue("charset"); + if (g_charset == null || g_charset.length() == 0) { + g_charset = "ISO8859-1"; + } + + szTrackerServers = iniReader.getValues("tracker_server"); + if (szTrackerServers == null) { + throw new FastdfsException("item \"tracker_server\" in " + conf_filename + " not found"); + } + + InetSocketAddress[] tracker_servers = new InetSocketAddress[szTrackerServers.length]; + for (int i = 0; i < szTrackerServers.length; i++) { + parts = szTrackerServers[i].split("\\:", 2); + if (parts.length != 2) { + throw new FastdfsException("the value of item \"tracker_server\" is invalid, the correct format is host:port"); + } + + tracker_servers[i] = new InetSocketAddress(parts[0].trim(), Integer.parseInt(parts[1].trim())); + } + g_tracker_group = new TrackerGroup(tracker_servers); + + g_tracker_http_port = iniReader.getIntValue("http.tracker_http_port", 80); + g_anti_steal_token = iniReader.getBoolValue("http.anti_steal_token", false); + if (g_anti_steal_token) { + g_secret_key = iniReader.getStrValue("http.secret_key"); + } + } + + /** + * load from properties file + * + * @param propsFilePath properties file path, eg: + * "fastdfs-client.properties" + * "config/fastdfs-client.properties" + * "/opt/fastdfs-client.properties" + * "C:\\Users\\James\\config\\fastdfs-client.properties" + * properties文件至少包含一个配置项 fastdfs.tracker_servers 例如: + * fastdfs.tracker_servers = 10.0.11.245:22122,10.0.11.246:22122 + * server的IP和端口用冒号':'分隔 + * server之间用逗号','分隔 + */ + public static void initByProperties(String propsFilePath) throws IOException, FastdfsException { + Properties props = new Properties(); + InputStream in = IniFileReader.loadFromOsFileSystemOrClasspathAsStream(propsFilePath); + if (in != null) { + props.load(in); + } + initByProperties(props); + } + + public static void initByProperties(Properties props) throws IOException, FastdfsException { + String trackerServersConf = props.getProperty(PROP_KEY_TRACKER_SERVERS); + if (trackerServersConf == null || trackerServersConf.trim().length() == 0) { + throw new FastdfsException(String.format("configure item %s is required", PROP_KEY_TRACKER_SERVERS)); + } + initByTrackers(trackerServersConf.trim()); + + String connectTimeoutInSecondsConf = props.getProperty(PROP_KEY_CONNECT_TIMEOUT_IN_SECONDS); + String networkTimeoutInSecondsConf = props.getProperty(PROP_KEY_NETWORK_TIMEOUT_IN_SECONDS); + String charsetConf = props.getProperty(PROP_KEY_CHARSET); + String httpAntiStealTokenConf = props.getProperty(PROP_KEY_HTTP_ANTI_STEAL_TOKEN); + String httpSecretKeyConf = props.getProperty(PROP_KEY_HTTP_SECRET_KEY); + String httpTrackerHttpPortConf = props.getProperty(PROP_KEY_HTTP_TRACKER_HTTP_PORT); + if (connectTimeoutInSecondsConf != null && connectTimeoutInSecondsConf.trim().length() != 0) { + g_connect_timeout = Integer.parseInt(connectTimeoutInSecondsConf.trim()) * 1000; + } + if (networkTimeoutInSecondsConf != null && networkTimeoutInSecondsConf.trim().length() != 0) { + g_network_timeout = Integer.parseInt(networkTimeoutInSecondsConf.trim()) * 1000; + } + if (charsetConf != null && charsetConf.trim().length() != 0) { + g_charset = charsetConf.trim(); + } + if (httpAntiStealTokenConf != null && httpAntiStealTokenConf.trim().length() != 0) { + g_anti_steal_token = Boolean.parseBoolean(httpAntiStealTokenConf); + } + if (httpSecretKeyConf != null && httpSecretKeyConf.trim().length() != 0) { + g_secret_key = httpSecretKeyConf.trim(); + } + if (httpTrackerHttpPortConf != null && httpTrackerHttpPortConf.trim().length() != 0) { + g_tracker_http_port = Integer.parseInt(httpTrackerHttpPortConf); + } + } + + /** + * load from properties file + * + * @param trackerServers 例如:"10.0.11.245:22122,10.0.11.246:22122" + * server的IP和端口用冒号':'分隔 + * server之间用逗号','分隔 + */ + public static void initByTrackers(String trackerServers) throws IOException, FastdfsException { + List list = new ArrayList(); + String spr1 = ","; + String spr2 = ":"; + String[] arr1 = trackerServers.trim().split(spr1); + for (String addrStr : arr1) { + String[] arr2 = addrStr.trim().split(spr2); + String host = arr2[0].trim(); + int port = Integer.parseInt(arr2[1].trim()); + list.add(new InetSocketAddress(host, port)); + } + InetSocketAddress[] trackerAddresses = list.toArray(new InetSocketAddress[list.size()]); + initByTrackers(trackerAddresses); + } + + public static void initByTrackers(InetSocketAddress[] trackerAddresses) throws IOException, FastdfsException { + g_tracker_group = new TrackerGroup(trackerAddresses); + } + + /** + * construct Socket object + * + * @param ip_addr ip address or hostname + * @param port port number + * @return connected Socket object + */ + public static Socket getSocket(String ip_addr, int port) throws IOException { + Socket sock = new Socket(); + sock.setSoTimeout(ClientGlobal.g_network_timeout); + sock.connect(new InetSocketAddress(ip_addr, port), ClientGlobal.g_connect_timeout); + return sock; + } + + /** + * construct Socket object + * + * @param addr InetSocketAddress object, including ip address and port + * @return connected Socket object + */ + public static Socket getSocket(InetSocketAddress addr) throws IOException { + Socket sock = new Socket(); + sock.setSoTimeout(ClientGlobal.g_network_timeout); + sock.connect(addr, ClientGlobal.g_connect_timeout); + return sock; + } + + public static int getG_connect_timeout() { + return g_connect_timeout; + } + + public static void setG_connect_timeout(int connect_timeout) { + ClientGlobal.g_connect_timeout = connect_timeout; + } + + public static int getG_network_timeout() { + return g_network_timeout; + } + + public static void setG_network_timeout(int network_timeout) { + ClientGlobal.g_network_timeout = network_timeout; + } + + public static String getG_charset() { + return g_charset; + } + + public static void setG_charset(String charset) { + ClientGlobal.g_charset = charset; + } + + public static int getG_tracker_http_port() { + return g_tracker_http_port; + } + + public static void setG_tracker_http_port(int tracker_http_port) { + ClientGlobal.g_tracker_http_port = tracker_http_port; + } + + public static boolean getG_anti_steal_token() { + return g_anti_steal_token; + } + + public static boolean isG_anti_steal_token() { + return g_anti_steal_token; + } + + public static void setG_anti_steal_token(boolean anti_steal_token) { + ClientGlobal.g_anti_steal_token = anti_steal_token; + } + + public static String getG_secret_key() { + return g_secret_key; + } + + public static void setG_secret_key(String secret_key) { + ClientGlobal.g_secret_key = secret_key; + } + + public static TrackerGroup getG_tracker_group() { + return g_tracker_group; + } + + public static void setG_tracker_group(TrackerGroup tracker_group) { + ClientGlobal.g_tracker_group = tracker_group; + } + + public static String configInfo() { + String trackerServers = ""; + if (g_tracker_group != null) { + InetSocketAddress[] trackerAddresses = g_tracker_group.tracker_servers; + for (InetSocketAddress inetSocketAddress : trackerAddresses) { + if (trackerServers.length() > 0) trackerServers += ","; + trackerServers += inetSocketAddress.toString().substring(1); + } + } + return "{" + + "\n g_connect_timeout(ms) = " + g_connect_timeout + + "\n g_network_timeout(ms) = " + g_network_timeout + + "\n g_charset = " + g_charset + + "\n g_anti_steal_token = " + g_anti_steal_token + + "\n g_secret_key = " + g_secret_key + + "\n g_tracker_http_port = " + g_tracker_http_port + + "\n trackerServers = " + trackerServers + + "\n}"; + } + +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/DownloadCallback.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/DownloadCallback.java new file mode 100644 index 000000000..5f31dffdd --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/DownloadCallback.java @@ -0,0 +1,27 @@ +/** + * Copyright (C) 2008 Happy Fish / YuQing + *

+ * FastDFS Java Client may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. + */ + +package org.csource.fastdfs; + +/** + * Download file callback interface + * + * @author Happy Fish / YuQing + * @version Version 1.4 + */ +public interface DownloadCallback { + /** + * recv file content callback function, may be called more than once when the file downloaded + * + * @param file_size file size + * @param data data buff + * @param bytes data bytes + * @return 0 success, return none zero(errno) if fail + */ + public int recv(long file_size, byte[] data, int bytes); +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/DownloadStream.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/DownloadStream.java new file mode 100644 index 000000000..2432339f1 --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/DownloadStream.java @@ -0,0 +1,44 @@ +package org.csource.fastdfs; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * Download file by stream (download callback class) + * + * @author zhouzezhong & Happy Fish / YuQing + * @version Version 1.11 + */ +public class DownloadStream implements DownloadCallback { + private OutputStream out; + private long currentBytes = 0; + + public DownloadStream(OutputStream out) { + super(); + this.out = out; + } + + /** + * recv file content callback function, may be called more than once when the file downloaded + * + * @param fileSize file size + * @param data data buff + * @param bytes data bytes + * @return 0 success, return none zero(errno) if fail + */ + public int recv(long fileSize, byte[] data, int bytes) { + try { + out.write(data, 0, bytes); + } catch (IOException ex) { + ex.printStackTrace(); + return -1; + } + + currentBytes += bytes; + if (this.currentBytes == fileSize) { + this.currentBytes = 0; + } + + return 0; + } +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/FileInfo.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/FileInfo.java new file mode 100644 index 000000000..e70d6de6d --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/FileInfo.java @@ -0,0 +1,125 @@ +/** + * Copyright (C) 2008 Happy Fish / YuQing + *

+ * FastDFS Java Client may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. + */ + +package org.csource.fastdfs; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Server Info + * + * @author Happy Fish / YuQing + * @version Version 1.23 + */ +public class FileInfo { + protected String source_ip_addr; + protected long file_size; + protected Date create_timestamp; + protected int crc32; + + /** + * Constructor + * + * @param file_size the file size + * @param create_timestamp create timestamp in seconds + * @param crc32 the crc32 signature + * @param source_ip_addr the source storage ip address + */ + public FileInfo(long file_size, int create_timestamp, int crc32, String source_ip_addr) { + this.file_size = file_size; + this.create_timestamp = new Date(create_timestamp * 1000L); + this.crc32 = crc32; + this.source_ip_addr = source_ip_addr; + } + + /** + * get the source ip address of the file uploaded to + * + * @return the source ip address of the file uploaded to + */ + public String getSourceIpAddr() { + return this.source_ip_addr; + } + + /** + * set the source ip address of the file uploaded to + * + * @param source_ip_addr the source ip address + */ + public void setSourceIpAddr(String source_ip_addr) { + this.source_ip_addr = source_ip_addr; + } + + /** + * get the file size + * + * @return the file size + */ + public long getFileSize() { + return this.file_size; + } + + /** + * set the file size + * + * @param file_size the file size + */ + public void setFileSize(long file_size) { + this.file_size = file_size; + } + + /** + * get the create timestamp of the file + * + * @return the create timestamp of the file + */ + public Date getCreateTimestamp() { + return this.create_timestamp; + } + + /** + * set the create timestamp of the file + * + * @param create_timestamp create timestamp in seconds + */ + public void setCreateTimestamp(int create_timestamp) { + this.create_timestamp = new Date(create_timestamp * 1000L); + } + + /** + * get the file CRC32 signature + * + * @return the file CRC32 signature + */ + public long getCrc32() { + return this.crc32; + } + + /** + * set the create timestamp of the file + * + * @param crc32 the crc32 signature + */ + public void setCrc32(int crc32) { + this.crc32 = crc32; + } + + /** + * to string + * + * @return string + */ + public String toString() { + SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + return "source_ip_addr = " + this.source_ip_addr + ", " + + "file_size = " + this.file_size + ", " + + "create_timestamp = " + df.format(this.create_timestamp) + ", " + + "crc32 = " + this.crc32; + } +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/ProtoCommon.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/ProtoCommon.java new file mode 100644 index 000000000..e197c278b --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/ProtoCommon.java @@ -0,0 +1,503 @@ +/** + * Copyright (C) 2008 Happy Fish / YuQing + *

+ * FastDFS Java Client may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. + **/ + +package org.csource.fastdfs; + +import org.csource.common.FastdfsException; +import org.csource.common.NameValuePair; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.Socket; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; + +/** + * protocol common functions + * + * @author Happy Fish / YuQing + * @version Version 1.18 + */ +public class ProtoCommon { + public static final byte FDFS_PROTO_CMD_QUIT = 82; + public static final byte TRACKER_PROTO_CMD_SERVER_LIST_GROUP = 91; + public static final byte TRACKER_PROTO_CMD_SERVER_LIST_STORAGE = 92; + public static final byte TRACKER_PROTO_CMD_SERVER_DELETE_STORAGE = 93; + public static final byte TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ONE = 101; + public static final byte TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ONE = 102; + public static final byte TRACKER_PROTO_CMD_SERVICE_QUERY_UPDATE = 103; + public static final byte TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ONE = 104; + public static final byte TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ALL = 105; + public static final byte TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ALL = 106; + public static final byte TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ALL = 107; + public static final byte TRACKER_PROTO_CMD_RESP = 100; + public static final byte FDFS_PROTO_CMD_ACTIVE_TEST = 111; + public static final byte STORAGE_PROTO_CMD_UPLOAD_FILE = 11; + public static final byte STORAGE_PROTO_CMD_DELETE_FILE = 12; + public static final byte STORAGE_PROTO_CMD_SET_METADATA = 13; + public static final byte STORAGE_PROTO_CMD_DOWNLOAD_FILE = 14; + public static final byte STORAGE_PROTO_CMD_GET_METADATA = 15; + public static final byte STORAGE_PROTO_CMD_UPLOAD_SLAVE_FILE = 21; + public static final byte STORAGE_PROTO_CMD_QUERY_FILE_INFO = 22; + public static final byte STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE = 23; //create appender file + public static final byte STORAGE_PROTO_CMD_APPEND_FILE = 24; //append file + public static final byte STORAGE_PROTO_CMD_MODIFY_FILE = 34; //modify appender file + public static final byte STORAGE_PROTO_CMD_TRUNCATE_FILE = 36; //truncate appender file + public static final byte STORAGE_PROTO_CMD_RESP = TRACKER_PROTO_CMD_RESP; + public static final byte FDFS_STORAGE_STATUS_INIT = 0; + public static final byte FDFS_STORAGE_STATUS_WAIT_SYNC = 1; + public static final byte FDFS_STORAGE_STATUS_SYNCING = 2; + public static final byte FDFS_STORAGE_STATUS_IP_CHANGED = 3; + public static final byte FDFS_STORAGE_STATUS_DELETED = 4; + public static final byte FDFS_STORAGE_STATUS_OFFLINE = 5; + public static final byte FDFS_STORAGE_STATUS_ONLINE = 6; + public static final byte FDFS_STORAGE_STATUS_ACTIVE = 7; + public static final byte FDFS_STORAGE_STATUS_NONE = 99; + /** + * for overwrite all old metadata + */ + public static final byte STORAGE_SET_METADATA_FLAG_OVERWRITE = 'O'; + /** + * for replace, insert when the meta item not exist, otherwise update it + */ + public static final byte STORAGE_SET_METADATA_FLAG_MERGE = 'M'; + public static final int FDFS_PROTO_PKG_LEN_SIZE = 8; + public static final int FDFS_PROTO_CMD_SIZE = 1; + public static final int FDFS_GROUP_NAME_MAX_LEN = 16; + public static final int FDFS_IPADDR_SIZE = 16; + public static final int FDFS_DOMAIN_NAME_MAX_SIZE = 128; + public static final int FDFS_VERSION_SIZE = 6; + public static final int FDFS_STORAGE_ID_MAX_SIZE = 16; + public static final String FDFS_RECORD_SEPERATOR = "\u0001"; + public static final String FDFS_FIELD_SEPERATOR = "\u0002"; + public static final int TRACKER_QUERY_STORAGE_FETCH_BODY_LEN = FDFS_GROUP_NAME_MAX_LEN + + FDFS_IPADDR_SIZE - 1 + FDFS_PROTO_PKG_LEN_SIZE; + public static final int TRACKER_QUERY_STORAGE_STORE_BODY_LEN = FDFS_GROUP_NAME_MAX_LEN + + FDFS_IPADDR_SIZE + FDFS_PROTO_PKG_LEN_SIZE; + public static final byte FDFS_FILE_EXT_NAME_MAX_LEN = 6; + public static final byte FDFS_FILE_PREFIX_MAX_LEN = 16; + public static final byte FDFS_FILE_PATH_LEN = 10; + public static final byte FDFS_FILENAME_BASE64_LENGTH = 27; + public static final byte FDFS_TRUNK_FILE_INFO_LEN = 16; + public static final byte ERR_NO_ENOENT = 2; + public static final byte ERR_NO_EIO = 5; + public static final byte ERR_NO_EBUSY = 16; + public static final byte ERR_NO_EINVAL = 22; + public static final byte ERR_NO_ENOSPC = 28; + public static final byte ECONNREFUSED = 61; + public static final byte ERR_NO_EALREADY = 114; + public static final long INFINITE_FILE_SIZE = 256 * 1024L * 1024 * 1024 * 1024 * 1024L; + public static final long APPENDER_FILE_SIZE = INFINITE_FILE_SIZE; + public static final long TRUNK_FILE_MARK_SIZE = 512 * 1024L * 1024 * 1024 * 1024 * 1024L; + public static final long NORMAL_LOGIC_FILENAME_LENGTH = FDFS_FILE_PATH_LEN + FDFS_FILENAME_BASE64_LENGTH + FDFS_FILE_EXT_NAME_MAX_LEN + 1; + public static final long TRUNK_LOGIC_FILENAME_LENGTH = NORMAL_LOGIC_FILENAME_LENGTH + FDFS_TRUNK_FILE_INFO_LEN; + protected static final int PROTO_HEADER_CMD_INDEX = FDFS_PROTO_PKG_LEN_SIZE; + protected static final int PROTO_HEADER_STATUS_INDEX = FDFS_PROTO_PKG_LEN_SIZE + 1; + + private ProtoCommon() { + } + + public static String getStorageStatusCaption(byte status) { + switch (status) { + case FDFS_STORAGE_STATUS_INIT: + return "INIT"; + case FDFS_STORAGE_STATUS_WAIT_SYNC: + return "WAIT_SYNC"; + case FDFS_STORAGE_STATUS_SYNCING: + return "SYNCING"; + case FDFS_STORAGE_STATUS_IP_CHANGED: + return "IP_CHANGED"; + case FDFS_STORAGE_STATUS_DELETED: + return "DELETED"; + case FDFS_STORAGE_STATUS_OFFLINE: + return "OFFLINE"; + case FDFS_STORAGE_STATUS_ONLINE: + return "ONLINE"; + case FDFS_STORAGE_STATUS_ACTIVE: + return "ACTIVE"; + case FDFS_STORAGE_STATUS_NONE: + return "NONE"; + default: + return "UNKOWN"; + } + } + + /** + * pack header by FastDFS transfer protocol + * + * @param cmd which command to send + * @param pkg_len package body length + * @param errno status code, should be (byte)0 + * @return packed byte buffer + */ + public static byte[] packHeader(byte cmd, long pkg_len, byte errno) throws UnsupportedEncodingException { + byte[] header; + byte[] hex_len; + + header = new byte[FDFS_PROTO_PKG_LEN_SIZE + 2]; + Arrays.fill(header, (byte) 0); + + hex_len = ProtoCommon.long2buff(pkg_len); + System.arraycopy(hex_len, 0, header, 0, hex_len.length); + header[PROTO_HEADER_CMD_INDEX] = cmd; + header[PROTO_HEADER_STATUS_INDEX] = errno; + return header; + } + + /** + * receive pack header + * + * @param in input stream + * @param expect_cmd expect response command + * @param expect_body_len expect response package body length + * @return RecvHeaderInfo: errno and pkg body length + */ + public static RecvHeaderInfo recvHeader(InputStream in, byte expect_cmd, long expect_body_len) throws IOException { + byte[] header; + int bytes; + long pkg_len; + + header = new byte[FDFS_PROTO_PKG_LEN_SIZE + 2]; + + if ((bytes = in.read(header)) != header.length) { + throw new IOException("recv package size " + bytes + " != " + header.length); + } + + if (header[PROTO_HEADER_CMD_INDEX] != expect_cmd) { + throw new IOException("recv cmd: " + header[PROTO_HEADER_CMD_INDEX] + " is not correct, expect cmd: " + expect_cmd); + } + + if (header[PROTO_HEADER_STATUS_INDEX] != 0) { + return new RecvHeaderInfo(header[PROTO_HEADER_STATUS_INDEX], 0); + } + + pkg_len = ProtoCommon.buff2long(header, 0); + if (pkg_len < 0) { + throw new IOException("recv body length: " + pkg_len + " < 0!"); + } + + if (expect_body_len >= 0 && pkg_len != expect_body_len) { + throw new IOException("recv body length: " + pkg_len + " is not correct, expect length: " + expect_body_len); + } + + return new RecvHeaderInfo((byte) 0, pkg_len); + } + + /** + * receive whole pack + * + * @param in input stream + * @param expect_cmd expect response command + * @param expect_body_len expect response package body length + * @return RecvPackageInfo: errno and reponse body(byte buff) + */ + public static RecvPackageInfo recvPackage(InputStream in, byte expect_cmd, long expect_body_len) throws IOException { + RecvHeaderInfo header = recvHeader(in, expect_cmd, expect_body_len); + if (header.errno != 0) { + return new RecvPackageInfo(header.errno, null); + } + + byte[] body = new byte[(int) header.body_len]; + int totalBytes = 0; + int remainBytes = (int) header.body_len; + int bytes; + + while (totalBytes < header.body_len) { + if ((bytes = in.read(body, totalBytes, remainBytes)) < 0) { + break; + } + + totalBytes += bytes; + remainBytes -= bytes; + } + + if (totalBytes != header.body_len) { + throw new IOException("recv package size " + totalBytes + " != " + header.body_len); + } + + return new RecvPackageInfo((byte) 0, body); + } + + /** + * split metadata to name value pair array + * + * @param meta_buff metadata + * @return name value pair array + */ + public static NameValuePair[] split_metadata(String meta_buff) { + return split_metadata(meta_buff, FDFS_RECORD_SEPERATOR, FDFS_FIELD_SEPERATOR); + } + + /** + * split metadata to name value pair array + * + * @param meta_buff metadata + * @param recordSeperator record/row seperator + * @param filedSeperator field/column seperator + * @return name value pair array + */ + public static NameValuePair[] split_metadata(String meta_buff, + String recordSeperator, String filedSeperator) { + String[] rows; + String[] cols; + NameValuePair[] meta_list; + + rows = meta_buff.split(recordSeperator); + meta_list = new NameValuePair[rows.length]; + for (int i = 0; i < rows.length; i++) { + cols = rows[i].split(filedSeperator, 2); + meta_list[i] = new NameValuePair(cols[0]); + if (cols.length == 2) { + meta_list[i].setValue(cols[1]); + } + } + + return meta_list; + } + + /** + * pack metadata array to string + * + * @param meta_list metadata array + * @return packed metadata + */ + public static String pack_metadata(NameValuePair[] meta_list) { + if (meta_list.length == 0) { + return ""; + } + + StringBuffer sb = new StringBuffer(32 * meta_list.length); + sb.append(meta_list[0].getName()).append(FDFS_FIELD_SEPERATOR).append(meta_list[0].getValue()); + for (int i = 1; i < meta_list.length; i++) { + sb.append(FDFS_RECORD_SEPERATOR); + sb.append(meta_list[i].getName()).append(FDFS_FIELD_SEPERATOR).append(meta_list[i].getValue()); + } + + return sb.toString(); + } + + /** + * send quit command to server and close socket + * + * @param sock the Socket object + */ + public static void closeSocket(Socket sock) throws IOException { + byte[] header; + header = packHeader(FDFS_PROTO_CMD_QUIT, 0, (byte) 0); + sock.getOutputStream().write(header); + sock.close(); + } + + /** + * send ACTIVE_TEST command to server, test if network is ok and the server is alive + * + * @param sock the Socket object + */ + public static boolean activeTest(Socket sock) throws IOException { + byte[] header; + header = packHeader(FDFS_PROTO_CMD_ACTIVE_TEST, 0, (byte) 0); + sock.getOutputStream().write(header); + + RecvHeaderInfo headerInfo = recvHeader(sock.getInputStream(), TRACKER_PROTO_CMD_RESP, 0); + return headerInfo.errno == 0 ? true : false; + } + + /** + * long convert to buff (big-endian) + * + * @param n long number + * @return 8 bytes buff + */ + public static byte[] long2buff(long n) { + byte[] bs; + + bs = new byte[8]; + bs[0] = (byte) ((n >> 56) & 0xFF); + bs[1] = (byte) ((n >> 48) & 0xFF); + bs[2] = (byte) ((n >> 40) & 0xFF); + bs[3] = (byte) ((n >> 32) & 0xFF); + bs[4] = (byte) ((n >> 24) & 0xFF); + bs[5] = (byte) ((n >> 16) & 0xFF); + bs[6] = (byte) ((n >> 8) & 0xFF); + bs[7] = (byte) (n & 0xFF); + + return bs; + } + + /** + * buff convert to long + * + * @param bs the buffer (big-endian) + * @param offset the start position based 0 + * @return long number + */ + public static long buff2long(byte[] bs, int offset) { + return (((long) (bs[offset] >= 0 ? bs[offset] : 256 + bs[offset])) << 56) | + (((long) (bs[offset + 1] >= 0 ? bs[offset + 1] : 256 + bs[offset + 1])) << 48) | + (((long) (bs[offset + 2] >= 0 ? bs[offset + 2] : 256 + bs[offset + 2])) << 40) | + (((long) (bs[offset + 3] >= 0 ? bs[offset + 3] : 256 + bs[offset + 3])) << 32) | + (((long) (bs[offset + 4] >= 0 ? bs[offset + 4] : 256 + bs[offset + 4])) << 24) | + (((long) (bs[offset + 5] >= 0 ? bs[offset + 5] : 256 + bs[offset + 5])) << 16) | + (((long) (bs[offset + 6] >= 0 ? bs[offset + 6] : 256 + bs[offset + 6])) << 8) | + ((long) (bs[offset + 7] >= 0 ? bs[offset + 7] : 256 + bs[offset + 7])); + } + + /** + * buff convert to int + * + * @param bs the buffer (big-endian) + * @param offset the start position based 0 + * @return int number + */ + public static int buff2int(byte[] bs, int offset) { + return (((int) (bs[offset] >= 0 ? bs[offset] : 256 + bs[offset])) << 24) | + (((int) (bs[offset + 1] >= 0 ? bs[offset + 1] : 256 + bs[offset + 1])) << 16) | + (((int) (bs[offset + 2] >= 0 ? bs[offset + 2] : 256 + bs[offset + 2])) << 8) | + ((int) (bs[offset + 3] >= 0 ? bs[offset + 3] : 256 + bs[offset + 3])); + } + + /** + * buff convert to ip address + * + * @param bs the buffer (big-endian) + * @param offset the start position based 0 + * @return ip address + */ + public static String getIpAddress(byte[] bs, int offset) { + if (bs[0] == 0 || bs[3] == 0) //storage server ID + { + return ""; + } + + int n; + StringBuilder sbResult = new StringBuilder(16); + for (int i = offset; i < offset + 4; i++) { + n = (bs[i] >= 0) ? bs[i] : 256 + bs[i]; + if (sbResult.length() > 0) { + sbResult.append("."); + } + sbResult.append(String.valueOf(n)); + } + + return sbResult.toString(); + } + + /** + * md5 function + * + * @param source the input buffer + * @return md5 string + */ + public static String md5(byte[] source) throws NoSuchAlgorithmException { + char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); + md.update(source); + byte tmp[] = md.digest(); + char str[] = new char[32]; + int k = 0; + for (int i = 0; i < 16; i++) { + str[k++] = hexDigits[tmp[i] >>> 4 & 0xf]; + str[k++] = hexDigits[tmp[i] & 0xf]; + } + + return new String(str); + } + + /** + * get token for file URL + * + * @param remote_filename the filename return by FastDFS server + * @param ts unix timestamp, unit: second + * @param secret_key the secret key + * @return token string + */ + public static String getToken(String remote_filename, int ts, String secret_key) throws UnsupportedEncodingException, NoSuchAlgorithmException, FastdfsException { + byte[] bsFilename = remote_filename.getBytes(ClientGlobal.g_charset); + byte[] bsKey = secret_key.getBytes(ClientGlobal.g_charset); + byte[] bsTimestamp = (new Integer(ts)).toString().getBytes(ClientGlobal.g_charset); + + byte[] buff = new byte[bsFilename.length + bsKey.length + bsTimestamp.length]; + System.arraycopy(bsFilename, 0, buff, 0, bsFilename.length); + System.arraycopy(bsKey, 0, buff, bsFilename.length, bsKey.length); + System.arraycopy(bsTimestamp, 0, buff, bsFilename.length + bsKey.length, bsTimestamp.length); + + return md5(buff); + } + + /** + * generate slave filename + * + * @param master_filename the master filename to generate the slave filename + * @param prefix_name the prefix name to generate the slave filename + * @param ext_name the extension name of slave filename, null for same as the master extension name + * @return slave filename string + */ + public static String genSlaveFilename(String master_filename, + String prefix_name, String ext_name) throws FastdfsException { + String true_ext_name; + int dotIndex; + + if (master_filename.length() < 28 + FDFS_FILE_EXT_NAME_MAX_LEN) { + throw new FastdfsException("master filename \"" + master_filename + "\" is invalid"); + } + + dotIndex = master_filename.indexOf('.', master_filename.length() - (FDFS_FILE_EXT_NAME_MAX_LEN + 1)); + if (ext_name != null) { + if (ext_name.length() == 0) { + true_ext_name = ""; + } else if (ext_name.charAt(0) == '.') { + true_ext_name = ext_name; + } else { + true_ext_name = "." + ext_name; + } + } else { + if (dotIndex < 0) { + true_ext_name = ""; + } else { + true_ext_name = master_filename.substring(dotIndex); + } + } + + if (true_ext_name.length() == 0 && prefix_name.equals("-m")) { + throw new FastdfsException("prefix_name \"" + prefix_name + "\" is invalid"); + } + + if (dotIndex < 0) { + return master_filename + prefix_name + true_ext_name; + } else { + return master_filename.substring(0, dotIndex) + prefix_name + true_ext_name; + } + } + + /** + * receive package info + */ + public static class RecvPackageInfo { + public byte errno; + public byte[] body; + + public RecvPackageInfo(byte errno, byte[] body) { + this.errno = errno; + this.body = body; + } + } + + /** + * receive header info + */ + public static class RecvHeaderInfo { + public byte errno; + public long body_len; + + public RecvHeaderInfo(byte errno, long body_len) { + this.errno = errno; + this.body_len = body_len; + } + } +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/ProtoStructDecoder.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/ProtoStructDecoder.java new file mode 100644 index 000000000..df7ec6c78 --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/ProtoStructDecoder.java @@ -0,0 +1,48 @@ +/** + * Copyright (C) 2008 Happy Fish / YuQing + *

+ * FastDFS Java Client may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. + */ + +package org.csource.fastdfs; + +import java.io.IOException; +import java.lang.reflect.Array; + +/** + * C struct body decoder + * + * @author Happy Fish / YuQing + * @version Version 1.17 + */ +public class ProtoStructDecoder { + /** + * Constructor + */ + public ProtoStructDecoder() { + } + + /** + * decode byte buffer + */ + public T[] decode(byte[] bs, Class clazz, int fieldsTotalSize) throws Exception { + if (bs.length % fieldsTotalSize != 0) { + throw new IOException("byte array length: " + bs.length + " is invalid!"); + } + + int count = bs.length / fieldsTotalSize; + int offset; + T[] results = (T[]) Array.newInstance(clazz, count); + + offset = 0; + for (int i = 0; i < results.length; i++) { + results[i] = clazz.newInstance(); + results[i].setFields(bs, offset); + offset += fieldsTotalSize; + } + + return results; + } +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/ServerInfo.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/ServerInfo.java new file mode 100644 index 000000000..f1c43a620 --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/ServerInfo.java @@ -0,0 +1,66 @@ +/** + * Copyright (C) 2008 Happy Fish / YuQing + *

+ * FastDFS Java Client may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. + */ + +package org.csource.fastdfs; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; + +/** + * Server Info + * + * @author Happy Fish / YuQing + * @version Version 1.7 + */ +public class ServerInfo { + protected String ip_addr; + protected int port; + + /** + * Constructor + * + * @param ip_addr address of the server + * @param port the port of the server + */ + public ServerInfo(String ip_addr, int port) { + this.ip_addr = ip_addr; + this.port = port; + } + + /** + * return the ip address + * + * @return the ip address + */ + public String getIpAddr() { + return this.ip_addr; + } + + /** + * return the port of the server + * + * @return the port of the server + */ + public int getPort() { + return this.port; + } + + /** + * connect to server + * + * @return connected Socket object + */ + public Socket connect() throws IOException { + Socket sock = new Socket(); + sock.setReuseAddress(true); + sock.setSoTimeout(ClientGlobal.g_network_timeout); + sock.connect(new InetSocketAddress(this.ip_addr, this.port), ClientGlobal.g_connect_timeout); + return sock; + } +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/StorageClient.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/StorageClient.java new file mode 100644 index 000000000..ff5c636d0 --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/StorageClient.java @@ -0,0 +1,1791 @@ +/** + * Copyright (C) 2008 Happy Fish / YuQing + *

+ * FastDFS Java Client may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. + */ + +package org.csource.fastdfs; + +import org.csource.common.Base64; +import org.csource.common.FastdfsException; +import org.csource.common.NameValuePair; + +import java.io.*; +import java.net.Socket; +import java.util.Arrays; + +/** + * Storage client for 2 fields file id: group name and filename + * + * @author Happy Fish / YuQing + * @version Version 1.24 + */ +public class StorageClient { + public final static Base64 base64 = new Base64('-', '_', '.', 0); + protected TrackerServer trackerServer; + protected StorageServer storageServer; + protected byte errno; + + /** + * constructor using global settings in class ClientGlobal + */ + public StorageClient() { + this.trackerServer = null; + this.storageServer = null; + } + + // 增加获取TrackerServer的方法 + public TrackerServer getTrackerServer() { + return this.trackerServer; + } + + /** + * constructor with tracker server and storage server + * + * @param trackerServer the tracker server, can be null + * @param storageServer the storage server, can be null + */ + public StorageClient(TrackerServer trackerServer, StorageServer storageServer) { + this.trackerServer = trackerServer; + this.storageServer = storageServer; + } + + /** + * get the error code of last call + * + * @return the error code of last call + */ + public byte getErrorCode() { + return this.errno; + } + + /** + * upload file to storage server (by file name) + * + * @param local_filename local filename to upload + * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename + * @param meta_list meta info array + * @return 2 elements string array if success:
+ *

  • results[0]: the group name to store the file
+ *
  • results[1]: the new created filename
+ * return null if fail + */ + public String[] upload_file(String local_filename, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + final String group_name = null; + return this.upload_file(group_name, local_filename, file_ext_name, meta_list); + } + + /** + * upload file to storage server (by file name) + * + * @param group_name the group name to upload file to, can be empty + * @param local_filename local filename to upload + * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename + * @param meta_list meta info array + * @return 2 elements string array if success:
+ *
  • results[0]: the group name to store the file
+ *
  • results[1]: the new created filename
+ * return null if fail + */ + protected String[] upload_file(String group_name, String local_filename, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + final byte cmd = ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_FILE; + return this.upload_file(cmd, group_name, local_filename, file_ext_name, meta_list); + } + + /** + * upload file to storage server (by file name) + * + * @param cmd the command + * @param group_name the group name to upload file to, can be empty + * @param local_filename local filename to upload + * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename + * @param meta_list meta info array + * @return 2 elements string array if success:
+ *
  • results[0]: the group name to store the file
+ *
  • results[1]: the new created filename
+ * return null if fail + */ + protected String[] upload_file(byte cmd, String group_name, String local_filename, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + File f = new File(local_filename); + FileInputStream fis = new FileInputStream(f); + + if (file_ext_name == null) { + int nPos = local_filename.lastIndexOf('.'); + if (nPos > 0 && local_filename.length() - nPos <= ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + 1) { + file_ext_name = local_filename.substring(nPos + 1); + } + } + + try { + return this.do_upload_file(cmd, group_name, null, null, file_ext_name, + f.length(), new UploadStream(fis, f.length()), meta_list); + } finally { + fis.close(); + } + } + + /** + * upload file to storage server (by file buff) + * + * @param file_buff file content/buff + * @param offset start offset of the buff + * @param length the length of buff to upload + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ *
  • results[0]: the group name to store the file
+ *
  • results[1]: the new created filename
+ * return null if fail + */ + public String[] upload_file(byte[] file_buff, int offset, int length, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + final String group_name = null; + return this.upload_file(group_name, file_buff, offset, length, file_ext_name, meta_list); + } + + /** + * upload file to storage server (by file buff) + * + * @param group_name the group name to upload file to, can be empty + * @param file_buff file content/buff + * @param offset start offset of the buff + * @param length the length of buff to upload + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ *
  • results[0]: the group name to store the file
+ *
  • results[1]: the new created filename
+ * return null if fail + */ + public String[] upload_file(String group_name, byte[] file_buff, int offset, int length, + String file_ext_name, NameValuePair[] meta_list) throws IOException, FastdfsException { + return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_FILE, group_name, null, null, file_ext_name, + length, new UploadBuff(file_buff, offset, length), meta_list); + } + + /** + * upload file to storage server (by file buff) + * + * @param file_buff file content/buff + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ *
  • results[0]: the group name to store the file
+ *
  • results[1]: the new created filename
+ * return null if fail + */ + public String[] upload_file(byte[] file_buff, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + final String group_name = null; + return this.upload_file(group_name, file_buff, 0, file_buff.length, file_ext_name, meta_list); + } + + /** + * upload file to storage server (by file buff) + * + * @param group_name the group name to upload file to, can be empty + * @param file_buff file content/buff + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ *
  • results[0]: the group name to store the file
+ *
  • results[1]: the new created filename
+ * return null if fail + */ + public String[] upload_file(String group_name, byte[] file_buff, + String file_ext_name, NameValuePair[] meta_list) throws IOException, FastdfsException { + return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_FILE, group_name, null, null, file_ext_name, + file_buff.length, new UploadBuff(file_buff, 0, file_buff.length), meta_list); + } + + /** + * upload file to storage server (by callback) + * + * @param group_name the group name to upload file to, can be empty + * @param file_size the file size + * @param callback the write data callback object + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ *
  • results[0]: the group name to store the file
+ *
  • results[1]: the new created filename
+ * return null if fail + */ + public String[] upload_file(String group_name, long file_size, UploadCallback callback, + String file_ext_name, NameValuePair[] meta_list) throws IOException, FastdfsException { + final String master_filename = null; + final String prefix_name = null; + + return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_FILE, group_name, master_filename, prefix_name, + file_ext_name, file_size, callback, meta_list); + } + + /** + * upload file to storage server (by file name, slave file mode) + * + * @param group_name the group name of master file + * @param master_filename the master file name to generate the slave file + * @param prefix_name the prefix name to generate the slave file + * @param local_filename local filename to upload + * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename + * @param meta_list meta info array + * @return 2 elements string array if success:
+ *
  • results[0]: the group name to store the file
+ *
  • results[1]: the new created filename
+ * return null if fail + */ + public String[] upload_file(String group_name, String master_filename, String prefix_name, + String local_filename, String file_ext_name, NameValuePair[] meta_list) throws IOException, FastdfsException { + if ((group_name == null || group_name.length() == 0) || + (master_filename == null || master_filename.length() == 0) || + (prefix_name == null)) { + throw new FastdfsException("invalid arguement"); + } + + File f = new File(local_filename); + FileInputStream fis = new FileInputStream(f); + + if (file_ext_name == null) { + int nPos = local_filename.lastIndexOf('.'); + if (nPos > 0 && local_filename.length() - nPos <= ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + 1) { + file_ext_name = local_filename.substring(nPos + 1); + } + } + + try { + return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_SLAVE_FILE, group_name, master_filename, prefix_name, + file_ext_name, f.length(), new UploadStream(fis, f.length()), meta_list); + } finally { + fis.close(); + } + } + + /** + * upload file to storage server (by file buff, slave file mode) + * + * @param group_name the group name of master file + * @param master_filename the master file name to generate the slave file + * @param prefix_name the prefix name to generate the slave file + * @param file_buff file content/buff + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ *
  • results[0]: the group name to store the file
+ *
  • results[1]: the new created filename
+ * return null if fail + */ + public String[] upload_file(String group_name, String master_filename, String prefix_name, + byte[] file_buff, String file_ext_name, NameValuePair[] meta_list) throws IOException, FastdfsException { + if ((group_name == null || group_name.length() == 0) || + (master_filename == null || master_filename.length() == 0) || + (prefix_name == null)) { + throw new FastdfsException("invalid arguement"); + } + + return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_SLAVE_FILE, group_name, master_filename, prefix_name, + file_ext_name, file_buff.length, new UploadBuff(file_buff, 0, file_buff.length), meta_list); + } + + /** + * upload file to storage server (by file buff, slave file mode) + * + * @param group_name the group name of master file + * @param master_filename the master file name to generate the slave file + * @param prefix_name the prefix name to generate the slave file + * @param file_buff file content/buff + * @param offset start offset of the buff + * @param length the length of buff to upload + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ *
  • results[0]: the group name to store the file
+ *
  • results[1]: the new created filename
+ * return null if fail + */ + public String[] upload_file(String group_name, String master_filename, String prefix_name, + byte[] file_buff, int offset, int length, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + if ((group_name == null || group_name.length() == 0) || + (master_filename == null || master_filename.length() == 0) || + (prefix_name == null)) { + throw new FastdfsException("invalid arguement"); + } + + return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_SLAVE_FILE, group_name, master_filename, prefix_name, + file_ext_name, length, new UploadBuff(file_buff, offset, length), meta_list); + } + + /** + * upload file to storage server (by callback, slave file mode) + * + * @param group_name the group name to upload file to, can be empty + * @param master_filename the master file name to generate the slave file + * @param prefix_name the prefix name to generate the slave file + * @param file_size the file size + * @param callback the write data callback object + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ *
  • results[0]: the group name to store the file
+ *
  • results[1]: the new created filename
+ * return null if fail + */ + public String[] upload_file(String group_name, String master_filename, + String prefix_name, long file_size, UploadCallback callback, + String file_ext_name, NameValuePair[] meta_list) throws IOException, FastdfsException { + return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_SLAVE_FILE, group_name, master_filename, prefix_name, + file_ext_name, file_size, callback, meta_list); + } + + /** + * upload appender file to storage server (by file name) + * + * @param local_filename local filename to upload + * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename + * @param meta_list meta info array + * @return 2 elements string array if success:
+ *
  • results[0]: the group name to store the file
+ *
  • results[1]: the new created filename
+ * return null if fail + */ + public String[] upload_appender_file(String local_filename, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + final String group_name = null; + return this.upload_appender_file(group_name, local_filename, file_ext_name, meta_list); + } + + /** + * upload appender file to storage server (by file name) + * + * @param group_name the group name to upload file to, can be empty + * @param local_filename local filename to upload + * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename + * @param meta_list meta info array + * @return 2 elements string array if success:
+ *
  • results[0]: the group name to store the file
+ *
  • results[1]: the new created filename
+ * return null if fail + */ + protected String[] upload_appender_file(String group_name, String local_filename, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + final byte cmd = ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE; + return this.upload_file(cmd, group_name, local_filename, file_ext_name, meta_list); + } + + /** + * upload appender file to storage server (by file buff) + * + * @param file_buff file content/buff + * @param offset start offset of the buff + * @param length the length of buff to upload + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ *
  • results[0]: the group name to store the file
+ *
  • results[1]: the new created filename
+ * return null if fail + */ + public String[] upload_appender_file(byte[] file_buff, int offset, int length, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + final String group_name = null; + return this.upload_appender_file(group_name, file_buff, offset, length, file_ext_name, meta_list); + } + + /** + * upload appender file to storage server (by file buff) + * + * @param group_name the group name to upload file to, can be empty + * @param file_buff file content/buff + * @param offset start offset of the buff + * @param length the length of buff to upload + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ *
  • results[0]: the group name to store the file
+ *
  • results[1]: the new created filename
+ * return null if fail + */ + public String[] upload_appender_file(String group_name, byte[] file_buff, int offset, int length, + String file_ext_name, NameValuePair[] meta_list) throws IOException, FastdfsException { + return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE, group_name, null, null, file_ext_name, + length, new UploadBuff(file_buff, offset, length), meta_list); + } + + /** + * upload appender file to storage server (by file buff) + * + * @param file_buff file content/buff + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ *
  • results[0]: the group name to store the file
+ *
  • results[1]: the new created filename
+ * return null if fail + */ + public String[] upload_appender_file(byte[] file_buff, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + final String group_name = null; + return this.upload_appender_file(group_name, file_buff, 0, file_buff.length, file_ext_name, meta_list); + } + + /** + * upload appender file to storage server (by file buff) + * + * @param group_name the group name to upload file to, can be empty + * @param file_buff file content/buff + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ *
  • results[0]: the group name to store the file
+ *
  • results[1]: the new created filename
+ * return null if fail + */ + public String[] upload_appender_file(String group_name, byte[] file_buff, + String file_ext_name, NameValuePair[] meta_list) throws IOException, FastdfsException { + return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE, group_name, null, null, file_ext_name, + file_buff.length, new UploadBuff(file_buff, 0, file_buff.length), meta_list); + } + + /** + * upload appender file to storage server (by callback) + * + * @param group_name the group name to upload file to, can be empty + * @param file_size the file size + * @param callback the write data callback object + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return 2 elements string array if success:
+ *
  • results[0]: the group name to store the file
+ *
  • results[1]: the new created filename
+ * return null if fail + */ + public String[] upload_appender_file(String group_name, long file_size, UploadCallback callback, + String file_ext_name, NameValuePair[] meta_list) throws IOException, FastdfsException { + final String master_filename = null; + final String prefix_name = null; + + return this.do_upload_file(ProtoCommon.STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE, group_name, master_filename, prefix_name, + file_ext_name, file_size, callback, meta_list); + } + + /** + * append file to storage server (by file name) + * + * @param group_name the group name of appender file + * @param appender_filename the appender filename + * @param local_filename local filename to append + * @return 0 for success, != 0 for error (error no) + */ + public int append_file(String group_name, String appender_filename, String local_filename) throws IOException, FastdfsException { + File f = new File(local_filename); + FileInputStream fis = new FileInputStream(f); + + try { + return this.do_append_file(group_name, appender_filename, f.length(), new UploadStream(fis, f.length())); + } finally { + fis.close(); + } + } + + /** + * append file to storage server (by file buff) + * + * @param group_name the group name of appender file + * @param appender_filename the appender filename + * @param file_buff file content/buff + * @return 0 for success, != 0 for error (error no) + */ + public int append_file(String group_name, String appender_filename, byte[] file_buff) throws IOException, FastdfsException { + return this.do_append_file(group_name, appender_filename, file_buff.length, new UploadBuff(file_buff, 0, file_buff.length)); + } + + /** + * append file to storage server (by file buff) + * + * @param group_name the group name of appender file + * @param appender_filename the appender filename + * @param file_buff file content/buff + * @param offset start offset of the buff + * @param length the length of buff to append + * @return 0 for success, != 0 for error (error no) + */ + public int append_file(String group_name, String appender_filename, + byte[] file_buff, int offset, int length) throws IOException, FastdfsException { + return this.do_append_file(group_name, appender_filename, length, new UploadBuff(file_buff, offset, length)); + } + + /** + * append file to storage server (by callback) + * + * @param group_name the group name to append file to + * @param appender_filename the appender filename + * @param file_size the file size + * @param callback the write data callback object + * @return 0 for success, != 0 for error (error no) + */ + public int append_file(String group_name, String appender_filename, + long file_size, UploadCallback callback) throws IOException, FastdfsException { + return this.do_append_file(group_name, appender_filename, file_size, callback); + } + + /** + * modify appender file to storage server (by file name) + * + * @param group_name the group name of appender file + * @param appender_filename the appender filename + * @param file_offset the offset of appender file + * @param local_filename local filename to append + * @return 0 for success, != 0 for error (error no) + */ + public int modify_file(String group_name, String appender_filename, + long file_offset, String local_filename) throws IOException, FastdfsException { + File f = new File(local_filename); + FileInputStream fis = new FileInputStream(f); + + try { + return this.do_modify_file(group_name, appender_filename, file_offset, + f.length(), new UploadStream(fis, f.length())); + } finally { + fis.close(); + } + } + + /** + * modify appender file to storage server (by file buff) + * + * @param group_name the group name of appender file + * @param appender_filename the appender filename + * @param file_offset the offset of appender file + * @param file_buff file content/buff + * @return 0 for success, != 0 for error (error no) + */ + public int modify_file(String group_name, String appender_filename, + long file_offset, byte[] file_buff) throws IOException, FastdfsException { + return this.do_modify_file(group_name, appender_filename, file_offset, + file_buff.length, new UploadBuff(file_buff, 0, file_buff.length)); + } + + /** + * modify appender file to storage server (by file buff) + * + * @param group_name the group name of appender file + * @param appender_filename the appender filename + * @param file_offset the offset of appender file + * @param file_buff file content/buff + * @param buffer_offset start offset of the buff + * @param buffer_length the length of buff to modify + * @return 0 for success, != 0 for error (error no) + */ + public int modify_file(String group_name, String appender_filename, + long file_offset, byte[] file_buff, int buffer_offset, int buffer_length) throws IOException, FastdfsException { + return this.do_modify_file(group_name, appender_filename, file_offset, + buffer_length, new UploadBuff(file_buff, buffer_offset, buffer_length)); + } + + /** + * modify appender file to storage server (by callback) + * + * @param group_name the group name to modify file to + * @param appender_filename the appender filename + * @param file_offset the offset of appender file + * @param modify_size the modify size + * @param callback the write data callback object + * @return 0 for success, != 0 for error (error no) + */ + public int modify_file(String group_name, String appender_filename, + long file_offset, long modify_size, UploadCallback callback) throws IOException, FastdfsException { + return this.do_modify_file(group_name, appender_filename, file_offset, + modify_size, callback); + } + + /** + * upload file to storage server + * + * @param cmd the command code + * @param group_name the group name to upload file to, can be empty + * @param master_filename the master file name to generate the slave file + * @param prefix_name the prefix name to generate the slave file + * @param file_ext_name file ext name, do not include dot(.) + * @param file_size the file size + * @param callback the write data callback object + * @param meta_list meta info array + * @return 2 elements string array if success:
+ *
  • results[0]: the group name to store the file
+ *
  • results[1]: the new created filename
+ * return null if fail + */ + protected String[] do_upload_file(byte cmd, String group_name, String master_filename, + String prefix_name, String file_ext_name, long file_size, UploadCallback callback, + NameValuePair[] meta_list) throws IOException, FastdfsException { + byte[] header; + byte[] ext_name_bs; + String new_group_name; + String remote_filename; + boolean bNewConnection; + Socket storageSocket; + byte[] sizeBytes; + byte[] hexLenBytes; + byte[] masterFilenameBytes; + boolean bUploadSlave; + int offset; + long body_len; + + bUploadSlave = ((group_name != null && group_name.length() > 0) && + (master_filename != null && master_filename.length() > 0) && + (prefix_name != null)); + if (bUploadSlave) { + bNewConnection = this.newUpdatableStorageConnection(group_name, master_filename); + } else { + bNewConnection = this.newWritableStorageConnection(group_name); + } + + try { + storageSocket = this.storageServer.getSocket(); + + ext_name_bs = new byte[ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN]; + Arrays.fill(ext_name_bs, (byte) 0); + if (file_ext_name != null && file_ext_name.length() > 0) { + byte[] bs = file_ext_name.getBytes(ClientGlobal.g_charset); + int ext_name_len = bs.length; + if (ext_name_len > ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN) { + ext_name_len = ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN; + } + System.arraycopy(bs, 0, ext_name_bs, 0, ext_name_len); + } + + if (bUploadSlave) { + masterFilenameBytes = master_filename.getBytes(ClientGlobal.g_charset); + + sizeBytes = new byte[2 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE]; + body_len = sizeBytes.length + ProtoCommon.FDFS_FILE_PREFIX_MAX_LEN + ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + + masterFilenameBytes.length + file_size; + + hexLenBytes = ProtoCommon.long2buff(master_filename.length()); + System.arraycopy(hexLenBytes, 0, sizeBytes, 0, hexLenBytes.length); + offset = hexLenBytes.length; + } else { + masterFilenameBytes = null; + sizeBytes = new byte[1 + 1 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE]; + body_len = sizeBytes.length + ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + file_size; + + sizeBytes[0] = (byte) this.storageServer.getStorePathIndex(); + offset = 1; + } + + hexLenBytes = ProtoCommon.long2buff(file_size); + System.arraycopy(hexLenBytes, 0, sizeBytes, offset, hexLenBytes.length); + + OutputStream out = storageSocket.getOutputStream(); + header = ProtoCommon.packHeader(cmd, body_len, (byte) 0); + byte[] wholePkg = new byte[(int) (header.length + body_len - file_size)]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + System.arraycopy(sizeBytes, 0, wholePkg, header.length, sizeBytes.length); + offset = header.length + sizeBytes.length; + if (bUploadSlave) { + byte[] prefix_name_bs = new byte[ProtoCommon.FDFS_FILE_PREFIX_MAX_LEN]; + byte[] bs = prefix_name.getBytes(ClientGlobal.g_charset); + int prefix_name_len = bs.length; + Arrays.fill(prefix_name_bs, (byte) 0); + if (prefix_name_len > ProtoCommon.FDFS_FILE_PREFIX_MAX_LEN) { + prefix_name_len = ProtoCommon.FDFS_FILE_PREFIX_MAX_LEN; + } + if (prefix_name_len > 0) { + System.arraycopy(bs, 0, prefix_name_bs, 0, prefix_name_len); + } + + System.arraycopy(prefix_name_bs, 0, wholePkg, offset, prefix_name_bs.length); + offset += prefix_name_bs.length; + } + + System.arraycopy(ext_name_bs, 0, wholePkg, offset, ext_name_bs.length); + offset += ext_name_bs.length; + + if (bUploadSlave) { + System.arraycopy(masterFilenameBytes, 0, wholePkg, offset, masterFilenameBytes.length); + offset += masterFilenameBytes.length; + } + + out.write(wholePkg); + + if ((this.errno = (byte) callback.send(out)) != 0) { + return null; + } + + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(storageSocket.getInputStream(), + ProtoCommon.STORAGE_PROTO_CMD_RESP, -1); + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return null; + } + + if (pkgInfo.body.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) { + throw new FastdfsException("body length: " + pkgInfo.body.length + " <= " + ProtoCommon.FDFS_GROUP_NAME_MAX_LEN); + } + + new_group_name = new String(pkgInfo.body, 0, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN).trim(); + remote_filename = new String(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN, pkgInfo.body.length - ProtoCommon.FDFS_GROUP_NAME_MAX_LEN); + String[] results = new String[2]; + results[0] = new_group_name; + results[1] = remote_filename; + + if (meta_list == null || meta_list.length == 0) { + return results; + } + + int result = 0; + try { + result = this.set_metadata(new_group_name, remote_filename, + meta_list, ProtoCommon.STORAGE_SET_METADATA_FLAG_OVERWRITE); + } catch (IOException ex) { + result = 5; + throw ex; + } finally { + if (result != 0) { + this.errno = (byte) result; + this.delete_file(new_group_name, remote_filename); + return null; + } + } + + return results; + } catch (IOException ex) { + if (!bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + + throw ex; + } finally { + if (bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + } + } + + /** + * append file to storage server + * + * @param group_name the group name of appender file + * @param appender_filename the appender filename + * @param file_size the file size + * @param callback the write data callback object + * @return return true for success, false for fail + */ + protected int do_append_file(String group_name, String appender_filename, + long file_size, UploadCallback callback) throws IOException, FastdfsException { + byte[] header; + boolean bNewConnection; + Socket storageSocket; + byte[] hexLenBytes; + byte[] appenderFilenameBytes; + int offset; + long body_len; + + if ((group_name == null || group_name.length() == 0) || + (appender_filename == null || appender_filename.length() == 0)) { + this.errno = ProtoCommon.ERR_NO_EINVAL; + return this.errno; + } + + bNewConnection = this.newUpdatableStorageConnection(group_name, appender_filename); + + try { + storageSocket = this.storageServer.getSocket(); + + appenderFilenameBytes = appender_filename.getBytes(ClientGlobal.g_charset); + body_len = 2 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE + appenderFilenameBytes.length + file_size; + + header = ProtoCommon.packHeader(ProtoCommon.STORAGE_PROTO_CMD_APPEND_FILE, body_len, (byte) 0); + byte[] wholePkg = new byte[(int) (header.length + body_len - file_size)]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + offset = header.length; + + hexLenBytes = ProtoCommon.long2buff(appender_filename.length()); + System.arraycopy(hexLenBytes, 0, wholePkg, offset, hexLenBytes.length); + offset += hexLenBytes.length; + + hexLenBytes = ProtoCommon.long2buff(file_size); + System.arraycopy(hexLenBytes, 0, wholePkg, offset, hexLenBytes.length); + offset += hexLenBytes.length; + + OutputStream out = storageSocket.getOutputStream(); + + System.arraycopy(appenderFilenameBytes, 0, wholePkg, offset, appenderFilenameBytes.length); + offset += appenderFilenameBytes.length; + + out.write(wholePkg); + if ((this.errno = (byte) callback.send(out)) != 0) { + return this.errno; + } + + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(storageSocket.getInputStream(), + ProtoCommon.STORAGE_PROTO_CMD_RESP, 0); + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return this.errno; + } + + return 0; + } catch (IOException ex) { + if (!bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + + throw ex; + } finally { + if (bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + } + } + + /** + * modify appender file to storage server + * + * @param group_name the group name of appender file + * @param appender_filename the appender filename + * @param file_offset the offset of appender file + * @param modify_size the modify size + * @param callback the write data callback object + * @return return true for success, false for fail + */ + protected int do_modify_file(String group_name, String appender_filename, + long file_offset, long modify_size, UploadCallback callback) throws IOException, FastdfsException { + byte[] header; + boolean bNewConnection; + Socket storageSocket; + byte[] hexLenBytes; + byte[] appenderFilenameBytes; + int offset; + long body_len; + + if ((group_name == null || group_name.length() == 0) || + (appender_filename == null || appender_filename.length() == 0)) { + this.errno = ProtoCommon.ERR_NO_EINVAL; + return this.errno; + } + + bNewConnection = this.newUpdatableStorageConnection(group_name, appender_filename); + + try { + storageSocket = this.storageServer.getSocket(); + + appenderFilenameBytes = appender_filename.getBytes(ClientGlobal.g_charset); + body_len = 3 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE + appenderFilenameBytes.length + modify_size; + + header = ProtoCommon.packHeader(ProtoCommon.STORAGE_PROTO_CMD_MODIFY_FILE, body_len, (byte) 0); + byte[] wholePkg = new byte[(int) (header.length + body_len - modify_size)]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + offset = header.length; + + hexLenBytes = ProtoCommon.long2buff(appender_filename.length()); + System.arraycopy(hexLenBytes, 0, wholePkg, offset, hexLenBytes.length); + offset += hexLenBytes.length; + + hexLenBytes = ProtoCommon.long2buff(file_offset); + System.arraycopy(hexLenBytes, 0, wholePkg, offset, hexLenBytes.length); + offset += hexLenBytes.length; + + hexLenBytes = ProtoCommon.long2buff(modify_size); + System.arraycopy(hexLenBytes, 0, wholePkg, offset, hexLenBytes.length); + offset += hexLenBytes.length; + + OutputStream out = storageSocket.getOutputStream(); + + System.arraycopy(appenderFilenameBytes, 0, wholePkg, offset, appenderFilenameBytes.length); + offset += appenderFilenameBytes.length; + + out.write(wholePkg); + if ((this.errno = (byte) callback.send(out)) != 0) { + return this.errno; + } + + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(storageSocket.getInputStream(), + ProtoCommon.STORAGE_PROTO_CMD_RESP, 0); + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return this.errno; + } + + return 0; + } catch (IOException ex) { + if (!bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + + throw ex; + } finally { + if (bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + } + } + + /** + * delete file from storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @return 0 for success, none zero for fail (error code) + */ + public int delete_file(String group_name, String remote_filename) throws IOException, FastdfsException { + boolean bNewConnection = this.newUpdatableStorageConnection(group_name, remote_filename); + Socket storageSocket = this.storageServer.getSocket(); + + try { + this.send_package(ProtoCommon.STORAGE_PROTO_CMD_DELETE_FILE, group_name, remote_filename); + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(storageSocket.getInputStream(), + ProtoCommon.STORAGE_PROTO_CMD_RESP, 0); + + this.errno = pkgInfo.errno; + return pkgInfo.errno; + } catch (IOException ex) { + if (!bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + + throw ex; + } finally { + if (bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + } + } + + /** + * truncate appender file to size 0 from storage server + * + * @param group_name the group name of storage server + * @param appender_filename the appender filename + * @return 0 for success, none zero for fail (error code) + */ + public int truncate_file(String group_name, String appender_filename) throws IOException, FastdfsException { + final long truncated_file_size = 0; + return this.truncate_file(group_name, appender_filename, truncated_file_size); + } + + /** + * truncate appender file from storage server + * + * @param group_name the group name of storage server + * @param appender_filename the appender filename + * @param truncated_file_size truncated file size + * @return 0 for success, none zero for fail (error code) + */ + public int truncate_file(String group_name, String appender_filename, + long truncated_file_size) throws IOException, FastdfsException { + byte[] header; + boolean bNewConnection; + Socket storageSocket; + byte[] hexLenBytes; + byte[] appenderFilenameBytes; + int offset; + int body_len; + + if ((group_name == null || group_name.length() == 0) || + (appender_filename == null || appender_filename.length() == 0)) { + this.errno = ProtoCommon.ERR_NO_EINVAL; + return this.errno; + } + + bNewConnection = this.newUpdatableStorageConnection(group_name, appender_filename); + + try { + storageSocket = this.storageServer.getSocket(); + + appenderFilenameBytes = appender_filename.getBytes(ClientGlobal.g_charset); + body_len = 2 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE + appenderFilenameBytes.length; + + header = ProtoCommon.packHeader(ProtoCommon.STORAGE_PROTO_CMD_TRUNCATE_FILE, body_len, (byte) 0); + byte[] wholePkg = new byte[header.length + body_len]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + offset = header.length; + + hexLenBytes = ProtoCommon.long2buff(appender_filename.length()); + System.arraycopy(hexLenBytes, 0, wholePkg, offset, hexLenBytes.length); + offset += hexLenBytes.length; + + hexLenBytes = ProtoCommon.long2buff(truncated_file_size); + System.arraycopy(hexLenBytes, 0, wholePkg, offset, hexLenBytes.length); + offset += hexLenBytes.length; + + OutputStream out = storageSocket.getOutputStream(); + + System.arraycopy(appenderFilenameBytes, 0, wholePkg, offset, appenderFilenameBytes.length); + offset += appenderFilenameBytes.length; + + out.write(wholePkg); + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(storageSocket.getInputStream(), + ProtoCommon.STORAGE_PROTO_CMD_RESP, 0); + this.errno = pkgInfo.errno; + return pkgInfo.errno; + } catch (IOException ex) { + if (!bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + + throw ex; + } finally { + if (bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + } + } + + /** + * download file from storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @return file content/buff, return null if fail + */ + public byte[] download_file(String group_name, String remote_filename) throws IOException, FastdfsException { + final long file_offset = 0; + final long download_bytes = 0; + + return this.download_file(group_name, remote_filename, file_offset, download_bytes); + } + + /** + * download file from storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @param file_offset the start offset of the file + * @param download_bytes download bytes, 0 for remain bytes from offset + * @return file content/buff, return null if fail + */ + public byte[] download_file(String group_name, String remote_filename, long file_offset, long download_bytes) throws IOException, FastdfsException { + boolean bNewConnection = this.newReadableStorageConnection(group_name, remote_filename); + Socket storageSocket = this.storageServer.getSocket(); + + try { + ProtoCommon.RecvPackageInfo pkgInfo; + + this.send_download_package(group_name, remote_filename, file_offset, download_bytes); + pkgInfo = ProtoCommon.recvPackage(storageSocket.getInputStream(), + ProtoCommon.STORAGE_PROTO_CMD_RESP, -1); + + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return null; + } + + return pkgInfo.body; + } catch (IOException ex) { + if (!bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + + throw ex; + } finally { + if (bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + } + } + + /** + * download file from storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @param local_filename filename on local + * @return 0 success, return none zero errno if fail + */ + public int download_file(String group_name, String remote_filename, + String local_filename) throws IOException, FastdfsException { + final long file_offset = 0; + final long download_bytes = 0; + return this.download_file(group_name, remote_filename, + file_offset, download_bytes, local_filename); + } + + /** + * download file from storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @param file_offset the start offset of the file + * @param download_bytes download bytes, 0 for remain bytes from offset + * @param local_filename filename on local + * @return 0 success, return none zero errno if fail + */ + public int download_file(String group_name, String remote_filename, + long file_offset, long download_bytes, + String local_filename) throws IOException, FastdfsException { + boolean bNewConnection = this.newReadableStorageConnection(group_name, remote_filename); + Socket storageSocket = this.storageServer.getSocket(); + try { + ProtoCommon.RecvHeaderInfo header; + FileOutputStream out = new FileOutputStream(local_filename); + try { + this.errno = 0; + this.send_download_package(group_name, remote_filename, file_offset, download_bytes); + + InputStream in = storageSocket.getInputStream(); + header = ProtoCommon.recvHeader(in, ProtoCommon.STORAGE_PROTO_CMD_RESP, -1); + this.errno = header.errno; + if (header.errno != 0) { + return header.errno; + } + + byte[] buff = new byte[256 * 1024]; + long remainBytes = header.body_len; + int bytes; + + //System.out.println("expect_body_len=" + header.body_len); + + while (remainBytes > 0) { + if ((bytes = in.read(buff, 0, remainBytes > buff.length ? buff.length : (int) remainBytes)) < 0) { + throw new IOException("recv package size " + (header.body_len - remainBytes) + " != " + header.body_len); + } + + out.write(buff, 0, bytes); + remainBytes -= bytes; + + //System.out.println("totalBytes=" + (header.body_len - remainBytes)); + } + + return 0; + } catch (IOException ex) { + if (this.errno == 0) { + this.errno = ProtoCommon.ERR_NO_EIO; + } + + throw ex; + } finally { + out.close(); + if (this.errno != 0) { + (new File(local_filename)).delete(); + } + } + } catch (IOException ex) { + if (!bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + + throw ex; + } finally { + if (bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + } + } + + /** + * download file from storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @param callback call callback.recv() when data arrive + * @return 0 success, return none zero errno if fail + */ + public int download_file(String group_name, String remote_filename, + DownloadCallback callback) throws IOException, FastdfsException { + final long file_offset = 0; + final long download_bytes = 0; + return this.download_file(group_name, remote_filename, + file_offset, download_bytes, callback); + } + + /** + * download file from storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @param file_offset the start offset of the file + * @param download_bytes download bytes, 0 for remain bytes from offset + * @param callback call callback.recv() when data arrive + * @return 0 success, return none zero errno if fail + */ + public int download_file(String group_name, String remote_filename, + long file_offset, long download_bytes, + DownloadCallback callback) throws IOException, FastdfsException { + int result; + boolean bNewConnection = this.newReadableStorageConnection(group_name, remote_filename); + Socket storageSocket = this.storageServer.getSocket(); + + try { + ProtoCommon.RecvHeaderInfo header; + this.send_download_package(group_name, remote_filename, file_offset, download_bytes); + + InputStream in = storageSocket.getInputStream(); + header = ProtoCommon.recvHeader(in, ProtoCommon.STORAGE_PROTO_CMD_RESP, -1); + this.errno = header.errno; + if (header.errno != 0) { + return header.errno; + } + + byte[] buff = new byte[2 * 1024]; + long remainBytes = header.body_len; + int bytes; + + //System.out.println("expect_body_len=" + header.body_len); + + while (remainBytes > 0) { + if ((bytes = in.read(buff, 0, remainBytes > buff.length ? buff.length : (int) remainBytes)) < 0) { + throw new IOException("recv package size " + (header.body_len - remainBytes) + " != " + header.body_len); + } + + if ((result = callback.recv(header.body_len, buff, bytes)) != 0) { + this.errno = (byte) result; + return result; + } + + remainBytes -= bytes; + //System.out.println("totalBytes=" + (header.body_len - remainBytes)); + } + + return 0; + } catch (IOException ex) { + if (!bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + + throw ex; + } finally { + if (bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + } + } + + /** + * get all metadata items from storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @return meta info array, return null if fail + */ + public NameValuePair[] get_metadata(String group_name, String remote_filename) throws IOException, FastdfsException { + boolean bNewConnection = this.newUpdatableStorageConnection(group_name, remote_filename); + Socket storageSocket = this.storageServer.getSocket(); + + try { + ProtoCommon.RecvPackageInfo pkgInfo; + + this.send_package(ProtoCommon.STORAGE_PROTO_CMD_GET_METADATA, group_name, remote_filename); + pkgInfo = ProtoCommon.recvPackage(storageSocket.getInputStream(), + ProtoCommon.STORAGE_PROTO_CMD_RESP, -1); + + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return null; + } + + return ProtoCommon.split_metadata(new String(pkgInfo.body, ClientGlobal.g_charset)); + } catch (IOException ex) { + if (!bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + + throw ex; + } finally { + if (bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + } + } + + /** + * set metadata items to storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @param meta_list meta item array + * @param op_flag flag, can be one of following values:
+ *
  • ProtoCommon.STORAGE_SET_METADATA_FLAG_OVERWRITE: overwrite all old + * metadata items
+ *
  • ProtoCommon.STORAGE_SET_METADATA_FLAG_MERGE: merge, insert when + * the metadata item not exist, otherwise update it
+ * @return 0 for success, !=0 fail (error code) + */ + public int set_metadata(String group_name, String remote_filename, + NameValuePair[] meta_list, byte op_flag) throws IOException, FastdfsException { + boolean bNewConnection = this.newUpdatableStorageConnection(group_name, remote_filename); + Socket storageSocket = this.storageServer.getSocket(); + + try { + byte[] header; + byte[] groupBytes; + byte[] filenameBytes; + byte[] meta_buff; + byte[] bs; + int groupLen; + byte[] sizeBytes; + ProtoCommon.RecvPackageInfo pkgInfo; + + if (meta_list == null) { + meta_buff = new byte[0]; + } else { + meta_buff = ProtoCommon.pack_metadata(meta_list).getBytes(ClientGlobal.g_charset); + } + + filenameBytes = remote_filename.getBytes(ClientGlobal.g_charset); + sizeBytes = new byte[2 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE]; + Arrays.fill(sizeBytes, (byte) 0); + + bs = ProtoCommon.long2buff(filenameBytes.length); + System.arraycopy(bs, 0, sizeBytes, 0, bs.length); + bs = ProtoCommon.long2buff(meta_buff.length); + System.arraycopy(bs, 0, sizeBytes, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE, bs.length); + + groupBytes = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; + bs = group_name.getBytes(ClientGlobal.g_charset); + + Arrays.fill(groupBytes, (byte) 0); + if (bs.length <= groupBytes.length) { + groupLen = bs.length; + } else { + groupLen = groupBytes.length; + } + System.arraycopy(bs, 0, groupBytes, 0, groupLen); + + header = ProtoCommon.packHeader(ProtoCommon.STORAGE_PROTO_CMD_SET_METADATA, + 2 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE + 1 + groupBytes.length + + filenameBytes.length + meta_buff.length, (byte) 0); + OutputStream out = storageSocket.getOutputStream(); + byte[] wholePkg = new byte[header.length + sizeBytes.length + 1 + groupBytes.length + filenameBytes.length]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + System.arraycopy(sizeBytes, 0, wholePkg, header.length, sizeBytes.length); + wholePkg[header.length + sizeBytes.length] = op_flag; + System.arraycopy(groupBytes, 0, wholePkg, header.length + sizeBytes.length + 1, groupBytes.length); + System.arraycopy(filenameBytes, 0, wholePkg, header.length + sizeBytes.length + 1 + groupBytes.length, filenameBytes.length); + out.write(wholePkg); + if (meta_buff.length > 0) { + out.write(meta_buff); + } + + pkgInfo = ProtoCommon.recvPackage(storageSocket.getInputStream(), + ProtoCommon.STORAGE_PROTO_CMD_RESP, 0); + + this.errno = pkgInfo.errno; + return pkgInfo.errno; + } catch (IOException ex) { + if (!bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + + throw ex; + } finally { + if (bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + } + } + + /** + * get file info decoded from the filename, fetch from the storage if necessary + * + * @param group_name the group name + * @param remote_filename the filename + * @return FileInfo object for success, return null for fail + */ + public FileInfo get_file_info(String group_name, String remote_filename) throws IOException, FastdfsException { + if (remote_filename.length() < ProtoCommon.FDFS_FILE_PATH_LEN + ProtoCommon.FDFS_FILENAME_BASE64_LENGTH + + ProtoCommon.FDFS_FILE_EXT_NAME_MAX_LEN + 1) { + this.errno = ProtoCommon.ERR_NO_EINVAL; + return null; + } + + byte[] buff = base64.decodeAuto(remote_filename.substring(ProtoCommon.FDFS_FILE_PATH_LEN, + ProtoCommon.FDFS_FILE_PATH_LEN + ProtoCommon.FDFS_FILENAME_BASE64_LENGTH)); + + long file_size = ProtoCommon.buff2long(buff, 4 * 2); + if (((remote_filename.length() > ProtoCommon.TRUNK_LOGIC_FILENAME_LENGTH) || + ((remote_filename.length() > ProtoCommon.NORMAL_LOGIC_FILENAME_LENGTH) && ((file_size & ProtoCommon.TRUNK_FILE_MARK_SIZE) == 0))) || + ((file_size & ProtoCommon.APPENDER_FILE_SIZE) != 0)) { //slave file or appender file + FileInfo fi = this.query_file_info(group_name, remote_filename); + if (fi == null) { + return null; + } + return fi; + } + + FileInfo fileInfo = new FileInfo(file_size, 0, 0, ProtoCommon.getIpAddress(buff, 0)); + fileInfo.setCreateTimestamp(ProtoCommon.buff2int(buff, 4)); + if ((file_size >> 63) != 0) { + file_size &= 0xFFFFFFFFL; //low 32 bits is file size + fileInfo.setFileSize(file_size); + } + fileInfo.setCrc32(ProtoCommon.buff2int(buff, 4 * 4)); + + return fileInfo; + } + + /** + * get file info from storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @return FileInfo object for success, return null for fail + */ + public FileInfo query_file_info(String group_name, String remote_filename) throws IOException, FastdfsException { + boolean bNewConnection = this.newUpdatableStorageConnection(group_name, remote_filename); + Socket storageSocket = this.storageServer.getSocket(); + + try { + byte[] header; + byte[] groupBytes; + byte[] filenameBytes; + byte[] bs; + int groupLen; + ProtoCommon.RecvPackageInfo pkgInfo; + + filenameBytes = remote_filename.getBytes(ClientGlobal.g_charset); + groupBytes = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; + bs = group_name.getBytes(ClientGlobal.g_charset); + + Arrays.fill(groupBytes, (byte) 0); + if (bs.length <= groupBytes.length) { + groupLen = bs.length; + } else { + groupLen = groupBytes.length; + } + System.arraycopy(bs, 0, groupBytes, 0, groupLen); + + header = ProtoCommon.packHeader(ProtoCommon.STORAGE_PROTO_CMD_QUERY_FILE_INFO, + +groupBytes.length + filenameBytes.length, (byte) 0); + OutputStream out = storageSocket.getOutputStream(); + byte[] wholePkg = new byte[header.length + groupBytes.length + filenameBytes.length]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + System.arraycopy(groupBytes, 0, wholePkg, header.length, groupBytes.length); + System.arraycopy(filenameBytes, 0, wholePkg, header.length + groupBytes.length, filenameBytes.length); + out.write(wholePkg); + + pkgInfo = ProtoCommon.recvPackage(storageSocket.getInputStream(), + ProtoCommon.STORAGE_PROTO_CMD_RESP, + 3 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE + + ProtoCommon.FDFS_IPADDR_SIZE); + + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return null; + } + + long file_size = ProtoCommon.buff2long(pkgInfo.body, 0); + int create_timestamp = (int) ProtoCommon.buff2long(pkgInfo.body, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + int crc32 = (int) ProtoCommon.buff2long(pkgInfo.body, 2 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + String source_ip_addr = (new String(pkgInfo.body, 3 * ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE, ProtoCommon.FDFS_IPADDR_SIZE)).trim(); + return new FileInfo(file_size, create_timestamp, crc32, source_ip_addr); + } catch (IOException ex) { + if (!bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + + throw ex; + } finally { + if (bNewConnection) { + try { + this.storageServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } finally { + this.storageServer = null; + } + } + } + } + + /** + * check storage socket, if null create a new connection + * + * @param group_name the group name to upload file to, can be empty + * @return true if create a new connection + */ + protected boolean newWritableStorageConnection(String group_name) throws IOException, FastdfsException { + if (this.storageServer != null) { + return false; + } else { + TrackerClient tracker = new TrackerClient(); + this.storageServer = tracker.getStoreStorage(this.trackerServer, group_name); + if (this.storageServer == null) { + throw new FastdfsException("getStoreStorage fail, errno code: " + tracker.getErrorCode()); + } + return true; + } + } + + /** + * check storage socket, if null create a new connection + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @return true if create a new connection + */ + protected boolean newReadableStorageConnection(String group_name, String remote_filename) throws IOException, FastdfsException { + if (this.storageServer != null) { + return false; + } else { + TrackerClient tracker = new TrackerClient(); + this.storageServer = tracker.getFetchStorage(this.trackerServer, group_name, remote_filename); + if (this.storageServer == null) { + throw new FastdfsException("getStoreStorage fail, errno code: " + tracker.getErrorCode()); + } + return true; + } + } + + /** + * check storage socket, if null create a new connection + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @return true if create a new connection + */ + protected boolean newUpdatableStorageConnection(String group_name, String remote_filename) throws IOException, FastdfsException { + if (this.storageServer != null) { + return false; + } else { + TrackerClient tracker = new TrackerClient(); + this.storageServer = tracker.getUpdateStorage(this.trackerServer, group_name, remote_filename); + if (this.storageServer == null) { + throw new FastdfsException("getStoreStorage fail, errno code: " + tracker.getErrorCode()); + } + return true; + } + } + + /** + * send package to storage server + * + * @param cmd which command to send + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + */ + protected void send_package(byte cmd, String group_name, String remote_filename) throws IOException { + byte[] header; + byte[] groupBytes; + byte[] filenameBytes; + byte[] bs; + int groupLen; + + groupBytes = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; + bs = group_name.getBytes(ClientGlobal.g_charset); + filenameBytes = remote_filename.getBytes(ClientGlobal.g_charset); + + Arrays.fill(groupBytes, (byte) 0); + if (bs.length <= groupBytes.length) { + groupLen = bs.length; + } else { + groupLen = groupBytes.length; + } + System.arraycopy(bs, 0, groupBytes, 0, groupLen); + + header = ProtoCommon.packHeader(cmd, groupBytes.length + filenameBytes.length, (byte) 0); + byte[] wholePkg = new byte[header.length + groupBytes.length + filenameBytes.length]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + System.arraycopy(groupBytes, 0, wholePkg, header.length, groupBytes.length); + System.arraycopy(filenameBytes, 0, wholePkg, header.length + groupBytes.length, filenameBytes.length); + this.storageServer.getSocket().getOutputStream().write(wholePkg); + } + + /** + * send package to storage server + * + * @param group_name the group name of storage server + * @param remote_filename filename on storage server + * @param file_offset the start offset of the file + * @param download_bytes download bytes + */ + protected void send_download_package(String group_name, String remote_filename, long file_offset, long download_bytes) throws IOException { + byte[] header; + byte[] bsOffset; + byte[] bsDownBytes; + byte[] groupBytes; + byte[] filenameBytes; + byte[] bs; + int groupLen; + + bsOffset = ProtoCommon.long2buff(file_offset); + bsDownBytes = ProtoCommon.long2buff(download_bytes); + groupBytes = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; + bs = group_name.getBytes(ClientGlobal.g_charset); + filenameBytes = remote_filename.getBytes(ClientGlobal.g_charset); + + Arrays.fill(groupBytes, (byte) 0); + if (bs.length <= groupBytes.length) { + groupLen = bs.length; + } else { + groupLen = groupBytes.length; + } + System.arraycopy(bs, 0, groupBytes, 0, groupLen); + + header = ProtoCommon.packHeader(ProtoCommon.STORAGE_PROTO_CMD_DOWNLOAD_FILE, + bsOffset.length + bsDownBytes.length + groupBytes.length + filenameBytes.length, (byte) 0); + byte[] wholePkg = new byte[header.length + bsOffset.length + bsDownBytes.length + groupBytes.length + filenameBytes.length]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + System.arraycopy(bsOffset, 0, wholePkg, header.length, bsOffset.length); + System.arraycopy(bsDownBytes, 0, wholePkg, header.length + bsOffset.length, bsDownBytes.length); + System.arraycopy(groupBytes, 0, wholePkg, header.length + bsOffset.length + bsDownBytes.length, groupBytes.length); + System.arraycopy(filenameBytes, 0, wholePkg, header.length + bsOffset.length + bsDownBytes.length + groupBytes.length, filenameBytes.length); + this.storageServer.getSocket().getOutputStream().write(wholePkg); + } + + /** + * Upload file by file buff + * + * @author Happy Fish / YuQing + * @version Version 1.12 + */ + public static class UploadBuff implements UploadCallback { + private byte[] fileBuff; + private int offset; + private int length; + + /** + * constructor + * + * @param fileBuff the file buff for uploading + */ + public UploadBuff(byte[] fileBuff, int offset, int length) { + super(); + this.fileBuff = fileBuff; + this.offset = offset; + this.length = length; + } + + /** + * send file content callback function, be called only once when the file uploaded + * + * @param out output stream for writing file content + * @return 0 success, return none zero(errno) if fail + */ + public int send(OutputStream out) throws IOException { + out.write(this.fileBuff, this.offset, this.length); + + return 0; + } + } +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/StorageClient1.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/StorageClient1.java new file mode 100644 index 000000000..87de70325 --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/StorageClient1.java @@ -0,0 +1,732 @@ +/** + * Copyright (C) 2008 Happy Fish / YuQing + *

+ * FastDFS Java Client may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. + */ + +package org.csource.fastdfs; + +import org.csource.common.FastdfsException; +import org.csource.common.NameValuePair; + +import java.io.IOException; + +/** + * Storage client for 1 field file id: combined group name and filename + * + * @author Happy Fish / YuQing + * @version Version 1.21 + */ +public class StorageClient1 extends StorageClient { + public static final String SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR = "/"; + + /** + * constructor + */ + public StorageClient1() { + super(); + } + + /** + * constructor + * + * @param trackerServer the tracker server, can be null + * @param storageServer the storage server, can be null + */ + public StorageClient1(TrackerServer trackerServer, StorageServer storageServer) { + super(trackerServer, storageServer); + } + + public static byte split_file_id(String file_id, String[] results) { + int pos = file_id.indexOf(SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR); + if ((pos <= 0) || (pos == file_id.length() - 1)) { + return ProtoCommon.ERR_NO_EINVAL; + } + + results[0] = file_id.substring(0, pos); //group name + results[1] = file_id.substring(pos + 1); //file name + return 0; + } + + /** + * upload file to storage server (by file name) + * + * @param local_filename local filename to upload + * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename + * @param meta_list meta info array + * @return file id(including group name and filename) if success,
+ * return null if fail + */ + public String upload_file1(String local_filename, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + String parts[] = this.upload_file(local_filename, file_ext_name, meta_list); + if (parts != null) { + return parts[0] + SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR + parts[1]; + } else { + return null; + } + } + + /** + * upload file to storage server (by file name) + * + * @param group_name the group name to upload file to, can be empty + * @param local_filename local filename to upload + * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename + * @param meta_list meta info array + * @return file id(including group name and filename) if success,
+ * return null if fail + */ + public String upload_file1(String group_name, String local_filename, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + String parts[] = this.upload_file(group_name, local_filename, file_ext_name, meta_list); + if (parts != null) { + return parts[0] + SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR + parts[1]; + } else { + return null; + } + } + + /** + * upload file to storage server (by file buff) + * + * @param file_buff file content/buff + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return file id(including group name and filename) if success,
+ * return null if fail + */ + public String upload_file1(byte[] file_buff, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + String parts[] = this.upload_file(file_buff, file_ext_name, meta_list); + if (parts != null) { + return parts[0] + SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR + parts[1]; + } else { + return null; + } + } + + /** + * upload file to storage server (by file buff) + * + * @param group_name the group name to upload file to, can be empty + * @param file_buff file content/buff + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return file id(including group name and filename) if success,
+ * return null if fail + */ + public String upload_file1(String group_name, byte[] file_buff, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + String parts[] = this.upload_file(group_name, file_buff, file_ext_name, meta_list); + if (parts != null) { + return parts[0] + SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR + parts[1]; + } else { + return null; + } + } + + /** + * upload file to storage server (by callback) + * + * @param group_name the group name to upload file to, can be empty + * @param file_size the file size + * @param callback the write data callback object + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return file id(including group name and filename) if success,
+ * return null if fail + */ + public String upload_file1(String group_name, long file_size, + UploadCallback callback, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + String parts[] = this.upload_file(group_name, file_size, callback, file_ext_name, meta_list); + if (parts != null) { + return parts[0] + SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR + parts[1]; + } else { + return null; + } + } + + /** + * upload appender file to storage server (by file name) + * + * @param local_filename local filename to upload + * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename + * @param meta_list meta info array + * @return file id(including group name and filename) if success,
+ * return null if fail + */ + public String upload_appender_file1(String local_filename, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + String parts[] = this.upload_appender_file(local_filename, file_ext_name, meta_list); + if (parts != null) { + return parts[0] + SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR + parts[1]; + } else { + return null; + } + } + + /** + * upload appender file to storage server (by file name) + * + * @param group_name the group name to upload file to, can be empty + * @param local_filename local filename to upload + * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename + * @param meta_list meta info array + * @return file id(including group name and filename) if success,
+ * return null if fail + */ + public String upload_appender_file1(String group_name, String local_filename, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + String parts[] = this.upload_appender_file(group_name, local_filename, file_ext_name, meta_list); + if (parts != null) { + return parts[0] + SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR + parts[1]; + } else { + return null; + } + } + + /** + * upload appender file to storage server (by file buff) + * + * @param file_buff file content/buff + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return file id(including group name and filename) if success,
+ * return null if fail + */ + public String upload_appender_file1(byte[] file_buff, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + String parts[] = this.upload_appender_file(file_buff, file_ext_name, meta_list); + if (parts != null) { + return parts[0] + SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR + parts[1]; + } else { + return null; + } + } + + /** + * upload appender file to storage server (by file buff) + * + * @param group_name the group name to upload file to, can be empty + * @param file_buff file content/buff + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return file id(including group name and filename) if success,
+ * return null if fail + */ + public String upload_appender_file1(String group_name, byte[] file_buff, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + String parts[] = this.upload_appender_file(group_name, file_buff, file_ext_name, meta_list); + if (parts != null) { + return parts[0] + SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR + parts[1]; + } else { + return null; + } + } + + /** + * upload appender file to storage server (by callback) + * + * @param group_name the group name to upload file to, can be empty + * @param file_size the file size + * @param callback the write data callback object + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return file id(including group name and filename) if success,
+ * return null if fail + */ + public String upload_appender_file1(String group_name, long file_size, + UploadCallback callback, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + String parts[] = this.upload_appender_file(group_name, file_size, callback, file_ext_name, meta_list); + if (parts != null) { + return parts[0] + SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR + parts[1]; + } else { + return null; + } + } + + /** + * upload file to storage server (by file name, slave file mode) + * + * @param master_file_id the master file id to generate the slave file + * @param prefix_name the prefix name to generate the slave file + * @param local_filename local filename to upload + * @param file_ext_name file ext name, do not include dot(.), null to extract ext name from the local filename + * @param meta_list meta info array + * @return file id(including group name and filename) if success,
+ * return null if fail + */ + public String upload_file1(String master_file_id, String prefix_name, + String local_filename, String file_ext_name, NameValuePair[] meta_list) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(master_file_id, parts); + if (this.errno != 0) { + return null; + } + + parts = this.upload_file(parts[0], parts[1], prefix_name, + local_filename, file_ext_name, meta_list); + if (parts != null) { + return parts[0] + SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR + parts[1]; + } else { + return null; + } + } + + /** + * upload file to storage server (by file buff, slave file mode) + * + * @param master_file_id the master file id to generate the slave file + * @param prefix_name the prefix name to generate the slave file + * @param file_buff file content/buff + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return file id(including group name and filename) if success,
+ * return null if fail + */ + public String upload_file1(String master_file_id, String prefix_name, + byte[] file_buff, String file_ext_name, NameValuePair[] meta_list) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(master_file_id, parts); + if (this.errno != 0) { + return null; + } + + parts = this.upload_file(parts[0], parts[1], prefix_name, file_buff, file_ext_name, meta_list); + if (parts != null) { + return parts[0] + SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR + parts[1]; + } else { + return null; + } + } + + /** + * upload file to storage server (by file buff, slave file mode) + * + * @param master_file_id the master file id to generate the slave file + * @param prefix_name the prefix name to generate the slave file + * @param file_buff file content/buff + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return file id(including group name and filename) if success,
+ * return null if fail + */ + public String upload_file1(String master_file_id, String prefix_name, + byte[] file_buff, int offset, int length, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(master_file_id, parts); + if (this.errno != 0) { + return null; + } + + parts = this.upload_file(parts[0], parts[1], prefix_name, file_buff, + offset, length, file_ext_name, meta_list); + if (parts != null) { + return parts[0] + SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR + parts[1]; + } else { + return null; + } + } + + /** + * upload file to storage server (by callback) + * + * @param master_file_id the master file id to generate the slave file + * @param prefix_name the prefix name to generate the slave file + * @param file_size the file size + * @param callback the write data callback object + * @param file_ext_name file ext name, do not include dot(.) + * @param meta_list meta info array + * @return file id(including group name and filename) if success,
+ * return null if fail + */ + public String upload_file1(String master_file_id, String prefix_name, long file_size, + UploadCallback callback, String file_ext_name, + NameValuePair[] meta_list) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(master_file_id, parts); + if (this.errno != 0) { + return null; + } + + parts = this.upload_file(parts[0], parts[1], prefix_name, file_size, callback, file_ext_name, meta_list); + if (parts != null) { + return parts[0] + SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR + parts[1]; + } else { + return null; + } + } + + /** + * append file to storage server (by file name) + * + * @param appender_file_id the appender file id + * @param local_filename local filename to append + * @return 0 for success, != 0 for error (error no) + */ + public int append_file1(String appender_file_id, String local_filename) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(appender_file_id, parts); + if (this.errno != 0) { + return this.errno; + } + + return this.append_file(parts[0], parts[1], local_filename); + } + + /** + * append file to storage server (by file buff) + * + * @param appender_file_id the appender file id + * @param file_buff file content/buff + * @return 0 for success, != 0 for error (error no) + */ + public int append_file1(String appender_file_id, byte[] file_buff) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(appender_file_id, parts); + if (this.errno != 0) { + return this.errno; + } + + return this.append_file(parts[0], parts[1], file_buff); + } + + /** + * append file to storage server (by file buff) + * + * @param appender_file_id the appender file id + * @param file_buff file content/buffer + * @param offset start offset of the buffer + * @param length the length of the buffer to append + * @return 0 for success, != 0 for error (error no) + */ + public int append_file1(String appender_file_id, byte[] file_buff, int offset, int length) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(appender_file_id, parts); + if (this.errno != 0) { + return this.errno; + } + + return this.append_file(parts[0], parts[1], file_buff, offset, length); + } + + /** + * append file to storage server (by callback) + * + * @param appender_file_id the appender file id + * @param file_size the file size + * @param callback the write data callback object + * @return 0 for success, != 0 for error (error no) + */ + public int append_file1(String appender_file_id, long file_size, UploadCallback callback) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(appender_file_id, parts); + if (this.errno != 0) { + return this.errno; + } + + return this.append_file(parts[0], parts[1], file_size, callback); + } + + /** + * modify appender file to storage server (by file name) + * + * @param appender_file_id the appender file id + * @param file_offset the offset of appender file + * @param local_filename local filename to append + * @return 0 for success, != 0 for error (error no) + */ + public int modify_file1(String appender_file_id, + long file_offset, String local_filename) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(appender_file_id, parts); + if (this.errno != 0) { + return this.errno; + } + + return this.modify_file(parts[0], parts[1], file_offset, local_filename); + } + + /** + * modify appender file to storage server (by file buff) + * + * @param appender_file_id the appender file id + * @param file_offset the offset of appender file + * @param file_buff file content/buff + * @return 0 for success, != 0 for error (error no) + */ + public int modify_file1(String appender_file_id, + long file_offset, byte[] file_buff) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(appender_file_id, parts); + if (this.errno != 0) { + return this.errno; + } + + return this.modify_file(parts[0], parts[1], file_offset, file_buff); + } + + /** + * modify appender file to storage server (by file buff) + * + * @param appender_file_id the appender file id + * @param file_offset the offset of appender file + * @param file_buff file content/buff + * @param buffer_offset start offset of the buff + * @param buffer_length the length of buff to modify + * @return 0 for success, != 0 for error (error no) + */ + public int modify_file1(String appender_file_id, + long file_offset, byte[] file_buff, int buffer_offset, int buffer_length) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(appender_file_id, parts); + if (this.errno != 0) { + return this.errno; + } + + return this.modify_file(parts[0], parts[1], file_offset, + file_buff, buffer_offset, buffer_length); + } + + /** + * modify appender file to storage server (by callback) + * + * @param appender_file_id the appender file id + * @param file_offset the offset of appender file + * @param modify_size the modify size + * @param callback the write data callback object + * @return 0 for success, != 0 for error (error no) + */ + public int modify_file1(String appender_file_id, + long file_offset, long modify_size, UploadCallback callback) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(appender_file_id, parts); + if (this.errno != 0) { + return this.errno; + } + + return this.modify_file(parts[0], parts[1], file_offset, modify_size, callback); + } + + /** + * delete file from storage server + * + * @param file_id the file id(including group name and filename) + * @return 0 for success, none zero for fail (error code) + */ + public int delete_file1(String file_id) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(file_id, parts); + if (this.errno != 0) { + return this.errno; + } + + return this.delete_file(parts[0], parts[1]); + } + + /** + * truncate appender file to size 0 from storage server + * + * @param appender_file_id the appender file id + * @return 0 for success, none zero for fail (error code) + */ + public int truncate_file1(String appender_file_id) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(appender_file_id, parts); + if (this.errno != 0) { + return this.errno; + } + + return this.truncate_file(parts[0], parts[1]); + } + + /** + * truncate appender file from storage server + * + * @param appender_file_id the appender file id + * @param truncated_file_size truncated file size + * @return 0 for success, none zero for fail (error code) + */ + public int truncate_file1(String appender_file_id, long truncated_file_size) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(appender_file_id, parts); + if (this.errno != 0) { + return this.errno; + } + + return this.truncate_file(parts[0], parts[1], truncated_file_size); + } + + /** + * download file from storage server + * + * @param file_id the file id(including group name and filename) + * @return file content/buffer, return null if fail + */ + public byte[] download_file1(String file_id) throws IOException, FastdfsException { + final long file_offset = 0; + final long download_bytes = 0; + + return this.download_file1(file_id, file_offset, download_bytes); + } + + /** + * download file from storage server + * + * @param file_id the file id(including group name and filename) + * @param file_offset the start offset of the file + * @param download_bytes download bytes, 0 for remain bytes from offset + * @return file content/buff, return null if fail + */ + public byte[] download_file1(String file_id, long file_offset, long download_bytes) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(file_id, parts); + if (this.errno != 0) { + return null; + } + + return this.download_file(parts[0], parts[1], file_offset, download_bytes); + } + + /** + * download file from storage server + * + * @param file_id the file id(including group name and filename) + * @param local_filename the filename on local + * @return 0 success, return none zero errno if fail + */ + public int download_file1(String file_id, String local_filename) throws IOException, FastdfsException { + final long file_offset = 0; + final long download_bytes = 0; + + return this.download_file1(file_id, file_offset, download_bytes, local_filename); + } + + /** + * download file from storage server + * + * @param file_id the file id(including group name and filename) + * @param file_offset the start offset of the file + * @param download_bytes download bytes, 0 for remain bytes from offset + * @param local_filename the filename on local + * @return 0 success, return none zero errno if fail + */ + public int download_file1(String file_id, long file_offset, long download_bytes, String local_filename) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(file_id, parts); + if (this.errno != 0) { + return this.errno; + } + + return this.download_file(parts[0], parts[1], file_offset, download_bytes, local_filename); + } + + /** + * download file from storage server + * + * @param file_id the file id(including group name and filename) + * @param callback the callback object, will call callback.recv() when data arrive + * @return 0 success, return none zero errno if fail + */ + public int download_file1(String file_id, DownloadCallback callback) throws IOException, FastdfsException { + final long file_offset = 0; + final long download_bytes = 0; + + return this.download_file1(file_id, file_offset, download_bytes, callback); + } + + /** + * download file from storage server + * + * @param file_id the file id(including group name and filename) + * @param file_offset the start offset of the file + * @param download_bytes download bytes, 0 for remain bytes from offset + * @param callback the callback object, will call callback.recv() when data arrive + * @return 0 success, return none zero errno if fail + */ + public int download_file1(String file_id, long file_offset, long download_bytes, DownloadCallback callback) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(file_id, parts); + if (this.errno != 0) { + return this.errno; + } + + return this.download_file(parts[0], parts[1], file_offset, download_bytes, callback); + } + + /** + * get all metadata items from storage server + * + * @param file_id the file id(including group name and filename) + * @return meta info array, return null if fail + */ + public NameValuePair[] get_metadata1(String file_id) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(file_id, parts); + if (this.errno != 0) { + return null; + } + + return this.get_metadata(parts[0], parts[1]); + } + + /** + * set metadata items to storage server + * + * @param file_id the file id(including group name and filename) + * @param meta_list meta item array + * @param op_flag flag, can be one of following values:
+ *

  • ProtoCommon.STORAGE_SET_METADATA_FLAG_OVERWRITE: overwrite all old + * metadata items
+ *
  • ProtoCommon.STORAGE_SET_METADATA_FLAG_MERGE: merge, insert when + * the metadata item not exist, otherwise update it
+ * @return 0 for success, !=0 fail (error code) + */ + public int set_metadata1(String file_id, NameValuePair[] meta_list, byte op_flag) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(file_id, parts); + if (this.errno != 0) { + return this.errno; + } + + return this.set_metadata(parts[0], parts[1], meta_list, op_flag); + } + + /** + * get file info from storage server + * + * @param file_id the file id(including group name and filename) + * @return FileInfo object for success, return null for fail + */ + public FileInfo query_file_info1(String file_id) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(file_id, parts); + if (this.errno != 0) { + return null; + } + + return this.query_file_info(parts[0], parts[1]); + } + + /** + * get file info decoded from filename + * + * @param file_id the file id(including group name and filename) + * @return FileInfo object for success, return null for fail + */ + public FileInfo get_file_info1(String file_id) throws IOException, FastdfsException { + String[] parts = new String[2]; + this.errno = this.split_file_id(file_id, parts); + if (this.errno != 0) { + return null; + } + + return this.get_file_info(parts[0], parts[1]); + } +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/StorageServer.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/StorageServer.java new file mode 100644 index 000000000..029c6a354 --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/StorageServer.java @@ -0,0 +1,57 @@ +/** + * Copyright (C) 2008 Happy Fish / YuQing + *

+ * FastDFS Java Client may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. + */ + +package org.csource.fastdfs; + +import java.io.IOException; +import java.net.InetSocketAddress; + +/** + * Storage Server Info + * + * @author Happy Fish / YuQing + * @version Version 1.11 + */ +public class StorageServer extends TrackerServer { + protected int store_path_index = 0; + + /** + * Constructor + * + * @param ip_addr the ip address of storage server + * @param port the port of storage server + * @param store_path the store path index on the storage server + */ + public StorageServer(String ip_addr, int port, int store_path) throws IOException { + super(ClientGlobal.getSocket(ip_addr, port), new InetSocketAddress(ip_addr, port)); + this.store_path_index = store_path; + } + + /** + * Constructor + * + * @param ip_addr the ip address of storage server + * @param port the port of storage server + * @param store_path the store path index on the storage server + */ + public StorageServer(String ip_addr, int port, byte store_path) throws IOException { + super(ClientGlobal.getSocket(ip_addr, port), new InetSocketAddress(ip_addr, port)); + if (store_path < 0) { + this.store_path_index = 256 + store_path; + } else { + this.store_path_index = store_path; + } + } + + /** + * @return the store path index on the storage server + */ + public int getStorePathIndex() { + return this.store_path_index; + } +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/StructBase.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/StructBase.java new file mode 100644 index 000000000..38d847ffa --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/StructBase.java @@ -0,0 +1,73 @@ +/** + * Copyright (C) 2008 Happy Fish / YuQing + *

+ * FastDFS Java Client may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. + */ + +package org.csource.fastdfs; + +import java.io.UnsupportedEncodingException; +import java.util.Date; + +/** + * C struct body decoder + * + * @author Happy Fish / YuQing + * @version Version 1.17 + */ +public abstract class StructBase { + /** + * set fields + * + * @param bs byte array + * @param offset start offset + */ + public abstract void setFields(byte[] bs, int offset); + + protected String stringValue(byte[] bs, int offset, FieldInfo filedInfo) { + try { + return (new String(bs, offset + filedInfo.offset, filedInfo.size, ClientGlobal.g_charset)).trim(); + } catch (UnsupportedEncodingException ex) { + ex.printStackTrace(); + return null; + } + } + + protected long longValue(byte[] bs, int offset, FieldInfo filedInfo) { + return ProtoCommon.buff2long(bs, offset + filedInfo.offset); + } + + protected int intValue(byte[] bs, int offset, FieldInfo filedInfo) { + return (int) ProtoCommon.buff2long(bs, offset + filedInfo.offset); + } + + protected int int32Value(byte[] bs, int offset, FieldInfo filedInfo) { + return ProtoCommon.buff2int(bs, offset + filedInfo.offset); + } + + protected byte byteValue(byte[] bs, int offset, FieldInfo filedInfo) { + return bs[offset + filedInfo.offset]; + } + + protected boolean booleanValue(byte[] bs, int offset, FieldInfo filedInfo) { + return bs[offset + filedInfo.offset] != 0; + } + + protected Date dateValue(byte[] bs, int offset, FieldInfo filedInfo) { + return new Date(ProtoCommon.buff2long(bs, offset + filedInfo.offset) * 1000); + } + + protected static class FieldInfo { + protected String name; + protected int offset; + protected int size; + + public FieldInfo(String name, int offset, int size) { + this.name = name; + this.offset = offset; + this.size = size; + } + } +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/StructGroupStat.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/StructGroupStat.java new file mode 100644 index 000000000..30cfd1c14 --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/StructGroupStat.java @@ -0,0 +1,225 @@ +/** + * Copyright (C) 2008 Happy Fish / YuQing + *

+ * FastDFS Java Client may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. + */ + +package org.csource.fastdfs; + +/** + * C struct body decoder + * + * @author Happy Fish / YuQing + * @version Version 1.18 + */ +public class StructGroupStat extends StructBase { + protected static final int FIELD_INDEX_GROUP_NAME = 0; + protected static final int FIELD_INDEX_TOTAL_MB = 1; + protected static final int FIELD_INDEX_FREE_MB = 2; + protected static final int FIELD_INDEX_TRUNK_FREE_MB = 3; + protected static final int FIELD_INDEX_STORAGE_COUNT = 4; + protected static final int FIELD_INDEX_STORAGE_PORT = 5; + protected static final int FIELD_INDEX_STORAGE_HTTP_PORT = 6; + protected static final int FIELD_INDEX_ACTIVE_COUNT = 7; + protected static final int FIELD_INDEX_CURRENT_WRITE_SERVER = 8; + protected static final int FIELD_INDEX_STORE_PATH_COUNT = 9; + protected static final int FIELD_INDEX_SUBDIR_COUNT_PER_PATH = 10; + protected static final int FIELD_INDEX_CURRENT_TRUNK_FILE_ID = 11; + + protected static int fieldsTotalSize; + protected static FieldInfo[] fieldsArray = new FieldInfo[12]; + + static { + int offset = 0; + fieldsArray[FIELD_INDEX_GROUP_NAME] = new FieldInfo("groupName", offset, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + 1); + offset += ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + 1; + + fieldsArray[FIELD_INDEX_TOTAL_MB] = new FieldInfo("totalMB", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_FREE_MB] = new FieldInfo("freeMB", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_TRUNK_FREE_MB] = new FieldInfo("trunkFreeMB", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_STORAGE_COUNT] = new FieldInfo("storageCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_STORAGE_PORT] = new FieldInfo("storagePort", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_STORAGE_HTTP_PORT] = new FieldInfo("storageHttpPort", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_ACTIVE_COUNT] = new FieldInfo("activeCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_CURRENT_WRITE_SERVER] = new FieldInfo("currentWriteServer", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_STORE_PATH_COUNT] = new FieldInfo("storePathCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_SUBDIR_COUNT_PER_PATH] = new FieldInfo("subdirCountPerPath", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_CURRENT_TRUNK_FILE_ID] = new FieldInfo("currentTrunkFileId", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsTotalSize = offset; + } + + protected String groupName; //name of this group + protected long totalMB; //total disk storage in MB + protected long freeMB; //free disk space in MB + protected long trunkFreeMB; //trunk free space in MB + protected int storageCount; //storage server count + protected int storagePort; //storage server port + protected int storageHttpPort; //storage server HTTP port + protected int activeCount; //active storage server count + protected int currentWriteServer; //current storage server index to upload file + protected int storePathCount; //store base path count of each storage server + protected int subdirCountPerPath; //sub dir count per store path + protected int currentTrunkFileId; //current trunk file id + + /** + * get fields total size + * + * @return fields total size + */ + public static int getFieldsTotalSize() { + return fieldsTotalSize; + } + + /** + * get group name + * + * @return group name + */ + public String getGroupName() { + return this.groupName; + } + + /** + * get total disk space in MB + * + * @return total disk space in MB + */ + public long getTotalMB() { + return this.totalMB; + } + + /** + * get free disk space in MB + * + * @return free disk space in MB + */ + public long getFreeMB() { + return this.freeMB; + } + + /** + * get trunk free space in MB + * + * @return trunk free space in MB + */ + public long getTrunkFreeMB() { + return this.trunkFreeMB; + } + + /** + * get storage server count in this group + * + * @return storage server count in this group + */ + public int getStorageCount() { + return this.storageCount; + } + + /** + * get active storage server count in this group + * + * @return active storage server count in this group + */ + public int getActiveCount() { + return this.activeCount; + } + + /** + * get storage server port + * + * @return storage server port + */ + public int getStoragePort() { + return this.storagePort; + } + + /** + * get storage server HTTP port + * + * @return storage server HTTP port + */ + public int getStorageHttpPort() { + return this.storageHttpPort; + } + + /** + * get current storage server index to upload file + * + * @return current storage server index to upload file + */ + public int getCurrentWriteServer() { + return this.currentWriteServer; + } + + /** + * get store base path count of each storage server + * + * @return store base path count of each storage server + */ + public int getStorePathCount() { + return this.storePathCount; + } + + /** + * get sub dir count per store path + * + * @return sub dir count per store path + */ + public int getSubdirCountPerPath() { + return this.subdirCountPerPath; + } + + /** + * get current trunk file id + * + * @return current trunk file id + */ + public int getCurrentTrunkFileId() { + return this.currentTrunkFileId; + } + + /** + * set fields + * + * @param bs byte array + * @param offset start offset + */ + public void setFields(byte[] bs, int offset) { + this.groupName = stringValue(bs, offset, fieldsArray[FIELD_INDEX_GROUP_NAME]); + this.totalMB = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_MB]); + this.freeMB = longValue(bs, offset, fieldsArray[FIELD_INDEX_FREE_MB]); + this.trunkFreeMB = longValue(bs, offset, fieldsArray[FIELD_INDEX_TRUNK_FREE_MB]); + this.storageCount = intValue(bs, offset, fieldsArray[FIELD_INDEX_STORAGE_COUNT]); + this.storagePort = intValue(bs, offset, fieldsArray[FIELD_INDEX_STORAGE_PORT]); + this.storageHttpPort = intValue(bs, offset, fieldsArray[FIELD_INDEX_STORAGE_HTTP_PORT]); + this.activeCount = intValue(bs, offset, fieldsArray[FIELD_INDEX_ACTIVE_COUNT]); + this.currentWriteServer = intValue(bs, offset, fieldsArray[FIELD_INDEX_CURRENT_WRITE_SERVER]); + this.storePathCount = intValue(bs, offset, fieldsArray[FIELD_INDEX_STORE_PATH_COUNT]); + this.subdirCountPerPath = intValue(bs, offset, fieldsArray[FIELD_INDEX_SUBDIR_COUNT_PER_PATH]); + this.currentTrunkFileId = intValue(bs, offset, fieldsArray[FIELD_INDEX_CURRENT_TRUNK_FILE_ID]); + } +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/StructStorageStat.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/StructStorageStat.java new file mode 100644 index 000000000..e503da18a --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/StructStorageStat.java @@ -0,0 +1,982 @@ +/** + * Copyright (C) 2008 Happy Fish / YuQing + *

+ * FastDFS Java Client may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. + */ + +package org.csource.fastdfs; + +import java.util.Date; + +/** + * C struct body decoder + * + * @author Happy Fish / YuQing + * @version Version 1.25 + */ +public class StructStorageStat extends StructBase { + protected static final int FIELD_INDEX_STATUS = 0; + protected static final int FIELD_INDEX_ID = 1; + protected static final int FIELD_INDEX_IP_ADDR = 2; + protected static final int FIELD_INDEX_DOMAIN_NAME = 3; + protected static final int FIELD_INDEX_SRC_IP_ADDR = 4; + protected static final int FIELD_INDEX_VERSION = 5; + protected static final int FIELD_INDEX_JOIN_TIME = 6; + protected static final int FIELD_INDEX_UP_TIME = 7; + protected static final int FIELD_INDEX_TOTAL_MB = 8; + protected static final int FIELD_INDEX_FREE_MB = 9; + protected static final int FIELD_INDEX_UPLOAD_PRIORITY = 10; + protected static final int FIELD_INDEX_STORE_PATH_COUNT = 11; + protected static final int FIELD_INDEX_SUBDIR_COUNT_PER_PATH = 12; + protected static final int FIELD_INDEX_CURRENT_WRITE_PATH = 13; + protected static final int FIELD_INDEX_STORAGE_PORT = 14; + protected static final int FIELD_INDEX_STORAGE_HTTP_PORT = 15; + + protected static final int FIELD_INDEX_CONNECTION_ALLOC_COUNT = 16; + protected static final int FIELD_INDEX_CONNECTION_CURRENT_COUNT = 17; + protected static final int FIELD_INDEX_CONNECTION_MAX_COUNT = 18; + + protected static final int FIELD_INDEX_TOTAL_UPLOAD_COUNT = 19; + protected static final int FIELD_INDEX_SUCCESS_UPLOAD_COUNT = 20; + protected static final int FIELD_INDEX_TOTAL_APPEND_COUNT = 21; + protected static final int FIELD_INDEX_SUCCESS_APPEND_COUNT = 22; + protected static final int FIELD_INDEX_TOTAL_MODIFY_COUNT = 23; + protected static final int FIELD_INDEX_SUCCESS_MODIFY_COUNT = 24; + protected static final int FIELD_INDEX_TOTAL_TRUNCATE_COUNT = 25; + protected static final int FIELD_INDEX_SUCCESS_TRUNCATE_COUNT = 26; + protected static final int FIELD_INDEX_TOTAL_SET_META_COUNT = 27; + protected static final int FIELD_INDEX_SUCCESS_SET_META_COUNT = 28; + protected static final int FIELD_INDEX_TOTAL_DELETE_COUNT = 29; + protected static final int FIELD_INDEX_SUCCESS_DELETE_COUNT = 30; + protected static final int FIELD_INDEX_TOTAL_DOWNLOAD_COUNT = 31; + protected static final int FIELD_INDEX_SUCCESS_DOWNLOAD_COUNT = 32; + protected static final int FIELD_INDEX_TOTAL_GET_META_COUNT = 33; + protected static final int FIELD_INDEX_SUCCESS_GET_META_COUNT = 34; + protected static final int FIELD_INDEX_TOTAL_CREATE_LINK_COUNT = 35; + protected static final int FIELD_INDEX_SUCCESS_CREATE_LINK_COUNT = 36; + protected static final int FIELD_INDEX_TOTAL_DELETE_LINK_COUNT = 37; + protected static final int FIELD_INDEX_SUCCESS_DELETE_LINK_COUNT = 38; + protected static final int FIELD_INDEX_TOTAL_UPLOAD_BYTES = 39; + protected static final int FIELD_INDEX_SUCCESS_UPLOAD_BYTES = 40; + protected static final int FIELD_INDEX_TOTAL_APPEND_BYTES = 41; + protected static final int FIELD_INDEX_SUCCESS_APPEND_BYTES = 42; + protected static final int FIELD_INDEX_TOTAL_MODIFY_BYTES = 43; + protected static final int FIELD_INDEX_SUCCESS_MODIFY_BYTES = 44; + protected static final int FIELD_INDEX_TOTAL_DOWNLOAD_BYTES = 45; + protected static final int FIELD_INDEX_SUCCESS_DOWNLOAD_BYTES = 46; + protected static final int FIELD_INDEX_TOTAL_SYNC_IN_BYTES = 47; + protected static final int FIELD_INDEX_SUCCESS_SYNC_IN_BYTES = 48; + protected static final int FIELD_INDEX_TOTAL_SYNC_OUT_BYTES = 49; + protected static final int FIELD_INDEX_SUCCESS_SYNC_OUT_BYTES = 50; + protected static final int FIELD_INDEX_TOTAL_FILE_OPEN_COUNT = 51; + protected static final int FIELD_INDEX_SUCCESS_FILE_OPEN_COUNT = 52; + protected static final int FIELD_INDEX_TOTAL_FILE_READ_COUNT = 53; + protected static final int FIELD_INDEX_SUCCESS_FILE_READ_COUNT = 54; + protected static final int FIELD_INDEX_TOTAL_FILE_WRITE_COUNT = 55; + protected static final int FIELD_INDEX_SUCCESS_FILE_WRITE_COUNT = 56; + protected static final int FIELD_INDEX_LAST_SOURCE_UPDATE = 57; + protected static final int FIELD_INDEX_LAST_SYNC_UPDATE = 58; + protected static final int FIELD_INDEX_LAST_SYNCED_TIMESTAMP = 59; + protected static final int FIELD_INDEX_LAST_HEART_BEAT_TIME = 60; + protected static final int FIELD_INDEX_IF_TRUNK_FILE = 61; + + protected static int fieldsTotalSize; + protected static FieldInfo[] fieldsArray = new FieldInfo[62]; + + static { + int offset = 0; + + fieldsArray[FIELD_INDEX_STATUS] = new FieldInfo("status", offset, 1); + offset += 1; + + fieldsArray[FIELD_INDEX_ID] = new FieldInfo("id", offset, ProtoCommon.FDFS_STORAGE_ID_MAX_SIZE); + offset += ProtoCommon.FDFS_STORAGE_ID_MAX_SIZE; + + fieldsArray[FIELD_INDEX_IP_ADDR] = new FieldInfo("ipAddr", offset, ProtoCommon.FDFS_IPADDR_SIZE); + offset += ProtoCommon.FDFS_IPADDR_SIZE; + + fieldsArray[FIELD_INDEX_DOMAIN_NAME] = new FieldInfo("domainName", offset, ProtoCommon.FDFS_DOMAIN_NAME_MAX_SIZE); + offset += ProtoCommon.FDFS_DOMAIN_NAME_MAX_SIZE; + + fieldsArray[FIELD_INDEX_SRC_IP_ADDR] = new FieldInfo("srcIpAddr", offset, ProtoCommon.FDFS_IPADDR_SIZE); + offset += ProtoCommon.FDFS_IPADDR_SIZE; + + fieldsArray[FIELD_INDEX_VERSION] = new FieldInfo("version", offset, ProtoCommon.FDFS_VERSION_SIZE); + offset += ProtoCommon.FDFS_VERSION_SIZE; + + fieldsArray[FIELD_INDEX_JOIN_TIME] = new FieldInfo("joinTime", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_UP_TIME] = new FieldInfo("upTime", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_TOTAL_MB] = new FieldInfo("totalMB", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_FREE_MB] = new FieldInfo("freeMB", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_UPLOAD_PRIORITY] = new FieldInfo("uploadPriority", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_STORE_PATH_COUNT] = new FieldInfo("storePathCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_SUBDIR_COUNT_PER_PATH] = new FieldInfo("subdirCountPerPath", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_CURRENT_WRITE_PATH] = new FieldInfo("currentWritePath", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_STORAGE_PORT] = new FieldInfo("storagePort", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_STORAGE_HTTP_PORT] = new FieldInfo("storageHttpPort", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_CONNECTION_ALLOC_COUNT] = new FieldInfo("connectionAllocCount", offset, 4); + offset += 4; + + fieldsArray[FIELD_INDEX_CONNECTION_CURRENT_COUNT] = new FieldInfo("connectionCurrentCount", offset, 4); + offset += 4; + + fieldsArray[FIELD_INDEX_CONNECTION_MAX_COUNT] = new FieldInfo("connectionMaxCount", offset, 4); + offset += 4; + + fieldsArray[FIELD_INDEX_TOTAL_UPLOAD_COUNT] = new FieldInfo("totalUploadCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_SUCCESS_UPLOAD_COUNT] = new FieldInfo("successUploadCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_TOTAL_APPEND_COUNT] = new FieldInfo("totalAppendCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_SUCCESS_APPEND_COUNT] = new FieldInfo("successAppendCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_TOTAL_MODIFY_COUNT] = new FieldInfo("totalModifyCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_SUCCESS_MODIFY_COUNT] = new FieldInfo("successModifyCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_TOTAL_TRUNCATE_COUNT] = new FieldInfo("totalTruncateCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_SUCCESS_TRUNCATE_COUNT] = new FieldInfo("successTruncateCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_TOTAL_SET_META_COUNT] = new FieldInfo("totalSetMetaCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_SUCCESS_SET_META_COUNT] = new FieldInfo("successSetMetaCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_TOTAL_DELETE_COUNT] = new FieldInfo("totalDeleteCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_SUCCESS_DELETE_COUNT] = new FieldInfo("successDeleteCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_TOTAL_DOWNLOAD_COUNT] = new FieldInfo("totalDownloadCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_SUCCESS_DOWNLOAD_COUNT] = new FieldInfo("successDownloadCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_TOTAL_GET_META_COUNT] = new FieldInfo("totalGetMetaCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_SUCCESS_GET_META_COUNT] = new FieldInfo("successGetMetaCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_TOTAL_CREATE_LINK_COUNT] = new FieldInfo("totalCreateLinkCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_SUCCESS_CREATE_LINK_COUNT] = new FieldInfo("successCreateLinkCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_TOTAL_DELETE_LINK_COUNT] = new FieldInfo("totalDeleteLinkCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_SUCCESS_DELETE_LINK_COUNT] = new FieldInfo("successDeleteLinkCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_TOTAL_UPLOAD_BYTES] = new FieldInfo("totalUploadBytes", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_SUCCESS_UPLOAD_BYTES] = new FieldInfo("successUploadBytes", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_TOTAL_APPEND_BYTES] = new FieldInfo("totalAppendBytes", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_SUCCESS_APPEND_BYTES] = new FieldInfo("successAppendBytes", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_TOTAL_MODIFY_BYTES] = new FieldInfo("totalModifyBytes", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_SUCCESS_MODIFY_BYTES] = new FieldInfo("successModifyBytes", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_TOTAL_DOWNLOAD_BYTES] = new FieldInfo("totalDownloadloadBytes", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_SUCCESS_DOWNLOAD_BYTES] = new FieldInfo("successDownloadloadBytes", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_TOTAL_SYNC_IN_BYTES] = new FieldInfo("totalSyncInBytes", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_SUCCESS_SYNC_IN_BYTES] = new FieldInfo("successSyncInBytes", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_TOTAL_SYNC_OUT_BYTES] = new FieldInfo("totalSyncOutBytes", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_SUCCESS_SYNC_OUT_BYTES] = new FieldInfo("successSyncOutBytes", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_TOTAL_FILE_OPEN_COUNT] = new FieldInfo("totalFileOpenCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_SUCCESS_FILE_OPEN_COUNT] = new FieldInfo("successFileOpenCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_TOTAL_FILE_READ_COUNT] = new FieldInfo("totalFileReadCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_SUCCESS_FILE_READ_COUNT] = new FieldInfo("successFileReadCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_TOTAL_FILE_WRITE_COUNT] = new FieldInfo("totalFileWriteCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_SUCCESS_FILE_WRITE_COUNT] = new FieldInfo("successFileWriteCount", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_LAST_SOURCE_UPDATE] = new FieldInfo("lastSourceUpdate", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_LAST_SYNC_UPDATE] = new FieldInfo("lastSyncUpdate", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_LAST_SYNCED_TIMESTAMP] = new FieldInfo("lastSyncedTimestamp", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_LAST_HEART_BEAT_TIME] = new FieldInfo("lastHeartBeatTime", offset, ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + fieldsArray[FIELD_INDEX_IF_TRUNK_FILE] = new FieldInfo("ifTrunkServer", offset, 1); + offset += 1; + + fieldsTotalSize = offset; + } + + protected byte status; + protected String id; + protected String ipAddr; + protected String srcIpAddr; + protected String domainName; //http domain name + protected String version; + protected long totalMB; //total disk storage in MB + protected long freeMB; //free disk storage in MB + protected int uploadPriority; //upload priority + protected Date joinTime; //storage join timestamp (create timestamp) + protected Date upTime; //storage service started timestamp + protected int storePathCount; //store base path count of each storage server + protected int subdirCountPerPath; + protected int storagePort; + protected int storageHttpPort; //storage http server port + protected int currentWritePath; //current write path index + protected int connectionAllocCount; + protected int connectionCurrentCount; + protected int connectionMaxCount; + protected long totalUploadCount; + protected long successUploadCount; + protected long totalAppendCount; + protected long successAppendCount; + protected long totalModifyCount; + protected long successModifyCount; + protected long totalTruncateCount; + protected long successTruncateCount; + protected long totalSetMetaCount; + protected long successSetMetaCount; + protected long totalDeleteCount; + protected long successDeleteCount; + protected long totalDownloadCount; + protected long successDownloadCount; + protected long totalGetMetaCount; + protected long successGetMetaCount; + protected long totalCreateLinkCount; + protected long successCreateLinkCount; + protected long totalDeleteLinkCount; + protected long successDeleteLinkCount; + protected long totalUploadBytes; + protected long successUploadBytes; + protected long totalAppendBytes; + protected long successAppendBytes; + protected long totalModifyBytes; + protected long successModifyBytes; + protected long totalDownloadloadBytes; + protected long successDownloadloadBytes; + protected long totalSyncInBytes; + protected long successSyncInBytes; + protected long totalSyncOutBytes; + protected long successSyncOutBytes; + protected long totalFileOpenCount; + protected long successFileOpenCount; + protected long totalFileReadCount; + protected long successFileReadCount; + protected long totalFileWriteCount; + protected long successFileWriteCount; + protected Date lastSourceUpdate; + protected Date lastSyncUpdate; + protected Date lastSyncedTimestamp; + protected Date lastHeartBeatTime; + protected boolean ifTrunkServer; + + /** + * get fields total size + * + * @return fields total size + */ + public static int getFieldsTotalSize() { + return fieldsTotalSize; + } + + /** + * get storage status + * + * @return storage status + */ + public byte getStatus() { + return this.status; + } + + /** + * get storage server id + * + * @return storage server id + */ + public String getId() { + return this.id; + } + + /** + * get storage server ip address + * + * @return storage server ip address + */ + public String getIpAddr() { + return this.ipAddr; + } + + /** + * get source storage ip address + * + * @return source storage ip address + */ + public String getSrcIpAddr() { + return this.srcIpAddr; + } + + /** + * get the domain name of the storage server + * + * @return the domain name of the storage server + */ + public String getDomainName() { + return this.domainName; + } + + /** + * get storage version + * + * @return storage version + */ + public String getVersion() { + return this.version; + } + + /** + * get total disk space in MB + * + * @return total disk space in MB + */ + public long getTotalMB() { + return this.totalMB; + } + + /** + * get free disk space in MB + * + * @return free disk space in MB + */ + public long getFreeMB() { + return this.freeMB; + } + + /** + * get storage server upload priority + * + * @return storage server upload priority + */ + public int getUploadPriority() { + return this.uploadPriority; + } + + /** + * get storage server join time + * + * @return storage server join time + */ + public Date getJoinTime() { + return this.joinTime; + } + + /** + * get storage server up time + * + * @return storage server up time + */ + public Date getUpTime() { + return this.upTime; + } + + /** + * get store base path count of each storage server + * + * @return store base path count of each storage server + */ + public int getStorePathCount() { + return this.storePathCount; + } + + /** + * get sub dir count per store path + * + * @return sub dir count per store path + */ + public int getSubdirCountPerPath() { + return this.subdirCountPerPath; + } + + /** + * get storage server port + * + * @return storage server port + */ + public int getStoragePort() { + return this.storagePort; + } + + /** + * get storage server HTTP port + * + * @return storage server HTTP port + */ + public int getStorageHttpPort() { + return this.storageHttpPort; + } + + /** + * get current write path index + * + * @return current write path index + */ + public int getCurrentWritePath() { + return this.currentWritePath; + } + + /** + * get total upload file count + * + * @return total upload file count + */ + public long getTotalUploadCount() { + return this.totalUploadCount; + } + + /** + * get success upload file count + * + * @return success upload file count + */ + public long getSuccessUploadCount() { + return this.successUploadCount; + } + + /** + * get total append count + * + * @return total append count + */ + public long getTotalAppendCount() { + return this.totalAppendCount; + } + + /** + * get success append count + * + * @return success append count + */ + public long getSuccessAppendCount() { + return this.successAppendCount; + } + + /** + * get total modify count + * + * @return total modify count + */ + public long getTotalModifyCount() { + return this.totalModifyCount; + } + + /** + * get success modify count + * + * @return success modify count + */ + public long getSuccessModifyCount() { + return this.successModifyCount; + } + + /** + * get total truncate count + * + * @return total truncate count + */ + public long getTotalTruncateCount() { + return this.totalTruncateCount; + } + + /** + * get success truncate count + * + * @return success truncate count + */ + public long getSuccessTruncateCount() { + return this.successTruncateCount; + } + + /** + * get total set meta data count + * + * @return total set meta data count + */ + public long getTotalSetMetaCount() { + return this.totalSetMetaCount; + } + + /** + * get success set meta data count + * + * @return success set meta data count + */ + public long getSuccessSetMetaCount() { + return this.successSetMetaCount; + } + + /** + * get total delete file count + * + * @return total delete file count + */ + public long getTotalDeleteCount() { + return this.totalDeleteCount; + } + + /** + * get success delete file count + * + * @return success delete file count + */ + public long getSuccessDeleteCount() { + return this.successDeleteCount; + } + + /** + * get total download file count + * + * @return total download file count + */ + public long getTotalDownloadCount() { + return this.totalDownloadCount; + } + + /** + * get success download file count + * + * @return success download file count + */ + public long getSuccessDownloadCount() { + return this.successDownloadCount; + } + + /** + * get total get metadata count + * + * @return total get metadata count + */ + public long getTotalGetMetaCount() { + return this.totalGetMetaCount; + } + + /** + * get success get metadata count + * + * @return success get metadata count + */ + public long getSuccessGetMetaCount() { + return this.successGetMetaCount; + } + + /** + * get total create linke count + * + * @return total create linke count + */ + public long getTotalCreateLinkCount() { + return this.totalCreateLinkCount; + } + + /** + * get success create linke count + * + * @return success create linke count + */ + public long getSuccessCreateLinkCount() { + return this.successCreateLinkCount; + } + + /** + * get total delete link count + * + * @return total delete link count + */ + public long getTotalDeleteLinkCount() { + return this.totalDeleteLinkCount; + } + + /** + * get success delete link count + * + * @return success delete link count + */ + public long getSuccessDeleteLinkCount() { + return this.successDeleteLinkCount; + } + + /** + * get total upload file bytes + * + * @return total upload file bytes + */ + public long getTotalUploadBytes() { + return this.totalUploadBytes; + } + + /** + * get success upload file bytes + * + * @return success upload file bytes + */ + public long getSuccessUploadBytes() { + return this.successUploadBytes; + } + + /** + * get total append bytes + * + * @return total append bytes + */ + public long getTotalAppendBytes() { + return this.totalAppendBytes; + } + + /** + * get success append bytes + * + * @return success append bytes + */ + public long getSuccessAppendBytes() { + return this.successAppendBytes; + } + + /** + * get total modify bytes + * + * @return total modify bytes + */ + public long getTotalModifyBytes() { + return this.totalModifyBytes; + } + + /** + * get success modify bytes + * + * @return success modify bytes + */ + public long getSuccessModifyBytes() { + return this.successModifyBytes; + } + + /** + * get total download file bytes + * + * @return total download file bytes + */ + public long getTotalDownloadloadBytes() { + return this.totalDownloadloadBytes; + } + + /** + * get success download file bytes + * + * @return success download file bytes + */ + public long getSuccessDownloadloadBytes() { + return this.successDownloadloadBytes; + } + + /** + * get total sync in bytes + * + * @return total sync in bytes + */ + public long getTotalSyncInBytes() { + return this.totalSyncInBytes; + } + + /** + * get success sync in bytes + * + * @return success sync in bytes + */ + public long getSuccessSyncInBytes() { + return this.successSyncInBytes; + } + + /** + * get total sync out bytes + * + * @return total sync out bytes + */ + public long getTotalSyncOutBytes() { + return this.totalSyncOutBytes; + } + + /** + * get success sync out bytes + * + * @return success sync out bytes + */ + public long getSuccessSyncOutBytes() { + return this.successSyncOutBytes; + } + + /** + * get total file opened count + * + * @return total file opened bytes + */ + public long getTotalFileOpenCount() { + return this.totalFileOpenCount; + } + + /** + * get success file opened count + * + * @return success file opened count + */ + public long getSuccessFileOpenCount() { + return this.successFileOpenCount; + } + + /** + * get total file read count + * + * @return total file read bytes + */ + public long getTotalFileReadCount() { + return this.totalFileReadCount; + } + + /** + * get success file read count + * + * @return success file read count + */ + public long getSuccessFileReadCount() { + return this.successFileReadCount; + } + + /** + * get total file write count + * + * @return total file write bytes + */ + public long getTotalFileWriteCount() { + return this.totalFileWriteCount; + } + + /** + * get success file write count + * + * @return success file write count + */ + public long getSuccessFileWriteCount() { + return this.successFileWriteCount; + } + + /** + * get last source update timestamp + * + * @return last source update timestamp + */ + public Date getLastSourceUpdate() { + return this.lastSourceUpdate; + } + + /** + * get last synced update timestamp + * + * @return last synced update timestamp + */ + public Date getLastSyncUpdate() { + return this.lastSyncUpdate; + } + + /** + * get last synced timestamp + * + * @return last synced timestamp + */ + public Date getLastSyncedTimestamp() { + return this.lastSyncedTimestamp; + } + + /** + * get last heart beat timestamp + * + * @return last heart beat timestamp + */ + public Date getLastHeartBeatTime() { + return this.lastHeartBeatTime; + } + + /** + * if the trunk server + * + * @return true for the trunk server, otherwise false + */ + public boolean isTrunkServer() { + return this.ifTrunkServer; + } + + /** + * get connection alloc count + * + * @return connection alloc count + */ + public int getConnectionAllocCount() { + return this.connectionAllocCount; + } + + /** + * get connection current count + * + * @return connection current count + */ + public int getConnectionCurrentCount() { + return this.connectionCurrentCount; + } + + /** + * get connection max count + * + * @return connection max count + */ + public int getConnectionMaxCount() { + return this.connectionMaxCount; + } + + /** + * set fields + * + * @param bs byte array + * @param offset start offset + */ + public void setFields(byte[] bs, int offset) { + this.status = byteValue(bs, offset, fieldsArray[FIELD_INDEX_STATUS]); + this.id = stringValue(bs, offset, fieldsArray[FIELD_INDEX_ID]); + this.ipAddr = stringValue(bs, offset, fieldsArray[FIELD_INDEX_IP_ADDR]); + this.srcIpAddr = stringValue(bs, offset, fieldsArray[FIELD_INDEX_SRC_IP_ADDR]); + this.domainName = stringValue(bs, offset, fieldsArray[FIELD_INDEX_DOMAIN_NAME]); + this.version = stringValue(bs, offset, fieldsArray[FIELD_INDEX_VERSION]); + this.totalMB = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_MB]); + this.freeMB = longValue(bs, offset, fieldsArray[FIELD_INDEX_FREE_MB]); + this.uploadPriority = intValue(bs, offset, fieldsArray[FIELD_INDEX_UPLOAD_PRIORITY]); + this.joinTime = dateValue(bs, offset, fieldsArray[FIELD_INDEX_JOIN_TIME]); + this.upTime = dateValue(bs, offset, fieldsArray[FIELD_INDEX_UP_TIME]); + this.storePathCount = intValue(bs, offset, fieldsArray[FIELD_INDEX_STORE_PATH_COUNT]); + this.subdirCountPerPath = intValue(bs, offset, fieldsArray[FIELD_INDEX_SUBDIR_COUNT_PER_PATH]); + this.storagePort = intValue(bs, offset, fieldsArray[FIELD_INDEX_STORAGE_PORT]); + this.storageHttpPort = intValue(bs, offset, fieldsArray[FIELD_INDEX_STORAGE_HTTP_PORT]); + this.currentWritePath = intValue(bs, offset, fieldsArray[FIELD_INDEX_CURRENT_WRITE_PATH]); + + this.connectionAllocCount = int32Value(bs, offset, fieldsArray[FIELD_INDEX_CONNECTION_ALLOC_COUNT]); + this.connectionCurrentCount = int32Value(bs, offset, fieldsArray[FIELD_INDEX_CONNECTION_CURRENT_COUNT]); + this.connectionMaxCount = int32Value(bs, offset, fieldsArray[FIELD_INDEX_CONNECTION_MAX_COUNT]); + + this.totalUploadCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_UPLOAD_COUNT]); + this.successUploadCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_SUCCESS_UPLOAD_COUNT]); + this.totalAppendCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_APPEND_COUNT]); + this.successAppendCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_SUCCESS_APPEND_COUNT]); + this.totalModifyCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_MODIFY_COUNT]); + this.successModifyCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_SUCCESS_MODIFY_COUNT]); + this.totalTruncateCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_TRUNCATE_COUNT]); + this.successTruncateCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_SUCCESS_TRUNCATE_COUNT]); + this.totalSetMetaCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_SET_META_COUNT]); + this.successSetMetaCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_SUCCESS_SET_META_COUNT]); + this.totalDeleteCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_DELETE_COUNT]); + this.successDeleteCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_SUCCESS_DELETE_COUNT]); + this.totalDownloadCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_DOWNLOAD_COUNT]); + this.successDownloadCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_SUCCESS_DOWNLOAD_COUNT]); + this.totalGetMetaCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_GET_META_COUNT]); + this.successGetMetaCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_SUCCESS_GET_META_COUNT]); + this.totalCreateLinkCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_CREATE_LINK_COUNT]); + this.successCreateLinkCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_SUCCESS_CREATE_LINK_COUNT]); + this.totalDeleteLinkCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_DELETE_LINK_COUNT]); + this.successDeleteLinkCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_SUCCESS_DELETE_LINK_COUNT]); + this.totalUploadBytes = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_UPLOAD_BYTES]); + this.successUploadBytes = longValue(bs, offset, fieldsArray[FIELD_INDEX_SUCCESS_UPLOAD_BYTES]); + this.totalAppendBytes = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_APPEND_BYTES]); + this.successAppendBytes = longValue(bs, offset, fieldsArray[FIELD_INDEX_SUCCESS_APPEND_BYTES]); + this.totalModifyBytes = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_MODIFY_BYTES]); + this.successModifyBytes = longValue(bs, offset, fieldsArray[FIELD_INDEX_SUCCESS_MODIFY_BYTES]); + this.totalDownloadloadBytes = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_DOWNLOAD_BYTES]); + this.successDownloadloadBytes = longValue(bs, offset, fieldsArray[FIELD_INDEX_SUCCESS_DOWNLOAD_BYTES]); + this.totalSyncInBytes = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_SYNC_IN_BYTES]); + this.successSyncInBytes = longValue(bs, offset, fieldsArray[FIELD_INDEX_SUCCESS_SYNC_IN_BYTES]); + this.totalSyncOutBytes = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_SYNC_OUT_BYTES]); + this.successSyncOutBytes = longValue(bs, offset, fieldsArray[FIELD_INDEX_SUCCESS_SYNC_OUT_BYTES]); + this.totalFileOpenCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_FILE_OPEN_COUNT]); + this.successFileOpenCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_SUCCESS_FILE_OPEN_COUNT]); + this.totalFileReadCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_FILE_READ_COUNT]); + this.successFileReadCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_SUCCESS_FILE_READ_COUNT]); + this.totalFileWriteCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_TOTAL_FILE_WRITE_COUNT]); + this.successFileWriteCount = longValue(bs, offset, fieldsArray[FIELD_INDEX_SUCCESS_FILE_WRITE_COUNT]); + this.lastSourceUpdate = dateValue(bs, offset, fieldsArray[FIELD_INDEX_LAST_SOURCE_UPDATE]); + this.lastSyncUpdate = dateValue(bs, offset, fieldsArray[FIELD_INDEX_LAST_SYNC_UPDATE]); + this.lastSyncedTimestamp = dateValue(bs, offset, fieldsArray[FIELD_INDEX_LAST_SYNCED_TIMESTAMP]); + this.lastHeartBeatTime = dateValue(bs, offset, fieldsArray[FIELD_INDEX_LAST_HEART_BEAT_TIME]); + this.ifTrunkServer = booleanValue(bs, offset, fieldsArray[FIELD_INDEX_IF_TRUNK_FILE]); + } +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/TrackerClient.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/TrackerClient.java new file mode 100644 index 000000000..a812c5ea8 --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/TrackerClient.java @@ -0,0 +1,811 @@ +/** + * Copyright (C) 2008 Happy Fish / YuQing + *

+ * FastDFS Java Client may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. + */ + +package org.csource.fastdfs; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.Socket; +import java.util.Arrays; + +/** + * Tracker client + * + * @author Happy Fish / YuQing + * @version Version 1.19 + */ +public class TrackerClient { + protected TrackerGroup tracker_group; + protected byte errno; + + /** + * constructor with global tracker group + */ + public TrackerClient() { + this.tracker_group = ClientGlobal.g_tracker_group; + } + + /** + * constructor with specified tracker group + * + * @param tracker_group the tracker group object + */ + public TrackerClient(TrackerGroup tracker_group) { + this.tracker_group = tracker_group; + } + + /** + * get the error code of last call + * + * @return the error code of last call + */ + public byte getErrorCode() { + return this.errno; + } + + /** + * get a connection to tracker server + * + * @return tracker server Socket object, return null if fail + */ + public TrackerServer getConnection() throws IOException { + return this.tracker_group.getConnection(); + } + + /** + * query storage server to upload file + * + * @param trackerServer the tracker server + * @return storage server Socket object, return null if fail + */ + public StorageServer getStoreStorage(TrackerServer trackerServer) throws IOException { + final String groupName = null; + return this.getStoreStorage(trackerServer, groupName); + } + + /** + * query storage server to upload file + * + * @param trackerServer the tracker server + * @param groupName the group name to upload file to, can be empty + * @return storage server object, return null if fail + */ + public StorageServer getStoreStorage(TrackerServer trackerServer, String groupName) throws IOException { + byte[] header; + String ip_addr; + int port; + byte cmd; + int out_len; + boolean bNewConnection; + byte store_path; + Socket trackerSocket; + + if (trackerServer == null) { + trackerServer = getConnection(); + if (trackerServer == null) { + return null; + } + bNewConnection = true; + } else { + bNewConnection = false; + } + + trackerSocket = trackerServer.getSocket(); + OutputStream out = trackerSocket.getOutputStream(); + + try { + if (groupName == null || groupName.length() == 0) { + cmd = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ONE; + out_len = 0; + } else { + cmd = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ONE; + out_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; + } + header = ProtoCommon.packHeader(cmd, out_len, (byte) 0); + out.write(header); + + if (groupName != null && groupName.length() > 0) { + byte[] bGroupName; + byte[] bs; + int group_len; + + bs = groupName.getBytes(ClientGlobal.g_charset); + bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; + + if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) { + group_len = bs.length; + } else { + group_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; + } + Arrays.fill(bGroupName, (byte) 0); + System.arraycopy(bs, 0, bGroupName, 0, group_len); + out.write(bGroupName); + } + + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(), + ProtoCommon.TRACKER_PROTO_CMD_RESP, + ProtoCommon.TRACKER_QUERY_STORAGE_STORE_BODY_LEN); + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return null; + } + + ip_addr = new String(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN, ProtoCommon.FDFS_IPADDR_SIZE - 1).trim(); + + port = (int) ProtoCommon.buff2long(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + + ProtoCommon.FDFS_IPADDR_SIZE - 1); + store_path = pkgInfo.body[ProtoCommon.TRACKER_QUERY_STORAGE_STORE_BODY_LEN - 1]; + + return new StorageServer(ip_addr, port, store_path); + } catch (IOException ex) { + if (!bNewConnection) { + try { + trackerServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } + } + + throw ex; + } finally { + if (bNewConnection) { + try { + trackerServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } + } + } + } + + /** + * query storage servers to upload file + * + * @param trackerServer the tracker server + * @param groupName the group name to upload file to, can be empty + * @return storage servers, return null if fail + */ + public StorageServer[] getStoreStorages(TrackerServer trackerServer, String groupName) throws IOException { + byte[] header; + String ip_addr; + int port; + byte cmd; + int out_len; + boolean bNewConnection; + Socket trackerSocket; + + if (trackerServer == null) { + trackerServer = getConnection(); + if (trackerServer == null) { + return null; + } + bNewConnection = true; + } else { + bNewConnection = false; + } + + trackerSocket = trackerServer.getSocket(); + OutputStream out = trackerSocket.getOutputStream(); + + try { + if (groupName == null || groupName.length() == 0) { + cmd = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ALL; + out_len = 0; + } else { + cmd = ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ALL; + out_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; + } + header = ProtoCommon.packHeader(cmd, out_len, (byte) 0); + out.write(header); + + if (groupName != null && groupName.length() > 0) { + byte[] bGroupName; + byte[] bs; + int group_len; + + bs = groupName.getBytes(ClientGlobal.g_charset); + bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; + + if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) { + group_len = bs.length; + } else { + group_len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; + } + Arrays.fill(bGroupName, (byte) 0); + System.arraycopy(bs, 0, bGroupName, 0, group_len); + out.write(bGroupName); + } + + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(), + ProtoCommon.TRACKER_PROTO_CMD_RESP, -1); + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return null; + } + + if (pkgInfo.body.length < ProtoCommon.TRACKER_QUERY_STORAGE_STORE_BODY_LEN) { + this.errno = ProtoCommon.ERR_NO_EINVAL; + return null; + } + + int ipPortLen = pkgInfo.body.length - (ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + 1); + final int recordLength = ProtoCommon.FDFS_IPADDR_SIZE - 1 + ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + if (ipPortLen % recordLength != 0) { + this.errno = ProtoCommon.ERR_NO_EINVAL; + return null; + } + + int serverCount = ipPortLen / recordLength; + if (serverCount > 16) { + this.errno = ProtoCommon.ERR_NO_ENOSPC; + return null; + } + + StorageServer[] results = new StorageServer[serverCount]; + byte store_path = pkgInfo.body[pkgInfo.body.length - 1]; + int offset = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; + + for (int i = 0; i < serverCount; i++) { + ip_addr = new String(pkgInfo.body, offset, ProtoCommon.FDFS_IPADDR_SIZE - 1).trim(); + offset += ProtoCommon.FDFS_IPADDR_SIZE - 1; + + port = (int) ProtoCommon.buff2long(pkgInfo.body, offset); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + results[i] = new StorageServer(ip_addr, port, store_path); + } + + return results; + } catch (IOException ex) { + if (!bNewConnection) { + try { + trackerServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } + } + + throw ex; + } finally { + if (bNewConnection) { + try { + trackerServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } + } + } + } + + /** + * query storage server to download file + * + * @param trackerServer the tracker server + * @param groupName the group name of storage server + * @param filename filename on storage server + * @return storage server Socket object, return null if fail + */ + public StorageServer getFetchStorage(TrackerServer trackerServer, + String groupName, String filename) throws IOException { + ServerInfo[] servers = this.getStorages(trackerServer, ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ONE, + groupName, filename); + if (servers == null) { + return null; + } else { + return new StorageServer(servers[0].getIpAddr(), servers[0].getPort(), 0); + } + } + + /** + * query storage server to update file (delete file or set meta data) + * + * @param trackerServer the tracker server + * @param groupName the group name of storage server + * @param filename filename on storage server + * @return storage server Socket object, return null if fail + */ + public StorageServer getUpdateStorage(TrackerServer trackerServer, + String groupName, String filename) throws IOException { + ServerInfo[] servers = this.getStorages(trackerServer, ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_UPDATE, + groupName, filename); + if (servers == null) { + return null; + } else { + return new StorageServer(servers[0].getIpAddr(), servers[0].getPort(), 0); + } + } + + /** + * get storage servers to download file + * + * @param trackerServer the tracker server + * @param groupName the group name of storage server + * @param filename filename on storage server + * @return storage servers, return null if fail + */ + public ServerInfo[] getFetchStorages(TrackerServer trackerServer, + String groupName, String filename) throws IOException { + return this.getStorages(trackerServer, ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ALL, + groupName, filename); + } + + /** + * query storage server to download file + * + * @param trackerServer the tracker server + * @param cmd command code, ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ONE or + * ProtoCommon.TRACKER_PROTO_CMD_SERVICE_QUERY_UPDATE + * @param groupName the group name of storage server + * @param filename filename on storage server + * @return storage server Socket object, return null if fail + */ + protected ServerInfo[] getStorages(TrackerServer trackerServer, + byte cmd, String groupName, String filename) throws IOException { + byte[] header; + byte[] bFileName; + byte[] bGroupName; + byte[] bs; + int len; + String ip_addr; + int port; + boolean bNewConnection; + Socket trackerSocket; + + if (trackerServer == null) { + trackerServer = getConnection(); + if (trackerServer == null) { + return null; + } + bNewConnection = true; + } else { + bNewConnection = false; + } + trackerSocket = trackerServer.getSocket(); + OutputStream out = trackerSocket.getOutputStream(); + + try { + bs = groupName.getBytes(ClientGlobal.g_charset); + bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; + bFileName = filename.getBytes(ClientGlobal.g_charset); + + if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) { + len = bs.length; + } else { + len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; + } + Arrays.fill(bGroupName, (byte) 0); + System.arraycopy(bs, 0, bGroupName, 0, len); + + header = ProtoCommon.packHeader(cmd, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + bFileName.length, (byte) 0); + byte[] wholePkg = new byte[header.length + bGroupName.length + bFileName.length]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + System.arraycopy(bGroupName, 0, wholePkg, header.length, bGroupName.length); + System.arraycopy(bFileName, 0, wholePkg, header.length + bGroupName.length, bFileName.length); + out.write(wholePkg); + + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(), + ProtoCommon.TRACKER_PROTO_CMD_RESP, -1); + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return null; + } + + if (pkgInfo.body.length < ProtoCommon.TRACKER_QUERY_STORAGE_FETCH_BODY_LEN) { + throw new IOException("Invalid body length: " + pkgInfo.body.length); + } + + if ((pkgInfo.body.length - ProtoCommon.TRACKER_QUERY_STORAGE_FETCH_BODY_LEN) % (ProtoCommon.FDFS_IPADDR_SIZE - 1) != 0) { + throw new IOException("Invalid body length: " + pkgInfo.body.length); + } + + int server_count = 1 + (pkgInfo.body.length - ProtoCommon.TRACKER_QUERY_STORAGE_FETCH_BODY_LEN) / (ProtoCommon.FDFS_IPADDR_SIZE - 1); + + ip_addr = new String(pkgInfo.body, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN, ProtoCommon.FDFS_IPADDR_SIZE - 1).trim(); + int offset = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + ProtoCommon.FDFS_IPADDR_SIZE - 1; + + port = (int) ProtoCommon.buff2long(pkgInfo.body, offset); + offset += ProtoCommon.FDFS_PROTO_PKG_LEN_SIZE; + + ServerInfo[] servers = new ServerInfo[server_count]; + servers[0] = new ServerInfo(ip_addr, port); + for (int i = 1; i < server_count; i++) { + servers[i] = new ServerInfo(new String(pkgInfo.body, offset, ProtoCommon.FDFS_IPADDR_SIZE - 1).trim(), port); + offset += ProtoCommon.FDFS_IPADDR_SIZE - 1; + } + + return servers; + } catch (IOException ex) { + if (!bNewConnection) { + try { + trackerServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } + } + + throw ex; + } finally { + if (bNewConnection) { + try { + trackerServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } + } + } + } + + /** + * query storage server to download file + * + * @param trackerServer the tracker server + * @param file_id the file id(including group name and filename) + * @return storage server Socket object, return null if fail + */ + public StorageServer getFetchStorage1(TrackerServer trackerServer, String file_id) throws IOException { + String[] parts = new String[2]; + this.errno = StorageClient1.split_file_id(file_id, parts); + if (this.errno != 0) { + return null; + } + + return this.getFetchStorage(trackerServer, parts[0], parts[1]); + } + + /** + * get storage servers to download file + * + * @param trackerServer the tracker server + * @param file_id the file id(including group name and filename) + * @return storage servers, return null if fail + */ + public ServerInfo[] getFetchStorages1(TrackerServer trackerServer, String file_id) throws IOException { + String[] parts = new String[2]; + this.errno = StorageClient1.split_file_id(file_id, parts); + if (this.errno != 0) { + return null; + } + + return this.getFetchStorages(trackerServer, parts[0], parts[1]); + } + + /** + * list groups + * + * @param trackerServer the tracker server + * @return group stat array, return null if fail + */ + public StructGroupStat[] listGroups(TrackerServer trackerServer) throws IOException { + byte[] header; + String ip_addr; + int port; + byte cmd; + int out_len; + boolean bNewConnection; + byte store_path; + Socket trackerSocket; + + if (trackerServer == null) { + trackerServer = getConnection(); + if (trackerServer == null) { + return null; + } + bNewConnection = true; + } else { + bNewConnection = false; + } + + trackerSocket = trackerServer.getSocket(); + OutputStream out = trackerSocket.getOutputStream(); + + try { + header = ProtoCommon.packHeader(ProtoCommon.TRACKER_PROTO_CMD_SERVER_LIST_GROUP, 0, (byte) 0); + out.write(header); + + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(), + ProtoCommon.TRACKER_PROTO_CMD_RESP, -1); + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return null; + } + + ProtoStructDecoder decoder = new ProtoStructDecoder(); + return decoder.decode(pkgInfo.body, StructGroupStat.class, StructGroupStat.getFieldsTotalSize()); + } catch (IOException ex) { + if (!bNewConnection) { + try { + trackerServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } + } + + throw ex; + } catch (Exception ex) { + ex.printStackTrace(); + this.errno = ProtoCommon.ERR_NO_EINVAL; + return null; + } finally { + if (bNewConnection) { + try { + trackerServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } + } + } + } + + /** + * query storage server stat info of the group + * + * @param trackerServer the tracker server + * @param groupName the group name of storage server + * @return storage server stat array, return null if fail + */ + public StructStorageStat[] listStorages(TrackerServer trackerServer, String groupName) throws IOException { + final String storageIpAddr = null; + return this.listStorages(trackerServer, groupName, storageIpAddr); + } + + /** + * query storage server stat info of the group + * + * @param trackerServer the tracker server + * @param groupName the group name of storage server + * @param storageIpAddr the storage server ip address, can be null or empty + * @return storage server stat array, return null if fail + */ + public StructStorageStat[] listStorages(TrackerServer trackerServer, + String groupName, String storageIpAddr) throws IOException { + byte[] header; + byte[] bGroupName; + byte[] bs; + int len; + boolean bNewConnection; + Socket trackerSocket; + + if (trackerServer == null) { + trackerServer = getConnection(); + if (trackerServer == null) { + return null; + } + bNewConnection = true; + } else { + bNewConnection = false; + } + trackerSocket = trackerServer.getSocket(); + OutputStream out = trackerSocket.getOutputStream(); + + try { + bs = groupName.getBytes(ClientGlobal.g_charset); + bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; + + if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) { + len = bs.length; + } else { + len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; + } + Arrays.fill(bGroupName, (byte) 0); + System.arraycopy(bs, 0, bGroupName, 0, len); + + int ipAddrLen; + byte[] bIpAddr; + if (storageIpAddr != null && storageIpAddr.length() > 0) { + bIpAddr = storageIpAddr.getBytes(ClientGlobal.g_charset); + if (bIpAddr.length < ProtoCommon.FDFS_IPADDR_SIZE) { + ipAddrLen = bIpAddr.length; + } else { + ipAddrLen = ProtoCommon.FDFS_IPADDR_SIZE - 1; + } + } else { + bIpAddr = null; + ipAddrLen = 0; + } + + header = ProtoCommon.packHeader(ProtoCommon.TRACKER_PROTO_CMD_SERVER_LIST_STORAGE, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + ipAddrLen, (byte) 0); + byte[] wholePkg = new byte[header.length + bGroupName.length + ipAddrLen]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + System.arraycopy(bGroupName, 0, wholePkg, header.length, bGroupName.length); + if (ipAddrLen > 0) { + System.arraycopy(bIpAddr, 0, wholePkg, header.length + bGroupName.length, ipAddrLen); + } + out.write(wholePkg); + + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(), + ProtoCommon.TRACKER_PROTO_CMD_RESP, -1); + this.errno = pkgInfo.errno; + if (pkgInfo.errno != 0) { + return null; + } + + ProtoStructDecoder decoder = new ProtoStructDecoder(); + return decoder.decode(pkgInfo.body, StructStorageStat.class, StructStorageStat.getFieldsTotalSize()); + } catch (IOException ex) { + if (!bNewConnection) { + try { + trackerServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } + } + + throw ex; + } catch (Exception ex) { + ex.printStackTrace(); + this.errno = ProtoCommon.ERR_NO_EINVAL; + return null; + } finally { + if (bNewConnection) { + try { + trackerServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } + } + } + } + + /** + * delete a storage server from the tracker server + * + * @param trackerServer the connected tracker server + * @param groupName the group name of storage server + * @param storageIpAddr the storage server ip address + * @return true for success, false for fail + */ + private boolean deleteStorage(TrackerServer trackerServer, + String groupName, String storageIpAddr) throws IOException { + byte[] header; + byte[] bGroupName; + byte[] bs; + int len; + Socket trackerSocket; + + trackerSocket = trackerServer.getSocket(); + OutputStream out = trackerSocket.getOutputStream(); + + bs = groupName.getBytes(ClientGlobal.g_charset); + bGroupName = new byte[ProtoCommon.FDFS_GROUP_NAME_MAX_LEN]; + + if (bs.length <= ProtoCommon.FDFS_GROUP_NAME_MAX_LEN) { + len = bs.length; + } else { + len = ProtoCommon.FDFS_GROUP_NAME_MAX_LEN; + } + Arrays.fill(bGroupName, (byte) 0); + System.arraycopy(bs, 0, bGroupName, 0, len); + + int ipAddrLen; + byte[] bIpAddr = storageIpAddr.getBytes(ClientGlobal.g_charset); + if (bIpAddr.length < ProtoCommon.FDFS_IPADDR_SIZE) { + ipAddrLen = bIpAddr.length; + } else { + ipAddrLen = ProtoCommon.FDFS_IPADDR_SIZE - 1; + } + + header = ProtoCommon.packHeader(ProtoCommon.TRACKER_PROTO_CMD_SERVER_DELETE_STORAGE, ProtoCommon.FDFS_GROUP_NAME_MAX_LEN + ipAddrLen, (byte) 0); + byte[] wholePkg = new byte[header.length + bGroupName.length + ipAddrLen]; + System.arraycopy(header, 0, wholePkg, 0, header.length); + System.arraycopy(bGroupName, 0, wholePkg, header.length, bGroupName.length); + System.arraycopy(bIpAddr, 0, wholePkg, header.length + bGroupName.length, ipAddrLen); + out.write(wholePkg); + + ProtoCommon.RecvPackageInfo pkgInfo = ProtoCommon.recvPackage(trackerSocket.getInputStream(), + ProtoCommon.TRACKER_PROTO_CMD_RESP, 0); + this.errno = pkgInfo.errno; + return pkgInfo.errno == 0; + } + + /** + * delete a storage server from the global FastDFS cluster + * + * @param groupName the group name of storage server + * @param storageIpAddr the storage server ip address + * @return true for success, false for fail + */ + public boolean deleteStorage(String groupName, String storageIpAddr) throws IOException { + return this.deleteStorage(ClientGlobal.g_tracker_group, groupName, storageIpAddr); + } + + /** + * delete a storage server from the FastDFS cluster + * + * @param trackerGroup the tracker server group + * @param groupName the group name of storage server + * @param storageIpAddr the storage server ip address + * @return true for success, false for fail + */ + public boolean deleteStorage(TrackerGroup trackerGroup, + String groupName, String storageIpAddr) throws IOException { + int serverIndex; + int notFoundCount; + TrackerServer trackerServer; + + notFoundCount = 0; + for (serverIndex = 0; serverIndex < trackerGroup.tracker_servers.length; serverIndex++) { + try { + trackerServer = trackerGroup.getConnection(serverIndex); + } catch (IOException ex) { + ex.printStackTrace(System.err); + this.errno = ProtoCommon.ECONNREFUSED; + return false; + } + + try { + StructStorageStat[] storageStats = listStorages(trackerServer, groupName, storageIpAddr); + if (storageStats == null) { + if (this.errno == ProtoCommon.ERR_NO_ENOENT) { + notFoundCount++; + } else { + return false; + } + } else if (storageStats.length == 0) { + notFoundCount++; + } else if (storageStats[0].getStatus() == ProtoCommon.FDFS_STORAGE_STATUS_ONLINE || + storageStats[0].getStatus() == ProtoCommon.FDFS_STORAGE_STATUS_ACTIVE) { + this.errno = ProtoCommon.ERR_NO_EBUSY; + return false; + } + } finally { + try { + trackerServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } + } + } + + if (notFoundCount == trackerGroup.tracker_servers.length) { + this.errno = ProtoCommon.ERR_NO_ENOENT; + return false; + } + + notFoundCount = 0; + for (serverIndex = 0; serverIndex < trackerGroup.tracker_servers.length; serverIndex++) { + try { + trackerServer = trackerGroup.getConnection(serverIndex); + } catch (IOException ex) { + System.err.println("connect to server " + trackerGroup.tracker_servers[serverIndex].getAddress().getHostAddress() + ":" + trackerGroup.tracker_servers[serverIndex].getPort() + " fail"); + ex.printStackTrace(System.err); + this.errno = ProtoCommon.ECONNREFUSED; + return false; + } + + try { + if (!this.deleteStorage(trackerServer, groupName, storageIpAddr)) { + if (this.errno != 0) { + if (this.errno == ProtoCommon.ERR_NO_ENOENT) { + notFoundCount++; + } else if (this.errno != ProtoCommon.ERR_NO_EALREADY) { + return false; + } + } + } + } finally { + try { + trackerServer.close(); + } catch (IOException ex1) { + ex1.printStackTrace(); + } + } + } + + if (notFoundCount == trackerGroup.tracker_servers.length) { + this.errno = ProtoCommon.ERR_NO_ENOENT; + return false; + } + + if (this.errno == ProtoCommon.ERR_NO_ENOENT) { + this.errno = 0; + } + + return this.errno == 0; + } +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/TrackerGroup.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/TrackerGroup.java new file mode 100644 index 000000000..d0d3a53e7 --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/TrackerGroup.java @@ -0,0 +1,107 @@ +/** + * Copyright (C) 2008 Happy Fish / YuQing + *

+ * FastDFS Java Client may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. + */ + +package org.csource.fastdfs; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; + +/** + * Tracker server group + * + * @author Happy Fish / YuQing + * @version Version 1.17 + */ +public class TrackerGroup { + public int tracker_server_index; + public InetSocketAddress[] tracker_servers; + protected Integer lock; + + /** + * Constructor + * + * @param tracker_servers tracker servers + */ + public TrackerGroup(InetSocketAddress[] tracker_servers) { + this.tracker_servers = tracker_servers; + this.lock = new Integer(0); + this.tracker_server_index = 0; + } + + /** + * return connected tracker server + * + * @return connected tracker server, null for fail + */ + public TrackerServer getConnection(int serverIndex) throws IOException { + Socket sock = new Socket(); + sock.setReuseAddress(true); + sock.setSoTimeout(ClientGlobal.g_network_timeout); + sock.connect(this.tracker_servers[serverIndex], ClientGlobal.g_connect_timeout); + return new TrackerServer(sock, this.tracker_servers[serverIndex]); + } + + /** + * return connected tracker server + * + * @return connected tracker server, null for fail + */ + public TrackerServer getConnection() throws IOException { + int current_index; + + synchronized (this.lock) { + this.tracker_server_index++; + if (this.tracker_server_index >= this.tracker_servers.length) { + this.tracker_server_index = 0; + } + + current_index = this.tracker_server_index; + } + + try { + return this.getConnection(current_index); + } catch (IOException ex) { + System.err.println("connect to server " + this.tracker_servers[current_index].getAddress().getHostAddress() + ":" + this.tracker_servers[current_index].getPort() + " fail"); + ex.printStackTrace(System.err); + } + + for (int i = 0; i < this.tracker_servers.length; i++) { + if (i == current_index) { + continue; + } + + try { + TrackerServer trackerServer = this.getConnection(i); + + synchronized (this.lock) { + if (this.tracker_server_index == current_index) { + this.tracker_server_index = i; + } + } + + return trackerServer; + } catch (IOException ex) { + System.err.println("connect to server " + this.tracker_servers[i].getAddress().getHostAddress() + ":" + this.tracker_servers[i].getPort() + " fail"); + ex.printStackTrace(System.err); + } + } + + return null; + } + + public Object clone() { + InetSocketAddress[] trackerServers = new InetSocketAddress[this.tracker_servers.length]; + for (int i = 0; i < trackerServers.length; i++) { + trackerServers[i] = new InetSocketAddress(this.tracker_servers[i].getAddress().getHostAddress(), this.tracker_servers[i].getPort()); + } + + return new TrackerGroup(trackerServers); + } +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/TrackerServer.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/TrackerServer.java new file mode 100644 index 000000000..dfc11b02e --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/TrackerServer.java @@ -0,0 +1,81 @@ +/** + * Copyright (C) 2008 Happy Fish / YuQing + *

+ * FastDFS Java Client may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. + */ + +package org.csource.fastdfs; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.Socket; + +/** + * Tracker Server Info + * + * @author Happy Fish / YuQing + * @version Version 1.11 + */ +public class TrackerServer { + protected Socket sock; + protected InetSocketAddress inetSockAddr; + + /** + * Constructor + * + * @param sock Socket of server + * @param inetSockAddr the server info + */ + public TrackerServer(Socket sock, InetSocketAddress inetSockAddr) { + this.sock = sock; + this.inetSockAddr = inetSockAddr; + } + + /** + * get the connected socket + * + * @return the socket + */ + public Socket getSocket() throws IOException { + if (this.sock == null) { + this.sock = ClientGlobal.getSocket(this.inetSockAddr); + } + + return this.sock; + } + + /** + * get the server info + * + * @return the server info + */ + public InetSocketAddress getInetSocketAddress() { + return this.inetSockAddr; + } + + public OutputStream getOutputStream() throws IOException { + return this.sock.getOutputStream(); + } + + public InputStream getInputStream() throws IOException { + return this.sock.getInputStream(); + } + + public void close() throws IOException { + if (this.sock != null) { + try { + ProtoCommon.closeSocket(this.sock); + } finally { + this.sock = null; + } + } + } + + protected void finalize() throws Throwable { + this.close(); + } +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/UploadCallback.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/UploadCallback.java new file mode 100644 index 000000000..f388b46f2 --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/UploadCallback.java @@ -0,0 +1,28 @@ +/** + * Copyright (C) 2008 Happy Fish / YuQing + *

+ * FastDFS Java Client may be copied only under the terms of the GNU Lesser + * General Public License (LGPL). + * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. + */ + +package org.csource.fastdfs; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * upload file callback interface + * + * @author Happy Fish / YuQing + * @version Version 1.0 + */ +public interface UploadCallback { + /** + * send file content callback function, be called only once when the file uploaded + * + * @param out output stream for writing file content + * @return 0 success, return none zero(errno) if fail + */ + public int send(OutputStream out) throws IOException; +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/UploadStream.java b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/UploadStream.java new file mode 100644 index 000000000..56fd20b05 --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/java/org/csource/fastdfs/UploadStream.java @@ -0,0 +1,55 @@ +package org.csource.fastdfs; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * Upload file by stream + * + * @author zhouzezhong & Happy Fish / YuQing + * @version Version 1.11 + */ +public class UploadStream implements UploadCallback { + private InputStream inputStream; //input stream for reading + private long fileSize = 0; //size of the uploaded file + + /** + * constructor + * + * @param inputStream input stream for uploading + * @param fileSize size of uploaded file + */ + public UploadStream(InputStream inputStream, long fileSize) { + super(); + this.inputStream = inputStream; + this.fileSize = fileSize; + } + + /** + * send file content callback function, be called only once when the file uploaded + * + * @param out output stream for writing file content + * @return 0 success, return none zero(errno) if fail + */ + public int send(OutputStream out) throws IOException { + long remainBytes = fileSize; + byte[] buff = new byte[256 * 1024]; + int bytes; + while (remainBytes > 0) { + try { + if ((bytes = inputStream.read(buff, 0, remainBytes > buff.length ? buff.length : (int) remainBytes)) < 0) { + return -1; + } + } catch (IOException ex) { + ex.printStackTrace(); + return -1; + } + + out.write(buff, 0, bytes); + remainBytes -= bytes; + } + + return 0; + } +} diff --git a/psi-java/fastdfs-spring-boot-starter/src/main/resources/META-INF/spring-configuration-metadata.json b/psi-java/fastdfs-spring-boot-starter/src/main/resources/META-INF/spring-configuration-metadata.json new file mode 100644 index 000000000..ad9475a13 --- /dev/null +++ b/psi-java/fastdfs-spring-boot-starter/src/main/resources/META-INF/spring-configuration-metadata.json @@ -0,0 +1,85 @@ +{ + "groups": [ + { + "name": "fastdfs", + "type": "io.github.bluemiaomiao.properties.FastdfsProperties", + "sourceType": "io.github.bluemiaomiao.properties.FastdfsProperties" + } + ], + "properties": [ + { + "name": "connectTimeout", + "type": "java.lang.String", + "sourceType": "io.github.bluemiaomiao.properties.FastdfsProperties", + "defaultValue": "5" + }, + { + "name": "networkTimeout", + "type": "java.lang.String", + "sourceType": "io.github.bluemiaomiao.properties.FastdfsProperties", + "defaultValue": "30" + }, + { + "name": "charset", + "type": "java.lang.String", + "defaultValue": "UTF-8" + }, + { + "name": "httpAntiStealToken", + "type": "java.lang.String", + "sourceType": "io.github.bluemiaomiao.properties.FastdfsProperties", + "defaultValue": "false" + }, + { + "name": "httpSecretKey", + "type": "java.lang.String", + "sourceType": "io.github.bluemiaomiao.properties.FastdfsProperties" + }, + { + "name": "httpTrackerHttpPort", + "type": "java.lang.Integer", + "sourceType": "io.github.bluemiaomiao.properties.FastdfsProperties" + }, + { + "name": "trackerServers", + "type": "java.lang.String", + "sourceType": "io.github.bluemiaomiao.properties.FastdfsProperties" + }, + { + "name": "connectionPoolMaxTotal", + "type": "java.lang.Integer", + "sourceType": "io.github.bluemiaomiao.properties.FastdfsProperties", + "defaultValue": "18" + }, + { + "name": "connectionPoolMaxIdle", + "type": "java.lang.Integer", + "sourceType": "io.github.bluemiaomiao.properties.FastdfsProperties", + "defaultValue": "18" + }, + { + "name": "connectionPoolMinIdle", + "type": "java.lang.Integer", + "sourceType": "io.github.bluemiaomiao.properties.FastdfsProperties", + "defaultValue": "2" + }, + { + "name": "nginxServers", + "type": "java.lang.String", + "sourceType": "io.github.bluemiaomiao.properties.FastdfsProperties" + } + ], + "hints": [ + { + "name": "http_anti_steal_token", + "values": [ + { + "value": "false" + }, + { + "value": "true" + } + ] + } + ] +} \ No newline at end of file diff --git a/psi-java/pom.xml b/psi-java/pom.xml new file mode 100644 index 000000000..a10f6743f --- /dev/null +++ b/psi-java/pom.xml @@ -0,0 +1,339 @@ + + + 4.0.0 + + org.springframework.cloud + spring-cloud-build + 2.3.5.RELEASE + + + com.zeroone.star + psi-java + ${revision} + pom + + code-generator + fastdfs-spring-boot-starter + psi-common + psi-domain + psi-apis + psi-oauth2 + psi-gateway + psi-login + psi-prepayment + + + + true + + 1.0.0-SNAPSHOT + Hoxton.SR12 + 2.2.8.RELEASE + 3.4.3.4 + 3.5.1 + 8.0.25 + 1.2.8 + 2.0.8 + 2.0.8 + 5.8.9 + 8.21 + 3.0.5 + + 1.3.2 + 2.3 + 0.40.2 + 6.6 + 2.3.1 + 3.0.1 + 1.0.3 + 7.14.0 + 1.3.0 + + + + + org.projectlombok + lombok + true + + + + cn.hutool + hutool-all + true + + + + org.springframework.boot + spring-boot-starter-actuator + true + + + + org.springframework.boot + spring-boot-starter-test + + + + + + + com.zeroone.star + psi-apis + ${revision} + + + com.zeroone.star + psi-common + ${revision} + + + com.zeroone.star + psi-domain + ${revision} + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring.cloud.version} + pom + import + + + + com.alibaba.cloud + spring-cloud-alibaba-dependencies + ${spring.cloud.alibaba.version} + pom + import + + + + cn.hutool + hutool-all + ${hutool.version} + + + + org.springframework.boot + spring-boot-starter-test + ${spring-boot.version} + test + + + org.junit.vintage + junit-vintage-engine + + + + + + + org.springframework.boot + spring-boot-starter-actuator + ${spring-boot.version} + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + + + + com.baomidou + mybatis-plus-boot-starter + ${mybaits.plus.version} + + + com.baomidou + mybatis-plus-extension + ${mybaits.plus.version} + + + + com.baomidou + mybatis-plus-generator + ${mybaits.plus.generator.version} + + + org.apache.velocity + velocity-engine-core + ${apache.velocity.version} + + + + com.alibaba + druid + ${durid.version} + + + com.alibaba + druid-spring-boot-starter + ${durid.version} + + + + mysql + mysql-connector-java + ${mysql.version} + runtime + + + + com.github.xiaoymin + knife4j-spring-boot-starter + ${knife4j.version} + + + com.github.xiaoymin + knife4j-aggregation-spring-boot-starter + ${knife4j.aggregation.version} + + + cn.hutool + hutool-all + + + + + + com.nimbusds + nimbus-jose-jwt + ${jwt.version} + + + + com.alibaba + easyexcel + ${easyexcel.version} + + + + + com.zeroone.star + fastdfs-spring-boot-starter + ${revision} + + + commons-io + commons-io + ${apache.common.io.version} + + + + net.logstash.logback + logstash-logback-encoder + ${logstash-logback-encoder.version} + + + + de.codecentric + spring-boot-admin-starter-server + ${spring-boot-admin.version} + + + + de.codecentric + spring-boot-admin-starter-client + ${spring-boot-admin.version} + + + + com.google.code.findbugs + annotations + ${gc.findbugs.version} + + + + cn.easy-es + easy-es-boot-starter + ${ee.version} + + + org.elasticsearch.client + elasticsearch-rest-high-level-client + ${es.client.version} + + + org.elasticsearch + elasticsearch + ${es.client.version} + + + + com.anji-plus + spring-boot-starter-captcha + ${captcha.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${java.version} + ${java.version} + UTF-8 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + repackage + + repackage + + + + + + io.fabric8 + docker-maven-plugin + ${docker.maven.plugin.version} + + + + + + diff --git a/psi-java/psi-apis/README.md b/psi-java/psi-apis/README.md new file mode 100644 index 000000000..44681eff7 --- /dev/null +++ b/psi-java/psi-apis/README.md @@ -0,0 +1,3 @@ +# 工程简介 +用于定义`API`接口,方便后续实现,所有`API`接口需要定义在这里 + diff --git a/psi-java/psi-apis/pom.xml b/psi-java/psi-apis/pom.xml new file mode 100644 index 000000000..ca18b470f --- /dev/null +++ b/psi-java/psi-apis/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + + psi-java + com.zeroone.star + ${revision} + ../pom.xml + + psi-apis + + + + com.zeroone.star + psi-domain + + + org.springframework + spring-web + + + com.zeroone.star + psi-common + + + diff --git a/psi-java/psi-apis/src/main/java/com/zeroone/star/project/cpp/SampleApis.java b/psi-java/psi-apis/src/main/java/com/zeroone/star/project/cpp/SampleApis.java new file mode 100644 index 000000000..91e8e3f74 --- /dev/null +++ b/psi-java/psi-apis/src/main/java/com/zeroone/star/project/cpp/SampleApis.java @@ -0,0 +1,54 @@ +package com.zeroone.star.project.cpp; + +import com.zeroone.star.project.dto.cpp.SampleDTO; +import com.zeroone.star.project.query.cpp.SampleQuery; +import com.zeroone.star.project.vo.JsonVO; +import com.zeroone.star.project.vo.PageVO; +import com.zeroone.star.project.vo.cpp.SampleVO; + +/** + *

+ * 描述:获取cpp模块接口定义 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +public interface SampleApis { + /** + * 获取cpp中的数据接口 + * @param query 查询对象 + * @return 查询结果 + */ + JsonVO> queryAll(SampleQuery query); + + /** + * 添加数据到数据库 + * @param dto 数据对象 + * @return 新增数据唯一编号 + */ + JsonVO addData(SampleDTO dto); + + /** + * 修改数据 + * @param dto 修改数据内容 + * @return 修改后的数据 + */ + JsonVO modifyData(SampleDTO dto); + + /** + * 删除数据 + * @param dto 删除数据对象 + * @return 删除数据的编号 + */ + JsonVO removeData(SampleDTO dto); + + /** + * 测试提交Json数据 + * @param dto 提交数据 + * @return 提交数据结果 + */ + JsonVO testJson(SampleDTO dto); +} diff --git a/psi-java/psi-apis/src/main/java/com/zeroone/star/project/login/LoginApis.java b/psi-java/psi-apis/src/main/java/com/zeroone/star/project/login/LoginApis.java new file mode 100644 index 000000000..fd5d7e0ca --- /dev/null +++ b/psi-java/psi-apis/src/main/java/com/zeroone/star/project/login/LoginApis.java @@ -0,0 +1,55 @@ +package com.zeroone.star.project.login; + +import com.zeroone.star.project.dto.login.LoginDTO; +import com.zeroone.star.project.dto.login.Oauth2TokenDTO; +import com.zeroone.star.project.vo.JsonVO; +import com.zeroone.star.project.vo.TreeNodeVO; +import com.zeroone.star.project.vo.login.LoginVO; +import com.zeroone.star.project.vo.login.MenuTreeVO; + +import java.util.List; + +/** + *

+ * 描述:用户登录接口 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +public interface LoginApis { + /** + * 授权登录接口 + * @param loginDTO 登录数据 + * @return 授权登录结果 + */ + JsonVO authLogin(LoginDTO loginDTO); + + /** + * 刷新Token认证 + * @param oauth2TokenDTO Token数据对象 + * @return 刷新Token结果 + */ + JsonVO refreshToken(Oauth2TokenDTO oauth2TokenDTO); + + /** + * 获取当前用户信息 + * @return 返回当前用户信息 + */ + JsonVO getCurrUser(); + + /** + * 退出登录 + * @return 退出结果 + */ + JsonVO logout(); + + /** + * 获取菜单数据 + * @return 菜单数据 + * @throws Exception 异常信息 + */ + JsonVO>> getMenus() throws Exception; +} diff --git a/psi-java/psi-apis/src/main/java/com/zeroone/star/project/oauth/AuthApis.java b/psi-java/psi-apis/src/main/java/com/zeroone/star/project/oauth/AuthApis.java new file mode 100644 index 000000000..1a4f1f55c --- /dev/null +++ b/psi-java/psi-apis/src/main/java/com/zeroone/star/project/oauth/AuthApis.java @@ -0,0 +1,27 @@ +package com.zeroone.star.project.oauth; + +import com.zeroone.star.project.dto.login.Oauth2TokenDTO; +import com.zeroone.star.project.vo.JsonVO; + +import java.security.Principal; +import java.util.Map; + +/** + *

+ * 描述:认证授权接口 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +public interface AuthApis { + /** + * 授权认证接口 + * @param principal 安全主体对象 + * @param parameters 传递参数 + * @return 响应结果 + */ + JsonVO postAccessToken(Principal principal, Map parameters); +} diff --git a/psi-java/psi-apis/src/main/java/com/zeroone/star/project/oauth/KeyPairApis.java b/psi-java/psi-apis/src/main/java/com/zeroone/star/project/oauth/KeyPairApis.java new file mode 100644 index 000000000..3b13a6322 --- /dev/null +++ b/psi-java/psi-apis/src/main/java/com/zeroone/star/project/oauth/KeyPairApis.java @@ -0,0 +1,27 @@ +package com.zeroone.star.project.oauth; + +import java.util.Map; + +/** + *

+ * 描述:密钥接口 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +public interface KeyPairApis { + /** + * 获取公钥 + * @return 返回公钥数据 + */ + Map getPublicKey(); + + /** + * 获取私钥 + * @return 返回私钥数据 + */ + Map getPrivateKey(); +} diff --git a/psi-java/psi-apis/src/main/java/com/zeroone/star/project/prepayment/PrepaymentApis.java b/psi-java/psi-apis/src/main/java/com/zeroone/star/project/prepayment/PrepaymentApis.java new file mode 100644 index 000000000..59e9d0022 --- /dev/null +++ b/psi-java/psi-apis/src/main/java/com/zeroone/star/project/prepayment/PrepaymentApis.java @@ -0,0 +1,136 @@ +package com.zeroone.star.project.prepayment; + +import com.zeroone.star.project.dto.prepayment.*; +import com.zeroone.star.project.query.prepayment.*; +import com.zeroone.star.project.vo.JsonVO; + +import com.zeroone.star.project.vo.PageVO; +import com.zeroone.star.project.vo.prepayment.DocListVO; + + +import com.zeroone.star.project.vo.prepayment.DetHavVO; +import com.zeroone.star.project.vo.prepayment.DetNoVO; + +import org.springframework.http.ResponseEntity; + +import com.zeroone.star.project.vo.prepayment.SupplierVO; + +import java.util.List; + +import com.zeroone.star.project.vo.prepayment.PaymentReqEntryVO; +import org.springframework.web.multipart.MultipartFile; + +import com.zeroone.star.project.dto.prepayment.*; +import com.zeroone.star.project.vo.JsonVO; +import com.zeroone.star.project.query.prepayment.DocListQuery; +import com.zeroone.star.project.vo.PageVO; +import com.zeroone.star.project.vo.prepayment.*; +import com.zeroone.star.project.query.prepayment.PreDetQuery; +import org.springframework.http.ResponseEntity; +import java.util.List; +import org.springframework.web.multipart.MultipartFile; + +/** + *

+ * 描述:API接口定义 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author forever爱 + * @version 1.0.0 + */ +public interface PrepaymentApis { + /** + * 修改采购预付单功能 + * param modifyDTO 带明细表的收款单DTO + * return 查询结果 + * author forever爱 + */ + JsonVO modify(ModifyDTO modifyDTO); + + /** + * 审核采购预付单功能 + * param auditDTO 审核DTO + * return 查询结果 + * author forever爱 + */ + JsonVO auditById(AuditDTO auditDTO); + + /** + * 保存采购预付单功能 + * param ModifyDTO 保存DTO + * return 查询结果 + * author forever爱 + */ + JsonVO save(ModifyDTO modifyDTO); + + /** + * 单据列表查询(有申请)和(无申请) + * param condition 查询条件 + * return 查询结果 + * author husj + * version 1.0.0 + */ + JsonVO> queryAllHav(DocListQuery condition); + JsonVO> queryAllNo(DocListQuery condition); + + /** + * 通过单据编号查询数据-采购预付有申请 + * param condition 单据编号-查询条件 + * return 查询结果 + * author hzp + */ + JsonVO queryByBillHav(PreDetQuery condition); + + /** + *通过单据编号查询数据-采购预付无申请 + * param condition 单据编号-查询条件 + * return 查询结果 + * author hzp + */ + JsonVO queryByBillNo (PreDetQuery condition); + + /** + * 删除预付单功能 + * param deleteDTO 包含付款单id + * return 删除结果 + * author 出运费 + */ + JsonVO deleteById(DeleteDTO deleteDTO) throws Exception; + + + /** + * 采购预付款操作 + * param prepaymentDTO + * return + * author 空 + */ + JsonVO prepaymentForPurchaseRequisitions(PrepaymentDTO prepaymentDTO); + + + /** + * 导入功能 + * author 内鬼 + */ + JsonVO> queryAllReq(FinPaymentReqQuery query); + + + /** + * 修改状态——关闭 + * author yu-hang + */ + JsonVO closeById(String id); + + /** + * 修改状态——反关闭 + * author yu-hang + */ + JsonVO uncloseById(String id); + + /** + * 修改状态——作废 + * author yu-hang + */ + JsonVO voidById(String id); +} diff --git a/psi-java/psi-apis/src/main/java/com/zeroone/star/project/sample/SampleApis.java b/psi-java/psi-apis/src/main/java/com/zeroone/star/project/sample/SampleApis.java new file mode 100644 index 000000000..530a56097 --- /dev/null +++ b/psi-java/psi-apis/src/main/java/com/zeroone/star/project/sample/SampleApis.java @@ -0,0 +1,32 @@ +package com.zeroone.star.project.sample; + +import com.zeroone.star.project.query.sample.SampleQuery; +import com.zeroone.star.project.vo.JsonVO; +import com.zeroone.star.project.vo.PageVO; +import com.zeroone.star.project.vo.sample.SampleVO; + +/** + *

+ * 描述:测试API接口定义 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +public interface SampleApis { + /** + * 测试分页查询 + * @param condition 查询条件 + * @return 查询结果 + */ + JsonVO> queryAll(SampleQuery condition); + + /** + * 通过编号查询数据 + * @param id 编号 + * @return 查询结果 + */ + JsonVO queryById(int id); +} diff --git a/psi-java/psi-common/README.md b/psi-java/psi-common/README.md new file mode 100644 index 000000000..f4e65dbd5 --- /dev/null +++ b/psi-java/psi-common/README.md @@ -0,0 +1,2 @@ +# 工程简介 +提供公用配置、公用组件、公用工具类,公用的内容都定义在这里 \ No newline at end of file diff --git a/psi-java/psi-common/pom.xml b/psi-java/psi-common/pom.xml new file mode 100644 index 000000000..6611d1e74 --- /dev/null +++ b/psi-java/psi-common/pom.xml @@ -0,0 +1,71 @@ + + + 4.0.0 + + psi-java + com.zeroone.star + ${revision} + ../pom.xml + + psi-common + + + + com.google.code.findbugs + annotations + + + + org.springframework.boot + spring-boot-starter-data-redis + provided + + + + com.github.xiaoymin + knife4j-spring-boot-starter + + + + com.baomidou + mybatis-plus-boot-starter + provided + + + + org.springframework.boot + spring-boot-starter-web + provided + + + + com.nimbusds + nimbus-jose-jwt + + + + com.alibaba + easyexcel + + + + + + + + com.zeroone.star + fastdfs-spring-boot-starter + + + commons-io + commons-io + + + io.springfox + springfox-spring-web + 2.10.5 + compile + + + diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/easyexcel/EasyExcelComponent.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/easyexcel/EasyExcelComponent.java new file mode 100644 index 000000000..2a85f8bfc --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/easyexcel/EasyExcelComponent.java @@ -0,0 +1,91 @@ +package com.zeroone.star.project.components.easyexcel; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.builder.ExcelWriterBuilder; +import com.alibaba.excel.write.metadata.WriteSheet; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +/** + *

+ * 描述:EasyExcel操作组件 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Component +public class EasyExcelComponent { + /** + * 定义每个页签存储的数据量 + */ + private static final int MAX_COUNT_PER_SHEET = 5000; + + /** + * 生成 Excel + * + * @param path Excel 存储路径 + * @param sheetName sheet名称 + * @param clazz 存储的数据类型 + * @param dataList 存储数据集合 + * @param 生成元素实体类类型 + */ + public void generateExcel(String path, String sheetName, Class clazz, List dataList) { + EasyExcel.write(path, clazz).sheet(sheetName).doWrite(dataList); + } + + /** + * 解析Excel + * + * @param path 解析的Excel的路径 + * @param clazz 存储的数据类型 + * @param 解析元素实体类类型 + * @return 解析后的数据集合 + */ + public List parseExcel(String path, Class clazz) { + ExcelReadListener listener = new ExcelReadListener<>(); + //sheet()方法表示读取所有的sheet + //doRead() 表示表示执行读取动作 + EasyExcel.read(path, clazz, listener).sheet().doRead(); + return listener.getDataList(); + } + + /** + * 导出到输出流 + * + * @param sheetName sheet名称 + * @param os 输出流 + * @param clazz 导出数据类型 + * @param dataList 导出的数据集 + * @param 生成元素实体类类型 + * @throws IOException IO异常 + */ + public void export(String sheetName, OutputStream os, Class clazz, List dataList) throws IOException { + ExcelWriterBuilder builder = EasyExcel.write(os, clazz); + ExcelWriter writer = builder.build(); + //计算总页数 + int sheetCount = dataList.size() / MAX_COUNT_PER_SHEET; + sheetCount = dataList.size() % MAX_COUNT_PER_SHEET == 0 ? sheetCount : sheetCount + 1; + //循环构建分页 + for (int i = 0; i < sheetCount; i++) { + //创建一个页签 + WriteSheet sheet = new WriteSheet(); + sheet.setSheetNo(i); + sheet.setSheetName(sheetName + (i + 1)); + //设置数据起始位置 + int start = i * MAX_COUNT_PER_SHEET; + int end = (i + 1) * MAX_COUNT_PER_SHEET; + end = Math.min(end, dataList.size()); + //写入数据到页签 + writer.write(dataList.subList(start, end), sheet); + } + writer.finish(); + os.close(); + } +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/easyexcel/ExcelReadListener.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/easyexcel/ExcelReadListener.java new file mode 100644 index 000000000..d4d431d77 --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/easyexcel/ExcelReadListener.java @@ -0,0 +1,33 @@ +package com.zeroone.star.project.components.easyexcel; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.read.listener.ReadListener; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +/** + *

+ * 描述:表格读取监听器 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +public class ExcelReadListener implements ReadListener { + @Getter + private final List dataList = new ArrayList<>(); + + @Override + public void invoke(T t, AnalysisContext analysisContext) { + dataList.add(t); + } + + @Override + public void doAfterAllAnalysed(AnalysisContext analysisContext) { + System.out.println("读取完成"); + } +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/easyexcel/LocalDateStringConverter.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/easyexcel/LocalDateStringConverter.java new file mode 100644 index 000000000..d5e146033 --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/easyexcel/LocalDateStringConverter.java @@ -0,0 +1,38 @@ +package com.zeroone.star.project.components.easyexcel; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; + +/** + * EasyExcel LocalDate 数据类型转换器 + */ +public class LocalDateStringConverter implements Converter { + @Override + public Class supportJavaTypeKey() { + return LocalDate.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.STRING; + } + + @Override + public LocalDate convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + return LocalDate.parse(cellData.getStringValue(), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + } + + @Override + public WriteCellData convertToExcelData(LocalDate value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + String format = formatter.format(value); + return new WriteCellData<>(format); + } +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/easyexcel/LocalDateTimeStringConverter.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/easyexcel/LocalDateTimeStringConverter.java new file mode 100644 index 000000000..51a33e635 --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/easyexcel/LocalDateTimeStringConverter.java @@ -0,0 +1,38 @@ +package com.zeroone.star.project.components.easyexcel; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +/** + * EasyExcel LocalDateTime 数据类型转换器 + */ +public class LocalDateTimeStringConverter implements Converter { + @Override + public Class supportJavaTypeKey() { + return LocalDateTime.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.STRING; + } + + @Override + public LocalDateTime convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + return LocalDateTime.parse(cellData.getStringValue(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + } + + @Override + public WriteCellData convertToExcelData(LocalDateTime value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + String format = formatter.format(value); + return new WriteCellData<>(format); + } +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/fastdfs/FastDfsClientComponent.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/fastdfs/FastDfsClientComponent.java new file mode 100644 index 000000000..a5b01b314 --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/fastdfs/FastDfsClientComponent.java @@ -0,0 +1,130 @@ +package com.zeroone.star.project.components.fastdfs; + +import io.github.bluemiaomiao.annotation.EnableFastdfsClient; +import io.github.bluemiaomiao.service.FastdfsClientService; +import org.apache.commons.io.FileUtils; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.io.File; + +/** + *

+ * 描述:封装dfs上传、下载等常用方法 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Component +@EnableFastdfsClient +public class FastDfsClientComponent { + + @Resource + private FastdfsClientService remoteService; + + /** + * 文件上传 + * + * @param fileName 文件全路径 + * @param extName 文件扩展名,不包含(.) + * @return 上传结果信息 + * @throws Exception 存储失败异常 + */ + public FastDfsFileInfo uploadFile(String fileName, String extName) throws Exception { + String[] info = remoteService.autoUpload(FileUtils.readFileToByteArray(new File(fileName)), extName); + if (info != null) { + return FastDfsFileInfo.builder() + .group(info[0]) + .storageId(info[1]) + .build(); + } + return null; + } + + /** + * 文件上传 + * + * @param fileName 文件全路径 + * @return 上传结果信息 + * @throws Exception 存储失败异常 + */ + public FastDfsFileInfo uploadFile(String fileName) throws Exception { + return uploadFile(fileName, null); + } + + /** + * 上传文件 + * + * @param fileContent 文件的内容,字节数组 + * @param extName 文件扩展名 + * @return 上传结果信息 + * @throws Exception 存储失败异常 + */ + public FastDfsFileInfo uploadFile(byte[] fileContent, String extName) throws Exception { + String[] info = remoteService.autoUpload(fileContent, extName); + if (info != null) { + return FastDfsFileInfo.builder() + .group(info[0]) + .storageId(info[1]) + .build(); + } + return null; + } + + /** + * 上传文件 + * + * @param fileContent 件的内容,字节数组 + * @return 上传结果信息 [0]:服务器分组,[1]:服务器ID + * @throws Exception 存储失败异常 + */ + public FastDfsFileInfo uploadFile(byte[] fileContent) throws Exception { + return uploadFile(fileContent, null); + } + + /** + * 文件下载 + * + * @param info 文件信息 + * @return 下载数据 + * @throws Exception 异常信息 + */ + public byte[] downloadFile(FastDfsFileInfo info) throws Exception { + return remoteService.download(info.getGroup(), info.getStorageId()); + } + + /** + * 删除文件 + * + * @param info 文件信息 + * @return 删除结果 0表示删除成功 + * @throws Exception 异常信息 + */ + public int deleteFile(FastDfsFileInfo info) throws Exception { + return remoteService.delete(info.getGroup(), info.getStorageId()); + } + + /** + * 解析成url地址 + * + * @param info 文件信息 + * @param urlPrefix 如:http://ip:port + * @param isToken 是否带防盗链 + * @return 获取失败返回null + */ + public String fetchUrl(FastDfsFileInfo info, String urlPrefix, boolean isToken) { + try { + if (isToken) { + return remoteService.autoDownloadWithToken(info.getGroup(), info.getStorageId(), urlPrefix); + } else { + return remoteService.autoDownloadWithoutToken(info.getGroup(), info.getStorageId(), urlPrefix); + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/fastdfs/FastDfsFileInfo.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/fastdfs/FastDfsFileInfo.java new file mode 100644 index 000000000..08d3f36bd --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/fastdfs/FastDfsFileInfo.java @@ -0,0 +1,27 @@ +package com.zeroone.star.project.components.fastdfs; + +import lombok.Builder; +import lombok.Data; + +/** + *

+ * 描述:dfs文件结果信息 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Data +@Builder +public class FastDfsFileInfo { + /** + * 服务器分组 + */ + private String group; + /** + * 对应的存储资源ID + */ + private String storageId; +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/jwt/JwtComponent.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/jwt/JwtComponent.java new file mode 100644 index 000000000..9f933db4e --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/jwt/JwtComponent.java @@ -0,0 +1,247 @@ +package com.zeroone.star.project.components.jwt; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.date.DateUtil; +import cn.hutool.crypto.SecureUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.nimbusds.jose.*; +import com.nimbusds.jose.crypto.MACSigner; +import com.nimbusds.jose.crypto.MACVerifier; +import com.nimbusds.jose.crypto.RSASSASigner; +import com.nimbusds.jose.crypto.RSASSAVerifier; +import com.nimbusds.jose.jwk.JWK; +import com.nimbusds.jose.jwk.RSAKey; +import com.zeroone.star.project.components.jwt.exception.JwtExpiredException; +import com.zeroone.star.project.components.jwt.exception.JwtInvalidException; +import io.micrometer.core.lang.Nullable; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.Resource; +import org.springframework.stereotype.Component; +import org.springframework.util.StreamUtils; + +import java.nio.charset.Charset; +import java.util.Date; +import java.util.List; + +/** + *

+ * 描述:JWT工具类 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Component +public class JwtComponent { + + /** + * 获取默认的PayloadDto对象 + * + * @param subject 主体内容 + * @param userName 用户名 + * @param authorities 权限列表 + * @return PayloadDto对象 + */ + public PayloadDTO getDefaultPayloadDto(String subject, String userName, List authorities) { + return getDefaultPayloadDto(subject, userName, authorities, 18000); + } + + /** + * 获取默认的PayloadDto对象,负载信息默认证书有效时间为18000秒 + * + * @param subject 主体内容 + * @param userName 用户名 + * @param authorities 权限列表 + * @param expSecond 有效时间,单位秒 + * @return PayloadDto对象 + */ + public PayloadDTO getDefaultPayloadDto(String subject, String userName, List authorities, int expSecond) { + Date now = new Date(); + Date exp = DateUtil.offsetSecond(now, expSecond); + return PayloadDTO.builder() + .sub(subject) + .exp(exp.getTime()) + .username(userName) + .authorities(authorities) + .build(); + } + + /** + * 验证并获取负载信息 + */ + private PayloadDTO parseToPayloadDto(JWSObject jwsObject, JWSVerifier jwsVerifier) throws Exception { + // 1 验证签名 + if (!jwsObject.verify(jwsVerifier)) { + throw new JwtInvalidException("token签名不合法!"); + } + // 2 获取负载信息 + String payload = jwsObject.getPayload().toString(); + PayloadDTO payloadDto = JSONUtil.toBean(payload, PayloadDTO.class); + + // 3 验证是否过期 + if (payloadDto.getExp() < System.currentTimeMillis()) { + throw new JwtExpiredException("token已过期!"); + } + + //4 返回负载信息 + return payloadDto; + } + + /** + * 使用HMAC算法构建Token + * + * @param payloadDto 负载信息 + * @param secret 秘钥 + * @return 返回Token字符串 + * @throws JOSEException 生成异常 + */ + public String generateTokenByHmac(PayloadDTO payloadDto, String secret) throws JOSEException { + //1 创建JWS头,设置签名算法和类型 + JWSHeader jwsHeader = new JWSHeader.Builder(JWSAlgorithm.HS256).type(JOSEObjectType.JWT).build(); + //2 将负载信息封装到Payload中 + Payload payload = new Payload(JSONUtil.toJsonStr(payloadDto)); + //3 创建JWS对象 + JWSObject jwsObject = new JWSObject(jwsHeader, payload); + //4 创建HMAC签名器 + secret = SecureUtil.md5(secret); + JWSSigner jwsSigner = new MACSigner(secret); + //5 签名 + jwsObject.sign(jwsSigner); + return jwsObject.serialize(); + } + + /** + * 验证HMAC Token + * + * @param token token字符串 + * @param secret 密钥 + * @return 负载信息对象 + * @throws Exception 验证异常 + */ + public PayloadDTO verifyTokenByHmac(String token, String secret) throws Exception { + //1 从token中解析JWS对象 + JWSObject jwsObject = JWSObject.parse(token); + //2 创建HMAC验证器 + secret = SecureUtil.md5(secret); + JWSVerifier jwsVerifier = new MACVerifier(secret); + //3 验证并获取负载信息 + return parseToPayloadDto(jwsObject, jwsVerifier); + } + + /** + * 通过RSA生成token + * @param payloadDto 负载信息 + * @param rsaKey 签名Key + * @return 返回Token字符串 + * @throws JOSEException 生成异常 + */ + public String generateTokenByRsa(PayloadDTO payloadDto, RSAKey rsaKey) throws JOSEException { + //1 创建JWS头,设置签名算法和类型 + JWSHeader jwsHeader = new JWSHeader.Builder(JWSAlgorithm.RS256).type(JOSEObjectType.JWT).build(); + //2 将负载信息封装到Payload中 + Payload payload = new Payload(JSONUtil.toJsonStr(payloadDto)); + //3 创建JWS对象 + JWSObject jwsObject = new JWSObject(jwsHeader, payload); + //4 创建RSA签名器 + JWSSigner jwsSigner = new RSASSASigner(rsaKey, true); + //5 签名 + jwsObject.sign(jwsSigner); + return jwsObject.serialize(); + } + + /** + * 验证RSA Token + * @param token token字符串 + * @param rsaKey 签名Key + * @return 负载信息对象 + * @throws Exception 验证异常 + */ + public PayloadDTO verifyTokenByRsa(String token, RSAKey rsaKey) throws Exception { + //1 从token中解析JWS对象 + JWSObject jwsObject = JWSObject.parse(token); + RSAKey publicRsaKey = rsaKey.toPublicJWK(); + + //2 使用RSA公钥创建RSA验证器 + JWSVerifier jwsVerifier = new RSASSAVerifier(publicRsaKey); + + //3 验证并获取负载信息 + return parseToPayloadDto(jwsObject, jwsVerifier); + } + + @Value("classpath:public.pem") + private Resource publicPem; + + @Value("classpath:private.pem") + private Resource privatePem; + + /** + * 通过默认公钥获取验证器 + * + * @return 返回验证器 + */ + @Nullable + private JWSVerifier getDefaultJwsVerifier() { + try { + // 读取公钥内容 + String publicKeyStr = StreamUtils.copyToString(publicPem.getInputStream(), Charset.defaultCharset()); + RSAKey rsaPublicKey = (RSAKey) JWK.parseFromPEMEncodedObjects(publicKeyStr); + return new RSASSAVerifier(rsaPublicKey); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 通过默认私钥获取签名器 + * + * @return 签名器 + */ + @Nullable + public JWSSigner getDefaultRsaJwsSigner() { + try { + // 读取私钥内容 + String privateKeyStr = StreamUtils.copyToString(privatePem.getInputStream(), Charset.defaultCharset()); + RSAKey rsaKey = (RSAKey) JWK.parseFromPEMEncodedObjects(privateKeyStr); + return new RSASSASigner(rsaKey.toRSAPrivateKey()); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 默认RSA凭证验证 + * + * @param token 验证凭证 + * @return 凭证的负载数据对应的字符串 + * @throws Exception 验证异常 + */ + @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") + public String defaultRsaVerify(String token) throws Exception { + //1 解析Token + JWSObject jwsObject = JWSObject.parse(token); + //2 获取默认RSA验证器器 + JWSVerifier jwsVerifier = getDefaultJwsVerifier(); + if (jwsVerifier == null) { + throw new JOSEException("签名验证器初始化失败"); + } + //3 签名验证 + if (!jwsObject.verify(jwsVerifier)) { + throw new JwtInvalidException("token签名不合法!"); + } + //4 获取负载信息 + String payloadStr = jwsObject.getPayload().toString(); + JSONObject jsonObject = new JSONObject(payloadStr); + //5 验证是否过期 + String expField = "exp"; + int mill = 1000; + if (Convert.toLong(jsonObject.get(expField)) < System.currentTimeMillis() / mill) { + throw new JwtExpiredException("token已过期!"); + } + return payloadStr; + } +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/jwt/PayloadDTO.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/jwt/PayloadDTO.java new file mode 100644 index 000000000..2556f05db --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/jwt/PayloadDTO.java @@ -0,0 +1,37 @@ +package com.zeroone.star.project.components.jwt; + +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +/** + *

+ * 描述:负载数据对象 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Data +@Builder +public class PayloadDTO { + /** + * 主体数据 + */ + private String sub; + /** + * 过期时间 + */ + private Long exp; + /** + * 用户名称 + */ + private String username; + /** + * 用户拥有的权限 + */ + private List authorities; +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/jwt/exception/JwtExpiredException.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/jwt/exception/JwtExpiredException.java new file mode 100644 index 000000000..2024a3c46 --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/jwt/exception/JwtExpiredException.java @@ -0,0 +1,17 @@ +package com.zeroone.star.project.components.jwt.exception; + +/** + *

+ * 描述:Token过期异常定义 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +public class JwtExpiredException extends RuntimeException { + public JwtExpiredException(String message) { + super(message); + } +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/jwt/exception/JwtInvalidException.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/jwt/exception/JwtInvalidException.java new file mode 100644 index 000000000..c0b2370a7 --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/jwt/exception/JwtInvalidException.java @@ -0,0 +1,17 @@ +package com.zeroone.star.project.components.jwt.exception; + +/** + *

+ * 描述:Token无效异常定义 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +public class JwtInvalidException extends RuntimeException { + public JwtInvalidException(String message) { + super(message); + } +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/poi/ExcelComponent.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/poi/ExcelComponent.java new file mode 100644 index 000000000..02e663c27 --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/poi/ExcelComponent.java @@ -0,0 +1,237 @@ +package com.zeroone.star.project.components.poi; + +import cn.hutool.core.date.DateTime; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.springframework.stereotype.Component; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.Date; +import java.util.List; + +/** + *

+ * 描述:POI Excel操作组件 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Component +public class ExcelComponent { + + /** + * 创建工作薄 + * @param filePath 文件保存路径 + * @return 返回工作薄对象 + */ + public MyWorkBook createWorkBook(String filePath) { + try { + //通过excel文件创建一个工作簿 + Workbook workbook = WorkbookFactory.create(new File(filePath)); + return new MyWorkBook(false, workbook); + } catch (IOException e) { + //excel文件不存在则创建一个空的工作薄 + Workbook workbook = createNullWorkBook(filePath.endsWith(".xlsx") ? 2 : 1); + return new MyWorkBook(true, workbook); + } + } + + /** + * 根据Excel类型创建一个空工作薄 + * + * @param type 1 xls 2 xlsx + */ + private Workbook createNullWorkBook(int type) { + Workbook workbook; + int xlsx = 2; + if (type == xlsx) { + workbook = new SXSSFWorkbook(); + } else { + workbook = new HSSFWorkbook(); + } + return workbook; + } + + /** + * 创建一个sheet + * + * @param wb 工作薄 + * @param sheetName sheet名称 + */ + private Sheet createSheet(Workbook wb, String sheetName) { + //判断页签是否存在 + Sheet sheet = wb.getSheet(sheetName); + if (sheet == null) { + //创建一个页签 + sheet = wb.createSheet(sheetName); + } + return sheet; + } + + /** + * 创建一行空行 + * + * @param sheet 页签 + * @param rowNumber 行索引 + * @param templateRow 样式模板行 + * @return 返回创建的空行 + */ + public Row createRow(Sheet sheet, int rowNumber, Row templateRow) { + Row row = sheet.createRow(rowNumber); + for (int i = 0; i < templateRow.getLastCellNum(); i++) { + //设置样式 + row.createCell(i).setCellStyle(templateRow.getCell(i).getCellStyle()); + } + return row; + } + + /** + * 设置单元格值 + * + * @param cell 单元格 + * @param filedData 填充值 + */ + private void setValue(Cell cell, Object filedData) { + //空字段不做数据处理 + if (filedData == null) { + return; + } + //TODO:需要处理其他特殊类型 + String type = filedData.getClass().getSimpleName(); + //如果数据是日期类型 + String dateTypeString = "date"; + if (dateTypeString.equalsIgnoreCase(type)) { + cell.setCellValue((Date) filedData); + } else { + cell.setCellValue(filedData.toString()); + } + } + + /** + * 反射填充一行数据 + * + * @param row 行对象 + * @param rowData 行数据对象 + * @param isCreateCell 是否需要创建单元格 + */ + public void fullRowData(Row row, Object rowData, boolean isCreateCell) { + //取出所有私有字段 + Field[] declaredFields = rowData.getClass().getDeclaredFields(); + for (int i = 0; i < declaredFields.length; i++) { + Field field = declaredFields[i]; + field.setAccessible(true); + //如果是序列化字段,则不做数据写入 + if ("serialVersionUID".equalsIgnoreCase(field.getName())) { + continue; + } + //将数据写入到单元格中 + try { + //获取到cell + Cell cell; + if (isCreateCell) { + cell = row.createCell(i); + } else { + cell = row.getCell(i); + if (cell == null) { + cell = row.createCell(i); + } + } + //设置值 + Object filedData = field.get(rowData); + setValue(cell, filedData); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + field.setAccessible(false); + } + } + + /** + * 标准表格填充数据方式 + * + * @param sheet 填充的分页 + * @param header 表头 + * @param data 表体内容 + */ + private void fullSheetData(Sheet sheet, String[] header, List data) { + //写表头 + Row rowHeader = sheet.createRow(0); + for (int i = 0; i < header.length; i++) { + rowHeader.createCell(i, CellType.STRING).setCellValue(header[i]); + } + + //写表内容 + int rowNum = 1; + for (Object one : data) { + //创建一个新行 + Row oneRow = sheet.createRow(rowNum); + //调用行数据填充方法 + fullRowData(oneRow, one, true); + //行号累加 + rowNum++; + } + } + + /** + * 保存工作薄 + * + * @param wb 工作薄对象 + * @param filePath 文件路径 + * @return 保存成功返回true + */ + private boolean saveWorkBook(Workbook wb, String filePath) { + FileOutputStream out = null; + try { + out = new FileOutputStream(filePath); + wb.write(out); + return true; + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (out != null) { + try { + wb.close(); + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return false; + } + + /** + * 保存一个Excel + * + * @param filePath 保存文件路径 + * @param header 表头 + * @param data 数据内容列表 + * @param sheetName 页签名称 + * @return 保存成功返回true + */ + public boolean saveData(String filePath, String[] header, List data, String sheetName) { + // 创建工作薄 + MyWorkBook workBook = createWorkBook(filePath); + // 创建Sheet + Sheet sheet = createSheet(workBook.getWorkbook(), sheetName); + // 填充Sheet数据 + fullSheetData(sheet, header, data); + // 保存表格 + if (workBook.isNull()) { + return saveWorkBook(workBook.getWorkbook(), filePath); + } else { + //构建一个新路径 + String newPath = filePath.substring(0, filePath.lastIndexOf(".")) + "-" + DateTime.now().toString("yyyy-MM-dd-HH-mm-ss-S"); + String suffix = filePath.substring(filePath.lastIndexOf(".")); + newPath += suffix; + return saveWorkBook(workBook.getWorkbook(), newPath); + } + } +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/poi/MyWorkBook.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/poi/MyWorkBook.java new file mode 100644 index 000000000..3e459aa47 --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/poi/MyWorkBook.java @@ -0,0 +1,31 @@ +package com.zeroone.star.project.components.poi; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; +import org.apache.poi.ss.usermodel.Workbook; + +/** + *

+ * 描述:自定义WorkBook + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@AllArgsConstructor +@Getter +@ToString +public class MyWorkBook { + /** + * 是否是新建的空工作薄 + */ + private boolean isNull; + + /** + * 关联一个工作薄对象 + */ + private Workbook workbook; +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/user/UserDTO.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/user/UserDTO.java new file mode 100644 index 000000000..15d638870 --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/user/UserDTO.java @@ -0,0 +1,37 @@ +package com.zeroone.star.project.components.user; + +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +/** + *

+ * 描述:用户数据 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Data +@Builder +public class UserDTO { + /** + * 用户编号 + */ + private Integer id; + /** + * 用户名称 + */ + private String username; + /** + * 是否启用 + */ + private Byte isEnabled; + /** + * 用户拥有角色列表 + */ + private List roles; +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/user/UserHolder.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/user/UserHolder.java new file mode 100644 index 000000000..4c5cf67ee --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/components/user/UserHolder.java @@ -0,0 +1,62 @@ +package com.zeroone.star.project.components.user; + +import cn.hutool.core.convert.Convert; +import cn.hutool.json.JSONObject; +import com.zeroone.star.project.components.jwt.JwtComponent; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.List; + +/** + *

+ * 描述:获取登录用户信息 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Component +public class UserHolder { + @Resource + JwtComponent jwtComponent; + + /** + * 从请求头中获取用户信息 + * @return 用户信息 + * @throws Exception 解析失败抛出异常 + */ + @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") + public UserDTO getCurrentUser() throws Exception { +// 从Header中获取用户信息 + ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + if (servletRequestAttributes == null) { + return null; + } + HttpServletRequest request = servletRequestAttributes.getRequest(); + String userStr = request.getHeader("user"); + //不是通过网关过来的,那么执行解析验证JWT + if(userStr == null){ + //从token中解析用户信息并设置到Header中去 + String realToken = request.getHeader("Authorization").replace("Bearer ", ""); + userStr = jwtComponent.defaultRsaVerify(realToken); + } + JSONObject userJsonObject = new JSONObject(userStr); + return UserDTO.builder() + .id(Convert.toInt(userJsonObject.get("id"))) + .username(userJsonObject.getStr("user_name")) + .isEnabled(Convert.toByte(1)) + .roles(Convert.toList(String.class, userJsonObject.get("authorities"))) + .build(); + //测试用用户信息 +// List list = new ArrayList(); +// list.add("111"); +// return new UserDTO(111,"admin", (byte) 1,list); + } +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/config/mybatis/MybatisPlusConfig.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/config/mybatis/MybatisPlusConfig.java new file mode 100644 index 000000000..c28ebfdc7 --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/config/mybatis/MybatisPlusConfig.java @@ -0,0 +1,34 @@ +package com.zeroone.star.project.config.mybatis; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + *

+ * 描述:MybatisPlus配置 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Configuration +public class MybatisPlusConfig { + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + // 分页插件 + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); + // 乐观锁插件 + interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); + // 防全表更新与删除插件 + interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); + return interceptor; + } +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/config/redis/RedisConfig.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/config/redis/RedisConfig.java new file mode 100644 index 000000000..c93f24a0d --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/config/redis/RedisConfig.java @@ -0,0 +1,50 @@ +package com.zeroone.star.project.config.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + *

+ * 描述:Redis配置 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Configuration +@EnableCaching +public class RedisConfig { + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(factory); + // 使用Jackson2JsonRedisSerialize 替换默认的jdkSerialize序列化 + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.activateDefaultTyping(om.getPolymorphicTypeValidator(),ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + // Redis字符串序列化 + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + } +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/config/swagger/SwaggerCore.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/config/swagger/SwaggerCore.java new file mode 100644 index 000000000..9829cb9ae --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/config/swagger/SwaggerCore.java @@ -0,0 +1,96 @@ +package com.zeroone.star.project.config.swagger; + +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.*; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spi.service.contexts.SecurityContext; +import springfox.documentation.spring.web.plugins.Docket; + +import java.util.Collections; +import java.util.List; + +/** + *

+ * 描述:Swagger工具包 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +public class SwaggerCore { + /** + * 默认Docket构建器 + * + * @param projectName 项目名称 + * @param apiBasePackage API扫描基础包 + * @param groupName API分组名称 + * @return Docket对象 + */ + public static Docket defaultDocketBuilder(String projectName, String apiBasePackage, String groupName) { + return new Docket(DocumentationType.SWAGGER_2) + .select() + .apis(RequestHandlerSelectors.basePackage(apiBasePackage)) + .paths(PathSelectors.any()) + .build() + .groupName(groupName) + .apiInfo(createApiInfo(projectName)) + .securitySchemes(securitySchemes()) + .securityContexts(securityContexts()); + } + + /** + * 构建文档说明对象 + * + * @param projectName 项目名称 + * @return ApiInfo对象 + */ + private static ApiInfo createApiInfo(String projectName) { + return new ApiInfoBuilder() + .title(projectName + " API接口服务") + .description("用于" + projectName + "前后端交互,提供一套API说明") + .version("1.0.0") + .contact(new Contact("零壹星球", "https://space.bilibili.com/1653229811/?spm_id_from=333.999.0.0", "01xq@mail.com")) + .license("Apache 2.0") + .licenseUrl("https://www.apache.org/licenses/LICENSE-2.0.html") + .build(); + } + + /** + * 构建权限协议列表 + * + * @return 认证协议列表 + */ + private static List securitySchemes() { + return Collections.singletonList( + new ApiKey("Authorization", "Authorization", "header")); + } + + /** + * 构建权限上下文列表 + * + * @return 认证上下文列表 + */ + private static List securityContexts() { + return Collections.singletonList( + SecurityContext.builder() + .securityReferences(defaultAuth()) + .build() + ); + } + + /** + * 构建默认认证作用域列表 + * + * @return 认证作用域列表 + */ + private static List defaultAuth() { + AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); + AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; + authorizationScopes[0] = authorizationScope; + return Collections.singletonList(new SecurityReference("Authorization", authorizationScopes)); + } +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/config/task/TaskConfig.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/config/task/TaskConfig.java new file mode 100644 index 000000000..3309d229b --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/config/task/TaskConfig.java @@ -0,0 +1,19 @@ +package com.zeroone.star.project.config.task; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; + +/** + *

+ * 描述:定时任务配置 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Configuration +@EnableScheduling +public class TaskConfig { +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/constant/AuthConstant.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/constant/AuthConstant.java new file mode 100644 index 000000000..82ebdb334 --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/constant/AuthConstant.java @@ -0,0 +1,38 @@ +package com.zeroone.star.project.constant; + +/** + *

+ * 描述:授权相关常量 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +public interface AuthConstant { + /** + * JWT存储权限前缀 + */ + String AUTHORITY_PREFIX = "ROLE_"; + + /** + * JWT存储权限属性 + */ + String AUTHORITY_CLAIM_NAME = "authorities"; + + /** + * app端客户端类型定义 + */ + String CLIENT_APP = "psi-app"; + + /** + * 管理端客户端类型定义 + */ + String CLIENT_MANAGER = "psi-manager"; + + /** + * 客户端密码 + */ + String CLIENT_PASSWORD = "123456"; +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/constant/RedisConstant.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/constant/RedisConstant.java new file mode 100644 index 000000000..33edfa561 --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/constant/RedisConstant.java @@ -0,0 +1,18 @@ +package com.zeroone.star.project.constant; + +/** + *

+ * 描述:Redis相关常量 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +public interface RedisConstant { + /** + * 角色资源映射Map的key + */ + String RESOURCE_ROLES_MAP = "AUTH:RESOURCE_ROLES"; +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/utils/easyExcel/EasyExcelUtils.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/utils/easyExcel/EasyExcelUtils.java new file mode 100644 index 000000000..eb748c17c --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/utils/easyExcel/EasyExcelUtils.java @@ -0,0 +1,46 @@ +package com.zeroone.star.project.utils.easyExcel; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +@Slf4j +public class EasyExcelUtils { + /** + * @param consumer 传入一个消费者接口对象,作用:业务逻辑处理 + * @param thresshold 批处理阈值,作用:减轻数据库的压力 + * @param 实体类 + */ + public static AnalysisEventListener getListener(Consumer> consumer, int thresshold) { + return new AnalysisEventListener() { + /** + * 存储对象 + */ + List list = new ArrayList<>(thresshold); + + //easyExcel每次从Excel中读取一行数据就会调用一次invoke方法 + @Override + public void invoke(T t, AnalysisContext analysisContext) { + log.info("read item: {}", t.toString()); + list.add(t); + if (list.size() >= thresshold) { + consumer.accept(list); + list.clear(); + } + } + + //easyExcel在将Excel表中数据读取完毕后,最终执行此方法 + @Override + public void doAfterAllAnalysed(AnalysisContext analysisContext) { + //最后,如果size 0) { + consumer.accept(list); + } + } + }; + } + +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/utils/easyExcel/converters/LocalDateConverter.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/utils/easyExcel/converters/LocalDateConverter.java new file mode 100644 index 000000000..935074204 --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/utils/easyExcel/converters/LocalDateConverter.java @@ -0,0 +1,40 @@ +package com.zeroone.star.project.utils.easyExcel.converters; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; + +public class LocalDateConverter implements Converter { + /** + * 要转换的 Java 类型 + */ + @Override + public Class supportJavaTypeKey() { + return LocalDate.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.STRING; + } + + @Override + public LocalDate convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + return LocalDate.parse(cellData.getStringValue(), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + } + + @Override + public WriteCellData convertToExcelData(LocalDate value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + String format = formatter.format(value); + return new WriteCellData(format); + + } + +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/utils/easyExcel/converters/LocalDateTimeConverter.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/utils/easyExcel/converters/LocalDateTimeConverter.java new file mode 100644 index 000000000..e5b54c622 --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/utils/easyExcel/converters/LocalDateTimeConverter.java @@ -0,0 +1,40 @@ +package com.zeroone.star.project.utils.easyExcel.converters; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public class LocalDateTimeConverter implements Converter { + /** + * 要转换的 Java 类型 + */ + @Override + public Class supportJavaTypeKey() { + return LocalDateTime.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.STRING; + } + + @Override + public LocalDateTime convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + return LocalDateTime.parse(cellData.getStringValue(), DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss")); + } + + @Override + public WriteCellData convertToExcelData(LocalDateTime value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + String format = formatter.format(value); + return new WriteCellData(format); + + } + +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/utils/tree/NodeMapper.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/utils/tree/NodeMapper.java new file mode 100644 index 000000000..9b0eb9914 --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/utils/tree/NodeMapper.java @@ -0,0 +1,21 @@ +package com.zeroone.star.project.utils.tree; + +/** + *

+ * 描述:对象转换节点数据匹配接口 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +public interface NodeMapper { + + /** + * 把一个对象转换为节点的数据对象 + * @param object 被转换对象 + * @return 转换后的节点数据 + */ + TreeNode objectMapper(T object); +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/utils/tree/TreeNode.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/utils/tree/TreeNode.java new file mode 100644 index 000000000..bbc757e41 --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/utils/tree/TreeNode.java @@ -0,0 +1,60 @@ +package com.zeroone.star.project.utils.tree; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + *

+ * 描述:用来定义一个树形节点的数据 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Data +public class TreeNode implements Serializable { + /** + * 唯一ID + */ + private String id; + /** + * 节点文本描述 + */ + private String text; + /** + * 节点对应图标 + */ + private String icon; + /** + * 节点链接地址 + */ + private String href; + /** + * 节点父节点ID + */ + private String pid; + /** + * 节点深度 + */ + private Integer depth; + /** + * 是否展开 + */ + private Boolean expanded; + /** + * 是否选中 + */ + private Boolean checked; + /** + * 节点包含的子节点 + */ + private List> children; + /** + * 节点源数据对象 + */ + private T raw; +} diff --git a/psi-java/psi-common/src/main/java/com/zeroone/star/project/utils/tree/TreeUtils.java b/psi-java/psi-common/src/main/java/com/zeroone/star/project/utils/tree/TreeUtils.java new file mode 100644 index 000000000..db9f75b00 --- /dev/null +++ b/psi-java/psi-common/src/main/java/com/zeroone/star/project/utils/tree/TreeUtils.java @@ -0,0 +1,65 @@ +package com.zeroone.star.project.utils.tree; + +import java.util.ArrayList; +import java.util.List; + +/** + *

+ * 描述:树形数据构建工具类 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +public class TreeUtils { + + /** + * 将列表数据转换成树状数据 + * + * @param list 列表数据 + * @param mapper 数据转换节点数据匹配接口 + * @param 源数据类型 + * @return 返回树状数据列表 + */ + public static List> listToTree(List list, NodeMapper mapper) { + // 把集合中的数据转换为树形节点数据 + List> nodes = new ArrayList<>(); + for (T row : list) { + TreeNode node = mapper.objectMapper(row); + nodes.add(node); + } + // 构建一个具有层次结构的树 + List> tree = new ArrayList<>(); + // 循环获取根节点 + for (TreeNode node : nodes) { + if (null == node.getPid()) { + tree.add(node); + node.setDepth(0); + // 每个节点查找子节点 + findChildNodes(node, nodes); + } + } + return tree; + } + + private static void findChildNodes(TreeNode parentNode, List> nodes) { + for (TreeNode child : nodes) { + // 找到子节点 + if (parentNode.getId().equals(child.getPid())) { + // 判断父节点中的子节点集合是否为空 + if (parentNode.getChildren() == null) { + parentNode.setChildren(new ArrayList<>()); + } + // 设置子节点的相关计算数据 + child.setDepth(parentNode.getDepth() + 1); + // 将子节点添加到父节点的子节点集合中 + parentNode.getChildren().add(child); + + // 查找子节点包含的子节点 + findChildNodes(child, nodes); + } + } + } +} diff --git a/psi-java/psi-common/src/main/resources/banner.txt b/psi-java/psi-common/src/main/resources/banner.txt new file mode 100644 index 000000000..7011bfc30 --- /dev/null +++ b/psi-java/psi-common/src/main/resources/banner.txt @@ -0,0 +1,9 @@ +${AnsiStyle.BOLD} __ _ ___ _____ ___ ___ + / \ / | / __| |_ _| / \ | _ \ + | () | | | \__ \ | | | - | | / + _\__/ _|_|_ |___/ _|_|_ |_|_| |_|_\ +_|""0""| _|""1""| _|""s""| _|""t""| _|""a""| _|""r""| +"`-0-0-' "`-0-0-' "`-0-0-' "`-0-0-' "`-0-0-' "`-0-0-' +${AnsiStyle.UNDERLINE}${AnsiColor.BRIGHT_CYAN}${application.title} ${application.version} +${AnsiColor.BLUE}Powered by ${application.company} +${AnsiColor.GREEN}Spring Boot ${spring-boot.version}${AnsiStyle.NORMAL} diff --git a/psi-java/psi-common/src/main/resources/config/application.yaml b/psi-java/psi-common/src/main/resources/config/application.yaml new file mode 100644 index 000000000..b8558da4b --- /dev/null +++ b/psi-java/psi-common/src/main/resources/config/application.yaml @@ -0,0 +1,30 @@ +# 应用版本描述 +application: + title: 零壹进销存 + version: 1.0.0-SNAPSHOT + company: 01星球 + +spring: + # 全局jackson配置 + jackson: + default-property-inclusion: non_null + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + serialization: + write-dates-as-timestamps: false + servlet: + multipart: + # 上传文件总的最大值 + max-request-size: 20MB + # 单个文件的最大值 + max-file-size: 10MB +management: + # 端点检查 + endpoints: + web: + exposure: + include: "*" + # 健康检查 + endpoint: + health: + show-details: always diff --git a/psi-java/psi-common/src/main/resources/config/bootstrap-dev.properties b/psi-java/psi-common/src/main/resources/config/bootstrap-dev.properties new file mode 100644 index 000000000..089c84fb5 --- /dev/null +++ b/psi-java/psi-common/src/main/resources/config/bootstrap-dev.properties @@ -0,0 +1,14 @@ +# Nacos\u914D\u7F6E +nacos.namespace=240a25a6-f2ed-411b-9eb7-cfdcf95c6546 +nacos.addr=43.138.51.248:8848 +nacos.contextPath=nacos + +# \u5F00\u53D1\u73AF\u5883\u7279\u6B8A\u5904\u7406 +# \u672C\u673A\u7684IP\u5730\u5740\uFF0C\u5BA2\u6237\u7AEF\u7ED9sentinel\u76D1\u63A7\u4F7F\u7528\uFF0C\u4E0D\u914D\u7F6E\u53EF\u80FD\u4F1A\u8BC6\u522B\u6210\u5176\u4ED6\u7F51\u5361\u7684ip\u5BFC\u81F4\u9519\u8BEF +spring.cloud.sentinel.transport.client-ip=192.168.31.99 + +# \u65E5\u5FD7\u7EA7\u522B +# logging.level.root=debug + +# \u5F00\u542FMP SQL\u65E5\u5FD7\u6253\u5370 +mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl diff --git a/psi-java/psi-common/src/main/resources/config/bootstrap-prod.properties b/psi-java/psi-common/src/main/resources/config/bootstrap-prod.properties new file mode 100644 index 000000000..b3aac5e76 --- /dev/null +++ b/psi-java/psi-common/src/main/resources/config/bootstrap-prod.properties @@ -0,0 +1,10 @@ +# Nacos\u914D\u7F6E +nacos.namespace=240a25a6-f2ed-411b-9eb7-cfdcf95c6546 +nacos.addr=43.138.51.248:8848 +nacos.contextPath=nacos + +# \u65E5\u5FD7\u7EA7\u522B +# logging.level.root=info + +# \u5173\u95EDMP SQL\u65E5\u5FD7\u6253\u5370 +mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.nologging.NoLoggingImpl diff --git a/psi-java/psi-common/src/main/resources/config/bootstrap-test.properties b/psi-java/psi-common/src/main/resources/config/bootstrap-test.properties new file mode 100644 index 000000000..004f696a3 --- /dev/null +++ b/psi-java/psi-common/src/main/resources/config/bootstrap-test.properties @@ -0,0 +1,10 @@ +# Nacos\u914D\u7F6E +nacos.namespace=240a25a6-f2ed-411b-9eb7-cfdcf95c6546 +nacos.addr=43.138.51.248:8848 +nacos.contextPath=nacos + +# \u65E5\u5FD7\u7EA7\u522B +# logging.level.root=debug + +# \u5F00\u542FMP SQL\u65E5\u5FD7\u6253\u5370 +mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl diff --git a/psi-java/psi-common/src/main/resources/config/bootstrap.properties b/psi-java/psi-common/src/main/resources/config/bootstrap.properties new file mode 100644 index 000000000..19ae64b5c --- /dev/null +++ b/psi-java/psi-common/src/main/resources/config/bootstrap.properties @@ -0,0 +1,59 @@ +# \u670D\u52A1\u7AEF\u53E3 +sp.seata=9998 +sp.doc=9999 +sp.gateway=10001 +sp.sample=10100 +sp.login=10200 +sp.cpp=10300 +sp.auth=10400 +sp.ws=10500 +sp.publish=10600 +sp.task=10650 +sp.ee=10660 +sp.mongo=10670 +sp.captcha=10680 +sp.prepayment=10690 + +# \u670D\u52A1\u540D\u79F0 +sn.seata=SEATA +sn.doc=DOC +sn.gateway=GATEWAY +sn.sample=SAMPLE +sn.login=LOGIN +sn.cpp=CPP +sn.auth=OAUTH2 +sn.ws=WEBSOCKET +sn.publish=PUBLISH +sn.task=TASK +sn.ee=EASY-ES +sn.mongo=MONGO +sn.captcha=CAPTCHA +sn.prepayment=PREPAYMENT +############### \u6CE8\u610F\uFF1A\u540E\u7EED\u65B0\u589E\u670D\u52A1\u6A21\u5757\u7684\uFF08\u670D\u52A1\u7AEF\u53E3\u3001\u670D\u52A1\u540D\u79F0\uFF09\uFF0C\u90FD\u5728nacos\u914D\u7F6E\u4E2D\u5FC3\u7684system.yaml\u6DFB\u52A0\uFF0C\u4E0D\u4FEE\u6539\u6B64\u914D\u7F6E\u6587\u4EF6 ############### + +# \u73AF\u5883\u9009\u62E9\u914D\u7F6E\u5207\u6362 +spring.profiles.active=dev + +# Nacos\u670D\u52A1\u53D1\u73B0\u914D\u7F6E\uFF0C\u53C2\u8003\u5730\u5740\uFF1Ahttps://github.com/alibaba/spring-cloud-alibaba/wiki/Nacos-discovery +# \u6307\u5B9A Nacos \u670D\u52A1\u4E2D\u5FC3\u4E3B\u673A\u548C\u7AEF\u53E3 +spring.cloud.nacos.discovery.server-addr=${nacos.addr} +# \u6307\u5B9A namespace\uFF0C\u9ED8\u8BA4\u4E3A public +spring.cloud.nacos.discovery.namespace=${nacos.namespace} + +# Nacos\u914D\u7F6E\u4E2D\u5FC3\u914D\u7F6E\uFF0C\u53C2\u8003\u5730\u5740\uFF1Ahttps://github.com/alibaba/spring-cloud-alibaba/wiki/Nacos-config +# \u6307\u5B9A Nacos \u914D\u7F6E\u4E2D\u5FC3\u4E3B\u673A\u548C\u7AEF\u53E3 +spring.cloud.nacos.config.server-addr=${nacos.addr} +# \u6307\u5B9A namespace\uFF0C\u9ED8\u8BA4\u4E3A public +spring.cloud.nacos.config.namespace=${nacos.namespace} +# \u914D\u7F6E\u6587\u4EF6\u524D\u7F00,\u9ED8\u8BA4\u4E3Aspring.application.name\u7684\u503C +spring.cloud.nacos.config.prefix=project +# \u914D\u7F6E\u6587\u4EF6\u6269\u5C55\u540D,\u76EE\u524D\u53EA\u652F\u6301properties\u548Cyaml\u7C7B\u578B +spring.cloud.nacos.config.file-extension=yaml + +# \u670D\u52A1\u5668\u542F\u52A8\u65F6\u9700\u8981\u7ACB\u5373\u52A0\u8F7D\u5171\u4EAB\u7684\u914D\u7F6E\uFF0C\u7701\u7565\u6269\u5C55\u540D +spring.cloud.nacos.config.extension-configs[0].data-id=system.yaml +spring.cloud.nacos.config.extension-configs[1].data-id=data-source.yaml +spring.cloud.nacos.config.extension-configs[2].data-id=third-services.yaml +spring.cloud.nacos.config.extension-configs[0].refresh=true +spring.cloud.nacos.config.extension-configs[1].refresh=true +spring.cloud.nacos.config.extension-configs[2].refresh=true diff --git a/psi-java/psi-common/src/main/resources/public.pem b/psi-java/psi-common/src/main/resources/public.pem new file mode 100644 index 000000000..1ebcfa3cf --- /dev/null +++ b/psi-java/psi-common/src/main/resources/public.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2CUog6kdKUOlOtdOHFcs +ts0KHt5eg8UPF6Yj/jte7jgxOWsYB571rdMzTDIYo1UIaYVOJcd3oio9QlebUZD7 +O4GL8oJmj9rNCVk60xfx3vhYISzdHbwQhUUgx+YDmDr5UJV/D/uhCdFKziTUBMjD +otSQXvCsbWIMGGEFbPXKe9VRmgqtjdNfWvjMa7spQwiy0gj7GeOUiIttkVZna6qF +FZRSRAxp3NJ9ELbcW7Kd9u5IFzrvxXNiYPOtIiw+zqJTYsSXUJTI7YQAXy9zqGtT +7QUFUjxUf+7b1DELpGZPmwGd5Jzj+zfTNsS3DRNuPQJPkPbpUo1qCsU55sXgcNrf +zwIDAQAB +-----END PUBLIC KEY----- diff --git a/psi-java/psi-domain/README.md b/psi-java/psi-domain/README.md new file mode 100644 index 000000000..1e4b68c59 --- /dev/null +++ b/psi-java/psi-domain/README.md @@ -0,0 +1,2 @@ +# 工程简介 +定义给个领域模型需要的实体,除了do层的领域模型,其它层的领域模型都需要定义在这里 \ No newline at end of file diff --git a/psi-java/psi-domain/pom.xml b/psi-java/psi-domain/pom.xml new file mode 100644 index 000000000..eabe8e5f5 --- /dev/null +++ b/psi-java/psi-domain/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + psi-java + com.zeroone.star + ${revision} + ../pom.xml + + psi-domain + + + + com.zeroone.star + psi-common + + + + com.github.xiaoymin + knife4j-spring-boot-starter + + + + com.baomidou + mybatis-plus-extension + + + + org.springframework.boot + spring-boot-starter-validation + + + io.swagger + swagger-annotations + 1.5.22 + compile + + + org.springframework + spring-web + + + com.alibaba + easyexcel + + + com.alibaba + easyexcel + + + diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/cpp/SampleDTO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/cpp/SampleDTO.java new file mode 100644 index 000000000..124d64e3c --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/cpp/SampleDTO.java @@ -0,0 +1,28 @@ +package com.zeroone.star.project.dto.cpp; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 描述:示例传输对象 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Data +@ApiModel("C++示例传输数据对象") +public class SampleDTO { + @ApiModelProperty(value = "编号", example = "1") + private Integer id; + @ApiModelProperty(value = "姓名", example = "C++") + private String name; + @ApiModelProperty(value = "年龄", example = "99") + private Integer age; + @ApiModelProperty(value = "性别", example = "男") + private String sex; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/log/WebLogDTO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/log/WebLogDTO.java new file mode 100644 index 000000000..a396b90e7 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/log/WebLogDTO.java @@ -0,0 +1,71 @@ +package com.zeroone.star.project.dto.log; + +import lombok.Data; + +/** + *

+ * 描述:Controller层的日志封装类 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Data +public class WebLogDTO { + /** + * 操作描述 + */ + private String description; + + /** + * 操作用户 + */ + private String username; + + /** + * 操作时间 + */ + private Long startTime; + + /** + * 消耗时间 + */ + private Integer spendTime; + + /** + * 根路径 + */ + private String basePath; + + /** + * URI + */ + private String uri; + + /** + * URL + */ + private String url; + + /** + * 请求类型 + */ + private String method; + + /** + * IP地址 + */ + private String ip; + + /** + * 请求参数 + */ + private String parameter; + + /** + * 请求返回的结果 + */ + private String result; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/login/LoginDTO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/login/LoginDTO.java new file mode 100644 index 000000000..44bc01951 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/login/LoginDTO.java @@ -0,0 +1,47 @@ +package com.zeroone.star.project.dto.login; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 描述:用户登录传输数据 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@ApiModel("登录上传数据对象") +@Data +@AllArgsConstructor +@NoArgsConstructor +public class LoginDTO { + /** + * 用户名 + */ + @ApiModelProperty(value = "用户名", example = "admin", required = true) + private String username; + + /** + * 密码 + */ + @ApiModelProperty(value = "密码", example = "123456", required = true) + private String password; + + /** + * 验证码 + */ + @ApiModelProperty(value = "验证码", example = "999818") + private String code; + + /** + * 登录客户端ID + */ + @ApiModelProperty(value = "登录客户端ID:project-app或project-manager", example = "project-manager", required = true) + private String clientId; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/login/Oauth2TokenDTO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/login/Oauth2TokenDTO.java new file mode 100644 index 000000000..ba1c26879 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/login/Oauth2TokenDTO.java @@ -0,0 +1,54 @@ +package com.zeroone.star.project.dto.login; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + *

+ * 描述:Oauth2获取Token返回信息封装 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@ApiModel("授权登录上传数据对象") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Oauth2TokenDTO { + /** + * 访问令牌 + */ + @ApiModelProperty(value = "授权令牌", example = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbImFsbCJdLCJpZCI6MSwiZXhwIjoxNjAwNzU4NjEzLCJhdXRob3JpdGllcyI6WyJBRE1JTiJdLCJqdGkiOiI2ZWY3MTkzNS04Yjk0LTQ0YzQtOGRhNC0wODhhMTVmOGQ5NzkiLCJjbGllbnRfaWQiOiJoZWFsdGgtY2xpZW50In0.RY6Eu9O35SRbtxOKrP0Db-kl7A9QK8XBr7KCP2Qnx1bGCoHm9v3OnXbOgZ95QMuo117wS3t8KyCAHIhclrDykl5kf_sV2_FrnrzZWYb8kSDB6pPKSSJLTWTud1eN9W07K2OKh9DHtDEW3CdnHXeV9I3yGJhIYuSaWcmq4pqOSd3UFktEcvUIQewcbdppsgT_CWngaXn88wNCmHjClvBuFuXL9r67_QwvWqJr1iCMrF9tOo993PzxP1P2zDkRwnINy9lRxly7lIkJ4Um5w7v4eeJmYo5e3VliagACKM-MOKqB6cy8nqUMkLW5r-t_74h_yxcjKdan0jRcjcpCXcHsrA") + private String token; + + /** + * 刷新令牌 + */ + @ApiModelProperty(value = "刷新令牌", required = true, example = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbImFsbCJdLCJhdGkiOiI2ZWY3MTkzNS04Yjk0LTQ0YzQtOGRhNC0wODhhMTVmOGQ5NzkiLCJpZCI6MSwiZXhwIjoxNjAwODQxNDEzLCJhdXRob3JpdGllcyI6WyJBRE1JTiJdLCJqdGkiOiJlMjU3ZDFjNi02Mzk0LTRkODItYmIxOC1mY2I4ZDBkOTczNzciLCJjbGllbnRfaWQiOiJoZWFsdGgtY2xpZW50In0.I2kxj_sOJZ2Ui2Hd8aPCPzCE-vP8kq4L6WXjBgrFUXahismN2ipRuqaMTzxC_sWBPaSjTSsElmYiN5q95ktm_QwLZbQkPb0wi2l9CggVKWSOpoz6QorIfpCh63Tc_GR3vPT6W9M2tdBiDtX477O5ddAmgAoXf62foOL-AjcCxSryTLrdICGbBq2ZArOGvKhF5NInF7BHX2LYTJF5Yt9B0y5YMdKdmIoMJwQLgPWwxktfHOjx2s-DordJEKjKSmLWkq9qa6MgxgYJQM7Ex-8obEtoxkEDDloC3SAZK_53YffnO14kY4025cWLH4N0p_RbrGPPz9bBthVO8YOog9nfGA") + private String refreshToken; + + /** + * 访问令牌头前缀 + */ + @ApiModelProperty(value = "访问令牌前缀", example = "Bearer ") + private String tokenHead; + + /** + * 有效时间(秒) + */ + @ApiModelProperty(value = "有效时间", example = "3599") + private Integer expiresIn; + + /** + * 登录客户端ID + */ + @ApiModelProperty(value = "登录客户端ID:project-app或project-manager", example = "project-manager", required = true) + private String clientId; +} + diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/notify/SampleNotifyDTO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/notify/SampleNotifyDTO.java new file mode 100644 index 000000000..876c0ed0f --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/notify/SampleNotifyDTO.java @@ -0,0 +1,26 @@ +package com.zeroone.star.project.dto.notify; + +import lombok.Data; + +/** + *

+ * 描述:示例通知数据对象 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Data +public class SampleNotifyDTO { + /** + * 客户端编号 + */ + private String clientId; + + /** + * 通知消息内容 + */ + private String message; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/prepayment/AuditDTO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/prepayment/AuditDTO.java new file mode 100644 index 000000000..8dad516ef --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/prepayment/AuditDTO.java @@ -0,0 +1,33 @@ +package com.zeroone.star.project.dto.prepayment; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + *

+ * 描述:审核 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author forever爱 + * @version 1.0.0 + */ + +@Data +@ApiModel("审核功能") +public class AuditDTO { + + @ApiModelProperty(value = "id",example = "1626949545251745795") + @NotBlank(message = "id不能为空") + private String id; + + @ApiModelProperty(value = "核批结果类型",example = "1(通过)") + private String approvalResultType; + + @ApiModelProperty(value = "核批意见",example = "xxx") + private String approvalRemark; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/prepayment/DeleteDTO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/prepayment/DeleteDTO.java new file mode 100644 index 000000000..e32a82372 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/prepayment/DeleteDTO.java @@ -0,0 +1,25 @@ +package com.zeroone.star.project.dto.prepayment; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + *

+ * 描述:删除数据传输对象 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 出运费 + * @version 1.0.0 + */ +@Data +@ApiModel("删除数据传输对象") +public class DeleteDTO { + @ApiModelProperty(value = "id", example = "10086") + @NotBlank(message = "id不能为空") + private String id; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/prepayment/DocListDTO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/prepayment/DocListDTO.java new file mode 100644 index 000000000..25e2d38f9 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/prepayment/DocListDTO.java @@ -0,0 +1,137 @@ +package com.zeroone.star.project.dto.prepayment; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + *

+ * 描述:单据查询传输对象 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author husj + * @version 1.0.0 + */ +@Data +@ApiModel("单据查询传输对象") +public class DocListDTO { + /** + * 单据编号 + */ + @ApiModelProperty(value = "单据编号",example = "CGYF-230208-020") + private String billNo; + + /** + * 单据日期 + */ + @ApiModelProperty(value = "单据日期",example = "2023-02-08") + private LocalDate billDate; + + /** + * 单据主题 + */ + @ApiModelProperty(value = "单据主题",example = "") + private String subject; + + /** + * 是否红字 + */ + @ApiModelProperty(value = "是否红字",example = "1") + private Integer isRubric; + /** + * 供应商 + */ + @ApiModelProperty(value = "供应商",example = "") + private String supplierId; + + /** + * 金额 + */ + @ApiModelProperty(value = "金额",example = "100.00") + private BigDecimal amt; + + /** + * 已核销金额 + */ + @ApiModelProperty(value = "已核销金额",example = "0.00") + private BigDecimal checkedAmt; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注",example = "100.00") + private String remark; + + /** + * 是否自动单据 + */ + @ApiModelProperty(value = "是否自动单据",example = "") + private Integer isAuto; + + /** + * 处理状态 + */ + @ApiModelProperty(value = "处理状态",example = "执行中") + private String billStage; + + /** + * 审核人 + */ + @ApiModelProperty(value = "审核人",example = "管理员") + private String approver; + + + /** + * 生效时间 + */ + @ApiModelProperty(value = "生效日期",example = "2023-02-08") + private LocalDateTime effectiveTime; + + /** + * 已关闭 + */ + @ApiModelProperty(value = "已关闭",example = "1") + private Integer isClosed; + + /** + * 是否作废 + */ + @ApiModelProperty(value = "是否作废",example = "") + private Boolean isVoided; + + /** + * 创建时间 + */ + @ApiModelProperty(value = "创建时间",example = "2023-02-08") + private LocalDateTime createTime; + + /** + * 创建人 + */ + @ApiModelProperty(value = "创建人",example = "管理员") + private String createBy; + + /** + * 创建部门 + */ + @ApiModelProperty(value = "创建部门",example = "市场部") + private String sysOrgCode; + + /** + * 修改时间 + */ + @ApiModelProperty(value = "修改时间",example = "2023-02-08") + private LocalDateTime updateTime; + + /** + * 修改人 + */ + @ApiModelProperty(value = "修改人",example = "管理员") + private String updateBy; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/prepayment/FinPaymentEntryDTO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/prepayment/FinPaymentEntryDTO.java new file mode 100644 index 000000000..94d83cd3d --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/prepayment/FinPaymentEntryDTO.java @@ -0,0 +1,66 @@ +package com.zeroone.star.project.dto.prepayment; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; + +/** + *

+ * 描述:付款单明细 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * author forever爱 + * version 1.0.0 + */ +@Data +public class FinPaymentEntryDTO { + @ApiModelProperty(value = "金额",example = "1000.00") + @NotNull(message = "金额不能为空") + private BigDecimal amt; + + @ApiModelProperty(value = "资金账户",example = "") + private String bankAccountId; + + @ApiModelProperty(value = "自定义1",example = "") + private String custom1; + + @ApiModelProperty(value = "自定义2",example = "") + private String custom2; + + @ApiModelProperty(value = "mid",example = "1626949545251745795") + @NotBlank(message = "mid不能为空") + private String mid; + + @ApiModelProperty(value = "单据编号",example = "TEST-202302-002") + @NotBlank(message = "单据编号不能为空") + private String billNo; + + @ApiModelProperty(value = "分录号",example = "10") + @NotNull(message = "分录号不能为空") + private Integer entryNo; + + @ApiModelProperty(value = "源单类型",example = "FinPaymentReq:2011") + private String srcBillType; + + @ApiModelProperty(value = "源单号",example = "TESTSQ-202302-002") + private String srcNo; + + @ApiModelProperty(value = "备注",example = "备注") + private String remark; + + @ApiModelProperty(value = "结算方式",example = "31") + private String settleMethod; + + @ApiModelProperty(value = "源单id",example = "1594317750844637186") + private String srcBillId; + + + + + +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/prepayment/ModifyDTO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/prepayment/ModifyDTO.java new file mode 100644 index 000000000..e5036b41d --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/prepayment/ModifyDTO.java @@ -0,0 +1,74 @@ +package com.zeroone.star.project.dto.prepayment; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.validation.annotation.Validated; + +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +/** + *

+ * 描述:修改采购预付单功能——有申请和无申请 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author forever爱 + * @version 1.0.0 + */ +@Data +@ApiModel("修改采购预付单功能") +public class ModifyDTO { + @ApiModelProperty(value = "id",example = "1626949545251745795") + private String id; + +// @ApiModelProperty(value = "金额",example = "1000.00") +// private BigDecimal amt; + + @ApiModelProperty(value = "单据日期",example = "2022-01-14") + @NotNull(message = "单据日期不能为空") + @DateTimeFormat(pattern = "yyyy-MM-dd") + private Date billDate; + + @ApiModelProperty(value = "单据编号",example = "TEST-202302-002") + @NotBlank(message = "单据编号不能为空") + private String billNo; + + @ApiModelProperty(value = "备注",example = "测试用") + private String remark; + +// @ApiModelProperty(value = "源单类型",example = "FinPaymentReq:2011") +// private String srcBillType; +// +// @ApiModelProperty(value = "源单id",example = "1594317750844637186") +// private String srcBillId; +// +// @ApiModelProperty(value = "源单号",example = "TESTSQ-202302-002") +// private String srcNo; + + @ApiModelProperty(value = "单据主题",example = "tittle") + private String subject; + + @ApiModelProperty(value = "供应商",example = "1584950950470164481") + @NotBlank(message = "供应商不能为空") + private String supplierId; + + @ApiModelProperty(value = "附件",example = "") + private String attachment; + + @ApiModelProperty(value = "版本",example = "") + private Integer version; + + @ApiModelProperty(value = "采购单明细",example = "") + @Valid + private List entryDTOList; + +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/prepayment/PrepaymentDTO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/prepayment/PrepaymentDTO.java new file mode 100644 index 000000000..15cbfc05e --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/prepayment/PrepaymentDTO.java @@ -0,0 +1,79 @@ +package com.zeroone.star.project.dto.prepayment; + + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; +import org.springframework.web.multipart.MultipartFile; + +/** + * @Author: Kong + * @License: (C) Copyright 2005-2019, xxx Corporation Limited. + * @Contact: xxx@xxx.com + * @Date: 2023-02-11 20:31 + * @Version: 1.0 + * @Description: 预付款 + */ +@Data +@ToString +@ApiModel("预付款信息") +public class PrepaymentDTO { + +// @ApiModelProperty(value = "id",example = "1626949545251745795") + private String id; + + @ApiModelProperty(value = "金额",example = "1000.00") + private BigDecimal amt; + + @ApiModelProperty(value = "附件",example = "temp/psi-预付_1676723329419.md") + private String attachment; + + @ApiModelProperty(value = "单据日期",example = "2022-01-14") + @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + private LocalDate billDate; + + @ApiModelProperty(value = "单据编号",example = "TEST-221120-002") + private String billNo; + + @ApiModelProperty(value = "已核销金额",example = "1000.00") + private BigDecimal checkAmt; + + @ApiModelProperty(value = "是否自动单据",example = "0") + private Integer isAuto; + + @ApiModelProperty(value = "是否红字",example = "0") + private Integer isRubric; + + @ApiModelProperty(value = "付款类型",example = "2011") + private String paymentType; + + @ApiModelProperty(value = "备注",example = "remark..") + private String remark; + +// @ApiModelProperty(value = "源单类型",example = "FinPaymentReq:2011") +// private String srcBillType; +// +// @ApiModelProperty(value = "源单id",example = "1594317750844637186") +// private String srcBillId; +// +// @ApiModelProperty(value = "源单号",example = "TESTSQ-221120-001") +// private String srcNo; + + @ApiModelProperty(value = "单据主题",example = "tittle") + private String subject; + + @ApiModelProperty(value = "供应商",example = "1584950950470164481") + private String supplierId; + + @ApiModelProperty(value = "采购明细单",example = "") + private List finPaymentEntryList; + +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/prepayment/StatusDTO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/prepayment/StatusDTO.java new file mode 100644 index 000000000..ee8ec0365 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/prepayment/StatusDTO.java @@ -0,0 +1,16 @@ +package com.zeroone.star.project.dto.prepayment; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 修改状态DTO + * author yu-hang + */ +@Data +@ApiModel("修改状态功能") +public class StatusDTO { + @ApiModelProperty(value = "id") + private String id; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/sample/SampleDTO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/sample/SampleDTO.java new file mode 100644 index 000000000..7969f6d4a --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/dto/sample/SampleDTO.java @@ -0,0 +1,28 @@ +package com.zeroone.star.project.dto.sample; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 描述:示例数据传输对象 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Data +@ApiModel("示例传输数据对象") +public class SampleDTO { + @ApiModelProperty(value = "编号", example = "1") + private Integer id; + @ApiModelProperty(value = "姓名", example = "张三") + private String name; + @ApiModelProperty(value = "性别", example = "男") + private String sex; + @ApiModelProperty(value = "年龄", example = "18") + private Integer age; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/PageQuery.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/PageQuery.java new file mode 100644 index 000000000..52466d3ce --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/PageQuery.java @@ -0,0 +1,30 @@ +package com.zeroone.star.project.query; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import javax.validation.constraints.Min; + +/** + *

+ * 描述:分页查询父类对象 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Getter +@Setter +@ToString +public class PageQuery { + @Min(value = 1, message = "页码最小值为1") + @ApiModelProperty(value = "查询页码", example = "1") + private long pageIndex; + @Min(value = 1, message = "条数最小值为1") + @ApiModelProperty(value = "查询条数", example = "10") + private long pageSize; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/cpp/SampleQuery.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/cpp/SampleQuery.java new file mode 100644 index 000000000..0ce0205c5 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/cpp/SampleQuery.java @@ -0,0 +1,27 @@ +package com.zeroone.star.project.query.cpp; + +import com.zeroone.star.project.query.PageQuery; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + *

+ * 描述:示例查询对象 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel("C++示例查询对象") +public class SampleQuery extends PageQuery { + @ApiModelProperty(value = "姓名", example = "张三") + private String name; + @ApiModelProperty(value = "性别", example = "男") + private String sex; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/prepayment/DocListQuery.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/prepayment/DocListQuery.java new file mode 100644 index 000000000..ab2688155 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/prepayment/DocListQuery.java @@ -0,0 +1,81 @@ +package com.zeroone.star.project.query.prepayment; + +import com.zeroone.star.project.query.PageQuery; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDate; + +/** + *

+ * 描述:单据列表查询对象 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author husj + * @version 1.0.0 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel("单据列表查询对象") +public class DocListQuery extends PageQuery { + + /** + * 单据编号 + */ + @ApiModelProperty(value = "单据编号") + private String billNo; + + /** + * 开始单据日期 + */ + @ApiModelProperty(value = "单据日期(开始)") + private String billDateStart; + /** + * 结束单据日期 + */ + @ApiModelProperty(value = "单据日期(结束)") + private String billDateEnd; + + /** + * 单据主题 + */ + @ApiModelProperty(value = "单据主题") + private String subject; + /** + * 供应商 + */ + @ApiModelProperty(value = "供应商") + private String supplierId; + /** + * 处理状态 + */ + @ApiModelProperty(value = "处理状态") + private String billStage; + /** + * 是否生效(前台数据 后台没有) + */ + @ApiModelProperty(value = "是否生效") + private Integer isEffective; + + /** + * 已关闭 + */ + @ApiModelProperty(value = "已关闭") + private Integer isClosed; + + /** + * 是否作废 + */ + @ApiModelProperty(value = "是否作废") + private Boolean isVoided; + + /** + * 付款类型 + */ + @ApiModelProperty(value = "付款类型") + private String paymentType; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/prepayment/FinPaymentExportQuery.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/prepayment/FinPaymentExportQuery.java new file mode 100644 index 000000000..50924cf46 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/prepayment/FinPaymentExportQuery.java @@ -0,0 +1,219 @@ +package com.zeroone.star.project.query.prepayment; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import com.alibaba.excel.annotation.write.style.ContentStyle; +import com.alibaba.excel.annotation.write.style.HeadStyle; +import com.alibaba.excel.enums.poi.HorizontalAlignmentEnum; +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; + +import com.zeroone.star.project.components.easyexcel.LocalDateStringConverter; +import com.zeroone.star.project.components.easyexcel.LocalDateTimeStringConverter; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +@Data +@HeadStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER)//表头样式 +@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER)//内容样式 +@ColumnWidth(20)//表头宽度 +public class FinPaymentExportQuery { + + @ApiModelProperty(value = "付款类型",example = "采购预付(无申请)") + @ExcelProperty(value = {"付款单信息","付款类型"}, index = 0) + private String isRequested; + + // 需要结合供应商表查询名称 + @ApiModelProperty(value = "供应商",example = "1584950950470164481") + @ExcelProperty(value = {"付款单信息","供应商"}, index = 1) + private String supplierId; + + @ApiModelProperty(value = "金额",example = "666.00") + @ExcelProperty(value = {"付款单信息","金额"}, index = 2) + private BigDecimal amt; + + @ApiModelProperty(value = "已核销金额",example = "0.00") + @ExcelProperty(value = {"付款单信息","已核销金额"}, index = 3) + private BigDecimal checkedAmt; + + // 以下为-明细表数据 + + @ApiModelProperty(value = "结算方式",example = "31(银行代扣)") + @ExcelProperty(value = {"付款单信息","付款明细","结算方式"}, index = 4) + private String settleMethod; + + @ApiModelProperty(value = "资金账户",example = "1584913699556106242") + @ExcelProperty(value = {"付款单信息","付款明细","资金账户"}, index = 5) + private String bankAccountId; + + @ApiModelProperty(value = "金额",example = "142000.00") + @ExcelProperty(value = {"付款单信息","付款明细","金额"}, index = 6) + private BigDecimal eAmt; + + @ApiModelProperty(value = "自定义1",example = "this is custom1 information") + @ExcelProperty(value = {"付款单信息","付款明细","自定义1"}, index = 7) + private String custom1; + + @ApiModelProperty(value = "源单分录号",example = "CGRK-221110-001") + @ExcelProperty(value = {"付款单信息","付款明细","源单分录号"}, index = 8) + private String eSrcNo; + + @ApiModelProperty(value = "分录号",example = "10") + @ExcelProperty(value = {"付款单信息","付款明细","分录号"}, index = 9) + private Integer entryNo; + + @ApiModelProperty(value = "自定义2",example = "this is custom2 information") + @ExcelProperty(value = {"付款单信息","付款明细","自定义2"}, index = 10) + private String custom2; + + @ApiModelProperty(value = "源单分录id",example = "404") + @ExcelProperty(value = {"付款单信息","付款明细","源单分录id"}, index = 11) + private String srcEntryId; + + @ApiModelProperty(value = "源单类型",example = "StkIo:101") + @ExcelProperty(value = {"付款单信息","付款明细","源单类型"}, index = 12) + private String eSrcBillType; + + @ApiModelProperty(value = "备注",example = "备注") + @ExcelProperty(value = {"付款单信息","付款明细","备注"}, index = 13) + private String eRemark; + + @ApiModelProperty(value = "单据编号",example = "CGFK-221110-001") + @ExcelProperty(value = {"付款单信息","付款明细","单据编号"}, index = 14) + private String eBillNo; + + @ApiModelProperty(value = "源单id",example = "1590717667678928898") + @ExcelProperty(value = {"付款单信息","付款明细","源单id"}, index = 15) + private String eSrcBillId; + + // 以上为-明细表数据 + + @ApiModelProperty(value = "是否生效",example = "1") + @ExcelProperty(value = {"付款单信息","是否生效"}, index = 16) + private String isEffective; + + @ApiModelProperty(value = "附件",example = "http://1.15.240.108:8888/group1/M00/00/01/AQ_wbGP2I02AJZgOAAeNLGKTjJk029.png?token=d7f2325f52092f4f07de04093d7f0036&ts=1677075275") + @ExcelProperty(value = {"付款单信息","附件"}, index = 17) + private String attachment; + + @ApiModelProperty(value = "源单id",example = "1594317750844637186") + @ExcelProperty(value = {"付款单信息","源单id"}, index = 18) + private String srcBillId; + + @ApiModelProperty(value = "单据主题",example = "tittle") + @ExcelProperty(value = {"付款单信息","单据主题"}, index = 19) + private String subject; + + @ApiModelProperty(value = "单据阶段",example = "11") + @ExcelProperty(value = {"付款单信息","单据阶段"}, index = 20) + private String billStage; + + @ApiModelProperty(value = "源单号",example = "CGYFSQ-221120-001") + @ExcelProperty(value = {"付款单信息","源单号"}, index = 21) + private String srcNo; + + @ApiModelProperty(value = "是否自动单据",example = "0") + @ExcelProperty(value = {"付款单信息","是否自动单据"}, index = 22) + private String isAuto; + + @ApiModelProperty(value = "备注",example = "remark..") + @ExcelProperty(value = {"付款单信息","备注"}, index = 23) + private String remark; + + @ApiModelProperty(value = "审批实例id",example = "dingtalk:Bgd6Yqw2Sw-XE8KYVI2fgA02311668951176") + @ExcelProperty(value = {"付款单信息","审批实例id"}, index = 24) + private String bpmiInstanceId; + + @ApiModelProperty(value = "已作废",example = "0") + @ExcelProperty(value = {"付款单信息","已作废"}, index = 25) + private String isVoided; + + @ApiModelProperty(value = "单据编号",example = "CGFK-221110-001") + @ExcelProperty(value = {"付款单信息","单据编号"}, index = 26) + private String billNo; + + @ApiModelProperty(value = "是否红字",example = "0") + @ExcelProperty(value = {"付款单信息","是否红字"}, index = 27) + private String isRubric; + + @ApiModelProperty(value = "源单类型",example = "FinPaymentReq:2011") + @ExcelProperty(value = {"付款单信息","源单类型"}, index = 28) + private String srcBillType; + + @ApiModelProperty(value = "制单时间",example = "2023-02-22 23:04:27") + @ExcelProperty(value = {"付款单信息","制单时间"}, index = 29, converter = LocalDateTimeStringConverter.class) + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + @ApiModelProperty(value = "生效时间",example = "2023-02-22 23:04:27") + @ExcelProperty(value = {"付款单信息","生效时间"}, index = 30, converter = LocalDateTimeStringConverter.class) + private LocalDateTime effectiveTime; + + @ApiModelProperty(value = "核批人",example = "admin") + @ExcelProperty(value = {"付款单信息","核批人"}, index = 31) + private String approver; + + @ApiModelProperty(value = "修改人",example = "admin") + @ExcelProperty(value = {"付款单信息","修改人"}, index = 32) + private String updateBy; + + @ApiModelProperty(value = "制单部门",example = "A01A03") + @ExcelProperty(value = {"付款单信息","制单部门"}, index = 33) + private String sysOrgCode; + + @ApiModelProperty(value = "已关闭",example = "0") + @ExcelProperty(value = {"付款单信息","已关闭"}, index = 34) + private String isClosed; + + @ApiModelProperty(value = "核批结果类型",example = "1") + @ExcelProperty(value = {"付款单信息","核批结果类型"}, index = 35) + private String approvalResultType; + + @ApiModelProperty(value = "单据日期",example = "2022-01-14") + @ExcelProperty(value = {"付款单信息","单据日期"}, index = 36, converter = LocalDateStringConverter.class) + private LocalDate billDate; + + @ApiModelProperty(value = "制单人",example = "admin") + @ExcelProperty(value = {"付款单信息","制单人"}, index = 37) + private String createBy; + + @ApiModelProperty(value = "核批意见",example = "通过") + @ExcelProperty(value = {"付款单信息","核批意见"}, index = 38) + private String approvalRemark; + + + // 以下为非表显内容,不导出到Excel + @ApiModelProperty(value = "id",example = "1590727821862420481") + @ExcelIgnore + private String id; + + @ApiModelProperty(value = "付款类型",example = "2011") + @ExcelIgnore + private String paymentType; //该字段来自实体类,名称存疑,暂时舍弃 + + @ApiModelProperty(value = "修改时间",example = "2022-11-21 08:56:09") + @ExcelIgnore + private LocalDateTime updateTime; + + @ApiModelProperty(value = "版本",example = "1.0") + @ExcelIgnore + private Integer version; + + // 以下为明细表的字段 + @ApiModelProperty(value = "eID",example = "1590727821900169217") + @ExcelIgnore + private String eid; + + @ApiModelProperty(value = "主表",example = "1590727821862420481") + @ExcelIgnore + private String mid; + + @ApiModelProperty(value = "版本",example = "1.0") + @ExcelIgnore + private Integer eVersion; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/prepayment/FinPaymentQuery.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/prepayment/FinPaymentQuery.java new file mode 100644 index 000000000..aadfda6c5 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/prepayment/FinPaymentQuery.java @@ -0,0 +1,200 @@ +package com.zeroone.star.project.query.prepayment; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.zeroone.star.project.query.PageQuery; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel("查询单据列表") +public class FinPaymentQuery extends PageQuery { + /** + * ID + */ +// @TableId(type = IdType.ASSIGN_ID) + @ApiModelProperty(value = "id") + private String id; + + /** + * 单据编号 + */ + @ApiModelProperty(value = "单据编号") + private String billNo; + + /** + * 单据日期 + */ + @ApiModelProperty(value = "单据日期") + private LocalDate billDate; + + /** + * 源单类型 + */ + @ApiModelProperty(value = "源单类型") + private String srcBillType; + + /** + * 源单id + */ + @ApiModelProperty(value = "源单id") + private String srcBillId; + + /** + * 源单号 + */ + @ApiModelProperty(value = "源单号") + private String srcNo; + + /** + * 单据主题 + */ + @ApiModelProperty(value = "单据主题") + private String subject; + + /** + * 是否红字 + */ + @ApiModelProperty(value = "是否红字") + private Integer isRubric; + + /** + * 付款类型 + */ + @ApiModelProperty(value = "付款类型") + private String paymentType; + + /** + * 供应商 + */ + @ApiModelProperty(value = "供应商") + private String supplierId; + + /** + * 金额 + */ + @ApiModelProperty(value = "金额") + private BigDecimal amt; + + /** + * 已核销金额 + */ + @ApiModelProperty(value = "已核销金额") + private BigDecimal checkedAmt; + + /** + * 附件 + */ + @ApiModelProperty(value = "附件") + private String attachment; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注") + private String remark; + + /** + * 是否自动单据 + */ + @ApiModelProperty(value = "是否自动单据") + private Integer isAuto; + + /** + * 处理状态 + */ + @ApiModelProperty(value = "处理状态") + private String billStage; + + /** + * 审核人 + */ + @ApiModelProperty(value = "审核人") + private String approver; + + /** + * 流程 + */ + @ApiModelProperty(value = "流程") + private String bpmiInstanceId; + + /** + * 核批结果类型 + */ + @ApiModelProperty(value = "核批结果类型") + private String approvalResultType; + + /** + * 核批意见 + */ + @ApiModelProperty(value = "核批意见") + private String approvalRemark; + + /** + * 是否通过 + */ + @ApiModelProperty(value = "是否通过") + private Integer isEffective; + + /** + * 生效时间 + */ + @ApiModelProperty(value = "生效时间") + private LocalDateTime effectiveTime; + + /** + * 已关闭 + */ + @ApiModelProperty(value = "已关闭") + private Integer isClosed; + + /** + * 是否作废 + */ + @ApiModelProperty(value = "是否作废") + private Boolean isVoided; + + /** + * 创建时间 + */ + @ApiModelProperty(value = "创建时间") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 创建人 + */ + @ApiModelProperty(value = "创建人") + private String createBy; + + /** + * 创建部门 + */ + @ApiModelProperty(value = "创建部门") + private String sysOrgCode; + + /** + * 修改时间 + */ + @ApiModelProperty(value = "修改时间") + private LocalDateTime updateTime; + + /** + * 修改人 + */ + @ApiModelProperty(value = "修改人") + private String updateBy; + + /** + * 版本 + */ + @ApiModelProperty(value = "版本") + private Integer version; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/prepayment/FinPaymentReqQuery.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/prepayment/FinPaymentReqQuery.java new file mode 100644 index 000000000..125f8be7e --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/prepayment/FinPaymentReqQuery.java @@ -0,0 +1,30 @@ +package com.zeroone.star.project.query.prepayment; + +import com.zeroone.star.project.query.PageQuery; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.validation.annotation.Validated; + +import javax.validation.constraints.NotBlank; +import java.time.LocalDate; + +@EqualsAndHashCode(callSuper = true) +@Data +@Validated +@ApiModel("申请单查询对象") +public class FinPaymentReqQuery extends PageQuery { + @NotBlank(message = "供应商id") + @ApiModelProperty(value = "供应商id", example = "1584950950470164481") + private String supplierId; + +// @ApiModelProperty(value = "单据编号", example = "CGYFSQ-230210-007") +// private String billNo; + +// @ApiModelProperty(value = "开始日期", example = "2023-02-03") +// private LocalDate startDate; +// +// @ApiModelProperty(value = "结束日期", example = "2023-02-04") +// private LocalDate endDate; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/prepayment/PreDetQuery.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/prepayment/PreDetQuery.java new file mode 100644 index 000000000..bd6f7e440 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/prepayment/PreDetQuery.java @@ -0,0 +1,24 @@ +package com.zeroone.star.project.query.prepayment; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.validation.constraints.NotBlank; + +/** + * @ClassName DetQuery + * @Description 根据单据编号查询 + * @Author HZP + * @Date 2023/2/12 14:15 + * @Version 1.0 + **/ +@EqualsAndHashCode(callSuper = false) +@Data +@ApiModel("单据编号查询") +public class PreDetQuery { + @NotBlank(message = "单据编号不能为空") + @ApiModelProperty(value = "单据编号",example = "CGYF-230211-022") + private String billNo; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/prepayment/PurchaseListQuery.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/prepayment/PurchaseListQuery.java new file mode 100644 index 000000000..ceb9f9d50 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/prepayment/PurchaseListQuery.java @@ -0,0 +1,38 @@ +package com.zeroone.star.project.query.prepayment; + +import com.zeroone.star.project.query.PageQuery; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +/** + * @Author: Kong + * @License: (C) Copyright 2005-2019, xxx Corporation Limited. + * @Contact: xxx@xxx.com + * @Date: 2023-02-11 20:16 + * @Version: 1.0 + * @Description: 采购清单 + */ +@ToString +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel("采购清单查询条件") +public class PurchaseListQuery extends PageQuery { + + @ApiModelProperty(value = "timestamp",example = "1594317750844637186") + private String _t; + + @ApiModelProperty(value = "付款类型",example = "2011") + private String self_payment_type; + + @ApiModelProperty(value = "已关闭",example = "1") + private Integer self_is_closed; + + @ApiModelProperty(value = "供应商id",example = "1584950950470164481") + private String self_supplier_id; + +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/sample/SampleQuery.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/sample/SampleQuery.java new file mode 100644 index 000000000..0c84ef30d --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/query/sample/SampleQuery.java @@ -0,0 +1,28 @@ +package com.zeroone.star.project.query.sample; + +import com.zeroone.star.project.query.PageQuery; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.validation.constraints.NotBlank; + +/** + *

+ * 描述:示例查询对象 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel("示例查询对象") +public class SampleQuery extends PageQuery { + @NotBlank(message = "用户名不能为空") + @ApiModelProperty(value = "姓名", example = "张三") + private String name; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/ExtendPageVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/ExtendPageVO.java new file mode 100644 index 000000000..5adae845f --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/ExtendPageVO.java @@ -0,0 +1,67 @@ +package com.zeroone.star.project.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + *

+ * 描述:分页数据显示扩展类 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class ExtendPageVO extends PageVO { + /** + * 根据指定的参数创建分页显示的对象 + * + * @param rows 记录数据 + * @param pageIndex 当前显示码 + * @param pageSize 当前页最大显示条数 + * @param total 数据总数 + */ + public ExtendPageVO(List rows, long pageIndex, long pageSize, long total) { + this.rows = rows; + this.pageIndex = pageIndex; + this.pageSize = pageSize; + this.total = total; + this.pages = (long) Math.ceil((double) total / pageSize); + } + + @ApiModelProperty(value = "是否有上一页", example = "false") + public boolean isPrevious() { + return this.pageIndex > 1; + } + + @ApiModelProperty(value = "是否有下一页", example = "true") + public boolean isNext() { + return this.pageIndex < this.pages; + } + + @ApiModelProperty(value = "上一页页码", example = "1") + public long getPreviousPage() { + return isPrevious() ? this.pageIndex - 1 : 1; + } + + @ApiModelProperty(value = "下一页页码", example = "3") + public long getNextPage() { + return isNext() ? this.pageIndex + 1 : this.pages; + } + + @ApiModelProperty(value = "是否是首页", example = "true") + public boolean isFirst() { + return this.pageIndex == 1; + } + + @ApiModelProperty(value = "是否是最后一页", example = "false") + public boolean isLast() { + return this.pageIndex.equals(this.pages); + } +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/JsonVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/JsonVO.java new file mode 100644 index 000000000..11b8c43a6 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/JsonVO.java @@ -0,0 +1,105 @@ +package com.zeroone.star.project.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + *

+ * 描述:前后端数据对接数据对象 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class JsonVO implements Serializable { + /** + * 状态码 + */ + @ApiModelProperty(value = "状态码", example = "10000") + private Integer code; + + /** + * 提示消息 + */ + @ApiModelProperty(value = "提示消息", example = "提示消息内容") + private String message; + + /** + * 数据对象 + */ + @ApiModelProperty(value = "数据对象") + private T data; + + /** + * 通过结果枚举设置状态码和提示消息 + * + * @param resultStatus 结果状态枚举 + */ + private void setStatus(ResultStatus resultStatus) { + this.setMessage(resultStatus.getMessage()); + this.setCode(resultStatus.getCode()); + } + + /** + * 静态构建方式 + * + * @param data 获取的数据 + * @param resultStatus 提示信息 + * @param JsonVO嵌套元素类型 + * @return 返回创建的JSON VO对象 + */ + public static JsonVO create(T data, ResultStatus resultStatus) { + JsonVO result = new JsonVO<>(); + result.setStatus(resultStatus); + result.setData(data); + return result; + } + + /** + * 静态构建方式 + * + * @param data 获取的数据 + * @param code 状态码 + * @param message 提示信息 + * @param JsonVO嵌套元素类型 + * @return 返回创建的JSON VO对象 + */ + public static JsonVO create(T data, int code, String message) { + JsonVO result = new JsonVO<>(); + result.setCode(code); + result.setMessage(message); + result.setData(data); + return result; + } + + /** + * 静态构建处理成功数据对象 + * + * @param data 数据对象 + * @param JsonVO嵌套元素类型 + * @return 返回创建的JSON VO对象 + */ + public static JsonVO success(T data) { + return create(data, ResultStatus.SUCCESS); + } + + /** + * 静态构建处理失败数据对象 + * + * @param data 数据对象 + * @param JsonVO嵌套元素类型 + * @return 返回创建的JSON VO对象 + */ + public static JsonVO fail(T data) { + return create(data, ResultStatus.FAIL); + } +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/PageVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/PageVO.java new file mode 100644 index 000000000..eb43e392b --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/PageVO.java @@ -0,0 +1,107 @@ +package com.zeroone.star.project.vo; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + *

+ * 描述:分页数据实体 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class PageVO implements Serializable { + /** + * 当前页码 + */ + @ApiModelProperty(value = "当前页码", example = "1") + protected Long pageIndex; + + /** + * 每页显示最大数据条数 + */ + @ApiModelProperty(value = "每页显示最大数据条数", example = "10") + protected Long pageSize; + + /** + * 数据的总条数 + */ + @ApiModelProperty(value = "总条数", example = "100000") + protected Long total; + + /** + * 数据的总页数 + */ + @ApiModelProperty(value = "总页数", example = "100") + protected Long pages; + + /** + * 当前页数据列表 + */ + @ApiModelProperty(value = "当前页数据列表") + protected List rows; + + /** + * 静态构建方法,将Page对象转换成当前数据对象 + * + * @param page 分页插件的page对象 + * @param 数据类型 + * @return 返回分页数据对象 + */ + public static PageVO create(Page page) { + PageVO pageResult = new PageVO<>(); + pageResult.setTotal(page.getTotal()); + pageResult.setRows(page.getRecords()); + pageResult.setPageIndex(page.getCurrent()); + pageResult.setPageSize(page.getSize()); + pageResult.setPages(page.getPages()); + return pageResult; + } + + /** + * 静态构建方法,将Page对象转换成当前数据对象 + * + * @param page 分页插件的page对象 + * @param tClass VO类型 + * @param VO数据类型 + * @param DO数据模型 + * @return 返回分页数据对象 + */ + public static PageVO create(Page page, Class tClass) { + PageVO pageResult = new PageVO<>(); + pageResult.setTotal(page.getTotal()); + pageResult.setPageIndex(page.getCurrent()); + pageResult.setPageSize(page.getSize()); + pageResult.setPages(page.getPages()); + //转换数据 + List records = page.getRecords(); + if (records != null && !records.isEmpty()) { + List rows = new ArrayList<>(); + for (D sub : records) { + try { + T t = tClass.newInstance(); + BeanUtil.copyProperties(sub, t); + rows.add(t); + } catch (InstantiationException | IllegalAccessException e) { + e.printStackTrace(); + } + } + pageResult.setRows(rows); + } + return pageResult; + } +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/ResultStatus.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/ResultStatus.java new file mode 100644 index 000000000..acff41f64 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/ResultStatus.java @@ -0,0 +1,45 @@ +package com.zeroone.star.project.vo; + +/** + *

+ * 描述:响应码枚举 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +public enum ResultStatus { + /***/ + UNAUTHORIZED("暂未登录或TOKEN已经过期", 401), + FORBIDDEN("没有相关权限", 403), + SERVER_ERROR("服务器错误", 9994), + PARAMS_INVALID("上传参数异常", 9995), + CONTENT_TYPE_ERR("ContentType错误",9996), + API_UN_IMPL("功能尚未实现", 9997), + SERVER_BUSY("服务器繁忙", 9998), + FAIL("操作失败", 9999), + SUCCESS("操作成功"), + ; + + private final String message; + private final int code; + + ResultStatus(String message, int code) { + this.message = message; + this.code = code; + } + + ResultStatus(String message) { + this(message, 10000); + } + + public String getMessage() { + return message; + } + + public int getCode() { + return code; + } +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/TreeNodeVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/TreeNodeVO.java new file mode 100644 index 000000000..744671b99 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/TreeNodeVO.java @@ -0,0 +1,41 @@ +package com.zeroone.star.project.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + *

+ * 描述:用来定义一个树形节点的数据 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Data +public class TreeNodeVO implements Serializable { + @ApiModelProperty(value = "唯一ID", example = "1") + private String id; + @ApiModelProperty(value = "节点文本描述", example = "会员管理") + private String text; + @ApiModelProperty(value = "节点对应图标", example = "fa-user-md") + private String icon; + @ApiModelProperty(value = "节点链接地址", example = "menuManagement") + private String href; + @ApiModelProperty(value = "节点父节点ID", example = "null") + private String pid; + @ApiModelProperty(value = "节点深度", example = "0") + private Integer depth; + @ApiModelProperty(value = "是否展开", example = "false") + private Boolean expanded; + @ApiModelProperty(value = "是否选中", example = "false") + private Boolean checked; + @ApiModelProperty(value = "节点包含的子节点") + private List> children; + @ApiModelProperty(value = "节点源数据对象") + private T raw; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/cpp/SampleVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/cpp/SampleVO.java new file mode 100644 index 000000000..bf8e4b1e2 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/cpp/SampleVO.java @@ -0,0 +1,28 @@ +package com.zeroone.star.project.vo.cpp; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 描述:示例视图对象 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Data +@ApiModel("C++示例显示对象") +public class SampleVO { + @ApiModelProperty(value = "编号", example = "1") + private Integer id; + @ApiModelProperty(value = "姓名", example = "张三") + private String name; + @ApiModelProperty(value = "性别", example = "男") + private String sex; + @ApiModelProperty(value = "年龄", example = "18") + private Integer age; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/login/LoginVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/login/LoginVO.java new file mode 100644 index 000000000..6b42cad75 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/login/LoginVO.java @@ -0,0 +1,33 @@ +package com.zeroone.star.project.vo.login; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + *

+ * 描述:登录显示数据对象 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@ApiModel("登录显示对象") +@Data +public class LoginVO { + @ApiModelProperty(value = "用户唯一编号", example = "1") + private Integer id; + + @ApiModelProperty(value = "用户名", example = "admin") + private String username; + + @ApiModelProperty(value = "是否启用 1 启用 0 禁用 ", example = "1") + private Byte isEnabled; + + @ApiModelProperty(value = "用户角色列表", example = "['ADMIN','MANAGER']") + private List roles; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/login/MenuTreeVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/login/MenuTreeVO.java new file mode 100644 index 000000000..81032da57 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/login/MenuTreeVO.java @@ -0,0 +1,28 @@ +package com.zeroone.star.project.vo.login; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 描述:树状菜单显示数据 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Data +public class MenuTreeVO { + @ApiModelProperty(value = "序号", example = "1") + private Integer id; + @ApiModelProperty(value = "菜单名称", example = "获取菜单列表") + private String name; + @ApiModelProperty(value = "路由地址", example = "") + private String path; + @ApiModelProperty(value = "图标", example = "fa-stethoscope") + private String icon; + @ApiModelProperty(value = "父级菜单编号", example = "") + private Integer parentMenuId; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/BasBankAccountVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/BasBankAccountVO.java new file mode 100644 index 000000000..c02a1b0f2 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/BasBankAccountVO.java @@ -0,0 +1,43 @@ +package com.zeroone.star.project.vo.prepayment; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Author: Kong + * @License: (C) Copyright 2005-2019, xxx Corporation Limited. + * @Contact: xxx@xxx.com + * @Date: 2023-02-15 11:30 + * @Version: 1.0 + * @Description: 银行账户 字典 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel("银行账户显示对象") +public class BasBankAccountVO { + /** + * id + */ + @ApiModelProperty(value = "id",example = "1584915128429649922") + private String value; + + /** + * 账号 + */ + @ApiModelProperty(value = "账号",example = "22345678901234567890") + private String text; + /** + * 账号 + */ + @ApiModelProperty(value = "账号",example = "22345678901234567890") + private String label; + /** + * 账号 + */ + @ApiModelProperty(value = "账号",example = "22345678901234567890") + private String title; +} \ No newline at end of file diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/DetHavVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/DetHavVO.java new file mode 100644 index 000000000..505dc3d22 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/DetHavVO.java @@ -0,0 +1,160 @@ +package com.zeroone.star.project.vo.prepayment; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; + +/** + * @ClassName DetHavVO + * @Description 查询订单详情-有申请 + * @Author HZP + * @Date 2023/2/12 11:30 + * @Version 1.0 + **/ +@Data +@ApiModel("有申请显示对象") +public class DetHavVO { + + /** + * 单据编号 + */ + @ApiModelProperty(value = "单据编号",example = "CGFK-221110-001") + private String billNo; + + /** + * 单据日期 + */ + @ApiModelProperty(value = "单据日期",example = "2022-11-11") + private LocalDate billDate; + + /** + * 单据主题 + */ + @ApiModelProperty(value = "单据主题",example = "") + private String subject; + + /** + * 是否红字 + */ + @ApiModelProperty(value = "红字单据",example = "1") + private Integer isRubric; + + /** + * 供应商 + */ + @ApiModelProperty(value = "供应商",example = "光缆厂家1") + private String supplierId; + + /** + * 已核销金额 + */ + @ApiModelProperty(value = "已核销金额",example = "0") + private BigDecimal checkedAmt; + + /** + * 附件 + */ + @ApiModelProperty(value = "附件",example = "--") + private String attachment; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注",example = "") + private String remark; + + /** + * 是否自动单据 + */ + @ApiModelProperty(value = "自动单据",example = "1") + private Integer isAuto; + + /** + * 审批实例 + */ + @ApiModelProperty(value = "审批实例",example = "") + private String bpmiInstance; + + /** + * 审核人 + */ + @ApiModelProperty(value = "核批人",example = "") + private String approver; + + /** + * 核批结果类型 + */ + @ApiModelProperty(value = "核批结果",example = "") + private String approvalResultType; + + /** + * 核批意见 + */ + @ApiModelProperty(value = "核批意见",example = "") + private String approvalRemark; + + /** + * 是否通过 + */ + @ApiModelProperty(value = "已生效",example = "1") + private Integer isEffective; + + /** + * 生效时间 + */ + @ApiModelProperty(value = "生效时间",example = "2022-11-12") + private LocalDateTime effectiveTime; + + /** + * 已关闭 + */ + @ApiModelProperty(value = "已关闭",example = "1") + private Integer isClosed; + + /** + * 是否作废 + */ + @ApiModelProperty(value = "已作废",example = "false") + private Boolean isVoided; + + /** + * 创建时间 + */ + @ApiModelProperty(value = "制单时间",example = "") + private LocalDateTime createTime; + + /** + * 创建人 + */ + @ApiModelProperty(value = "制单人",example = "管理员") + private String createBy; + + /** + * 创建部门 + */ + @ApiModelProperty(value = "制单部门",example = "研发部") + private String sysOrgCode; + + /** + * 修改时间 + */ + @ApiModelProperty(value = "修改时间",example = "") + private LocalDateTime updateTime; + + /** + * 修改人 + */ + @ApiModelProperty(value = "修改人",example = "") + private String updateBy; + + @ApiModelProperty(value = "明细",example = "") + private List listDetail; + + @ApiModelProperty(value = "采购预付申请单",example = "") + private FinPaymentReqVO req; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/DetNoVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/DetNoVO.java new file mode 100644 index 000000000..41da2ec49 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/DetNoVO.java @@ -0,0 +1,159 @@ +package com.zeroone.star.project.vo.prepayment; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; + +/** + * @ClassName DetNoVO + * @Description 查询订单详情-无申请 + * @Author HZP + * @Date 2023/2/12 11:33 + * @Version 1.0 + **/ +@Data +@ApiModel("无申请显示对象") +public class DetNoVO { + /** + * 单据编号 + */ + @ApiModelProperty(value = "单据编号",example = "CGFK-221121-001") + private String billNo; + + /** + * 单据日期 + */ + @ApiModelProperty(value = "单据日期",example = "2022-11-11") + private LocalDate billDate; + + /** + * 单据主题 + */ + @ApiModelProperty(value = "单据主题",example = "") + private String subject; + + /** + * 是否红字 + */ + @ApiModelProperty(value = "红字单据",example = "1") + private Integer isRubric; + + /** + * 供应商 + */ + @ApiModelProperty(value = "供应商",example = "光缆厂家1") + private String supplierId; + + /** + * 已核销金额 + */ + @ApiModelProperty(value = "已核销金额",example = "0") + private BigDecimal checkedAmt; + + /** + * 附件 + */ + @ApiModelProperty(value = "附件",example = "--") + private String attachment; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注",example = "") + private String remark; + + /** + * 是否自动单据 + */ + @ApiModelProperty(value = "自动单据",example = "1") + private Integer isAuto; + + /** + * 审批实例 + */ + @ApiModelProperty(value = "审批实例",example = "") + private String bpmiInstance; + + /** + * 审核人 + */ + @ApiModelProperty(value = "核批人",example = "") + private String approver; + + /** + * 核批结果类型 + */ + @ApiModelProperty(value = "核批结果",example = "") + private String approvalResultType; + + /** + * 核批意见 + */ + @ApiModelProperty(value = "核批意见",example = "") + private String approvalRemark; + + /** + * 是否通过 + */ + @ApiModelProperty(value = "已生效",example = "1") + private Integer isEffective; + + /** + * 生效时间 + */ + @ApiModelProperty(value = "生效时间",example = "2022-11-12") + private LocalDateTime effectiveTime; + + /** + * 已关闭 + */ + @ApiModelProperty(value = "已关闭",example = "1") + private Integer isClosed; + + /** + * 是否作废 + */ + @ApiModelProperty(value = "已作废",example = "false") + private Boolean isVoided; + + /** + * 创建时间 + */ + @ApiModelProperty(value = "制单时间",example = "") + private LocalDateTime createTime; + + /** + * 创建人 + */ + @ApiModelProperty(value = "制单人",example = "管理员") + private String createBy; + + /** + * 创建部门 + */ + @ApiModelProperty(value = "制单部门",example = "研发部") + private String sysOrgCode; + + /** + * 修改时间 + */ + @ApiModelProperty(value = "修改时间",example = "") + private LocalDateTime updateTime; + + /** + * 修改人 + */ + @ApiModelProperty(value = "修改人",example = "") + private String updateBy; + + @ApiModelProperty(value = "明细",example = "") + private List listDetail; + + @ApiModelProperty(value = "采购订单",example = "") + private PurOrderVO purOrder; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/DocListVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/DocListVO.java new file mode 100644 index 000000000..4d23c4098 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/DocListVO.java @@ -0,0 +1,146 @@ +package com.zeroone.star.project.vo.prepayment; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + *

+ * 描述:展示单据列表 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author husj + * @version 1.0.0 + */ +@Data +@ApiModel("显示单据列表") +public class DocListVO { + + @ApiModelProperty(value = "id",example = "11111") + private String id; + + /** + * 单据编号 + */ + @ApiModelProperty(value = "单据编号",example = "CGYF-230208-020") + private String billNo; + + /** + * 单据日期 + */ + @ApiModelProperty(value = "单据日期",example = "2023-02-08") + private LocalDate billDate; + + /** + * 单据主题 + */ + @ApiModelProperty(value = "单据主题",example = "") + private String subject; + + /** + * 是否红字 + */ + @ApiModelProperty(value = "是否红字",example = "1") + private Integer isRubric; + /** + * 供应商 + */ + @ApiModelProperty(value = "供应商",example = "") + private String supplierId; + + /** + * 金额 + */ + @ApiModelProperty(value = "金额",example = "100.00") + private BigDecimal amt; + + /** + * 已核销金额 + */ + @ApiModelProperty(value = "已核销金额",example = "0.00") + private BigDecimal checkedAmt; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注",example = "100.00") + private String remark; + + /** + * 是否自动单据 + */ + @ApiModelProperty(value = "是否自动单据",example = "") + private Integer isAuto; + + /** + * 处理状态 + */ + @ApiModelProperty(value = "处理状态",example = "执行中") + private String billStage; + + /** + * 审核人 + */ + @ApiModelProperty(value = "审核人",example = "管理员") + private String approver; + + + /** + * 生效时间 + */ + @ApiModelProperty(value = "生效日期",example = "2023-02-08") + private LocalDateTime effectiveTime; + + /** + * 是否生效(前台数据 后台没有) + */ + @ApiModelProperty(value = "是否生效",example = "") + private Integer isEffective; + + /** + * 已关闭 + */ + @ApiModelProperty(value = "已关闭",example = "1") + private Integer isClosed; + + /** + * 是否作废 + */ + @ApiModelProperty(value = "是否作废",example = "") + private Boolean isVoided; + + /** + * 创建时间 + */ + @ApiModelProperty(value = "创建时间",example = "2023-02-08") + private LocalDateTime createTime; + + /** + * 创建人 + */ + @ApiModelProperty(value = "创建人",example = "管理员") + private String createBy; + + /** + * 创建部门 + */ + @ApiModelProperty(value = "创建部门",example = "市场部") + private String sysOrgCode; + + /** + * 修改时间 + */ + @ApiModelProperty(value = "修改时间",example = "2023-02-08") + private LocalDateTime updateTime; + + /** + * 修改人 + */ + @ApiModelProperty(value = "修改人",example = "管理员") + private String updateBy; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/FinPaymentEntryVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/FinPaymentEntryVO.java new file mode 100644 index 000000000..94ec690b7 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/FinPaymentEntryVO.java @@ -0,0 +1,41 @@ +package com.zeroone.star.project.vo.prepayment; + + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * ClassName FinPaymentVO + * @escription 明细对应源单对象 + * Author HZP、KONG + * Date 2023/2/12 15:32 + * Version 1.0 + **/ +@Data +@ApiModel("明细源单对象") +public class FinPaymentEntryVO { + @ApiModelProperty(value = "源单号",example = "CGFKSQ-230211-004") + private String srcBillNo; + + @ApiModelProperty(value = "结算方式",example = "") + private String settleMethod; + + @ApiModelProperty(value = "资金账户",example = "") + private String bankAccountId; + + @ApiModelProperty(value = "金额",example = "90000") + private BigDecimal amt; + + @ApiModelProperty(value = "备注",example = "") + private String remark; + + @ApiModelProperty(value = "自定义1",example = "") + private String custom1; + + @ApiModelProperty(value = "自定义2",example = "") + private String custom2; +} + diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/FinPaymentReqVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/FinPaymentReqVO.java new file mode 100644 index 000000000..a0e5a5882 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/FinPaymentReqVO.java @@ -0,0 +1,84 @@ +package com.zeroone.star.project.vo.prepayment; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import java.math.BigDecimal; +import java.sql.Date; + +/** + *

+ * 付款申请单明细 + *

+ * + * @author Kong + * @since 2023-02-11 + */ +@Data +@ApiModel("采购明细对象") +public class FinPaymentReqVO { +//jeecg_row_key + /** + * id + */ + @ApiModelProperty(value = "id",example = "1594317750844637186") + private String id; + + /** + * 单据号 + */ + @ApiModelProperty(value = "单据编号",example = "CGYFSQ-221120-001") + private String billNo; + + /** + * 单据日期 + */ + @ApiModelProperty(value = "单据日期",example = "2022-11-20") + private Date billDate; + + /** + * 付款类型 + */ + @ApiModelProperty(value = "付款类型",example = "2011") + private Integer paymentType; + + /** + * 已关闭 + */ + @ApiModelProperty(value = "已关闭",example = "1") + private Integer isClosed; + + @ApiModelProperty(value = "操作部门",example = "A01A03") + private String opDept; + + /** + * 业务员 + */ + @ApiModelProperty(value = "业务员",example = "zhagnxiao") + private String operator; + + /** + * 供应商 + */ + @ApiModelProperty(value = "供应商",example = "1584950950470164481") + private String supplierId; + + /** + * 含税金额 + */ + @ApiModelProperty(value = "申请金额",example = "1000.00") + private BigDecimal amt; + + /** + * 含税金额 + */ + @ApiModelProperty(value = "已付金额",example = "1000.00") + private BigDecimal paidAmount; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注",example = "备注") + private String remark; + +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/FinPaymentVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/FinPaymentVO.java new file mode 100644 index 000000000..a8f887289 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/FinPaymentVO.java @@ -0,0 +1,197 @@ +package com.zeroone.star.project.vo.prepayment; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +@Data +@ApiModel("显示单据列表") +public class FinPaymentVO { + /** + * ID + */ +// @TableId(type = IdType.ASSIGN_ID) + @ApiModelProperty(value = "id") + private String id; + + /** + * 单据编号 + */ + @ApiModelProperty(value = "单据编号") + private String billNo; + + /** + * 单据日期 + */ + @ApiModelProperty(value = "单据日期") + private LocalDate billDate; + + /** + * 源单类型 + */ + @ApiModelProperty(value = "源单类型") + private String srcBillType; + + /** + * 源单id + */ + @ApiModelProperty(value = "源单id") + private String srcBillId; + + /** + * 源单号 + */ + @ApiModelProperty(value = "源单号") + private String srcNo; + + /** + * 单据主题 + */ + @ApiModelProperty(value = "单据主题") + private String subject; + + /** + * 是否红字 + */ + @ApiModelProperty(value = "是否红字") + private Integer isRubric; + + /** + * 付款类型 + */ + @ApiModelProperty(value = "付款类型") + private String paymentType; + + /** + * 供应商 + */ + @ApiModelProperty(value = "供应商") + private String supplierId; + + /** + * 金额 + */ + @ApiModelProperty(value = "金额") + private BigDecimal amt; + + /** + * 已核销金额 + */ + @ApiModelProperty(value = "已核销金额") + private BigDecimal checkedAmt; + + /** + * 附件 + */ + @ApiModelProperty(value = "附件") + private String attachment; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注") + private String remark; + + /** + * 是否自动单据 + */ + @ApiModelProperty(value = "是否自动单据") + private Integer isAuto; + + /** + * 处理状态 + */ + @ApiModelProperty(value = "处理状态") + private String billStage; + + /** + * 审核人 + */ + @ApiModelProperty(value = "审核人") + private String approver; + + /** + * 流程 + */ + @ApiModelProperty(value = "流程") + private String bpmiInstanceId; + + /** + * 核批结果类型 + */ + @ApiModelProperty(value = "核批结果类型") + private String approvalResultType; + + /** + * 核批意见 + */ + @ApiModelProperty(value = "核批意见") + private String approvalRemark; + + /** + * 是否通过 + */ + @ApiModelProperty(value = "是否通过") + private Integer isEffective; + + /** + * 生效时间 + */ + @ApiModelProperty(value = "生效时间") + private LocalDateTime effectiveTime; + + /** + * 已关闭 + */ + @ApiModelProperty(value = "已关闭") + private Integer isClosed; + + /** + * 是否作废 + */ + @ApiModelProperty(value = "是否作废") + private Boolean isVoided; + + /** + * 创建时间 + */ + @ApiModelProperty(value = "创建时间") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 创建人 + */ + @ApiModelProperty(value = "创建人") + private String createBy; + + /** + * 创建部门 + */ + @ApiModelProperty(value = "创建部门") + private String sysOrgCode; + + /** + * 修改时间 + */ + @ApiModelProperty(value = "修改时间") + private LocalDateTime updateTime; + + /** + * 修改人 + */ + @ApiModelProperty(value = "修改人") + private String updateBy; + + /** + * 版本 + */ + @ApiModelProperty(value = "版本") + private Integer version; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/OrderListVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/OrderListVO.java new file mode 100644 index 000000000..b5f2f9f95 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/OrderListVO.java @@ -0,0 +1,28 @@ +package com.zeroone.star.project.vo.prepayment; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import java.util.List; + +/** + * @Author: Kong + * @License: (C) Copyright 2005-2019, xxx Corporation Limited. + * @Contact: xxx@xxx.com + * @Date: 2023-02-18 11:31 + * @Version: 1.0 + * @Description: 采购列表 + */ +@Data +@AllArgsConstructor +@ApiModel("采购列表显示对象") +public class OrderListVO { + + @ApiModelProperty(value = "记录列表",example = "") + private List records; + + @ApiModelProperty(value = "记录数",example = "10") + private Integer total; + +} \ No newline at end of file diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/PaymentReqEntryVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/PaymentReqEntryVO.java new file mode 100644 index 000000000..238cdfe31 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/PaymentReqEntryVO.java @@ -0,0 +1,55 @@ +package com.zeroone.star.project.vo.prepayment; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +@Data +@ApiModel("申请单明细显示对象") +public class PaymentReqEntryVO { + + /** + * 单据编号 + */ + @ApiModelProperty(value = "源单号", example = "CGDD-221120-001") + private String srcNo; + + /** + * 结算方式 + */ + @ApiModelProperty(value = "结算方式", example = "现金") + private String settleMethod; + + /** + * 资金账户 + */ + @ApiModelProperty(value = "资金账户", example = "12345678901234567890") + private String bankAccountId; + + /** + * 金额 + */ + @ApiModelProperty(value = "金额", example = "10000") + private BigDecimal amt; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注", example = "备注1") + private String remark; + + /** + * 自定义1 + */ + @ApiModelProperty(value = "自定义1", example = "自定义1") + private String custom1; + + /** + * 自定义2 + */ + @ApiModelProperty(value = "自定义2", example = "自定义2") + private String custom2; + +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/PurOrderEntryVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/PurOrderEntryVO.java new file mode 100644 index 000000000..c422c6896 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/PurOrderEntryVO.java @@ -0,0 +1,168 @@ +package com.zeroone.star.project.vo.prepayment; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import java.math.BigDecimal; +import java.sql.Date; +import java.time.LocalDateTime; + +/** + *

+ * 采购订单明细 + *

+ * 参数涉及 PurOrder + entry两张表 + * @author Kong + * @since 2023-02-11 + */ +@Data +@ApiModel("采购明细对象") +public class PurOrderEntryVO{ +//TODO billDate需要单独传 + /** + * id + */ + @ApiModelProperty(value = "id",example = "1590710155294588930") + private String id; + + /** + * 单据号 + */ + @ApiModelProperty(value = "单据编号",example = "CGDD-221110-001") + private String billNo; + + /** + * 单据日期 + */ + @ApiModelProperty(value = "单据日期",example = "2022-01-14") + private Date billDate; + + /** + * 交货方式 + */ + @ApiModelProperty(value = "交货方式",example = "") + private String deliveryMethod; + + /** + * 交货地点 + */ + @ApiModelProperty(value = "交货地点",example = "") + private String deliveryPlace; + + /** + * 交货日期 + */ + @ApiModelProperty(value = "交货日期",example = "") + private LocalDateTime deliveryTime; + + /** + * 已关闭 + */ + @ApiModelProperty(value = "已关闭",example = "0") + private Integer isClosed; + + @ApiModelProperty(value = "操作部门",example = "A01A03") + private String opDept; + + /** + * 业务员 + */ + @ApiModelProperty(value = "业务员",example = "zhagnxiao") + private String operator; + + /** + * 付款方式 + */ + @ApiModelProperty(value = "付款方式",example = "") + private String paymentMethod; + + /** + * 预付款余额 + */ + @ApiModelProperty(value = "预付款余额",example = "0.00") + private BigDecimal prepaymentBal; + + /** + * 采购类型 + */ + @ApiModelProperty(value = "采购类型",example = "2") + private String purType; + + /** + * 供应商 + */ + @ApiModelProperty(value = "供应商",example = "1584950950470164481") + private String supplierId; + + /** + * 分录号 + */ + @ApiModelProperty(value = "分录号",example = "10") + private Integer entryNo; + + /** + * 源单分录号 + */ + @ApiModelProperty(value = "源单分录号",example = "10") + private String srcNo; + + /** + * 数量 + */ + @ApiModelProperty(value = "数量",example = "11") + private BigDecimal qty; + + /** + * 含税金额 + */ + @ApiModelProperty(value = "含税金额",example = "88000.00") + private BigDecimal amt; + + /** + * 已入库数量 + */ + @ApiModelProperty(value = "已入库数量",example = "11.000000") + private BigDecimal inQty; + + /** + * 已入库成本 + */ + @ApiModelProperty(value = "已入库成本",example = "88000.00") + private BigDecimal inCost; + + /** + * 结算金额 + */ + @ApiModelProperty(value = "结算金额",example = "88000.00") + private BigDecimal settleAmt; + + /** + * 已开票金额 + */ + @ApiModelProperty(value = "已开票金额",example = "88000.00") + private BigDecimal invoicedAmt; + + /** + * 发票类型 + */ + private String invoiceType; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注",example = "备注") + private String remark; + + /** + * 自定义1 + */ + @ApiModelProperty(value = "自定义1",example = "") + private String custom1; + + /** + * 自定义2 + */ + @ApiModelProperty(value = "自定义2",example = "") + private String custom2; + +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/PurOrderVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/PurOrderVO.java new file mode 100644 index 000000000..b3277174f --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/PurOrderVO.java @@ -0,0 +1,107 @@ +package com.zeroone.star.project.vo.prepayment; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + * @ClassName PurOrderVO + * @Description 采购订单对象 + * @Author HZP + * @Date 2023/2/12 16:06 + * @Version 1.0 + **/ +@Data +@ApiModel("采购订单对象") +public class PurOrderVO { + /** + * id + */ + @ApiModelProperty(value = "id",example = "1590710155252645889") + private String id; + + /** + * 单据编号 + */ + @ApiModelProperty(value = "单据编号",example = "CGDD-221110-001") + private String billNo; + + /** + * 单据日期 + */ + @ApiModelProperty(value = "单据日期",example = "2022-01-13") + private LocalDate billDate; + + /** + * 单据主题 + */ + @ApiModelProperty(value = "单据主题",example = "") + private String subject; + + /** + * 源单号 + */ + @ApiModelProperty(value = "源单号",example = "") + private String srcNo; + + /** + * 采购类型 + */ + @ApiModelProperty(value = "采购类型",example = "2") + private String purType; + /** + * 金额 + */ + @ApiModelProperty(value = "采购金额",example = "142000.00") + private BigDecimal amt; + /** + * 预付款余额 + */ + @ApiModelProperty(value = "预付余额",example = "0.00") + private BigDecimal prepaymentBal; + /** + * 结算金额 + */ + @ApiModelProperty(value = "结算金额",example = "142000.00") + private BigDecimal settleAmt; + /** + * 已结算金额 + */ + @ApiModelProperty(value = "已结算金额",example = "142000.00") + private BigDecimal settledAmt; + /** + * 付款方式 + */ + @ApiModelProperty(value = "付款方式",example = "") + private String paymentMethod; + + /** + * 结算方式 + */ + @ApiModelProperty(value = "结算方式",example = "") + private String settleMethod; + /** + * 交货日期 + */ + @ApiModelProperty(value = "交货日期",example = "") + private LocalDateTime deliveryTime; + /** + * 交货方式 + */ + @ApiModelProperty(value = "交货方式",example = "") + private String deliveryMethod; + /** + * 交货地点 + */ + @ApiModelProperty(value = "交货地点",example = "") + private String deliveryPlace; + /** + * 备注 + */ + @ApiModelProperty(value = "备注",example = "") + private String remark; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/ReqVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/ReqVO.java new file mode 100644 index 000000000..427442473 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/ReqVO.java @@ -0,0 +1,48 @@ +package com.zeroone.star.project.vo.prepayment; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDate; + +@Data +@ApiModel("采购预付申请单分录") +public class ReqVO { + @ApiModelProperty(value = "id",example = "1594317750844637186") + private String id; + + @ApiModelProperty(value = "单据编号",example = "CGYFSQ-221120-001") + private String billNo; + + @ApiModelProperty(value = "单据日期",example = "2023-02-11") + private LocalDate billDate; + + @ApiModelProperty(value = "单据主题",example = "无") + private String subject; + + @ApiModelProperty(value = "付款类型",example = "2011") + private Integer paymentType; + + @ApiModelProperty(value = "供应商",example = "1584950950470164481") + private String supplierId; + + @ApiModelProperty(value = "操作部门",example = "A01A03") + private String opDept; + + @ApiModelProperty(value = "业务员",example = "zhagnxiao") + private String operator; + + @ApiModelProperty(value = "申请金额",example = "90000") + private BigDecimal amt; + + @ApiModelProperty(value = "已付金额",example = "0") + private BigDecimal paidAmt; + + @ApiModelProperty(value = "备注",example = "无") + private String remark; + + @ApiModelProperty(value = "已关闭",example = "1") + private Integer isClosed; +} diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/SupplierVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/SupplierVO.java new file mode 100644 index 000000000..a896d1a8a --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/SupplierVO.java @@ -0,0 +1,36 @@ +package com.zeroone.star.project.vo.prepayment; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; + + +/** + * @Author: Kong + * @License: (C) Copyright 2005-2019, xxx Corporation Limited. + * @Contact: xxx@xxx.com + * @Date: 2023-02-11 21:20 + * @Version: 1.0 + * @Description: + */ +@Data +@AllArgsConstructor +@ApiModel("供应商显示对象") +public class SupplierVO { + /** + * id + */ + @ApiModelProperty(value = "id",example = "1623600860981665793") + private String id; + + /** + * 助记名 + */ + @ApiModelProperty(value = "助记名",example = "00001 公交卡") + private String aux_name; + + + + +} \ No newline at end of file diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/SysDepartVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/SysDepartVO.java new file mode 100644 index 000000000..5721452a6 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/SysDepartVO.java @@ -0,0 +1,41 @@ +package com.zeroone.star.project.vo.prepayment; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; + +/** + * @Author: Kong + * @License: (C) Copyright 2005-2019, xxx Corporation Limited. + * @Contact: xxx@xxx.com + * @Date: 2023-02-15 11:27 + * @Version: 1.0 + * @Description: 组织机构表 字典 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@ApiModel("组织机构显示对象") +public class SysDepartVO { + /** + * 机构编码 + */ + @ApiModelProperty(value = "机构编码",example = "A01A03") + private String value; + + /** + * 机构/部门名称 + */ + @ApiModelProperty(value = "机构/部门名称",example = "市场部") + private String text; + /** + * 机构/部门名称 + */ + @ApiModelProperty(value = "机构/部门名称",example = "市场部") + private String label; + /** + * 机构/部门名称 + */ + @ApiModelProperty(value = "机构/部门名称",example = "市场部") + private String title; +} \ No newline at end of file diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/SysUserVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/SysUserVO.java new file mode 100644 index 000000000..c2f034135 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/prepayment/SysUserVO.java @@ -0,0 +1,42 @@ +package com.zeroone.star.project.vo.prepayment; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * @Author: Kong + * @License: (C) Copyright 2005-2019, xxx Corporation Limited. + * @Contact: xxx@xxx.com + * @Date: 2023-02-15 11:19 + * @Version: 1.0 + * @Description: 用户表 字典 + */ +@Data +@AllArgsConstructor +@ApiModel("系统用户显示对象") +public class SysUserVO { + /** + * 登录账号 + */ + @ApiModelProperty(value = "用户名",example = "liyewu") + private String value; + + /** + * 真实姓名 + */ + @ApiModelProperty(value = "真实姓名",example = "李业武") + private String text; + /** + * 真实姓名 + */ + @ApiModelProperty(value = "真实姓名",example = "李业武") + private String label; + /** + * 真实姓名 + */ + @ApiModelProperty(value = "真实姓名",example = "李业武") + private String title; + +} \ No newline at end of file diff --git a/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/sample/SampleVO.java b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/sample/SampleVO.java new file mode 100644 index 000000000..f457f3f30 --- /dev/null +++ b/psi-java/psi-domain/src/main/java/com/zeroone/star/project/vo/sample/SampleVO.java @@ -0,0 +1,28 @@ +package com.zeroone.star.project.vo.sample; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

+ * 描述:示例视图对象 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Data +@ApiModel("示例显示对象") +public class SampleVO { + @ApiModelProperty(value = "编号", example = "1") + private Integer id; + @ApiModelProperty(value = "姓名", example = "张三") + private String name; + @ApiModelProperty(value = "性别", example = "男") + private String sex; + @ApiModelProperty(value = "年龄", example = "18") + private Integer age; +} diff --git a/psi-java/psi-gateway/Dockerfile b/psi-java/psi-gateway/Dockerfile new file mode 100644 index 000000000..05e85695f --- /dev/null +++ b/psi-java/psi-gateway/Dockerfile @@ -0,0 +1,4 @@ +FROM openjdk:8 +MAINTAINER 01star +ADD target/psi-gateway-1.0.0-SNAPSHOT.jar app.jar +CMD java -jar app.jar --spring.profiles.active=test --logging.file.path=/tmp/logs/spring-boot diff --git a/psi-java/psi-gateway/README.md b/psi-java/psi-gateway/README.md new file mode 100644 index 000000000..9308f17ab --- /dev/null +++ b/psi-java/psi-gateway/README.md @@ -0,0 +1,3 @@ +# 工程简介 + +服务网关,负责请求转发和鉴权功能,整合`Spring Security + OAuth2` diff --git a/psi-java/psi-gateway/pom.xml b/psi-java/psi-gateway/pom.xml new file mode 100644 index 000000000..8e801cf9c --- /dev/null +++ b/psi-java/psi-gateway/pom.xml @@ -0,0 +1,96 @@ + + + 4.0.0 + + com.zeroone.star + psi-java + ${revision} + ../pom.xml + + psi-gateway + + + + + com.zeroone.star + psi-common + + + + com.zeroone.star + psi-domain + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + org.springframework.cloud + spring-cloud-starter-gateway + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + org.springframework.boot + spring-boot-starter-webflux + + + org.springframework.security + spring-security-config + + + org.springframework.security + spring-security-oauth2-resource-server + + + org.springframework.security + spring-security-oauth2-client + + + org.springframework.security + spring-security-oauth2-jose + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + com.zeroone.star.gateway.GatewayApplication + + + + io.fabric8 + docker-maven-plugin + + + http://192.168.220.128:2375 + + + + 01star/${project.artifactId}:${project.version} + + ${project.basedir} + + + + + + + + + diff --git a/psi-java/psi-gateway/script/start.sh b/psi-java/psi-gateway/script/start.sh new file mode 100644 index 000000000..38f00d5d3 --- /dev/null +++ b/psi-java/psi-gateway/script/start.sh @@ -0,0 +1,11 @@ +#!bin/bash +app_name='psi-gateway' +docker stop ${app_name} +echo '----stop container----' +docker rm ${app_name} +echo '----rm container----' +docker run -p 10001:10001 --name ${app_name} \ +-v /etc/localtime:/etc/localtime \ +-v /home/app/${app_name}/logs:/tmp/logs \ +-d 01star/${app_name}:1.0.0-SNAPSHOT +echo '----start container----' diff --git a/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/GatewayApplication.java b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/GatewayApplication.java new file mode 100644 index 000000000..e2dd587ce --- /dev/null +++ b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/GatewayApplication.java @@ -0,0 +1,25 @@ +package com.zeroone.star.gateway; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; + +/** + *

+ * 描述:服务器启动入口 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@SpringBootApplication +@EnableDiscoveryClient +public class GatewayApplication { + + public static void main(String[] args) { + SpringApplication.run(GatewayApplication.class, args); + } + +} diff --git a/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/authorization/AuthorizationManager.java b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/authorization/AuthorizationManager.java new file mode 100644 index 000000000..23280c688 --- /dev/null +++ b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/authorization/AuthorizationManager.java @@ -0,0 +1,94 @@ +package com.zeroone.star.gateway.authorization; + +import cn.hutool.core.convert.Convert; +import com.zeroone.star.project.constant.AuthConstant; +import com.zeroone.star.project.constant.RedisConstant; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.security.authorization.AuthorizationDecision; +import org.springframework.security.authorization.ReactiveAuthorizationManager; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.web.server.authorization.AuthorizationContext; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * 描述:鉴权管理器,用于判断是否有资源的访问权限 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@RefreshScope +@Component +public class AuthorizationManager implements ReactiveAuthorizationManager { + @Resource + private RedisTemplate redisTemplate; + + @Value("${secure.openauthorization}") + private boolean isOpenAuthorization; + + /** + * 通过路径查询角色列表 + * @param path 路径名 + * @return 没有查询到返回空列表 + */ + private List queryRoleListByPath(String path) { + Object obj = redisTemplate.opsForHash().get(RedisConstant.RESOURCE_ROLES_MAP, path); + if (obj == null) { + return new ArrayList<>(); + } + List authorities = Convert.toList(String.class, obj); + authorities = authorities.stream().map(roleName -> roleName = AuthConstant.AUTHORITY_PREFIX + roleName).collect(Collectors.toList()); + return authorities; + } + + @Override + public Mono check(Mono mono, AuthorizationContext authorizationContext) { + //如果关闭鉴权功能,直接放行 + if (!isOpenAuthorization) { + return Mono.just(new AuthorizationDecision(true)); + } + + //1 从Redis中获取当前路径可访问角色列表 + String path = authorizationContext.getExchange().getRequest().getURI().getPath(); + List authorities = queryRoleListByPath(path); + // 没有查询到结果,尝试查找通配符 + if (authorities.isEmpty()) { + // 1.1 处理二级地址, 比如:请求地址为 "/fc/get",此时匹配 "/fc/**" + String[] arr = path.split("/"); + String currPath = "/" + arr[1] + "/**"; + authorities = queryRoleListByPath(currPath); + // 1.2 处理参数变量,比如请求地址为 "/fc/get/参数变量",此时匹配 "/fc/get/**" + if (authorities.isEmpty()) { + currPath = path.substring(0, path.lastIndexOf("/") + 1) + "**"; + authorities = queryRoleListByPath(currPath); + } + } + + //2 认证通过且角色匹配的用户可访问当前路径 + return mono + // 判断是否认证 + .filter(Authentication::isAuthenticated) + // 获取权限对象列表(即:角色列表) + .flatMapIterable(Authentication::getAuthorities) + // 遍历获取权限对象(即:获取单个角色名) + .map(GrantedAuthority::getAuthority) + // 查看当前路径中是否包对应权限(即:是否包含角色名) + .any(authorities::contains) + // 根据判断结果构建一个鉴权对象 + .map(AuthorizationDecision::new) + // 没有权限列表的情况,构建一个无权访问对象 + .defaultIfEmpty(new AuthorizationDecision(false)); + } +} diff --git a/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/config/RedisInit.java b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/config/RedisInit.java new file mode 100644 index 000000000..092445d89 --- /dev/null +++ b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/config/RedisInit.java @@ -0,0 +1,19 @@ +package com.zeroone.star.gateway.config; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +/** + *

+ * 描述:Redis初始化 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Configuration +@ComponentScan("com.zeroone.star.project.config.redis") +public class RedisInit { +} diff --git a/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/config/ResourceServerConfig.java b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/config/ResourceServerConfig.java new file mode 100644 index 000000000..e96bf736a --- /dev/null +++ b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/config/ResourceServerConfig.java @@ -0,0 +1,83 @@ +package com.zeroone.star.gateway.config; + +import cn.hutool.core.util.ArrayUtil; +import com.zeroone.star.gateway.authorization.AuthorizationManager; +import com.zeroone.star.gateway.filter.CorsFilter; +import com.zeroone.star.gateway.filter.WhitePathFilter; +import com.zeroone.star.gateway.handler.RestfulAccessDeniedHandler; +import com.zeroone.star.gateway.handler.RestfulAuthenticationEntryPoint; +import com.zeroone.star.project.constant.AuthConstant; +import lombok.AllArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.convert.converter.Converter; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; +import org.springframework.security.config.web.server.SecurityWebFiltersOrder; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; +import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter; +import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter; +import org.springframework.security.web.server.SecurityWebFilterChain; +import reactor.core.publisher.Mono; + +/** + *

+ * 描述:资源服务器配置 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@AllArgsConstructor +@Configuration +@EnableWebFluxSecurity +public class ResourceServerConfig { + private final AuthorizationManager authorizationManager; + private final WhitePathConfig whitePathConfig; + private final RestfulAccessDeniedHandler restfulAccessDeniedHandler; + private final RestfulAuthenticationEntryPoint restfulAuthenticationEntryPoint; + private final WhitePathFilter whitePathFilter; + private final CorsFilter corsFilter; + + @Bean + public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { + //跨域支持 + http.cors().and().csrf().disable(); + http.addFilterAt(corsFilter, SecurityWebFiltersOrder.SECURITY_CONTEXT_SERVER_WEB_EXCHANGE); + //jwt凭证转换器 + http.oauth2ResourceServer().jwt() + .jwtAuthenticationConverter(jwtAuthenticationConverter()); + //自定义处理JWT请求头过期或签名错误的结果 + http.oauth2ResourceServer().authenticationEntryPoint(restfulAuthenticationEntryPoint); + //对白名单路径,直接移除JWT请求头 + http.addFilterBefore(whitePathFilter, SecurityWebFiltersOrder.AUTHENTICATION); + http.authorizeExchange() + //白名单配置 + .pathMatchers(ArrayUtil.toArray(whitePathConfig.getUrls(), String.class)).permitAll() + //OPTIONS预检请求直接放行 + .pathMatchers(HttpMethod.OPTIONS).permitAll() + //鉴权管理器配置 + .anyExchange().access(authorizationManager) + .and().exceptionHandling() + //处理未授权 + .accessDeniedHandler(restfulAccessDeniedHandler) + //处理未认证 + .authenticationEntryPoint(restfulAuthenticationEntryPoint); + return http.build(); + } + + @Bean + public Converter> jwtAuthenticationConverter() { + JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter(); + jwtGrantedAuthoritiesConverter.setAuthorityPrefix(AuthConstant.AUTHORITY_PREFIX); + jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName(AuthConstant.AUTHORITY_CLAIM_NAME); + JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter(); + jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter); + return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter); + } +} diff --git a/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/config/WhitePathConfig.java b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/config/WhitePathConfig.java new file mode 100644 index 000000000..2a9b244c6 --- /dev/null +++ b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/config/WhitePathConfig.java @@ -0,0 +1,24 @@ +package com.zeroone.star.gateway.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + *

+ * 描述:网关白名单配置 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Data +@Component +@ConfigurationProperties(prefix="secure.white") +public class WhitePathConfig { + private List urls; +} diff --git a/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/filter/AuthGlobalFilter.java b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/filter/AuthGlobalFilter.java new file mode 100644 index 000000000..f0c7e5923 --- /dev/null +++ b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/filter/AuthGlobalFilter.java @@ -0,0 +1,55 @@ +package com.zeroone.star.gateway.filter; + +import cn.hutool.core.util.StrUtil; +import com.nimbusds.jose.JWSObject; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.core.Ordered; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import java.text.ParseException; + +/** + *

+ * 描述:将登录用户的JWT转化成用户信息的全局过滤器 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Component +@Slf4j +public class AuthGlobalFilter implements GlobalFilter, Ordered { + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + String token = exchange.getRequest().getHeaders().getFirst("Authorization"); + if (StrUtil.isEmpty(token)) { + return chain.filter(exchange); + } + //TODO:判断凭证是否注销需要在此补充逻辑 + try { + //从token中解析用户信息并设置到Header中去 + String realToken = token.replace("Bearer ", ""); + JWSObject jwsObject = JWSObject.parse(realToken); + String userStr = jwsObject.getPayload().toString(); + log.info("AuthGlobalFilter.filter() user:{}", userStr); + ServerHttpRequest request = exchange.getRequest().mutate().header("user", userStr).build(); + exchange = exchange.mutate().request(request).build(); + } catch (ParseException e) { + e.printStackTrace(); + } + return chain.filter(exchange); + } + + @Override + public int getOrder() { + return 0; + } +} + diff --git a/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/filter/CorsFilter.java b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/filter/CorsFilter.java new file mode 100644 index 000000000..39e17b24a --- /dev/null +++ b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/filter/CorsFilter.java @@ -0,0 +1,47 @@ +package com.zeroone.star.gateway.filter; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.stereotype.Component; +import org.springframework.web.cors.reactive.CorsUtils; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilter; +import org.springframework.web.server.WebFilterChain; +import reactor.core.publisher.Mono; + +/** + *

+ * 描述:跨域过滤器 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Component +public class CorsFilter implements WebFilter { + @SuppressWarnings("NullableProblems") + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + ServerHttpRequest request = exchange.getRequest(); + if (CorsUtils.isCorsRequest(request)) { + ServerHttpResponse response = exchange.getResponse(); + HttpHeaders headers = response.getHeaders(); + headers.set(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*"); + headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "*"); + headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "*"); + headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "false"); + headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*"); + headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "3600"); + if (request.getMethod() == HttpMethod.OPTIONS) { + response.setStatusCode(HttpStatus.OK); + return Mono.empty(); + } + } + return chain.filter(exchange); + } +} diff --git a/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/filter/WhitePathFilter.java b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/filter/WhitePathFilter.java new file mode 100644 index 000000000..913118401 --- /dev/null +++ b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/filter/WhitePathFilter.java @@ -0,0 +1,49 @@ +package com.zeroone.star.gateway.filter; + +import com.zeroone.star.gateway.config.WhitePathConfig; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.stereotype.Component; +import org.springframework.util.AntPathMatcher; +import org.springframework.util.PathMatcher; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilter; +import org.springframework.web.server.WebFilterChain; +import reactor.core.publisher.Mono; + +import javax.annotation.Resource; +import java.net.URI; +import java.util.List; + +/** + *

+ * 描述:白名单路径处理 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Component +public class WhitePathFilter implements WebFilter { + @Resource + WhitePathConfig whitePathConfig; + + @SuppressWarnings("NullableProblems") + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + ServerHttpRequest request = exchange.getRequest(); + URI uri = request.getURI(); + PathMatcher pathMatcher = new AntPathMatcher(); + //白名单路径移除JWT请求头 + List whiteUrls = whitePathConfig.getUrls(); + for (String whiteUrl : whiteUrls) { + if (pathMatcher.match(whiteUrl, uri.getPath())) { + request = exchange.getRequest().mutate().header("Authorization", "").build(); + exchange = exchange.mutate().request(request).build(); + return chain.filter(exchange); + } + } + return chain.filter(exchange); + } +} diff --git a/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/handler/CommonSender.java b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/handler/CommonSender.java new file mode 100644 index 000000000..97baaba8f --- /dev/null +++ b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/handler/CommonSender.java @@ -0,0 +1,42 @@ +package com.zeroone.star.gateway.handler; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.zeroone.star.project.vo.JsonVO; +import com.zeroone.star.project.vo.ResultStatus; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import java.nio.charset.StandardCharsets; + +/** + *

+ * 描述:通用消息发送工具类 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +class CommonSender { + static Mono sender(ServerWebExchange exchange, ResultStatus resultStatus, String data){ + ServerHttpResponse response = exchange.getResponse(); + response.setStatusCode(HttpStatus.OK); + response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + ObjectMapper mapper = new ObjectMapper(); + String body = ""; + try { + body = mapper.writeValueAsString(JsonVO.create(data, resultStatus)); + } catch (JsonProcessingException e1) { + e1.printStackTrace(); + } + DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(StandardCharsets.UTF_8)); + return response.writeWith(Mono.just(buffer)); + } +} diff --git a/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/handler/RestfulAccessDeniedHandler.java b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/handler/RestfulAccessDeniedHandler.java new file mode 100644 index 000000000..2c312f731 --- /dev/null +++ b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/handler/RestfulAccessDeniedHandler.java @@ -0,0 +1,26 @@ +package com.zeroone.star.gateway.handler; + +import com.zeroone.star.project.vo.ResultStatus; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +/** + *

+ * 描述:没有权限访问时下发消息 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Component +public class RestfulAccessDeniedHandler implements ServerAccessDeniedHandler { + @Override + public Mono handle(ServerWebExchange exchange, AccessDeniedException denied) { + return CommonSender.sender(exchange, ResultStatus.FORBIDDEN, denied.getMessage()); + } +} diff --git a/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/handler/RestfulAuthenticationEntryPoint.java b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/handler/RestfulAuthenticationEntryPoint.java new file mode 100644 index 000000000..ab0aa680e --- /dev/null +++ b/psi-java/psi-gateway/src/main/java/com/zeroone/star/gateway/handler/RestfulAuthenticationEntryPoint.java @@ -0,0 +1,26 @@ +package com.zeroone.star.gateway.handler; + +import com.zeroone.star.project.vo.ResultStatus; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.server.ServerAuthenticationEntryPoint; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +/** + *

+ * 描述:没有登录或token过期时下发消息 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Component +public class RestfulAuthenticationEntryPoint implements ServerAuthenticationEntryPoint { + @Override + public Mono commence(ServerWebExchange exchange, AuthenticationException e) { + return CommonSender.sender(exchange, ResultStatus.UNAUTHORIZED, e.getMessage()); + } +} diff --git a/psi-java/psi-gateway/src/main/resources/application.yaml b/psi-java/psi-gateway/src/main/resources/application.yaml new file mode 100644 index 000000000..889c7b5af --- /dev/null +++ b/psi-java/psi-gateway/src/main/resources/application.yaml @@ -0,0 +1,51 @@ +server: + port: ${sp.gateway} +spring: + application: + name: ${sn.gateway} + security: + oauth2: + resourceserver: + jwt: + # 公钥文件配置 + public-key-location: classpath:public.pem + cloud: + gateway: + discovery: + locator: + # 开启从注册中心动态创建路由的功能 + enabled: true + # 注意:这里的路径配置需要移植到nacos配置中心system.yaml中 + routes: + - id: oauth2-auth-route + uri: lb://${sn.auth} + predicates: + - Path=/auth/** + filters: + - StripPrefix=1 + - id: login-route + uri: lb://${sn.login} + predicates: + - Path=/login/** + - id: sample-route + uri: lb://${sn.sample} + predicates: + - Path=/sample/** + - id: cpp-route + uri: lb://${sn.cpp} + predicates: + - Path=/cpp/** + - id: cpp-route + uri: lb://${sn.payment} + predicates: + - Path=/payment/** +secure: + # 配置是否开启鉴权 + openauthorization: true + # 配置白名单路径 + white: + urls: + - "/actuator/**" + - "/auth/oauth/token" + - "/login/auth-login" + - "/login/refresh-token" diff --git a/psi-java/psi-login/Dockerfile b/psi-java/psi-login/Dockerfile new file mode 100644 index 000000000..ed863780b --- /dev/null +++ b/psi-java/psi-login/Dockerfile @@ -0,0 +1,4 @@ +FROM openjdk:8 +MAINTAINER 01star +ADD target/psi-login-1.0.0-SNAPSHOT.jar app.jar +CMD java -jar app.jar --spring.profiles.active=test --logging.file.path=/tmp/logs/spring-boot diff --git a/psi-java/psi-login/README.md b/psi-java/psi-login/README.md new file mode 100644 index 000000000..d5c50eb2a --- /dev/null +++ b/psi-java/psi-login/README.md @@ -0,0 +1,9 @@ +# 工程简介 + +登录模块,用于处理登录认证以及用户登录信息获取 + +# 延伸阅读 + +## `sentinel`配置参考 + +https://sentinelguard.io/zh-cn/docs/basic-api-resource-rule.html diff --git a/psi-java/psi-login/pom.xml b/psi-java/psi-login/pom.xml new file mode 100644 index 000000000..892636144 --- /dev/null +++ b/psi-java/psi-login/pom.xml @@ -0,0 +1,93 @@ + + + 4.0.0 + + com.zeroone.star + psi-java + ${revision} + ../pom.xml + + psi-login + + + + org.springframework.boot + spring-boot-starter-web + + + + com.zeroone.star + psi-apis + + + + com.zeroone.star + psi-common + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + + + com.baomidou + mybatis-plus-boot-starter + + + + com.alibaba + druid-spring-boot-starter + + + + mysql + mysql-connector-java + + + + + + org.springframework.boot + spring-boot-maven-plugin + + com.zeroone.star.login.LoginApplication + + + + io.fabric8 + docker-maven-plugin + + + http://192.168.220.128:2375 + + + + 01star/${project.artifactId}:${project.version} + + ${project.basedir} + + + + + + + + diff --git a/psi-java/psi-login/script/start.sh b/psi-java/psi-login/script/start.sh new file mode 100644 index 000000000..4f1fe3f3a --- /dev/null +++ b/psi-java/psi-login/script/start.sh @@ -0,0 +1,11 @@ +#!bin/bash +app_name='psi-login' +docker stop ${app_name} +echo '----stop container----' +docker rm ${app_name} +echo '----rm container----' +docker run -p 10200:10200 --name ${app_name} \ +-v /etc/localtime:/etc/localtime \ +-v /home/app/${app_name}/logs:/tmp/logs \ +-d 01star/${app_name}:1.0.0-SNAPSHOT +echo '----start container----' diff --git a/psi-java/psi-login/src/main/java/com/zeroone/star/login/LoginApplication.java b/psi-java/psi-login/src/main/java/com/zeroone/star/login/LoginApplication.java new file mode 100644 index 000000000..a9b110495 --- /dev/null +++ b/psi-java/psi-login/src/main/java/com/zeroone/star/login/LoginApplication.java @@ -0,0 +1,26 @@ +package com.zeroone.star.login; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; + +/** + *

+ * 描述:服务器启动入口 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * @author 阿伟学长 + * @version 1.0.0 + */ +@SpringBootApplication +@EnableDiscoveryClient +@EnableFeignClients +public class LoginApplication { + + public static void main(String[] args) { + SpringApplication.run(LoginApplication.class, args); + } + +} diff --git a/psi-java/psi-login/src/main/java/com/zeroone/star/login/config/ComponentInit.java b/psi-java/psi-login/src/main/java/com/zeroone/star/login/config/ComponentInit.java new file mode 100644 index 000000000..4a6c5d643 --- /dev/null +++ b/psi-java/psi-login/src/main/java/com/zeroone/star/login/config/ComponentInit.java @@ -0,0 +1,21 @@ +package com.zeroone.star.login.config; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +/** + *

+ * 描述:初始化自定义组件 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * @author 阿伟学长 + * @version 1.0.0 + */ +@Configuration +@ComponentScan({ + "com.zeroone.star.project.components.jwt", + "com.zeroone.star.project.components.user" +}) +public class ComponentInit { +} diff --git a/psi-java/psi-login/src/main/java/com/zeroone/star/login/config/MyBaitsInit.java b/psi-java/psi-login/src/main/java/com/zeroone/star/login/config/MyBaitsInit.java new file mode 100644 index 000000000..700b2aade --- /dev/null +++ b/psi-java/psi-login/src/main/java/com/zeroone/star/login/config/MyBaitsInit.java @@ -0,0 +1,18 @@ +package com.zeroone.star.login.config; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +/** + *

+ * 描述:初始化mybatis + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * @author 阿伟学长 + * @version 1.0.0 + */ +@Configuration +@ComponentScan("com.zeroone.star.project.config.mybatis") +public class MyBaitsInit { +} diff --git a/psi-java/psi-login/src/main/java/com/zeroone/star/login/config/SwaggerConfig.java b/psi-java/psi-login/src/main/java/com/zeroone/star/login/config/SwaggerConfig.java new file mode 100644 index 000000000..49cb1a264 --- /dev/null +++ b/psi-java/psi-login/src/main/java/com/zeroone/star/login/config/SwaggerConfig.java @@ -0,0 +1,26 @@ +package com.zeroone.star.login.config; + +import com.zeroone.star.project.config.swagger.SwaggerCore; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc; + +/** + *

+ * 描述:Swagger配置 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * @author 阿伟学长 + * @version 1.0.0 + */ +@Configuration +@EnableSwagger2WebMvc +public class SwaggerConfig { + @Bean + Docket loginApi() { + return SwaggerCore.defaultDocketBuilder("登录模块", "com.zeroone.star.login.controller", "login"); + } +} + diff --git a/psi-java/psi-login/src/main/java/com/zeroone/star/login/config/TreeConfig.java b/psi-java/psi-login/src/main/java/com/zeroone/star/login/config/TreeConfig.java new file mode 100644 index 000000000..915e29038 --- /dev/null +++ b/psi-java/psi-login/src/main/java/com/zeroone/star/login/config/TreeConfig.java @@ -0,0 +1,37 @@ +package com.zeroone.star.login.config; + +import com.zeroone.star.project.utils.tree.NodeMapper; +import com.zeroone.star.project.utils.tree.TreeNode; +import com.zeroone.star.project.vo.login.MenuTreeVO; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + *

+ * 描述:实现数据转换为树形节点数据匹配接口 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * @author 阿伟学长 + * @version 1.0.0 + */ +@Configuration +public class TreeConfig { + @Bean + public NodeMapper createMenuNodeMapper() { + return menu -> { + TreeNode treeNode = new TreeNode<>(); + treeNode.setId(menu.getId().toString()); + treeNode.setText(menu.getName()); + if (menu.getParentMenuId() == null) { + treeNode.setPid(null); + } else { + treeNode.setPid(menu.getParentMenuId().toString()); + } + treeNode.setRaw(menu); + treeNode.setHref(menu.getPath()); + treeNode.setIcon(menu.getIcon()); + return treeNode; + }; + } +} diff --git a/psi-java/psi-login/src/main/java/com/zeroone/star/login/controller/LoginController.java b/psi-java/psi-login/src/main/java/com/zeroone/star/login/controller/LoginController.java new file mode 100644 index 000000000..a7a732bd5 --- /dev/null +++ b/psi-java/psi-login/src/main/java/com/zeroone/star/login/controller/LoginController.java @@ -0,0 +1,134 @@ +package com.zeroone.star.login.controller; + +import cn.hutool.core.bean.BeanUtil; +import com.zeroone.star.login.service.IMenuService; +import com.zeroone.star.login.service.OauthService; +import com.zeroone.star.project.components.user.UserDTO; +import com.zeroone.star.project.components.user.UserHolder; +import com.zeroone.star.project.constant.AuthConstant; +import com.zeroone.star.project.dto.login.LoginDTO; +import com.zeroone.star.project.dto.login.Oauth2TokenDTO; +import com.zeroone.star.project.login.LoginApis; +import com.zeroone.star.project.utils.tree.NodeMapper; +import com.zeroone.star.project.utils.tree.TreeNode; +import com.zeroone.star.project.utils.tree.TreeUtils; +import com.zeroone.star.project.vo.JsonVO; +import com.zeroone.star.project.vo.ResultStatus; +import com.zeroone.star.project.vo.TreeNodeVO; +import com.zeroone.star.project.vo.login.LoginVO; +import com.zeroone.star.project.vo.login.MenuTreeVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + *

+ * 描述:登录接口 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * @author 阿伟学长 + * @version 1.0.0 + */ +@RestController +@RequestMapping("login") +@Api(tags = "login") +public class LoginController implements LoginApis { + @Resource + OauthService oAuthService; + @Resource + UserHolder userHolder; + + @ApiOperation(value = "授权登录") + @PostMapping("auth-login") + @Override + public JsonVO authLogin(LoginDTO loginDTO) { + // TODO:未实现验证码验证 + // 账号密码认证 + Map params = new HashMap<>(5); + params.put("grant_type", "password"); + params.put("client_id", loginDTO.getClientId()); + params.put("client_secret", AuthConstant.CLIENT_PASSWORD); + params.put("username", loginDTO.getUsername()); + params.put("password", loginDTO.getPassword()); + return oAuthService.postAccessToken(params); + // TODO:未实现认证成功后如何实现注销凭证(如记录凭证到内存数据库) + } + + @ApiOperation(value = "刷新登录") + @PostMapping("refresh-token") + @Override + public JsonVO refreshToken(Oauth2TokenDTO oauth2TokenDTO) { + //TODO:未实现注销凭证验证 + Map params = new HashMap<>(4); + params.put("grant_type", "refresh_token"); + params.put("client_id", oauth2TokenDTO.getClientId()); + params.put("client_secret", AuthConstant.CLIENT_PASSWORD); + params.put("refresh_token", oauth2TokenDTO.getRefreshToken()); + return oAuthService.postAccessToken(params); + } + + @ApiOperation(value = "获取当前用户") + @GetMapping("current-user") + @Override + public JsonVO getCurrUser() { + UserDTO currentUser; + try { + currentUser = userHolder.getCurrentUser(); + } catch (Exception e) { + return JsonVO.create(null, ResultStatus.FAIL.getCode(), e.getMessage()); + } + if (currentUser == null) { + return JsonVO.fail(null); + } else { + //TODO:这里需要根据业务逻辑接口,重新实现 + LoginVO vo = new LoginVO(); + BeanUtil.copyProperties(currentUser, vo); + return JsonVO.success(vo); + } + } + + @ApiOperation(value = "退出登录") + @GetMapping("logout") + @Override + public JsonVO logout() { + // TODO:登出逻辑,需要配合登录逻辑实现 + return null; + } + + @Resource + IMenuService menuService; + + @Resource + NodeMapper nodeMapper; + + @ApiOperation(value = "获取菜单") + @GetMapping("get-menus") + @Override + public JsonVO>> getMenus() throws Exception { + // TODO:未实现根据实际数据库设计业务逻辑,下面逻辑属于示例逻辑 + //1 获取当前用户 + UserDTO currentUser = userHolder.getCurrentUser(); + //2 获取当前用户拥有的菜单 + List menus = menuService.listMenuByRoleName(currentUser.getRoles()); + //3 转换树形结构 + List> treeNodes = TreeUtils.listToTree(menus, nodeMapper); + //4 转换成VO数据 + List> tree = new ArrayList<>(); + for (TreeNode sub : treeNodes) { + TreeNodeVO one = new TreeNodeVO<>(); + BeanUtil.copyProperties(sub, one); + tree.add(one); + } + return JsonVO.success(tree); + } +} diff --git a/psi-java/psi-login/src/main/java/com/zeroone/star/login/entity/Menu.java b/psi-java/psi-login/src/main/java/com/zeroone/star/login/entity/Menu.java new file mode 100644 index 000000000..01a700695 --- /dev/null +++ b/psi-java/psi-login/src/main/java/com/zeroone/star/login/entity/Menu.java @@ -0,0 +1,74 @@ +package com.zeroone.star.login.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +/** + *

+ * 菜单 + *

+ * @author 阿伟 + */ +@Getter +@Setter +public class Menu implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 菜单编号 + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 菜单名 + */ + private String name; + + /** + * 链接地址 + */ + private String linkUrl; + + /** + * 路由地址 + */ + private String path; + + /** + * 显示优先级别 + */ + private Integer priority; + + /** + * 图标 + */ + private String icon; + + /** + * 描述 + */ + private String description; + + /** + * 父级菜单编号 + */ + private Integer parentMenuId; + + /** + * 层次级别 + */ + private Integer level; + + /** + * 是否启用 0 禁用 1 启用 + */ + private Integer isEnable; + + +} diff --git a/psi-java/psi-login/src/main/java/com/zeroone/star/login/fallback/OauthServiceFallbackFactory.java b/psi-java/psi-login/src/main/java/com/zeroone/star/login/fallback/OauthServiceFallbackFactory.java new file mode 100644 index 000000000..38e7384c2 --- /dev/null +++ b/psi-java/psi-login/src/main/java/com/zeroone/star/login/fallback/OauthServiceFallbackFactory.java @@ -0,0 +1,22 @@ +package com.zeroone.star.login.fallback; + +import com.zeroone.star.login.service.impl.OauthServiceImpl; +import feign.hystrix.FallbackFactory; +import org.springframework.stereotype.Component; + +/** + *

+ * 描述:授权服务异常回调工厂 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * @author 阿伟学长 + * @version 1.0.0 + */ +@Component +public class OauthServiceFallbackFactory implements FallbackFactory { + @Override + public OauthServiceImpl create(Throwable throwable) { + return new OauthServiceImpl(throwable); + } +} diff --git a/psi-java/psi-login/src/main/java/com/zeroone/star/login/mapper/MenuMapper.java b/psi-java/psi-login/src/main/java/com/zeroone/star/login/mapper/MenuMapper.java new file mode 100644 index 000000000..eb406ead0 --- /dev/null +++ b/psi-java/psi-login/src/main/java/com/zeroone/star/login/mapper/MenuMapper.java @@ -0,0 +1,23 @@ +package com.zeroone.star.login.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.zeroone.star.login.entity.Menu; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + *

+ * 菜单 Mapper 接口 + *

+ * @author 阿伟 + */ +@Mapper +public interface MenuMapper extends BaseMapper { + /** + * 通过角色名获取对应的菜单资源 + * @param roleName 角色名 + * @return 返回菜单列表 + */ + List selectByRoleName(String roleName); +} diff --git a/psi-java/psi-login/src/main/java/com/zeroone/star/login/service/IMenuService.java b/psi-java/psi-login/src/main/java/com/zeroone/star/login/service/IMenuService.java new file mode 100644 index 000000000..1b7e0db1f --- /dev/null +++ b/psi-java/psi-login/src/main/java/com/zeroone/star/login/service/IMenuService.java @@ -0,0 +1,22 @@ +package com.zeroone.star.login.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.zeroone.star.login.entity.Menu; +import com.zeroone.star.project.vo.login.MenuTreeVO; + +import java.util.List; + +/** + *

+ * 菜单 服务类 + *

+ * @author 阿伟 + */ +public interface IMenuService extends IService { + /** + * 通过角色名称获取,菜单资源 + * @param roleNames 角色名称 + * @return 返回菜单列表 + */ + List listMenuByRoleName(List roleNames); +} diff --git a/psi-java/psi-login/src/main/java/com/zeroone/star/login/service/OauthService.java b/psi-java/psi-login/src/main/java/com/zeroone/star/login/service/OauthService.java new file mode 100644 index 000000000..6dab792ac --- /dev/null +++ b/psi-java/psi-login/src/main/java/com/zeroone/star/login/service/OauthService.java @@ -0,0 +1,30 @@ +package com.zeroone.star.login.service; + +import com.zeroone.star.login.fallback.OauthServiceFallbackFactory; +import com.zeroone.star.project.dto.login.Oauth2TokenDTO; +import com.zeroone.star.project.vo.JsonVO; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.Map; + +/** + *

+ * 描述:授权声明式服务接口 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * @author 阿伟学长 + * @version 1.0.0 + */ +@FeignClient(value = "${sn.auth}", fallbackFactory = OauthServiceFallbackFactory.class) +public interface OauthService { + /** + * 声明式调用授权服务 + * @param parameters 参数列表 + * @return 授权数据 + */ + @PostMapping("/oauth/token") + JsonVO postAccessToken(@RequestParam Map parameters); +} diff --git a/psi-java/psi-login/src/main/java/com/zeroone/star/login/service/impl/MenuServiceImpl.java b/psi-java/psi-login/src/main/java/com/zeroone/star/login/service/impl/MenuServiceImpl.java new file mode 100644 index 000000000..acbb11c55 --- /dev/null +++ b/psi-java/psi-login/src/main/java/com/zeroone/star/login/service/impl/MenuServiceImpl.java @@ -0,0 +1,40 @@ +package com.zeroone.star.login.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.zeroone.star.login.entity.Menu; +import com.zeroone.star.login.mapper.MenuMapper; +import com.zeroone.star.login.service.IMenuService; +import com.zeroone.star.project.vo.login.MenuTreeVO; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + *

+ * 菜单 服务实现类 + *

+ * @author 阿伟 + */ +@Service +public class MenuServiceImpl extends ServiceImpl implements IMenuService { + + @Override + public List listMenuByRoleName(List roleNames) { + //1 定义一个Menus数组用于存放Menus对象 + List result = new ArrayList<>(); + //2 遍历获取角色获取所有的菜单列表 + roleNames.forEach(roleName -> { + //通过角色名获取菜单列表 + List tMenus = baseMapper.selectByRoleName(roleName); + tMenus.forEach(menu -> { + MenuTreeVO vo = new MenuTreeVO(); + BeanUtils.copyProperties(menu, vo); + result.add(vo); + }); + }); + //返回查询结果 + return result; + } +} diff --git a/psi-java/psi-login/src/main/java/com/zeroone/star/login/service/impl/OauthServiceImpl.java b/psi-java/psi-login/src/main/java/com/zeroone/star/login/service/impl/OauthServiceImpl.java new file mode 100644 index 000000000..8a418f7e6 --- /dev/null +++ b/psi-java/psi-login/src/main/java/com/zeroone/star/login/service/impl/OauthServiceImpl.java @@ -0,0 +1,37 @@ +package com.zeroone.star.login.service.impl; + +import com.zeroone.star.login.service.OauthService; +import com.zeroone.star.project.dto.login.Oauth2TokenDTO; +import com.zeroone.star.project.vo.JsonVO; +import lombok.AllArgsConstructor; + +import java.util.Map; + +/** + *

+ * 描述:授权服务降级实现 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * @author 阿伟学长 + * @version 1.0.0 + */ +@AllArgsConstructor +public class OauthServiceImpl implements OauthService { + private Throwable throwable; + + private void setMessage(JsonVO vo) { + if (throwable.getMessage() != null) { + vo.setMessage(throwable.getMessage()); + } else { + vo.setMessage(throwable.getClass().toGenericString()); + } + } + + @Override + public JsonVO postAccessToken(Map parameters) { + JsonVO vo = JsonVO.fail(null); + setMessage(vo); + return vo; + } +} diff --git a/psi-java/psi-login/src/main/resources/application.yaml b/psi-java/psi-login/src/main/resources/application.yaml new file mode 100644 index 000000000..866c8a396 --- /dev/null +++ b/psi-java/psi-login/src/main/resources/application.yaml @@ -0,0 +1,25 @@ +server: + port: ${sp.login} +spring: + application: + name: ${sn.login} + cloud: + sentinel: + transport: + # 控制台地址 + dashboard: ${sentinel.dashboard} + port: 8720 + eager: true + +# 开启sentinel声明式服务熔断 +feign: + sentinel: + enabled: true + +# 负载均衡配置 +ribbon: + MaxAutoRetries: 0 #(默认1次 不包括第一次)最大重试次数,当注册中心中可以找到服务,但是服务连不上时将会重试,如果注册中心中找不到服务则直接走断路器 + MaxAutoRetriesNextServer: 1 #(默认0次 不包括第一次)切换实例的重试次数 + OkToRetryOnAllOperations: false #对所有操作请求都进行重试,如果是get则可以,如果是post,put等操作没有实现幂等的情况下是很危险的,所以设置为false + ConnectTimeout: 5000 #(默认1s,即1000)请求连接的超时时间 + ReadTimeout: 5000 #(默认1s,即1000)请求处理的超时时间 diff --git a/psi-java/psi-login/src/main/resources/mapper/MenuMapper.xml b/psi-java/psi-login/src/main/resources/mapper/MenuMapper.xml new file mode 100644 index 000000000..cfdb1f524 --- /dev/null +++ b/psi-java/psi-login/src/main/resources/mapper/MenuMapper.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + diff --git a/psi-java/psi-oauth2/Dockerfile b/psi-java/psi-oauth2/Dockerfile new file mode 100644 index 000000000..5ca181408 --- /dev/null +++ b/psi-java/psi-oauth2/Dockerfile @@ -0,0 +1,4 @@ +FROM openjdk:8 +MAINTAINER 01star +ADD target/psi-oauth2-1.0.0-SNAPSHOT.jar app.jar +CMD java -jar app.jar --spring.profiles.active=test --logging.file.path=/tmp/logs/spring-boot diff --git a/psi-java/psi-oauth2/README.md b/psi-java/psi-oauth2/README.md new file mode 100644 index 000000000..a90afe153 --- /dev/null +++ b/psi-java/psi-oauth2/README.md @@ -0,0 +1,237 @@ +# 工程简介 + +`OAuth2`认证服务,负责对登录用户进行认证,整合`Spring Security + OAuth2` + +# 延伸阅读 + +## 一、`RSA`证书 + +### 1 生成证书 + +首先通过终端进入到`resources`目录,然后执行证书生成命令。 + +```sh +keytool -genkeypair -alias 01star -keyalg RSA -keypass 123456 -keystore jwt.jks -storepass 123456 -validity 3650 +keytool -importkeystore -srckeystore jwt.jks -destkeystore jwt.jks -deststoretype pkcs12 +``` + +> **参数帮助说明** +> +> ```sh +> keytool密钥和证书管理工具 +> 命令: +> -certreq 生成证书请求 +> -changealias 更改条目的别名 +> -delete 删除条目 +> -exportcert 导出证书 +> -genkeypair 生成密钥对 +> -genseckey 生成密钥 +> -gencert 根据证书请求生成证书 +> -importcert 导入证书或证书链 +> -importpass 导入口令 +> -importkeystore 从其他密钥库导入一个或所有条目 +> -keypasswd 更改条目的密钥口令 +> -list 列出密钥库中的条目 +> -printcert 打印证书内容 +> -printcertreq 打印证书请求的内容 +> -printcrl 打印 CRL 文件的内容 +> -storepasswd 更改密钥库的存储口令 +> 使用 "keytool -command_name -help" 获取 command_name 的用法 +> +> keytool -genkeypair [OPTION]... +> 生成密钥对选项: +> -alias 要处理的条目的别名 +> -keyalg 密钥算法名称 +> -keysize 密钥位大小 +> -sigalg 签名算法名称 +> -destalias 目标别名 +> -dname 唯一判别名 +> -startdate 证书有效期开始日期/时间 +> -ext X.509 扩展 +> -validity 有效天数 +> -keypass 密钥口令 +> -keystore 密钥库名称 +> -storepass 密钥库口令 +> -storetype 密钥库类型 +> -providername 提供方名称 +> -providerclass 提供方类名 +> -providerarg 提供方参数 +> -providerpath 提供方类路径 +> -v 详细输出 +> -protected 通过受保护的机制的口令使用 +> "keytool -help" 获取所有可用命令 +> ``` + +### 2 提取公钥 + +通过`openssl`可以提取PUBLIC KEY格式,windows下需要安装 `openssl` + +http://slproweb.com/products/Win32OpenSSL.html + +```sh +keytool -list -rfc --keystore jwt.jks | openssl x509 -inform pem -pubkey +``` + +提取结果 + +``` +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2CUog6kdKUOlOtdOHFcs +ts0KHt5eg8UPF6Yj/jte7jgxOWsYB571rdMzTDIYo1UIaYVOJcd3oio9QlebUZD7 +O4GL8oJmj9rNCVk60xfx3vhYISzdHbwQhUUgx+YDmDr5UJV/D/uhCdFKziTUBMjD +otSQXvCsbWIMGGEFbPXKe9VRmgqtjdNfWvjMa7spQwiy0gj7GeOUiIttkVZna6qF +FZRSRAxp3NJ9ELbcW7Kd9u5IFzrvxXNiYPOtIiw+zqJTYsSXUJTI7YQAXy9zqGtT +7QUFUjxUf+7b1DELpGZPmwGd5Jzj+zfTNsS3DRNuPQJPkPbpUo1qCsU55sXgcNrf +zwIDAQAB +-----END PUBLIC KEY----- + +-----BEGIN CERTIFICATE----- +MIIDYzCCAkugAwIBAgIEZ/7xkDANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQGEwJj +bjEQMA4GA1UECBMHc2ljaHVhbjEQMA4GA1UEBxMHY2hlbmdkdTEPMA0GA1UEChMG +MDFzdGFyMQ8wDQYDVQQLEwYwMXN0YXIxDTALBgNVBAMTBGF3ZWkwHhcNMjExMjI5 +MDE0NDIzWhcNMzExMjI3MDE0NDIzWjBiMQswCQYDVQQGEwJjbjEQMA4GA1UECBMH +c2ljaHVhbjEQMA4GA1UEBxMHY2hlbmdkdTEPMA0GA1UEChMGMDFzdGFyMQ8wDQYD +VQQLEwYwMXN0YXIxDTALBgNVBAMTBGF3ZWkwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDYJSiDqR0pQ6U6104cVyy2zQoe3l6DxQ8XpiP+O17uODE5axgH +nvWt0zNMMhijVQhphU4lx3eiKj1CV5tRkPs7gYvygmaP2s0JWTrTF/He+FghLN0d +vBCFRSDH5gOYOvlQlX8P+6EJ0UrOJNQEyMOi1JBe8KxtYgwYYQVs9cp71VGaCq2N +019a+MxruylDCLLSCPsZ45SIi22RVmdrqoUVlFJEDGnc0n0Qttxbsp327kgXOu/F +c2Jg860iLD7OolNixJdQlMjthABfL3Ooa1PtBQVSPFR/7tvUMQukZk+bAZ3knOP7 +N9M2xLcNE249Ak+Q9ulSjWoKxTnmxeBw2t/PAgMBAAGjITAfMB0GA1UdDgQWBBRo +czTTqtgEoqi6ryQAif2qJFl2lDANBgkqhkiG9w0BAQsFAAOCAQEAqhAO1nB2UHoH +11stZ5uw72vH+vGmCoSP/bXQwKvBxcWEdpjw6xsZSGyojheVUCA0yfOy3KY8gZkl +jjTdpH0MtCKBASdjCHfmmvzq+DOXI2Xlq7eNvNU2AwKolwByVUEUX7bcIrRshXE0 +Mzcgwb4YigSgpnQ5dm+nWq6pDcBDQ1Xi94bSNtaFct08jHEStv9LVP1+icrzXBGr +Ji2o4ODDn6PCbxqmwq5b3y1vl/vcU50xP+yjrTqT6nkJLTxMvaYc/s+6X3QYz4SB +QY2fIHOY6vHVNnAyRHFdOoFFXkbHzSDeWZ72Jf23gCaBISRrYaOGsWtmijgf9idH +snHq0k6a1A== +-----END CERTIFICATE----- +``` + +### 3 提取私钥 + +需要把证书先转成`pfx`格式 + +```sh +keytool -v -importkeystore -srckeystore jwt.jks -srcstoretype jks -srcstorepass 123456 -destkeystore jwt.pfx -deststoretype pkcs12 -deststorepass 123456 -destkeypass 123456 +``` + +提取私钥 + +```sh +#显示在屏幕上 +openssl pkcs12 -in jwt.pfx -nocerts -nodes + +#输出到文件 +openssl pkcs12 -in jwt.pfx -nocerts -nodes -out jwt.key +``` + +提取格式如 + +``` +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDYJSiDqR0pQ6U6 +104cVyy2zQoe3l6DxQ8XpiP+O17uODE5axgHnvWt0zNMMhijVQhphU4lx3eiKj1C +V5tRkPs7gYvygmaP2s0JWTrTF/He+FghLN0dvBCFRSDH5gOYOvlQlX8P+6EJ0UrO +JNQEyMOi1JBe8KxtYgwYYQVs9cp71VGaCq2N019a+MxruylDCLLSCPsZ45SIi22R +VmdrqoUVlFJEDGnc0n0Qttxbsp327kgXOu/Fc2Jg860iLD7OolNixJdQlMjthABf +L3Ooa1PtBQVSPFR/7tvUMQukZk+bAZ3knOP7N9M2xLcNE249Ak+Q9ulSjWoKxTnm +xeBw2t/PAgMBAAECggEADHXH6h8boT9XDRdQV23nE/qp9LGY/Tuk7RYUyRkfFdiD +be3wiq/tNcIRGPliVjgWrg6TPLZM/To2IdbvCzqyYPHM4YQG6ZARddKBA55DwTjL +y83MSWSIB0a+5wcpeeMccDrOAlvdIrW//DY/Sq9QJ9jdIbv6FKwsSlN9fpSEwbKl +TDqwZJCyc5KBKq7r6NixO/ksATi1uaQUfJT5b4sakGKUN5I7MwAjST4em7Ze8VVc +HGt1ClaTgLxKfPMurd0Ec+8o/3ex/PkU7Wx8AHqAj/IQsLdNB2arHePpcQVzHjsb +u4+zJSrtxOzrZlC/qfPObh8+o/i72K556ZfcEFjb8QKBgQDt2qD5sKn592+xtGXX +rzv/8G1CdE6Zy4WBUl33gov2rbGvmkrAeDGWV7dgTW0fPI9oXhV4Ioc7q61cDp8C +U9FDjDNpEEhUextq4VFjJWQ2tUvigyTkMFT7dEg1j35jbMGmvNh9jWQzdeM3Rheb +Q8VVGbZ5i2z4iGpfrDfStUeiiwKBgQDooow36Y5KZtvbnkF+C0nqQ7LC63ZsSBTS +UQgFWw5sBJssv9DsZIm1Ke14aHZftrDm67mg+/xsrw3+DZxwlaui8zA4PLpmTrGj +AnJ/2F9En8LZtb/ove+gXuQjZrNUsHh6+OpMWaEC1Flp3+jaPoaKZPp0ta/WYHPi +OEQ3uvh0TQKBgH0FvjeAtNe/R+aQfDey1EbjiYq0t9v/Ll2bfejrpcYz5oH3B/PD +Oc1crfbgu8r/eiHR0lcjTxH+W1FYHhyLEiP/Pcar2FkPnInBhZYnwVVAVnLpnCqV +fRXvOUVt93EraV7LRMA54cFq5dPX8/CY3tCsg03AC7dXfRJs46rNvqmhAoGACyR1 ++Nub8B5bG3rKAkKCKNFTR5jFlEwjiytMag1BdJUH5a3OUPRD0ESQ1jqSqOT0NitG +Odq37XC5B9kZDB9vGB/zyE3IU8wjH/6nA06WyY+pYoodBgXK63CAFt39auoE60bu +2fdVCfCn07Vgzss94HUTtfFZ2bfG9SfixJSU/+UCgYEAyW1Si7qQRiNUSJWU8Jae +yFWOL1mvZRpXPUlg70H4wARoJjK6XgNKcE6GWbOedNtyiVJ7b07bmf9YJX2NWOzE +913vLOeLSlJeJAoQHEoYCM0nnOEcfUMiuOx59R4zk4RzSC64uK9PeguGSS6RaQwQ +8aj6l5u1SVtUNRb+ZjPCU8c= +-----END PRIVATE KEY----- +``` + +## 二、数据库脚本 + +```sql +DROP TABLE IF EXISTS `user_role`; +DROP TABLE IF EXISTS `role_menu`; +DROP TABLE IF EXISTS `role`; +DROP TABLE IF EXISTS `user`; +DROP TABLE IF EXISTS `menu`; + +CREATE TABLE `user` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户编号', + `username` varchar(32) DEFAULT NULL COMMENT '账户名', + `password` varchar(256) DEFAULT NULL COMMENT '密码', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表'; + +CREATE TABLE `role` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一ID', + `name` varchar(32) DEFAULT NULL COMMENT '角色名', + `keyword` varchar(64) DEFAULT NULL COMMENT '关键词', + `description` varchar(128) DEFAULT NULL COMMENT '角色描述', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色表'; + +CREATE TABLE `user_role` ( + `user_id` int(11) NOT NULL COMMENT '用户ID', + `role_id` int(11) NOT NULL COMMENT '角色ID', + PRIMARY KEY (`user_id`,`role_id`), + CONSTRAINT `FK_Reference_u_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`), + CONSTRAINT `FK_Reference_u_role` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户角色'; + +CREATE TABLE `menu` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '菜单编号', + `name` varchar(128) DEFAULT NULL COMMENT '菜单名', + `link_url` varchar(128) DEFAULT NULL COMMENT '链接地址', + `path` varchar(128) DEFAULT NULL COMMENT '路由地址', + `priority` int(11) DEFAULT NULL COMMENT '显示优先级别', + `icon` varchar(64) DEFAULT NULL COMMENT '图标', + `description` varchar(128) DEFAULT NULL COMMENT '描述', + `parent_menu_id` int(11) DEFAULT NULL COMMENT '父级菜单编号', + `level` int(11) DEFAULT NULL COMMENT '层次级别', + `is_enable` tinyint(4) DEFAULT '1' COMMENT '是否启用 0 禁用 1 启用', + PRIMARY KEY (`id`), + CONSTRAINT `FK_Reference_menu` FOREIGN KEY (`parent_menu_id`) REFERENCES `menu` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='菜单'; + +CREATE TABLE `role_menu` ( + `role_id` int(11) NOT NULL COMMENT '角色ID', + `menu_id` int(11) NOT NULL COMMENT '菜单ID', + PRIMARY KEY (`role_id`,`menu_id`), + CONSTRAINT `FK_Reference_r_menu` FOREIGN KEY (`menu_id`) REFERENCES `menu` (`id`), + CONSTRAINT `FK_Reference_r_role` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色菜单关系表'; + +INSERT INTO `user` VALUES ('1', 'admin', '$2a$10$K7U.Xolbbz3fGsAzpIawmeQuTWt/W0TXA8DpugqRwWsE0PeRSi1Vu'); +INSERT INTO `user` VALUES ('2', 'test', '$2a$10$K7U.Xolbbz3fGsAzpIawmeQuTWt/W0TXA8DpugqRwWsE0PeRSi1Vu'); +INSERT INTO `role` VALUES ('1', '超级管理员', 'SUPER_ADMIN', null); +INSERT INTO `role` VALUES ('2', '普通管理员', 'ADMIN', null); +INSERT INTO `user_role` VALUES ('1', '1'); +INSERT INTO `user_role` VALUES ('2', '2'); + +INSERT INTO `menu` VALUES ('1', '示例查询', '/cpp/query', '2', '2', 'fa-user-md', null, null, '1', '1'); +INSERT INTO `menu` VALUES ('2', '示例添加', '/cpp/add', '/2-1', '1', null, null, '1', '2', '1'); +INSERT INTO `menu` VALUES ('3', '示例修改', '/cpp/modify', '/2-2', '2', null, null, '1', '2', '1'); +INSERT INTO `menu` VALUES ('4', '示例删除', '/cpp/delete', '/2-3', '3', null, null, '1', '2', '1'); +INSERT INTO `menu` VALUES ('5', '示例JSON', '/cpp/json', '/2-3', '3', null, null, '1', '2', '1'); +INSERT INTO `role_menu` VALUES ('1', '1'); +INSERT INTO `role_menu` VALUES ('1', '2'); +INSERT INTO `role_menu` VALUES ('1', '3'); +INSERT INTO `role_menu` VALUES ('1', '4'); +INSERT INTO `role_menu` VALUES ('1', '5'); +INSERT INTO `role_menu` VALUES ('2', '1'); +INSERT INTO `role_menu` VALUES ('2', '5'); +``` + diff --git a/psi-java/psi-oauth2/pom.xml b/psi-java/psi-oauth2/pom.xml new file mode 100644 index 000000000..fa71a84d0 --- /dev/null +++ b/psi-java/psi-oauth2/pom.xml @@ -0,0 +1,94 @@ + + + 4.0.0 + + com.zeroone.star + psi-java + ${revision} + ../pom.xml + + psi-oauth2 + + + + org.springframework.boot + spring-boot-starter-web + + + + com.zeroone.star + psi-common + + + + com.zeroone.star + psi-apis + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + org.springframework.cloud + spring-cloud-starter-oauth2 + + + + com.baomidou + mybatis-plus-boot-starter + + + + com.alibaba + druid-spring-boot-starter + + + + mysql + mysql-connector-java + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + com.zeroone.star.oauth2.Oauth2Application + + + + io.fabric8 + docker-maven-plugin + + + http://192.168.220.128:2375 + + + + 01star/${project.artifactId}:${project.version} + + ${project.basedir} + + + + + + + + + diff --git a/psi-java/psi-oauth2/script/start.sh b/psi-java/psi-oauth2/script/start.sh new file mode 100644 index 000000000..5b9d61bf5 --- /dev/null +++ b/psi-java/psi-oauth2/script/start.sh @@ -0,0 +1,11 @@ +#!bin/bash +app_name='psi-oauth2' +docker stop ${app_name} +echo '----stop container----' +docker rm ${app_name} +echo '----rm container----' +docker run -p 10400:10400 --name ${app_name} \ +-v /etc/localtime:/etc/localtime \ +-v /home/app/${app_name}/logs:/tmp/logs \ +-d 01star/${app_name}:1.0.0-SNAPSHOT +echo '----start container----' diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/Oauth2Application.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/Oauth2Application.java new file mode 100644 index 000000000..60400196d --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/Oauth2Application.java @@ -0,0 +1,25 @@ +package com.zeroone.star.oauth2; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; + +/** + *

+ * 描述:服务器启动入口 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@SpringBootApplication +@EnableDiscoveryClient +public class Oauth2Application { + + public static void main(String[] args) { + SpringApplication.run(Oauth2Application.class, args); + } + +} diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/config/MyBatisInit.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/config/MyBatisInit.java new file mode 100644 index 000000000..c6cf57495 --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/config/MyBatisInit.java @@ -0,0 +1,20 @@ +package com.zeroone.star.oauth2.config; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +/** + *

+ * 描述:MyBatis初始化 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Configuration +@ComponentScan("com.zeroone.star.project.config.mybatis") +public class MyBatisInit { + +} diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/config/Oauth2ServerConfig.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/config/Oauth2ServerConfig.java new file mode 100644 index 000000000..7cab1a8bb --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/config/Oauth2ServerConfig.java @@ -0,0 +1,145 @@ +package com.zeroone.star.oauth2.config; + +import com.zeroone.star.oauth2.entity.SecurityUser; +import com.zeroone.star.oauth2.service.impl.UserDetailsServiceImpl; +import com.zeroone.star.project.constant.AuthConstant; +import lombok.AllArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.token.TokenEnhancer; +import org.springframework.security.oauth2.provider.token.TokenEnhancerChain; +import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; +import org.springframework.security.rsa.crypto.KeyStoreKeyFactory; +import org.springframework.stereotype.Component; + +import java.security.KeyPair; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + *

+ * 描述:JWT Token增强实现,将用户ID记录到Token里面 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * @author 阿伟学长 + * @version 1.0.0 + */ +@Component +class JwtTokenEnhancer implements TokenEnhancer { + @Override + public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) { + SecurityUser securityUser = (SecurityUser) oAuth2Authentication.getPrincipal(); + Map info = new HashMap<>(1); + //把用户ID设置到JWT中 + info.put("id", securityUser.getUser().getId()); + DefaultOAuth2AccessToken result = (DefaultOAuth2AccessToken) oAuth2AccessToken; + result.setAdditionalInformation(info); + return result; + } +} + +/** + *

+ * 描述:权限授权服务配置 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * @author 阿伟学长 + * @version 1.0.0 + */ +@Configuration +@EnableAuthorizationServer +@AllArgsConstructor +public class Oauth2ServerConfig extends AuthorizationServerConfigurerAdapter { + + private final PasswordEncoder passwordEncoder; + private final UserDetailsServiceImpl userDetailsService; + private final AuthenticationManager authenticationManager; + private final JwtTokenEnhancer jwtTokenEnhancer; + + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + // 针对于第三方客户端配置 + // 指定哪些应用可以访问授权服务并颁发令牌 + // 访问模式是什么 + clients.inMemory() + //配置客户端ID(管理端) + .withClient(AuthConstant.CLIENT_MANAGER) + //配置访问密码 + .secret(passwordEncoder.encode(AuthConstant.CLIENT_PASSWORD)) + //配置授权范围,客户端传递scope必须为下面的值或者不携带scope + .scopes("all") + //配置支持的授权模式,支持用户名密码认证和凭证刷新 + .authorizedGrantTypes("password", "refresh_token") + //配置颁发令牌的有效时间,这里修改成了24小时 + .accessTokenValiditySeconds(3600 * 24) + //配置颁发刷新令牌的有效时间,这里修改成了1周 + .refreshTokenValiditySeconds(3600 * 24 * 7) + .and() + //配置客户端ID(用户端,如app) + .withClient(AuthConstant.CLIENT_APP) + .secret(passwordEncoder.encode(AuthConstant.CLIENT_PASSWORD)) + .scopes("all") + .authorizedGrantTypes("password", "refresh_token") + .accessTokenValiditySeconds(3600 * 24) + .refreshTokenValiditySeconds(3600 * 24 * 7); + } + + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + //定义JWT内置增强内容 + List delegates = new ArrayList<>(); + delegates.add(jwtTokenEnhancer); + delegates.add(accessTokenConverter()); + //配置JWT的内容增强器 + TokenEnhancerChain enhancerChain = new TokenEnhancerChain(); + enhancerChain.setTokenEnhancers(delegates); + //授权服务端点访问配置 + endpoints + //配置授权管理器 + .authenticationManager(authenticationManager) + //配置加载用户信息的服务 + .userDetailsService(userDetailsService) + //设置凭证签名转换器 + .accessTokenConverter(accessTokenConverter()) + //设置凭证增强附加额外信息到凭证中 + .tokenEnhancer(enhancerChain); + } + + @Override + public void configure(AuthorizationServerSecurityConfigurer security) { + // 访问安全性配置 + // 在BasicAuthenticationFilter之前添加ClientCredentialsTokenEndpointFilter, + // 使用ClientDetailsUserDetailsService来进行登陆认证 + security.allowFormAuthenticationForClients(); + } + + @Bean + public JwtAccessTokenConverter accessTokenConverter() { + //使用非对称加密算法来对Token进行签名 + JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter(); + jwtAccessTokenConverter.setKeyPair(keyPair()); + return jwtAccessTokenConverter; + } + + @Bean + public KeyPair keyPair() { + //从classpath下的证书中获取秘钥对 + KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("jwt.jks"), "123456".toCharArray()); + return keyStoreKeyFactory.getKeyPair("01star", "123456".toCharArray()); + } +} diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/config/RedisInit.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/config/RedisInit.java new file mode 100644 index 000000000..ce62a341f --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/config/RedisInit.java @@ -0,0 +1,19 @@ +package com.zeroone.star.oauth2.config; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +/** + *

+ * 描述:Redis初始化 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Configuration +@ComponentScan("com.zeroone.star.project.config.redis") +public class RedisInit { +} diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/config/WebSecurityConfig.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/config/WebSecurityConfig.java new file mode 100644 index 000000000..22911d426 --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/config/WebSecurityConfig.java @@ -0,0 +1,47 @@ +package com.zeroone.star.oauth2.config; + +import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +/** + *

+ * 描述:SpringSecurity配置 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Configuration +@EnableWebSecurity +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeRequests() + // 内置端点请求放行 + .requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll() + // 公钥获取放行 + .antMatchers("/rsa/public-key").permitAll() + // 其他请求需要已认证才能访问 + .anyRequest().authenticated(); + } + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/controller/AuthController.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/controller/AuthController.java new file mode 100644 index 000000000..5dc770301 --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/controller/AuthController.java @@ -0,0 +1,59 @@ +package com.zeroone.star.oauth2.controller; + +import com.zeroone.star.project.dto.login.Oauth2TokenDTO; +import com.zeroone.star.project.oauth.AuthApis; +import com.zeroone.star.project.vo.JsonVO; +import com.zeroone.star.project.vo.ResultStatus; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.security.Principal; +import java.util.Map; + +/** + *

+ * 描述:认证服务相关接口 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@RestController +@RequestMapping("oauth") +public class AuthController implements AuthApis { + private final TokenEndpoint tokenEndpoint; + + @Autowired + public AuthController(TokenEndpoint tokenEndpoint) { + this.tokenEndpoint = tokenEndpoint; + } + + @Override + @PostMapping("token") + public JsonVO postAccessToken(Principal principal, @RequestParam Map parameters) { + //调用oAuth2AccessToken的postAccessToken接口来刷新或颁发token + OAuth2AccessToken oAuth2AccessToken; + try { + oAuth2AccessToken = tokenEndpoint.postAccessToken(principal, parameters).getBody(); + } catch (Exception e) { + return JsonVO.create(null, ResultStatus.FAIL.getCode(), "postAccessToken:" + e.getClass().getSimpleName() + ":" + e.getMessage()); + } + if (oAuth2AccessToken != null) { + Oauth2TokenDTO oauth2TokenDto = new Oauth2TokenDTO( + oAuth2AccessToken.getValue(), + oAuth2AccessToken.getRefreshToken().getValue(), + "Bearer ", + oAuth2AccessToken.getExpiresIn(), + parameters.get("client_id")); + return JsonVO.create(oauth2TokenDto, ResultStatus.SUCCESS); + } + return JsonVO.create(null, ResultStatus.FAIL.getCode(), "oAuth2AccessToken为null"); + } +} diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/controller/KeyPairController.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/controller/KeyPairController.java new file mode 100644 index 000000000..d0711f470 --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/controller/KeyPairController.java @@ -0,0 +1,48 @@ +package com.zeroone.star.oauth2.controller; + +import com.nimbusds.jose.jwk.JWKSet; +import com.nimbusds.jose.jwk.RSAKey; +import com.zeroone.star.project.oauth.KeyPairApis; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.security.KeyPair; +import java.security.interfaces.RSAPublicKey; +import java.util.Map; + +/** + *

+ * 描述:获取RSA密钥接口 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@RestController +@RequestMapping("rsa") +public class KeyPairController implements KeyPairApis { + private final KeyPair keyPair; + + @Autowired + public KeyPairController(KeyPair keyPair) { + this.keyPair = keyPair; + } + + @Override + @GetMapping("public-key") + public Map getPublicKey() { + RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); + RSAKey key = new RSAKey.Builder(publicKey).build(); + return new JWKSet(key).toJSONObject(); + } + + @Override + @GetMapping("private-key") + public Map getPrivateKey() { + return null; + } +} diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/entity/Menu.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/entity/Menu.java new file mode 100644 index 000000000..486df5c8a --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/entity/Menu.java @@ -0,0 +1,75 @@ +package com.zeroone.star.oauth2.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +/** + *

+ * 菜单 + *

+ * + * @author 阿伟 + */ +@Getter +@Setter +public class Menu implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 菜单编号 + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 菜单名 + */ + private String name; + + /** + * 链接地址 + */ + private String linkUrl; + + /** + * 路由地址 + */ + private String path; + + /** + * 显示优先级别 + */ + private Integer priority; + + /** + * 图标 + */ + private String icon; + + /** + * 描述 + */ + private String description; + + /** + * 父级菜单编号 + */ + private Integer parentMenuId; + + /** + * 层次级别 + */ + private Integer level; + + /** + * 是否启用 0 禁用 1 启用 + */ + private Integer isEnable; + + +} diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/entity/Role.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/entity/Role.java new file mode 100644 index 000000000..467eccc17 --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/entity/Role.java @@ -0,0 +1,45 @@ +package com.zeroone.star.oauth2.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +/** + *

+ * 角色表 + *

+ * + * @author 阿伟 + */ +@Getter +@Setter +public class Role implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 唯一ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 角色名 + */ + private String name; + + /** + * 关键词 + */ + private String keyword; + + /** + * 角色描述 + */ + private String description; + + +} diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/entity/SecurityUser.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/entity/SecurityUser.java new file mode 100644 index 000000000..ab0ec4c47 --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/entity/SecurityUser.java @@ -0,0 +1,39 @@ +package com.zeroone.star.oauth2.entity; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.springframework.security.core.GrantedAuthority; + +import java.util.Collection; + +/** + *

+ * 描述:权限认证用户实体 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Getter +@Setter +@ToString +public class SecurityUser extends org.springframework.security.core.userdetails.User { + /** + * 关联一个用户对象 + */ + private User user; + + /** + * 构造初始化 + * + * @param user 数据库的User对象 + * @param authorities 权限列表 + */ + public SecurityUser(User user, Collection authorities) { + super(user.getUsername(), user.getPassword(), authorities); + this.user = user; + } +} diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/entity/User.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/entity/User.java new file mode 100644 index 000000000..a7e7401ba --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/entity/User.java @@ -0,0 +1,40 @@ +package com.zeroone.star.oauth2.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +/** + *

+ * 用户表 + *

+ * + * @author 阿伟 + */ +@Getter +@Setter +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 用户编号 + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 账户名 + */ + private String username; + + /** + * 密码 + */ + private String password; + + +} diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/mapper/MenuMapper.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/mapper/MenuMapper.java new file mode 100644 index 000000000..3e72e5209 --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/mapper/MenuMapper.java @@ -0,0 +1,17 @@ +package com.zeroone.star.oauth2.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.zeroone.star.oauth2.entity.Menu; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 菜单 Mapper 接口 + *

+ * + * @author 阿伟 + */ +@Mapper +public interface MenuMapper extends BaseMapper { + +} diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/mapper/RoleMapper.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/mapper/RoleMapper.java new file mode 100644 index 000000000..cd2b826d6 --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/mapper/RoleMapper.java @@ -0,0 +1,31 @@ +package com.zeroone.star.oauth2.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.zeroone.star.oauth2.entity.Role; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + *

+ * 角色表 Mapper 接口 + *

+ * + * @author 阿伟 + */ +@Mapper +public interface RoleMapper extends BaseMapper { + /** + * 通过用户编号查询角色 + * @param userId 用户编号 + * @return 角色列表 + */ + List selectByUserId(int userId); + + /** + * 通过菜单路径获取对应的角色 + * @param path 菜单路径 + * @return 角色列表 + */ + List selectByMenuPath(String path); +} diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/mapper/UserMapper.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/mapper/UserMapper.java new file mode 100644 index 000000000..1dbc8086e --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/mapper/UserMapper.java @@ -0,0 +1,17 @@ +package com.zeroone.star.oauth2.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.zeroone.star.oauth2.entity.User; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 用户表 Mapper 接口 + *

+ * + * @author 阿伟 + */ +@Mapper +public interface UserMapper extends BaseMapper { + +} diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/IMenuService.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/IMenuService.java new file mode 100644 index 000000000..8da9caf4a --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/IMenuService.java @@ -0,0 +1,21 @@ +package com.zeroone.star.oauth2.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.zeroone.star.oauth2.entity.Menu; + +import java.util.List; + +/** + *

+ * 菜单 服务类 + *

+ * + * @author 阿伟 + */ +public interface IMenuService extends IService { + /** + * 获取菜单中的链接地址 + * @return 查询结果 + */ + List listAllLinkUrl(); +} diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/IRoleService.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/IRoleService.java new file mode 100644 index 000000000..21a7443f1 --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/IRoleService.java @@ -0,0 +1,29 @@ +package com.zeroone.star.oauth2.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.zeroone.star.oauth2.entity.Role; + +import java.util.List; + +/** + *

+ * 角色表 服务类 + *

+ * + * @author 阿伟 + */ +public interface IRoleService extends IService { + /** + * 通过用户编号获取角色列表 + * @param userId 用户编号 + * @return 角色列表 + */ + List listRoleByUserId(int userId); + + /** + * 获取指定菜单路径有访问权限的角色 + * @param path 指定菜单路径 + * @return 角色列表 + */ + List listRoleByMenuPath(String path); +} diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/IUserService.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/IUserService.java new file mode 100644 index 000000000..3b65b01e4 --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/IUserService.java @@ -0,0 +1,15 @@ +package com.zeroone.star.oauth2.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.zeroone.star.oauth2.entity.User; + +/** + *

+ * 用户表 服务类 + *

+ * + * @author 阿伟 + */ +public interface IUserService extends IService { + +} diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/impl/MenuServiceImpl.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/impl/MenuServiceImpl.java new file mode 100644 index 000000000..c1eee2cb3 --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/impl/MenuServiceImpl.java @@ -0,0 +1,29 @@ +package com.zeroone.star.oauth2.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.zeroone.star.oauth2.entity.Menu; +import com.zeroone.star.oauth2.mapper.MenuMapper; +import com.zeroone.star.oauth2.service.IMenuService; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 菜单 服务实现类 + *

+ * + * @author 阿伟 + */ +@Service +public class MenuServiceImpl extends ServiceImpl implements IMenuService { + + @Override + public List listAllLinkUrl() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.select("link_url"); + wrapper.isNotNull("link_url"); + return baseMapper.selectList(wrapper); + } +} diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/impl/ResourceServiceImpl.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/impl/ResourceServiceImpl.java new file mode 100644 index 000000000..91974c63e --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/impl/ResourceServiceImpl.java @@ -0,0 +1,54 @@ +package com.zeroone.star.oauth2.service.impl; + +import com.zeroone.star.oauth2.entity.Menu; +import com.zeroone.star.oauth2.entity.Role; +import com.zeroone.star.oauth2.service.IMenuService; +import com.zeroone.star.oauth2.service.IRoleService; +import com.zeroone.star.project.constant.RedisConstant; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +/** + *

+ * 描述:路径与角色资源服务器初始化服务 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Service +public class ResourceServiceImpl { + @Resource + private RedisTemplate redisTemplate; + @Resource + private IMenuService menuService; + @Resource + private IRoleService roleService; + + @PostConstruct + public void init() { + // 定义缓存map + Map> resourceRolesMap = new TreeMap<>(); + // 1 获取所有菜单 + List tMenus = menuService.listAllLinkUrl(); + tMenus.forEach(menu -> { + // 2 获取菜单对应的角色 + List rolesMenu = roleService.listRoleByMenuPath(menu.getLinkUrl()); + List roles = new ArrayList<>(); + rolesMenu.forEach(role -> roles.add(role.getKeyword())); + resourceRolesMap.put(menu.getLinkUrl(), roles); + }); + + //将资源缓存到redis + redisTemplate.opsForHash().putAll(RedisConstant.RESOURCE_ROLES_MAP, resourceRolesMap); + } +} diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/impl/RoleServiceImpl.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/impl/RoleServiceImpl.java new file mode 100644 index 000000000..300d3641f --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/impl/RoleServiceImpl.java @@ -0,0 +1,30 @@ +package com.zeroone.star.oauth2.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.zeroone.star.oauth2.entity.Role; +import com.zeroone.star.oauth2.mapper.RoleMapper; +import com.zeroone.star.oauth2.service.IRoleService; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 角色表 服务实现类 + *

+ * + * @author 阿伟 + */ +@Service +public class RoleServiceImpl extends ServiceImpl implements IRoleService { + + @Override + public List listRoleByUserId(int userId) { + return baseMapper.selectByUserId(userId); + } + + @Override + public List listRoleByMenuPath(String path) { + return baseMapper.selectByMenuPath(path); + } +} diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/impl/UserDetailsServiceImpl.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/impl/UserDetailsServiceImpl.java new file mode 100644 index 000000000..ba73cf5d5 --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/impl/UserDetailsServiceImpl.java @@ -0,0 +1,64 @@ +package com.zeroone.star.oauth2.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.zeroone.star.oauth2.entity.Role; +import com.zeroone.star.oauth2.entity.SecurityUser; +import com.zeroone.star.oauth2.entity.User; +import com.zeroone.star.oauth2.service.IRoleService; +import com.zeroone.star.oauth2.service.IUserService; +import com.zeroone.star.project.constant.AuthConstant; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.List; + +/** + *

+ * 描述:用户权限权限服务实现 + *

+ *

版权:©01星球

+ *

地址:01星球总部

+ * + * @author 阿伟学长 + * @version 1.0.0 + */ +@Service +public class UserDetailsServiceImpl implements UserDetailsService { + @Resource + IUserService userService; + @Resource + IRoleService roleService; + @Resource + HttpServletRequest request; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + String clientId = request.getParameter("client_id"); + if (AuthConstant.CLIENT_MANAGER.equals(clientId)) { + //1 通过用户名查找用户对象 + User user = new User(); + user.setUsername(username); + user = userService.getOne(new QueryWrapper<>(user)); + if (user == null) { + throw new UsernameNotFoundException("用户名或密码错误"); + } + //2 通过用户ID获取角色列表 + List roles = roleService.listRoleByUserId(user.getId()); + //3 将数据库角色转换成Security权限对象 + List authorities = new ArrayList<>(); + roles.forEach(role -> authorities.add(new SimpleGrantedAuthority(role.getKeyword()))); + //4 构建权限角色对象 + return new SecurityUser(user, authorities); + } else if (AuthConstant.CLIENT_APP.equals(clientId)) { + throw new UsernameNotFoundException("用户端查找用户尚未实现"); + } + throw new UsernameNotFoundException("登录客户端ID错误"); + } +} diff --git a/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/impl/UserServiceImpl.java b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/impl/UserServiceImpl.java new file mode 100644 index 000000000..b422db72e --- /dev/null +++ b/psi-java/psi-oauth2/src/main/java/com/zeroone/star/oauth2/service/impl/UserServiceImpl.java @@ -0,0 +1,19 @@ +package com.zeroone.star.oauth2.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.zeroone.star.oauth2.entity.User; +import com.zeroone.star.oauth2.mapper.UserMapper; +import com.zeroone.star.oauth2.service.IUserService; +import org.springframework.stereotype.Service; + +/** + *

+ * 用户表 服务实现类 + *

+ * + * @author 阿伟 + */ +@Service +public class UserServiceImpl extends ServiceImpl implements IUserService { + +} diff --git a/psi-java/psi-oauth2/src/main/resources/application.yaml b/psi-java/psi-oauth2/src/main/resources/application.yaml new file mode 100644 index 000000000..21dc66b71 --- /dev/null +++ b/psi-java/psi-oauth2/src/main/resources/application.yaml @@ -0,0 +1,5 @@ +server: + port: ${sp.auth} +spring: + application: + name: ${sn.auth} diff --git a/psi-java/psi-oauth2/src/main/resources/jwt.jks b/psi-java/psi-oauth2/src/main/resources/jwt.jks new file mode 100644 index 000000000..ae0ec277a Binary files /dev/null and b/psi-java/psi-oauth2/src/main/resources/jwt.jks differ diff --git a/psi-java/psi-oauth2/src/main/resources/jwt.jks.old b/psi-java/psi-oauth2/src/main/resources/jwt.jks.old new file mode 100644 index 000000000..c54f7568a Binary files /dev/null and b/psi-java/psi-oauth2/src/main/resources/jwt.jks.old differ diff --git a/psi-java/psi-oauth2/src/main/resources/jwt.pfx b/psi-java/psi-oauth2/src/main/resources/jwt.pfx new file mode 100644 index 000000000..6bf0d0829 Binary files /dev/null and b/psi-java/psi-oauth2/src/main/resources/jwt.pfx differ diff --git a/psi-java/psi-oauth2/src/main/resources/mapper/MenuMapper.xml b/psi-java/psi-oauth2/src/main/resources/mapper/MenuMapper.xml new file mode 100644 index 000000000..1ef3fec1d --- /dev/null +++ b/psi-java/psi-oauth2/src/main/resources/mapper/MenuMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/psi-java/psi-oauth2/src/main/resources/mapper/RoleMapper.xml b/psi-java/psi-oauth2/src/main/resources/mapper/RoleMapper.xml new file mode 100644 index 000000000..16b6c1047 --- /dev/null +++ b/psi-java/psi-oauth2/src/main/resources/mapper/RoleMapper.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/psi-java/psi-oauth2/src/main/resources/mapper/UserMapper.xml b/psi-java/psi-oauth2/src/main/resources/mapper/UserMapper.xml new file mode 100644 index 000000000..aadef2f12 --- /dev/null +++ b/psi-java/psi-oauth2/src/main/resources/mapper/UserMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/psi-java/psi-oauth2/src/test/java/com/zeroone/star/oauth2/Oauth2ApplicationTests.java b/psi-java/psi-oauth2/src/test/java/com/zeroone/star/oauth2/Oauth2ApplicationTests.java new file mode 100644 index 000000000..4503cf4d1 --- /dev/null +++ b/psi-java/psi-oauth2/src/test/java/com/zeroone/star/oauth2/Oauth2ApplicationTests.java @@ -0,0 +1,19 @@ +package com.zeroone.star.oauth2; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.crypto.password.PasswordEncoder; + +import javax.annotation.Resource; + +@SpringBootTest +class Oauth2ApplicationTests { + @Resource + PasswordEncoder passwordEncoder; + + @Test + void contextLoads() { + System.out.println(passwordEncoder.encode("123456")); + } + +} diff --git a/psi-java/psi-prepayment/Dockerfile b/psi-java/psi-prepayment/Dockerfile new file mode 100644 index 000000000..7d903ac91 --- /dev/null +++ b/psi-java/psi-prepayment/Dockerfile @@ -0,0 +1,5 @@ +FROM openjdk:8 +MAINTAINER 01star +ADD target/psi-prepayment-1.0.0-SNAPSHOT.jar app.jar +CMD java -Xms64m -Xmx64m -jar app.jar --spring.cloud.nacos.discovery.ip=8.130.20.243 --spring.profiles.active=test --logging.file.path=/tmp/logs/spring-boot +#CMD java -jar app.jar --spring.profiles.active=test --logging.file.path=/tmp/logs/spring-boot diff --git a/psi-java/psi-prepayment/README.md b/psi-java/psi-prepayment/README.md new file mode 100644 index 000000000..5de898ee5 --- /dev/null +++ b/psi-java/psi-prepayment/README.md @@ -0,0 +1 @@ +用于实现采购预付 diff --git a/psi-java/psi-prepayment/pom.xml b/psi-java/psi-prepayment/pom.xml new file mode 100644 index 000000000..26f8bb190 --- /dev/null +++ b/psi-java/psi-prepayment/pom.xml @@ -0,0 +1,107 @@ + + + + com.zeroone.star + psi-java + ${revision} + ../pom.xml + + 4.0.0 + + psi-prepayment + + + + org.springframework.boot + spring-boot-starter-web + + + + com.zeroone.star + psi-common + + + com.zeroone.star + psi-apis + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + mysql + mysql-connector-java + + + + com.alibaba + druid-spring-boot-starter + + + + com.baomidou + mybatis-plus-boot-starter + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-seata + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + + org.springframework.boot + spring-boot-starter-aop + + + + net.logstash.logback + logstash-logback-encoder + + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + com.zeroone.star.prepayment.PrepaymentApplication + + + + io.fabric8 + docker-maven-plugin + + + http://8.130.20.243:2375 + + + + 01star/${project.artifactId}:${project.version} + + ${project.basedir} + + + + + + + + + diff --git a/psi-java/psi-prepayment/script/start.sh b/psi-java/psi-prepayment/script/start.sh new file mode 100644 index 000000000..20f5aae63 --- /dev/null +++ b/psi-java/psi-prepayment/script/start.sh @@ -0,0 +1,11 @@ +#!bin/bash +app_name='psi-prepayment' +docker stop ${app_name} +echo '----stop container----' +docker rm ${app_name} +echo '----rm container----' +docker run -p 10690:10690 --name ${app_name} \ +-v /etc/localtime:/etc/localtime \ +-v /home/app/${app_name}/logs:/tmp/logs \ +-d 01star/${app_name}:1.0.0-SNAPSHOT +echo '----start container----' diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/PrepaymentApplication.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/PrepaymentApplication.java new file mode 100644 index 000000000..46462c074 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/PrepaymentApplication.java @@ -0,0 +1,20 @@ +package com.zeroone.star.prepayment; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; + +/** + * Description + * Author forever爱 + * Date 2023/2/10 + */ +@SpringBootApplication +@EnableDiscoveryClient +@MapperScan("com.zeroone.star.prepayment.mapper") +public class PrepaymentApplication { + public static void main(String[] args) { + SpringApplication.run(PrepaymentApplication.class,args); + } +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/config/ComponentInit.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/config/ComponentInit.java new file mode 100644 index 000000000..6e9949446 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/config/ComponentInit.java @@ -0,0 +1,14 @@ +package com.zeroone.star.prepayment.config; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan({ + "com.zeroone.star.project.components.fastdfs", + "com.zeroone.star.project.components.easyexcel", + "com.zeroone.star.project.components.jwt", + "com.zeroone.star.project.components.user" +}) +public class ComponentInit { +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/config/GlobalExceptionHandler.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/config/GlobalExceptionHandler.java new file mode 100644 index 000000000..7211119db --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/config/GlobalExceptionHandler.java @@ -0,0 +1,82 @@ +package com.zeroone.star.prepayment.config; + +import com.zeroone.star.project.vo.JsonVO; +import com.zeroone.star.project.vo.ResultStatus; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.validation.FieldError; +import org.springframework.web.HttpMediaTypeException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.MissingServletRequestParameterException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import javax.validation.Path; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +@RestControllerAdvice +public class GlobalExceptionHandler { + /** + * 系统通用异常处理 + */ + @ExceptionHandler(value = Exception.class) + public JsonVO exceptionHandler(Exception e) { + if (e instanceof HttpMediaTypeException) { + return JsonVO.create(e.getMessage(), ResultStatus.CONTENT_TYPE_ERR); + } + return JsonVO.create(e.getMessage(), ResultStatus.SERVER_ERROR); + } + + /** + * requestBody参数校验异常处理 + */ + @ExceptionHandler(value = + {MethodArgumentNotValidException.class, BindException.class}) + public JsonVO methodArgumentNotValidHandler(Exception e) { + BindingResult bindingResult; + if (e instanceof MethodArgumentNotValidException) { + //@RequestBody参数校验 + bindingResult = ((MethodArgumentNotValidException) e).getBindingResult(); + } else { + //@ModelAttribute参数校验 + bindingResult = ((BindException) e).getBindingResult(); + } + FieldError fieldError = bindingResult.getFieldError(); + String data = ""; + if (fieldError != null) { + data = "[" + fieldError.getField() + "]" + fieldError.getDefaultMessage(); + } + return JsonVO.create(data, ResultStatus.PARAMS_INVALID); + } + + /** + * requestParam参数校验异常处理 + */ + @ExceptionHandler(value = { + ConstraintViolationException.class, + MissingServletRequestParameterException.class}) + public JsonVO constraintViolationHandler(Exception e) { + String field = ""; + String msg = ""; + if (e instanceof ConstraintViolationException) { + ConstraintViolation constraint = ((ConstraintViolationException) e) + .getConstraintViolations().stream().findFirst().orElse(null); + if (constraint != null) { + List pathList = StreamSupport.stream + (constraint.getPropertyPath().spliterator(), false) + .collect(Collectors.toList()); + field = pathList.get(pathList.size() - 1).getName(); + msg = constraint.getMessage(); + } + } else { + // 非JSR标准返回的异常,要自定义提示文本 + field = ((MissingServletRequestParameterException) e).getParameterName(); + msg = "参数值缺失"; + } + return JsonVO.create("[" + field + "]" + msg, ResultStatus.PARAMS_INVALID); + } +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/config/MyBatisInit.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/config/MyBatisInit.java new file mode 100644 index 000000000..dff7b236e --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/config/MyBatisInit.java @@ -0,0 +1,16 @@ +package com.zeroone.star.prepayment.config; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +/** + * @Description + * @Author forever爱 + * @Date 2023/2/10 + */ +@Configuration +@ComponentScan({ + "com.zeroone.star.project.config.mybatis" +}) +public class MyBatisInit { +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/config/SwaggerConfig.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/config/SwaggerConfig.java new file mode 100644 index 000000000..03c9c63fe --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/config/SwaggerConfig.java @@ -0,0 +1,21 @@ +package com.zeroone.star.prepayment.config; + +import com.zeroone.star.project.config.swagger.SwaggerCore; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc; + +/** + * @Description + * @Author forever爱 + * @Date 2023/2/10 + */ +@Configuration +@EnableSwagger2WebMvc +public class SwaggerConfig { + @Bean + Docket modifyApi() { + return SwaggerCore.defaultDocketBuilder("采购预付", "com.zeroone.star.prepayment.controller", "prepayment"); + } +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/controller/CommonController.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/controller/CommonController.java new file mode 100644 index 000000000..c4f38d4fe --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/controller/CommonController.java @@ -0,0 +1,104 @@ +package com.zeroone.star.prepayment.controller; + +import com.zeroone.star.prepayment.service.*; +import com.zeroone.star.project.query.prepayment.PurchaseListQuery; +import com.zeroone.star.project.vo.JsonVO; +import com.zeroone.star.project.vo.PageVO; +import com.zeroone.star.project.vo.prepayment.*; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.List; + +@RestController +@RequestMapping("common") +@Api(tags = "公共接口") +public class CommonController { + @Resource + ISysDepartService departService; + @Resource + IBasBankAccountService basBankAccountService; + @Resource + ISysUserService userService; + @Resource + IBasSupplierService supplierService; + @Resource + IFinPaymentReqService finPaymentReqService; + @Resource + IPurOrderService purOrderService; + /** + * 获取供应商列表 + * author 空 + * since 2023-02-13 + */ + @GetMapping("getSuppliers") + @ApiOperation(value = "获取供应商列表") + public JsonVO> querySupplierList() { + List supplierList = supplierService.getSupplierList(); + return JsonVO.success(supplierList); + } + + /** + * 获取系统用户列表 + * author 空 + * since 2023-02-13 + */ + @GetMapping("sys_user,realname,username") + @ApiOperation(value = "获取用户字典") + public JsonVO> getSysUsersName() { + List sysUserList = userService.getSysUserList(); + return JsonVO.success(sysUserList); + } + + /** + * 获取组织机构表 + * author 空 + * since 2023-02-13 + */ + @GetMapping("sys_depart,depart_name,org_code") + @ApiOperation(value = "获取部门字典") + public JsonVO> getSysDepart() { + List departs = departService.getDeparts(); + return JsonVO.success(departs); + } + + /** + * 获取银行账户列表 + * author 空 + * since 2023-02-13 + */ + @GetMapping("bas_bank_account,account_no,id") + @ApiOperation(value = "获取银行账户列表") + public JsonVO> getBankAccount() { + List basBankAccountList = basBankAccountService.getBasBankAccountList(); + return JsonVO.success(basBankAccountList); + } + + /** + * 获取采购项目清单(无申请) + * author 空 + * since 2023-02-13 + */ + @GetMapping("list-purhcaserequisitions") + @ApiOperation(value = "获取采购清单(无申请)") + public JsonVO> queryForAppliedPurchaseRequisitions(PurchaseListQuery purchaseListQuery) { + PageVO purOrder = purOrderService.getPurOrder(purchaseListQuery); + return JsonVO.success(purOrder); + } + + /** + * 获取采购项目清单(有申请) + * author 空 + * since 2023-02-13 + */ + @GetMapping("list-appliedpurhcaserequisitions") + @ApiOperation(value = "获取采购清单(有申请)") + public JsonVO> queryForPurchaseRequisitions(PurchaseListQuery purchaseListQuery) { + PageVO finPaymentReq = finPaymentReqService.getFinPaymentReq(purchaseListQuery); + return JsonVO.success(finPaymentReq); + } +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/controller/FileController.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/controller/FileController.java new file mode 100644 index 000000000..9d843c366 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/controller/FileController.java @@ -0,0 +1,107 @@ +package com.zeroone.star.prepayment.controller; + +import com.zeroone.star.prepayment.service.IFinPaymentService; +import com.zeroone.star.project.components.fastdfs.FastDfsClientComponent; +import com.zeroone.star.project.components.fastdfs.FastDfsFileInfo; +import com.zeroone.star.project.vo.JsonVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.SneakyThrows; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; + +@Controller +@RequestMapping("file") +@Api(tags = "文件操作") +public class FileController { + @Resource + FastDfsClientComponent dfsClient; + + @Value("${fastdfs.nginx-servers}") + private String serverUrl; + + @Resource + IFinPaymentService paymentService; + /** + * 上传附件 + * author forever爱、KONG + */ + @SneakyThrows + @ApiOperation(value = "文件上传") + @ResponseBody + @PostMapping("upload") + public JsonVO upload(MultipartFile file) { + // 获取文件名 + String filename = file.getOriginalFilename(); + if (filename == null) { + return JsonVO.fail("文件名为空"); + } + // 获取文件的后缀 + String suffix = filename.substring(filename.lastIndexOf(".") + 1); + // 上传文件到FastDFS + FastDfsFileInfo result = dfsClient.uploadFile(file.getBytes(), suffix); + if (result == null) { + return JsonVO.fail("文件上传失败"); + } + // 拼接文件下载地址 + String downloadUrl = dfsClient.fetchUrl(result, serverUrl, true); + return JsonVO.success(downloadUrl); + } + + /** + * 导出功能实现 + * author 明破 + * since 2023-02-13 + */ + @GetMapping("export-payments-excel") + @ApiOperation(value = "获取导出文件") + public ResponseEntity download(String paymentType) { + // 实体类中的paymentType,2011代表采购预付有申请,2010代表采购预付无申请 + if(paymentType.equals("2011")){ + return paymentService.download(true); + } + else if(paymentType.equals("2010")){ + return paymentService.download(false); + }else{ + return ResponseEntity.noContent().build(); + } + } + + @GetMapping(value = "export-payments-url") + @ApiOperation(value = "获取导出链接") + @ResponseBody + public JsonVO downloadUrl(String paymentType) { + // 实体类中的paymentType,2011代表采购预付有申请,2010代表采购预付无申请 + if(paymentType.equals("2011")) { + return paymentService.downloadUrl(true); + }else if(paymentType.equals("2010")) { + return paymentService.downloadUrl(false); + }else { + return JsonVO.fail("获取文件链接失败"); + } + } + + /** + * Excel 表格导入 + * param file Excel 文件 + * return 处理结果 + * author 内鬼 + */ + @PostMapping("import-payments-excel") + @ResponseBody + @ApiOperation("导入功能(返回值data值表示导入成功与否)") + public JsonVO excelImport(@RequestParam("file") MultipartFile file) { + try { + paymentService.importExcelOfPayment(file); + } catch (Exception e) { + e.printStackTrace(); + return JsonVO.fail("文件导入失败"); + } + return JsonVO.success("文件导入成功!"); + } +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/controller/PrepaymentController.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/controller/PrepaymentController.java new file mode 100644 index 000000000..d1a1da2f1 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/controller/PrepaymentController.java @@ -0,0 +1,274 @@ +package com.zeroone.star.prepayment.controller; + +import com.zeroone.star.prepayment.service.IPrepaymentService; +import com.zeroone.star.project.components.user.UserDTO; +import com.zeroone.star.project.components.user.UserHolder; +import com.zeroone.star.project.dto.prepayment.*; +import com.zeroone.star.project.prepayment.PrepaymentApis; +import com.zeroone.star.project.query.prepayment.*; +import com.zeroone.star.project.vo.JsonVO; +import com.zeroone.star.project.vo.PageVO; +import com.zeroone.star.project.vo.ResultStatus; +import com.zeroone.star.project.vo.prepayment.DetHavVO; +import com.zeroone.star.project.vo.prepayment.DetNoVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.GetMapping; +import javax.annotation.Resource; +import javax.validation.constraints.NotBlank; + +import com.zeroone.star.prepayment.service.*; +import com.zeroone.star.project.vo.prepayment.*; + +@RestController +@RequestMapping("prepayment") +@Api(tags = "预付模块") +@Validated +public class PrepaymentController implements PrepaymentApis { + @Resource + IPrepaymentService prepaymentService; + @Resource + UserHolder userHolder; + @Resource + IFinPaymentReqService paymentReqService; + + /** + * 修改采购预付单功能 + * author forever爱 + * since 2023-02-13 + */ + @PutMapping("edit") + @ApiOperation(value = "修改采购预付单功能(返回值data值表示更新成功与否)") + @Override + public JsonVO modify(@Validated ModifyDTO modifyDTO) { + //获取用户信息 + UserDTO currentUser; + try { + currentUser = userHolder.getCurrentUser(); + } catch (Exception e) { + return JsonVO.create(null, ResultStatus.FAIL.getCode(), e.getMessage()); + } + if (currentUser == null) { + return JsonVO.fail(null); + } + return prepaymentService.modify(modifyDTO,currentUser); + } + + /** + * 审核采购预付单功能 + * author forever爱 + * since 2023-02-13 + */ + @PutMapping("audit") + @ApiOperation(value = "审核采购预付单功能(返回值data值表示更新成功与否)") + @Override + public JsonVO auditById(@Validated AuditDTO auditDTO) { + UserDTO currentUser; + try { + currentUser = userHolder.getCurrentUser(); + } catch (Exception e) { + return JsonVO.create(null, ResultStatus.FAIL.getCode(), e.getMessage()); + } + if (currentUser == null) { + return JsonVO.fail(null); + } + return prepaymentService.auditById(auditDTO,currentUser); + } + + /** + * 保存采购预付单功能 + * param ModifyDTO 保存DTO + * return 查询结果 + * author forever爱 + */ + @PutMapping("save") + @ApiOperation("保存采购预付单功能(返回值data值表示更新成功与否)") + @Override + public JsonVO save(@Validated ModifyDTO modifyDTO) { + UserDTO currentUser; + try { + currentUser = userHolder.getCurrentUser(); + } catch (Exception e) { + return JsonVO.create(null, ResultStatus.FAIL.getCode(), e.getMessage()); + } + if (currentUser == null) { + return JsonVO.fail(null); + } + return prepaymentService.save(modifyDTO,currentUser); + } + + /** + * 单据分页查询 + * 采购预付(有申请):payment_type 2011 + * 采购预付(无申请):payment_type 2010 + * author husj、hzp + * since 2023-02-13 + */ + @Override + @GetMapping("query-all-hav") + @ApiOperation(value = "查询采购预付单功能(有申请)") + @ResponseBody + public JsonVO> queryAllHav(DocListQuery condition) { + condition.setPaymentType("2011"); + return JsonVO.success(prepaymentService.queryAll(condition)); + } + + @Override + @GetMapping("query-all-no") + @ApiOperation(value = "查询采购预付单功能(无申请)") + @ResponseBody + public JsonVO> queryAllNo(DocListQuery condition) { + condition.setPaymentType("2010"); + return JsonVO.success(prepaymentService.queryAll(condition)); + } + + /** + * 根据单据编号查询信息 + * author hzp + * since 2023-02-13 + */ + @GetMapping("query-one-hav") + @ApiOperation(value = "查看单据详情信息(有申请)") + @Override + public JsonVO queryByBillHav(@Validated PreDetQuery condition) { + return prepaymentService.queryByBillHav(condition); + } + + @GetMapping("query-one-no") + @ApiOperation(value = "查看单据详情信息(无申请)") + @Override + public JsonVO queryByBillNo(@Validated PreDetQuery condition) { + return prepaymentService.queryByBillNo(condition); + } + + /** + * 删除 + * author 出运费 + * since 2023-02-13 + */ + @DeleteMapping("delete") + @ApiOperation(value = "删除功能(返回值data值保存删除成功与否)") + @Override + public JsonVO deleteById(@Validated DeleteDTO deleteDTO) throws Exception { + return prepaymentService.deleteById(deleteDTO); + } + + /** + * 添加 + * author 空 + * since 2023-02-13 + */ + @PostMapping("insert") + @ApiOperation(value = "添加采购预付单功能(返回值data值表示创建成功与否)") + @Override + public JsonVO prepaymentForPurchaseRequisitions(PrepaymentDTO prepaymentDTO) { + //获取用户信息 + UserDTO currentUser; + try { + currentUser = userHolder.getCurrentUser(); + } catch (Exception e) { + return JsonVO.create(null, ResultStatus.FAIL.getCode(), e.getMessage()); + } + if (currentUser == null) { + return JsonVO.fail(null); + } + return prepaymentService.prepay(prepaymentDTO,currentUser); + } + + + /** + * 采购预付申请单分录列表 + * param supplierName 供应商名 + * return 分录明细列表 + * author 内鬼 + */ + @Override + @GetMapping("query-all-paymentReq") + @ResponseBody + @ApiOperation("付款申请单分录列表查询") + public JsonVO> queryAllReq(FinPaymentReqQuery query) { + PageVO paymentReqEntryPage = paymentReqService.listFinPaymentReq(query); + return JsonVO.success(paymentReqEntryPage); + } + + /** + * 修改状态 + * author yu-hang + */ + @Override + public JsonVO closeById(String id) { + //获取用户信息 + UserDTO currentUser; + try { + currentUser = userHolder.getCurrentUser(); + } catch (Exception e) { + return JsonVO.create(null, ResultStatus.FAIL.getCode(), e.getMessage()); + } + if (currentUser == null) { + return JsonVO.fail(null); + } + return prepaymentService.closeById(id,currentUser); + } + + @Override + public JsonVO uncloseById(String id) { + //获取用户信息 + UserDTO currentUser; + try { + currentUser = userHolder.getCurrentUser(); + } catch (Exception e) { + return JsonVO.create(null, ResultStatus.FAIL.getCode(), e.getMessage()); + } + if (currentUser == null) { + return JsonVO.fail(null); + } + return prepaymentService.uncloseById(id,currentUser); + } + + @Override + public JsonVO voidById(String id) { + //获取用户信息 + UserDTO currentUser; + try { + currentUser = userHolder.getCurrentUser(); + } catch (Exception e) { + return JsonVO.create(null, ResultStatus.FAIL.getCode(), e.getMessage()); + } + if (currentUser == null) { + return JsonVO.fail(null); + } + return prepaymentService.voidById(id,currentUser); + } + + @PutMapping("void") + @ApiOperation(value = "作废操作(返回值data值表示更新成功与否)") + public JsonVO voidByIdValidate(@NotBlank(message = "id不能为空") @RequestParam String id) { + return voidById(id); + } + + @PutMapping("unclose") + @ApiOperation(value = "反关闭操作(返回值data值表示更新成功与否)") + public JsonVO uncloseByIdValidate(@NotBlank(message = "id不能为空") @RequestParam String id) { + return uncloseById(id); + } + + @PutMapping("close") + @ApiOperation(value = "关闭操作(返回值data值表示更新成功与否)") + public JsonVO closeByIdValidate(@NotBlank(message = "id不能为空") @RequestParam String id) { + return closeById(id); + } + +// @GetMapping("query-one") +// @ApiOperation(value = "示例编号查询") +// public JsonVO queryByIdValidate( +// @Min(value = 1, message = "最小值必须为1") +// @RequestParam int id) { +// return queryById(id); +// } +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/BasBankAccount.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/BasBankAccount.java new file mode 100644 index 000000000..064447f77 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/BasBankAccount.java @@ -0,0 +1,109 @@ +package com.zeroone.star.prepayment.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 银行账户 + *

+ * + * @author Kong + * @since 2023-02-17 + */ +@Getter +@Setter +@TableName("bas_bank_account") +public class BasBankAccount implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 账号 + */ + private String accountNo; + + /** + * 账户名称 + */ + private String name; + + /** + * 币种 + */ + private String currency; + + /** + * 初始余额 + */ + private BigDecimal initBal; + + /** + * 行号 + */ + private String bankNo; + + /** + * 银行地址 + */ + private String bankAddress; + + /** + * 账户管理员 + */ + private String manager; + + /** + * 备注 + */ + private String remark; + + /** + * 附件 + */ + private String attachment; + + /** + * 是否启用 + */ + private Integer isEnabled; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 版本 + */ + private Integer version; + + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/BasSupplier.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/BasSupplier.java new file mode 100644 index 000000000..182f80cea --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/BasSupplier.java @@ -0,0 +1,243 @@ +package com.zeroone.star.prepayment.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 供应商 + *

+ * + * @author Kong + * @since 2023-02-17 + */ +@Getter +@Setter +@TableName("bas_supplier") +public class BasSupplier implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 编码 + */ + private String code; + + /** + * 名称 + */ + private String name; + + /** + * 简称 + */ + private String shortName; + + /** + * 助记名 + */ + private String auxName; + + /** + * 供应商分类 + */ + private String supplierCategory; + + /** + * 供应商等级 + */ + private String supplierLevel; + + /** + * 纳税规模 + */ + private String taxScale; + + /** + * 所属总公司 + */ + private String headquarters; + + /** + * 所属地区 + */ + private String area; + + /** + * 业务区域 + */ + private String bizArea; + + /** + * 供应商地址 + */ + private String address; + + /** + * 供应商网站 + */ + private String website; + + /** + * 法人代表 + */ + private String legalPerson; + + /** + * 法人电话 + */ + private String legalPersonPhone; + + /** + * 财务信息联系人 + */ + private String financialContacts; + + /** + * 财务信息联系电话 + */ + private String financialPhone; + + /** + * 开票信息单位名称 + */ + private String invoiceCompany; + + /** + * 开票信息税号 + */ + private String invoiceTaxCode; + + /** + * 开票信息开户行 + */ + private String invoiceBankName; + + /** + * 开票信息行号 + */ + private String invoiceBankCode; + + /** + * 开票信息账号 + */ + private String invoiceAccount; + + /** + * 开票信息联系电话 + */ + private String invoicePhone; + + /** + * 开票地址 + */ + private String invoiceAddress; + + /** + * 办款资料单位名称 + */ + private String receiptCompany; + + /** + * 办款资料开户行 + */ + private String receiptBankName; + + /** + * 办款资料行号 + */ + private String receiptBankCode; + + /** + * 办款资料账号 + */ + private String receiptAccount; + + /** + * 收件信息收件人 + */ + private String recvName; + + /** + * 收件信息联系电话 + */ + private String recvPhone; + + /** + * 收件信息传真 + */ + private String recvFax; + + /** + * 收件信息Email + */ + private String recvEmail; + + /** + * 收件信息地址 + */ + private String recvAddress; + + /** + * 收件信息邮编 + */ + private String recvPostcode; + + /** + * 附件 + */ + private String attachment; + + /** + * 启用 + */ + private Integer isEnabled; + + /** + * 备选供应商 + */ + private String alterSuppliers; + + /** + * 备注 + */ + private String remark; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 版本 + */ + private Integer version; + + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/FinPayment.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/FinPayment.java new file mode 100644 index 000000000..20741a5a9 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/FinPayment.java @@ -0,0 +1,216 @@ +package com.zeroone.star.prepayment.entity; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.baomidou.mybatisplus.annotation.*; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +import com.zeroone.star.project.utils.easyExcel.converters.LocalDateConverter; +import com.zeroone.star.project.utils.easyExcel.converters.LocalDateTimeConverter; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 付款单 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +@Getter +@Setter +@TableName("fin_payment") +public class FinPayment implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(type = IdType.ASSIGN_ID) + @ExcelProperty("id") + private String id; + + /** + * 单据编号 + */ + @ExcelProperty("bill_no") + private String billNo; + + /** + * 单据日期 + */ + @ExcelProperty(value = "bill_date", converter = LocalDateConverter.class) + private LocalDate billDate; + + /** + * 源单类型 + */ + @ExcelProperty("src_bill_type") + private String srcBillType; + + /** + * 源单id + */ + @ExcelProperty("src_bill_id") + private String srcBillId; + + /** + * 源单号 + */ + @ExcelProperty("src_no") + private String srcNo; + + /** + * 单据主题 + */ + @ExcelProperty("subject") + private String subject; + + /** + * 是否红字 + */ + @ExcelProperty("is_rubric") + private Integer isRubric; + + /** + * 付款类型 + */ + @ExcelProperty("payment_type") + private String paymentType; + + /** + * 供应商 + */ + @ExcelProperty("supplier_id") + private String supplierId; + + /** + * 金额 + */ + @ExcelProperty("amt") + private BigDecimal amt; + + /** + * 已核销金额 + */ + @ExcelProperty("checked_amt") + private BigDecimal checkedAmt; + + /** + * 附件 + */ + @ExcelProperty("attachment") + private String attachment; + + /** + * 备注 + */ + @ExcelProperty("remark") + private String remark; + + /** + * 是否自动单据 + */ + @ExcelProperty("is_auto") + private Integer isAuto; + + /** + * 处理状态 + */ + @ExcelProperty("bill_stage") + private String billStage; + + /** + * 审核人 + */ + @ExcelProperty("approver") + private String approver; + + /** + * 流程 + */ + @ExcelProperty("bpmi_instance_id") + private String bpmiInstanceId; + + /** + * 核批结果类型 + */ + @ExcelProperty("approval_result_type") + private String approvalResultType; + + /** + * 核批意见 + */ + @ExcelProperty("approval_mark") + private String approvalRemark; + + /** + * 是否通过 + */ + @ExcelProperty("is_effective") + private Integer isEffective; + + /** + * 生效时间 + */ + @ExcelProperty("effective_time") + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime effectiveTime; + + /** + * 已关闭 + */ + @ExcelProperty("is_closed") + private Integer isClosed; + + /** + * 是否作废 + */ + @ExcelProperty("is_voided") + private Boolean isVoided; + + /** + * 创建时间 + */ + @ExcelProperty(value = "create_time", converter = LocalDateTimeConverter.class) + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 创建人 + */ + @ExcelProperty("create_by") + private String createBy; + + /** + * 创建部门 + */ + @ExcelProperty("sys_org_code") + private String sysOrgCode; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.UPDATE) + @ExcelProperty(value = "update_time", converter = LocalDateTimeConverter.class) + private LocalDateTime updateTime; + + /** + * 修改人 + */ + @ExcelProperty("update_by") + private String updateBy; + + /** + * 版本 + */ + @ExcelProperty("version") + private Integer version; + + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/FinPaymentEntry.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/FinPaymentEntry.java new file mode 100644 index 000000000..ef8a159db --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/FinPaymentEntry.java @@ -0,0 +1,100 @@ +package com.zeroone.star.prepayment.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 付款单明细 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +@Getter +@Setter +@TableName("fin_payment_entry") +public class FinPaymentEntry implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(type = IdType.ASSIGN_ID) + private String id; + + /** + * 主表 + */ + private String mid; + + /** + * 单据编号 + */ + private String billNo; + + /** + * 分录号 + */ + private Integer entryNo; + + /** + * 源单类型 + */ + private String srcBillType; + + private String srcBillId; + + /** + * 源单分录id + */ + private String srcEntryId; + + /** + * 源单分录号 + */ + private String srcNo; + + /** + * 结算方式 + */ + private String settleMethod; + + /** + * 资金账户 + */ + private String bankAccountId; + + /** + * 金额 + */ + private BigDecimal amt; + + /** + * 备注 + */ + private String remark; + + /** + * 自定义1 + */ + private String custom1; + + /** + * 自定义2 + */ + private String custom2; + + /** + * 版本 + */ + private Integer version; + + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/FinPaymentReq.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/FinPaymentReq.java new file mode 100644 index 000000000..67e8e5525 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/FinPaymentReq.java @@ -0,0 +1,191 @@ +package com.zeroone.star.prepayment.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 付款申请单 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +@Getter +@Setter +@TableName("fin_payment_req") +public class FinPaymentReq implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单据编号 + */ + private String billNo; + + /** + * 单据日期 + */ + private LocalDate billDate; + + /** + * 源单类型 + */ + private String srcBillType; + + /** + * 源单id + */ + private String srcBillId; + + /** + * 源单号 + */ + private String srcNo; + + /** + * 单据主题 + */ + private String subject; + + /** + * 是否红字 + */ + private Integer isRubric; + + /** + * 付款类型 + */ + private String paymentType; + + /** + * 供应商 + */ + private String supplierId; + + /** + * 业务部门 + */ + private String opDept; + + /** + * 业务员 + */ + private String operator; + + /** + * 申请金额 + */ + private BigDecimal amt; + + /** + * 已付金额 + */ + private BigDecimal paidAmt; + + /** + * 附件 + */ + private String attachment; + + /** + * 备注 + */ + private String remark; + + /** + * 是否自动生成 + */ + private Integer isAuto; + + /** + * 单据阶段 + */ + private String billStage; + + /** + * 审核人 + */ + private String approver; + + /** + * 审批实例id + */ + private String bpmiInstanceId; + + /** + * 核批结果类型 + */ + private String approvalResultType; + + /** + * 核批意见 + */ + private String approvalRemark; + + /** + * 是否生效 + */ + private Integer isEffective; + + /** + * 生效时间 + */ + private LocalDateTime effectiveTime; + + /** + * 已关闭 + */ + private Integer isClosed; + + /** + * 是否作废 + */ + private Integer isVoided; + + /** + * 创建部门 + */ + private String sysOrgCode; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.UPDATE) + private LocalDateTime updateTime; + + /** + * 版本 + */ + private Integer version; + + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/FinPaymentReqEntry.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/FinPaymentReqEntry.java new file mode 100644 index 000000000..171e9adcf --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/FinPaymentReqEntry.java @@ -0,0 +1,95 @@ +package com.zeroone.star.prepayment.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 付款申请单明细 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +@Getter +@Setter +@TableName("fin_payment_req_entry") +public class FinPaymentReqEntry implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 主表 + */ + private String mid; + + /** + * 单据号 + */ + private String billNo; + + /** + * 分录号 + */ + private Integer entryNo; + + /** + * 源单类型 + */ + private String srcBillType; + + /** + * srcBillId + */ + private String srcBillId; + + /** + * 源单分录id + */ + private String srcEntryId; + + /** + * 源单分录号 + */ + private String srcNo; + + /** + * 申请金额 + */ + private BigDecimal amt; + + /** + * 已付金额 + */ + private BigDecimal paidAmt; + + /** + * 备注 + */ + private String remark; + + /** + * 自定义1 + */ + private String custom1; + + /** + * 自定义2 + */ + private String custom2; + + /** + * 版本 + */ + private Integer version; + + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/PurOrder.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/PurOrder.java new file mode 100644 index 000000000..c3b3ea771 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/PurOrder.java @@ -0,0 +1,294 @@ +package com.zeroone.star.prepayment.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 采购订单 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +@Getter +@Setter +@TableName("pur_order") +public class PurOrder implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 单据编号 + */ + private String billNo; + + /** + * 单据日期 + */ + private LocalDate billDate; + + /** + * 源单类型 + */ + private String srcBillType; + + /** + * 源单id + */ + private String srcBillId; + + /** + * 源单号 + */ + private String srcNo; + + private String subject; + + /** + * 是否红字 + */ + private Integer isRubric; + + /** + * 采购类型 + */ + private String purType; + + /** + * 供应商 + */ + private String supplierId; + + /** + * 联系人 + */ + private String contact; + + /** + * 联系电话 + */ + private String phone; + + /** + * 传真 + */ + private String fax; + + /** + * 电子邮件 + */ + private String email; + + private String opDept; + + /** + * 业务员 + */ + private String operator; + + /** + * 交货方式 + */ + private String deliveryMethod; + + /** + * 交货地点 + */ + private String deliveryPlace; + + /** + * 交货日期 + */ + private LocalDateTime deliveryTime; + + /** + * 运输方式 + */ + private String transportMethod; + + /** + * 付款方式 + */ + private String paymentMethod; + + /** + * 结算方式 + */ + private String settleMethod; + + /** + * 结算日期 + */ + private LocalDate settleTime; + + /** + * 开票方式 + */ + private String invoiceMethod; + + /** + * 发票类型 + */ + private String invoiceType; + + /** + * 外币币种 + */ + private String currency; + + /** + * 汇率 + */ + private BigDecimal exchangeRate; + + /** + * 数量 + */ + private BigDecimal qty; + + /** + * 金额 + */ + private BigDecimal amt; + + /** + * 预付款余额 + */ + private BigDecimal prepaymentBal; + + /** + * 结算数量 + */ + private BigDecimal settleQty; + + /** + * 结算金额 + */ + private BigDecimal settleAmt; + + /** + * 已入库数量 + */ + private Double inQty; + + /** + * 已入库成本 + */ + private BigDecimal inCost; + + /** + * 已结算金额 + */ + private BigDecimal settledAmt; + + /** + * 已开票金额 + */ + private BigDecimal invoicedAmt; + + /** + * 附件 + */ + private String attachment; + + /** + * 备注 + */ + private String remark; + + /** + * 是否自动生成 + */ + private Integer isAuto; + + /** + * 单据阶段 + */ + private String billStage; + + /** + * 审核人 + */ + private String approver; + + /** + * 审批实例id + */ + private String bpmiInstanceId; + + /** + * 核批结果类型 + */ + private String approvalResultType; + + /** + * 核批意见 + */ + private String approvalRemark; + + /** + * 是否生效 + */ + private Integer isEffective; + + /** + * 生效时间 + */ + private LocalDateTime effectiveTime; + + /** + * 已关闭 + */ + private Integer isClosed; + + /** + * 是否作废 + */ + private Integer isVoided; + + /** + * 创建部门 + */ + private String sysOrgCode; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 修改人 + */ + private String updateBy; + + /** + * 修改时间 + */ + private LocalDateTime updateTime; + + /** + * 版本 + */ + private Integer version; + + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/PurOrderEntry.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/PurOrderEntry.java new file mode 100644 index 000000000..2fa10732a --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/PurOrderEntry.java @@ -0,0 +1,155 @@ +package com.zeroone.star.prepayment.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.math.BigDecimal; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 采购订单明细 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +@Getter +@Setter +@TableName("pur_order_entry") +public class PurOrderEntry implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 主表 + */ + private String mid; + + /** + * 单据号 + */ + private String billNo; + + /** + * 分录号 + */ + private Integer entryNo; + + /** + * 源单类型 + */ + private String srcBillType; + + /** + * srcBillId + */ + private String srcBillId; + + /** + * 源单分录id + */ + private String srcEntryId; + + /** + * 源单分录号 + */ + private String srcNo; + + /** + * 物料 + */ + private String materialId; + + /** + * 计量单位 + */ + private String unitId; + + /** + * 数量 + */ + private BigDecimal qty; + + /** + * 税率% + */ + private BigDecimal taxRate; + + /** + * 含税单价 + */ + private BigDecimal price; + + /** + * 折扣率% + */ + private BigDecimal discountRate; + + /** + * 税额 + */ + private BigDecimal tax; + + /** + * 含税金额 + */ + private BigDecimal amt; + + /** + * 已入库数量 + */ + private BigDecimal inQty; + + /** + * 已入库成本 + */ + private BigDecimal inCost; + + /** + * 结算数量 + */ + private BigDecimal settleQty; + + /** + * 结算金额 + */ + private BigDecimal settleAmt; + + /** + * 已开票数量 + */ + private BigDecimal invoicedQty; + + /** + * 已开票金额 + */ + private BigDecimal invoicedAmt; + + /** + * 备注 + */ + private String remark; + + /** + * 自定义1 + */ + private String custom1; + + /** + * 自定义2 + */ + private String custom2; + + /** + * 版本 + */ + private Integer version; + + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/SysDepart.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/SysDepart.java new file mode 100644 index 000000000..c6dd65f09 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/SysDepart.java @@ -0,0 +1,134 @@ +package com.zeroone.star.prepayment.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; + +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 组织机构表 + *

+ * + * @author Kong + * @since 2023-02-17 + */ +@Data +@TableName("sys_depart") +public class SysDepart implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private String id; + + /** + * 父机构ID + */ + private String parentId; + + /** + * 机构/部门名称 + */ + private String departName; + + /** + * 英文名 + */ + private String departNameEn; + + /** + * 缩写 + */ + private String departNameAbbr; + + /** + * 排序 + */ + private Integer departOrder; + + /** + * 描述 + */ + private String description; + + /** + * 机构类别 1组织机构,2岗位 + */ + private String orgCategory; + + /** + * 机构类型 1一级部门 2子部门 + */ + private String orgType; + + /** + * 机构编码 + */ + private String orgCode; + + /** + * 手机号 + */ + private String mobile; + + /** + * 传真 + */ + private String fax; + + /** + * 地址 + */ + private String address; + + /** + * 备注 + */ + private String memo; + + /** + * 状态(1启用,0不启用) + */ + private String status; + + /** + * 删除状态(0,正常,1已删除) + */ + private String delFlag; + + /** + * 对接企业微信的ID + */ + private String qywxIdentifier; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建日期 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 更新人 + */ + private String updateBy; + + /** + * 更新日期 + */ + private LocalDateTime updateTime; + + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/SysUser.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/SysUser.java new file mode 100644 index 000000000..7fca91ed6 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/entity/SysUser.java @@ -0,0 +1,153 @@ +package com.zeroone.star.prepayment.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.time.LocalDateTime; +import lombok.Getter; +import lombok.Setter; + +/** + *

+ * 用户表 + *

+ * + * @author Kong + * @since 2023-02-17 + */ +@Getter +@Setter +@TableName("sys_user") +public class SysUser implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + private String id; + + /** + * 登录账号 + */ + private String username; + + /** + * 真实姓名 + */ + private String realname; + + /** + * 密码 + */ + private String password; + + /** + * md5密码盐 + */ + private String salt; + + /** + * 头像 + */ + private String avatar; + + /** + * 生日 + */ + private LocalDateTime birthday; + + /** + * 性别(0-默认未知,1-男,2-女) + */ + private Boolean sex; + + /** + * 电子邮件 + */ + private String email; + + /** + * 电话 + */ + private String phone; + + /** + * 登录会话的机构编码 + */ + private String orgCode; + + /** + * 性别(1-正常,2-冻结) + */ + private Boolean status; + + /** + * 删除状态(0-正常,1-已删除) + */ + private Boolean delFlag; + + /** + * 同步工作流引擎(1-同步,0-不同步) + */ + private Boolean activitiSync; + + /** + * 工号,唯一键 + */ + private String workNo; + + /** + * 职务,关联职务表 + */ + private String post; + + /** + * 座机号 + */ + private String telephone; + + /** + * 创建人 + */ + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 更新人 + */ + private String updateBy; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 身份(1普通成员 2上级) + */ + private Boolean userIdentity; + + /** + * 负责部门 + */ + private String departIds; + + /** + * 多租户标识 + */ + private String relTenantIds; + + /** + * 设备ID + */ + private String clientId; + + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/handler/MyMetaObjectHandler.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/handler/MyMetaObjectHandler.java new file mode 100644 index 000000000..559f0e523 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/handler/MyMetaObjectHandler.java @@ -0,0 +1,22 @@ +package com.zeroone.star.prepayment.handler; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.Date; + +@Component +public class MyMetaObjectHandler implements MetaObjectHandler { + @Override + public void insertFill(MetaObject metaObject) { + this.setFieldValByName("createTime", LocalDateTime.now(), metaObject); + this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject); + } + + @Override + public void updateFill(MetaObject metaObject) { + this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject); + } +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/BasBankAccountMapper.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/BasBankAccountMapper.java new file mode 100644 index 000000000..dd3576c42 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/BasBankAccountMapper.java @@ -0,0 +1,18 @@ +package com.zeroone.star.prepayment.mapper; + +import com.zeroone.star.prepayment.entity.BasBankAccount; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 银行账户 Mapper 接口 + *

+ * + * @author Kong + * @since 2023-02-17 + */ +@Mapper +public interface BasBankAccountMapper extends BaseMapper { + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/BasSupplierMapper.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/BasSupplierMapper.java new file mode 100644 index 000000000..c71919f45 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/BasSupplierMapper.java @@ -0,0 +1,18 @@ +package com.zeroone.star.prepayment.mapper; + +import com.zeroone.star.prepayment.entity.BasSupplier; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 供应商 Mapper 接口 + *

+ * + * @author Kong + * @since 2023-02-17 + */ +@Mapper +public interface BasSupplierMapper extends BaseMapper { + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/FinPaymentEntryMapper.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/FinPaymentEntryMapper.java new file mode 100644 index 000000000..183041065 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/FinPaymentEntryMapper.java @@ -0,0 +1,18 @@ +package com.zeroone.star.prepayment.mapper; + +import com.zeroone.star.prepayment.entity.FinPaymentEntry; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 付款单明细 Mapper 接口 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +@Mapper +public interface FinPaymentEntryMapper extends BaseMapper { + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/FinPaymentMapper.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/FinPaymentMapper.java new file mode 100644 index 000000000..ea33197f5 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/FinPaymentMapper.java @@ -0,0 +1,21 @@ +package com.zeroone.star.prepayment.mapper; + +import com.zeroone.star.prepayment.entity.FinPayment; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + *

+ * 付款单 Mapper 接口 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +@Mapper +public interface FinPaymentMapper extends BaseMapper { + + void addBatch(List paymentReq); +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/FinPaymentReqEntryMapper.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/FinPaymentReqEntryMapper.java new file mode 100644 index 000000000..7572790af --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/FinPaymentReqEntryMapper.java @@ -0,0 +1,18 @@ +package com.zeroone.star.prepayment.mapper; + +import com.zeroone.star.prepayment.entity.FinPaymentReqEntry; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 付款申请单明细 Mapper 接口 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +@Mapper +public interface FinPaymentReqEntryMapper extends BaseMapper { + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/FinPaymentReqMapper.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/FinPaymentReqMapper.java new file mode 100644 index 000000000..487a13559 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/FinPaymentReqMapper.java @@ -0,0 +1,18 @@ +package com.zeroone.star.prepayment.mapper; + +import com.zeroone.star.prepayment.entity.FinPaymentReq; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 付款申请单 Mapper 接口 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +@Mapper +public interface FinPaymentReqMapper extends BaseMapper { + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/PurOrderEntryMapper.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/PurOrderEntryMapper.java new file mode 100644 index 000000000..b7b2bc7c6 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/PurOrderEntryMapper.java @@ -0,0 +1,18 @@ +package com.zeroone.star.prepayment.mapper; + +import com.zeroone.star.prepayment.entity.PurOrderEntry; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 采购订单明细 Mapper 接口 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +@Mapper +public interface PurOrderEntryMapper extends BaseMapper { + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/PurOrderMapper.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/PurOrderMapper.java new file mode 100644 index 000000000..ed22684cc --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/PurOrderMapper.java @@ -0,0 +1,18 @@ +package com.zeroone.star.prepayment.mapper; + +import com.zeroone.star.prepayment.entity.PurOrder; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 采购订单 Mapper 接口 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +@Mapper +public interface PurOrderMapper extends BaseMapper { + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/SysDepartMapper.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/SysDepartMapper.java new file mode 100644 index 000000000..1f4bbe096 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/SysDepartMapper.java @@ -0,0 +1,18 @@ +package com.zeroone.star.prepayment.mapper; + +import com.zeroone.star.prepayment.entity.SysDepart; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 组织机构表 Mapper 接口 + *

+ * + * @author Kong + * @since 2023-02-17 + */ +@Mapper +public interface SysDepartMapper extends BaseMapper { + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/SysUserMapper.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/SysUserMapper.java new file mode 100644 index 000000000..bf783e5e7 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/mapper/SysUserMapper.java @@ -0,0 +1,18 @@ +package com.zeroone.star.prepayment.mapper; + +import com.zeroone.star.prepayment.entity.SysUser; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 用户表 Mapper 接口 + *

+ * + * @author Kong + * @since 2023-02-17 + */ +@Mapper +public interface SysUserMapper extends BaseMapper { + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IBasBankAccountService.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IBasBankAccountService.java new file mode 100644 index 000000000..15e061396 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IBasBankAccountService.java @@ -0,0 +1,25 @@ +package com.zeroone.star.prepayment.service; + +import com.zeroone.star.prepayment.entity.BasBankAccount; +import com.baomidou.mybatisplus.extension.service.IService; +import com.zeroone.star.project.vo.prepayment.BasBankAccountVO; + +import java.util.List; + +/** + *

+ * 银行账户 服务类 + *

+ * + * @author Kong + * @since 2023-02-17 + */ +public interface IBasBankAccountService extends IService { + + /** + * 获取银行账户列表 + * @return BasBankAccountVO 银行账户显示对象 + * @author 空 + */ + public List getBasBankAccountList(); +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IBasSupplierService.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IBasSupplierService.java new file mode 100644 index 000000000..78c9fbd3b --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IBasSupplierService.java @@ -0,0 +1,25 @@ +package com.zeroone.star.prepayment.service; + +import com.zeroone.star.prepayment.entity.BasSupplier; +import com.baomidou.mybatisplus.extension.service.IService; +import com.zeroone.star.project.vo.prepayment.SupplierVO; + +import java.util.List; + +/** + *

+ * 供应商 服务类 + *

+ * + * @author Kong + * @since 2023-02-17 + */ +public interface IBasSupplierService extends IService { + + /** + * 获取供应商列表 + * @return SupplierVO 供应商显示对象 + * @author Kong + */ + public List getSupplierList(); +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IFinPaymentEntryService.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IFinPaymentEntryService.java new file mode 100644 index 000000000..e2c305272 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IFinPaymentEntryService.java @@ -0,0 +1,41 @@ +package com.zeroone.star.prepayment.service; +import com.zeroone.star.prepayment.entity.FinPaymentEntry; +import com.baomidou.mybatisplus.extension.service.IService; +import com.zeroone.star.project.components.user.UserDTO; +import com.zeroone.star.project.dto.prepayment.ModifyDTO; +import com.zeroone.star.project.dto.prepayment.PrepaymentDTO; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + *

+ * 付款单明细 服务类 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +@Component +public interface IFinPaymentEntryService extends IService { + + /** + * 修改付款单明细 + * author forever爱 + */ + boolean saveByBillNo(ModifyDTO modifyDTO); + + /** + * 插入 + * author kong + */ + int insert(PrepaymentDTO prepaymentDTO); + + /** + * 根据mid查询对应明细 + * @param mid 主表ID + * @param srcBillType 源单类型( FinPaymentEntry / PurOrder ) + * @return 查询结果 + */ + List listByMid(String mid, String srcBillType); +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IFinPaymentReqEntryService.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IFinPaymentReqEntryService.java new file mode 100644 index 000000000..3fa94351d --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IFinPaymentReqEntryService.java @@ -0,0 +1,15 @@ +package com.zeroone.star.prepayment.service; +import com.zeroone.star.prepayment.entity.FinPaymentReqEntry; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 付款申请单明细 服务类 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +public interface IFinPaymentReqEntryService extends IService { + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IFinPaymentReqService.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IFinPaymentReqService.java new file mode 100644 index 000000000..302a538ac --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IFinPaymentReqService.java @@ -0,0 +1,46 @@ +package com.zeroone.star.prepayment.service; +import com.baomidou.mybatisplus.extension.service.IService; +import com.zeroone.star.project.query.prepayment.FinPaymentReqQuery; +import com.zeroone.star.project.query.prepayment.PurchaseListQuery; +import com.zeroone.star.prepayment.entity.FinPaymentReq; +import com.zeroone.star.project.vo.PageVO; +import com.zeroone.star.project.vo.prepayment.FinPaymentReqVO; +import com.zeroone.star.project.vo.prepayment.ReqVO; +import org.springframework.stereotype.Component; + + +/** + *

+ * 付款申请单 服务类 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +@Component +public interface IFinPaymentReqService extends IService { + + /** + * 获取有申请采购单(分页) + * param purchaseListQuery + * return + */ + PageVO getFinPaymentReq(PurchaseListQuery purchaseListQuery); + + /** + * 根据明细的源单id查询对应申请单 + * @param srcBillId 源单id + * @return 查询结果 + */ + FinPaymentReq getBySrcBillId(String srcBillId); + + + /** + * FinPaymentReq 服务类 + * TODO FinPaymentReqVO需要更换,新建ReqVO + * author neigui + * since 2023-02-18 + */ + PageVO listFinPaymentReq(FinPaymentReqQuery query); + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IFinPaymentService.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IFinPaymentService.java new file mode 100644 index 000000000..eaab73c1d --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IFinPaymentService.java @@ -0,0 +1,112 @@ +package com.zeroone.star.prepayment.service; +import com.zeroone.star.prepayment.entity.FinPayment; +import com.baomidou.mybatisplus.extension.service.IService; +import com.zeroone.star.project.components.user.UserDTO; +import com.zeroone.star.project.dto.prepayment.AuditDTO; +import com.zeroone.star.project.dto.prepayment.ModifyDTO; +import com.zeroone.star.project.dto.prepayment.PrepaymentDTO; +import com.zeroone.star.project.query.prepayment.DocListQuery; +import com.zeroone.star.project.vo.JsonVO; +import com.zeroone.star.project.vo.PageVO; +import com.zeroone.star.project.vo.prepayment.DocListVO; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +/** + *

+ * 付款单 服务类 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +@Component +public interface IFinPaymentService extends IService { + + + /** + * 修改付款单 + * author forever爱 + */ + boolean updateByBillNo(ModifyDTO modifyDTO, UserDTO userDTO); + /** + * 审核采购预付单功能 + * param auditDTO 审核DTO + * return 查询结果 + * author forever爱 + */ + JsonVO auditById(AuditDTO auditDTO, UserDTO userDTO); + + /** + * 保存付款单 + * author forever爱 + */ + boolean saveByBillNo(ModifyDTO modifyDTO, UserDTO userDTO); + + /** + * 添加付款单 + * param prepaymentDTO + * return + * author KONG + */ + int insert(PrepaymentDTO prepaymentDTO, UserDTO userDTO); + + PageVO listAll(DocListQuery condition); + + /** + * 根据单据编号查询指定付款单 + * param billNo 单据编号 + * return 查询结果 + * author hzp + */ + FinPayment getByBillNo(String billNo); + + + /** + * 根据id查询付款单 + * author yuhang + */ + FinPayment selectById(String id); + + /** + * 关闭功能 + * author yuhang + */ + JsonVO closeById(String id,UserDTO userDTO); + + /** + * 反关闭功能 + * author yuhang + */ + JsonVO uncloseById(String id,UserDTO userDTO); + + /** + * 作废功能 + * author yuhang + */ + JsonVO voidById(String id,UserDTO userDTO); + + /** + * 导入 + * author neigui + */ + void importExcelOfPayment(MultipartFile file) throws Exception; + + /** + * 获取导出文件 + * return 返回响应对象 + * author 明破 + */ + ResponseEntity download(boolean isRequested); + + /** + * 获取导出链接 + * return 返回下载路径 + * author 明破 + */ + JsonVO downloadUrl(boolean isRequested); + +} + + diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IPrepaymentService.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IPrepaymentService.java new file mode 100644 index 000000000..e2d6b8aea --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IPrepaymentService.java @@ -0,0 +1,147 @@ +package com.zeroone.star.prepayment.service; + +import com.zeroone.star.project.components.user.UserDTO; +import com.zeroone.star.project.dto.prepayment.*; +import com.zeroone.star.project.query.prepayment.DocListQuery; +import com.zeroone.star.project.query.prepayment.PreDetQuery; +import com.zeroone.star.project.vo.JsonVO; +import com.zeroone.star.project.vo.PageVO; +import com.zeroone.star.project.vo.prepayment.*; +import org.springframework.http.ResponseEntity; +import org.springframework.web.multipart.MultipartFile; +import java.util.List; + +/** + * 付款单 服务类 + * author forever爱 + * since 2023-02-13 + */ +public interface IPrepaymentService { + /** + * 修改采购预付单功能 + * param modifyDTO 带明细表的收款单DTO + * return 查询结果 + * author forever爱 + */ + JsonVO modify(ModifyDTO modifyDTO, UserDTO userDTO); + + /** + * 审核采购预付单功能 + * param auditDTO 审核DTO + * return 查询结果 + * author forever爱 + */ + JsonVO auditById(AuditDTO auditDTO, UserDTO userDTO); + + /** + * 保存采购预付单功能 + * param ModifyDTO 保存DTO + * return 查询结果 + * author forever爱 + */ + JsonVO save(ModifyDTO modifyDTO, UserDTO userDTO); + + /** + * 单据列表查询 + * param condition 查询条件 + * return 查询结果 + * author husj + * version 1.0.0 + */ + PageVO queryAll(DocListQuery condition); + + + /** + * 通过单据编号查询数据-采购预付有申请 + * param condition 单据编号-查询条件 + * return 查询结果 + * author hzp + */ + JsonVO queryByBillHav(PreDetQuery condition); + + /** + *通过单据编号查询数据-采购预付无申请 + * param condition 单据编号-查询条件 + * return 查询结果 + * author hzp + */ + JsonVO queryByBillNo (PreDetQuery condition); + + /** + * 获取导出文件 + * return 返回响应对象 + * author 明破 + */ + ResponseEntity download(); + + /** + * 获取导出链接 + * return 返回下载路径 + * author 明破 + */ + JsonVO downloadUrl(); + + /** + * 删除预付单功能 + * param deleteDTO 包含付款单id + * return 删除结果 + * author 出运费 + */ + JsonVO deleteById(DeleteDTO deleteDTO) throws Exception; + + /** + * 采购预付款操作 + * param prepaymentDTO + * return + * author 空 + */ + JsonVO prepay(PrepaymentDTO prepaymentDTO,UserDTO userDTO); + + /** + * 获取供应商列表 + * return 供应商列表 + * author 空 + */ + JsonVO> querySupplierList(); + +// /** +// * 获取采购项目清单(无申请) +// * param purchaseListQuery +// * return 采购项目清单 +// * author 空 +// */ +// public JsonVO> queryForPurchaseRequisitions(PurchaseListQuery purchaseListQuery); + +// /** +// * 获取采购项目清单(有申请) +// * param purchaseListQuery +// * return 采购项目清单 +// * author 空 +// */ +// public JsonVO> queryForAppliedPurchaseRequisitions(PurchaseListQuery purchaseListQuery); + + /** + * 导入功能 + * author 内鬼 + */ + JsonVO> queryAllByBillNo(String billNo); + JsonVO excelImport(MultipartFile file); + + /** + * 修改状态——关闭 + * author yu-hang + */ + JsonVO closeById(String id,UserDTO userDTO); + + /** + * 修改状态——反关闭 + * author yu-hang + */ + JsonVO uncloseById(String id,UserDTO userDTO); + + /** + * 修改状态——作废 + * author yu-hang + */ + JsonVO voidById(String id,UserDTO userDTO); +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IPurOrderEntryService.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IPurOrderEntryService.java new file mode 100644 index 000000000..748335497 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IPurOrderEntryService.java @@ -0,0 +1,16 @@ +package com.zeroone.star.prepayment.service; + +import com.zeroone.star.prepayment.entity.PurOrderEntry; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 采购订单明细 服务类 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +public interface IPurOrderEntryService extends IService { + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IPurOrderService.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IPurOrderService.java new file mode 100644 index 000000000..dd70610d9 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/IPurOrderService.java @@ -0,0 +1,36 @@ +package com.zeroone.star.prepayment.service; +import com.zeroone.star.prepayment.entity.PurOrder; +import com.baomidou.mybatisplus.extension.service.IService; +import com.zeroone.star.project.query.prepayment.PurchaseListQuery; +import com.zeroone.star.project.vo.PageVO; +import com.zeroone.star.project.vo.prepayment.PurOrderVO; +import org.springframework.stereotype.Component; + +/** + *

+ * 采购订单 服务类 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +@Component +public interface IPurOrderService extends IService { + + /** + * 获取无申请采购单(分页) + * param condition 查询条件 + * return 无申请采购单 + * author KONG + */ + public PageVO getPurOrder(PurchaseListQuery condition); + + /** + * 根据明细的源单id查询对应采购单 + * param srcBillId 源单ID + * return 查询结果 + * author hzp + */ + PurOrder getBySrcBillId(String srcBillId); + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/ISysDepartService.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/ISysDepartService.java new file mode 100644 index 000000000..633559d60 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/ISysDepartService.java @@ -0,0 +1,25 @@ +package com.zeroone.star.prepayment.service; + +import com.zeroone.star.prepayment.entity.SysDepart; +import com.baomidou.mybatisplus.extension.service.IService; +import com.zeroone.star.project.vo.prepayment.SysDepartVO; + +import java.util.List; + +/** + *

+ * 组织机构表 服务类 + *

+ * + * @author Kong + * @since 2023-02-17 + */ +public interface ISysDepartService extends IService { + + /** + * 获取部门显示对象 + * @return SysDepart 部门显示对象 + * @author 空 + */ + public List getDeparts(); +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/ISysUserService.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/ISysUserService.java new file mode 100644 index 000000000..7498fb3fa --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/ISysUserService.java @@ -0,0 +1,26 @@ +package com.zeroone.star.prepayment.service; + +import com.zeroone.star.prepayment.entity.SysUser; +import com.baomidou.mybatisplus.extension.service.IService; +import com.zeroone.star.project.vo.prepayment.SysUserVO; + +import java.util.List; + +/** + *

+ * 用户表 服务类 + *

+ * + * @author Kong + * @since 2023-02-17 + */ +public interface ISysUserService extends IService { + + /** + * 获取用户列表 (用户名、真实姓名) + * @return SysUserVO 用户显示对象 + * @author Kong + */ + public List getSysUserList(); + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/BasBankAccountServiceImpl.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/BasBankAccountServiceImpl.java new file mode 100644 index 000000000..4e62ea35f --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/BasBankAccountServiceImpl.java @@ -0,0 +1,43 @@ +package com.zeroone.star.prepayment.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.zeroone.star.prepayment.entity.BasBankAccount; +import com.zeroone.star.prepayment.mapper.BasBankAccountMapper; +import com.zeroone.star.prepayment.service.IBasBankAccountService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.zeroone.star.project.vo.prepayment.BasBankAccountVO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + *

+ * 银行账户 服务实现类 + *

+ * + * @author Kong + * @since 2023-02-17 + */ +@Service +public class BasBankAccountServiceImpl extends ServiceImpl implements IBasBankAccountService { + + @Autowired + BasBankAccountMapper bankAccountMapper; + + @Override + public List getBasBankAccountList() { + QueryWrapper queryWrapper = new QueryWrapper<>(); + List basBankAccounts = bankAccountMapper.selectList(queryWrapper); + + //封装成vo + ArrayList basBankAccountVOS = new ArrayList<>(); + for (BasBankAccount bankAccount:basBankAccounts){ + BasBankAccountVO bankAccounttVO = new BasBankAccountVO(bankAccount.getId(),bankAccount.getAccountNo(),bankAccount.getAccountNo(),bankAccount.getAccountNo()); + basBankAccountVOS.add(bankAccounttVO); + } + + return basBankAccountVOS; + } +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/BasSupplierServiceImpl.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/BasSupplierServiceImpl.java new file mode 100644 index 000000000..29eb75a67 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/BasSupplierServiceImpl.java @@ -0,0 +1,41 @@ +package com.zeroone.star.prepayment.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.zeroone.star.prepayment.entity.BasSupplier; +import com.zeroone.star.prepayment.mapper.BasSupplierMapper; +import com.zeroone.star.prepayment.service.IBasSupplierService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.zeroone.star.project.vo.prepayment.SupplierVO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + *

+ * 供应商 服务实现类 + *

+ * + * @author Kong + * @since 2023-02-17 + */ +@Service +public class BasSupplierServiceImpl extends ServiceImpl implements IBasSupplierService { + + @Autowired + BasSupplierMapper supplierMapper; + + @Override + public List getSupplierList() { + QueryWrapper queryWrapper = new QueryWrapper<>(); + List suppliers = supplierMapper.selectList(queryWrapper); + + ArrayList supplierVOS = new ArrayList<>(); + for (BasSupplier supplier : suppliers){ + supplierVOS.add(new SupplierVO(supplier.getId(),supplier.getAuxName())) ; + } + + return supplierVOS; + } +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/FinPaymentEntryServiceImpl.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/FinPaymentEntryServiceImpl.java new file mode 100644 index 000000000..c8951c475 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/FinPaymentEntryServiceImpl.java @@ -0,0 +1,85 @@ +package com.zeroone.star.prepayment.service.impl; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.zeroone.star.prepayment.entity.FinPaymentEntry; +import com.zeroone.star.prepayment.mapper.FinPaymentEntryMapper; +import com.zeroone.star.prepayment.service.IFinPaymentEntryService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.zeroone.star.project.dto.prepayment.FinPaymentEntryDTO; +import com.zeroone.star.project.dto.prepayment.ModifyDTO; +import com.zeroone.star.project.dto.prepayment.PrepaymentDTO; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import java.util.List; +import java.util.Random; +import java.util.stream.Collectors; + +/** + *

+ * 付款单明细 服务实现类 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +@Service +public class FinPaymentEntryServiceImpl extends ServiceImpl implements IFinPaymentEntryService { + + + /** + * 保存付款单明细 + * author forever爱 + */ + @Override + public boolean saveByBillNo(ModifyDTO modifyDTO) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("bill_no", modifyDTO.getBillNo()); + baseMapper.delete(queryWrapper); + List entryDTOList = modifyDTO.getEntryDTOList(); + List finPaymentEntryList = entryDTOList.stream().map( + dto -> { + FinPaymentEntry entity = new FinPaymentEntry(); + BeanUtils.copyProperties(dto, entity); + return entity; + } + ).collect(Collectors.toList()); + return saveBatch(finPaymentEntryList); + } + + /** + * 添加 + * Author: Kong + */ + @Override + public int insert(PrepaymentDTO prepaymentDTO) { + //获取主表id TODO MP自动生成的ID如何获取 + String id1 = prepaymentDTO.getId(); + int res = 0; + for (FinPaymentEntryDTO finPaymentEntryDTO:prepaymentDTO.getFinPaymentEntryList()){ + //生成明细表id +// long timestamp2 = System.currentTimeMillis(); // 毫秒级时间戳 +// int randNum2 = new Random().nextInt(1000000000); // 生成9位随机数 +// String uniqueId2 = timestamp2 + String.format("%09d", randNum2); // 将时间戳和随机数拼接起来 +// String id2 = uniqueId2.substring(0, 19);// 截取前19位作为最终的唯一ID + FinPaymentEntry finPaymentEntry = new FinPaymentEntry(); + BeanUtils.copyProperties(finPaymentEntryDTO,finPaymentEntry); +// finPaymentEntry.setId(id2); + finPaymentEntry.setMid(id1);//将主表id放入mid + finPaymentEntry.setBillNo(prepaymentDTO.getBillNo());//获取单号 + res = baseMapper.insert(finPaymentEntry); + } + return res; + } + @Override + public List listByMid(String mid, String srcBillType) { + QueryWrapper FinEntryQueryWrapper = new QueryWrapper<>(); + FinEntryQueryWrapper.eq("mid",mid); + FinEntryQueryWrapper.like("src_bill_type",srcBillType); + List finPaymentEntries = baseMapper.selectList(FinEntryQueryWrapper); + if(finPaymentEntries!=null) + return finPaymentEntries; + return null; + } + +} + + diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/FinPaymentReqEntryServiceImpl.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/FinPaymentReqEntryServiceImpl.java new file mode 100644 index 000000000..40f249836 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/FinPaymentReqEntryServiceImpl.java @@ -0,0 +1,19 @@ +package com.zeroone.star.prepayment.service.impl; +import com.zeroone.star.prepayment.entity.FinPaymentReqEntry; +import com.zeroone.star.prepayment.mapper.FinPaymentReqEntryMapper; +import com.zeroone.star.prepayment.service.IFinPaymentReqEntryService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 付款申请单明细 服务实现类 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +@Service +public class FinPaymentReqEntryServiceImpl extends ServiceImpl implements IFinPaymentReqEntryService { + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/FinPaymentReqServiceImpl.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/FinPaymentReqServiceImpl.java new file mode 100644 index 000000000..ad9511cff --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/FinPaymentReqServiceImpl.java @@ -0,0 +1,77 @@ +package com.zeroone.star.prepayment.service.impl; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.zeroone.star.prepayment.entity.FinPaymentReq; +import com.zeroone.star.prepayment.mapper.FinPaymentReqMapper; +import com.zeroone.star.prepayment.service.IFinPaymentReqService; +import com.zeroone.star.project.query.prepayment.PurchaseListQuery; +import com.zeroone.star.project.vo.PageVO; +import com.zeroone.star.project.vo.prepayment.FinPaymentReqVO; +import com.zeroone.star.project.vo.prepayment.ReqVO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.zeroone.star.project.query.prepayment.FinPaymentReqQuery; +/** + * Author: Kong + */ + +@Service +public class FinPaymentReqServiceImpl extends ServiceImpl implements IFinPaymentReqService { + + @Autowired + FinPaymentReqMapper finPaymentReqMapper; + + @Override + public PageVO getFinPaymentReq(PurchaseListQuery condition) { + //分页对象 + Page page = new Page<>(condition.getPageIndex(),condition.getPageSize()); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("supplier_id",condition.getSelf_supplier_id()); + if (condition.getSelf_payment_type()!=null){ + wrapper.eq("payment_type",condition.getSelf_payment_type()); + } + if (condition.getSelf_is_closed()!=null){ + wrapper.eq("is_closed",condition.getSelf_payment_type()); + } + //执行分页查询 + Page res = finPaymentReqMapper.selectPage(page, wrapper); + return PageVO.create(res,FinPaymentReqVO.class); + } + + @Override + public FinPaymentReq getBySrcBillId(String srcBillId) { + QueryWrapper FinReqQueryWrapper = new QueryWrapper<>(); + FinReqQueryWrapper.eq("id",srcBillId); + FinPaymentReq finPaymentReq = baseMapper.selectOne(FinReqQueryWrapper); + if(finPaymentReq!=null) + return finPaymentReq; + return null; + } + @Override + public PageVO listFinPaymentReq(FinPaymentReqQuery query) { + // 构建分页对象 + Page paymentReqPage = new Page<>(query.getPageIndex(), query.getPageSize()); + // 构建查询条件 + QueryWrapper paymentReqQueryWrapper = new QueryWrapper<>(); + // 获取供应商id + String supplierId = query.getSupplierId(); +// if (StrUtil.isNotBlank(supplierId)) { +// paymentReqQueryWrapper.eq("supplier_id", supplierId); +// } + paymentReqQueryWrapper.eq("supplier_id", supplierId); + // 约束单据日期 +// LocalDate stDate = query.getStartDate(); +// LocalDate edDate = query.getEndDate(); +// if (stDate != null && edDate != null && stDate.isBefore(edDate)) { +// paymentReqQueryWrapper.between("billDate", stDate, edDate); +// } else if (stDate != null && edDate == null) { +// paymentReqQueryWrapper.gt("billDate", stDate); +// } else if (stDate == null && edDate != null) { +// paymentReqQueryWrapper.lt("billDate", edDate); +// } + // 执行分页查询 + Page resPage = baseMapper.selectPage(paymentReqPage, paymentReqQueryWrapper); + return PageVO.create(resPage, ReqVO.class); + } +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/FinPaymentServiceImpl.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/FinPaymentServiceImpl.java new file mode 100644 index 000000000..9243f73a2 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/FinPaymentServiceImpl.java @@ -0,0 +1,421 @@ +package com.zeroone.star.prepayment.service.impl; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.IdUtil; +import com.alibaba.excel.EasyExcel; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.zeroone.star.prepayment.entity.FinPayment; +import com.zeroone.star.prepayment.mapper.FinPaymentMapper; +import com.zeroone.star.prepayment.service.IFinPaymentService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.zeroone.star.project.components.user.UserDTO; +import com.zeroone.star.project.components.user.UserHolder; +import com.zeroone.star.project.dto.prepayment.AuditDTO; +import com.zeroone.star.project.dto.prepayment.ModifyDTO; +import com.zeroone.star.project.query.prepayment.DocListQuery; +import com.zeroone.star.project.utils.easyExcel.EasyExcelUtils; +import com.zeroone.star.project.vo.JsonVO; +import com.zeroone.star.project.vo.PageVO; +import com.zeroone.star.project.vo.prepayment.DocListVO; +import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import java.time.LocalDateTime; +import com.zeroone.star.project.dto.prepayment.PrepaymentDTO; +import org.springframework.beans.BeanUtils; +import org.springframework.web.multipart.MultipartFile; +import java.util.List; +import java.util.function.Consumer; +import cn.hutool.core.date.DateTime; +import com.zeroone.star.prepayment.entity.FinPaymentEntry; +import com.zeroone.star.prepayment.mapper.FinPaymentEntryMapper; +import com.zeroone.star.project.components.easyexcel.EasyExcelComponent; +import com.zeroone.star.project.components.fastdfs.FastDfsClientComponent; +import com.zeroone.star.project.components.fastdfs.FastDfsFileInfo; +import com.zeroone.star.project.query.prepayment.FinPaymentExportQuery; +import lombok.SneakyThrows; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import java.io.ByteArrayOutputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; + +/** + *

+ * 付款单 服务实现类 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +@Service +public class FinPaymentServiceImpl extends ServiceImpl implements IFinPaymentService { + + @Resource + FinPaymentMapper finPaymentMapper; + + /** + * 修改付款单 + * author forever爱 + */ + @Override + public boolean updateByBillNo(ModifyDTO modifyDTO, UserDTO userDTO) { + FinPayment finPayment = new FinPayment(); + BeanUtil.copyProperties(modifyDTO, finPayment); + finPayment.setUpdateBy(userDTO.getUsername()); + finPayment.setBillStage("14"); + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + updateWrapper.eq("bill_no", finPayment.getBillNo()); + return update(finPayment,updateWrapper); + } + + /** + * 审核采购预付单功能 + * param auditDTO 审核DTO + * return 查询结果 + * author forever爱 + */ + @Override + public JsonVO auditById(AuditDTO auditDTO, UserDTO userDTO) { + FinPayment finPayment = new FinPayment(); + BeanUtil.copyProperties(auditDTO, finPayment); + //审核生效时间、修改时间 +// finPayment.setUpdateTime(LocalDateTime.now()); +// finPayment.setEffectiveTime(LocalDateTime.now()); + //审核人、修改人信息 + finPayment.setApprover(userDTO.getUsername()); + finPayment.setUpdateBy(userDTO.getUsername()); + boolean flag = updateById(finPayment); + if (flag) { + return JsonVO.success("修改成功"); + } + return JsonVO.fail("修改失败"); + } + + /** + * 保存采购预付单功能 + * TODO 测试 + * billStage 12---编制中 + * param ModifyDTO 保存DTO + * return 查询结果 + * author forever爱 + */ + @Override + public boolean saveByBillNo(ModifyDTO modifyDTO, UserDTO userDTO) { + FinPayment finPayment = new FinPayment(); + BeanUtil.copyProperties(modifyDTO, finPayment); + finPayment.setUpdateBy(userDTO.getUsername()); + finPayment.setBillStage("12"); + //根据单据编号修改finpayment表 + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + updateWrapper.eq("bill_no", finPayment.getBillNo()); + return update(finPayment,updateWrapper); + } + + /** + * 添加采购预付单 + * Author: Kong + */ + @Override + public int insert(PrepaymentDTO prepaymentDTO, UserDTO userDTO){ + FinPayment finPayment = new FinPayment(); + BeanUtils.copyProperties(prepaymentDTO,finPayment); + //时间 +// finPayment.setCreateTime(LocalDateTime.now()); + //用户信息 + finPayment.setCreateBy(userDTO.getUsername()); + return finPaymentMapper.insert(finPayment); + } + + @Override + public PageVO listAll(DocListQuery condition) { + //构建分页对象 + Page finPaymentPage = new Page<>(condition.getPageIndex(),condition.getPageSize()); + //创建查询条件 + QueryWrapper finPaymentQueryWrapper = new QueryWrapper<>(); + //根据单据编号查询 + if (condition.getBillNo()!=null)finPaymentQueryWrapper.eq("bill_no",condition.getBillNo()); + //根据单据日期查询 + if(condition.getBillDateStart()!=null && condition.getBillDateEnd()!=null) + finPaymentQueryWrapper.between("bill_date",condition.getBillDateStart(),condition.getBillDateEnd()); + else if (condition.getBillDateStart()!=null) + finPaymentQueryWrapper.ge("bill_date",condition.getBillDateStart()); + else if(condition.getBillDateEnd()!=null) + finPaymentQueryWrapper.le("bill_date",condition.getBillDateEnd()); + //根据单据主题查询 + if (condition.getSubject()!=null)finPaymentQueryWrapper.like("subject",condition.getSubject()); + //根据供应商查询 + if (condition.getSupplierId()!=null)finPaymentQueryWrapper.eq("supplier_id",condition.getSupplierId()); + //根据处理状态查询 + if (condition.getBillStage()!=null)finPaymentQueryWrapper.eq("bill_stage",condition.getBillStage()); + //根据是否生效查询 + if (condition.getIsEffective()!=null)finPaymentQueryWrapper.eq("is_effective",condition.getIsEffective()); + //根据是否关闭查询 + if (condition.getIsClosed()!=null)finPaymentQueryWrapper.eq("is_closed",condition.getIsClosed()); + //根据是否作废查询 + if (condition.getIsVoided()!=null)finPaymentQueryWrapper.eq("is_voided",condition.getIsVoided()); + //根据付款类型查询(即2011是有申请,2010是无申请) + if (condition.getPaymentType()!=null)finPaymentQueryWrapper.eq("payment_type",condition.getPaymentType()); + //执行SQL + Page result = baseMapper.selectPage(finPaymentPage, finPaymentQueryWrapper); + return PageVO.create(result,DocListVO.class); + } + + /** + * ClassName FinPaymentServiceImpl + * Description IFinPaymentService服务类的实现 + * Author HZP + * Date 2023/2/18 21:48 + * Version 1.0 + **/ + @Override + public FinPayment getByBillNo(String billNo) { + QueryWrapper FinQueryWrapper = new QueryWrapper<>(); + FinQueryWrapper.eq("bill_no", billNo); + return baseMapper.selectOne(FinQueryWrapper); + } + + /** + * 根据id查询付款单 + * author yuhang + */ + @Override + public FinPayment selectById(String id) { + QueryWrapper FinQueryWrapper = new QueryWrapper<>(); + FinQueryWrapper.eq("id", id); + return baseMapper.selectOne(FinQueryWrapper); + } + + @Override + public JsonVO closeById(String id,UserDTO userDTO) { + FinPayment finPayment = selectById(id); + // 查询要关闭的单据信息 + if (finPayment == null) { + return JsonVO.fail("此单据不存在!"); + } + //单据阶段为执行中,才可以关闭 + if ("32".equals(finPayment.getBillStage())) { + finPayment.setId(id); + finPayment.setBillStage("33"); + finPayment.setIsClosed(1); + finPayment.setUpdateTime(LocalDateTime.now()); + finPayment.setUpdateBy(userDTO.getUsername()); + boolean flag = updateById(finPayment); + if (flag) { + return JsonVO.success("修改成功"); + } + return JsonVO.fail("修改失败"); + } + return JsonVO.fail("单据阶段错误!"); + } + + @Override + public JsonVO uncloseById(String id,UserDTO userDTO) { + FinPayment finPayment = selectById(id); + // 查询要关闭的单据信息 + if (finPayment == null) { + return JsonVO.fail("此单据不存在!"); + } + //单据阶段为执行止或者执行完,才可以关闭 + String billStage = finPayment.getBillStage(); + if ("33".equals(billStage) || "34".equals(billStage)) { + finPayment.setId(id); + finPayment.setBillStage("32"); + finPayment.setIsClosed(0); + finPayment.setUpdateTime(LocalDateTime.now()); + finPayment.setUpdateBy(userDTO.getUsername()); + boolean flag = updateById(finPayment); + if (flag) { + return JsonVO.success("修改成功"); + } + return JsonVO.fail("修改失败"); + } + return JsonVO.fail("单据阶段错误!"); + } + + @Override + public JsonVO voidById(String id,UserDTO userDTO) { + FinPayment finPayment = selectById(id); + // 查询要关闭的单据信息 + if (finPayment == null) { + return JsonVO.fail("此单据不存在!"); + } + //单据阶段为执行止或者执行完,才可以关闭 + String billStage = finPayment.getBillStage(); + if ("33".equals(billStage) || "34".equals(billStage)) { + return JsonVO.fail("单据阶段错误!"); + } + finPayment.setId(id); + finPayment.setIsVoided(true); + finPayment.setUpdateTime(LocalDateTime.now()); + finPayment.setUpdateBy(userDTO.getUsername()); + boolean flag = updateById(finPayment); + if (flag) { + return JsonVO.success("修改成功"); + } + return JsonVO.fail("修改失败"); + } + + @Resource + EasyExcelComponent excel; + @Resource + FastDfsClientComponent dfsClient; + @Value("${fastdfs.nginx-servers}") + private String serverUrl; + @Resource + FinPaymentEntryMapper paymentEntryMapper; + @Resource + FinPaymentMapper paymentMapper; + + @Override + public void importExcelOfPayment(MultipartFile file) throws Exception { + EasyExcel.read(file.getInputStream(), FinPayment.class, EasyExcelUtils.getListener(this.process(), 2)).sheet().doRead(); + } + + + /** + * 导出获取无申请采购预付表 + * + * @return 无申请带有明细信息的采购预付信息列表 + */ + private List fetchExportFinPayment(boolean isRequested) { + + // 获取主表数据 + List allFinPayments; + QueryWrapper finPaymentQueryWrapper = new QueryWrapper<>(); + if (isRequested) { + finPaymentQueryWrapper.eq("payment_type", 2011); + } else { + finPaymentQueryWrapper.eq("payment_type", 2010); + } + allFinPayments = finPaymentMapper.selectList(finPaymentQueryWrapper); + + // 初始化最终结果列表及明细查询条件 + List results = new ArrayList<>(); + QueryWrapper finPaymentEntryQueryWrapper = new QueryWrapper<>(); + + // 装填最终结果数据 + for (FinPayment nowFinPayment : allFinPayments) { + + // 创建一个导出对象准备存储一行数据 + FinPaymentExportQuery temp = new FinPaymentExportQuery(); + // 将查询获取到的主表属性对应拷贝到导出实体类的属性 + BeanUtils.copyProperties(nowFinPayment, temp); + // 对应原始数据修改显示信息 + if (isRequested) { + temp.setIsRequested("采购预付(有申请)"); + } else { + temp.setIsRequested("采购预付(无申请)"); + } + temp.setIsEffective(nowFinPayment.getIsEffective() == 1 ? "是" : "否"); + temp.setIsAuto(nowFinPayment.getIsAuto() == 1 ? "是" : "否"); + temp.setIsVoided(nowFinPayment.getIsVoided() ? "是" : "否"); + temp.setIsRubric(nowFinPayment.getIsRubric() == 1 ? "是" : "否"); + temp.setIsClosed(nowFinPayment.getIsClosed() == 1 ? "是" : "否"); + + + // 构造明细表查询条件 + finPaymentEntryQueryWrapper.eq("mid", nowFinPayment.getId()); + // 查询明细表数据 + List finPaymentEntryList = paymentEntryMapper.selectList(finPaymentEntryQueryWrapper); + + // 清空查询条件避免重复添加多个条件 + finPaymentEntryQueryWrapper.clear(); + + // 将查询到的明细表属性对应拷贝到导出实体类(多条)并将其添加到最终结果列表中 + for (FinPaymentEntry entryTemp : finPaymentEntryList) { + BeanUtils.copyProperties(entryTemp, temp); + temp.setEid(entryTemp.getId()); + temp.setMid(entryTemp.getMid()); + temp.setEBillNo(entryTemp.getBillNo()); + temp.setESrcBillType(entryTemp.getSrcBillType()); + temp.setESrcNo(entryTemp.getSrcNo()); + temp.setEAmt(entryTemp.getAmt()); + temp.setERemark(entryTemp.getRemark()); + temp.setEVersion(entryTemp.getVersion()); + results.add(temp); + } + } + + return results; + } + + /** + * 获取导出文件 + * + * @param isRequested 获取需要导出的信息类别(有申请/无申请?) + * @return 导出报表文件 + */ + @SneakyThrows + @Override + public ResponseEntity download(boolean isRequested) { + + // 获取数据,参数控制是否有申请 + List results = fetchExportFinPayment(isRequested); + + // 导出Excel + ByteArrayOutputStream out = new ByteArrayOutputStream(); + excel.export("采购预付单信息", out, FinPaymentExportQuery.class, results); + // 创建响应头 + HttpHeaders headers = new HttpHeaders(); + // 构建下载文件名称 + String fileName = "fin_payment_" + DateTime.now().toString("yyyyMMddHHmmssS") + ".xlsx"; + fileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1); + headers.setContentDispositionFormData("attachment", fileName); + headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); + ResponseEntity result = new ResponseEntity<>(out.toByteArray(), headers, HttpStatus.CREATED); + out.close(); + return result; + + } + + @SneakyThrows + @Override + public JsonVO downloadUrl(boolean isRequested) { + + // 获取数据,参数控制是否有申请 + List results = fetchExportFinPayment(isRequested); + + // 导出Excel + ByteArrayOutputStream out = new ByteArrayOutputStream(); + excel.export("PaymentNoRequest", out, FinPaymentExportQuery.class, results); + // 上传到fastdfs + String suffix = "xlsx"; + FastDfsFileInfo result = dfsClient.uploadFile(out.toByteArray(), suffix); + //关闭输出流 + out.close(); + // 处理传递结果 + if (result == null) { + return JsonVO.fail("文件上传失败"); + } + // 拼接上下文地址 + String downloadUrl = dfsClient.fetchUrl(result, serverUrl, true); + + return JsonVO.success(downloadUrl); + } + + // 用于获取当前登录的用户信息 + @Resource + UserHolder userHolder; + /** + * 返回一个接口实现 + */ + public Consumer> process() { + return payments -> { + for (FinPayment payment : payments) { + payment.setId(IdUtil.getSnowflake().nextIdStr()); + payment.setCreateTime(LocalDateTime.now()); + try { + UserDTO currentUser = userHolder.getCurrentUser(); + payment.setCreateBy(currentUser.getUsername()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + paymentMapper.addBatch(payments); + }; + } +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/PrepaymentServiceImpl.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/PrepaymentServiceImpl.java new file mode 100644 index 000000000..98d90ab5e --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/PrepaymentServiceImpl.java @@ -0,0 +1,296 @@ +package com.zeroone.star.prepayment.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.zeroone.star.prepayment.entity.FinPayment; +import com.zeroone.star.prepayment.entity.FinPaymentEntry; +import com.zeroone.star.prepayment.mapper.FinPaymentEntryMapper; +import com.zeroone.star.prepayment.mapper.FinPaymentMapper; +import com.zeroone.star.prepayment.service.IFinPaymentEntryService; +import com.zeroone.star.prepayment.service.IFinPaymentReqService; +import com.zeroone.star.prepayment.service.IFinPaymentService; +import com.zeroone.star.prepayment.service.IPrepaymentService; +import com.zeroone.star.project.components.user.UserDTO; +import com.zeroone.star.project.dto.prepayment.*; +import com.zeroone.star.project.vo.JsonVO; +import com.zeroone.star.project.vo.PageVO; +import com.zeroone.star.project.vo.prepayment.*; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; +import javax.annotation.Resource; +import java.util.List; +import java.util.Random; +import com.zeroone.star.prepayment.entity.FinPaymentReq; +import com.zeroone.star.prepayment.entity.PurOrder; +import com.zeroone.star.prepayment.service.*; +import com.zeroone.star.project.query.prepayment.DocListQuery; +import com.zeroone.star.project.query.prepayment.PreDetQuery; +import java.util.ArrayList; + +/** + * 付款单 服务类 + * author forever爱 + * since 2023-02-13 + */ +@Service +public class PrepaymentServiceImpl extends ServiceImpl implements IPrepaymentService { + + @Resource + IFinPaymentService finPaymentService; + @Resource + IFinPaymentEntryService finPaymentEntryService; + @Resource + IFinPaymentReqService finPaymentReqService; + @Resource + IPurOrderService purOrderService; + @Resource + FinPaymentMapper finPaymentMapper; + @Resource + FinPaymentEntryMapper finPaymentEntryMapper; + + /** + * 修改采购预付单 + * 步骤: + * 1、finPayment表 数据修改 + * 2、finPaymentEntry表 数据修改 + * 3、判断是 + * 3、finPaymentEntry表 插入数据列表 + * 4、判断是否成功,如果成功 + * 5、如果失败 + * param modifyDTO 修改DTO + * return + * author forever爱 + */ + @Override + @Transactional + public JsonVO modify(ModifyDTO modifyDTO, UserDTO userDTO) { + //1、finPayment表中数据修改 + finPaymentService.updateByBillNo(modifyDTO,userDTO); + //2、finPaymentEntry表中数据修改 + boolean flag = finPaymentEntryService.saveByBillNo(modifyDTO); + //3、判断成功还是失败 + if (flag){ + return JsonVO.success("修改成功"); + } + return JsonVO.fail("修改失败"); + } + + /** + * 审核采购预付单功能 + * author forever爱 + * since 2023-02-13 + */ + @Override + public JsonVO auditById(AuditDTO auditDTO, UserDTO userDTO) { + return finPaymentService.auditById(auditDTO,userDTO); + } + + /** + * 保存采购预付单功能 + * author forever爱 + * since 2023-02-13 + */ + @Override + @Transactional + public JsonVO save(ModifyDTO modifyDTO, UserDTO userDTO) { + //1、finPayment表中数据修改 + finPaymentService.saveByBillNo(modifyDTO,userDTO); + //2、finPaymentEntry表中数据修改 + boolean flag = finPaymentEntryService.saveByBillNo(modifyDTO); + //3、判断成功还是失败 + if (flag){ + return JsonVO.success("保存成功"); + } + return JsonVO.fail("保存失败"); + } + + /** + * 单据分页查询 + * 采购预付(有申请):payment_type 2011 + * 采购预付(无申请):payment_type 2010 + * author husj + * since 2023-02-13 + */ + @Override + public PageVO queryAll(DocListQuery condition) { + return finPaymentService.listAll(condition); + } + + + /** + * 根据单据编号查询信息 + * author hzp + * since 2023-02-13 + */ + @Override + public JsonVO queryByBillHav(PreDetQuery condition) { + //根据查询条件里的单据编号去fin_payment查询对应付款单据 + FinPayment finPayment = finPaymentService.getByBillNo(condition.getBillNo()); + //根据fin_payment_entry表mid对应fin_payment中id查询对应明细,且对应fin_payment_req表 + List finPaymentEntrys = finPaymentEntryService.listByMid(finPayment.getId(),"FinPaymentReq"); + //判空 + if(finPaymentEntrys==null){ + DetHavVO detHavVO = new DetHavVO(); + BeanUtil.copyProperties(finPayment,detHavVO); + return JsonVO.success(detHavVO); + } + //明细单中的src_bill_id对应申请单中的id查询对应申请单 + FinPaymentReq finPaymentReq = finPaymentReqService.getBySrcBillId(finPaymentEntrys.get(0).getSrcBillId()); + //非空判断 + if(finPaymentReq==null){ + finPaymentReq=new FinPaymentReq(); + } + //构建明细单列表VO + List finPaymentEntryVOList = new ArrayList<>(); + for (FinPaymentEntry finPaymentEntry : finPaymentEntrys) { + FinPaymentEntryVO finPaymentEntryVO = new FinPaymentEntryVO(); + BeanUtil.copyProperties(finPaymentEntry,finPaymentEntryVO); + finPaymentEntryVO.setSrcBillNo(finPaymentReq.getBillNo()); + finPaymentEntryVOList.add(finPaymentEntryVO); + } + FinPaymentReqVO finPaymentReqVO = new FinPaymentReqVO(); + BeanUtil.copyProperties(finPaymentReq,finPaymentReqVO); + DetHavVO detHavVO = new DetHavVO(); + BeanUtil.copyProperties(finPayment,detHavVO); + detHavVO.setReq(finPaymentReqVO); + detHavVO.setListDetail(finPaymentEntryVOList); + return JsonVO.success(detHavVO); + } + + @Override + public JsonVO queryByBillNo(PreDetQuery condition) { + //根据查询条件里的单据编号去fin_payment查询对应付款单据 + FinPayment finPayment = finPaymentService.getByBillNo(condition.getBillNo()); + //根据fin_payment_entry表mid对应fin_payment中id查询对应明细,且对应Pur_Order + List finPaymentEntrys = finPaymentEntryService.listByMid(finPayment.getId(),"PurOrder"); + //判空 + if(finPaymentEntrys==null){ + DetNoVO detNoVO = new DetNoVO(); + BeanUtil.copyProperties(finPayment,detNoVO); + return JsonVO.success(detNoVO); + } + //明细单中的src_bill_id对应申请单中的id查询对应采购单 + PurOrder purOrder = purOrderService.getBySrcBillId(finPaymentEntrys.get(0).getSrcBillId()); + //非空判断 + if(purOrder==null){ + purOrder = new PurOrder(); + } + //构建明细单列表和返回VO + List finPaymentEntryVOList = new ArrayList<>(); + for (FinPaymentEntry finPaymentEntry : finPaymentEntrys) { + FinPaymentEntryVO finPaymentEntryVO = new FinPaymentEntryVO(); + BeanUtil.copyProperties(finPaymentEntry,finPaymentEntryVO); + finPaymentEntryVO.setSrcBillNo(purOrder.getBillNo()); + finPaymentEntryVOList.add(finPaymentEntryVO); + } + PurOrderVO purOrderVO = new PurOrderVO(); + BeanUtil.copyProperties(purOrder,purOrderVO); + DetNoVO detNoVO = new DetNoVO(); + BeanUtil.copyProperties(finPayment,detNoVO); + detNoVO.setListDetail(finPaymentEntryVOList); + detNoVO.setPurOrder(purOrderVO); + return JsonVO.success(detNoVO); + } + + @Override + public ResponseEntity download() { + return null; + } + + @Override + public JsonVO downloadUrl() { + return null; + } + + /** + * 删除功能 + * author 出运费 + */ + @Override + @Transactional + public JsonVO deleteById(DeleteDTO deleteDTO) { +// //(不清楚具体数字代表什么处理状态 所以这一步先省略) +// //获取处理状态 + String billStage = finPaymentMapper.selectById(deleteDTO.getId()).getBillStage(); + //只有编制中的可以删除 + if ("12".equals(billStage)){ + int i = finPaymentMapper.deleteById(deleteDTO.getId()); + int mid = finPaymentEntryMapper.delete(new QueryWrapper().eq("mid", deleteDTO.getId())); + if (i > 0&&mid > 0){ + return JsonVO.success("删除成功!"); + }else { + return JsonVO.fail("删除失败!"); + } + } + return JsonVO.fail("删除失败!"); + } + + /** + * 采购预付款操作 + * param prepaymentDTO + * return + * author 空 + */ + @Override + @Transactional + public JsonVO prepay(PrepaymentDTO prepaymentDTO,UserDTO userDTO) { + //生成19位id + long timestamp1 = System.currentTimeMillis(); // 毫秒级时间戳 + int randNum1 = new Random().nextInt(1000000000); // 生成9位随机数 + String uniqueId1 = timestamp1 + String.format("%09d", randNum1); // 将时间戳和随机数拼接起来 + String id1 = uniqueId1.substring(0, 19);// 截取前19位作为最终的唯一ID + prepaymentDTO.setId(id1); + finPaymentService.insert(prepaymentDTO,userDTO); + int res = finPaymentEntryService.insert(prepaymentDTO); + if (res == 1){ + return JsonVO.success("修改成功"); + } + return JsonVO.fail("修改失败"); + } + + + @Override + public JsonVO> querySupplierList() { + return null; + } + + @Override + public JsonVO> queryAllByBillNo(String billNo) { + return null; + } + + @Override + public JsonVO excelImport(MultipartFile file) { + return null; + } + + /** + * 关闭功能 + * author yuhang + */ + @Override + public JsonVO closeById(String id,UserDTO userDTO) { + return finPaymentService.closeById(id,userDTO); + } + + /** + * 反关闭功能 + * author yuhang + */ + @Override + public JsonVO uncloseById(String id,UserDTO userDTO) { + return finPaymentService.uncloseById(id, userDTO); + } + + /** + * 作废功能 + * author yuhang + */ + @Override + public JsonVO voidById(String id,UserDTO userDTO) { + return finPaymentService.voidById(id, userDTO); + } +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/PurOrderEntryServiceImpl.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/PurOrderEntryServiceImpl.java new file mode 100644 index 000000000..fc802e8c5 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/PurOrderEntryServiceImpl.java @@ -0,0 +1,20 @@ +package com.zeroone.star.prepayment.service.impl; + +import com.zeroone.star.prepayment.entity.PurOrderEntry; +import com.zeroone.star.prepayment.mapper.PurOrderEntryMapper; +import com.zeroone.star.prepayment.service.IPurOrderEntryService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 采购订单明细 服务实现类 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +@Service +public class PurOrderEntryServiceImpl extends ServiceImpl implements IPurOrderEntryService { + +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/PurOrderServiceImpl.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/PurOrderServiceImpl.java new file mode 100644 index 000000000..a9165c611 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/PurOrderServiceImpl.java @@ -0,0 +1,54 @@ +package com.zeroone.star.prepayment.service.impl; +import com.zeroone.star.prepayment.entity.PurOrder; +import com.zeroone.star.prepayment.mapper.PurOrderMapper; +import com.zeroone.star.prepayment.service.IPurOrderService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.zeroone.star.project.query.prepayment.PurchaseListQuery; +import com.zeroone.star.project.vo.PageVO; +import com.zeroone.star.project.vo.prepayment.PurOrderVO; +import org.springframework.beans.factory.annotation.Autowired; +/** + *

+ * 采购订单 服务实现类 + *

+ * + * @author zhd + * @since 2023-02-18 + */ +@Service +public class PurOrderServiceImpl extends ServiceImpl implements IPurOrderService { + @Autowired + PurOrderMapper purOrderMapper; + + @Override + public PageVO getPurOrder(PurchaseListQuery condition) { + Page purOrderPage = new Page<>(condition.getPageIndex(), condition.getPageSize()); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("supplier_id",condition.getSelf_supplier_id()); +// if (condition.getSelf_payment_type()!=null){ +// wrapper.eq("payment_type",condition.getSelf_payment_type()); +// } + if (condition.getSelf_is_closed()!=null){ + wrapper.eq("is_closed",condition.getSelf_is_closed()); + } + Page purOrder= purOrderMapper.selectPage(purOrderPage, wrapper); + return PageVO.create(purOrder,PurOrderVO.class); + } + /** + * ClassName PurOrderServiceImpl + * Description IPurOrderService服务类的实现 + * Author HZP + **/ + @Override + public PurOrder getBySrcBillId(String srcBillId) { + QueryWrapper PurOrderQueryWrapper = new QueryWrapper<>(); + PurOrderQueryWrapper.eq("id",srcBillId); + PurOrder purOrder = baseMapper.selectOne(PurOrderQueryWrapper); + if(purOrder!=null) + return purOrder; + return null; + } +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/SysDepartServiceImpl.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/SysDepartServiceImpl.java new file mode 100644 index 000000000..e73137c30 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/SysDepartServiceImpl.java @@ -0,0 +1,43 @@ +package com.zeroone.star.prepayment.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.zeroone.star.prepayment.entity.SysDepart; +import com.zeroone.star.prepayment.mapper.SysDepartMapper; +import com.zeroone.star.prepayment.service.ISysDepartService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.zeroone.star.project.vo.prepayment.SysDepartVO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import java.util.ArrayList; +import java.util.List; + +/** + *

+ * 组织机构表 服务实现类 + *

+ * + * @author Kong + * @since 2023-02-17 + */ +@Service +public class SysDepartServiceImpl extends ServiceImpl implements ISysDepartService { + + @Autowired + SysDepartMapper sysDepartMapper; + + @Override + public List getDeparts() { + //查询sys_depart表数据 获取所有部门对象 + QueryWrapper queryWrapper = new QueryWrapper<>(); + List departList = sysDepartMapper.selectList(queryWrapper); + + //封装成vo + ArrayList departVOS = new ArrayList<>(); + for (SysDepart depart:departList){ + SysDepartVO sysDepartVO = new SysDepartVO(depart.getOrgCode(),depart.getDepartName(),depart.getDepartName(),depart.getDepartName()); + departVOS.add(sysDepartVO); + } + + return departVOS; + } +} diff --git a/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/SysUserServiceImpl.java b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/SysUserServiceImpl.java new file mode 100644 index 000000000..1d62e1679 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/java/com/zeroone/star/prepayment/service/impl/SysUserServiceImpl.java @@ -0,0 +1,40 @@ +package com.zeroone.star.prepayment.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.zeroone.star.prepayment.entity.SysUser; +import com.zeroone.star.prepayment.mapper.SysUserMapper; +import com.zeroone.star.prepayment.service.ISysUserService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.zeroone.star.project.vo.prepayment.SysUserVO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import java.util.ArrayList; +import java.util.List; + +/** + *

+ * 用户表 服务实现类 + *

+ * + * @author Kong + * @since 2023-02-17 + */ +@Service +public class SysUserServiceImpl extends ServiceImpl implements ISysUserService { + @Autowired + SysUserMapper userMapper; + + @Override + public List getSysUserList() { + QueryWrapper queryWrapper = new QueryWrapper<>(); + List userList = userMapper.selectList(queryWrapper); + + ArrayList sysUserVOS = new ArrayList<>(); + for (SysUser user : userList){ + SysUserVO sysUserVO = new SysUserVO(user.getUsername(),user.getRealname(),user.getRealname(),user.getRealname()); + sysUserVOS.add(sysUserVO); + } + + return sysUserVOS; + } +} diff --git a/psi-java/psi-prepayment/src/main/resources/application.yaml b/psi-java/psi-prepayment/src/main/resources/application.yaml new file mode 100644 index 000000000..1637d19ce --- /dev/null +++ b/psi-java/psi-prepayment/src/main/resources/application.yaml @@ -0,0 +1,11 @@ +server: + port: ${sp.prepayment} +spring: + application: + name: ${sn.prepayment} + +#server: +# port: ${sp.payment} +#spring: +# application: +# name: ${sn.payment} diff --git a/psi-java/psi-prepayment/src/main/resources/mapper/BasBankAccountMapper.xml b/psi-java/psi-prepayment/src/main/resources/mapper/BasBankAccountMapper.xml new file mode 100644 index 000000000..510b1db78 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/resources/mapper/BasBankAccountMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/psi-java/psi-prepayment/src/main/resources/mapper/BasSupplierMapper.xml b/psi-java/psi-prepayment/src/main/resources/mapper/BasSupplierMapper.xml new file mode 100644 index 000000000..c022edcfe --- /dev/null +++ b/psi-java/psi-prepayment/src/main/resources/mapper/BasSupplierMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/psi-java/psi-prepayment/src/main/resources/mapper/FinPaymentEntryMapper.xml b/psi-java/psi-prepayment/src/main/resources/mapper/FinPaymentEntryMapper.xml new file mode 100644 index 000000000..086a4ef78 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/resources/mapper/FinPaymentEntryMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/psi-java/psi-prepayment/src/main/resources/mapper/FinPaymentMapper.xml b/psi-java/psi-prepayment/src/main/resources/mapper/FinPaymentMapper.xml new file mode 100644 index 000000000..a26f12b3f --- /dev/null +++ b/psi-java/psi-prepayment/src/main/resources/mapper/FinPaymentMapper.xml @@ -0,0 +1,15 @@ + + + + + + insert into fin_payment values + + (#{payment.billNo},#{payment.billNo},#{payment.billDate},#{payment.srcBillType},#{payment.srcBillId},#{payment.srcNo},#{payment.subject},#{payment.isRubric},#{payment.paymentType} + ,#{payment.supplierId},#{payment.amt},#{payment.checkedAmt},#{payment.attachment},#{payment.remark},#{payment.isAuto},#{payment.billStage},#{payment.approver} + ,#{payment.bpmiInstanceId},#{payment.approvalResultType},#{payment.approvalRemark},#{payment.isEffective},#{payment.effectiveTime},#{payment.isClosed} + ,#{payment.isVoided},#{payment.createTime},#{payment.createBy},#{payment.sysOrgCode},#{payment.updateTime},#{payment.updateBy},#{payment.version}) + + + + diff --git a/psi-java/psi-prepayment/src/main/resources/mapper/FinPaymentReqEntryMapper.xml b/psi-java/psi-prepayment/src/main/resources/mapper/FinPaymentReqEntryMapper.xml new file mode 100644 index 000000000..35a85d1ac --- /dev/null +++ b/psi-java/psi-prepayment/src/main/resources/mapper/FinPaymentReqEntryMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/psi-java/psi-prepayment/src/main/resources/mapper/FinPaymentReqMapper.xml b/psi-java/psi-prepayment/src/main/resources/mapper/FinPaymentReqMapper.xml new file mode 100644 index 000000000..b919f7bf6 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/resources/mapper/FinPaymentReqMapper.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/psi-java/psi-prepayment/src/main/resources/mapper/PurOrderEntryMapper.xml b/psi-java/psi-prepayment/src/main/resources/mapper/PurOrderEntryMapper.xml new file mode 100644 index 000000000..30e8f6ae6 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/resources/mapper/PurOrderEntryMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/psi-java/psi-prepayment/src/main/resources/mapper/PurOrderMapper.xml b/psi-java/psi-prepayment/src/main/resources/mapper/PurOrderMapper.xml new file mode 100644 index 000000000..d9175fbc1 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/resources/mapper/PurOrderMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/psi-java/psi-prepayment/src/main/resources/mapper/SysDepartMapper.xml b/psi-java/psi-prepayment/src/main/resources/mapper/SysDepartMapper.xml new file mode 100644 index 000000000..0203b0df9 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/resources/mapper/SysDepartMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/psi-java/psi-prepayment/src/main/resources/mapper/SysUserMapper.xml b/psi-java/psi-prepayment/src/main/resources/mapper/SysUserMapper.xml new file mode 100644 index 000000000..832adc893 --- /dev/null +++ b/psi-java/psi-prepayment/src/main/resources/mapper/SysUserMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/psi-java/psi-prepayment/src/test/java/com/zeroone/star/prepayment/service/SysDepartServiceTest.java b/psi-java/psi-prepayment/src/test/java/com/zeroone/star/prepayment/service/SysDepartServiceTest.java new file mode 100644 index 000000000..89cf60cdb --- /dev/null +++ b/psi-java/psi-prepayment/src/test/java/com/zeroone/star/prepayment/service/SysDepartServiceTest.java @@ -0,0 +1,67 @@ +package com.zeroone.star.prepayment.service; + +import com.zeroone.star.prepayment.PrepaymentApplication; +import com.zeroone.star.prepayment.entity.SysDepart; +import com.zeroone.star.project.query.prepayment.PurchaseListQuery; +import com.zeroone.star.project.vo.PageVO; +import com.zeroone.star.project.vo.prepayment.*; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.List; + +/** + * @Author: Kong + * @License: (C) Copyright 2005-2019, xxx Corporation Limited. + * @Contact: xxx@xxx.com + * @Date: 2023-02-18 9:26 + * @Version: 1.0 + * @Description: + */ +@SpringBootTest(classes = PrepaymentApplication.class) +public class SysDepartServiceTest { + + @Autowired + ISysDepartService departService; + @Autowired + IBasBankAccountService basBankAccountService; + @Autowired + IBasSupplierService supplierService; + @Autowired + ISysUserService userService; + @Autowired + IFinPaymentReqService finPaymentReqService; + @Test + void testGetDeparts(){ + List departs = departService.getDeparts(); + System.out.println(departs); + } + + @Test + void testGetSupplierList(){ + List supplierList = supplierService.getSupplierList(); + System.out.println(supplierList); + } + + @Test + void testGetBasBankAccountList(){ + List basBankAccountList = basBankAccountService.getBasBankAccountList(); + System.out.println(basBankAccountList); + } + + @Test + void testGetSysUserList(){ + List sysUserList = userService.getSysUserList(); + System.out.println(sysUserList); + } + + @Test + void testGetFinPaymentReq(){ + PurchaseListQuery query = new PurchaseListQuery("1","2011",1,"1584950950470164481"); + query.setPageIndex(1); + query.setPageSize(10); + PageVO finPaymentReq = finPaymentReqService.getFinPaymentReq(query); + System.out.println(finPaymentReq); + } +} \ No newline at end of file