| @@ -0,0 +1,211 @@ | |||
| Apache License | |||
| Version 2.0, January 2004 | |||
| http://www.apache.org/licenses/ | |||
| TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | |||
| 1. Definitions. | |||
| "License" shall mean the terms and conditions for use, reproduction, | |||
| and distribution as defined by Sections 1 through 9 of this document. | |||
| "Licensor" shall mean the copyright owner or entity authorized by | |||
| the copyright owner that is granting the License. | |||
| "Legal Entity" shall mean the union of the acting entity and all | |||
| other entities that control, are controlled by, or are under common | |||
| control with that entity. For the purposes of this definition, | |||
| "control" means (i) the power, direct or indirect, to cause the | |||
| direction or management of such entity, whether by contract or | |||
| otherwise, or (ii) ownership of fifty percent (50%) or more of the | |||
| outstanding shares, or (iii) beneficial ownership of such entity. | |||
| "You" (or "Your") shall mean an individual or Legal Entity | |||
| exercising permissions granted by this License. | |||
| "Source" form shall mean the preferred form for making modifications, | |||
| including but not limited to software source code, documentation | |||
| source, and configuration files. | |||
| "Object" form shall mean any form resulting from mechanical | |||
| transformation or translation of a Source form, including but | |||
| not limited to compiled object code, generated documentation, | |||
| and conversions to other media types. | |||
| "Work" shall mean the work of authorship, whether in Source or | |||
| Object form, made available under the License, as indicated by a | |||
| copyright notice that is included in or attached to the work | |||
| (an example is provided in the Appendix below). | |||
| "Derivative Works" shall mean any work, whether in Source or Object | |||
| form, that is based on (or derived from) the Work and for which the | |||
| editorial revisions, annotations, elaborations, or other modifications | |||
| represent, as a whole, an original work of authorship. For the purposes | |||
| of this License, Derivative Works shall not include works that remain | |||
| separable from, or merely link (or bind by name) to the interfaces of, | |||
| the Work and Derivative Works thereof. | |||
| "Contribution" shall mean any work of authorship, including | |||
| the original version of the Work and any modifications or additions | |||
| to that Work or Derivative Works thereof, that is intentionally | |||
| submitted to Licensor for inclusion in the Work by the copyright owner | |||
| or by an individual or Legal Entity authorized to submit on behalf of | |||
| the copyright owner. For the purposes of this definition, "submitted" | |||
| means any form of electronic, verbal, or written communication sent | |||
| to the Licensor or its representatives, including but not limited to | |||
| communication on electronic mailing lists, source code control systems, | |||
| and issue tracking systems that are managed by, or on behalf of, the | |||
| Licensor for the purpose of discussing and improving the Work, but | |||
| excluding communication that is conspicuously marked or otherwise | |||
| designated in writing by the copyright owner as "Not a Contribution." | |||
| "Contributor" shall mean Licensor and any individual or Legal Entity | |||
| on behalf of whom a Contribution has been received by Licensor and | |||
| subsequently incorporated within the Work. | |||
| 2. Grant of Copyright License. Subject to the terms and conditions of | |||
| this License, each Contributor hereby grants to You a perpetual, | |||
| worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |||
| copyright license to reproduce, prepare Derivative Works of, | |||
| publicly display, publicly perform, sublicense, and distribute the | |||
| Work and such Derivative Works in Source or Object form. | |||
| 3. Grant of Patent License. Subject to the terms and conditions of | |||
| this License, each Contributor hereby grants to You a perpetual, | |||
| worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |||
| (except as stated in this section) patent license to make, have made, | |||
| use, offer to sell, sell, import, and otherwise transfer the Work, | |||
| where such license applies only to those patent claims licensable | |||
| by such Contributor that are necessarily infringed by their | |||
| Contribution(s) alone or by combination of their Contribution(s) | |||
| with the Work to which such Contribution(s) was submitted. If You | |||
| institute patent litigation against any entity (including a | |||
| cross-claim or counterclaim in a lawsuit) alleging that the Work | |||
| or a Contribution incorporated within the Work constitutes direct | |||
| or contributory patent infringement, then any patent licenses | |||
| granted to You under this License for that Work shall terminate | |||
| as of the date such litigation is filed. | |||
| 4. Redistribution. You may reproduce and distribute copies of the | |||
| Work or Derivative Works thereof in any medium, with or without | |||
| modifications, and in Source or Object form, provided that You | |||
| meet the following conditions: | |||
| (a) You must give any other recipients of the Work or | |||
| Derivative Works a copy of this License; and | |||
| (b) You must cause any modified files to carry prominent notices | |||
| stating that You changed the files; and | |||
| (c) You must retain, in the Source form of any Derivative Works | |||
| that You distribute, all copyright, patent, trademark, and | |||
| attribution notices from the Source form of the Work, | |||
| excluding those notices that do not pertain to any part of | |||
| the Derivative Works; and | |||
| (d) If the Work includes a "NOTICE" text file as part of its | |||
| distribution, then any Derivative Works that You distribute must | |||
| include a readable copy of the attribution notices contained | |||
| within such NOTICE file, excluding those notices that do not | |||
| pertain to any part of the Derivative Works, in at least one | |||
| of the following places: within a NOTICE text file distributed | |||
| as part of the Derivative Works; within the Source form or | |||
| documentation, if provided along with the Derivative Works; or, | |||
| within a display generated by the Derivative Works, if and | |||
| wherever such third-party notices normally appear. The contents | |||
| of the NOTICE file are for informational purposes only and | |||
| do not modify the License. You may add Your own attribution | |||
| notices within Derivative Works that You distribute, alongside | |||
| or as an addendum to the NOTICE text from the Work, provided | |||
| that such additional attribution notices cannot be construed | |||
| as modifying the License. | |||
| You may add Your own copyright statement to Your modifications and | |||
| may provide additional or different license terms and conditions | |||
| for use, reproduction, or distribution of Your modifications, or | |||
| for any such Derivative Works as a whole, provided Your use, | |||
| reproduction, and distribution of the Work otherwise complies with | |||
| the conditions stated in this License. | |||
| 5. Submission of Contributions. Unless You explicitly state otherwise, | |||
| any Contribution intentionally submitted for inclusion in the Work | |||
| by You to the Licensor shall be under the terms and conditions of | |||
| this License, without any additional terms or conditions. | |||
| Notwithstanding the above, nothing herein shall supersede or modify | |||
| the terms of any separate license agreement you may have executed | |||
| with Licensor regarding such Contributions. | |||
| 6. Trademarks. This License does not grant permission to use the trade | |||
| names, trademarks, service marks, or product names of the Licensor, | |||
| except as required for reasonable and customary use in describing the | |||
| origin of the Work and reproducing the content of the NOTICE file. | |||
| 7. Disclaimer of Warranty. Unless required by applicable law or | |||
| agreed to in writing, Licensor provides the Work (and each | |||
| Contributor provides its Contributions) on an "AS IS" BASIS, | |||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | |||
| implied, including, without limitation, any warranties or conditions | |||
| of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | |||
| PARTICULAR PURPOSE. You are solely responsible for determining the | |||
| appropriateness of using or redistributing the Work and assume any | |||
| risks associated with Your exercise of permissions under this License. | |||
| 8. Limitation of Liability. In no event and under no legal theory, | |||
| whether in tort (including negligence), contract, or otherwise, | |||
| unless required by applicable law (such as deliberate and grossly | |||
| negligent acts) or agreed to in writing, shall any Contributor be | |||
| liable to You for damages, including any direct, indirect, special, | |||
| incidental, or consequential damages of any character arising as a | |||
| result of this License or out of the use or inability to use the | |||
| Work (including but not limited to damages for loss of goodwill, | |||
| work stoppage, computer failure or malfunction, or any and all | |||
| other commercial damages or losses), even if such Contributor | |||
| has been advised of the possibility of such damages. | |||
| 9. Accepting Warranty or Additional Liability. While redistributing | |||
| the Work or Derivative Works thereof, You may choose to offer, | |||
| and charge a fee for, acceptance of support, warranty, indemnity, | |||
| or other liability obligations and/or rights consistent with this | |||
| License. However, in accepting such obligations, You may act only | |||
| on Your own behalf and on Your sole responsibility, not on behalf | |||
| of any other Contributor, and only if You agree to indemnify, | |||
| defend, and hold each Contributor harmless for any liability | |||
| incurred by, or claims asserted against, such Contributor by reason | |||
| of your accepting any such warranty or additional liability. | |||
| END OF TERMS AND CONDITIONS | |||
| APPENDIX: How to apply the Apache License to your work. | |||
| To apply the Apache License to your work, attach the following | |||
| boilerplate notice, with the fields enclosed by brackets "[]" | |||
| replaced with your own identifying information. (Don't include | |||
| the brackets!) The text should be enclosed in the appropriate | |||
| comment syntax for the file format. We also recommend that a | |||
| file or class name and description of purpose be included on the | |||
| same "printed page" as the copyright notice for easier | |||
| identification within third-party archives. | |||
| Copyright [yyyy] [name of copyright owner] | |||
| Licensed under the Apache License, Version 2.0 (the "License"); | |||
| you may not use this file except in compliance with the License. | |||
| You may obtain a copy of the License at | |||
| http://www.apache.org/licenses/LICENSE-2.0 | |||
| Unless required by applicable law or agreed to in writing, software | |||
| distributed under the License is distributed on an "AS IS" BASIS, | |||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| See the License for the specific language governing permissions and | |||
| limitations under the License. | |||
| Other dependencies and licenses: | |||
| ---------------------------------------------------------------------------------------- | |||
| Open Source Software Licensed Under the Apache License, Version 2.0: | |||
| The below software in this distribution may have been modified. | |||
| ---------------------------------------------------------------------------------------- | |||
| 1. EL-ADMIN | |||
| Copyright 2019-2020 Zheng Jie | |||
| @@ -0,0 +1,103 @@ | |||
| <p align="center"> | |||
| <a href="http://tianshu.org.cn"> | |||
| <img width="200" src="http://tianshu.org.cn/template/default/assets/img/logo4.png"> | |||
| </a> | |||
| </p> | |||
| <h1 align="center">天枢一站式AI模型开发平台</h1> | |||
| **天枢人工智能开源开放平台**(简称:**天枢平台**)是天枢平台由之江实验室牵头,联合北京一流科技、中国信通院和浙江大学共同自研的人工智能开源平台。整个平台由一站式AI模型开发平台、高性能深度学习框架和模型炼知框架三大子系统组成。 | |||
| 其中, **一站式AI模型开发平台面**(简称:**一站式开发平台**)面向AI模型生产的生命周期,提供了包括数据处理、模型开发、模型训练和模型管理等功能,方便用户一站式构建AI算法。 | |||
| ## 平台优势 | |||
| * **一站式开发**:为用户提供一站式深度学习开发功能,通过智能数据处理、便利的模型开发和模型训练,打通深度学习全链路; | |||
| * **集成先进算法**:除了囊括常规AI算法外,之江天枢还集成了多领域的独家算法,提供业界领先性能。 | |||
| * **灵活易用**:除了一站式深度学习开发平台,亦提供可视化和动静结合编码方式,调试灵活,小白亦可快速上手。 | |||
| * **性能优越**:集成自主研发的分布式训练平台,提供高性能的分布式计算体验,节省训练成本和训练时间。 | |||
| ## 页面预览 | |||
|  | |||
| ## 功能列表 | |||
| <table> | |||
| <tbody> | |||
| <tr> | |||
| <td rowspan="12">一站式开发平台</td> | |||
| </tr> | |||
| <tr> | |||
| <td>数据管理</td> | |||
| <td>数据集管理</td> | |||
| </tr> | |||
| <tr> | |||
| <td rowspan="2">模型开发</td> | |||
| <td>Notebook</td> | |||
| </tr> | |||
| <tr> | |||
| <td>算法管理</td> | |||
| </tr> | |||
| <tr> | |||
| <td rowspan="2">训练管理</td> | |||
| <td>镜像管理</td> | |||
| </tr> | |||
| <tr> | |||
| <td>训练任务</td> | |||
| </tr> | |||
| <tr> | |||
| <td>模型管理</td> | |||
| <td>模型列表</td> | |||
| </tr> | |||
| <tr> | |||
| <td rowspan="5">控制台</td> | |||
| <td>用户管理</td> | |||
| </tr> | |||
| <tr> | |||
| <td>角色管理</td> | |||
| </tr> | |||
| <tr> | |||
| <td>菜单管理</td> | |||
| </tr> | |||
| <tr> | |||
| <td>字典管理</td> | |||
| </tr> | |||
| <tr> | |||
| <td>集群状态</td> | |||
| </tr> | |||
| </tbody> | |||
| </table> | |||
| ## 技术架构 | |||
|  | |||
| ## 技术栈 | |||
| - 后端: [Spring Boot](https://spring.io/projects/spring-boot) | |||
| - 前端: [Vue.js](https://vuejs.org/), [Element](https://element.eleme.cn/) | |||
| - 数据处理 [Yolo](https://pjreddie.com/darknet/yolo/) ... | |||
| - 可视化: [Django](https://www.djangoproject.com/) ... | |||
| - 中间件: [MySQL](https://www.mysql.com/), [MyBatis-Plus](https://mp.baomidou.com/), [Redis](https://redis.io/) | |||
| - 基础设施: [Docker](https://www.docker.com/), [Kubernetes](https://kubernetes.io/) | |||
| ## 目录结构 | |||
| ``` | |||
| ├── dubhe_data_process 数据处理服务 | |||
| ├── dubhe-server 后端服务 | |||
| ├── dubhe-visual-server 可视化服务 | |||
| ├── webapp 前端服务 | |||
| ``` | |||
| ## 反馈问题 | |||
| - [在线社区](http://www.aiiaos.cn/index.php?s=/forum/index/forum/id/45.html) | |||
| - 钉钉交流群 | |||
| <a href="./docs/images/dingtalk.jpg"><img src="http://cdn.qjycloud.com/dingtalk.jpg" width="320" /></a> | |||
| ## 许可证书 | |||
| 本项目的发布受[Apache 2.0 license](./LICENSE)许可认证。 | |||
| @@ -0,0 +1,53 @@ | |||
| /target/ | |||
| .mvn* | |||
| mvnw | |||
| mvnw.cmd | |||
| kubeconfig | |||
| ### STS ### | |||
| .apt_generated | |||
| .classpath | |||
| .factorypath | |||
| .project | |||
| .settings | |||
| .springBeans | |||
| .sts4-cache | |||
| ### IntelliJ IDEA ### | |||
| .idea | |||
| *.iws | |||
| *.iml | |||
| *.ipr | |||
| ### NetBeans ### | |||
| /nbproject/private/ | |||
| /build/ | |||
| /nbbuild/ | |||
| /dist/ | |||
| /nbdist/ | |||
| /.nb-gradle/ | |||
| # system ignore | |||
| .DS_Store | |||
| Thumbs.db | |||
| *.orig | |||
| # maven ignore | |||
| target/ | |||
| output/ | |||
| *.jar | |||
| !.mvn/wrapper/* | |||
| *.war | |||
| *.zip | |||
| *.tar | |||
| #*.tar.gz | |||
| # eclipse ignore | |||
| .settings/ | |||
| .project | |||
| .classpath | |||
| logs/ | |||
| /dubhe-k8s/src/main/resources/kubeconfig | |||
| /dubhe-k8s/src/main/resources | |||
| *.log | |||
| /dubhe-admin/kubeconfig | |||
| @@ -0,0 +1,10 @@ | |||
| # type: subject | |||
| # type:feat增加新功能;fix修复错误;docs修改文档;style修改样式;refactor代码重构;test增加测试模块,不涉及生产环境的代码;chore更新核心模块,包配置文件,不涉及生产环境的代码 | |||
| # subject: 一两句话简述提交原因,与下方详细描述间隔一行 | |||
| # body:提交详细原因,与下方脚注间隔一行 | |||
| # footer(可选):1.提供链接关联issue、2.关闭issue | |||
| @@ -0,0 +1,98 @@ | |||
| # 之江天枢-服务端 | |||
| **之江天枢一站式人工智能开源平台**(简称:**之江天枢**),包括海量数据处理、交互式模型构建(包含Notebook和模型可视化)、AI模型高效训练。多维度产品形态满足从开发者到大型企业的不同需求,将提升人工智能技术的研发效率、扩大算法模型的应用范围,进一步构建人工智能生态“朋友圈”。 | |||
| ## 源码部署 | |||
| ### 准备环境 | |||
| 安装如下软件环境。 | |||
| - OpenJDK:1.8+ | |||
| - Redis: 3.0+ | |||
| - Maven: 3.0+ | |||
| - MYSQL: 5.5.0+ | |||
| ### 下载源码 | |||
| ``` bash | |||
| git clone https://codeup.teambition.com/zhejianglab/dubhe-server.git | |||
| # 进入项目根目录 | |||
| cd dubhe-server | |||
| ``` | |||
| ### 创建DB | |||
| 在MySQL中依次执行如下sql文件 | |||
| ``` | |||
| sql/v1/00-Dubhe-DB.sql | |||
| sql/v1/01-Dubhe-DDL.sql | |||
| sql/v1/02-Dubhe-DML.sql | |||
| ``` | |||
| ### 配置 | |||
| 根据实际情况修改如下配置文件。 | |||
| ``` | |||
| dubhe-admin/src/main/resources/config/application-prod.yml | |||
| ``` | |||
| ### 构建 | |||
| ``` bash | |||
| # 构建,生成的 jar 包位于 ./dubhe-admin/target/dubhe-admin-1.0.jar | |||
| mvn clean compile package | |||
| ``` | |||
| ### 启动 | |||
| ``` bash | |||
| # 指定启动环境为 prod | |||
| java -jar ./dubhe-admin/target/dubhe-admin-1.0.jar --spring.profiles.active=prod | |||
| ``` | |||
| ## 本地开发 | |||
| ### 必要条件: | |||
| 导入maven项目,下载所需的依赖包 | |||
| mysql下创建数据库dubhe,初始化数据脚本 | |||
| 安装redis | |||
| ### 启动: | |||
| mvn spring-boot:run | |||
| ## 代码结构: | |||
| ``` | |||
| ├── common 公共模块 | |||
| ├── dubhe-admin 开发与训练模块 | |||
| │ ├── src | |||
| │ │ └── main | |||
| │ │ ├── java | |||
| │ │ │ └── org | |||
| │ │ │ └── dubhe | |||
| │ │ │ ├── AppRun.java | |||
| │ │ │ ├── domain 实体对象 | |||
| │ │ │ ├── repository 数据库层 | |||
| │ │ │ ├── rest 控制层 | |||
| │ │ │ └── service 服务层 | |||
| │ │ │ ├── dto 数据传输对象 | |||
| │ │ │ ├── impl 服务实现 | |||
| │ │ │ └── mapper 对象转化 | |||
| │ │ └── resources 配置文件 | |||
| ├── dubhe-data 数据处理模块 | |||
| ├── dubhe-model 模型管理模块 | |||
| ├── dubhe-system 系统管理 | |||
| ``` | |||
| ## docker服务器 | |||
| 上传镜像功能依赖docker服务,harbor与dokcer的信任配置如下: | |||
| ### 1、对外开放端口 | |||
| vi /lib/systemd/system/docker.service | |||
| ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock | |||
| ### 2、信任harbor地址 | |||
| vi /etc/docker/daemon.json | |||
| { | |||
| "exec-opts": ["native.cgroupdriver=systemd"], | |||
| "log-driver": "json-file", | |||
| "insecure-registries":[harbor地址], | |||
| "log-opts": { | |||
| "max-size": "100m" | |||
| } | |||
| } | |||
| ### 3、重新启动 | |||
| systemctl daemon-reload | |||
| service docker restart | |||
| systemctl status docker | |||
| @@ -0,0 +1,121 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
| xmlns="http://maven.apache.org/POM/4.0.0" | |||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
| <parent> | |||
| <artifactId>dubheplatform</artifactId> | |||
| <groupId>zhejianglab</groupId> | |||
| <version>1.0</version> | |||
| </parent> | |||
| <modelVersion>4.0.0</modelVersion> | |||
| <properties> | |||
| <hutool.version>5.0.6</hutool.version> | |||
| <minio.version>7.0.2</minio.version> | |||
| <aspectjweaver.version>1.8.9</aspectjweaver.version> | |||
| </properties> | |||
| <artifactId>common</artifactId> | |||
| <name>公共模块</name> | |||
| <dependencies> | |||
| <!--工具包--> | |||
| <dependency> | |||
| <groupId>cn.hutool</groupId> | |||
| <artifactId>hutool-all</artifactId> | |||
| <version>${hutool.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.google.guava</groupId> | |||
| <artifactId>guava</artifactId> | |||
| <version>21.0</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.github.penggle</groupId> | |||
| <artifactId>kaptcha</artifactId> | |||
| <version>${kaptcha.version}</version> | |||
| </dependency> | |||
| <!-- shiro --> | |||
| <dependency> | |||
| <groupId>org.apache.shiro</groupId> | |||
| <artifactId>shiro-spring</artifactId> | |||
| <version>${shiro.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.auth0</groupId> | |||
| <artifactId>java-jwt</artifactId> | |||
| <version>${jwt.version}</version> | |||
| <exclusions> | |||
| <exclusion> | |||
| <groupId>*</groupId> | |||
| <artifactId>*</artifactId> | |||
| </exclusion> | |||
| </exclusions> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>io.minio</groupId> | |||
| <artifactId>minio</artifactId> | |||
| <version>${minio.version}</version> | |||
| </dependency> | |||
| <!-- aspect --> | |||
| <dependency> | |||
| <groupId>org.aspectj</groupId> | |||
| <artifactId>aspectjweaver</artifactId> | |||
| <version>${aspectjweaver.version}</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>javax.xml.bind</groupId> | |||
| <artifactId>jaxb-api</artifactId> | |||
| <version>2.3.0</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.sun.xml.bind</groupId> | |||
| <artifactId>jaxb-impl</artifactId> | |||
| <version>2.3.0</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.sun.xml.bind</groupId> | |||
| <artifactId>jaxb-core</artifactId> | |||
| <version>2.3.0</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>commons-io</groupId> | |||
| <artifactId>commons-io</artifactId> | |||
| <version>1.3.2</version> | |||
| <scope>compile</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>net.lingala.zip4j</groupId> | |||
| <artifactId>zip4j</artifactId> | |||
| <version>1.3.2</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.apache.commons</groupId> | |||
| <artifactId>commons-compress</artifactId> | |||
| <version>1.20</version> | |||
| </dependency> | |||
| </dependencies> | |||
| <build> | |||
| <plugins> | |||
| <plugin> | |||
| <groupId>org.springframework.boot</groupId> | |||
| <artifactId>spring-boot-maven-plugin</artifactId> | |||
| </plugin> | |||
| <!-- 跳过单元测试 --> | |||
| <plugin> | |||
| <groupId>org.apache.maven.plugins</groupId> | |||
| <artifactId>maven-surefire-plugin</artifactId> | |||
| <configuration> | |||
| <skipTests>true</skipTests> | |||
| </configuration> | |||
| </plugin> | |||
| </plugins> | |||
| <resources> | |||
| <resource> | |||
| <filtering>true</filtering> | |||
| <directory>src/main/resources</directory> | |||
| </resource> | |||
| </resources> | |||
| </build> | |||
| </project> | |||
| @@ -0,0 +1,32 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.annotation; | |||
| import java.lang.annotation.*; | |||
| /** | |||
| * @description API版本控制注解 | |||
| * @date 2020-04-06 | |||
| */ | |||
| @Target({ElementType.METHOD, ElementType.TYPE}) | |||
| @Retention(RetentionPolicy.RUNTIME) | |||
| @Documented | |||
| public @interface ApiVersion { | |||
| //标识版本号 | |||
| int value() default 1; | |||
| } | |||
| @@ -0,0 +1,44 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.annotation; | |||
| import java.lang.annotation.*; | |||
| /** | |||
| * 数据权限过滤Mapper拦截 | |||
| * | |||
| * @date 2020-06-22 | |||
| */ | |||
| @Target({ElementType.METHOD, ElementType.TYPE}) | |||
| @Retention(RetentionPolicy.RUNTIME) | |||
| @Documented | |||
| public @interface DataPermission { | |||
| /** | |||
| * 不需要数据权限的方法名 | |||
| */ | |||
| String[] ignores() default {}; | |||
| /** | |||
| * 只在方法的注解上使用,代表方法的数据权限类型,如果不加注解,只会识别带"select"方法名的方法 | |||
| * | |||
| * @return | |||
| */ | |||
| String[] permission() default {}; | |||
| } | |||
| @@ -0,0 +1,87 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.annotation; | |||
| import java.lang.annotation.ElementType; | |||
| import java.lang.annotation.Retention; | |||
| import java.lang.annotation.RetentionPolicy; | |||
| import java.lang.annotation.Target; | |||
| import java.lang.reflect.InvocationTargetException; | |||
| import java.lang.reflect.Method; | |||
| import javax.validation.Constraint; | |||
| import javax.validation.ConstraintValidator; | |||
| import javax.validation.ConstraintValidatorContext; | |||
| import javax.validation.Payload; | |||
| /** | |||
| * @date: 2020-05-21 | |||
| */ | |||
| @Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE }) | |||
| @Retention(RetentionPolicy.RUNTIME) | |||
| @Constraint(validatedBy = EnumValue.Validator.class) | |||
| public @interface EnumValue { | |||
| String message() default "custom.value.invalid"; | |||
| Class<?>[] groups() default {}; | |||
| Class<? extends Payload>[] payload() default {}; | |||
| Class<? extends Enum<?>> enumClass(); | |||
| String enumMethod(); | |||
| class Validator implements ConstraintValidator<EnumValue, Object> { | |||
| private Class<? extends Enum<?>> enumClass; | |||
| private String enumMethod; | |||
| @Override | |||
| public void initialize(EnumValue enumValue) { | |||
| enumMethod = enumValue.enumMethod(); | |||
| enumClass = enumValue.enumClass(); | |||
| } | |||
| @Override | |||
| public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) { | |||
| if (value == null) { | |||
| return Boolean.TRUE; | |||
| } | |||
| if (enumClass == null || enumMethod == null) { | |||
| return Boolean.TRUE; | |||
| } | |||
| Class<?> valueClass = value.getClass(); | |||
| try { | |||
| Method method = enumClass.getMethod(enumMethod, valueClass); | |||
| if (!Boolean.TYPE.equals(method.getReturnType()) && !Boolean.class.equals(method.getReturnType())) { | |||
| throw new RuntimeException(String.format("%s method return is not boolean type in the %s class", enumMethod, enumClass)); | |||
| } | |||
| Boolean result = (Boolean)method.invoke(null, value); | |||
| return result == null ? false : result; | |||
| } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { | |||
| throw new RuntimeException(e); | |||
| } catch (NoSuchMethodException | SecurityException e) { | |||
| throw new RuntimeException(String.format("This %s(%s) method does not exist in the %s", enumMethod, valueClass, enumClass), e); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,23 @@ | |||
| /** | |||
| * Copyright 2019-2020 Zheng Jie | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package org.dubhe.annotation; | |||
| /** | |||
| * @description 日志 | |||
| * @date 2020-03-15 | |||
| */ | |||
| public @interface Log { | |||
| } | |||
| @@ -0,0 +1,68 @@ | |||
| /** | |||
| * Copyright 2019-2020 Zheng Jie | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package org.dubhe.annotation; | |||
| import java.lang.annotation.ElementType; | |||
| import java.lang.annotation.Retention; | |||
| import java.lang.annotation.RetentionPolicy; | |||
| import java.lang.annotation.Target; | |||
| /** | |||
| * @description 构建Wrapper的注解 | |||
| * @date 2020-03-26 | |||
| */ | |||
| @Target(ElementType.FIELD) | |||
| @Retention(RetentionPolicy.RUNTIME) | |||
| public @interface Query { | |||
| String propName() default ""; | |||
| Type type() default Type.EQ; | |||
| String blurry() default ""; | |||
| enum Type { | |||
| // 相等 | |||
| EQ | |||
| // 不等于 | |||
| , NE | |||
| // 大于 | |||
| , GT | |||
| // 大于等于 | |||
| , GE | |||
| // 小于 | |||
| , LT | |||
| // 小于等于 | |||
| , LE, | |||
| BETWEEN, | |||
| NOT_BETWEEN, | |||
| LIKE, | |||
| NOT_LIKE, | |||
| LIkE_LEFT, | |||
| LIKE_RIGHT, | |||
| IS_NULL, | |||
| IS_NOT_NULL, | |||
| IN, | |||
| NOT_IN, | |||
| INSQL, | |||
| NOT_INSQL, | |||
| ORDER_BY | |||
| } | |||
| } | |||
| @@ -0,0 +1,33 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.annotation; | |||
| import java.lang.annotation.ElementType; | |||
| import java.lang.annotation.Retention; | |||
| import java.lang.annotation.RetentionPolicy; | |||
| import java.lang.annotation.Target; | |||
| /** | |||
| * @description 限流 | |||
| * @date 2020-03-15 | |||
| */ | |||
| @Target(ElementType.METHOD) | |||
| @Retention(RetentionPolicy.RUNTIME) | |||
| public @interface RateLimit { | |||
| double limitNum() default 20; | |||
| } | |||
| @@ -0,0 +1,87 @@ | |||
| /** | |||
| * Copyright 2019-2020 Zheng Jie | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package org.dubhe.aspect; | |||
| import java.util.UUID; | |||
| import org.aspectj.lang.JoinPoint; | |||
| import org.aspectj.lang.ProceedingJoinPoint; | |||
| import org.aspectj.lang.annotation.Around; | |||
| import org.aspectj.lang.annotation.Aspect; | |||
| import org.aspectj.lang.annotation.Pointcut; | |||
| import org.dubhe.enums.LogEnum; | |||
| import org.dubhe.utils.LogUtil; | |||
| import org.slf4j.MDC; | |||
| import org.springframework.stereotype.Component; | |||
| import org.springframework.util.StringUtils; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| /** | |||
| * @date 2020/04/10 | |||
| */ | |||
| @Component | |||
| @Aspect | |||
| @Slf4j | |||
| public class LogAspect { | |||
| public static final String TRACE_ID = "traceId"; | |||
| @Pointcut("execution(* org.dubhe..service..*.*(..))) " | |||
| + "and execution(* org.dubhe..schedule..*.*(..))) " | |||
| + "and execution(* org.dubhe..util*..*.*(..)))") | |||
| public void serviceAspect() { | |||
| } | |||
| @Pointcut("execution(* org.dubhe..rest..*.*(..))) ") | |||
| public void restAspect() { | |||
| } | |||
| @Pointcut(" execution(* org.dubhe..task..*.*(..))) ") | |||
| public void taskAspect() { | |||
| } | |||
| @Pointcut(" serviceAspect() || taskAspect() ") | |||
| public void aroundAspect() { | |||
| } | |||
| @Around("aroundAspect()") | |||
| public Object around(JoinPoint joinPoint) throws Throwable { | |||
| if (StringUtils.isEmpty(MDC.get(TRACE_ID))) { | |||
| MDC.put(TRACE_ID, UUID.randomUUID().toString()); | |||
| } | |||
| return combineLogInfo(joinPoint); | |||
| } | |||
| @Around("restAspect()") | |||
| public Object aroundRest(JoinPoint joinPoint) throws Throwable { | |||
| MDC.clear(); | |||
| MDC.put(TRACE_ID, UUID.randomUUID().toString()); | |||
| return combineLogInfo(joinPoint); | |||
| } | |||
| private Object combineLogInfo(JoinPoint joinPoint) throws Throwable { | |||
| Object[] param = joinPoint.getArgs(); | |||
| LogUtil.info(LogEnum.REST_REQ, "uri:{},input:{},==>begin", joinPoint.getSignature(), param); | |||
| long start = System.currentTimeMillis(); | |||
| Object result = ((ProceedingJoinPoint) joinPoint).proceed(); | |||
| long end = System.currentTimeMillis(); | |||
| LogUtil.info(LogEnum.REST_REQ, "uri:{},output:{},proc_time:{},<==end", joinPoint.getSignature().toString(), | |||
| result, end - start); | |||
| return result; | |||
| } | |||
| } | |||
| @@ -0,0 +1,58 @@ | |||
| /** | |||
| * Copyright 2019-2020 Zheng Jie | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package org.dubhe.base; | |||
| import java.util.List; | |||
| /** | |||
| * @description DTO Entity 转换 | |||
| * @date 2020-03-15 | |||
| */ | |||
| public interface BaseConvert<D, E> { | |||
| /** | |||
| * DTO转Entity | |||
| * | |||
| * @param dto / | |||
| * @return / | |||
| */ | |||
| E toEntity(D dto); | |||
| /** | |||
| * Entity转DTO | |||
| * | |||
| * @param entity / | |||
| * @return / | |||
| */ | |||
| D toDto(E entity); | |||
| /** | |||
| * DTO集合转Entity集合 | |||
| * | |||
| * @param dtoList / | |||
| * @return / | |||
| */ | |||
| List<E> toEntity(List<D> dtoList); | |||
| /** | |||
| * Entity集合转DTO集合 | |||
| * | |||
| * @param entityList / | |||
| * @return / | |||
| */ | |||
| List<D> toDto(List<E> entityList); | |||
| } | |||
| @@ -0,0 +1,48 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.base; | |||
| import lombok.Getter; | |||
| import lombok.Setter; | |||
| import java.io.Serializable; | |||
| import java.sql.Timestamp; | |||
| /** | |||
| * @description DTO基础类 | |||
| * @date 2020-03-15 | |||
| */ | |||
| @Getter | |||
| @Setter | |||
| public class BaseDTO implements Serializable { | |||
| private Boolean deleted; | |||
| private Timestamp createTime; | |||
| private Timestamp updateTime; | |||
| @Override | |||
| public String toString() { | |||
| return "BaseDTO{" + | |||
| "deleted=" + deleted + | |||
| ", createTime=" + createTime + | |||
| ", updateTime=" + updateTime + | |||
| '}'; | |||
| } | |||
| } | |||
| @@ -0,0 +1,76 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.base; | |||
| import com.baomidou.mybatisplus.annotation.FieldFill; | |||
| import com.baomidou.mybatisplus.annotation.TableField; | |||
| import com.baomidou.mybatisplus.annotation.TableLogic; | |||
| import lombok.Data; | |||
| import org.apache.commons.lang3.builder.ToStringBuilder; | |||
| import java.io.Serializable; | |||
| import java.lang.reflect.Field; | |||
| import java.sql.Timestamp; | |||
| /** | |||
| * @description Entity基础类 | |||
| * @date 2020-03-15 | |||
| */ | |||
| @Data | |||
| public class BaseEntity implements Serializable { | |||
| private static final long serialVersionUID = 4936056317364745513L; | |||
| /** | |||
| * 删除标识 | |||
| **/ | |||
| @TableField(value = "deleted",fill = FieldFill.INSERT) | |||
| @TableLogic | |||
| private Boolean deleted = false; | |||
| @TableField(value = "create_user_id",fill = FieldFill.INSERT) | |||
| private Long createUserId; | |||
| @TableField(value = "update_user_id",fill = FieldFill.INSERT_UPDATE) | |||
| private Long updateUserId; | |||
| @TableField(value = "create_time",fill = FieldFill.INSERT) | |||
| private Timestamp createTime; | |||
| @TableField(value = "update_time",fill = FieldFill.INSERT_UPDATE) | |||
| private Timestamp updateTime; | |||
| @Override | |||
| public String toString() { | |||
| ToStringBuilder builder = new ToStringBuilder(this); | |||
| Field[] fields = this.getClass().getDeclaredFields(); | |||
| try { | |||
| for (Field f : fields) { | |||
| f.setAccessible(true); | |||
| builder.append(f.getName(), f.get(this)).append("\n"); | |||
| } | |||
| } catch (Exception e) { | |||
| builder.append("toString builder encounter an error"); | |||
| } | |||
| return builder.toString(); | |||
| } | |||
| public @interface Update { | |||
| } | |||
| } | |||
| @@ -0,0 +1,44 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.base; | |||
| import io.swagger.annotations.ApiModelProperty; | |||
| import lombok.Data; | |||
| import lombok.experimental.Accessors; | |||
| import javax.validation.constraints.NotBlank; | |||
| import java.io.Serializable; | |||
| /** | |||
| * @description 镜像基础类DTO | |||
| * @date: 2020-07-14 | |||
| */ | |||
| @Data | |||
| @Accessors(chain = true) | |||
| public class BaseImageDTO implements Serializable { | |||
| private static final long serialVersionUID = 1L; | |||
| @ApiModelProperty(value = "镜像版本", required = true) | |||
| @NotBlank(message = "镜像版本不能为空") | |||
| private String imageTag; | |||
| @ApiModelProperty(value = "镜像名称", required = true) | |||
| @NotBlank(message = "镜像名称不能为空") | |||
| private String imageName; | |||
| } | |||
| @@ -0,0 +1,46 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.base; | |||
| import io.swagger.annotations.ApiModelProperty; | |||
| import lombok.Data; | |||
| import java.io.Serializable; | |||
| import java.sql.Timestamp; | |||
| /** | |||
| * @description: VO基础类 | |||
| * @date: 2020-05-22 | |||
| */ | |||
| @Data | |||
| public class BaseVO implements Serializable { | |||
| private static final long serialVersionUID = 1L; | |||
| @ApiModelProperty("创建人") | |||
| private Long createUserId; | |||
| @ApiModelProperty("创建时间") | |||
| private Timestamp createTime; | |||
| @ApiModelProperty("修改人") | |||
| private Long updateUserId; | |||
| @ApiModelProperty("修改时间") | |||
| private Timestamp updateTime; | |||
| } | |||
| @@ -0,0 +1,76 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.base; | |||
| import io.swagger.annotations.ApiModel; | |||
| import io.swagger.annotations.ApiModelProperty; | |||
| import lombok.Data; | |||
| import org.slf4j.MDC; | |||
| import java.io.Serializable; | |||
| /** | |||
| * @description 统一的公共响应体 | |||
| * @date 2020-03-16 | |||
| */ | |||
| @Data | |||
| @ApiModel(description = "统一的公共响应体") | |||
| public class DataResponseBody<T> implements Serializable { | |||
| /** | |||
| * 返回状态码 | |||
| */ | |||
| @ApiModelProperty("返回状态码") | |||
| private Integer code; | |||
| /** | |||
| * 返回信息 | |||
| */ | |||
| @ApiModelProperty("返回信息") | |||
| private String msg; | |||
| /** | |||
| * 泛型数据 | |||
| */ | |||
| @ApiModelProperty("泛型数据") | |||
| private T data; | |||
| /** | |||
| * 链路追踪ID | |||
| */ | |||
| @ApiModelProperty("链路追踪ID") | |||
| private String traceId; | |||
| public DataResponseBody() { | |||
| this(ResponseCode.SUCCESS, null); | |||
| } | |||
| public DataResponseBody(T data) { | |||
| this(ResponseCode.SUCCESS, null, data); | |||
| } | |||
| public DataResponseBody(Integer code, String msg) { | |||
| this(code, msg, null); | |||
| } | |||
| public DataResponseBody(Integer code, String msg, T data) { | |||
| this.code = code; | |||
| this.msg = msg; | |||
| this.data = data; | |||
| this.traceId = MDC.get("traceId"); | |||
| } | |||
| } | |||
| @@ -0,0 +1,99 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.base; | |||
| /** | |||
| * @date: 2020-05-14 | |||
| */ | |||
| public final class MagicNumConstant { | |||
| public static final int NEGATIVE_ONE = -1; | |||
| public static final int ZERO = 0; | |||
| public static final int ONE = 1; | |||
| public static final int TWO = 2; | |||
| public static final int THREE = 3; | |||
| public static final int FOUR = 4; | |||
| public static final int FIVE = 5; | |||
| public static final int SIX = 6; | |||
| public static final int SEVEN = 7; | |||
| public static final int EIGHT = 8; | |||
| public static final int NINE = 9; | |||
| public static final int TEN = 10; | |||
| public static final int ELEVEN = 11; | |||
| public static final int SIXTEEN = 16; | |||
| public static final int TWENTY = 20; | |||
| public static final int FIFTY = 50; | |||
| public static final int SIXTY = 60; | |||
| public static final int SIXTY_TWO = 62; | |||
| public static final int SIXTY_FOUR = 64; | |||
| public static final int INTEGER_TWO_HUNDRED_AND_FIFTY_FIVE = 255; | |||
| public static final int ONE_HUNDRED = 100; | |||
| public static final int ONE_HUNDRED_TWENTY_EIGHT = 128; | |||
| public static final int TWO_HUNDRED = 200; | |||
| public static final int FIVE_HUNDRED = 500; | |||
| public static final int FIVE_HUNDRED_AND_SIXTEEN = 516; | |||
| public static final int ONE_THOUSAND = 1000; | |||
| public static final int BINARY_TEN_EXP = 1024; | |||
| public static final int ONE_THOUSAND_ONE_HUNDRED = 1100; | |||
| public static final int ONE_THOUSAND_ONE_HUNDRED_ONE = 1101; | |||
| public static final int ONE_THOUSAND_TWO_HUNDRED = 1200; | |||
| public static final int ONE_THOUSAND_TWO_HUNDRED_ONE = 1201; | |||
| public static final int ONE_THOUSAND_TWENTY_FOUR = 1024; | |||
| public static final int ONE_THOUSAND_THREE_HUNDRED = 1300; | |||
| public static final int ONE_THOUSAND_THREE_HUNDRED_ONE = 1301; | |||
| public static final int ONE_THOUSAND_THREE_HUNDRED_NINE = 1309; | |||
| public static final int ONE_THOUSAND_FIVE_HUNDRED = 1500; | |||
| public static final int TWO_THOUSAND = 2000; | |||
| public static final int TWO_THOUSAND_TWENTY_EIGHT = 2048; | |||
| public static final int THREE_THOUSAND = 3000; | |||
| public static final int FOUR_THOUSAND = 4000; | |||
| public static final int NINE_THOUSAND = 9000; | |||
| public static final int NINE_THOUSAND_NINE_HUNDRED_NINTY_NINE = 9999; | |||
| public static final int TEN_THOUSAND = 10000; | |||
| public static final int FIFTEEN_THOUSAND = 15000; | |||
| public static final int HUNDRED_THOUSAND = 100000; | |||
| public static final int MILLION = 1000000; | |||
| public static final int ONE_MINUTE = 60000; | |||
| public static final long NEGATIVE_ONE__LONG = -1L; | |||
| public static final long ZERO_LONG = 0L; | |||
| public static final long ONE_LONG = 1L; | |||
| public static final long TWO_LONG = 2L; | |||
| public static final long THREE_LONG = 3L; | |||
| public static final long FOUR_LONG = 4L; | |||
| public static final long FIVE_LONG = 5L; | |||
| public static final long SIX_LONG = 6L; | |||
| public static final long SEVEN_LONG = 7L; | |||
| public static final long EIGHT_LONG = 8L; | |||
| public static final long NINE_LONG = 9L; | |||
| public static final long TEN_LONG = 10L; | |||
| public static final long TWELVE_LONG = 12L; | |||
| public static final long SIXTY_LONG = 60L; | |||
| public static final long TEN_THOUSAND_LONG = 10000L; | |||
| public static final long ONE_ZERO_ONE_ZERO_ONE_ZERO_LONG = 101010L; | |||
| public static final long NINE_ZERO_NINE_ZERO_NINE_ZERO_LONG = 909090L; | |||
| public static final long ONE_YEAR_BEFORE_LONG = 1552579200000L; | |||
| public static final int SIXITY_0XFF = 0xFF; | |||
| private MagicNumConstant() { | |||
| } | |||
| } | |||
| @@ -0,0 +1,62 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.base; | |||
| import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | |||
| import io.swagger.annotations.ApiModelProperty; | |||
| import lombok.Data; | |||
| import lombok.experimental.Accessors; | |||
| import org.dubhe.constant.NumberConstant; | |||
| import javax.validation.constraints.Min; | |||
| /** | |||
| * @description: 分页基类 | |||
| * @date: 2020-05-8 | |||
| */ | |||
| @Data | |||
| @Accessors(chain = true) | |||
| public class PageQueryBase<T> { | |||
| @ApiModelProperty(value = "分页-当前页数") | |||
| @Min(value = 1, message = "current不能小于1") | |||
| private Integer current; | |||
| @ApiModelProperty(value = "分页-每页展示数") | |||
| @Min(value = 1, message = "size不能小于1") | |||
| private Integer size; | |||
| @ApiModelProperty(value = "排序字段") | |||
| private String sort; | |||
| @ApiModelProperty(value = "排序方式,asc | desc") | |||
| private String order; | |||
| public Page<T> toPage() { | |||
| Page<T> page = new Page(); | |||
| if (this.current != null) { | |||
| page.setCurrent(this.current); | |||
| } | |||
| if (this.size != null && this.size < NumberConstant.MAX_PAGE_SIZE) { | |||
| page.setSize(this.size); | |||
| } | |||
| return page; | |||
| } | |||
| } | |||
| @@ -0,0 +1,33 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.base; | |||
| /** | |||
| * @description 返回状态码 | |||
| * @date 2020-02-23 | |||
| */ | |||
| public class ResponseCode { | |||
| public static Integer SUCCESS = 200; | |||
| public static Integer UNAUTHORIZED = 401; | |||
| public static Integer ERROR = 10000; | |||
| public static Integer ENTITY_NOT_EXIST = 10001; | |||
| public static Integer BADREQUEST = 10002; | |||
| public static Integer SERVICE_ERROR = 10003; | |||
| public static Integer DOCKER_ERROR = 10004; | |||
| } | |||
| @@ -0,0 +1,56 @@ | |||
| /** | |||
| * Copyright 2019-2020 Zheng Jie | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package org.dubhe.config; | |||
| import org.springframework.context.annotation.Bean; | |||
| import org.springframework.context.annotation.Configuration; | |||
| import org.springframework.web.cors.CorsConfiguration; | |||
| import org.springframework.web.cors.UrlBasedCorsConfigurationSource; | |||
| import org.springframework.web.filter.CorsFilter; | |||
| /** | |||
| * @description 允许跨域 | |||
| * @date 2020-02-23 | |||
| */ | |||
| @Configuration | |||
| public class GlobalCorsConfig { | |||
| @Bean | |||
| public CorsFilter corsFilter() { | |||
| //1.添加CORS配置信息 | |||
| CorsConfiguration config = new CorsConfiguration(); | |||
| //放行哪些原始域 | |||
| config.addAllowedOrigin("*"); | |||
| //是否发送Cookie信息 | |||
| config.setAllowCredentials(true); | |||
| //放行哪些原始域(请求方式) | |||
| config.addAllowedMethod("OPTIONS"); | |||
| config.addAllowedMethod("HEAD"); | |||
| config.addAllowedMethod("GET"); | |||
| config.addAllowedMethod("PUT"); | |||
| config.addAllowedMethod("POST"); | |||
| config.addAllowedMethod("DELETE"); | |||
| config.addAllowedMethod("PATCH"); | |||
| config.addAllowedHeader("*"); | |||
| //2.添加映射路径 | |||
| UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource(); | |||
| configSource.registerCorsConfiguration("/**", config); | |||
| //3.返回新的CorsFilter. | |||
| return new CorsFilter(configSource); | |||
| } | |||
| } | |||
| @@ -0,0 +1,44 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.config; | |||
| import lombok.Getter; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.context.annotation.Configuration; | |||
| /** | |||
| * @description k8s命名相关配置 | |||
| * | |||
| * @date 2020-05-13 | |||
| */ | |||
| @Getter | |||
| @Configuration | |||
| public class K8sNameConfig { | |||
| @Value("${k8s.nfs-root-path}") | |||
| private String nfsRootPath; | |||
| @Value("${k8s.namespace}") | |||
| private String namespace; | |||
| @Value("${minio.bucketName}") | |||
| private String fileBucket; | |||
| @Value("${train-job.docker-dataset-path}") | |||
| private String datasetPath; | |||
| } | |||
| @@ -0,0 +1,65 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.config; | |||
| import com.google.code.kaptcha.impl.DefaultKaptcha; | |||
| import com.google.code.kaptcha.util.Config; | |||
| import org.springframework.context.annotation.Bean; | |||
| import org.springframework.stereotype.Component; | |||
| import java.util.Properties; | |||
| /** | |||
| * @description 验证码配置 | |||
| * @date 2020-02-23 | |||
| */ | |||
| @Component | |||
| public class KaptchaConfig { | |||
| private final static String CODE_LENGTH = "4"; | |||
| private final static String SESSION_KEY = "verification_session_key"; | |||
| @Bean | |||
| public DefaultKaptcha defaultKaptcha() { | |||
| DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); | |||
| Properties properties = new Properties(); | |||
| // 设置边框 | |||
| properties.setProperty("kaptcha.border", "yes"); | |||
| // 设置边框颜色 | |||
| properties.setProperty("kaptcha.border.color", "105,179,90"); | |||
| // 设置字体颜色 | |||
| properties.setProperty("kaptcha.textproducer.font.color", "blue"); | |||
| // 设置图片宽度 | |||
| properties.setProperty("kaptcha.image.width", "108"); | |||
| // 设置图片高度 | |||
| properties.setProperty("kaptcha.image.height", "28"); | |||
| // 设置字体尺寸 | |||
| properties.setProperty("kaptcha.textproducer.font.size", "26"); | |||
| // 设置session key | |||
| properties.setProperty("kaptcha.session.key", SESSION_KEY); | |||
| // 设置验证码长度 | |||
| properties.setProperty("kaptcha.textproducer.char.length", CODE_LENGTH); | |||
| // 设置字体 | |||
| properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,黑体"); | |||
| //去噪点 | |||
| properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.NoNoise"); | |||
| Config config = new Config(properties); | |||
| defaultKaptcha.setConfig(config); | |||
| return defaultKaptcha; | |||
| } | |||
| } | |||
| @@ -0,0 +1,44 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.config; | |||
| import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; | |||
| import org.springframework.context.annotation.Bean; | |||
| import org.springframework.context.annotation.Configuration; | |||
| import java.time.LocalDateTime; | |||
| import java.time.format.DateTimeFormatter; | |||
| @Configuration | |||
| public class LocalDateTimeSerializerConfig { | |||
| @Value("${spring.jackson.date-format}") | |||
| private String pattern; | |||
| @Bean | |||
| public LocalDateTimeSerializer localDateTimeDeserializer() { | |||
| return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern)); | |||
| } | |||
| @Bean | |||
| public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() { | |||
| return builder -> builder.serializerByType(LocalDateTime.class, localDateTimeDeserializer()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,95 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.config; | |||
| import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; | |||
| import org.apache.ibatis.reflection.MetaObject; | |||
| import org.dubhe.constant.StringConstant; | |||
| import org.dubhe.domain.dto.UserDTO; | |||
| import org.dubhe.enums.SwitchEnum; | |||
| import org.dubhe.utils.DateUtil; | |||
| import org.dubhe.utils.JwtUtils; | |||
| import org.springframework.stereotype.Component; | |||
| import java.util.Objects; | |||
| /** | |||
| * @description 处理新增和更新的基础数据填充,配合BaseEntity和MyBatisPlusConfig使用 | |||
| * @date 2020-6-10 | |||
| */ | |||
| @Component | |||
| public class MetaHandlerConfig implements MetaObjectHandler { | |||
| private final String LOCK_USER_ID = "LOCK_USER_ID"; | |||
| /** | |||
| * 新增数据执行 | |||
| * | |||
| * @param metaObject | |||
| */ | |||
| @Override | |||
| public void insertFill(MetaObject metaObject) { | |||
| if (Objects.isNull(getFieldValByName(StringConstant.CREATE_TIME, metaObject))) { | |||
| this.setFieldValByName(StringConstant.CREATE_TIME, DateUtil.getCurrentTimestamp(), metaObject); | |||
| } | |||
| if (Objects.isNull(getFieldValByName(StringConstant.UPDATE_TIME, metaObject))) { | |||
| this.setFieldValByName(StringConstant.UPDATE_TIME, DateUtil.getCurrentTimestamp(), metaObject); | |||
| } | |||
| synchronized (LOCK_USER_ID){ | |||
| if (Objects.isNull(getFieldValByName(StringConstant.UPDATE_USER_ID, metaObject))) { | |||
| this.setFieldValByName(StringConstant.UPDATE_USER_ID, getUserId(), metaObject); | |||
| } | |||
| if (Objects.isNull(getFieldValByName(StringConstant.CREATE_USER_ID, metaObject))) { | |||
| this.setFieldValByName(StringConstant.CREATE_USER_ID, getUserId(), metaObject); | |||
| } | |||
| } | |||
| if (Objects.isNull(getFieldValByName(StringConstant.DELETED, metaObject))) { | |||
| this.setFieldValByName(StringConstant.DELETED, SwitchEnum.getBooleanValue(SwitchEnum.OFF.getValue()), metaObject); | |||
| } | |||
| } | |||
| /** | |||
| * 更新数据执行 | |||
| * | |||
| * @param metaObject | |||
| */ | |||
| @Override | |||
| public void updateFill(MetaObject metaObject) { | |||
| if (Objects.isNull(getFieldValByName(StringConstant.UPDATE_TIME, metaObject))) { | |||
| this.setFieldValByName(StringConstant.UPDATE_TIME, DateUtil.getCurrentTimestamp(), metaObject); | |||
| } | |||
| if (Objects.isNull(getFieldValByName(StringConstant.UPDATE_USER_ID, metaObject))) { | |||
| this.setFieldValByName(StringConstant.UPDATE_USER_ID, getUserId(), metaObject); | |||
| } | |||
| } | |||
| /** | |||
| * 获取用户ID | |||
| * | |||
| * @return | |||
| */ | |||
| private Long getUserId() { | |||
| UserDTO userDTO = JwtUtils.getCurrentUserDto(); | |||
| return Objects.isNull(userDTO) ? null : userDTO.getId(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,310 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.config; | |||
| import com.baomidou.mybatisplus.core.override.MybatisMapperProxy; | |||
| import com.baomidou.mybatisplus.core.parser.ISqlParser; | |||
| import com.baomidou.mybatisplus.core.parser.SqlParserHelper; | |||
| import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; | |||
| import com.baomidou.mybatisplus.extension.plugins.tenant.TenantHandler; | |||
| import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser; | |||
| import com.google.common.collect.Sets; | |||
| import net.sf.jsqlparser.expression.Expression; | |||
| import net.sf.jsqlparser.expression.LongValue; | |||
| import net.sf.jsqlparser.expression.operators.relational.ExpressionList; | |||
| import net.sf.jsqlparser.expression.operators.relational.InExpression; | |||
| import net.sf.jsqlparser.schema.Column; | |||
| import org.apache.ibatis.mapping.MappedStatement; | |||
| import org.apache.shiro.UnavailableSecurityManagerException; | |||
| import org.dubhe.annotation.DataPermission; | |||
| import org.dubhe.base.MagicNumConstant; | |||
| import org.dubhe.constant.PermissionConstant; | |||
| import org.dubhe.domain.dto.UserDTO; | |||
| import org.dubhe.domain.entity.Role; | |||
| import org.dubhe.enums.LogEnum; | |||
| import org.dubhe.utils.JwtUtils; | |||
| import org.dubhe.utils.LogUtil; | |||
| import org.springframework.beans.BeansException; | |||
| import org.springframework.context.ApplicationContext; | |||
| import org.springframework.context.ApplicationContextAware; | |||
| import org.springframework.context.ApplicationListener; | |||
| import org.springframework.context.annotation.Bean; | |||
| import org.springframework.context.annotation.Configuration; | |||
| import org.springframework.context.event.ContextRefreshedEvent; | |||
| import org.springframework.core.annotation.AnnotationUtils; | |||
| import org.springframework.transaction.annotation.EnableTransactionManagement; | |||
| import org.springframework.util.CollectionUtils; | |||
| import java.lang.annotation.Annotation; | |||
| import java.lang.reflect.Field; | |||
| import java.lang.reflect.Method; | |||
| import java.lang.reflect.Proxy; | |||
| import java.util.*; | |||
| import java.util.stream.Collectors; | |||
| /** | |||
| * @description MybatisPlus配置类 | |||
| * @date 2020-06-24 | |||
| */ | |||
| @EnableTransactionManagement | |||
| @Configuration | |||
| public class MybatisPlusConfig implements ApplicationListener<ContextRefreshedEvent>, ApplicationContextAware { | |||
| /** | |||
| * 以此字段作为租户实现数据隔离 | |||
| */ | |||
| private static final String TENANT_ID_COLUMN = "create_user_id"; | |||
| /** | |||
| * 以0作为公共数据的标识 | |||
| */ | |||
| private static final long PUBLIC_TENANT_ID = MagicNumConstant.ZERO; | |||
| private static final Set<Long> PUBLIC_TENANT_ID_SET = new HashSet<Long>() {{ | |||
| add(PUBLIC_TENANT_ID); | |||
| }}; | |||
| private static final String PACKAGE_SEPARATOR = "."; | |||
| private static final Set<String> SELECT_PERMISSION = new HashSet<String>() {{ | |||
| add(PermissionConstant.SELECT); | |||
| }}; | |||
| private static final Set<String> UPDATE_DELETE_PERMISSION = new HashSet<String>() {{ | |||
| add(PermissionConstant.UPDATE); | |||
| add(PermissionConstant.DELETE); | |||
| }}; | |||
| private static final String SELECT_STR = "select"; | |||
| /** | |||
| * 优先级高于dataFilters,如果ignore,则不进行sql注入 | |||
| */ | |||
| private Map<String, Set<String>> dataFilters = new HashMap<>(); | |||
| private ApplicationContext applicationContext; | |||
| public Set<Long> tenantId; | |||
| /** | |||
| * mybatis plus 分页插件 | |||
| * 其中增加了通过多租户实现了数据权限功能 | |||
| * | |||
| * @return | |||
| */ | |||
| @Bean | |||
| public PaginationInterceptor paginationInterceptor() { | |||
| PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); | |||
| List<ISqlParser> sqlParserList = new ArrayList<>(); | |||
| TenantSqlParser tenantSqlParser = new TenantSqlParser(); | |||
| tenantSqlParser.setTenantHandler(new TenantHandler() { | |||
| @Override | |||
| public Expression getTenantId(boolean where) { | |||
| Set<Long> tenants = tenantId; | |||
| final boolean multipleTenantIds = tenants.size() > MagicNumConstant.ONE; | |||
| if (multipleTenantIds) { | |||
| return multipleTenantIdCondition(tenants); | |||
| } else { | |||
| return singleTenantIdCondition(tenants); | |||
| } | |||
| } | |||
| private Expression singleTenantIdCondition(Set<Long> tenants) { | |||
| return new LongValue((Long) tenants.toArray()[0]); | |||
| } | |||
| private Expression multipleTenantIdCondition(Set<Long> tenants) { | |||
| final InExpression inExpression = new InExpression(); | |||
| inExpression.setLeftExpression(new Column(getTenantIdColumn())); | |||
| final ExpressionList itemsList = new ExpressionList(); | |||
| final List<Expression> inValues = new ArrayList<>(tenants.size()); | |||
| tenants.forEach(i -> | |||
| inValues.add(new LongValue(i)) | |||
| ); | |||
| itemsList.setExpressions(inValues); | |||
| inExpression.setRightItemsList(itemsList); | |||
| return inExpression; | |||
| } | |||
| @Override | |||
| public String getTenantIdColumn() { | |||
| return TENANT_ID_COLUMN; | |||
| } | |||
| @Override | |||
| public boolean doTableFilter(String tableName) { | |||
| return false; | |||
| } | |||
| }); | |||
| sqlParserList.add(tenantSqlParser); | |||
| paginationInterceptor.setSqlParserList(sqlParserList); | |||
| paginationInterceptor.setSqlParserFilter(metaObject -> { | |||
| MappedStatement ms = SqlParserHelper.getMappedStatement(metaObject); | |||
| String method = ms.getId(); | |||
| if (!dataFilters.containsKey(method) || isAdmin()) { | |||
| return true; | |||
| } | |||
| Set<String> permission = dataFilters.get(method); | |||
| tenantId = getTenantId(permission); | |||
| return false; | |||
| }); | |||
| return paginationInterceptor; | |||
| } | |||
| /** | |||
| * 判断用户是否是管理员 | |||
| * 如果未登录,无法请求任何接口,所以不会到该层,因此匿名认为是定时任务,给予admin权限。 | |||
| * | |||
| * @return 判断用户是否是管理员 | |||
| */ | |||
| private boolean isAdmin() { | |||
| UserDTO user; | |||
| try { | |||
| user = JwtUtils.getCurrentUserDto(); | |||
| } catch (UnavailableSecurityManagerException e) { | |||
| return true; | |||
| } | |||
| if (Objects.isNull(user)) { | |||
| return true; | |||
| } | |||
| List<Role> roles; | |||
| if ((roles = user.getRoles()) == null) { | |||
| return false; | |||
| } | |||
| Set<String> permissions = roles.stream().map(Role::getPermission).collect(Collectors.toSet()); | |||
| if (CollectionUtils.isEmpty(permissions)) { | |||
| return false; | |||
| } | |||
| return user.getId() == PermissionConstant.ANONYMOUS_USER || user.getId() == PermissionConstant.ADMIN_USER_ID; | |||
| } | |||
| /** | |||
| * 如果是管理员,在前一步isAdmin已过滤; | |||
| * 如果是匿名用户,在shiro层被过滤; | |||
| * 因此只会是无角色、权限用户或普通用户 | |||
| * | |||
| * @return Set<Long> 租户ID集合 | |||
| */ | |||
| private Set<Long> getTenantId(Set<String> permission) { | |||
| UserDTO user = JwtUtils.getCurrentUserDto(); | |||
| List<Role> roles; | |||
| if (Objects.isNull(user) || (roles = user.getRoles()) == null) { | |||
| if (permission.contains(PermissionConstant.SELECT)) { | |||
| return PUBLIC_TENANT_ID_SET; | |||
| } | |||
| return Collections.EMPTY_SET; | |||
| } | |||
| Set<String> permissions = roles.stream().map(Role::getPermission).collect(Collectors.toSet()); | |||
| if (CollectionUtils.isEmpty(permissions)) { | |||
| if (permission.contains(PermissionConstant.SELECT)) { | |||
| return PUBLIC_TENANT_ID_SET; | |||
| } | |||
| return Collections.EMPTY_SET; | |||
| } | |||
| if (permission.contains(PermissionConstant.SELECT)) { | |||
| return new HashSet<Long>() {{ | |||
| add(PUBLIC_TENANT_ID); | |||
| add(user.getId()); | |||
| }}; | |||
| } | |||
| return new HashSet<Long>() {{ | |||
| add(user.getId()); | |||
| }}; | |||
| } | |||
| /** | |||
| * 设置上下文 | |||
| * #需要通过上下文 获取SpringBean | |||
| * | |||
| * @param applicationContext spring上下文 | |||
| * @throws BeansException 找不到bean异常 | |||
| */ | |||
| @Override | |||
| public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { | |||
| this.applicationContext = applicationContext; | |||
| } | |||
| @Override | |||
| public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) { | |||
| Class<? extends Annotation> annotationClass = DataPermission.class; | |||
| Map<String, Object> beanWithAnnotation = applicationContext.getBeansWithAnnotation(annotationClass); | |||
| Set<Map.Entry<String, Object>> entitySet = beanWithAnnotation.entrySet(); | |||
| for (Map.Entry<String, Object> entry : entitySet) { | |||
| Proxy proxy = (Proxy) entry.getValue(); | |||
| Class clazz = getMapperClass(proxy); | |||
| populateDataFilters(clazz); | |||
| } | |||
| } | |||
| /** | |||
| * 根据mapper对应代理对象获取Class | |||
| * | |||
| * @param proxy mapper对应代理对象 | |||
| * @return | |||
| */ | |||
| private Class getMapperClass(Proxy proxy) { | |||
| try { | |||
| Field field = proxy.getClass().getSuperclass().getDeclaredField("h"); | |||
| field.setAccessible(true); | |||
| MybatisMapperProxy mapperProxy = (MybatisMapperProxy) field.get(proxy); | |||
| field = mapperProxy.getClass().getDeclaredField("mapperInterface"); | |||
| field.setAccessible(true); | |||
| return (Class) field.get(mapperProxy); | |||
| } catch (NoSuchFieldException | IllegalAccessException e) { | |||
| LogUtil.error(LogEnum.BIZ_DATASET, "reflect error", e); | |||
| } | |||
| return null; | |||
| } | |||
| /** | |||
| * 填充数据权限过滤,处理那些需要排除的方法 | |||
| * | |||
| * @param clazz 需要处理的类(mapper) | |||
| */ | |||
| private void populateDataFilters(Class clazz) { | |||
| if (clazz == null) { | |||
| return; | |||
| } | |||
| Method[] methods = clazz.getMethods(); | |||
| DataPermission dataPermission = AnnotationUtils.findAnnotation((Class<?>) clazz, DataPermission.class); | |||
| Set<String> ignores = Sets.newHashSet(dataPermission.ignores()); | |||
| for (Method method : methods) { | |||
| if (ignores.contains(method.getName())) { | |||
| continue; | |||
| } | |||
| Set<String> permission = getDataPermission(method); | |||
| dataFilters.put(clazz.getName() + PACKAGE_SEPARATOR + method.getName(), permission); | |||
| } | |||
| } | |||
| /** | |||
| * 获取方法上权限注解 | |||
| * 权限注解包含 | |||
| * 1.用户拥有指定权限才可以执行该方法:比如 PermissionConstant.SELECT 表示用户必须拥有select权限,才可以使用该方法 | |||
| * 2.方法权限校验排除:比如 ignores = {"insert"} 表示insert方法不做权限处理 | |||
| * | |||
| * @param method 方法对象 | |||
| * @return | |||
| */ | |||
| private Set<String> getDataPermission(Method method) { | |||
| DataPermission dataPermission = AnnotationUtils.findAnnotation(method, DataPermission.class); | |||
| // 无注解时以方法名判断 | |||
| if (dataPermission == null) { | |||
| if (method.getName().contains(SELECT_STR)) { | |||
| return SELECT_PERMISSION; | |||
| } | |||
| return UPDATE_DELETE_PERMISSION; | |||
| } | |||
| return Sets.newHashSet(dataPermission.permission()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,41 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.config; | |||
| import lombok.Data; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.stereotype.Component; | |||
| /** | |||
| * @description NFS config | |||
| * @create 2020/5/13 | |||
| */ | |||
| @Data | |||
| @Component | |||
| public class NfsConfig { | |||
| @Value("${k8s.nfs}") | |||
| private String nfsIp; | |||
| @Value("${k8s.nfs-root-path}") | |||
| private String rootDir; | |||
| @Value("/${minio.bucketName}/") | |||
| private String bucket; | |||
| } | |||
| @@ -0,0 +1,214 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.config; | |||
| import cn.hutool.core.lang.Assert; | |||
| import com.alibaba.fastjson.JSON; | |||
| import com.alibaba.fastjson.parser.ParserConfig; | |||
| import com.alibaba.fastjson.serializer.SerializerFeature; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| import org.apache.commons.codec.digest.DigestUtils; | |||
| import org.dubhe.utils.StringUtils; | |||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; | |||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | |||
| import org.springframework.boot.autoconfigure.data.redis.RedisProperties; | |||
| import org.springframework.boot.context.properties.EnableConfigurationProperties; | |||
| import org.springframework.cache.Cache; | |||
| import org.springframework.cache.annotation.CachingConfigurerSupport; | |||
| import org.springframework.cache.annotation.EnableCaching; | |||
| import org.springframework.cache.interceptor.CacheErrorHandler; | |||
| import org.springframework.cache.interceptor.KeyGenerator; | |||
| import org.springframework.context.annotation.Bean; | |||
| import org.springframework.context.annotation.Configuration; | |||
| import org.springframework.data.redis.cache.RedisCacheConfiguration; | |||
| import org.springframework.data.redis.connection.RedisConnectionFactory; | |||
| import org.springframework.data.redis.core.RedisOperations; | |||
| import org.springframework.data.redis.core.RedisTemplate; | |||
| import org.springframework.data.redis.serializer.RedisSerializationContext; | |||
| import org.springframework.data.redis.serializer.RedisSerializer; | |||
| import java.nio.charset.Charset; | |||
| import java.nio.charset.StandardCharsets; | |||
| import java.time.Duration; | |||
| import java.util.HashMap; | |||
| import java.util.Map; | |||
| /** | |||
| * @description redis配置类 | |||
| * @date 2020-03-25 | |||
| */ | |||
| @Slf4j | |||
| @Configuration | |||
| @EnableCaching | |||
| @ConditionalOnClass(RedisOperations.class) | |||
| @EnableConfigurationProperties(RedisProperties.class) | |||
| public class RedisConfig extends CachingConfigurerSupport { | |||
| /** | |||
| * 设置 redis 数据默认过期时间,默认2小时 | |||
| * 设置@cacheable 序列化方式 | |||
| */ | |||
| @Bean | |||
| public RedisCacheConfiguration redisCacheConfiguration() { | |||
| FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); | |||
| RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig(); | |||
| configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofHours(2)); | |||
| return configuration; | |||
| } | |||
| @SuppressWarnings("all") | |||
| @Bean(name = "redisTemplate") | |||
| @ConditionalOnMissingBean(name = "redisTemplate") | |||
| public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { | |||
| RedisTemplate<Object, Object> template = new RedisTemplate<>(); | |||
| //序列化 | |||
| FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); | |||
| // value值的序列化采用fastJsonRedisSerializer | |||
| template.setValueSerializer(fastJsonRedisSerializer); | |||
| template.setHashValueSerializer(fastJsonRedisSerializer); | |||
| // 全局开启AutoType,这里方便开发,使用全局的方式 | |||
| ParserConfig.getGlobalInstance().setAutoTypeSupport(true); | |||
| // 建议使用这种方式,小范围指定白名单 | |||
| // ParserConfig.getGlobalInstance().addAccept("org.dubhe.domain"); | |||
| // key的序列化采用StringRedisSerializer | |||
| template.setKeySerializer(new StringRedisSerializer()); | |||
| template.setHashKeySerializer(new StringRedisSerializer()); | |||
| template.setConnectionFactory(redisConnectionFactory); | |||
| return template; | |||
| } | |||
| /** | |||
| * 自定义缓存key生成策略,默认将使用该策略 | |||
| */ | |||
| @Bean | |||
| @Override | |||
| public KeyGenerator keyGenerator() { | |||
| return (target, method, params) -> { | |||
| Map<String, Object> container = new HashMap<>(3); | |||
| Class<?> targetClassClass = target.getClass(); | |||
| // 类地址 | |||
| container.put("class", targetClassClass.toGenericString()); | |||
| // 方法名称 | |||
| container.put("methodName", method.getName()); | |||
| // 包名称 | |||
| container.put("package", targetClassClass.getPackage()); | |||
| // 参数列表 | |||
| for (int i = 0; i < params.length; i++) { | |||
| container.put(String.valueOf(i), params[i]); | |||
| } | |||
| // 转为JSON字符串 | |||
| String jsonString = JSON.toJSONString(container); | |||
| // 做SHA256 Hash计算,得到一个SHA256摘要作为Key | |||
| return DigestUtils.sha256Hex(jsonString); | |||
| }; | |||
| } | |||
| @Bean | |||
| @Override | |||
| public CacheErrorHandler errorHandler() { | |||
| // 异常处理,当Redis发生异常时,打印日志,但是程序正常走 | |||
| log.info("初始化 -> [{}]", "Redis CacheErrorHandler"); | |||
| return new CacheErrorHandler() { | |||
| @Override | |||
| public void handleCacheGetError(RuntimeException e, Cache cache, Object key) { | |||
| log.error("Redis occur handleCacheGetError:key -> [{}]", key, e); | |||
| } | |||
| @Override | |||
| public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) { | |||
| log.error("Redis occur handleCachePutError:key -> [{}];value -> [{}]", key, value, e); | |||
| } | |||
| @Override | |||
| public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) { | |||
| log.error("Redis occur handleCacheEvictError:key -> [{}]", key, e); | |||
| } | |||
| @Override | |||
| public void handleCacheClearError(RuntimeException e, Cache cache) { | |||
| log.error("Redis occur handleCacheClearError:", e); | |||
| } | |||
| }; | |||
| } | |||
| } | |||
| /** | |||
| * Value 序列化 | |||
| * | |||
| * @param <T> | |||
| */ | |||
| class FastJsonRedisSerializer<T> implements RedisSerializer<T> { | |||
| private Class<T> clazz; | |||
| FastJsonRedisSerializer(Class<T> clazz) { | |||
| super(); | |||
| this.clazz = clazz; | |||
| } | |||
| @Override | |||
| public byte[] serialize(T t) { | |||
| if (t == null) { | |||
| return new byte[0]; | |||
| } | |||
| return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(StandardCharsets.UTF_8); | |||
| } | |||
| @Override | |||
| public T deserialize(byte[] bytes) { | |||
| if (bytes == null || bytes.length <= 0) { | |||
| return null; | |||
| } | |||
| String str = new String(bytes, StandardCharsets.UTF_8); | |||
| return JSON.parseObject(str, clazz); | |||
| } | |||
| } | |||
| /** | |||
| * 重写序列化器 | |||
| * | |||
| */ | |||
| class StringRedisSerializer implements RedisSerializer<Object> { | |||
| private final Charset charset; | |||
| StringRedisSerializer() { | |||
| this(StandardCharsets.UTF_8); | |||
| } | |||
| private StringRedisSerializer(Charset charset) { | |||
| Assert.notNull(charset, "Charset must not be null!"); | |||
| this.charset = charset; | |||
| } | |||
| @Override | |||
| public String deserialize(byte[] bytes) { | |||
| return (bytes == null ? null : new String(bytes, charset)); | |||
| } | |||
| @Override | |||
| public byte[] serialize(Object object) { | |||
| String string = JSON.toJSONString(object); | |||
| if (StringUtils.isBlank(string)) { | |||
| return null; | |||
| } | |||
| string = string.replace("\"", ""); | |||
| return string.getBytes(charset); | |||
| } | |||
| } | |||
| @@ -0,0 +1,70 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.config; | |||
| import org.springframework.context.annotation.PropertySource; | |||
| import org.springframework.context.i18n.LocaleContextHolder; | |||
| import java.util.HashMap; | |||
| import java.util.Locale; | |||
| import java.util.Map; | |||
| import java.util.ResourceBundle; | |||
| /** | |||
| * @description 加载配置 | |||
| * @date 2020-03-15 | |||
| */ | |||
| @PropertySource(value = {"classpath:config/thirdParty.properties", "classpath:i18n/messages*.properties"}) | |||
| public final class Resources { | |||
| /** | |||
| * 第三方登录配置 | |||
| */ | |||
| public static final ResourceBundle THIRDPARTY = ResourceBundle.getBundle("config/thirdParty"); | |||
| /** | |||
| * 国际化信息 | |||
| */ | |||
| private static final Map<String, ResourceBundle> MESSAGES = new HashMap<String, ResourceBundle>(); | |||
| /** | |||
| * 国际化信息 | |||
| */ | |||
| public static String getMessage(String key, Object... params) { | |||
| Locale locale = LocaleContextHolder.getLocale(); | |||
| ResourceBundle message = MESSAGES.get(locale.getLanguage()); | |||
| if (message == null) { | |||
| synchronized (MESSAGES) { | |||
| message = MESSAGES.get(locale.getLanguage()); | |||
| if (message == null) { | |||
| message = ResourceBundle.getBundle("i18n/messages", locale); | |||
| MESSAGES.put(locale.getLanguage(), message); | |||
| } | |||
| } | |||
| } | |||
| if (params != null && params.length > 0) { | |||
| return String.format(message.getString(key), params); | |||
| } | |||
| return message.getString(key); | |||
| } | |||
| /** | |||
| * 清除国际化信息 | |||
| */ | |||
| public static void flushMessage() { | |||
| MESSAGES.clear(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,36 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.config; | |||
| import org.springframework.context.annotation.Configuration; | |||
| import org.springframework.security.config.annotation.web.builders.HttpSecurity; | |||
| import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; | |||
| /** | |||
| * @description 关闭Security | |||
| * @date 2020-03-25 | |||
| */ | |||
| @Configuration | |||
| public class SecurityConfig extends WebSecurityConfigurerAdapter { | |||
| @Override | |||
| protected void configure(HttpSecurity http) throws Exception { | |||
| http.authorizeRequests().antMatchers("/**").permitAll().and().csrf().disable(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,138 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.config; | |||
| import com.fasterxml.classmate.TypeResolver; | |||
| import com.google.common.base.Predicates; | |||
| import io.swagger.annotations.ApiModel; | |||
| import io.swagger.annotations.ApiModelProperty; | |||
| import lombok.Data; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.context.annotation.Bean; | |||
| import org.springframework.context.annotation.Configuration; | |||
| import org.springframework.core.Ordered; | |||
| import org.springframework.data.domain.Pageable; | |||
| import springfox.documentation.builders.ApiInfoBuilder; | |||
| import springfox.documentation.builders.ParameterBuilder; | |||
| import springfox.documentation.builders.PathSelectors; | |||
| import springfox.documentation.schema.AlternateTypeRule; | |||
| import springfox.documentation.schema.AlternateTypeRuleConvention; | |||
| import springfox.documentation.schema.ModelRef; | |||
| import springfox.documentation.service.ApiInfo; | |||
| import springfox.documentation.service.Parameter; | |||
| import springfox.documentation.spi.DocumentationType; | |||
| import springfox.documentation.spring.web.plugins.Docket; | |||
| import springfox.documentation.swagger2.annotations.EnableSwagger2; | |||
| import java.sql.Timestamp; | |||
| import java.util.ArrayList; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| import static com.google.common.collect.Lists.newArrayList; | |||
| import static springfox.documentation.schema.AlternateTypeRules.newRule; | |||
| /** | |||
| * @description api页面 /swagger-ui.html | |||
| * @date 2020-03-25 | |||
| */ | |||
| @Configuration | |||
| @EnableSwagger2 | |||
| public class SwaggerConfig { | |||
| @Value("${jwt.header}") | |||
| private String tokenHeader; | |||
| @Value("${jwt.token-start-with}") | |||
| private String tokenStartWith; | |||
| @Value("${swagger.enabled}") | |||
| private Boolean enabled; | |||
| @Value("${server.rest-version}") | |||
| private String restVersion; | |||
| @Bean | |||
| @SuppressWarnings("all") | |||
| public Docket createRestApi() { | |||
| List<Parameter> pars = new ArrayList<>(); | |||
| pars.add(new ParameterBuilder().name(tokenHeader).description("token") | |||
| .modelRef(new ModelRef("string")) | |||
| .parameterType("header") | |||
| .defaultValue(tokenStartWith + " ") | |||
| .required(true) | |||
| .build()); | |||
| pars.add(new ParameterBuilder().name("version").description("版本") | |||
| .modelRef(new ModelRef("string")) | |||
| .parameterType("path") | |||
| .defaultValue(restVersion) | |||
| .required(false) | |||
| .build()); | |||
| return new Docket(DocumentationType.SWAGGER_2) | |||
| .enable(enabled) | |||
| .apiInfo(apiInfo()) | |||
| .select() | |||
| .paths(Predicates.not(PathSelectors.regex("/error.*"))) | |||
| .build().directModelSubstitute(Timestamp.class, Date.class) | |||
| .globalOperationParameters(pars); | |||
| } | |||
| private ApiInfo apiInfo() { | |||
| return new ApiInfoBuilder() | |||
| .title("之江天枢一站式人工智能开源平台") | |||
| .version("1.0") | |||
| .build(); | |||
| } | |||
| } | |||
| /** | |||
| * 将Pageable转换展示在swagger中 | |||
| */ | |||
| @Configuration | |||
| class SwaggerDataConfig { | |||
| @Bean | |||
| public AlternateTypeRuleConvention pageableConvention(final TypeResolver resolver) { | |||
| return new AlternateTypeRuleConvention() { | |||
| @Override | |||
| public int getOrder() { | |||
| return Ordered.HIGHEST_PRECEDENCE; | |||
| } | |||
| @Override | |||
| public List<AlternateTypeRule> rules() { | |||
| return newArrayList(newRule(resolver.resolve(Pageable.class), resolver.resolve(Page.class))); | |||
| } | |||
| }; | |||
| } | |||
| @ApiModel | |||
| @Data | |||
| private static class Page { | |||
| @ApiModelProperty("页码 (0..N)") | |||
| private Integer page; | |||
| @ApiModelProperty("每页显示的数目") | |||
| private Integer size; | |||
| @ApiModelProperty("以下列格式排序标准:property[,asc | desc]。 默认排序顺序为升序。 支持多种排序条件:如:id,asc") | |||
| private List<String> sort; | |||
| } | |||
| } | |||
| @@ -0,0 +1,39 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.config; | |||
| import lombok.Data; | |||
| import org.springframework.boot.context.properties.ConfigurationProperties; | |||
| import org.springframework.stereotype.Component; | |||
| /** | |||
| * @description harbor相关配置 | |||
| * @date 2020-07-17 | |||
| */ | |||
| @Data | |||
| @Component | |||
| @ConfigurationProperties(prefix = "harbor") | |||
| public class TrainHarborConfig { | |||
| private String address; | |||
| private String username; | |||
| private String password; | |||
| private String modelName; | |||
| } | |||
| @@ -0,0 +1,50 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.config; | |||
| import org.dubhe.interceptor.K8sCallBackPodInterceptor; | |||
| import org.dubhe.utils.K8sCallBackTool; | |||
| import org.springframework.context.annotation.Configuration; | |||
| import org.springframework.web.servlet.config.annotation.InterceptorRegistration; | |||
| import org.springframework.web.servlet.config.annotation.InterceptorRegistry; | |||
| import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | |||
| import javax.annotation.Resource; | |||
| /** | |||
| * @description Web Mvc Config | |||
| * | |||
| * @date 2020-05-28 | |||
| */ | |||
| @Configuration | |||
| public class WebMvcConfig implements WebMvcConfigurer { | |||
| @Resource | |||
| private K8sCallBackPodInterceptor k8sCallBackPodInterceptor; | |||
| @Override | |||
| public void addInterceptors(InterceptorRegistry registry) { | |||
| InterceptorRegistration registration = registry.addInterceptor(k8sCallBackPodInterceptor); | |||
| // 拦截配置 | |||
| registration.addPathPatterns(K8sCallBackTool.getK8sCallbackPaths()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,35 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.config; | |||
| import org.dubhe.handle.CustomRequestMappingHandlerMapping; | |||
| import org.springframework.boot.SpringBootConfiguration; | |||
| import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations; | |||
| import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; | |||
| /** | |||
| * @description API版本控制 | |||
| * @date 2020-04-06 | |||
| */ | |||
| @SpringBootConfiguration | |||
| public class WebMvcRegistrationsConfig implements WebMvcRegistrations { | |||
| @Override | |||
| public RequestMappingHandlerMapping getRequestMappingHandlerMapping() { | |||
| return new CustomRequestMappingHandlerMapping(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,46 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.constant; | |||
| import lombok.Getter; | |||
| /** | |||
| * @description 算法枚举类 | |||
| * @date 2020-05-12 | |||
| */ | |||
| @Getter | |||
| public enum AlgorithmSourceEnum { | |||
| /** | |||
| * MINE 算法来源 我的算法 | |||
| */ | |||
| MINE(1, "MINE"), | |||
| /** | |||
| * PRE 算法来源 预置算法 | |||
| */ | |||
| PRE(2,"PRE"); | |||
| private Integer status; | |||
| private String message; | |||
| AlgorithmSourceEnum(Integer status, String message) { | |||
| this.status = status; | |||
| this.message = message; | |||
| } | |||
| } | |||
| @@ -0,0 +1,39 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.constant; | |||
| /** | |||
| * @Description 数字常量 | |||
| * @Date 2020-6-9 | |||
| */ | |||
| public class NumberConstant { | |||
| public final static int NUMBER_0 = 0; | |||
| public final static int NUMBER_1 = 1; | |||
| public final static int NUMBER_2 = 2; | |||
| public final static int NUMBER_3 = 3; | |||
| public final static int NUMBER_5 = 5; | |||
| public final static int NUMBER_10 = 10; | |||
| public final static int NUMBER_30 = 30; | |||
| public final static int NUMBER_50 = 50; | |||
| public final static int NUMBER_60 = 60; | |||
| public final static int HOUR_SECOND = 60 * 60; | |||
| public final static int DAY_SECOND = 60 * 60 * 24; | |||
| public final static int WEEK_SECOND = 60 * 60 * 24 * 7; | |||
| public final static int MAX_PAGE_SIZE = 2000; | |||
| } | |||
| @@ -0,0 +1,40 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.constant; | |||
| import lombok.Data; | |||
| import org.springframework.stereotype.Component; | |||
| /** | |||
| * @description: 权限常量 | |||
| * @since: 2020-05-25 14:39 | |||
| */ | |||
| @Component | |||
| @Data | |||
| public class PermissionConstant { | |||
| /** | |||
| * 超级用户 | |||
| */ | |||
| public static final long ADMIN_USER_ID = 1L; | |||
| public static final long ANONYMOUS_USER = -1L; | |||
| public static final String SELECT = "select"; | |||
| public static final String UPDATE = "update"; | |||
| public static final String DELETE = "delete"; | |||
| } | |||
| @@ -0,0 +1,66 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.constant; | |||
| /** | |||
| * @description 权限标识,对应 menu 表中的 permission 字段 | |||
| * @date 2020-05-14 | |||
| */ | |||
| public final class Permissions { | |||
| /** | |||
| * 数据管理 | |||
| */ | |||
| public static final String DATA = "data"; | |||
| public static final String DATA_DATASET = "data:dataset"; | |||
| /** | |||
| * 模型开发 | |||
| */ | |||
| public static final String DEVELOPMENT = "development"; | |||
| public static final String DEVELOPMENT_NOTEBOOK = "development:notebook"; | |||
| public static final String DEVELOPMENT_ALGORITHM = "development:algorithm"; | |||
| /** | |||
| * 训练管理 | |||
| */ | |||
| public static final String TRAINING = "training"; | |||
| public static final String TRAINING_IMAGE = "training:image"; | |||
| public static final String TRAINING_JOB = "training:job"; | |||
| /** | |||
| * 模型管理 | |||
| */ | |||
| public static final String MODEL = "model"; | |||
| public static final String MODEL_MODEL = "model:model"; | |||
| /** | |||
| * 控制台 | |||
| */ | |||
| public static final String SYSTEM = "system"; | |||
| public static final String SYSTEM_USER = "system:user"; | |||
| public static final String SYSTEM_ROLE = "system:role"; | |||
| public static final String SYSTEM_MENU = "system:menu"; | |||
| public static final String SYSTEM_DICT = "system:dict"; | |||
| public static final String SYSTEM_NODE = "system:node"; | |||
| public static final String SYSTEM_LOG = "system:log"; | |||
| public static final String SYSTEM_TEAM = "system:team"; | |||
| private Permissions() { | |||
| } | |||
| } | |||
| @@ -0,0 +1,46 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.constant; | |||
| /** | |||
| * @description 字符串constant | |||
| * @date 2020-05-14 | |||
| */ | |||
| public final class StringConstant { | |||
| public static final String MSIE = "MSIE"; | |||
| public static final String MOZILLA = "Mozilla"; | |||
| /** | |||
| * 公共字段 | |||
| */ | |||
| public static final String CREATE_TIME = "createTime"; | |||
| public static final String UPDATE_TIME = "updateTime"; | |||
| public static final String UPDATE_USER_ID = "updateUserId"; | |||
| public static final String CREATE_USER_ID = "createUserId"; | |||
| public static final String DELETED = "deleted"; | |||
| public static final String UTF8 = "utf-8"; | |||
| /** | |||
| * 测试环境 | |||
| */ | |||
| public static final String PROFILE_ACTIVE_TEST = "test"; | |||
| private StringConstant() { | |||
| } | |||
| } | |||
| @@ -0,0 +1,46 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.constant; | |||
| /** | |||
| * @description 符号常量 | |||
| * @Date 2020-5-29 | |||
| */ | |||
| public class SymbolConstant { | |||
| public static final String SLASH = "/"; | |||
| public static final String COMMA = ","; | |||
| public static final String COLON = ":"; | |||
| public static final String LINEBREAK = "\n"; | |||
| public static final String BLANK = ""; | |||
| public static final String QUESTION = "?"; | |||
| public static final String ZERO = "0"; | |||
| public static final String DOT = "."; | |||
| public static final String TOKEN = "token"; | |||
| public static final String GET = "get"; | |||
| public static final String SET = "set"; | |||
| public static final String BRACKETS = "{}"; | |||
| public static final String BACKSLASH = "\\"; | |||
| public static final String BACKSLASH_MARK= "\\\""; | |||
| public static final String DOUBLE_MARK= "\"\""; | |||
| public static final String MARK= "\""; | |||
| private SymbolConstant() { | |||
| } | |||
| } | |||
| @@ -0,0 +1,47 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.constant; | |||
| import lombok.Data; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.stereotype.Component; | |||
| /** | |||
| * @description 算法常量 | |||
| * @date 2020-06-02 | |||
| */ | |||
| @Data | |||
| @Component | |||
| public class TrainAlgorithmConstant { | |||
| @Value("${train-algorithm.is-train-out}") | |||
| private Boolean isTrainOut; | |||
| @Value("${train-algorithm.is-train-log}") | |||
| private Boolean isTrainLog; | |||
| @Value("${train-algorithm.is-visualized-log}") | |||
| private Boolean isVisualizedLog; | |||
| @Value("${train-algorithm.algorithm-source}") | |||
| private Integer algorithmSource; | |||
| @Value("${train-algorithm.fork}") | |||
| private Boolean fork; | |||
| } | |||
| @@ -0,0 +1,100 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.constant; | |||
| import lombok.Data; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.stereotype.Component; | |||
| /** | |||
| * @description 训练常量 | |||
| * @create: 2020-05-12 | |||
| */ | |||
| @Component | |||
| @Data | |||
| public class TrainJobConstant { | |||
| @Value("${train-job.namespace}") | |||
| private String namespace; | |||
| @Value("${train-job.version-label}") | |||
| private String versionLabel; | |||
| @Value("${train-job.separator}") | |||
| private String separator; | |||
| @Value("${train-job.pod-name}") | |||
| private String podName; | |||
| @Value("${train-job.python-format}") | |||
| private String pythonFormat; | |||
| @Value("${train-job.manage}") | |||
| private String manage; | |||
| @Value("${train-job.out-path}") | |||
| private String outPath; | |||
| @Value("${train-job.log-path}") | |||
| private String logPath; | |||
| @Value("${train-job.visualized-log-path}") | |||
| private String visualizedLogPath; | |||
| @Value("${train-job.docker-dataset-path}") | |||
| private String dockerDatasetPath; | |||
| @Value("${train-job.docker-train-path}") | |||
| private String dockerTrainPath; | |||
| @Value("${train-job.docker-out-path}") | |||
| private String dockerOutPath; | |||
| @Value("${train-job.docker-log-path}") | |||
| private String dockerLogPath; | |||
| @Value("${train-job.docker-dataset}") | |||
| private String dockerDataset; | |||
| @Value("${train-job.docker-visualized-log-path}") | |||
| private String dockerVisualizedLogPath; | |||
| @Value("${train-job.load-path}") | |||
| private String loadPath; | |||
| @Value("${train-job.load-key}") | |||
| private String loadKey; | |||
| @Value("${train-job.eight}") | |||
| private String eight; | |||
| @Value("${train-job.plus-eight}") | |||
| private String plusEight; | |||
| public static final String TRAIN_ID = "trainId"; | |||
| public static final String TRAIN_VERSION = "trainVersion"; | |||
| public static final String RUN_TIME = "runtime"; | |||
| public static final String TRAIN_STATUS = "trainStatus"; | |||
| public static final String CREATE_TIME = "createTime"; | |||
| public static final String ALGORITHM_NAME = "algorithmName"; | |||
| } | |||
| @@ -0,0 +1,36 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.constant; | |||
| import org.springframework.stereotype.Component; | |||
| import lombok.Data; | |||
| /** | |||
| * @description 算法用途 | |||
| * @date: 2020-06-23 | |||
| */ | |||
| @Component | |||
| @Data | |||
| public class UserAuxiliaryInfoConstant { | |||
| public static final String ALGORITHM_USAGE ="algorithem_usage"; | |||
| } | |||
| @@ -0,0 +1,65 @@ | |||
| /** | |||
| * Copyright 2019-2020 Zheng Jie | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package org.dubhe.domain.dto; | |||
| import com.fasterxml.jackson.annotation.JsonIgnore; | |||
| import io.swagger.annotations.ApiModelProperty; | |||
| import lombok.Data; | |||
| import org.dubhe.domain.entity.Role; | |||
| import org.dubhe.domain.entity.UserAvatar; | |||
| import java.io.Serializable; | |||
| import java.sql.Timestamp; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| /** | |||
| * @description 用户信息 | |||
| * @date 2020-06-29 | |||
| */ | |||
| @Data | |||
| public class UserDTO implements Serializable { | |||
| @ApiModelProperty(hidden = true) | |||
| private Long id; | |||
| private String username; | |||
| private String nickName; | |||
| private String sex; | |||
| private String email; | |||
| private String phone; | |||
| private Boolean enabled; | |||
| private String remark; | |||
| @JsonIgnore | |||
| private String password; | |||
| private Date lastPasswordResetTime; | |||
| private Timestamp createTime; | |||
| private List<Role> roles; | |||
| private UserAvatar userAvatar; | |||
| } | |||
| @@ -0,0 +1,64 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.domain.entity; | |||
| import java.io.Serializable; | |||
| import org.dubhe.base.MagicNumConstant; | |||
| import com.alibaba.fastjson.annotation.JSONField; | |||
| import cn.hutool.core.date.DateUtil; | |||
| import lombok.Data; | |||
| import lombok.experimental.Accessors; | |||
| /** | |||
| * @description 日志对象封装类 | |||
| * @date 2020-06-29 | |||
| */ | |||
| @Data | |||
| @Accessors(chain = true) | |||
| public class LogInfo implements Serializable { | |||
| @JSONField(ordinal = MagicNumConstant.ONE) | |||
| private String traceId; | |||
| @JSONField(ordinal = MagicNumConstant.TWO) | |||
| private String type; | |||
| @JSONField(ordinal = MagicNumConstant.THREE) | |||
| private String level; | |||
| @JSONField(ordinal = MagicNumConstant.FOUR) | |||
| private String cName; | |||
| @JSONField(ordinal = MagicNumConstant.FIVE) | |||
| private String mName; | |||
| @JSONField(ordinal = MagicNumConstant.SIX) | |||
| private String line; | |||
| @JSONField(ordinal = MagicNumConstant.SEVEN) | |||
| private String time = DateUtil.now(); | |||
| @JSONField(ordinal = MagicNumConstant.EIGHT) | |||
| private Object info; | |||
| public void setInfo(Object info) { | |||
| this.info = info; | |||
| } | |||
| } | |||
| @@ -0,0 +1,120 @@ | |||
| /** | |||
| * Copyright 2019-2020 Zheng Jie | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package org.dubhe.domain.entity; | |||
| import com.baomidou.mybatisplus.annotation.*; | |||
| import lombok.AllArgsConstructor; | |||
| import lombok.Builder; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| import org.dubhe.base.BaseEntity; | |||
| import org.hibernate.validator.constraints.Length; | |||
| import javax.validation.constraints.NotBlank; | |||
| import javax.validation.constraints.NotNull; | |||
| import java.io.Serializable; | |||
| import java.sql.Timestamp; | |||
| import java.util.Objects; | |||
| /** | |||
| * @description 菜单实体 | |||
| * @date 2020-06-29 | |||
| */ | |||
| @Data | |||
| @Builder | |||
| @AllArgsConstructor | |||
| @NoArgsConstructor | |||
| @TableName("menu") | |||
| public class Menu extends BaseEntity implements Serializable { | |||
| private static final long serialVersionUID = 3100515433018008777L; | |||
| @TableId(value = "id", type = IdType.AUTO) | |||
| private Long id; | |||
| @NotBlank | |||
| private String name; | |||
| @TableField(value = "sort") | |||
| private Long sort = 999L; | |||
| @TableField(value = "path") | |||
| private String path; | |||
| @TableField(value = "component") | |||
| private String component; | |||
| /** | |||
| * 类型,目录、菜单、按钮 | |||
| */ | |||
| @TableField(value = "type") | |||
| private Integer type; | |||
| /** | |||
| * 权限 | |||
| */ | |||
| @TableField(value = "permission") | |||
| private String permission; | |||
| @TableField(value = "component_name") | |||
| private String componentName; | |||
| @TableField(value = "icon") | |||
| private String icon; | |||
| /** | |||
| * 布局类型 | |||
| */ | |||
| @TableField(value = "layout") | |||
| private String layout; | |||
| @TableField(value = "cache") | |||
| private Boolean cache; | |||
| @TableField(value = "hidden") | |||
| private Boolean hidden; | |||
| /** | |||
| * 上级菜单ID | |||
| */ | |||
| @TableField(value = "pid") | |||
| private Long pid; | |||
| @TableField(value = "deleted",fill = FieldFill.INSERT) | |||
| private Boolean deleted; | |||
| @Override | |||
| public boolean equals(Object o) { | |||
| if (this == o) { | |||
| return true; | |||
| } | |||
| if (o == null || getClass() != o.getClass()) { | |||
| return false; | |||
| } | |||
| Menu menu = (Menu) o; | |||
| return Objects.equals(id, menu.id); | |||
| } | |||
| @Override | |||
| public int hashCode() { | |||
| return Objects.hash(id); | |||
| } | |||
| public @interface Update { | |||
| } | |||
| } | |||
| @@ -0,0 +1,87 @@ | |||
| /** | |||
| * Copyright 2019-2020 Zheng Jie | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package org.dubhe.domain.entity; | |||
| import com.baomidou.mybatisplus.annotation.*; | |||
| import lombok.AllArgsConstructor; | |||
| import lombok.Builder; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| import org.dubhe.base.BaseEntity; | |||
| import org.hibernate.validator.constraints.Length; | |||
| import javax.validation.constraints.NotBlank; | |||
| import javax.validation.constraints.NotEmpty; | |||
| import java.io.Serializable; | |||
| import java.sql.Timestamp; | |||
| import java.util.Objects; | |||
| import java.util.Set; | |||
| /** | |||
| * @description 角色实体 | |||
| * @date 2020-06-29 | |||
| */ | |||
| @Data | |||
| @Builder | |||
| @AllArgsConstructor | |||
| @NoArgsConstructor | |||
| @TableName("role") | |||
| public class Role extends BaseEntity implements Serializable { | |||
| private static final long serialVersionUID = -812009584744832371L; | |||
| @TableId(value = "id", type = IdType.AUTO) | |||
| private Long id; | |||
| @TableField(value = "name") | |||
| private String name; | |||
| /** | |||
| * 权限 | |||
| */ | |||
| @TableField(value = "permission") | |||
| private String permission; | |||
| @TableField(value = "remark") | |||
| private String remark; | |||
| @TableField(exist = false) | |||
| private Set<Menu> menus; | |||
| @TableField(value = "deleted",fill = FieldFill.INSERT) | |||
| private Boolean deleted = false; | |||
| @Override | |||
| public boolean equals(Object o) { | |||
| if (this == o) { | |||
| return true; | |||
| } | |||
| if (o == null || getClass() != o.getClass()) { | |||
| return false; | |||
| } | |||
| Role role = (Role) o; | |||
| return Objects.equals(id, role.id); | |||
| } | |||
| @Override | |||
| public int hashCode() { | |||
| return Objects.hash(id); | |||
| } | |||
| public @interface Update { | |||
| } | |||
| } | |||
| @@ -0,0 +1,49 @@ | |||
| /** | |||
| * Copyright 2019-2020 Zheng Jie | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package org.dubhe.domain.entity; | |||
| import com.baomidou.mybatisplus.annotation.TableField; | |||
| import com.baomidou.mybatisplus.annotation.TableName; | |||
| import lombok.AllArgsConstructor; | |||
| import lombok.Builder; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| import java.io.Serializable; | |||
| /** | |||
| * @description 角色菜单关系实体 | |||
| * @date 2020-06-29 | |||
| */ | |||
| @Data | |||
| @Builder | |||
| @AllArgsConstructor | |||
| @NoArgsConstructor | |||
| @TableName("roles_menus") | |||
| public class RoleMenu implements Serializable { | |||
| private static final long serialVersionUID = -6296866205797727963L; | |||
| @TableField(value = "menu_id") | |||
| private Long menuId; | |||
| @TableField(value = "role_id") | |||
| private Long roleId; | |||
| } | |||
| @@ -0,0 +1,85 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.domain.entity; | |||
| import com.baomidou.mybatisplus.annotation.IdType; | |||
| import com.baomidou.mybatisplus.annotation.TableField; | |||
| import com.baomidou.mybatisplus.annotation.TableId; | |||
| import com.baomidou.mybatisplus.annotation.TableName; | |||
| import lombok.AllArgsConstructor; | |||
| import lombok.Builder; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| import javax.validation.constraints.NotBlank; | |||
| import javax.validation.constraints.NotNull; | |||
| import java.sql.Timestamp; | |||
| import java.util.List; | |||
| import java.util.Objects; | |||
| /** | |||
| * @description 团队实体 | |||
| * @date 2020-06-29 | |||
| */ | |||
| @TableName("team") | |||
| @Data | |||
| @Builder | |||
| @NoArgsConstructor | |||
| @AllArgsConstructor | |||
| public class Team { | |||
| @TableId(value = "id", type = IdType.AUTO) | |||
| @NotNull(groups = Update.class) | |||
| private Long id; | |||
| @TableField(value = "name") | |||
| @NotBlank | |||
| private String name; | |||
| @TableField(value = "enabled") | |||
| @NotNull | |||
| private Boolean enabled; | |||
| /** | |||
| * 团队成员 | |||
| */ | |||
| @TableField(exist = false) | |||
| private List<User> teamUserList; | |||
| @TableField(value = "create_time") | |||
| private Timestamp createTime; | |||
| @Override | |||
| public boolean equals(Object o) { | |||
| if (this == o) { | |||
| return true; | |||
| } | |||
| if (o == null || getClass() != o.getClass()) { | |||
| return false; | |||
| } | |||
| Team dept = (Team) o; | |||
| return Objects.equals(id, dept.id) && | |||
| Objects.equals(name, dept.name); | |||
| } | |||
| @Override | |||
| public int hashCode() { | |||
| return Objects.hash(id, name); | |||
| } | |||
| public @interface Update { | |||
| } | |||
| } | |||
| @@ -0,0 +1,58 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.domain.entity; | |||
| import com.baomidou.mybatisplus.annotation.IdType; | |||
| import com.baomidou.mybatisplus.annotation.TableField; | |||
| import com.baomidou.mybatisplus.annotation.TableId; | |||
| import com.baomidou.mybatisplus.annotation.TableName; | |||
| import lombok.Data; | |||
| import javax.validation.constraints.NotNull; | |||
| import java.io.Serializable; | |||
| /** | |||
| * @description 团队用户关系实体 | |||
| * @date 2020-06-29 | |||
| */ | |||
| @Data | |||
| @TableName("teams_users_roles") | |||
| public class TeamUserRole implements Serializable { | |||
| @TableId(value = "id", type = IdType.AUTO) | |||
| @NotNull() | |||
| private Long id; | |||
| /** | |||
| * 团队 | |||
| */ | |||
| @TableField(exist = false) | |||
| private Team team; | |||
| /** | |||
| * 用户 | |||
| */ | |||
| @TableField(exist = false) | |||
| private User user; | |||
| /** | |||
| * 角色 | |||
| */ | |||
| @TableField(exist = false) | |||
| private Role role; | |||
| } | |||
| @@ -0,0 +1,126 @@ | |||
| /** | |||
| * Copyright 2019-2020 Zheng Jie | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package org.dubhe.domain.entity; | |||
| import com.baomidou.mybatisplus.annotation.*; | |||
| import lombok.AllArgsConstructor; | |||
| import lombok.Builder; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| import org.dubhe.base.BaseEntity; | |||
| import javax.validation.constraints.NotBlank; | |||
| import javax.validation.constraints.NotEmpty; | |||
| import javax.validation.constraints.NotNull; | |||
| import java.io.Serializable; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| import java.util.Objects; | |||
| /** | |||
| * @description 用户实体 | |||
| * @date 2020-06-29 | |||
| */ | |||
| @Data | |||
| @TableName("user") | |||
| @Builder | |||
| @NoArgsConstructor | |||
| @AllArgsConstructor | |||
| public class User extends BaseEntity implements Serializable { | |||
| private static final long serialVersionUID = -3836401769559845765L; | |||
| @TableId(value = "id", type = IdType.AUTO) | |||
| @NotNull(groups = Update.class) | |||
| private Long id; | |||
| @NotBlank | |||
| @TableField(value = "username") | |||
| private String username; | |||
| /** | |||
| * 用户昵称 | |||
| */ | |||
| @TableField(value = "nick_name") | |||
| @NotBlank | |||
| private String nickName; | |||
| /** | |||
| * 性别 | |||
| */ | |||
| @TableField(value = "sex") | |||
| private String sex; | |||
| @NotBlank | |||
| @TableField(value = "email") | |||
| private String email; | |||
| @NotBlank | |||
| @TableField(value = "phone") | |||
| private String phone; | |||
| @NotNull | |||
| @TableField(value = "enabled") | |||
| private Boolean enabled; | |||
| @TableField(value = "password") | |||
| private String password; | |||
| @TableField(value = "last_password_reset_time") | |||
| private Date lastPasswordResetTime; | |||
| @TableField(value = "remark") | |||
| private String remark; | |||
| @TableField(value = "avatar_id") | |||
| private Long avatarId; | |||
| @TableField(exist = false) | |||
| private UserAvatar userAvatar; | |||
| @NotEmpty | |||
| @TableField(exist = false) | |||
| private List<Role> roles; | |||
| @TableField(value = "deleted",fill = FieldFill.INSERT) | |||
| private Boolean deleted = false; | |||
| @Override | |||
| public boolean equals(Object o) { | |||
| if (this == o) { | |||
| return true; | |||
| } | |||
| if (o == null || getClass() != o.getClass()) { | |||
| return false; | |||
| } | |||
| User user = (User) o; | |||
| return Objects.equals(id, user.id) && | |||
| Objects.equals(username, user.username); | |||
| } | |||
| @Override | |||
| public int hashCode() { | |||
| return Objects.hash(id, username); | |||
| } | |||
| public @interface Update { | |||
| } | |||
| } | |||
| @@ -0,0 +1,58 @@ | |||
| /** | |||
| * Copyright 2019-2020 Zheng Jie | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package org.dubhe.domain.entity; | |||
| import cn.hutool.core.util.ObjectUtil; | |||
| import com.baomidou.mybatisplus.annotation.IdType; | |||
| import com.baomidou.mybatisplus.annotation.TableField; | |||
| import com.baomidou.mybatisplus.annotation.TableId; | |||
| import com.baomidou.mybatisplus.annotation.TableName; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| import org.dubhe.base.BaseEntity; | |||
| import java.io.Serializable; | |||
| /** | |||
| * @description 用户头像实体 | |||
| * @date 2020-06-29 | |||
| */ | |||
| @Data | |||
| @NoArgsConstructor | |||
| @TableName("user_avatar") | |||
| public class UserAvatar extends BaseEntity implements Serializable { | |||
| @TableId(value = "id", type = IdType.AUTO) | |||
| private Long id; | |||
| @TableField(value = "real_name") | |||
| private String realName; | |||
| @TableField(value = "path") | |||
| private String path; | |||
| @TableField(value = "size") | |||
| private String size; | |||
| public UserAvatar(UserAvatar userAvatar, String realName, String path, String size) { | |||
| this.id = ObjectUtil.isNotEmpty(userAvatar) ? userAvatar.getId() : null; | |||
| this.realName = realName; | |||
| this.path = path; | |||
| this.size = size; | |||
| } | |||
| } | |||
| @@ -0,0 +1,47 @@ | |||
| /** | |||
| * Copyright 2019-2020 Zheng Jie | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package org.dubhe.domain.entity; | |||
| import com.baomidou.mybatisplus.annotation.TableField; | |||
| import com.baomidou.mybatisplus.annotation.TableName; | |||
| import lombok.AllArgsConstructor; | |||
| import lombok.Builder; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| import java.io.Serializable; | |||
| /** | |||
| * @description 用户角色关系实体 | |||
| * @date 2020-06-29 | |||
| */ | |||
| @Data | |||
| @Builder | |||
| @AllArgsConstructor | |||
| @NoArgsConstructor | |||
| @TableName("users_roles") | |||
| public class UserRole implements Serializable { | |||
| private static final long serialVersionUID = -6296866205797727963L; | |||
| @TableField(value = "user_id") | |||
| private Long userId; | |||
| @TableField(value = "role_id") | |||
| private Long roleId; | |||
| } | |||
| @@ -0,0 +1,35 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.dto.callback; | |||
| import io.swagger.annotations.ApiModel; | |||
| import lombok.Data; | |||
| /** | |||
| * @descripton 个性化参数实现 与 个性化参数个性化校验 | |||
| * | |||
| * @date 2020-05-28 | |||
| */ | |||
| @ApiModel(description = "k8s pod异步回调Algorithm") | |||
| @Data | |||
| public class AlgorithmK8sPodCallbackCreateDTO extends BaseK8sPodCallbackCreateDTO { | |||
| @Override | |||
| public String toString() { | |||
| return super.toString(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,33 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.dto.callback; | |||
| import io.swagger.annotations.ApiModel; | |||
| import lombok.Data; | |||
| /** | |||
| * @descripton k8s方异步回调统一汇总类,即不管什么业务所有请求参数都放在这个类中 | |||
| * | |||
| * @date 2020-05-28 | |||
| */ | |||
| @ApiModel(description = "k8s方 pod异步回调汇总类") | |||
| @Data | |||
| public class AllK8sPodCallbackCreateDTO extends BaseK8sPodCallbackCreateDTO{ | |||
| } | |||
| @@ -0,0 +1,76 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.dto.callback; | |||
| import io.swagger.annotations.ApiModel; | |||
| import io.swagger.annotations.ApiModelProperty; | |||
| import lombok.Data; | |||
| import javax.validation.constraints.NotEmpty; | |||
| /** | |||
| * @descripton 统一通用参数实现与校验 | |||
| * | |||
| * @date 2020-05-28 | |||
| */ | |||
| @ApiModel(description = "k8s pod异步回调基类") | |||
| @Data | |||
| public class BaseK8sPodCallbackCreateDTO { | |||
| @ApiModelProperty(required = true,value = "k8s namespace") | |||
| @NotEmpty(message = "namespace 不能为空!") | |||
| private String namespace; | |||
| @ApiModelProperty(required = true,value = "k8s resource name") | |||
| @NotEmpty(message = "resourceName 不能为空!") | |||
| private String resourceName; | |||
| @ApiModelProperty(required = true,value = "k8s pod name") | |||
| @NotEmpty(message = "podName 不能为空!") | |||
| private String podName; | |||
| @ApiModelProperty(value = "k8s pod phase",notes = "对应PodPhaseEnum") | |||
| @NotEmpty(message = "phase 不能为空!") | |||
| private String phase; | |||
| @ApiModelProperty(value = "k8s pod containerStatuses state") | |||
| private String messages; | |||
| public BaseK8sPodCallbackCreateDTO(){ | |||
| } | |||
| public BaseK8sPodCallbackCreateDTO(String namespace,String resourceName,String podName,String phase,String messages){ | |||
| this.namespace = namespace; | |||
| this.resourceName = resourceName; | |||
| this.podName = podName; | |||
| this.phase = phase; | |||
| this.messages = messages; | |||
| } | |||
| @Override | |||
| public String toString() { | |||
| return "BaseK8sPodCallbackReq{" + | |||
| "namespace='" + namespace + '\'' + | |||
| ", resourceName='" + resourceName + '\'' + | |||
| ", podName='" + podName + '\'' + | |||
| ", phase='" + phase + '\'' + | |||
| ", messages=" + messages + | |||
| '}'; | |||
| } | |||
| } | |||
| @@ -0,0 +1,36 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.dto.callback; | |||
| import io.swagger.annotations.ApiModel; | |||
| import lombok.Data; | |||
| /** | |||
| * @descripton k8s pod异步回调Notebook | |||
| * | |||
| * @date 2020-05-28 | |||
| */ | |||
| @ApiModel(description = "k8s pod异步回调Notebook") | |||
| @Data | |||
| public class NotebookK8sPodCallbackCreateDTO extends BaseK8sPodCallbackCreateDTO { | |||
| @Override | |||
| public String toString() { | |||
| return super.toString(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,80 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.enums; | |||
| import lombok.Getter; | |||
| import java.util.HashMap; | |||
| import java.util.Map; | |||
| /** | |||
| * @desc: 业务模块 | |||
| * | |||
| * @date 2020.05.25 | |||
| */ | |||
| @Getter | |||
| public enum BizEnum { | |||
| /** | |||
| * 模型开发 | |||
| */ | |||
| NOTEBOOK("模型开发","notebook",0), | |||
| /** | |||
| * 算法管理 | |||
| */ | |||
| ALGORITHM("算法管理","algorithm",1), | |||
| ; | |||
| /** | |||
| * 业务模块名称 | |||
| */ | |||
| private String bizName; | |||
| /** | |||
| * 业务模块名称 | |||
| */ | |||
| private String bizCode; | |||
| /** | |||
| * 业务源代号 | |||
| */ | |||
| private Integer createResource; | |||
| BizEnum(String bizName,String bizCode, Integer createResource) { | |||
| this.createResource = createResource; | |||
| this.bizName = bizName; | |||
| this.bizCode = bizCode; | |||
| } | |||
| private static final Map<Integer,BizEnum> RESOURCE_ENUM_MAP = new HashMap<Integer,BizEnum>(){ | |||
| { | |||
| for (BizEnum enums:BizEnum.values()){ | |||
| put(enums.getCreateResource(),enums); | |||
| } | |||
| } | |||
| }; | |||
| /** | |||
| * 根据createResource获取BizEnum | |||
| * @param createResource | |||
| * @return | |||
| */ | |||
| public static BizEnum getByCreateResource(int createResource){ | |||
| return RESOURCE_ENUM_MAP.get(createResource); | |||
| } | |||
| } | |||
| @@ -0,0 +1,91 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.enums; | |||
| import java.util.HashMap; | |||
| import java.util.Map; | |||
| /** | |||
| * @desc: 业务NFS路径枚举 | |||
| * @date 2020.05.13 | |||
| */ | |||
| public enum BizNfsEnum { | |||
| /** | |||
| * 模型开发 NFS 路径命名 | |||
| */ | |||
| NOTEBOOK(BizEnum.NOTEBOOK, "notebook"), | |||
| /** | |||
| * 算法管理 NFS 路径命名 | |||
| */ | |||
| ALGORITHM(BizEnum.ALGORITHM, "algorithm-manage"), | |||
| ; | |||
| BizNfsEnum(BizEnum bizEnum, String bizNfsPath) { | |||
| this.bizEnum = bizEnum; | |||
| this.bizNfsPath = bizNfsPath; | |||
| } | |||
| /** | |||
| * 业务模块 | |||
| */ | |||
| private BizEnum bizEnum; | |||
| /** | |||
| * 业务模块nfs路径 | |||
| */ | |||
| private String bizNfsPath; | |||
| private static final Map<Integer, BizNfsEnum> RESOURCE_ENUM_MAP = new HashMap<Integer, BizNfsEnum>() { | |||
| { | |||
| for (BizNfsEnum enums : BizNfsEnum.values()) { | |||
| put(enums.getCreateResource(), enums); | |||
| } | |||
| } | |||
| }; | |||
| /** | |||
| * 根据createResource获取BizNfsEnum | |||
| * | |||
| * @param createResource | |||
| * @return | |||
| */ | |||
| public static BizNfsEnum getByCreateResource(int createResource) { | |||
| return RESOURCE_ENUM_MAP.get(createResource); | |||
| } | |||
| public String getBizName() { | |||
| return bizEnum == null ? null : bizEnum.getBizName(); | |||
| } | |||
| public Integer getCreateResource() { | |||
| return bizEnum == null ? null : bizEnum.getCreateResource(); | |||
| } | |||
| public String getBizNfsPath() { | |||
| return bizNfsPath; | |||
| } | |||
| public BizEnum getBizEnum(){ | |||
| return bizEnum; | |||
| } | |||
| public String getBizCode() { | |||
| return bizEnum == null ? null :bizEnum.getBizCode(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,61 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.enums; | |||
| import lombok.Getter; | |||
| /** | |||
| * @description 日志类型枚举类 | |||
| * @date 2020-06-23 | |||
| */ | |||
| @Getter | |||
| public enum LogEnum { | |||
| // 系统报错日志 | |||
| SYS_ERR, | |||
| // 用户请求日志 | |||
| REST_REQ, | |||
| // 训练模块 | |||
| BIZ_TRAIN, | |||
| // 系统模块 | |||
| BIZ_SYS, | |||
| // 模型模块 | |||
| BIZ_MODEL, | |||
| // 数据集模块 | |||
| BIZ_DATASET, | |||
| // k8s模块 | |||
| BIZ_K8S, | |||
| //note book | |||
| NOTE_BOOK, | |||
| //NFS UTILS | |||
| NFS_UTIL; | |||
| /** | |||
| * 判断日志类型不能为空 | |||
| * | |||
| * @param logType 日志类型 | |||
| * @return boolean 返回类型 | |||
| */ | |||
| public static boolean isLogType(LogEnum logType) { | |||
| if (logType != null) { | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| } | |||
| @@ -0,0 +1,95 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.enums; | |||
| /** | |||
| * @Description 是否开关枚举 | |||
| * @Date 2020-06-01 | |||
| */ | |||
| public enum SwitchEnum { | |||
| /** | |||
| * OFF 否 | |||
| */ | |||
| OFF(0, "否"), | |||
| /** | |||
| * ON 否 | |||
| */ | |||
| ON(1, "是"), | |||
| ; | |||
| private Integer value; | |||
| private String desc; | |||
| SwitchEnum(Integer value, String desc) { | |||
| this.value = value; | |||
| this.desc = desc; | |||
| } | |||
| public Integer getValue() { | |||
| return this.value; | |||
| } | |||
| public String getDesc() { | |||
| return desc; | |||
| } | |||
| public void setDesc(String desc) { | |||
| this.desc = desc; | |||
| } | |||
| public static SwitchEnum getEnumValue(Integer value) { | |||
| switch (value) { | |||
| case 0: | |||
| return OFF; | |||
| case 1: | |||
| return ON; | |||
| default: | |||
| return OFF; | |||
| } | |||
| } | |||
| public static Boolean getBooleanValue(Integer value) { | |||
| switch (value) { | |||
| case 1: | |||
| return true; | |||
| case 0: | |||
| return false; | |||
| default: | |||
| return false; | |||
| } | |||
| } | |||
| public static boolean isExist(Integer value) { | |||
| for (SwitchEnum itm : SwitchEnum.values()) { | |||
| if (value.compareTo(itm.getValue()) == 0) { | |||
| return true; | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| @Override | |||
| public String toString() { | |||
| return "[" + this.value + "]" + this.desc; | |||
| } | |||
| } | |||
| @@ -0,0 +1,101 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.enums; | |||
| import lombok.Getter; | |||
| import java.util.Arrays; | |||
| import java.util.List; | |||
| /** | |||
| * @description 训练任务枚举类 | |||
| * @date 2020-04-27 | |||
| */ | |||
| @Getter | |||
| public enum TrainJobStatusEnum { | |||
| /** | |||
| * PENDING | |||
| */ | |||
| PENDING(0, "PENDING"), | |||
| /** | |||
| * RUNNING | |||
| */ | |||
| RUNNING(1, "RUNNING"), | |||
| /** | |||
| * SUCCEEDED | |||
| */ | |||
| SUCCEEDED(2, "SUCCEEDED"), | |||
| /** | |||
| * FAILED | |||
| */ | |||
| FAILED(3, "FAILED"), | |||
| /** | |||
| * STOP | |||
| */ | |||
| STOP(4, "STOP"), | |||
| /** | |||
| * UNKNOWN | |||
| */ | |||
| UNKNOWN(5, "UNKNOWN"), | |||
| /** | |||
| * DELETED | |||
| */ | |||
| DELETED(6, "DELETED"), | |||
| /** | |||
| * CREATE_FAILED | |||
| */ | |||
| CREATE_FAILED(7, "CREATE_FAILED"); | |||
| private Integer status; | |||
| private String message; | |||
| TrainJobStatusEnum(Integer status, String message) { | |||
| this.status = status; | |||
| this.message = message; | |||
| } | |||
| public static TrainJobStatusEnum get(String msg) { | |||
| for (TrainJobStatusEnum statusEnum : values()) { | |||
| if (statusEnum.message.equalsIgnoreCase(msg)) { | |||
| return statusEnum; | |||
| } | |||
| } | |||
| return UNKNOWN; | |||
| } | |||
| public static boolean isEnd(String msg) { | |||
| List<String> endList = Arrays.asList("SUCCEEDED", "FAILED", "STOP", "CREATE_FAILED"); | |||
| return endList.stream().anyMatch(s -> s.equalsIgnoreCase(msg)); | |||
| } | |||
| public static boolean isEnd(Integer num) { | |||
| List<Integer> endList = Arrays.asList(2, 3, 4, 7); | |||
| return endList.stream().anyMatch(s -> s.equals(num)); | |||
| } | |||
| public static boolean checkStopStatus(Integer num) { | |||
| return SUCCEEDED.getStatus().equals(num) || | |||
| FAILED.getStatus().equals(num) || | |||
| STOP.getStatus().equals(num) || | |||
| CREATE_FAILED.getStatus().equals(num) || | |||
| DELETED.getStatus().equals(num); | |||
| } | |||
| } | |||
| @@ -0,0 +1,69 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.exception; | |||
| import lombok.Getter; | |||
| /** | |||
| * @description 通用异常code | |||
| * @date 2020-03-26 | |||
| */ | |||
| @Getter | |||
| public enum BaseErrorCode implements ErrorCode { | |||
| /** | |||
| * undefined error | |||
| */ | |||
| UNDEFINED(10000, "操作成功!"), | |||
| ERROR(10001, "操作失败!"), | |||
| ERROR_SYSTEM(10002, "系统繁忙!"), | |||
| UNAUTHORIZED(401, "无权访问!"), | |||
| /** | |||
| * system 模块异常码 | |||
| */ | |||
| SYSTEM_USERNAME_ALREADY_EXISTS(20000, "账号已存在!"), | |||
| SYSTEM_CODE_ALREADY_EXISTS(20001, "Code already exists!"), | |||
| SYSTEM_USER_IS_NOT_EXISTS(20002, "用户不存在!"), | |||
| SYSTEM_USER_ALREADY_REGISTER(20003, "账号已注册!"), | |||
| SYSTEM_USER_REGISTER_EMAIL_INFO_EXPIRED(20004, "邮箱验证码已过期!"), | |||
| SYSTEM_USER_EMAIL_ALREADY_EXISTS(20004, "该邮箱已被注册!"), | |||
| SYSTEM_USER_EMAIL_PASSWORD_ERROR(20005, "邮件密码错误!"), | |||
| SYSTEM_USER_EMAIL_CODE_CANNOT_EXCEED_TIMES(20006, "邮件发送不能超过三次!"), | |||
| SYSTEM_USER_EMAIL_OR_CODE_ERROR(20007, "邮箱地址或验证码错误、请重新输入!"), | |||
| SYSTEM_USER_IS_LOCKED(20008, "用户已锁定!"), | |||
| SYSTEM_USER_USERNAME_OR_PASSWORD_ERROR(20009, "账号或密码不正确!"), | |||
| SYSTEM_USER_USERNAME_IS_LOCKED(20010, "账号已锁定,6小时后解锁!"), | |||
| SYSTEM_USER_CANNOT_UPDATE_ADMIN(20011, "仅超级管理员可操作!"), | |||
| SYSTEM_USER_TOKEN_INFO_IS_NULL(20012, "登录信息不存在!"), | |||
| SYSTEM_USER_EMAIL_NOT_EXISTS(20013, "该邮箱未注册!"), | |||
| SYSTEM_USER_CANNOT_DELETE(20014, "系统默认用户不可删除!"), | |||
| SYSTEM_ROLE_CANNOT_DELETE(20015, "系统默认角色不可删除!"), | |||
| ; | |||
| Integer code; | |||
| String msg; | |||
| BaseErrorCode(Integer code, String msg) { | |||
| this.code = code; | |||
| this.msg = msg; | |||
| } | |||
| } | |||
| @@ -0,0 +1,72 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.exception; | |||
| import lombok.Getter; | |||
| import org.dubhe.base.DataResponseBody; | |||
| import org.dubhe.base.ResponseCode; | |||
| /** | |||
| * @description 业务异常 | |||
| * @date 2020-03-13 | |||
| */ | |||
| @Getter | |||
| public class BusinessException extends RuntimeException { | |||
| private DataResponseBody responseBody; | |||
| public BusinessException(String msg) { | |||
| super(msg); | |||
| this.responseBody = new DataResponseBody(ResponseCode.BADREQUEST, msg); | |||
| } | |||
| public BusinessException(String msg, Throwable cause) { | |||
| super(msg,cause); | |||
| this.responseBody = new DataResponseBody(ResponseCode.BADREQUEST, msg); | |||
| } | |||
| public BusinessException(Throwable cause) { | |||
| super(cause); | |||
| this.responseBody = new DataResponseBody(ResponseCode.BADREQUEST); | |||
| } | |||
| public BusinessException(Integer code, String msg, String info, Throwable cause) { | |||
| super(msg,cause); | |||
| if (info == null) { | |||
| this.responseBody = new DataResponseBody(code, msg); | |||
| } else { | |||
| this.responseBody = new DataResponseBody(code, msg + ":" + info); | |||
| } | |||
| } | |||
| public BusinessException(ErrorCode errorCode, Throwable cause) { | |||
| this(errorCode.getCode(), errorCode.getMsg(), null, cause); | |||
| } | |||
| public BusinessException(ErrorCode errorCode, String info, Throwable cause) { | |||
| this(errorCode.getCode(), errorCode.getMsg(), info, cause); | |||
| } | |||
| public BusinessException(ErrorCode errorCode) { | |||
| this(errorCode, null); | |||
| } | |||
| public BusinessException(Integer code,String msg) { | |||
| this.responseBody = new DataResponseBody(code, msg); | |||
| } | |||
| } | |||
| @@ -0,0 +1,48 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.exception; | |||
| import lombok.Getter; | |||
| import org.dubhe.base.DataResponseBody; | |||
| import org.dubhe.base.ResponseCode; | |||
| /** | |||
| * @description 验证码异常 | |||
| * @date 2020-02-23 | |||
| */ | |||
| @Getter | |||
| public class CaptchaException extends RuntimeException { | |||
| private static final long serialVersionUID = 1L; | |||
| private DataResponseBody responseBody; | |||
| private Throwable cause; | |||
| public CaptchaException(String msg) { | |||
| this.responseBody = new DataResponseBody(ResponseCode.BADREQUEST, msg); | |||
| } | |||
| public CaptchaException(String msg, Throwable cause) { | |||
| this.cause = cause; | |||
| this.responseBody = new DataResponseBody(ResponseCode.BADREQUEST, msg); | |||
| } | |||
| public CaptchaException(Throwable cause) { | |||
| this.cause = cause; | |||
| this.responseBody = new DataResponseBody(ResponseCode.BADREQUEST); | |||
| } | |||
| } | |||
| @@ -0,0 +1,48 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.exception; | |||
| import lombok.Getter; | |||
| import org.dubhe.base.DataResponseBody; | |||
| import org.dubhe.base.ResponseCode; | |||
| /** | |||
| * @Description docker 异常 | |||
| * @Date 2020-6-6 | |||
| **/ | |||
| @Getter | |||
| public class DockerBizException extends RuntimeException { | |||
| private static final long serialVersionUID = 1L; | |||
| private DataResponseBody responseBody; | |||
| private Throwable cause; | |||
| public DockerBizException(String msg) { | |||
| this.responseBody = new DataResponseBody(ResponseCode.DOCKER_ERROR, msg); | |||
| } | |||
| public DockerBizException(String msg, Throwable cause) { | |||
| this.cause = cause; | |||
| this.responseBody = new DataResponseBody(ResponseCode.DOCKER_ERROR, msg); | |||
| } | |||
| public DockerBizException(Throwable cause) { | |||
| this.cause = cause; | |||
| this.responseBody = new DataResponseBody(ResponseCode.DOCKER_ERROR); | |||
| } | |||
| } | |||
| @@ -0,0 +1,39 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.exception; | |||
| /** | |||
| * @description 异常code | |||
| * @date 2020-03-26 | |||
| */ | |||
| public interface ErrorCode { | |||
| /** | |||
| * 错误码 | |||
| * @return code | |||
| */ | |||
| Integer getCode(); | |||
| /** | |||
| * error info | |||
| * @return | |||
| */ | |||
| String getMsg(); | |||
| } | |||
| @@ -0,0 +1,44 @@ | |||
| /** | |||
| * Copyright 2019-2020 Zheng Jie | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package org.dubhe.exception; | |||
| import lombok.Getter; | |||
| import org.dubhe.base.DataResponseBody; | |||
| import org.dubhe.base.ResponseCode; | |||
| /** | |||
| * @description 登录异常 | |||
| * @date 2020-02-23 | |||
| */ | |||
| @Getter | |||
| public class LoginException extends RuntimeException { | |||
| private DataResponseBody responseBody; | |||
| private Throwable cause; | |||
| public LoginException(String msg) { | |||
| this.responseBody = new DataResponseBody(ResponseCode.BADREQUEST, msg); | |||
| } | |||
| public LoginException(String msg, Throwable cause) { | |||
| this.cause = cause; | |||
| this.responseBody = new DataResponseBody(ResponseCode.BADREQUEST, msg); | |||
| } | |||
| public LoginException(Throwable cause) { | |||
| this.cause = cause; | |||
| this.responseBody = new DataResponseBody(ResponseCode.BADREQUEST); | |||
| } | |||
| } | |||
| @@ -0,0 +1,42 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.exception; | |||
| import lombok.Getter; | |||
| /** | |||
| * Description : NFS utils 工具异常 | |||
| * | |||
| * @date 15.06.2020 | |||
| */ | |||
| @Getter | |||
| public class NfsBizException extends BusinessException { | |||
| private static final long serialVersionUID = 1L; | |||
| public NfsBizException(Throwable cause){ | |||
| super(cause); | |||
| } | |||
| public NfsBizException(String msg){ | |||
| super(msg); | |||
| } | |||
| } | |||
| @@ -0,0 +1,45 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.exception; | |||
| import lombok.Getter; | |||
| /** | |||
| * @description: Notebook 业务处理异常 | |||
| * | |||
| * @date 2020.04.27 | |||
| */ | |||
| @Getter | |||
| public class NotebookBizException extends BusinessException{ | |||
| private static final long serialVersionUID = 1L; | |||
| public NotebookBizException(String msg) { | |||
| super(msg); | |||
| } | |||
| public NotebookBizException(String msg, Throwable cause) { | |||
| super(msg,cause); | |||
| } | |||
| public NotebookBizException(Throwable cause) { | |||
| super(cause); | |||
| } | |||
| } | |||
| @@ -0,0 +1,47 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.exception; | |||
| import lombok.Getter; | |||
| import org.dubhe.base.DataResponseBody; | |||
| import org.dubhe.base.ResponseCode; | |||
| /** | |||
| * @description 权限异常 | |||
| * @date 2020-02-23 | |||
| */ | |||
| @Getter | |||
| public class UnauthorizedException extends RuntimeException { | |||
| private DataResponseBody responseBody; | |||
| private Throwable cause; | |||
| public UnauthorizedException(String msg) { | |||
| this.responseBody = new DataResponseBody(ResponseCode.UNAUTHORIZED, msg); | |||
| } | |||
| public UnauthorizedException(String msg, Throwable cause) { | |||
| this.cause = cause; | |||
| this.responseBody = new DataResponseBody(ResponseCode.UNAUTHORIZED, msg); | |||
| } | |||
| public UnauthorizedException(Throwable cause) { | |||
| this.cause = cause; | |||
| this.responseBody = new DataResponseBody(ResponseCode.UNAUTHORIZED); | |||
| } | |||
| } | |||
| @@ -0,0 +1,190 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.exception.handler; | |||
| import java.util.Objects; | |||
| import org.apache.shiro.ShiroException; | |||
| import org.apache.shiro.authc.AuthenticationException; | |||
| import org.apache.shiro.authc.IncorrectCredentialsException; | |||
| import org.apache.shiro.authc.LockedAccountException; | |||
| import org.apache.shiro.authc.UnknownAccountException; | |||
| import org.dubhe.base.DataResponseBody; | |||
| import org.dubhe.base.ResponseCode; | |||
| import org.dubhe.enums.LogEnum; | |||
| import org.dubhe.exception.BusinessException; | |||
| import org.dubhe.exception.CaptchaException; | |||
| import org.dubhe.exception.LoginException; | |||
| import org.dubhe.exception.NotebookBizException; | |||
| import org.dubhe.exception.UnauthorizedException; | |||
| import org.dubhe.utils.LogUtil; | |||
| import org.springframework.http.HttpStatus; | |||
| import org.springframework.http.ResponseEntity; | |||
| import org.springframework.validation.BindException; | |||
| import org.springframework.validation.ObjectError; | |||
| import org.springframework.web.bind.MethodArgumentNotValidException; | |||
| import org.springframework.web.bind.annotation.ExceptionHandler; | |||
| import org.springframework.web.bind.annotation.RestControllerAdvice; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| /** | |||
| * @description 处理异常 | |||
| * @date 2020-02-23 | |||
| */ | |||
| @Slf4j | |||
| @RestControllerAdvice | |||
| public class GlobalExceptionHandler { | |||
| /** | |||
| * 处理所有不可知的异常 | |||
| */ | |||
| @ExceptionHandler(Throwable.class) | |||
| public ResponseEntity<DataResponseBody> handleException(Throwable e) { | |||
| // 打印堆栈信息 | |||
| LogUtil.error(LogEnum.SYS_ERR, e); | |||
| return buildResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR, | |||
| new DataResponseBody(ResponseCode.ERROR, e.getMessage())); | |||
| } | |||
| /** | |||
| * UnauthorizedException | |||
| */ | |||
| @ExceptionHandler(UnauthorizedException.class) | |||
| public ResponseEntity<DataResponseBody> badCredentialsException(UnauthorizedException e) { | |||
| // 打印堆栈信息 | |||
| LogUtil.error(LogEnum.SYS_ERR, e); | |||
| String message = "坏的凭证".equals(e.getMessage()) ? "用户名或密码不正确" : e.getMessage(); | |||
| return buildResponseEntity(HttpStatus.UNAUTHORIZED, new DataResponseBody(ResponseCode.ERROR, message)); | |||
| } | |||
| /** | |||
| * 处理自定义异常 | |||
| */ | |||
| @ExceptionHandler(value = BusinessException.class) | |||
| public ResponseEntity<DataResponseBody> badRequestException(BusinessException e) { | |||
| // 打印堆栈信息 | |||
| LogUtil.error(LogEnum.SYS_ERR, e); | |||
| return buildResponseEntity(HttpStatus.OK, e.getResponseBody()); | |||
| } | |||
| /** | |||
| * 处理自定义异常 | |||
| */ | |||
| @ExceptionHandler(value = AuthenticationException.class) | |||
| public ResponseEntity<DataResponseBody> badRequestException(AuthenticationException e) { | |||
| // 打印堆栈信息 | |||
| LogUtil.error(LogEnum.SYS_ERR, e); | |||
| return buildResponseEntity(HttpStatus.OK, new DataResponseBody(ResponseCode.UNAUTHORIZED, "无权访问")); | |||
| } | |||
| /** | |||
| * shiro 异常捕捉 | |||
| */ | |||
| @ExceptionHandler(value = ShiroException.class) | |||
| public ResponseEntity<DataResponseBody> accountException(ShiroException e) { | |||
| // 打印堆栈信息 | |||
| LogUtil.error(LogEnum.SYS_ERR, e); | |||
| ResponseEntity<DataResponseBody> responseEntity; | |||
| if (e instanceof IncorrectCredentialsException) { | |||
| responseEntity = buildResponseEntity(HttpStatus.OK, new DataResponseBody(ResponseCode.ERROR, "密码不正确")); | |||
| } else if (e instanceof UnknownAccountException) { | |||
| responseEntity = buildResponseEntity(HttpStatus.OK, new DataResponseBody(ResponseCode.ERROR, "此账户不存在")); | |||
| } | |||
| else if (e instanceof LockedAccountException) { | |||
| responseEntity = buildResponseEntity(HttpStatus.OK, new DataResponseBody(ResponseCode.ERROR, "未知的账号")); | |||
| } | |||
| else if (e instanceof UnknownAccountException) { | |||
| responseEntity = buildResponseEntity(HttpStatus.OK, new DataResponseBody(ResponseCode.ERROR, "账户已被禁用")); | |||
| } | |||
| else { | |||
| responseEntity = buildResponseEntity(HttpStatus.OK, | |||
| new DataResponseBody(ResponseCode.UNAUTHORIZED, "无权访问")); | |||
| } | |||
| return responseEntity; | |||
| } | |||
| /** | |||
| * 处理自定义异常 | |||
| */ | |||
| @ExceptionHandler(value = LoginException.class) | |||
| public ResponseEntity<DataResponseBody> loginException(LoginException e) { | |||
| // 打印堆栈信息 | |||
| LogUtil.error(LogEnum.SYS_ERR, e); | |||
| return buildResponseEntity(HttpStatus.UNAUTHORIZED, e.getResponseBody()); | |||
| } | |||
| /** | |||
| * 处理自定义异常 | |||
| */ | |||
| @ExceptionHandler(value = CaptchaException.class) | |||
| public ResponseEntity<DataResponseBody> captchaException(CaptchaException e) { | |||
| // 打印堆栈信息 | |||
| LogUtil.error(LogEnum.SYS_ERR, e); | |||
| return buildResponseEntity(HttpStatus.OK, e.getResponseBody()); | |||
| } | |||
| /** | |||
| * 处理自定义异常 | |||
| */ | |||
| @ExceptionHandler(value = NotebookBizException.class) | |||
| public ResponseEntity<DataResponseBody> captchaException(NotebookBizException e) { | |||
| // 打印堆栈信息 | |||
| LogUtil.error(LogEnum.SYS_ERR, e); | |||
| return buildResponseEntity(HttpStatus.OK, e.getResponseBody()); | |||
| } | |||
| /** | |||
| * 处理所有接口数据验证异常 | |||
| */ | |||
| @ExceptionHandler(MethodArgumentNotValidException.class) | |||
| public ResponseEntity<DataResponseBody> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { | |||
| // 打印堆栈信息 | |||
| LogUtil.error(LogEnum.SYS_ERR, e); | |||
| String[] str = Objects.requireNonNull(e.getBindingResult().getAllErrors().get(0).getCodes())[1].split("\\."); | |||
| String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage(); | |||
| String msg = "不能为空"; | |||
| if (msg.equals(message)) { | |||
| message = str[1] + ":" + message; | |||
| } | |||
| return buildResponseEntity(HttpStatus.BAD_REQUEST, new DataResponseBody(ResponseCode.ERROR, message)); | |||
| } | |||
| @ExceptionHandler(BindException.class) | |||
| public ResponseEntity<DataResponseBody> bindException(BindException e) { | |||
| // 打印堆栈信息 | |||
| LogUtil.error(LogEnum.SYS_ERR, e); | |||
| ObjectError error = e.getAllErrors().get(0); | |||
| return buildResponseEntity(HttpStatus.BAD_REQUEST, | |||
| new DataResponseBody(ResponseCode.ERROR, error.getDefaultMessage())); | |||
| } | |||
| /** | |||
| * 统一返回 | |||
| * | |||
| * @param httpStatus | |||
| * @param responseBody | |||
| * @return | |||
| */ | |||
| private ResponseEntity<DataResponseBody> buildResponseEntity(HttpStatus httpStatus, DataResponseBody responseBody) { | |||
| return new ResponseEntity<>(responseBody, httpStatus); | |||
| } | |||
| } | |||
| @@ -0,0 +1,121 @@ | |||
| /** | |||
| * Copyright 2019-2020 Zheng Jie | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package org.dubhe.factory; | |||
| import org.dubhe.base.DataResponseBody; | |||
| import org.dubhe.base.ResponseCode; | |||
| /** | |||
| * @desc DataResponseBody 工厂类 | |||
| * | |||
| * @date 2020.05.28 | |||
| */ | |||
| public class DataResponseFactory { | |||
| private DataResponseFactory(){ | |||
| } | |||
| /** | |||
| * 成功响应 | |||
| * | |||
| * @param <T> | |||
| * @return | |||
| */ | |||
| public static <T> DataResponseBody success(){ | |||
| return success(null,null); | |||
| } | |||
| /** | |||
| * 成功响应 | |||
| * | |||
| * @param data | |||
| * @param <T> | |||
| * @return | |||
| */ | |||
| public static <T> DataResponseBody success(T data){ | |||
| return success(null,data); | |||
| } | |||
| /** | |||
| * 成功响应 | |||
| * | |||
| * @param msg | |||
| * @return | |||
| */ | |||
| public static DataResponseBody successWithMsg(String msg){ | |||
| return success(msg,null); | |||
| } | |||
| /** | |||
| * 成功响应 | |||
| * | |||
| * @param msg | |||
| * @param data | |||
| * @param <T> | |||
| * @return | |||
| */ | |||
| public static <T> DataResponseBody success(String msg, T data){ | |||
| return new DataResponseBody(ResponseCode.SUCCESS,msg,data); | |||
| } | |||
| /** | |||
| * 失败响应 msg | |||
| * | |||
| * @param msg | |||
| * @return | |||
| */ | |||
| public static DataResponseBody failed(String msg){ | |||
| return failed(ResponseCode.ERROR,msg,null); | |||
| } | |||
| /** | |||
| * 失败响应 | |||
| * | |||
| * @param failedCode | |||
| * @param msg | |||
| * @return | |||
| */ | |||
| public static DataResponseBody failed(Integer failedCode,String msg){ | |||
| return failed(failedCode,msg,null); | |||
| } | |||
| /** | |||
| * 失败响应 | |||
| * | |||
| * @param failedCode | |||
| * @return | |||
| */ | |||
| public static DataResponseBody failed(Integer failedCode){ | |||
| return failed(failedCode,null,null); | |||
| } | |||
| /** | |||
| * 失败响应 | |||
| * | |||
| * @param failedCode | |||
| * @param msg | |||
| * @param data | |||
| * @param <T> | |||
| * @return | |||
| */ | |||
| public static <T> DataResponseBody failed(Integer failedCode, String msg, T data){ | |||
| return new DataResponseBody(failedCode,msg,data); | |||
| } | |||
| } | |||
| @@ -0,0 +1,60 @@ | |||
| /** | |||
| * Copyright 2019-2020 Zheng Jie | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| */ | |||
| package org.dubhe.filter; | |||
| import ch.qos.logback.classic.Level; | |||
| import ch.qos.logback.classic.spi.ILoggingEvent; | |||
| import ch.qos.logback.core.filter.AbstractMatcherFilter; | |||
| import ch.qos.logback.core.spi.FilterReply; | |||
| /** | |||
| * @description 自定义日志过滤器 | |||
| * @date 2020-07-21 | |||
| */ | |||
| public class FileLogFilter extends AbstractMatcherFilter<ILoggingEvent> { | |||
| Level level; | |||
| /** | |||
| * 重写decide方法 | |||
| * | |||
| * @param iLoggingEvent event to decide upon. | |||
| * @return FilterReply | |||
| */ | |||
| @Override | |||
| public FilterReply decide(ILoggingEvent iLoggingEvent) { | |||
| if (!isStarted()) { | |||
| return FilterReply.NEUTRAL; | |||
| } | |||
| if (iLoggingEvent.getLevel().equals(level) && iLoggingEvent.getMessage() != null | |||
| && iLoggingEvent.getMessage().startsWith("{") && iLoggingEvent.getMessage().endsWith("}")) { | |||
| return onMatch; | |||
| } | |||
| return onMismatch; | |||
| } | |||
| public void setLevel(Level level) { | |||
| this.level = level; | |||
| } | |||
| @Override | |||
| public void start() { | |||
| if (this.level != null) { | |||
| super.start(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,68 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.handle; | |||
| import org.springframework.web.servlet.mvc.condition.RequestCondition; | |||
| import javax.servlet.http.HttpServletRequest; | |||
| import java.util.regex.Matcher; | |||
| import java.util.regex.Pattern; | |||
| /** | |||
| * @description API版本控制 | |||
| * @date 2020-04-06 | |||
| */ | |||
| public class ApiVersionCondition implements RequestCondition<ApiVersionCondition> { | |||
| /** | |||
| * 路径中版本的前缀, 这里用 /v[1-9]/的形式 | |||
| */ | |||
| private final static Pattern VERSION_PREFIX_PATTERN = Pattern.compile("v(\\d+)/"); | |||
| private int apiVersion; | |||
| public ApiVersionCondition(int apiVersion) { | |||
| this.apiVersion = apiVersion; | |||
| } | |||
| @Override | |||
| public ApiVersionCondition combine(ApiVersionCondition other) { | |||
| // 采用最后定义优先原则,则方法上的定义覆盖类上面的定义 | |||
| return new ApiVersionCondition(other.getApiVersion()); | |||
| } | |||
| @Override | |||
| public ApiVersionCondition getMatchingCondition(HttpServletRequest request) { | |||
| Matcher m = VERSION_PREFIX_PATTERN.matcher(request.getRequestURI()); | |||
| if (m.find()) { | |||
| Integer version = Integer.valueOf(m.group(1)); | |||
| if (version >= this.apiVersion) { | |||
| return this; | |||
| } | |||
| } | |||
| return null; | |||
| } | |||
| @Override | |||
| public int compareTo(ApiVersionCondition other, HttpServletRequest request) { | |||
| // 优先匹配最新的版本号 | |||
| return other.getApiVersion() - this.apiVersion; | |||
| } | |||
| public int getApiVersion() { | |||
| return apiVersion; | |||
| } | |||
| } | |||
| @@ -0,0 +1,64 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.handle; | |||
| import lombok.Data; | |||
| import org.apache.shiro.authz.annotation.RequiresPermissions; | |||
| import org.dubhe.annotation.ApiVersion; | |||
| import org.springframework.core.annotation.AnnotationUtils; | |||
| import org.springframework.stereotype.Component; | |||
| import org.springframework.web.servlet.mvc.condition.RequestCondition; | |||
| import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; | |||
| import java.lang.reflect.Method; | |||
| import java.util.HashSet; | |||
| import java.util.Set; | |||
| /** | |||
| * @description 权限注解收集 | |||
| * @date 2020-04-06 | |||
| */ | |||
| @Component | |||
| @Data | |||
| public class CustomRequestMappingHandlerMapping extends RequestMappingHandlerMapping { | |||
| Set<String> permissionsSet =new HashSet<String>(); | |||
| @Override | |||
| protected RequestCondition<ApiVersionCondition> getCustomTypeCondition(Class<?> handlerType) { | |||
| ApiVersion apiVersion = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class); | |||
| return createCondition(apiVersion); | |||
| } | |||
| @Override | |||
| protected RequestCondition<ApiVersionCondition> getCustomMethodCondition(Method method) { | |||
| RequiresPermissions requiresPermissions = AnnotationUtils.findAnnotation(method, RequiresPermissions.class); | |||
| if(requiresPermissions != null){ | |||
| if(requiresPermissions.value()!=null){ | |||
| for(int i=0;i<requiresPermissions.value().length;i++){ | |||
| permissionsSet.add(requiresPermissions.value()[i]); | |||
| } | |||
| } | |||
| } | |||
| ApiVersion apiVersion = AnnotationUtils.findAnnotation(method, ApiVersion.class); | |||
| return createCondition(apiVersion); | |||
| } | |||
| private RequestCondition<ApiVersionCondition> createCondition(ApiVersion apiVersion) { | |||
| return apiVersion == null ? null : new ApiVersionCondition(apiVersion.value()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,58 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.interceptor; | |||
| import org.dubhe.enums.LogEnum; | |||
| import org.dubhe.utils.K8sCallBackTool; | |||
| import org.dubhe.utils.LogUtil; | |||
| import org.dubhe.utils.StringUtils; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Component; | |||
| import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; | |||
| import javax.servlet.http.HttpServletRequest; | |||
| import javax.servlet.http.HttpServletResponse; | |||
| /** | |||
| * @description k8s pod 异步回调拦截器 | |||
| * | |||
| * @date 2020-05-28 | |||
| */ | |||
| @Component | |||
| public class K8sCallBackPodInterceptor extends HandlerInterceptorAdapter { | |||
| @Autowired | |||
| private K8sCallBackTool k8sCallBackTool; | |||
| @Override | |||
| public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { | |||
| String uri = request.getRequestURI(); | |||
| LogUtil.debug(LogEnum.BIZ_K8S,"接收到k8s异步请求,URI:{}",uri); | |||
| String k8sCallbackToken = request.getHeader(K8sCallBackTool.K8S_CALLBACK_TOKEN); | |||
| if (StringUtils.isBlank(k8sCallbackToken)){ | |||
| LogUtil.warn(LogEnum.BIZ_K8S,"k8s异步回调没有配置【{}】,URI:{}",K8sCallBackTool.K8S_CALLBACK_TOKEN,uri); | |||
| return false; | |||
| } | |||
| boolean pass = k8sCallBackTool.validateToken(k8sCallbackToken); | |||
| if (!pass){ | |||
| LogUtil.warn(LogEnum.BIZ_K8S,"k8s异步回调token:【{}】 验证不通过,URI:{}",k8sCallbackToken,uri); | |||
| } | |||
| return pass; | |||
| } | |||
| } | |||
| @@ -0,0 +1,97 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.utils; | |||
| import cn.hutool.core.util.HexUtil; | |||
| import org.dubhe.enums.LogEnum; | |||
| import javax.crypto.Cipher; | |||
| import javax.crypto.NoSuchPaddingException; | |||
| import javax.crypto.spec.SecretKeySpec; | |||
| import java.nio.charset.StandardCharsets; | |||
| import java.security.InvalidKeyException; | |||
| import java.security.MessageDigest; | |||
| import java.security.NoSuchAlgorithmException; | |||
| /** | |||
| * @description AES加解密工具 | |||
| * @date 2020-06-01 | |||
| */ | |||
| public class AesUtil { | |||
| private static final String AES = "AES"; | |||
| private AesUtil(){ | |||
| } | |||
| /** | |||
| * | |||
| * @param mode Cipher mode | |||
| * @param key 秘钥 | |||
| * @return Cipher | |||
| * @throws NoSuchAlgorithmException | |||
| * @throws NoSuchPaddingException | |||
| * @throws InvalidKeyException | |||
| */ | |||
| private static Cipher getCipher(int mode,String key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException { | |||
| MessageDigest md5Digest = MessageDigest.getInstance("MD5"); | |||
| SecretKeySpec secretKeySpec = new SecretKeySpec(md5Digest.digest(key.getBytes(StandardCharsets.UTF_8)), AES); | |||
| Cipher cipher = Cipher.getInstance(AES); | |||
| cipher.init(mode, secretKeySpec); | |||
| return cipher; | |||
| } | |||
| /** | |||
| * 加密 | |||
| * | |||
| * @param data 原文 | |||
| * @param key 秘钥 | |||
| * @return String 密文 | |||
| */ | |||
| public static String encrypt(String data, String key) { | |||
| try { | |||
| Cipher cipher = getCipher(Cipher.ENCRYPT_MODE,key); | |||
| byte[] content = data.getBytes(StandardCharsets.UTF_8); | |||
| return new String(HexUtil.encodeHex(cipher.doFinal(content), false)); | |||
| } catch (Exception e) { | |||
| LogUtil.error(LogEnum.BIZ_SYS,"Md5Util 加密失败 ",e); | |||
| return null; | |||
| } | |||
| } | |||
| /** | |||
| * 解密 | |||
| * @param hexData 十六进制密文 | |||
| * @param key 秘钥 | |||
| * @return String 密文 | |||
| */ | |||
| public static String decrypt(String hexData, String key) { | |||
| try { | |||
| Cipher cipher = getCipher(Cipher.DECRYPT_MODE,key); | |||
| byte[] content = HexUtil.decodeHex(hexData); | |||
| return new String(cipher.doFinal(content), StandardCharsets.UTF_8); | |||
| } catch (Exception e) { | |||
| LogUtil.error(LogEnum.BIZ_SYS,"Md5Util 解密失败 ",e); | |||
| return null; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,80 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.utils; | |||
| import java.sql.Timestamp; | |||
| import java.time.Instant; | |||
| import java.time.LocalDate; | |||
| import java.time.LocalDateTime; | |||
| import java.time.ZoneId; | |||
| /** | |||
| * @description 日期工具类 | |||
| * @date 2020-6-10 | |||
| */ | |||
| public class DateUtil { | |||
| /** | |||
| * 获取当前时间戳 | |||
| * | |||
| * @return | |||
| */ | |||
| public static Timestamp getCurrentTimestamp() { | |||
| return Timestamp.valueOf(LocalDateTime.now()); | |||
| } | |||
| /** | |||
| * 获取六小时后时间 | |||
| * @return | |||
| */ | |||
| public static long getAfterSixHourTime(){ | |||
| long l1 = getTimestampOfDateTime(LocalDateTime.now()); | |||
| long milli = getTimestampOfDateTime(LocalDateTime.now().plusHours(6)); | |||
| return (milli-l1); | |||
| } | |||
| /** | |||
| * LocalDateTime -> long | |||
| * @param localDateTime | |||
| * @return | |||
| */ | |||
| public static long getTimestampOfDateTime(LocalDateTime localDateTime) { | |||
| ZoneId zone = ZoneId.systemDefault(); | |||
| Instant instant = localDateTime.atZone(zone).toInstant(); | |||
| return instant.toEpochMilli(); | |||
| } | |||
| /** | |||
| * 获取第二天凌晨时间 | |||
| * @return | |||
| */ | |||
| public static long getSecondTime(){ | |||
| LocalDateTime localDateTime = LocalDateTime.now(); | |||
| long l1 = localDateTime.atZone(ZoneId.of("Asia/Shanghai")).toInstant().toEpochMilli(); | |||
| LocalDate localDate = LocalDate.now(); | |||
| LocalDate localDate1 = localDate.plusDays(1); | |||
| LocalDateTime localDateTime1 = localDate1.atStartOfDay(); | |||
| long milli = localDateTime1.atZone(ZoneId.of("Asia/Shanghai")).toInstant().toEpochMilli(); | |||
| System.out.println("当前时间到第二天凌晨的毫秒数"+(milli-l1)); | |||
| return (milli-l1); | |||
| } | |||
| } | |||
| @@ -0,0 +1,47 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.utils; | |||
| /** | |||
| * @description 日期工具类 | |||
| * @date 2020-5-29 | |||
| **/ | |||
| public class DubheDateUtil { | |||
| private static final int SIXTY = 60; | |||
| /** | |||
| * 将时间 秒 转为 小时 | |||
| * | |||
| * @param second 秒数 | |||
| * @return | |||
| */ | |||
| public static String convert2Str(Long second) { | |||
| if (null == second || second < 1) { | |||
| return ""; | |||
| } | |||
| Long hh = second / (SIXTY * SIXTY); | |||
| second = second % (SIXTY * SIXTY); | |||
| Long mm = second / SIXTY; | |||
| Long ss = second % SIXTY; | |||
| StringBuilder sb = new StringBuilder(); | |||
| sb.append(String.format("%02d", hh)).append(":").append(String.format("%02d", mm)).append(":").append(String.format("%02d", ss)); | |||
| return sb.toString(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,100 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.utils; | |||
| import javax.crypto.Cipher; | |||
| import javax.crypto.SecretKey; | |||
| import javax.crypto.SecretKeyFactory; | |||
| import javax.crypto.spec.DESKeySpec; | |||
| import javax.crypto.spec.IvParameterSpec; | |||
| import java.nio.charset.StandardCharsets; | |||
| /** | |||
| * @description 加密 | |||
| * @date 2020-03-13 | |||
| */ | |||
| public class EncryptUtils { | |||
| private static String strParam = "Passw0rd"; | |||
| private static Cipher cipher; | |||
| private static IvParameterSpec iv = new IvParameterSpec(strParam.getBytes(StandardCharsets.UTF_8)); | |||
| private static DESKeySpec getDesKeySpec(String source) throws Exception { | |||
| if (source == null || source.length() == 0) { | |||
| return null; | |||
| } | |||
| cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); | |||
| String strKey = "Passw0rd"; | |||
| return new DESKeySpec(strKey.getBytes(StandardCharsets.UTF_8)); | |||
| } | |||
| /** | |||
| * 对称加密 | |||
| */ | |||
| public static String desEncrypt(String source) throws Exception { | |||
| DESKeySpec desKeySpec = getDesKeySpec(source); | |||
| SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); | |||
| SecretKey secretKey = keyFactory.generateSecret(desKeySpec); | |||
| cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv); | |||
| return byte2hex( | |||
| cipher.doFinal(source.getBytes(StandardCharsets.UTF_8))).toUpperCase(); | |||
| } | |||
| /** | |||
| * 对称解密 | |||
| */ | |||
| public static String desDecrypt(String source) throws Exception { | |||
| byte[] src = hex2byte(source.getBytes()); | |||
| DESKeySpec desKeySpec = getDesKeySpec(source); | |||
| SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); | |||
| SecretKey secretKey = keyFactory.generateSecret(desKeySpec); | |||
| cipher.init(Cipher.DECRYPT_MODE, secretKey, iv); | |||
| byte[] retByte = cipher.doFinal(src); | |||
| return new String(retByte); | |||
| } | |||
| private static String byte2hex(byte[] inStr) { | |||
| String stmp; | |||
| StringBuilder out = new StringBuilder(inStr.length * 2); | |||
| for (byte b : inStr) { | |||
| stmp = Integer.toHexString(b & 0xFF); | |||
| if (stmp.length() == 1) { | |||
| // 如果是0至F的单位字符串,则添加0 | |||
| out.append("0").append(stmp); | |||
| } else { | |||
| out.append(stmp); | |||
| } | |||
| } | |||
| return out.toString(); | |||
| } | |||
| private static byte[] hex2byte(byte[] b) { | |||
| int size = 2; | |||
| if ((b.length % size) != 0) { | |||
| throw new IllegalArgumentException("长度不是偶数"); | |||
| } | |||
| byte[] b2 = new byte[b.length / 2]; | |||
| for (int n = 0; n < b.length; n += size) { | |||
| String item = new String(b, n, 2); | |||
| b2[n / 2] = (byte) Integer.parseInt(item, 16); | |||
| } | |||
| return b2; | |||
| } | |||
| } | |||
| @@ -0,0 +1,355 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.utils; | |||
| import cn.hutool.core.codec.Base64; | |||
| import cn.hutool.core.io.IoUtil; | |||
| import cn.hutool.core.util.IdUtil; | |||
| import cn.hutool.poi.excel.BigExcelWriter; | |||
| import cn.hutool.poi.excel.ExcelUtil; | |||
| import org.apache.poi.util.IOUtils; | |||
| import org.dubhe.exception.BusinessException; | |||
| import org.springframework.web.multipart.MultipartFile; | |||
| import javax.servlet.ServletOutputStream; | |||
| import javax.servlet.http.HttpServletRequest; | |||
| import javax.servlet.http.HttpServletResponse; | |||
| import java.io.*; | |||
| import java.security.MessageDigest; | |||
| import java.text.DecimalFormat; | |||
| import java.text.SimpleDateFormat; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| /** | |||
| * @description File工具类,扩展 hutool 工具包 | |||
| * @date 2020-03-14 | |||
| */ | |||
| public class FileUtil extends cn.hutool.core.io.FileUtil { | |||
| /** | |||
| * 定义GB的计算常量 | |||
| */ | |||
| private static final int GB = 1024 * 1024 * 1024; | |||
| /** | |||
| * 定义MB的计算常量 | |||
| */ | |||
| private static final int MB = 1024 * 1024; | |||
| /** | |||
| * 定义KB的计算常量 | |||
| */ | |||
| private static final int KB = 1024; | |||
| /** | |||
| * 格式化小数 | |||
| */ | |||
| private static final DecimalFormat DF = new DecimalFormat("0.00"); | |||
| /** | |||
| * MultipartFile转File | |||
| */ | |||
| public static File toFile(MultipartFile multipartFile) { | |||
| // 获取文件名 | |||
| String fileName = multipartFile.getOriginalFilename(); | |||
| // 获取文件后缀 | |||
| String prefix = "." + getExtensionName(fileName); | |||
| File file = null; | |||
| try { | |||
| // 用uuid作为文件名,防止生成的临时文件重复 | |||
| file = File.createTempFile(IdUtil.simpleUUID(), prefix); | |||
| // MultipartFile to File | |||
| multipartFile.transferTo(file); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return file; | |||
| } | |||
| /** | |||
| * 获取文件扩展名,不带 . | |||
| */ | |||
| public static String getExtensionName(String filename) { | |||
| if ((filename != null) && (filename.length() > 0)) { | |||
| int dot = filename.lastIndexOf('.'); | |||
| if ((dot > -1) && (dot < (filename.length() - 1))) { | |||
| return filename.substring(dot + 1); | |||
| } | |||
| } | |||
| return filename; | |||
| } | |||
| /** | |||
| * Java文件操作 获取不带扩展名的文件名 | |||
| */ | |||
| public static String getFileNameNoEx(String filename) { | |||
| if ((filename != null) && (filename.length() > 0)) { | |||
| int dot = filename.lastIndexOf('.'); | |||
| if ((dot > -1) && (dot < (filename.length()))) { | |||
| return filename.substring(0, dot); | |||
| } | |||
| } | |||
| return filename; | |||
| } | |||
| /** | |||
| * 文件大小转换 | |||
| */ | |||
| public static String getSize(long size) { | |||
| String resultSize; | |||
| if (size / GB >= 1) { | |||
| //如果当前Byte的值大于等于1GB | |||
| resultSize = DF.format(size / (float) GB) + "GB "; | |||
| } else if (size / MB >= 1) { | |||
| //如果当前Byte的值大于等于1MB | |||
| resultSize = DF.format(size / (float) MB) + "MB "; | |||
| } else if (size / KB >= 1) { | |||
| //如果当前Byte的值大于等于1KB | |||
| resultSize = DF.format(size / (float) KB) + "KB "; | |||
| } else { | |||
| resultSize = size + "B "; | |||
| } | |||
| return resultSize; | |||
| } | |||
| /** | |||
| * inputStream 转 File | |||
| */ | |||
| static File inputStreamToFile(InputStream ins, String name) throws Exception { | |||
| File file = new File(System.getProperty("java.io.tmpdir") + File.separator + name); | |||
| if (file.exists()) { | |||
| return file; | |||
| } | |||
| OutputStream os = new FileOutputStream(file); | |||
| int bytesRead; | |||
| int len = 8192; | |||
| byte[] buffer = new byte[len]; | |||
| while ((bytesRead = ins.read(buffer, 0, len)) != -1) { | |||
| os.write(buffer, 0, bytesRead); | |||
| } | |||
| os.close(); | |||
| ins.close(); | |||
| return file; | |||
| } | |||
| /** | |||
| * 将文件名解析成文件的上传路径 | |||
| */ | |||
| public static File upload(MultipartFile file, String filePath) { | |||
| Date date = new Date(); | |||
| SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssS"); | |||
| String name = getFileNameNoEx(file.getOriginalFilename()); | |||
| String suffix = getExtensionName(file.getOriginalFilename()); | |||
| String nowStr = "-" + format.format(date); | |||
| try { | |||
| String fileName = name + nowStr + "." + suffix; | |||
| String path = filePath + fileName; | |||
| // getCanonicalFile 可解析正确各种路径 | |||
| File dest = new File(path).getCanonicalFile(); | |||
| // 检测是否存在目录 | |||
| if (!dest.getParentFile().exists()) { | |||
| dest.getParentFile().mkdirs(); | |||
| } | |||
| // 文件写入 | |||
| file.transferTo(dest); | |||
| return dest; | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return null; | |||
| } | |||
| public static String fileToBase64(File file) throws Exception { | |||
| FileInputStream inputFile = new FileInputStream(file); | |||
| String base64; | |||
| byte[] buffer = new byte[(int) file.length()]; | |||
| inputFile.read(buffer); | |||
| inputFile.close(); | |||
| base64 = Base64.encode(buffer); | |||
| return base64.replaceAll("[\\s*\t\n\r]", ""); | |||
| } | |||
| /** | |||
| * 导出excel | |||
| */ | |||
| public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response) throws IOException { | |||
| String tempPath = System.getProperty("java.io.tmpdir") + IdUtil.fastSimpleUUID() + ".xlsx"; | |||
| File file = new File(tempPath); | |||
| BigExcelWriter writer = ExcelUtil.getBigWriter(file); | |||
| // 一次性写出内容,使用默认样式,强制输出标题 | |||
| writer.write(list, true); | |||
| //response为HttpServletResponse对象 | |||
| response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"); | |||
| //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码 | |||
| response.setHeader("Content-Disposition", "attachment;filename=file.xlsx"); | |||
| ServletOutputStream out = response.getOutputStream(); | |||
| // 终止后删除临时文件 | |||
| file.deleteOnExit(); | |||
| writer.flush(out, true); | |||
| //此处记得关闭输出Servlet流 | |||
| IoUtil.close(out); | |||
| } | |||
| /** | |||
| * 下载文件 | |||
| */ | |||
| public static void download(String path, HttpServletResponse response) { | |||
| if (path == null) { | |||
| return; | |||
| } | |||
| FileInputStream fis = null; | |||
| ServletOutputStream out = null; | |||
| try { | |||
| File file = new File(path); | |||
| fis = new FileInputStream(file); | |||
| out = response.getOutputStream(); | |||
| IOUtils.copy(fis, out); | |||
| response.flushBuffer(); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } finally { | |||
| if (fis != null) { | |||
| try { | |||
| fis.close(); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| //此处记得关闭输出Servlet流 | |||
| IoUtil.close(out); | |||
| } | |||
| } | |||
| public static String getFileType(String type) { | |||
| String documents = "txt doc pdf ppt pps xlsx xls docx"; | |||
| String music = "mp3 wav wma mpa ram ra aac aif m4a"; | |||
| String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg"; | |||
| String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg"; | |||
| if (image.contains(type)) { | |||
| return "图片"; | |||
| } else if (documents.contains(type)) { | |||
| return "文档"; | |||
| } else if (music.contains(type)) { | |||
| return "音乐"; | |||
| } else if (video.contains(type)) { | |||
| return "视频"; | |||
| } else { | |||
| return "其他"; | |||
| } | |||
| } | |||
| public static void checkSize(long maxSize, long size) { | |||
| // 1M | |||
| int len = 1024 * 1024; | |||
| if (size > (maxSize * len)) { | |||
| throw new BusinessException("文件超出规定大小"); | |||
| } | |||
| } | |||
| /** | |||
| * 判断两个文件是否相同 | |||
| */ | |||
| public static boolean check(File file1, File file2) { | |||
| String img1Md5 = getMd5(file1); | |||
| String img2Md5 = getMd5(file2); | |||
| return img1Md5.equals(img2Md5); | |||
| } | |||
| /** | |||
| * 判断两个文件是否相同 | |||
| */ | |||
| public static boolean check(String file1Md5, String file2Md5) { | |||
| return file1Md5.equals(file2Md5); | |||
| } | |||
| private static byte[] getByte(File file) { | |||
| // 得到文件长度 | |||
| byte[] b = new byte[(int) file.length()]; | |||
| try { | |||
| InputStream in = new FileInputStream(file); | |||
| try { | |||
| in.read(b); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } catch (FileNotFoundException e) { | |||
| e.printStackTrace(); | |||
| return null; | |||
| } | |||
| return b; | |||
| } | |||
| private static String getMd5(byte[] bytes) { | |||
| // 16进制字符 | |||
| char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; | |||
| try { | |||
| MessageDigest mdTemp = MessageDigest.getInstance("MD5"); | |||
| mdTemp.update(bytes); | |||
| byte[] md = mdTemp.digest(); | |||
| int j = md.length; | |||
| char[] str = new char[j * 2]; | |||
| int k = 0; | |||
| // 移位 输出字符串 | |||
| for (byte byte0 : md) { | |||
| str[k++] = hexDigits[byte0 >>> 4 & 0xf]; | |||
| str[k++] = hexDigits[byte0 & 0xf]; | |||
| } | |||
| return new String(str); | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return null; | |||
| } | |||
| /** | |||
| * 下载文件 | |||
| * | |||
| * @param request / | |||
| * @param response / | |||
| * @param file / | |||
| */ | |||
| public static void downloadFile(HttpServletRequest request, HttpServletResponse response, File file, boolean deleteOnExit) { | |||
| response.setCharacterEncoding(request.getCharacterEncoding()); | |||
| response.setContentType("application/octet-stream"); | |||
| FileInputStream fis = null; | |||
| try { | |||
| fis = new FileInputStream(file); | |||
| response.setHeader("Content-Disposition", "attachment; filename=" + file.getName()); | |||
| IOUtils.copy(fis, response.getOutputStream()); | |||
| response.flushBuffer(); | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| } finally { | |||
| if (fis != null) { | |||
| try { | |||
| fis.close(); | |||
| if (deleteOnExit) { | |||
| file.deleteOnExit(); | |||
| } | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| public static String getMd5(File file) { | |||
| return getMd5(getByte(file)); | |||
| } | |||
| } | |||
| @@ -0,0 +1,131 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.utils; | |||
| import org.apache.commons.io.IOUtils; | |||
| import org.dubhe.enums.LogEnum; | |||
| import javax.net.ssl.HttpsURLConnection; | |||
| import javax.net.ssl.SSLContext; | |||
| import javax.net.ssl.SSLSocketFactory; | |||
| import javax.net.ssl.TrustManager; | |||
| import javax.net.ssl.X509TrustManager; | |||
| import java.io.BufferedReader; | |||
| import java.io.InputStream; | |||
| import java.io.InputStreamReader; | |||
| import java.net.URL; | |||
| import java.security.cert.CertificateException; | |||
| import java.security.cert.X509Certificate; | |||
| import static org.dubhe.constant.StringConstant.UTF8; | |||
| import static org.dubhe.constant.SymbolConstant.BLANK; | |||
| /** | |||
| * @description: httpClient工具类,不校验SSL证书 | |||
| * @date: 2020-5-21 | |||
| */ | |||
| public class HttpClientUtils { | |||
| public static String sendHttps(String path) { | |||
| InputStream inputStream = null; | |||
| BufferedReader bufferedReader = null; | |||
| InputStreamReader inputStreamReader = null; | |||
| StringBuilder stringBuider = new StringBuilder(); | |||
| String result = BLANK; | |||
| HttpsURLConnection con = null; | |||
| try { | |||
| con = getConnection(path); | |||
| con.connect(); | |||
| /**将返回的输入流转换成字符串**/ | |||
| inputStream = con.getInputStream(); | |||
| inputStreamReader = new InputStreamReader(inputStream, UTF8); | |||
| bufferedReader = new BufferedReader(inputStreamReader); | |||
| String str = null; | |||
| while ((str = bufferedReader.readLine()) != null) { | |||
| stringBuider.append(str); | |||
| } | |||
| result = stringBuider.toString(); | |||
| LogUtil.info(LogEnum.BIZ_SYS,"Request path:{}, SUCCESS, result:{}", path, result); | |||
| } catch (Exception e) { | |||
| LogUtil.error(LogEnum.BIZ_SYS,"Request path:{}, ERROR, exception:{}", path, e); | |||
| return result; | |||
| } finally { | |||
| closeResource(bufferedReader,inputStreamReader,inputStream,con); | |||
| } | |||
| return result; | |||
| } | |||
| private static void closeResource(BufferedReader bufferedReader,InputStreamReader inputStreamReader,InputStream inputStream,HttpsURLConnection con) { | |||
| IOUtils.closeQuietly(bufferedReader); | |||
| if (inputStreamReader != null) { | |||
| IOUtils.closeQuietly(inputStreamReader); | |||
| } | |||
| if (inputStream != null) { | |||
| IOUtils.closeQuietly(inputStream); | |||
| } | |||
| if (con != null) { | |||
| con.disconnect(); | |||
| } | |||
| } | |||
| private static HttpsURLConnection getConnection(String path){ | |||
| HttpsURLConnection con = null; | |||
| try { | |||
| /**创建并初始化SSLContext对象**/ | |||
| TrustManager[] trustManagers = {new X509TrustManager() { | |||
| @Override | |||
| public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { | |||
| } | |||
| @Override | |||
| public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { | |||
| } | |||
| @Override | |||
| public X509Certificate[] getAcceptedIssuers() { | |||
| return null; | |||
| } | |||
| }}; | |||
| SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE"); | |||
| sslContext.init(null, trustManagers, new java.security.SecureRandom()); | |||
| /**得到SSLSocketFactory对象**/ | |||
| SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); | |||
| URL url = new URL(path); | |||
| con = (HttpsURLConnection) url.openConnection(); | |||
| con.setSSLSocketFactory(sslSocketFactory); | |||
| con.setUseCaches(false); | |||
| }catch (Exception e){ | |||
| LogUtil.error(LogEnum.BIZ_SYS,"Request path:{}, error, exception:{}", path, e); | |||
| } | |||
| return con; | |||
| } | |||
| } | |||
| @@ -0,0 +1,66 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.utils; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| /** | |||
| * @description: HttpUtil | |||
| * @date 2020.04.30 | |||
| */ | |||
| @Slf4j | |||
| public class HttpUtils { | |||
| private HttpUtils() { | |||
| } | |||
| /** | |||
| * 判断http请求是否成功 | |||
| * | |||
| * @param httpCode | |||
| * 1XX Informational(信息性状态码) | |||
| * 2XX Success(成功状态码) | |||
| * 3XX Redirection(重定向状态码) | |||
| * 4XX Client Error(客户端错误状态码) | |||
| * 5XX Server Error(服务器错误状态码) | |||
| * @return | |||
| */ | |||
| public static boolean isSuccess(String httpCode){ | |||
| if (StringUtils.isBlank(httpCode)){ | |||
| return false; | |||
| } | |||
| return httpCode.length() == 3 && httpCode.startsWith("2"); | |||
| } | |||
| /** | |||
| * 判断http请求是否成功 | |||
| * | |||
| * @param httpCode | |||
| * 1XX Informational(信息性状态码) | |||
| * 2XX Success(成功状态码) | |||
| * 3XX Redirection(重定向状态码) | |||
| * 4XX Client Error(客户端错误状态码) | |||
| * 5XX Server Error(服务器错误状态码) | |||
| * @return | |||
| */ | |||
| public static boolean isSuccess(int httpCode) { | |||
| return isSuccess(String.valueOf(httpCode)); | |||
| } | |||
| } | |||
| @@ -0,0 +1,37 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.utils; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.context.annotation.Configuration; | |||
| /** | |||
| * @description JWT配置类 | |||
| * @date 2020-04-15 | |||
| */ | |||
| @Configuration | |||
| public class JwcConfig { | |||
| @Value("${jwt.online-key}") | |||
| public String onlineKey; | |||
| @Autowired | |||
| public RedisUtils redisUtils; | |||
| @Value("${jwt.token-validity-in-seconds}") | |||
| public Long jwtExpiration; | |||
| @Value("${jwt.base64-secret}") | |||
| public String secret; | |||
| } | |||
| @@ -0,0 +1,203 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.utils; | |||
| import com.auth0.jwt.JWT; | |||
| import com.auth0.jwt.JWTCreator.Builder; | |||
| import com.auth0.jwt.JWTVerifier; | |||
| import com.auth0.jwt.algorithms.Algorithm; | |||
| import com.auth0.jwt.exceptions.JWTDecodeException; | |||
| import com.auth0.jwt.interfaces.Claim; | |||
| import com.auth0.jwt.interfaces.DecodedJWT; | |||
| import org.apache.shiro.SecurityUtils; | |||
| import org.apache.shiro.crypto.SecureRandomNumberGenerator; | |||
| import org.apache.shiro.mgt.SecurityManager; | |||
| import org.apache.shiro.util.ThreadContext; | |||
| import org.dubhe.domain.dto.UserDTO; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Component; | |||
| import java.io.UnsupportedEncodingException; | |||
| import java.util.Calendar; | |||
| import java.util.Date; | |||
| import java.util.Map; | |||
| import java.util.Map.Entry; | |||
| import java.util.Objects; | |||
| import java.util.concurrent.TimeUnit; | |||
| /** | |||
| * @description JWT | |||
| * @date 2020-03-14 | |||
| */ | |||
| @Component | |||
| public class JwtUtils { | |||
| /** | |||
| * 请求头 | |||
| */ | |||
| public static final String AUTH_HEADER = "Authorization"; | |||
| /** | |||
| * 过期时间20分钟 | |||
| */ | |||
| private static final long EXPIRE_TIME = 20 * 60 * 1000; | |||
| private static final String FIELD_NAME = "USER_NAME"; | |||
| private static JwcConfig jwcConfig; | |||
| private static RedisUtils redisUtils; | |||
| @Autowired | |||
| public void setJwcConfig(JwcConfig mtJwcConfig) { | |||
| jwcConfig = mtJwcConfig; | |||
| } | |||
| @Autowired | |||
| public void setRedisUtils(RedisUtils myredisUtils) { | |||
| redisUtils = myredisUtils; | |||
| } | |||
| /** | |||
| * 验证token是否正确 | |||
| */ | |||
| public static boolean verify(String token, String username) { | |||
| try { | |||
| Algorithm algorithm = null; | |||
| algorithm = Algorithm.HMAC256(jwcConfig.secret); | |||
| JWTVerifier verifier = JWT.require(algorithm).withClaim(FIELD_NAME, username).build(); | |||
| verifier.verify(token); | |||
| return true; | |||
| } catch (UnsupportedEncodingException exception) { | |||
| return false; | |||
| } | |||
| } | |||
| /** | |||
| * 获得token中的自定义信息,无需secret解密也能获得 | |||
| */ | |||
| public static String getClaimFiled(String token, String filed) { | |||
| try { | |||
| DecodedJWT jwt = JWT.decode(token); | |||
| return jwt.getClaim(filed).asString(); | |||
| } catch (JWTDecodeException e) { | |||
| return null; | |||
| } | |||
| } | |||
| /** | |||
| * 生成签名 | |||
| */ | |||
| public static String sign(String userName) { | |||
| try { | |||
| Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME); | |||
| Algorithm algorithm = Algorithm.HMAC256(jwcConfig.secret); | |||
| // 附带username, | |||
| String token = JWT.create().withClaim(FIELD_NAME, userName).withExpiresAt(date).sign(algorithm); | |||
| saveToken(userName, token); | |||
| return token; | |||
| } catch (UnsupportedEncodingException e) { | |||
| return null; | |||
| } | |||
| } | |||
| /** | |||
| * 获取用户名 | |||
| */ | |||
| public static String getUserName(String token) { | |||
| return getClaimFiled(token, FIELD_NAME); | |||
| } | |||
| /** | |||
| * 获取 token的签发时间 | |||
| */ | |||
| public static Date getIssuedAt(String token) { | |||
| try { | |||
| DecodedJWT jwt = JWT.decode(token); | |||
| return jwt.getIssuedAt(); | |||
| } catch (JWTDecodeException e) { | |||
| return null; | |||
| } | |||
| } | |||
| /** | |||
| * 验证 token是否过期 | |||
| */ | |||
| public static boolean isTokenExpired(String token) { | |||
| Date now = Calendar.getInstance().getTime(); | |||
| DecodedJWT jwt = JWT.decode(token); | |||
| return jwt.getExpiresAt().before(now); | |||
| } | |||
| /** | |||
| * 刷新 token的过期时间 | |||
| */ | |||
| public static String refreshTokenExpired(String token) { | |||
| DecodedJWT jwt = JWT.decode(token); | |||
| Map<String, Claim> claims = jwt.getClaims(); | |||
| try { | |||
| Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME); | |||
| Algorithm algorithm = Algorithm.HMAC256(jwcConfig.secret); | |||
| Builder builer = JWT.create().withExpiresAt(date); | |||
| for (Entry<String, Claim> entry : claims.entrySet()) { | |||
| builer.withClaim(entry.getKey(), entry.getValue().asString()); | |||
| } | |||
| String newToken = builer.sign(algorithm); | |||
| String userName = claims.get(FIELD_NAME).asString(); | |||
| String tokenKey = getUserTokenKey(userName); | |||
| if (redisUtils.get(tokenKey) == null) { | |||
| return null; | |||
| } | |||
| saveToken(userName, newToken); | |||
| return newToken; | |||
| } catch (UnsupportedEncodingException e) { | |||
| return null; | |||
| } | |||
| } | |||
| /** | |||
| * 生成16位随机盐 | |||
| */ | |||
| public static String generateSalt() { | |||
| SecureRandomNumberGenerator secureRandom = new SecureRandomNumberGenerator(); | |||
| String hex = secureRandom.nextBytes(16).toHex(); | |||
| return hex; | |||
| } | |||
| /** | |||
| * 获取当前用户 | |||
| */ | |||
| public static UserDTO getCurrentUserDto() { | |||
| Object principal = null; | |||
| SecurityManager manager = ThreadContext.getSecurityManager(); | |||
| if (!Objects.isNull(manager)) { | |||
| principal = SecurityUtils.getSubject().getPrincipal(); | |||
| } | |||
| return Objects.isNull(principal) ? null : (UserDTO) principal; | |||
| } | |||
| /** | |||
| * 获取用户token key | |||
| */ | |||
| private static String getUserTokenKey(String userName) { | |||
| return jwcConfig.onlineKey + userName; | |||
| } | |||
| private static void saveToken(String userName, String token) { | |||
| String tokenKey = getUserTokenKey(userName); | |||
| redisUtils.set(tokenKey, token, jwcConfig.jwtExpiration, TimeUnit.MINUTES); | |||
| } | |||
| } | |||
| @@ -0,0 +1,168 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.utils; | |||
| import cn.hutool.core.date.DateField; | |||
| import cn.hutool.core.date.DatePattern; | |||
| import cn.hutool.core.date.DateUtil; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.stereotype.Component; | |||
| import java.util.ArrayList; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| /** | |||
| * @description k8s命名相关工具类 token使用MD5加密,并设置超时时间 | |||
| * @date 2020-05-28 | |||
| */ | |||
| @Component | |||
| public class K8sCallBackTool { | |||
| /** | |||
| * k8s 回调 token秘钥 | |||
| */ | |||
| @Value("${k8s.callback.token.secret-key}") | |||
| private String secretKey; | |||
| /** | |||
| * k8s 回调token超时时间 | |||
| */ | |||
| @Value("${k8s.callback.token.expire-seconds}") | |||
| private Integer expireSeconds; | |||
| /** | |||
| * k8s 回调域名或IP:Port | |||
| */ | |||
| @Value("${k8s.callback.url}") | |||
| private String url; | |||
| /** | |||
| * k8s 回调token key | |||
| */ | |||
| public static final String K8S_CALLBACK_TOKEN = "k8sCallbackToken"; | |||
| /** | |||
| * 失败重试次数 | |||
| */ | |||
| private static final int RETRY_COUNT = 3; | |||
| /** | |||
| * k8s 回调匹配地址 | |||
| */ | |||
| private static final List<String> K8S_CALLBACK_PATH; | |||
| /** | |||
| * k8s 回调路径 | |||
| */ | |||
| private static final String K8S_CALLBACK_PATH_POD = "/api/k8s/callback/pod/"; | |||
| static { | |||
| K8S_CALLBACK_PATH = new ArrayList<>(); | |||
| // 添加需要token权限校验的地址(Shiro匿名访问的地址) | |||
| K8S_CALLBACK_PATH.add(K8S_CALLBACK_PATH_POD + "**"); | |||
| } | |||
| /** | |||
| * 获取 k8s 回调匹配地址 | |||
| * | |||
| * @return List<String> | |||
| */ | |||
| public static List<String> getK8sCallbackPaths() { | |||
| return new ArrayList<>(K8S_CALLBACK_PATH); | |||
| } | |||
| /** | |||
| * 生成k8s回调 | |||
| * | |||
| * @return String | |||
| */ | |||
| public String generateToken() { | |||
| String expireTime = DateUtil.format( | |||
| DateUtil.offset(new Date(), DateField.SECOND, expireSeconds), | |||
| DatePattern.PURE_DATETIME_PATTERN | |||
| ); | |||
| return AesUtil.encrypt(expireTime, secretKey); | |||
| } | |||
| /** | |||
| * 验证token | |||
| * | |||
| * @param token | |||
| * @return boolean | |||
| */ | |||
| public boolean validateToken(String token) { | |||
| String expireTime = AesUtil.decrypt(token, secretKey); | |||
| String nowTime = DateUtil.format( | |||
| new Date(), | |||
| DatePattern.PURE_DATETIME_PATTERN | |||
| ); | |||
| return expireTime.compareTo(nowTime) > 0; | |||
| } | |||
| /** | |||
| * 判断当前是否可以再次重试 | |||
| * | |||
| * @param retryTimes 第n次试图重试 | |||
| * @return boolean | |||
| */ | |||
| public boolean continueRetry(int retryTimes) { | |||
| return retryTimes <= RETRY_COUNT; | |||
| } | |||
| /** | |||
| * 获取回调地址 | |||
| * | |||
| * @param podLabel | |||
| * @return String | |||
| */ | |||
| public String getPodCallbackUrl(String podLabel) { | |||
| return url + K8S_CALLBACK_PATH_POD + podLabel; | |||
| } | |||
| /** | |||
| * 获取超时时间秒 | |||
| * | |||
| * @param timeoutSecond 超时秒数 | |||
| * @return Long | |||
| */ | |||
| public static Long getTimeoutSecondLong(int timeoutSecond) { | |||
| return Long.valueOf( | |||
| DateUtil.format( | |||
| DateUtil.offset( | |||
| new Date(), DateField.SECOND, timeoutSecond | |||
| ), | |||
| DatePattern.PURE_DATETIME_PATTERN | |||
| ) | |||
| ); | |||
| } | |||
| /** | |||
| * 获取当前秒数 | |||
| * | |||
| * @return Long | |||
| */ | |||
| public static Long getCurrentSecondLong() { | |||
| return Long.valueOf( | |||
| DateUtil.format( | |||
| new Date(), | |||
| DatePattern.PURE_DATETIME_PATTERN | |||
| ) | |||
| ); | |||
| } | |||
| } | |||
| @@ -0,0 +1,255 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.utils; | |||
| import cn.hutool.core.date.DatePattern; | |||
| import cn.hutool.core.date.DateUtil; | |||
| import cn.hutool.core.util.RandomUtil; | |||
| import org.dubhe.config.K8sNameConfig; | |||
| import org.dubhe.constant.SymbolConstant; | |||
| import org.dubhe.enums.BizEnum; | |||
| import org.dubhe.enums.BizNfsEnum; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.stereotype.Component; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import java.util.Date; | |||
| /** | |||
| * @description k8s命名相关工具类 | |||
| * @date 2020-05-13 | |||
| */ | |||
| @Component | |||
| public class K8sNameTool { | |||
| @Autowired | |||
| private K8sNameConfig k8sNameConfig; | |||
| /** | |||
| * 命名分隔符 | |||
| */ | |||
| private static final char SEPARATOR = '-'; | |||
| /** | |||
| * 文件分隔符 | |||
| */ | |||
| private static final String K8S_FILE_SEPARATOR = "/"; | |||
| /** | |||
| * 资源名称前缀 | |||
| */ | |||
| private static final String RESOURCE_NAME = "rn"; | |||
| /** | |||
| * 随机长度值 | |||
| */ | |||
| private static final int RANDOM_LENGTH = 4; | |||
| /** | |||
| * 生成 ResourceName | |||
| * | |||
| * @param bizEnum 业务枚举 | |||
| * @param resourceInfo 资源备注信息(保证同业务下唯一并且命名规范) | |||
| * @return String | |||
| */ | |||
| public String generateResourceName(BizEnum bizEnum, String resourceInfo) { | |||
| return bizEnum.getBizCode() + SEPARATOR + RESOURCE_NAME + SEPARATOR + resourceInfo; | |||
| } | |||
| /** | |||
| * 生成 Notebook的NameSpace | |||
| * | |||
| * @param userId | |||
| * @return namespace | |||
| */ | |||
| public String generateNameSpace(long userId) { | |||
| return this.k8sNameConfig.getNamespace() + SEPARATOR + userId; | |||
| } | |||
| /** | |||
| * 从resourceName中获取资源信息 | |||
| * | |||
| * @param bizEnum 业务枚举 | |||
| * @param resourceName | |||
| * @return resourceInfo | |||
| */ | |||
| public String getResourceInfoFromResourceName(BizEnum bizEnum, String resourceName) { | |||
| if (StringUtils.isEmpty(resourceName) || !resourceName.contains(bizEnum.getBizCode() + SEPARATOR)) { | |||
| return null; | |||
| } | |||
| return resourceName.replace(bizEnum.getBizCode() + SEPARATOR + RESOURCE_NAME + SEPARATOR, SymbolConstant.BLANK); | |||
| } | |||
| /** | |||
| * 从namespace 获取使用者ID | |||
| * | |||
| * @param namespace | |||
| * @return Long | |||
| */ | |||
| public Long getUserIdFromNameSpace(String namespace) { | |||
| if (StringUtils.isEmpty(namespace) || !namespace.contains(this.k8sNameConfig.getNamespace() + SEPARATOR)) { | |||
| return null; | |||
| } | |||
| return Long.valueOf(namespace.replace(this.k8sNameConfig.getNamespace() + SEPARATOR, "")); | |||
| } | |||
| /** | |||
| * 生成业务模块相对路径 | |||
| * | |||
| * @param bizNfsEnum 业务NFS路径枚举 | |||
| * @return String 例如: /{biz}/{userId}/{YYYYMMDDhhmmssSSS+四位随机数}/ | |||
| */ | |||
| public String getNfsPath(BizNfsEnum bizNfsEnum, long userId) { | |||
| if (bizNfsEnum == null) { | |||
| return null; | |||
| } | |||
| return optimizationPath(K8S_FILE_SEPARATOR | |||
| + bizNfsEnum.getBizNfsPath() | |||
| + K8S_FILE_SEPARATOR | |||
| + userId | |||
| + K8S_FILE_SEPARATOR | |||
| + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_FORMAT) + RandomUtil.randomString(RANDOM_LENGTH) | |||
| + K8S_FILE_SEPARATOR); | |||
| } | |||
| /** | |||
| * 去除NFS根路径 | |||
| * | |||
| * @param nfsPath | |||
| * @return String | |||
| */ | |||
| public String removeNfsRootPath(String nfsPath) { | |||
| if (StringUtils.isBlank(nfsPath) || !nfsPath.startsWith(k8sNameConfig.getNfsRootPath())) { | |||
| return nfsPath; | |||
| } | |||
| return optimizationPath(K8S_FILE_SEPARATOR + nfsPath.replace(k8sNameConfig.getNfsRootPath(), "")); | |||
| } | |||
| /** | |||
| * 路径添加bucket | |||
| * | |||
| * @param nfsPath | |||
| * @return String | |||
| */ | |||
| public String appendBucket(String nfsPath) { | |||
| return optimizationPath(K8S_FILE_SEPARATOR | |||
| + k8sNameConfig.getFileBucket() | |||
| + K8S_FILE_SEPARATOR | |||
| + nfsPath); | |||
| } | |||
| /** | |||
| * 路径添加时间戳随机数 | |||
| * | |||
| * @param nfsPath | |||
| * @return String | |||
| */ | |||
| public String appendTimeStampAndRandomNum(String nfsPath) { | |||
| return optimizationPath(nfsPath | |||
| + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_FORMAT) + RandomUtil.randomString(RANDOM_LENGTH) | |||
| + K8S_FILE_SEPARATOR); | |||
| } | |||
| /** | |||
| * nfs路径根据业务转换 | |||
| * | |||
| * @param nfsPath | |||
| * @param sourceBizNfsEnum 源业务 NFS Path | |||
| * @param targetBizNfsEnum 目标业务 NFS Path | |||
| * @return String | |||
| */ | |||
| public String convertNfsPath(String nfsPath, BizNfsEnum sourceBizNfsEnum, BizNfsEnum targetBizNfsEnum) { | |||
| if (!validateBizNfsPath(nfsPath, sourceBizNfsEnum) || targetBizNfsEnum == null) { | |||
| return nfsPath; | |||
| } | |||
| return optimizationPath(nfsPath.replace(K8S_FILE_SEPARATOR + sourceBizNfsEnum.getBizNfsPath() + K8S_FILE_SEPARATOR | |||
| , K8S_FILE_SEPARATOR + targetBizNfsEnum.getBizNfsPath() + K8S_FILE_SEPARATOR)); | |||
| } | |||
| /** | |||
| * 获取NFS绝对路径 | |||
| * | |||
| * @param nfsPath | |||
| * @return String | |||
| */ | |||
| public String getAbsoluteNfsPath(String nfsPath) { | |||
| if (StringUtils.isBlank(nfsPath)) { | |||
| return nfsPath; | |||
| } | |||
| return optimizationPath(k8sNameConfig.getNfsRootPath() | |||
| + K8S_FILE_SEPARATOR | |||
| + k8sNameConfig.getFileBucket() | |||
| + K8S_FILE_SEPARATOR | |||
| + nfsPath); | |||
| } | |||
| /** | |||
| * 验证 nfsPath 是否是所属业务路径 | |||
| * | |||
| * @param nfsPath | |||
| * @param bizNfsEnum | |||
| * @return boolean | |||
| */ | |||
| public boolean validateBizNfsPath(String nfsPath, BizNfsEnum bizNfsEnum) { | |||
| return org.apache.commons.lang3.StringUtils.isNotBlank(nfsPath) | |||
| && bizNfsEnum != null | |||
| && nfsPath.contains(bizNfsEnum.getBizNfsPath()) | |||
| && !nfsPath.contains(K8S_FILE_SEPARATOR + k8sNameConfig.getFileBucket() + K8S_FILE_SEPARATOR) | |||
| && !nfsPath.contains(K8S_FILE_SEPARATOR + k8sNameConfig.getNfsRootPath() + K8S_FILE_SEPARATOR); | |||
| } | |||
| /** | |||
| * 路径优化 | |||
| * | |||
| * @param path | |||
| * @return String | |||
| */ | |||
| private String optimizationPath(String path) { | |||
| if (StringUtils.isBlank(path)) { | |||
| return path; | |||
| } | |||
| return path.replaceAll("///*", K8S_FILE_SEPARATOR); | |||
| } | |||
| /** | |||
| * 获取k8s pod标签 | |||
| * | |||
| * @param bizEnum | |||
| * @return String | |||
| */ | |||
| public String getPodLabel(BizEnum bizEnum) { | |||
| return bizEnum == null ? null : bizEnum.getBizCode(); | |||
| } | |||
| /** | |||
| * 获取数据集在镜像中路径 | |||
| * | |||
| * @return String | |||
| */ | |||
| public String getDatasetPath() { | |||
| return k8sNameConfig.getDatasetPath(); | |||
| } | |||
| /** | |||
| * 自送生成K8S名称,供K8S使用 | |||
| * | |||
| * @return String | |||
| */ | |||
| public String getK8sName() { | |||
| return DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_FORMAT) | |||
| + RandomUtil.randomString(RANDOM_LENGTH); | |||
| } | |||
| } | |||
| @@ -0,0 +1,39 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.utils; | |||
| import java.text.SimpleDateFormat; | |||
| import java.util.Calendar; | |||
| /** | |||
| * @description Key生成工具类 | |||
| * @date 2020-06-08 | |||
| */ | |||
| public class KeyUtil { | |||
| /** | |||
| * 生成训练任务的key,目前规则为:train-{user_id}-{time} | |||
| * @param userId 用户id | |||
| * @return 训练任务的key | |||
| */ | |||
| public static String generateTrainKey(long userId) { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); | |||
| return "train-" + userId + '-' + dateFormat.format(calendar.getTime()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,255 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.utils; | |||
| import ch.qos.logback.classic.Level; | |||
| import com.alibaba.fastjson.JSON; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| import org.apache.commons.lang3.exception.ExceptionUtils; | |||
| import org.dubhe.aspect.LogAspect; | |||
| import org.dubhe.base.MagicNumConstant; | |||
| import org.dubhe.constant.SymbolConstant; | |||
| import org.dubhe.domain.entity.LogInfo; | |||
| import org.dubhe.enums.LogEnum; | |||
| import org.slf4j.MDC; | |||
| import org.slf4j.helpers.MessageFormatter; | |||
| import java.util.Arrays; | |||
| import java.util.UUID; | |||
| /** | |||
| * @description 日志工具类 | |||
| * @date 2020-06-29 | |||
| */ | |||
| @Slf4j | |||
| public class LogUtil { | |||
| /** | |||
| * info级别的日志 | |||
| * | |||
| * @param logType 日志类型 | |||
| * @param object 打印的日志参数 | |||
| */ | |||
| public static void info(LogEnum logType, Object... object) { | |||
| logHandle(logType, Level.INFO, object); | |||
| } | |||
| /** | |||
| * debug级别的日志 | |||
| * | |||
| * @param logType 日志类型 | |||
| * @param object 打印的日志参数 | |||
| */ | |||
| public static void debug(LogEnum logType, Object... object) { | |||
| logHandle(logType, Level.DEBUG, object); | |||
| } | |||
| /** | |||
| * error级别的日志 | |||
| * | |||
| * @param logType 日志类型 | |||
| * @param object 打印的日志参数 | |||
| */ | |||
| public static void error(LogEnum logType, Object... object) { | |||
| errorObjectHandle(object); | |||
| logHandle(logType, Level.ERROR, object); | |||
| } | |||
| /** | |||
| * warn级别的日志 | |||
| * | |||
| * @param logType 日志类型 | |||
| * @param object 打印的日志参数 | |||
| */ | |||
| public static void warn(LogEnum logType, Object... object) { | |||
| logHandle(logType, Level.WARN, object); | |||
| } | |||
| /** | |||
| * trace级别的日志 | |||
| * | |||
| * @param logType 日志类型 | |||
| * @param object 打印的日志参数 | |||
| */ | |||
| public static void trace(LogEnum logType, Object... object) { | |||
| logHandle(logType, Level.TRACE, object); | |||
| } | |||
| /** | |||
| * 日志处理 | |||
| * | |||
| * @param logType 日志类型 | |||
| * @param level 日志级别 | |||
| * @param object 打印的日志参数 | |||
| */ | |||
| private static void logHandle(LogEnum logType, Level level, Object[] object) { | |||
| LogInfo logInfo = generateLogInfo(logType, level, object); | |||
| String logInfoJsonStr = logJsonStringLengthLimit(logInfo); | |||
| switch (Level.toLevel(logInfo.getLevel()).levelInt) { | |||
| case Level.TRACE_INT: | |||
| log.trace(logInfoJsonStr); | |||
| break; | |||
| case Level.DEBUG_INT: | |||
| log.debug(logInfoJsonStr); | |||
| break; | |||
| case Level.INFO_INT: | |||
| log.info(logInfoJsonStr); | |||
| break; | |||
| case Level.WARN_INT: | |||
| log.warn(logInfoJsonStr); | |||
| break; | |||
| case Level.ERROR_INT: | |||
| log.error(logInfoJsonStr); | |||
| break; | |||
| default: | |||
| } | |||
| } | |||
| /** | |||
| * 日志信息组装的内部方法 | |||
| * | |||
| * @param logType 日志类型 | |||
| * @param level 日志级别 | |||
| * @param object 打印的日志参数 | |||
| * @return LogInfo日志对象信息 | |||
| */ | |||
| private static LogInfo generateLogInfo(LogEnum logType, Level level, Object[] object) { | |||
| LogInfo logInfo = new LogInfo(); | |||
| // 日志类型检测 | |||
| if (!LogEnum.isLogType(logType)) { | |||
| level = Level.ERROR; | |||
| object = new Object[MagicNumConstant.ONE]; | |||
| object[MagicNumConstant.ZERO] = String.valueOf("logType【").concat(String.valueOf(logType)) | |||
| .concat("】is error !"); | |||
| logType = LogEnum.SYS_ERR; | |||
| } | |||
| // 获取trace_id | |||
| if (StringUtils.isEmpty(MDC.get(LogAspect.TRACE_ID))) { | |||
| MDC.put(LogAspect.TRACE_ID, UUID.randomUUID().toString()); | |||
| } | |||
| // 设置logInfo的level,type,traceId属性 | |||
| logInfo.setLevel(level.levelStr).setType(logType.toString()).setTraceId(MDC.get(LogAspect.TRACE_ID)); | |||
| // 设置logInfo的堆栈信息 | |||
| setLogStackInfo(logInfo); | |||
| // 设置logInfo的info信息 | |||
| setLogInfo(logInfo, object); | |||
| // 截取loginfo的长度并转换成json字符串 | |||
| return logInfo; | |||
| } | |||
| /** | |||
| * 设置loginfo的堆栈信息 | |||
| * | |||
| * @param logInfo 日志对象 | |||
| */ | |||
| private static void setLogStackInfo(LogInfo logInfo) { | |||
| StackTraceElement[] elements = Thread.currentThread().getStackTrace(); | |||
| if (elements.length >= MagicNumConstant.SIX) { | |||
| logInfo.setCName(elements[MagicNumConstant.FIVE].getClassName()) | |||
| .setMName(elements[MagicNumConstant.FIVE].getMethodName()) | |||
| .setLine(String.valueOf(elements[MagicNumConstant.FIVE].getLineNumber())); | |||
| } | |||
| } | |||
| /** | |||
| * 限制log日志的长度并转换成json | |||
| * | |||
| * @param logInfo 日志对象 | |||
| * @return String 日志对象Json字符串 | |||
| */ | |||
| private static String logJsonStringLengthLimit(LogInfo logInfo) { | |||
| try { | |||
| String jsonString = JSON.toJSONString(logInfo.getInfo()); | |||
| if (jsonString.length() > MagicNumConstant.TEN_THOUSAND) { | |||
| jsonString = jsonString.substring(MagicNumConstant.ZERO, MagicNumConstant.TEN_THOUSAND); | |||
| } | |||
| logInfo.setInfo(jsonString); | |||
| jsonString = JSON.toJSONString(logInfo); | |||
| jsonString = jsonString.replace(SymbolConstant.BACKSLASH_MARK, SymbolConstant.MARK) | |||
| .replace(SymbolConstant.DOUBLE_MARK, SymbolConstant.MARK) | |||
| .replace(SymbolConstant.BRACKETS, SymbolConstant.BLANK); | |||
| return jsonString; | |||
| } catch (Exception e) { | |||
| logInfo.setLevel(Level.ERROR.levelStr).setType(LogEnum.SYS_ERR.toString()) | |||
| .setInfo("cannot serialize exception: " + ExceptionUtils.getStackTrace(e)); | |||
| return JSON.toJSONString(logInfo); | |||
| } | |||
| } | |||
| /** | |||
| * 设置日志对象的info信息 | |||
| * | |||
| * @param logInfo 日志对象 | |||
| * @param object 打印的日志参数 | |||
| */ | |||
| private static void setLogInfo(LogInfo logInfo, Object[] object) { | |||
| for (Object obj : object) { | |||
| if (obj instanceof Exception) { | |||
| log.error((ExceptionUtils.getStackTrace((Throwable) obj))); | |||
| } | |||
| } | |||
| if (object.length > MagicNumConstant.ONE) { | |||
| logInfo.setInfo(MessageFormatter.arrayFormat(object[MagicNumConstant.ZERO].toString(), | |||
| Arrays.copyOfRange(object, MagicNumConstant.ONE, object.length)).getMessage()); | |||
| } else if (object.length == MagicNumConstant.ONE && object[MagicNumConstant.ZERO] instanceof Exception) { | |||
| logInfo.setInfo((ExceptionUtils.getStackTrace((Exception) object[MagicNumConstant.ZERO]))); | |||
| } else if (object.length == MagicNumConstant.ONE) { | |||
| logInfo.setInfo( | |||
| object[MagicNumConstant.ZERO] == null ? SymbolConstant.BLANK : object[MagicNumConstant.ZERO]); | |||
| } else { | |||
| logInfo.setInfo(SymbolConstant.BLANK); | |||
| } | |||
| } | |||
| /** | |||
| * 处理Exception的情况 | |||
| * | |||
| * @param object 打印的日志参数 | |||
| */ | |||
| private static void errorObjectHandle(Object[] object) { | |||
| if (object.length >= MagicNumConstant.TWO) { | |||
| object[MagicNumConstant.ZERO] = String.valueOf(object[MagicNumConstant.ZERO]) | |||
| .concat(SymbolConstant.BRACKETS); | |||
| } | |||
| if (object.length == MagicNumConstant.TWO && object[MagicNumConstant.ONE] instanceof Exception) { | |||
| log.error((ExceptionUtils.getStackTrace((Throwable) object[MagicNumConstant.ONE]))); | |||
| object[MagicNumConstant.ONE] = ExceptionUtils.getStackTrace((Exception) object[MagicNumConstant.ONE]); | |||
| } else if (object.length >= MagicNumConstant.THREE) { | |||
| for (int i = 0; i < object.length; i++) { | |||
| if (object[i] instanceof Exception) { | |||
| log.error((ExceptionUtils.getStackTrace((Throwable) object[i]))); | |||
| object[i] = ExceptionUtils.getStackTrace((Exception) object[i]); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,49 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.utils; | |||
| import org.dubhe.base.MagicNumConstant; | |||
| /** | |||
| * @description: 计算工具类 | |||
| * @create: 2020/6/4 14:53 | |||
| */ | |||
| public class MathUtils { | |||
| /** | |||
| * 字符串整数加法 | |||
| * num1+num2 | |||
| * @param num1 | |||
| * @param num2 | |||
| * @return | |||
| */ | |||
| public static String add(String num1,String num2){ | |||
| return String.valueOf((!RegexUtil.isDigits(num1) ? MagicNumConstant.ZERO:Integer.valueOf(num1)) + (!RegexUtil.isDigits(num2)?MagicNumConstant.ZERO:Integer.valueOf(num2))); | |||
| } | |||
| /** | |||
| * 字符串整数减法 | |||
| * num1 - num2 | |||
| * @param num1 | |||
| * @param num2 | |||
| * @return | |||
| */ | |||
| public static String reduce(String num1,String num2){ | |||
| return String.valueOf((!RegexUtil.isDigits(num1) ? MagicNumConstant.ZERO:Integer.valueOf(num1)) - (!RegexUtil.isDigits(num2)?MagicNumConstant.ZERO:Integer.valueOf(num2))); | |||
| } | |||
| } | |||
| @@ -0,0 +1,286 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.utils; | |||
| import cn.hutool.core.io.IoUtil; | |||
| import cn.hutool.http.HttpRequest; | |||
| import com.alibaba.fastjson.JSONObject; | |||
| import io.minio.MinioClient; | |||
| import io.minio.PutObjectOptions; | |||
| import io.minio.Result; | |||
| import io.minio.errors.*; | |||
| import io.minio.messages.DeleteError; | |||
| import io.minio.messages.Item; | |||
| import io.swagger.annotations.ApiModel; | |||
| import io.swagger.annotations.ApiModelProperty; | |||
| import lombok.Data; | |||
| import org.apache.commons.lang.StringUtils; | |||
| import org.dubhe.base.MagicNumConstant; | |||
| import org.dubhe.enums.LogEnum; | |||
| import org.dubhe.exception.BusinessException; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.stereotype.Service; | |||
| import javax.annotation.PostConstruct; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.nio.charset.Charset; | |||
| import java.util.ArrayList; | |||
| import java.util.HashMap; | |||
| import java.util.HashSet; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| import java.util.Set; | |||
| /** | |||
| * @description Minio工具类 | |||
| * @date 2020-05-09 | |||
| */ | |||
| @Service | |||
| public class MinioUtil { | |||
| @Value("${minio.url}") | |||
| private String url; | |||
| @Value("${minio.accessKey}") | |||
| private String accessKey; | |||
| @Value("${minio.secretKey}") | |||
| private String secretKey; | |||
| private MinioClient client; | |||
| @PostConstruct | |||
| public void init() { | |||
| try { | |||
| client = new MinioClient(url, accessKey, secretKey); | |||
| } catch (InvalidEndpointException e) { | |||
| LogUtil.warn(LogEnum.BIZ_DATASET, "MinIO endpoint invalid. e:", e); | |||
| } catch (InvalidPortException e) { | |||
| LogUtil.warn(LogEnum.BIZ_DATASET, "MinIO endpoint port invalid. e:", e); | |||
| } | |||
| } | |||
| /** | |||
| * 写文件 | |||
| * | |||
| * @param bucket 桶名称 | |||
| * @param fullFilePath 文件存储的全路径,包括文件名,非'/'开头. e.g. dataset/12/annotation/test.txt | |||
| * @param content file content. can not be null | |||
| */ | |||
| public void writeString(String bucket, String fullFilePath, String content) throws Exception { | |||
| boolean isExist = client.bucketExists(bucket); | |||
| if (!isExist) { | |||
| client.makeBucket(bucket); | |||
| } | |||
| InputStream inputStream = IoUtil.toUtf8Stream(content); | |||
| PutObjectOptions options = new PutObjectOptions(inputStream.available(), MagicNumConstant.NEGATIVE_ONE); | |||
| client.putObject(bucket, fullFilePath, inputStream, options); | |||
| } | |||
| /** | |||
| * 读取文件 | |||
| * | |||
| * @param bucket | |||
| * @param fullFilePath 文件存储的全路径,包括文件名,非'/'开头. e.g. dataset/12/annotation/test.txt | |||
| * @return String | |||
| */ | |||
| public String readString(String bucket, String fullFilePath) throws Exception { | |||
| try (InputStream is = client.getObject(bucket, fullFilePath)) { | |||
| return IoUtil.read(is, Charset.defaultCharset()); | |||
| } | |||
| } | |||
| /** | |||
| * 文件删除 | |||
| * | |||
| * @param bucket | |||
| * @param fullFilePath 文件存储的全路径,包括文件名,非'/'开头. e.g. dataset/12/annotation/test.txt | |||
| */ | |||
| public void del(String bucket, String fullFilePath) throws Exception { | |||
| Iterable<Result<Item>> items = client.listObjects(bucket, fullFilePath); | |||
| Set<String> files = new HashSet<>(); | |||
| for (Result<Item> item : items) { | |||
| files.add(item.get().objectName()); | |||
| } | |||
| Iterable<Result<DeleteError>> results = client.removeObjects(bucket, files); | |||
| for (Result<DeleteError> result : results) { | |||
| result.get(); | |||
| } | |||
| } | |||
| /** | |||
| * 批量删除文件 | |||
| * | |||
| * @param bucket | |||
| * @param objectNames | |||
| */ | |||
| public void delFiles(String bucket,List<String> objectNames) throws Exception{ | |||
| Iterable<Result<DeleteError>> results = client.removeObjects(bucket, objectNames); | |||
| for (Result<DeleteError> result : results) { | |||
| result.get(); | |||
| } | |||
| } | |||
| /** | |||
| * 获取对象名称 | |||
| * | |||
| */ | |||
| public List<String> getObjects(String bucketName, String prefix)throws Exception{ | |||
| List<String> fileNames = new ArrayList<>(); | |||
| Iterable<Result<Item>> results = client.listObjects(bucketName, prefix); | |||
| for(Result<Item> result:results){ | |||
| Item item = result.get(); | |||
| fileNames.add(item.objectName()); | |||
| } | |||
| return fileNames; | |||
| } | |||
| /** | |||
| * 获取文件流 | |||
| * | |||
| */ | |||
| public InputStream getObjectInputStream(String bucket,String objectName)throws Exception{ | |||
| return client.getObject(bucket, objectName); | |||
| } | |||
| /** | |||
| * 文件夹复制 | |||
| * | |||
| * @param bucket | |||
| * @param sourceFiles 源文件 | |||
| * @param targetDir 目标文件夹 | |||
| */ | |||
| public void copyDir(String bucket, List<String> sourceFiles, String targetDir) { | |||
| sourceFiles.forEach(sourceFile -> { | |||
| InputStream inputStream = null; | |||
| try { | |||
| String sourceObjectName = sourceFile; | |||
| String targetObjectName = targetDir + "/" + StringUtils.substringAfterLast(sourceObjectName, "/"); | |||
| inputStream = client.getObject(bucket, sourceObjectName); | |||
| byte[] buf = new byte[512]; | |||
| int bytesRead; | |||
| int count = MagicNumConstant.ZERO; | |||
| while ((bytesRead = inputStream.read(buf, MagicNumConstant.ZERO, buf.length)) >= MagicNumConstant.ZERO) { | |||
| count += bytesRead; | |||
| } | |||
| PutObjectOptions options = new PutObjectOptions(count, MagicNumConstant.ZERO); | |||
| client.putObject(bucket, targetObjectName, client.getObject(bucket, sourceObjectName), options); | |||
| } catch (Exception e) { | |||
| LogUtil.error(LogEnum.BIZ_DATASET, "MinIO file copy exception, {}", e); | |||
| } finally { | |||
| try { | |||
| if (inputStream != null) { | |||
| inputStream.close(); | |||
| } | |||
| } catch (IOException e) { | |||
| LogUtil.error(LogEnum.BIZ_DATASET, "MinIO file read stream closed failed, {}", e); | |||
| } | |||
| } | |||
| }); | |||
| } | |||
| @Data | |||
| @Service | |||
| public class MinioWebTokenBody { | |||
| @Value("${minioweb.GetToken.url}") | |||
| private String tokenUrl; | |||
| @Value("${minioweb.GetToken.param.id}") | |||
| private int id; | |||
| @Value("${minioweb.GetToken.param.jsonrpc}") | |||
| private String jsonrpc; | |||
| @Value("${minioweb.GetToken.param.method}") | |||
| private String method; | |||
| @Value("${minioweb.zip.url}") | |||
| private String zipUrl; | |||
| /** | |||
| * 生成文件下载请求参数方法 | |||
| * | |||
| * @param bucketName | |||
| * @param prefix | |||
| * @param objects | |||
| * @return MinioDownloadDto | |||
| */ | |||
| public MinioDownloadDto getDownloadParam(String bucketName, String prefix, List<String> objects, String zipName) { | |||
| String paramTemplate = "{\"id\":%d,\"jsonrpc\":\"%s\",\"params\":{\"username\":\"%s\",\"password\":\"%s\"},\"method\":\"%s\"}"; | |||
| String downloadBodyTemplate = "{\"bucketName\":\"%s\",\"prefix\":\"%s\",\"objects\":[%s]}"; | |||
| String param = String.format(paramTemplate, id, jsonrpc, accessKey, secretKey, method); | |||
| String result = HttpRequest.post(url + tokenUrl).contentType("application/json").body(param).execute().body(); | |||
| String token = JSONObject.parseObject(result).getJSONObject("result").getString("token"); | |||
| return new MinioDownloadDto(token, String.format(downloadBodyTemplate, bucketName, prefix, getStrFromList(objects)), zipName); | |||
| } | |||
| public String getStrFromList(List<String> objects) { | |||
| List<String> result = new ArrayList<>(); | |||
| objects.stream().forEach(s -> { | |||
| result.add("\"" + s + "\""); | |||
| }); | |||
| return StringUtils.join(result, ","); | |||
| } | |||
| } | |||
| @ApiModel | |||
| @Data | |||
| public class MinioDownloadDto { | |||
| @ApiModelProperty("下载压缩包请求token") | |||
| private String token; | |||
| @ApiModelProperty("下载压缩包请求参数") | |||
| private String body; | |||
| @ApiModelProperty("下载压缩包请求需要的header") | |||
| private Map<String, Object> headers; | |||
| @ApiModelProperty("下载压缩包文件名称") | |||
| private String zipName; | |||
| public MinioDownloadDto() { | |||
| } | |||
| public MinioDownloadDto(String token, String body, String zipName) { | |||
| this.token = token; | |||
| this.body = body; | |||
| this.zipName = zipName; | |||
| Map<String, Object> headers = new HashMap<>(); | |||
| headers.put("Content-Type", "text/plain;charset=UTF-8"); | |||
| this.headers = headers; | |||
| } | |||
| } | |||
| /** | |||
| * 生成一个给HTTP PUT请求用的presigned URL。浏览器/移动端的客户端可以用这个URL进行上传, | |||
| * 即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天 | |||
| * | |||
| * @param bucketName 存储桶名称 | |||
| * @param objectName 存储桶里的对象名称 | |||
| * @param expires 失效时间(以秒为单位),默认是7天,不得大于七天 | |||
| * @return String | |||
| */ | |||
| public String getEncryptedPutUrl(String bucketName, String objectName, Integer expires) { | |||
| if (StringUtils.isEmpty(objectName)) { | |||
| throw new BusinessException("object name cannot be empty"); | |||
| } | |||
| try { | |||
| return client.presignedPutObject(bucketName, objectName, expires); | |||
| } catch (Exception e) { | |||
| LogUtil.error(LogEnum.BIZ_DATASET, e.getMessage()); | |||
| throw new BusinessException("MinIO an error occurred, please contact the administrator"); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,76 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.utils; | |||
| import com.emc.ecs.nfsclient.nfs.nfs3.Nfs3; | |||
| import com.emc.ecs.nfsclient.rpc.CredentialUnix; | |||
| import org.apache.commons.pool2.PooledObject; | |||
| import org.apache.commons.pool2.PooledObjectFactory; | |||
| import org.apache.commons.pool2.impl.DefaultPooledObject; | |||
| import org.dubhe.config.NfsConfig; | |||
| import org.dubhe.enums.LogEnum; | |||
| import org.springframework.stereotype.Component; | |||
| import java.io.IOException; | |||
| /** | |||
| * @description NFS工厂类 | |||
| * @date 2020-05-13 | |||
| */ | |||
| @Component | |||
| public class NfsFactory implements PooledObjectFactory<Nfs3> { | |||
| private final NfsConfig nfsConfig; | |||
| public NfsFactory(NfsConfig nfsConfig) { | |||
| this.nfsConfig = nfsConfig; | |||
| } | |||
| @Override | |||
| public PooledObject<Nfs3> makeObject() { | |||
| Nfs3 nfs3 = null; | |||
| try { | |||
| nfs3 = new Nfs3(nfsConfig.getNfsIp(), nfsConfig.getRootDir(), new CredentialUnix(0, 0, null), 3); | |||
| } catch (IOException e) { | |||
| LogUtil.error(LogEnum.NFS_UTIL, "创建NFS对象失败: ", e); | |||
| } | |||
| return new DefaultPooledObject<>(nfs3); | |||
| } | |||
| @Override | |||
| public void destroyObject(PooledObject<Nfs3> pooledObject) { | |||
| LogUtil.info(LogEnum.NFS_UTIL, "销毁NFS对象: ", pooledObject.getObject()); | |||
| } | |||
| @Override | |||
| public boolean validateObject(PooledObject<Nfs3> pooledObject) { | |||
| LogUtil.info(LogEnum.NFS_UTIL, "验证NFS对象: ", pooledObject.getObject()); | |||
| return true; | |||
| } | |||
| @Override | |||
| public void activateObject(PooledObject<Nfs3> pooledObject) { | |||
| LogUtil.info(LogEnum.NFS_UTIL, "激活NFS对象: ", pooledObject.getObject()); | |||
| } | |||
| @Override | |||
| public void passivateObject(PooledObject<Nfs3> pooledObject) { | |||
| LogUtil.info(LogEnum.NFS_UTIL, "钝化NFS对象: ", pooledObject.getObject()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,114 @@ | |||
| /** | |||
| * Copyright 2020 Zhejiang Lab. All Rights Reserved. | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * ============================================================= | |||
| */ | |||
| package org.dubhe.utils; | |||
| import com.emc.ecs.nfsclient.nfs.nfs3.Nfs3; | |||
| import org.apache.commons.pool2.impl.GenericObjectPool; | |||
| import org.apache.commons.pool2.impl.GenericObjectPoolConfig; | |||
| import org.dubhe.enums.LogEnum; | |||
| import org.springframework.stereotype.Component; | |||
| /** | |||
| * @description NFS3 连接池 | |||
| * @date 2020-05-18 | |||
| */ | |||
| @Component | |||
| public class NfsPool { | |||
| /** | |||
| * NFS工厂对象 | |||
| */ | |||
| private NfsFactory nfsFactory; | |||
| /** | |||
| * GenericObjectPool对象 | |||
| */ | |||
| private final GenericObjectPool<Nfs3> genericObjectPool; | |||
| /** | |||
| * 最大总共连接数 | |||
| */ | |||
| public static final int MAX_TOTAL = 300; | |||
| /** | |||
| * 最小连接数 | |||
| */ | |||
| public static final int MIN = 20; | |||
| /** | |||
| * 最大连接数 | |||
| */ | |||
| public static final int MAX = 300; | |||
| /** | |||
| * 最大等待时间 单位毫秒 | |||
| */ | |||
| public static final int MAX_WAIT_TIME = 3000; | |||
| /** | |||
| * 初始化连接池 | |||
| * | |||
| * @param nfsFactory | |||
| */ | |||
| public NfsPool(NfsFactory nfsFactory) { | |||
| this.nfsFactory = nfsFactory; | |||
| GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); | |||
| poolConfig.setMaxTotal(MAX_TOTAL); | |||
| poolConfig.setMinIdle(MIN); | |||
| poolConfig.setMaxIdle(MAX); | |||
| poolConfig.setMaxWaitMillis(MAX_WAIT_TIME); | |||
| this.genericObjectPool = new GenericObjectPool<>(nfsFactory, poolConfig); | |||
| } | |||
| /** | |||
| * 从连接池中取连接 | |||
| * | |||
| * @return nfs3 | |||
| */ | |||
| public Nfs3 getNfs() { | |||
| try { | |||
| LogUtil.info(LogEnum.NFS_UTIL,"NFS线程 活跃数量:{} ,空闲数量: {} , 等待队列数量 : {}",genericObjectPool.getNumActive(),genericObjectPool.getNumIdle(),genericObjectPool.getNumWaiters()); | |||
| return genericObjectPool.borrowObject(); | |||
| } catch (Exception e) { | |||
| LogUtil.error(LogEnum.NFS_UTIL, "获取NFS连接失败: {} ", e); | |||
| return null; | |||
| } | |||
| } | |||
| /** | |||
| * 释放连接到连接池 | |||
| * | |||
| * @param nfs3 | |||
| */ | |||
| public void revertNfs(Nfs3 nfs3) { | |||
| try { | |||
| if(nfs3 != null){ | |||
| LogUtil.info(LogEnum.NFS_UTIL,"成功释放对象 : {} ", nfs3); | |||
| genericObjectPool.returnObject(nfs3); | |||
| } | |||
| } catch (Exception e) { | |||
| LogUtil.error(LogEnum.NFS_UTIL, " 释放NFS连接失败: ", e); | |||
| } | |||
| } | |||
| /** | |||
| * 销毁公共池 | |||
| */ | |||
| public void destroyPool() { | |||
| try { | |||
| genericObjectPool.close(); | |||
| } catch (Exception e) { | |||
| LogUtil.error(LogEnum.NFS_UTIL, "销毁NFS连接失败: ", e); | |||
| } | |||
| } | |||
| } | |||