57 Commits

Author SHA1 Message Date
燕陇琪
e97ff288f1 添加密级字段 2025-05-30 12:50:52 +08:00
燕陇琪
683037c60d feat(流水线): github的流水线配置 2025-04-02 20:25:47 +08:00
燕陇琪
b09feb2cb5 feat(流水线): github的流水线配置 2025-04-02 20:25:28 +08:00
燕陇琪
d2d80d4988 feat(流水线): github的流水线配置 2025-04-02 20:20:58 +08:00
燕陇琪
12cdeba2eb feat(流水线): github的流水线配置 2025-04-02 20:16:02 +08:00
燕陇琪
3abfd182f9 feat(流水线): github的流水线配置 2025-04-02 20:13:55 +08:00
燕陇琪
a125e7c493 feat(流水线): github的流水线配置 2025-04-02 20:00:08 +08:00
燕陇琪
53f7ea1c92 feat(流水线): github的流水线配置 2025-04-02 19:16:30 +08:00
燕陇琪
4752f8e577 feat(流水线): github的流水线配置 2025-04-02 19:07:42 +08:00
燕陇琪
76933effe3 feat(流水线): github的流水线配置 2025-04-02 19:01:29 +08:00
燕陇琪
88333ed930 feat(流水线): github的流水线配置 2025-04-02 18:59:35 +08:00
燕陇琪
0c2e7b96ec feat(流水线): github的流水线配置 2025-04-02 18:47:24 +08:00
燕陇琪
206ea8ac5a feat(流水线): github的流水线配置 2025-04-02 18:35:52 +08:00
燕陇琪
3b2ea5f061 feat(流水线): github的流水线配置 2025-04-02 18:27:24 +08:00
燕陇琪
3343aa9ca4 feat(流水线): 添加github的流水线 2025-04-02 17:30:02 +08:00
燕陇琪
b0c104a1c9 release(发版): 发布release-2.0.5 2025-04-02 17:17:14 +08:00
燕陇琪
fcb78277fe feat(请求路径): 适配其他服务的请求路径 2025-04-02 17:10:20 +08:00
59ca7bfe4a fix(pom.xml): 插件的修改 2025-02-20 23:58:07 +08:00
lqyan
98c1bb8d9f feat(pom.xml): 升级central-publishing-maven-plugin的版本为0.7.0 2025-02-20 21:38:54 +08:00
lqyan
31b9a53799 fix(文件): 修改文件的测试类 2025-02-20 19:18:13 +08:00
lqyan
2765639cff feat(文件下载): 文件下载支持强制下载和文件流的获取 2025-02-20 19:14:21 +08:00
lqyan
85aef61455 feat(作业): 增加查询历史作业的接口 2025-02-20 18:46:59 +08:00
lqyan
9aecf0b6a2 doc(扩展方式): 解决扩展方式的文档问题 2025-02-20 18:02:44 +08:00
lqyan
4054c373b1 doc(集成方式): 增加使用方式和扩展方式的文档 2025-02-20 17:58:19 +08:00
lqyan
72f508c14f feat(sdk): 项目使用优化和代码的优化 2025-02-20 17:24:52 +08:00
lqyan
9ae5d9acd2 doc(使用说明): 增加没有网络环境和没有maven环境的使用方法说明 2025-02-19 18:40:21 +08:00
lqyan
58209849dc feat(版本发布): 推送中央maven的配置 2024-08-23 19:10:30 +08:00
lqyan
55838a455f fix(编译): 解决编译的jar不能使用的问题 2024-08-19 16:44:39 +08:00
lqyan
bfb613c15f 上传到maven仓库的配置 2024-08-19 15:59:19 +08:00
lqyan
4f2490e797 feat(扩展 优化): 优化SDK在Springboot项目中的扩展体验 2024-08-19 12:01:08 +08:00
lqyan
88d7b7b65c feat(示例): 增加SpringBoot示例以及SDK扩展逻辑的优化 2024-08-19 11:59:35 +08:00
lqyan
753a40a6d0 release(发布): release-2.0.2 2024-08-09 19:13:57 +08:00
lqyan
0c9e98247c feat(应用): 增加更加用途和文件后缀获取应用列表 2024-08-09 19:11:36 +08:00
lqyan
d134b8dc70 feat(版本发布): 2.0.1版发布 2024-08-09 10:33:38 +08:00
lqyan
3686d17f9d feat(会话连接): 支持会话连接支持获取 WEB 会话的URL 2024-08-08 19:41:56 +08:00
lqyan
75c7e02253 feat(启动应用): 支持应用启动获取 WEB 会话的URL 2024-07-26 22:19:23 +08:00
lqyan
8ed0c93867 doc(文件上传): 文件上传方法重载 2024-07-25 10:20:47 +08:00
lqyan
79a73fed6b doc(集成文档): 修改集成文档 2024-07-25 00:05:51 +08:00
lqyan
1ddd65e34e feat(数据): 测试类的适配 2024-07-24 23:19:48 +08:00
lqyan
89e858cc39 feat(数据): 数据增加额外的属性 2024-07-24 23:19:23 +08:00
lqyan
9bc5138a18 fix(作业): 添加查询仿真作业提交表单接口 2024-07-24 23:18:39 +08:00
lqyan
688617b530 fix(获取Token): 优化Token获取时间戳,支持自定义获取 2024-07-24 23:17:28 +08:00
lqyan
56b9683cf3 fix(自动配置): SpringBoot的自动配置的优化 2024-07-24 17:57:05 +08:00
lqyan
0ac882f645 fix(认证): 新增AccessKey接口安全认证的方式 2024-07-24 16:35:44 +08:00
lqyan
40df7537d1 fix(获取令牌): 解决了获取令牌之后一段时间后不能访问的问题 2024-06-06 17:28:26 +08:00
lqyan
94599f04f0 doc(readme): 修改jar包下载位置 2024-06-05 17:46:46 +08:00
lqyan
646fb869dc fix(spring使用): 解决spring使用出现空指针异常的问题 2024-06-05 16:47:01 +08:00
lqyan
1dafc6dac8 Merge branch 'master' of github.com:yanlongqi/jhinno-openapi-java-sdk 2024-06-05 15:10:35 +08:00
lqyan
193e7b4fc2 doc(readme): 优化使用说明 2024-06-05 15:03:21 +08:00
lqyan
ec7d38f9dc doc(readme): 优化使用说明 2024-06-05 14:41:57 +08:00
燕陇琪
dda983c9e8 Merge branch 'bugfix' into 'master'
Bugfix

See merge request solutions/jhinno-openapi-java-sdk!2
2024-06-05 05:04:59 +00:00
yanlongqi
cb765320ab Merge pull request #5 from yanlongqi/bugfix
Bugfix:解决json在序列化的过程中有些字段不识别而报错的问题
2024-06-05 13:02:37 +08:00
lqyan
2ab5c20fb5 feat(数据序列化): 解决json在序列化的过程中有些字段不识别而报错的问题 2024-06-05 12:59:55 +08:00
lqyan
51c068c28d feat(数据序列化): 解决json在序列化的过程中有些字段不识别而报错的问题 2024-06-05 11:58:56 +08:00
燕陇琪
f3cb13703a Merge branch 'feat-20240604-springboot-starter' into 'master'
feat(新版发布): 开发Springboot-starter方便集成方调用,修复获取token本地时间和服务器时间有差异而导致的报错问题

See merge request solutions/jhinno-openapi-java-sdk!1
2024-06-05 03:31:45 +00:00
yanlongqi
78ff3feb90 Merge pull request #3 from yanlongqi/feat-20240604-springboot-starter
feat(新版发布): 开发Springboot-starter方便集成方调用,修复获取token本地时间和服务器时间有差异而导致的报错问题
2024-06-05 10:56:05 +08:00
lqyan
1ff758a31a feat(新版发布): 开发Springboot-starter方便集成方调用,修复获取token本地时间和服务器时间有差异而导致的报错问题 2024-06-05 10:48:43 +08:00
95 changed files with 3455 additions and 1646 deletions

31
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,31 @@
name: deploy
on:
# 支持手动触发构建
workflow_dispatch:
release:
types: [released]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: 拉取源码
uses: actions/checkout@v2
- name: Set up Apache Maven Central
uses: actions/setup-java@v4
with:
java-version: 8.0.302+8
distribution: 'temurin'
cache: maven
server-id: central
server-username: MAVEN_USERNAME
server-password: MAVEN_CENTRAL_TOKEN
gpg-passphrase: MAVEN_GPG_PASSPHRASE
gpg-private-key: ${{ secrets.GPG_SECRET }}
- name: Publish to Apache Maven Central
run: mvn deploy
env:
MAVEN_USERNAME: ${{ secrets.OSSRH_USER }}
MAVEN_CENTRAL_TOKEN: ${{ secrets.OSSRH_PASSWORD }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSWORD }}

5
.gitignore vendored
View File

@@ -4,10 +4,7 @@ target/
!**/src/test/**/target/ !**/src/test/**/target/
### IntelliJ IDEA ### ### IntelliJ IDEA ###
.idea/modules.xml /.idea/
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws *.iws
*.iml *.iml
*.ipr *.ipr

8
.idea/.gitignore generated vendored
View File

@@ -1,8 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SmartInputSourceJavaSceneConfigState">
<option name="customChineseScenes" value="{&quot;capsLockState&quot;:false,&quot;code&quot;:&quot;;ArgsException(errorMessage);setUserNameCn(userNameCn)&quot;,&quot;enable&quot;:true,&quot;languageType&quot;:&quot;CHINESE&quot;,&quot;name&quot;:&quot;自定义中文切换&quot;,&quot;tip&quot;:&quot;&quot;}" />
</component>
</project>

8
.idea/encodings.xml generated
View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
<file url="PROJECT" charset="UTF-8" />
</component>
</project>

View File

@@ -1,8 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="JavadocDeclaration" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ADDITIONAL_TAGS" value="date" />
</inspection_tool>
</profile>
</component>

13
.idea/misc.xml generated
View File

@@ -1,13 +0,0 @@
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

124
.idea/uiDesigner.xml generated
View File

@@ -1,124 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

6
.idea/vcs.xml generated
View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

395
README.md
View File

@@ -1,103 +1,244 @@
# Jhinno OpenAPI SDK for Java # 1. Jhinno OpenAPI SDK for Java
针对Java的景行API SDK使Java开发人员能够轻松使用景行API接口。您可以在几分钟内开始通过Mavenjar文件使用它。 针对 Java 的景行 API SDK 使 Java 开发人员能够轻松使用景行 API 接口。您可以在几分钟内开始通过 Mavenjar 文件使用它。
- [仓库地址https://github.com/yanlongqi/jhinno-openapi-java-sdk](https://github.com/yanlongqi/jhinno-openapi-java-sdk) - [仓库地址https://github.com/yanlongqi/jhinno-openapi-java-sdk](https://github.com/yanlongqi/jhinno-openapi-java-sdk)
- [开发文档https://jhinno-sdk-doc.yuchat.top/apidocs](https://jhinno-sdk-doc.yuchat.top/apidocs) - [jar 包下载https://github.com/yanlongqi/jhinno-openapi-java-sdk/releases](https://github.com/yanlongqi/jhinno-openapi-java-sdk/releases)
- [最新jar包jhinno-openapi-java-sdk-1.0.0.jar](https://jhinno-jenkins.yuchat.top/job/jhinno-openapi-java-sdk/lastSuccessfulBuild/artifact/target/jhinno-openapi-java-sdk-1.0.0.jar)
- [最新源码包jhinno-openapi-java-sdk-1.0.0-sources.jar](https://jhinno-jenkins.yuchat.top/job/jhinno-openapi-java-sdk/lastSuccessfulBuild/artifact/target/jhinno-openapi-java-sdk-1.0.0-sources.jar)
## 必要条件 ## 1.1 必要条件
- Java 1.8 or later - Java 1.8 or later
- Maven - Maven
## 支持的Appform的版本 ## 1.2 支持的 Appform 的版本
1. JH_Appform_6.0_Release 1. JH_Appform_6.0_Release
2. JH_Appform_6.0_SP1_Release 2. JH_Appform_6.0_SP1_Release
3. JH_Appform_6.1_Release
4. JH_Appform_6.2_Release(使用: release-2.0.3
5. JH_Appform_6.3_Release(使用: release-2.0.4
5. JH_Appform_6.3_Release(使用: release-2.0.5
## 安装 # 2. 快速开始
建议在您的项目中使用Jhinno OpenAPI SDK for Java的方法是从Maven中使用它。导入方法如下 ## 2.1 SpringBoot
方法一通过Maven仓库安装 ### 2.1.1 安装
> 添加仓库地址改方案为备用方案后续会上传至Maven中央仓库目前不影响正常使用 建议在您的项目中使用 Jhinno OpenAPI SDK for Java 的方法是从 Maven 中使用它。:
```xml #### 方法一:通过命令将 jar 包导入本地 Maven 仓库
<repositories> ```shell
<repository>
<id>jhinno-nexus</id> # SDK Client的jar包的导入其中<path-to-dir>为jar的路径<path-to-dir>为jar包路径
<name>jhinno-nexus</name> mvn org.apache.maven.plugins:maven-install-plugin:3.1.1:install-file -Dfile="<path-to-dir>/jhinno-openapi-java-sdk-x.x.x.jar" -Dsources="<path-to-dir>/jhinno-openapi-java-sdk-x.x.x-sources.jar"
<url>https://jhinno-nexus.yuchat.top/repository/maven-releases</url> # 例如
</repository> mvn org.apache.maven.plugins:maven-install-plugin:3.1.1:install-file -Dfile="E:/下载/jhinno-openapi-java-sdk-2.0.0.jar" -Dsources="E:/下载/jhinno-openapi-java-sdk-2.0.0-sources.jar"
</repositories>
# SDK SpringBoot Starter的jar包的导入其中<path-to-dir>为jar的路径<path-to-dir>为jar包路径
mvn org.apache.maven.plugins:maven-install-plugin:3.1.1:install-file -Dfile="<path-to-dir>/jhinno-openapi-sdk-spring-boot-starter-x.x.x.jar" -Dsources="<path-to-dir>/jhinno-openapi-sdk-spring-boot-starter-x.x.x-sources.jar"
# 例如
mvn org.apache.maven.plugins:maven-install-plugin:3.1.1:install-file -Dfile="E:/下载/jhinno-openapi-sdk-spring-boot-starter-2.0.0.jar" -Dsources="E:/下载/jhinno-openapi-sdk-spring-boot-starter-2.0.0-sources.jar"
``` ```
添加依赖 > 注:
>
> - jhinno-openapi-java-sdk-x.x.x.jar 为 SDK 的 jar 包。
> - jhinno-openapi-java-sdk-x.x.x-sources.jar 为源码包,添加可方便查看 SDK 代码的注释。
> - jhinno-openapi-sdk-spring-boot-starter-x.x.x.jar 为 SDK 的 spring-boot-starter 的 jar 包。
> - jhinno-openapi-sdk-spring-boot-starter-x.x.x-sources.jar 为 SDK 的 spring-boot-starter 的源码包。
#### 方法二:通过源码导入
```shell
git clone https://github.com/yanlongqi/jhinno-openapi-java-sdk.git
cd jhinno-openapi-java-sdk
mvn clean install
```
### 2.1.2 引入`jhinno-openapi-sdk-spring-boot-starter`坐标
```xml ```xml
<dependency> <dependency>
<groupId>com.jhinno</groupId> <groupId>com.jhinno</groupId>
<artifactId>jhinno-openapi-java-sdk</artifactId> <artifactId>jhinno-openapi-sdk-spring-boot-starter</artifactId>
<version>1.0.0</version> <version>${最新的版本号}</version>
</dependency> </dependency>
``` ```
方法二通过命令将jar包导入本地Maven仓库 #### 方法三:直接使用 jar 包
如果开发环境没有网络,或者没有使用 maven 的构建工具,则可以使用 jar 包的方式导入。下载`dependency-jar.zip``jhinno-openapi-java-sdk-2.0.3-sources.jar``jhinno-openapi-java-sdk-2.0.3.jar`导入到你的 java 项目的 lib 里面。如果你的项目是 SpringBoot 项目,则还需要导入`jhinno-openapi-sdk-spring-boot-starter-2.0.3.jar``jhinno-openapi-sdk-spring-boot-starter-2.0.3-sources.jar
`这两个 jar 包。
### 2.1.3 配置
在 SpringBoot 的`application.properties``application.yml`里面配置
#### 2.1.3.1 application.yaml
```yaml
jhinno:
openapi:
server-url: https://172.17.0.5
access-key: xxxxx
access-key-secret: xxxx
auth-type: access_secret_mode
```
#### 2.1.3.2 application.properties
```properties
jhinno.openapi.server-url=https://{appform服务器的地址}
jhinno.openapi.access-key=xxxxx
jhinno.openapi.access-key-secret=xxxx
jhinno.openapi.auth-type=access_secret_mode
```
> 注:
>
> - 其中`jhinno.openapi.server-url`为景行接口服务的 BaseUrl
> - `auth-type` 认证类型,`token_mode`(Token 认证) 和 `access_secret_mode`AccessKey 认证Appform Release 6.2 `token_mode`
作为过渡,将会弃用;
> - `jhinno.openapi.used-server-time`是否获取服务器时间来请求 token关闭可提高获取 token 的时间,但打开有可能因为服务器时间不准确而导致 token 获取失败的问题。
> - `access-key` 和 `access-key-secret` 作为访问接口的凭证,需要提供集成商名称、系统名称、负责人姓名、负责电话电话信息申请。
> - 更多配置见`com.jhinno.sdk.openapi.autoconfigure.JHOpenapiProperties`源码。
### 2.1.4 使用
`com.jhinno.sdk.openapi.api`包下面对应`app``data``file``job``organization`这几个子包,分别代表景行`Appform`
的应用、作业数据、文件、作业操作、组织等接口资源。开发者只需要使用接口的执行器(`JHxxxApiExecution`
)即可使用资源,如:`JHFileApiExecution`
```java
public class DemoUserSDK {
/**
* 注入要调用的执行器
*/
@Autowired
private JHFileApiExecution fileApiExecution;
void contextLoads() {
// 调用执行其中想要调用的方法
List<FileInfo> list = fileApiExecution.getFileList("jhadmin", "$HOME");
System.out.println(list);
}
}
```
## 2.2 Spring
### 2.2.1 安装
建议在您的项目中使用 Jhinno OpenAPI SDK for Java 的方法是从 Maven 中使用它。:
#### 方法一:通过命令将 jar 包导入本地 Maven 仓库(无网络开发额外配置)
```shell ```shell
# 其中<path-to-dir>为jar的路径<path-to-dir>为jar包路径
# SDK Client的jar包的导入其中<path-to-dir>为jar的路径<path-to-dir>为jar包路径
mvn org.apache.maven.plugins:maven-install-plugin:3.1.1:install-file -Dfile="<path-to-dir>/jhinno-openapi-java-sdk-1.0.0.jar" -Dsources="<path-to-dir>/jhinno-openapi-java-sdk-1.0.0-sources.jar" mvn org.apache.maven.plugins:maven-install-plugin:3.1.1:install-file -Dfile="<path-to-dir>/jhinno-openapi-java-sdk-1.0.0.jar" -Dsources="<path-to-dir>/jhinno-openapi-java-sdk-1.0.0-sources.jar"
# 例如 # 例如
mvn org.apache.maven.plugins:maven-install-plugin:3.1.1:install-file -Dfile="E:/下载/jhinno-openapi-java-sdk-1.0.0.jar" -Dsources="E:/下载/jhinno-openapi-java-sdk-1.0.0-sources.jar" mvn org.apache.maven.plugins:maven-install-plugin:3.1.1:install-file -Dfile="E:/下载/jhinno-openapi-java-sdk-1.0.0.jar" -Dsources="E:/下载/jhinno-openapi-java-sdk-1.0.0-sources.jar"
``` ```
> 注: > 注:
> - jhinno-openapi-java-sdk-x.x.x.jar 为SDK的jar包。 >
> - jhinno-openapi-java-sdk-x.x.x-sources.jar 为源码包添加可方便查看SDK代码的注释 > - jhinno-openapi-java-sdk-x.x.x.jar 为 SDK 的 jar 包
> - jhinno-openapi-java-sdk-x.x.x-sources.jar 为源码包,添加可方便查看 SDK 代码的注释。
然后在`pom.xml`添加 #### 方法二:通过源码导入(无网络开发额外配置)
```shell
git clone https://github.com/yanlongqi/jhinno-openapi-java-sdk.git
cd jhinno-openapi-java-sdk
mvn clean install
```
### 2.2.2 引入`jhinno-openapi-java-sdk`坐标
```xml ```xml
<dependency> <dependency>
<groupId>com.jhinno</groupId> <groupId>com.jhinno</groupId>
<artifactId>jhinno-openapi-java-sdk</artifactId> <artifactId>jhinno-openapi-java-sdk</artifactId>
<version>1.0.0</version> <version>${最新的版本号}</version>
</dependency> </dependency>
``` ```
方法三:直接在`pom.xml`引用jar(改方法可能会出现一些莫名其妙的问题,所以不建议使用) ### 2.2.3 配置
spring.xml 添加以下内容
```xml ```xml
<!-- 其中{path-to-file}为jar的位置 --> <?xml version="1.0" encoding="utf-8"?>
<beans>
<bean id="apiClient" class="com.jhinno.sdk.openapi.client.JHApiClient" init-method="initDefaultApiClient">
<constructor-arg value="https://172.17.0.5"/>
</bean>
<bean id="requestExecution" class="com.jhinno.sdk.openapi.api.JHRequestExecution">
<constructor-arg ref="apiClient" />
</bean>
<bean id="appApiExecution" class="com.jhinno.sdk.openapi.api.app.JHAppApiExecution" init-method="init"></bean>
<bean id="dataApiExecution" class="com.jhinno.sdk.openapi.api.data.JHDataApiExecution" init-method="init"></bean>
<bean id="fileApiExecution" class="com.jhinno.sdk.openapi.api.file.JHFileApiExecution" init-method="init"></bean>
<bean id="jhJobApiExecution" class="com.jhinno.sdk.openapi.api.job.JHJobApiExecution" init-method="init"></bean>
<bean id="departmentApiExecution" class="com.jhinno.sdk.openapi.api.organization.JHDepartmentApiExecution" init-method="init"></bean>
<bean id="userApiExecution" class="com.jhinno.sdk.openapi.api.organization.JHUserApiExecution" init-method="init"></bean>
</beans>
```
### 2.2.4 使用
`com.jhinno.sdk.openapi.api`包下面对应`app``data``file``job``organization`这几个子包,分别代表景行`Appform`
的应用、作业数据、文件、作业操作、组织等接口资源。开发者只需要使用接口的执行器(`JHxxxApiExecution`
)即可使用资源,如:`JHAppApiExecution`
```java
public class DemoUserSDK {
/**
* 注入要调用的执行器
*/
@Autowired
private JHFileApiExecution fileApiExecution;
void contextLoads() {
// 调用执行其中想要调用的方法
List<FileInfo> list = fileApiExecution.getFileList("jhadmin", "$HOME");
System.out.println(list);
}
}
```
## 2.3 普通 java 项目
### 2.3.1 安装
- 同 2.2.1 安装一样
### 2.3.2 引入`jhinno-openapi-java-sdk`坐标
```xml
<dependency> <dependency>
<groupId>com.jhinno</groupId> <groupId>com.jhinno</groupId>
<artifactId>jhinno-openapi-java-sdk</artifactId> <artifactId>jhinno-openapi-java-sdk</artifactId>
<version>1.0.0</version> <version>${最新的版本号}</version>
<scope>system</scope>
<systemPath>{path-to-file}</systemPath>
</dependency> </dependency>
``` ```
例如 ### 2.3.3 使用
```xml
<!-- 其中{path-to-file}为jar的位置 -->
<dependency>
<groupId>com.jhinno</groupId>
<artifactId>jhinno-openapi-java-sdk</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>D:/jar/jhinno-openapi-java-sdk-1.0.0.jar</systemPath>
</dependency>
```
## 使用
`com.jhinno.sdk.openapi.api`包下面对应`app``data``file``job``organization`这几个子包,分别代表景行`Appform` `com.jhinno.sdk.openapi.api`包下面对应`app``data``file``job``organization`这几个子包,分别代表景行`Appform`
的应用、作业数据、文件、作业操作、组织等接口资源。开发者只需要使用接口的执行器(`JHxxxApiExecution` 的应用、作业数据、文件、作业操作、组织等接口资源。开发者只需要使用接口的执行器(`JHxxxApiExecution`
@@ -105,90 +246,182 @@ mvn org.apache.maven.plugins:maven-install-plugin:3.1.1:install-file -Dfile="E:/
具体的使用步骤如下: 具体的使用步骤如下:
1. 创建一个`JHApiClient`客户端此为HTTP连接池为确保资源浪费需保证全局唯一每次创建执行器都使用个客户端。 1. 创建一个`JHApiClient`客户端,此为 HTTP 连接池,为确保资源浪费,需保证全局唯一,每次创建执行器都使用个客户端。
2. 创建接口的执行器,即:`JHxxxApiExecution`,如:`JHAppApiExecution` 2. 创建接口的执行器,即:`JHxxxApiExecution`,如:`JHAppApiExecution`
3. 调用接口执行器的方法,使用景行接口资源,如下代码片段。 3. 调用接口执行器的方法,使用景行接口资源,如下代码片段。
```java ```java
public class DemoUserSDK { public class JHApiUtile {
/** /**
* JHApiClient 是一个HTTP连接池开发者需要复用 * 创建一个API执行器管理器
* 其中https://192.168.87.25/appform为景行API服务的地址
* 注意: JHApiClient为内置的http连接池系统只需要初始化一份即可单例调用
*/ */
private static final JHApiClient client = JHApiClient.build("https://192.168.87.25/appform"); public static final JHApiExecutionManage API_EXECUTION_MANAGE = new JHApiExecutionManage("https://192.168.87.24");
public static final String ACCESS_KEY = "3f03747f147942bd8debd81b6c9c6a80";
public static final String ACCESS_KEY_SECRET = "e0681859b91c499eb1d2c8e09cea3242";
static {
// 配置API执行器管理器设置认证信息等。
API_EXECUTRON_MANAGE.configureApiExecution(t -> {
// 默认为使用Token模式如何使用的Token模式则不需要配置ACCESS_KEY和ACCESS_KEY SECRET
// t.setAuthType(AuthType.ACCESS_KEY);
t.setAccessKey(ACCESS_KEY);
t.setAccessKeySecret(ACCESS_KEY_SECRET);
});
}
public static void main(String[] args) { public static void main(String[] args) {
// 初始化一个调用调用景行会话服务接口执行器 // 从API执行器管理器取出调用应用相关接口执行器
JHAppApiExecution jhAppApiExecution = new JHAppApiExecution(client); JHAppApiExecution jhAppApiExecution = JHClientConfig.API_EXECUTION_MANAGE.getApiExecution(JHAppApiExecution.class);
// 调用启动会话的接口 // 调用启动会话的接口
AppStartedInfo appStartedInfo = jhAppApiExecution.desktopStart("jhadmin", "linux_desktop", new AppStartRequest()); jhAppApiExecution.desktopStart("jhadmin", "linux_desktop");
// 打印接口的调用结果
System.out.println(appStartedInfo);
} }
} }
``` ```
## 支持SDK的扩展 # 3. 支持 SDK 的扩展
如果是基于景行定制的接口本SDK没有包含这些方法因此您可以基于`JHApiExecution`快速进行扩展,具体的扩展步骤如下: 如果是基于景行定制的接口,本 SDK 没有包含这些方法,因此您可以基于`JHApiExecution`快速进行扩展,具体的扩展步骤如下:
- 新建需要扩展的执行器命名为`JHxxxApiExecution`,并继承`JHApiExecution` - 新建需要扩展的执行器命名为`JHxxxApiExecution`,并继承`JHApiExecution`
- 编写基于接口调用的方法; - 编写基于接口调用的方法;
父类提供了封装好的`get``post``put``delete`方法可以直接使用而不考虑token的问题 父类提供了封装好的`get``post``put``delete`方法,可以直接使用,而不考虑 token 的问题
## 3.1 SpringBoot 项目
### 3.1.1 方式一
通过实现`JHApiExecution`接口,实现自定义的`JHDemoApiExecution`,并注册到 Spring 容器中。
```java ```java
/** /**
* 注意一下代码为伪代码需要根据实际的情况进行修改其示例代码可参照SDK中JHApiExecution子类的实现 * 注意一下代码为伪代码需要根据实际的情况进行修改其示例代码可参照SDK中JHDemoApiExecution子类的实现
*/ */
public class JHAppApiExecution extends JHApiExecution { @Component
public class JHDemoApiExecution extends JHApiExecution {
/** private JHRequestExecution execution;
* 获取一个执行器的实例
* @Override
* @param jhApiClient 请求的客户端 public void init(JHRequestExecution execution) {
*/ this.execution = execution;
public JHAppApiExecution(JHApiClient jhApiClient) {
super(jhApiClient);
} }
public XxxDTO getXXXX(String username, String demoParams) { public XxxDTO getXXXX(String username, String demoParams) {
return get("/demo/path", username, new TypeReference<ResponseResult<XxxDTO>>() { return execution.get("/demo/path", username, new TypeReference<ResponseResult<XxxDTO>>() {
}); });
} }
} }
``` ```
## 构建 ### 3.1.2 方式二
一旦您检出代码就可以使用Maven构建它。使用以下命令进行构建 通过注入 `JHRequestExecution` 的方式来注入
```java
/**
* 注意一下代码为伪代码需要根据实际的情况进行修改其示例代码可参照SDK中JHDemoApiExecution子类的实现
*/
public class JHDemoApiExecution extends JHApiExecution {
@Autowired
private JHRequestExecution execution;
public XxxDTO getXXXX(String username, String demoParams) {
// ResponseResult<XxxDTO> 可以参照接口文档定义自己的数据传输对象
return execution.get("/demo/path", username, new TypeReference<ResponseResult<XxxDTO>>() {
});
}
}
```shell
mvn clean package -DskipTests -P product
``` ```
## 代码贡献 # 3.2 非 SpringBoot 项目
- 代码必须格式化使用IDEA自带的格式即可 ```java
- 请求路径必须放在一个单独的const类中统一维护具体可参考现有代码提交 /**
* 注意一下代码为伪代码需要根据实际的情况进行修改其示例代码可参照SDK中JHDemoApiExecution子类的实现
*/
public class JHDemoApiExecution extends JHApiExecution {
private JHRequestExecution execution;
@Override
public void init(JHRequestExecution execution) {
this.execution = execution;
}
public XxxDTO getXXXX(String username, String demoParams) {
return execution.get("/demo/path", username, new TypeReference<ResponseResult<XxxDTO>>() {
});
}
}
public class JHApiUtile {
public static final JHApiExecutionManage API_EXECUTION_MANAGE = new JHApiExecutionManage("https://192.168.87.24");
public static final String ACCESS_KEY = "3f03747f147942bd8debd81b6c9c6a80";
public static final String ACCESS_KEY_SECRET = "e0681859b91c499eb1d2c8e09cea3242";
static {
// 配置API执行器管理器设置认证信息等。
API_EXECUTRON_MANAGE.configureApiExecution(t -> {
// 默认为使用Token模式如何使用的Token模式则不需要配置ACCESS_KEY和ACCESS_KEY SECRET
// t.setAuthType(AuthType.ACCESS_KEY);
t.setAccessKey(ACCESS_KEY);
t.setAccessKeySecret(ACCESS_KEY_SECRET);
});
// 注册自定义的API执行器会自动配置你自定义的执行器
API_EXECUTRON_MANAGE.registerApiExecution(new JHDemoApiExecution());
}
public static void main(String[] args) {
// 从API执行器管理器取出调用应用相关接口的执行器
JHDemoApiExecution jhAppApiExecution = JHClientConfig.API_EXECUTION_MANAGE.getApiExecution(JHDemoApiExecution.class);
// 调用启动会话的接口
jhAppApiExecution.getXXXX("jhadmin", "xxxx");
}
}
```
# 4. 构建
一旦您检出代码,就可以使用 Maven 构建它。使用以下命令进行构建:
```shell
mvn clean package
```
# 5. 代码贡献
- 代码必须格式化,使用 IDEA 自带的格式即可;
- 请求路径必须放在一个单独的 const 类中统一维护,具体可参考现有代码提交;
- 封装新的接口是需要继承`JHApiExecution`,调用父类的辅助方法辅助封装; - 封装新的接口是需要继承`JHApiExecution`,调用父类的辅助方法辅助封装;
## 作者 # 6. 作者
- [yanlongqi](https://github.com/yanlongqi) - [yanlongqi](https://github.com/yanlongqi)
## 支持 # 7. 支持
- 电话同微信18794888087 - 电话同微信18794888087
- 邮箱lqyan@jhinno.com - 邮箱lqyan@jhinno.com

View File

@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>jhinno-openapi-java-sdk</artifactId>
<version>2.0.5</version>
<packaging>jar</packaging>
<name>Jhinno OpenAPI SDK for Java</name>
<description>The Jhinno OpenAPI SDK for Java used for accessing Jhinno OpenApi Service</description>
<url>http://jhinno.com</url>
<parent>
<groupId>com.jhinno</groupId>
<artifactId>jhinno-openapi-java-sdk-parent</artifactId>
<version>2.0.5</version>
</parent>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
<exclusions>
<exclusion>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,20 @@
package com.jhinno.sdk.openapi;
/**
* 目前Appform的认证类型有两个Token模式和AK/SK的模式。
* 使用AK/SK的模式需要应用门户安装API接口安全插件并且需要配置AK/SK信息。
* 推荐使用AK/SK的模式Token模式后续将被弃用
*/
public enum AuthType {
/**
* Token模式不推荐使用后续将被弃用
*/
TOKEN_MODE,
/**
* AK/SK模式推荐使用但需要服务端安装接口安全插件
*/
ACCESS_SECRET_MODE,
}

View File

@@ -1,7 +1,5 @@
package com.jhinno.sdk.openapi; package com.jhinno.sdk.openapi;
import org.omg.CosNaming.NamingContextPackage.NotFound;
/** /**
* 客户端错误相关常亮的定义 * 客户端错误相关常亮的定义
* *

View File

@@ -0,0 +1,102 @@
package com.jhinno.sdk.openapi;
import com.fasterxml.jackson.databind.util.StdDateFormat;
import java.text.DateFormat;
/**
* @author yanlongqi
* @date 2024/1/31 10:17
*/
public class CommonConstant {
/**
* 请求成功时的标识
*/
public static final String SUCCESS = "success";
/**
* 请求失败时的标识
*/
public static final String FAILED = "failed";
/**
* AES获取Token格式
*/
public static final String TokenUserFormat = "%s,%s";
/**
* 获取token时AES加密的默认key
*/
public static final String DEFAULT_AES_KEY = "jin5no@aqec8gtw6";
/**
* 字符逗号
*/
public static final String NORMAL_CHARACTER_COMMA = ",";
/**
* 签名key
*/
public static final String SIGNATURE = "signature";
/**
* 集成方Key
*/
public static final String ACCESS_KEY = "accessKey";
/**
* 用户名
*/
public static final String USERNAME = "username";
/**
* 时间戳
*/
public static final String CURRENT_TIME_MILLIS = "currentTimeMillis";
/**
* TOKEN
*/
public static final String TOKEN = "token";
/**
* 签名加密格式
* <ul>
* <li> accessKey </li>
* <li> username </li>
* <li> currentTimeMillis </li>
* </ul>
*/
public static final String SIGNATURE_FORMAT = "#%s#%s#%s#";
/**
* HmacSHA256 算法
*/
public static final String HMAC_SHA_256_ALGORITHM = "HmacSHA256";
/**
* AES 算法
*/
public static final String AES_ALGORITHM = "AES";
/**
* AES ECB Padding
*/
public static final String AES_ECB_PADDING = "AES/ECB/PKCS5Padding";
/**
* 标准日期时间格式精确到秒yyyy-MM-dd HH:mm:ss
*/
public static final String NORM_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
/**
* 时间转换
*/
public static final DateFormat HTTP_DATETIME_FORMAT = new StdDateFormat();
}

View File

@@ -0,0 +1,12 @@
package com.jhinno.sdk.openapi;
import com.jhinno.sdk.openapi.api.JHRequestExecution;
public interface JHApiExecution {
/**
* 初始化API执行器
*/
void init(JHRequestExecution execution);
}

View File

@@ -0,0 +1,105 @@
package com.jhinno.sdk.openapi;
import java.util.HashMap;
import java.util.Map;
import com.jhinno.sdk.openapi.api.JHRequestExecution;
import com.jhinno.sdk.openapi.api.app.JHAppApiExecution;
import com.jhinno.sdk.openapi.api.data.JHDataApiExecution;
import com.jhinno.sdk.openapi.api.file.JHFileApiExecution;
import com.jhinno.sdk.openapi.api.job.JHJobApiExecution;
import com.jhinno.sdk.openapi.api.organization.JHDepartmentApiExecution;
import com.jhinno.sdk.openapi.api.organization.JHUserApiExecution;
import com.jhinno.sdk.openapi.client.JHApiClient;
import com.jhinno.sdk.openapi.client.JHApiHttpClient;
public class JHApiExecutionManage {
public static final Map<Class<? extends JHApiExecution>, JHApiExecution> API_CLIENT_MAP = new HashMap<>();
public final JHRequestExecution EXECUTION;
/**
* 创建一个带有默认HTTP客户端的API执行管理器
*
* @param appformBaseUrl 景行API的URL
*/
public JHApiExecutionManage(String appformBaseUrl) {
JHApiClient client = new JHApiClient(appformBaseUrl);
client.initDefaultApiClient();
EXECUTION = new JHRequestExecution(client);
initApiExecution();
}
/**
* 创建一个带有自定义HTTP客户端的API执行管理器
*
* @param httpClient 自定义HTTP客户端
* @param appformBaseUrl 景行API的URL
*/
public JHApiExecutionManage(JHApiHttpClient httpClient, String appformBaseUrl) {
JHApiClient client = new JHApiClient(appformBaseUrl);
client.setApiHttpClient(httpClient);
EXECUTION = new JHRequestExecution(client);
EXECUTION.setAuthType(AuthType.TOKEN_MODE);
initApiExecution();
}
/**
* 初始化默认的执行器
*/
private void initApiExecution() {
API_CLIENT_MAP.put(JHAppApiExecution.class, new JHAppApiExecution());
API_CLIENT_MAP.put(JHDataApiExecution.class, new JHDataApiExecution());
API_CLIENT_MAP.put(JHFileApiExecution.class, new JHFileApiExecution());
API_CLIENT_MAP.put(JHJobApiExecution.class, new JHJobApiExecution());
API_CLIENT_MAP.put(JHDepartmentApiExecution.class, new JHDepartmentApiExecution());
API_CLIENT_MAP.put(JHUserApiExecution.class, new JHUserApiExecution());
API_CLIENT_MAP.forEach((key, value) -> {
value.init(EXECUTION);
});
}
/**
* 配置API执行器
*
* @param configurator API执行器配置器
*/
public void configureApiExecution(ApiExecutionConfigurator configurator) {
configurator.configure(EXECUTION);
}
/**
* 注册自定义的执行器
*
* @param execution 自定义的执行器实例
*/
public void registerApiExecution(JHApiExecution execution) {
execution.init(EXECUTION);
API_CLIENT_MAP.put(execution.getClass(), execution);
}
/**
* 获取一个特定的执行器用于调用接口
*
* @param <T> 执行器的类型
* @param clazz 执行器的类
* @return 执行器实例
*/
public <T extends JHApiExecution> T getApiExecution(Class<? extends T> clazz) {
return (T) API_CLIENT_MAP.get(clazz);
}
/**
* API执行器配置器接口用于配置API执行器的参数
*/
public static interface ApiExecutionConfigurator {
/**
* 配置API执行器的参数
*
* @param execution API执行器实例
*/
void configure(JHRequestExecution execution);
}
}

View File

@@ -1,17 +1,23 @@
package com.jhinno.sdk.openapi.api; package com.jhinno.sdk.openapi.api;
import cn.hutool.crypto.symmetric.AES;
import cn.hutool.http.ContentType;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.jhinno.sdk.openapi.ArgsException; import com.jhinno.sdk.openapi.*;
import com.jhinno.sdk.openapi.CommonConstant;
import com.jhinno.sdk.openapi.ServiceException;
import com.jhinno.sdk.openapi.api.app.JHAppApiExecution; import com.jhinno.sdk.openapi.api.app.JHAppApiExecution;
import com.jhinno.sdk.openapi.api.auth.AuthPathConstant; import com.jhinno.sdk.openapi.api.auth.AuthPathConstant;
import com.jhinno.sdk.openapi.client.DefaultHttpClientConfig;
import com.jhinno.sdk.openapi.client.JHApiClient; import com.jhinno.sdk.openapi.client.JHApiClient;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import com.jhinno.sdk.openapi.api.app.AppPathConstant; import com.jhinno.sdk.openapi.api.app.AppPathConstant;
import org.apache.http.entity.ContentType;
import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@@ -25,38 +31,65 @@ import java.util.concurrent.ConcurrentHashMap;
* 对于定制接口可参考以下步骤封装调用方法 * 对于定制接口可参考以下步骤封装调用方法
* <ol> * <ol>
* <li>定义一个const类同来存放接口的路径方便后期的维护{@link AppPathConstant}</li> * <li>定义一个const类同来存放接口的路径方便后期的维护{@link AppPathConstant}</li>
* <li>继承{@link JHApiExecution}{@link JHAppApiExecution}</li> * <li>继承{@link JHRequestExecution}{@link JHAppApiExecution}</li>
* <li>参考{@link JHAppApiExecution}中封装的方法调用{@link JHApiExecution}中的getpostputdelete等对新的接口封装</li> * <li>参考{@link JHAppApiExecution}中封装的方法调用{@link JHRequestExecution}中的getpostputdelete等对新的接口封装</li>
* </ol> * </ol>
* *
* @author yanlongqi * @author yanlongqi
* @date 2024/1/30 19:39 * @date 2024/1/30 19:39
* @see JHAppApiExecution * @see JHAppApiExecution
*/ */
public class JHApiExecution { @Data
@NoArgsConstructor
public class JHRequestExecution {
/** /**
* JHApiClient实例 * JHApiClient实例
*/ */
public JHApiClient jhApiClient; private JHApiClient jhApiClient;
/** /**
* token的超时时间 * token的超时时间
*/ */
private int tokenTimeout = CommonConstant.DEFAULT_TOKEN_EFFECTIVE_TIME; private int tokenTimeout = DefaultHttpClientConfig.DEFAULT_TOKEN_EFFECTIVE_TIME;
/** /**
* token提前获取的时间 * token提前获取的时间
*/ */
private int tokenResidueTime = CommonConstant.DEFAULT_TOKEN_RESIDUE_TIME; private int tokenResidueTime = DefaultHttpClientConfig.DEFAULT_TOKEN_RESIDUE_TIME;
/**
* 是否使用服务器时间开启可能会导致请求过慢但是不会太慢默认token会有缓存
*/
private boolean isUsedServerTime = DefaultHttpClientConfig.DEFAULT_IS_USED_SERVER_TIME;
/**
* 是否强制获取用户的token默认{@link DefaultHttpClientConfig#DEFAULT_IS_FORCE_GET_TOKEN},
* 如果强制获取token则每次请求都去获取token
*/
private boolean isForceGetToken = DefaultHttpClientConfig.DEFAULT_IS_FORCE_GET_TOKEN;
/**
* 接口请求的认证类型
*/
private AuthType authType = AuthType.TOKEN_MODE;
/**
* 访问密钥
*/
private String accessKey;
/**
* 访问密钥密码
*/
private String accessKeySecret;
/** /**
* 获取一个执行器的实例 * 获取一个执行器的实例
* *
* @param jhApiClient 请求的客户端 * @param jhApiClient 请求的客户端
*/ */
protected JHApiExecution(JHApiClient jhApiClient) { public JHRequestExecution(JHApiClient jhApiClient) {
this.jhApiClient = jhApiClient; this.jhApiClient = jhApiClient;
} }
@@ -66,41 +99,21 @@ public class JHApiExecution {
private static final Map<String, TokenInfo> TOKEN_INFO_MAP = new ConcurrentHashMap<>(20); private static final Map<String, TokenInfo> TOKEN_INFO_MAP = new ConcurrentHashMap<>(20);
/** /**
* 设置在JHApiClient实例的实例 * 设置是否使用服务器时间
* *
* @param jhApiClient 客户端实例 * @param usedServerTime 是否使用服务器时间
*/ */
public void setJHApiClient(JHApiClient jhApiClient) { public void setUsedServerTime(boolean usedServerTime) {
this.jhApiClient = jhApiClient; isUsedServerTime = usedServerTime;
}
/**
* 设置token超时的时间单位分钟
*
* @param tokenTimeout token的超时时间
*/
public void setTokenTimeout(int tokenTimeout) {
this.tokenTimeout = tokenTimeout;
}
/**
* 设置提前获取token的时间单位分钟
*
* @param tokenResidueTime 提前获取token的时间
*/
public void setTokenResidueTime(int tokenResidueTime) {
this.tokenResidueTime = tokenResidueTime;
} }
/** /**
* 获取用户的Token * 获取用户的Token
* *
* @param username 用户名 * @param username 用户名
* @param isForce 是否强制获取toke
* @return 用户的token * @return 用户的token
*/ */
public String getToken(String username, boolean isForce) { public String getToken(String username) {
if (StringUtils.isBlank(username)) { if (StringUtils.isBlank(username)) {
throw new ArgsException("用户名称不能为空!"); throw new ArgsException("用户名称不能为空!");
} }
@@ -108,14 +121,25 @@ public class JHApiExecution {
// 防止因为服务器时间的问题二导致token不可用可以通过此配置提前获取token // 防止因为服务器时间的问题二导致token不可用可以通过此配置提前获取token
int tokenEffectiveTime = (tokenTimeout - tokenResidueTime) * 60 * 1000; int tokenEffectiveTime = (tokenTimeout - tokenResidueTime) * 60 * 1000;
// 如果是强制获取用户令牌为空用户令牌过期等则获取令牌 // 如果是强制获取用户令牌为空用户令牌过期等则获取令牌
if (isForce || tokenInfo == null || System.currentTimeMillis() - tokenInfo.getCurrentTimestamp() < tokenEffectiveTime) { if (isForceGetToken || tokenInfo == null
|| System.currentTimeMillis() - tokenInfo.getCurrentTimestamp() > tokenEffectiveTime) {
Map<String, Object> params = new HashMap<>(2); Map<String, Object> params = new HashMap<>(2);
params.put("timeout", tokenTimeout); params.put("timeout", tokenTimeout);
String currentTimeMillis = getCurrentTimeMillis();
String beforeEncryption = String.format(CommonConstant.TokenUserFormat, username, currentTimeMillis);
try {
SecretKeySpec secretKey = new SecretKeySpec(
CommonConstant.DEFAULT_AES_KEY.getBytes(StandardCharsets.UTF_8), CommonConstant.AES_ALGORITHM);
Cipher cipher = Cipher.getInstance(CommonConstant.AES_ECB_PADDING);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encryptBytes = cipher.doFinal(beforeEncryption.getBytes(StandardCharsets.UTF_8));
params.put("username", Base64.getEncoder().encodeToString(encryptBytes));
} catch (Exception e) {
throw new ClientException("AES加密失败失败原因" + e.getMessage(), e);
}
AES aes = new AES(CommonConstant.DEFAULT_AES_KEY.getBytes());
String base64 = aes.encryptBase64(String.format("%s,%s", username, System.currentTimeMillis()));
params.put("username", base64);
String url = JHApiClient.getUrl(AuthPathConstant.AUTH_TOKEN_PATH, params); String url = JHApiClient.getUrl(AuthPathConstant.AUTH_TOKEN_PATH, params);
Map<String, String> token = get(url, new TypeReference<ResponseResult<Map<String, String>>>() { Map<String, String> token = get(url, new TypeReference<ResponseResult<Map<String, String>>>() {
}); });
@@ -129,34 +153,71 @@ public class JHApiExecution {
} }
/** /**
* 获取用户的Token获取缓存不强制获取 * @return
*
* @param username 用户名
* @return 用户的token
*/ */
public String getToken(String username) { public String getCurrentTimeMillis() {
return getToken(username, false); if (authType == AuthType.ACCESS_SECRET_MODE || !isUsedServerTime) {
return String.valueOf(System.currentTimeMillis());
}
return jhApiClient.getAppformServerCurrentTimeMillis();
} }
/** /**
* 构建一个带token的请求头 * 构建一个带token的请求头
* *
* @param username 用户名 * @param username 用户名
* @param isContentType 是否携带默认的Content-type默认为{@link ContentType#JSON} * @param isContentType 是否携带默认的Content-type默认为{@link ContentType#APPLICATION_JSON}
* @return 请求头 * @return 请求头
*/ */
protected Map<String, String> getHeaders(String username, boolean isContentType) { public Map<String, Object> getHeaders(String username, boolean isContentType) {
Map<String, String> headers = new HashMap<>(); Map<String, Object> headers = new HashMap<>();
// 默认请求json数据 // 默认请求json数据
if (isContentType) { if (isContentType) {
headers.put("Content-type", ContentType.JSON.getValue()); headers.put("Content-type", ContentType.APPLICATION_JSON.getMimeType());
} }
if (authType == AuthType.ACCESS_SECRET_MODE) {
if (StringUtils.isBlank(accessKey)) {
throw new ClientException("AccessKey不能为空");
}
if (StringUtils.isBlank(accessKeySecret)) {
throw new ClientException("AccessKeySecret不能为空");
}
headers.put(CommonConstant.ACCESS_KEY, accessKey);
if (StringUtils.isBlank(username)) { if (StringUtils.isBlank(username)) {
username = StringUtils.EMPTY;
}
headers.put(CommonConstant.USERNAME, username);
String currentTimeMillis = getCurrentTimeMillis();
headers.put(CommonConstant.CURRENT_TIME_MILLIS, currentTimeMillis);
headers.put(CommonConstant.SIGNATURE, getsSignature(username, currentTimeMillis));
} else if (authType == AuthType.TOKEN_MODE && StringUtils.isNotBlank(username)) {
headers.put(CommonConstant.TOKEN, getToken(username));
}
return headers; return headers;
} }
headers.put("token", getToken(username));
return headers; /**
* 获取签名
*
* @param username 用户名
* @param currentTimeMillis 时间戳
* @return 签名
*/
public String getsSignature(String username, String currentTimeMillis) {
SecretKeySpec secretKey = new SecretKeySpec(accessKeySecret.getBytes(StandardCharsets.UTF_8),
CommonConstant.HMAC_SHA_256_ALGORITHM);
try {
Mac mac = Mac.getInstance(CommonConstant.HMAC_SHA_256_ALGORITHM);
mac.init(secretKey);
String beforeSignature = String.format(CommonConstant.SIGNATURE_FORMAT, accessKey, username,
currentTimeMillis);
byte[] digest = mac.doFinal(beforeSignature.getBytes(StandardCharsets.UTF_8));
return Hex.encodeHexString(digest);
} catch (Exception e) {
throw new ClientException("签名加密失败,失败信息:" + e.getMessage(), e);
}
} }
/** /**
@@ -165,7 +226,7 @@ public class JHApiExecution {
* @param username 用户名 * @param username 用户名
* @return 请求头 * @return 请求头
*/ */
protected Map<String, String> getHeaders(String username) { public Map<String, Object> getHeaders(String username) {
return getHeaders(username, true); return getHeaders(username, true);
} }
@@ -198,7 +259,6 @@ public class JHApiExecution {
return result.getData(); return result.getData();
} }
/** /**
* 发起一个有返回值的POST请求 * 发起一个有返回值的POST请求
* *
@@ -218,7 +278,6 @@ public class JHApiExecution {
return result.getData(); return result.getData();
} }
/** /**
* 发起一个有返回值的POST请求 * 发起一个有返回值的POST请求
* *
@@ -232,7 +291,6 @@ public class JHApiExecution {
return post(path, username, null, type); return post(path, username, null, type);
} }
/** /**
* 发起一个没有返回值的POST请求 * 发起一个没有返回值的POST请求
* *
@@ -242,14 +300,14 @@ public class JHApiExecution {
* @param <B> 请求体数据类型 * @param <B> 请求体数据类型
*/ */
public <B> void post(String path, String username, B body) { public <B> void post(String path, String username, B body) {
ResponseResult<?> result = jhApiClient.post(path, body, getHeaders(username), new TypeReference<ResponseResult<?>>() { ResponseResult<?> result = jhApiClient.post(path, body, getHeaders(username),
new TypeReference<ResponseResult<?>>() {
}); });
if (StringUtils.equals(result.getResult(), CommonConstant.FAILED)) { if (StringUtils.equals(result.getResult(), CommonConstant.FAILED)) {
throw new ServiceException(path, result.getCode(), result.getMessage()); throw new ServiceException(path, result.getCode(), result.getMessage());
} }
} }
/** /**
* 发起一个没有请求体没有数据返回的POST请求 * 发起一个没有请求体没有数据返回的POST请求
* *
@@ -261,7 +319,6 @@ public class JHApiExecution {
}); });
} }
/** /**
* 发起一个有返回值的PUT请求 * 发起一个有返回值的PUT请求
* *
@@ -281,7 +338,6 @@ public class JHApiExecution {
return result.getData(); return result.getData();
} }
/** /**
* 发起一个有返回值的PUT请求 * 发起一个有返回值的PUT请求
* *
@@ -304,14 +360,14 @@ public class JHApiExecution {
* @param <B> 请求体数据类型 * @param <B> 请求体数据类型
*/ */
public <B> void put(String path, String username, B body) { public <B> void put(String path, String username, B body) {
ResponseResult<?> result = jhApiClient.put(path, body, getHeaders(username), new TypeReference<ResponseResult<?>>() { ResponseResult<?> result = jhApiClient.put(path, body, getHeaders(username),
new TypeReference<ResponseResult<?>>() {
}); });
if (StringUtils.equals(result.getResult(), CommonConstant.FAILED)) { if (StringUtils.equals(result.getResult(), CommonConstant.FAILED)) {
throw new ServiceException(path, result.getCode(), result.getMessage()); throw new ServiceException(path, result.getCode(), result.getMessage());
} }
} }
/** /**
* 发起一个没有请求体没有数据返回的PUT请求 * 发起一个没有请求体没有数据返回的PUT请求
* *
@@ -323,7 +379,6 @@ public class JHApiExecution {
}); });
} }
/** /**
* 发起一个DELETE请求有数据返回 * 发起一个DELETE请求有数据返回
* *
@@ -341,7 +396,6 @@ public class JHApiExecution {
return result.getData(); return result.getData();
} }
/** /**
* 发起一个DELETE请求没有数据返回 * 发起一个DELETE请求没有数据返回
* *
@@ -349,16 +403,16 @@ public class JHApiExecution {
* @param username 用户名 * @param username 用户名
*/ */
public void delete(String path, String username) { public void delete(String path, String username) {
ResponseResult<?> result = jhApiClient.delete(path, getHeaders(username), new TypeReference<ResponseResult<?>>() { ResponseResult<?> result = jhApiClient.delete(path, getHeaders(username),
new TypeReference<ResponseResult<?>>() {
}); });
if (StringUtils.equals(result.getResult(), CommonConstant.FAILED)) { if (StringUtils.equals(result.getResult(), CommonConstant.FAILED)) {
throw new ServiceException(path, result.getCode(), result.getMessage()); throw new ServiceException(path, result.getCode(), result.getMessage());
} }
} }
/** /**
* 退出用户的登录释放许可 * 退出用户的登录释放许可当用户退出登录后建议清除用户的token信息
* *
* @param username 用户名 * @param username 用户名
*/ */

View File

@@ -0,0 +1,116 @@
package com.jhinno.sdk.openapi.api.app;
/**
* 关于会话请求路径的path
*
* @author yanlongqi
* @date 2024/2/1 16:27
*/
public class AppPathConstant {
/**
* 申请会话
*/
public static final String APPS_START_PATH = "/appform/ws/api/apps/{appId}/start";
/**
* 查询会列表
*/
public static final String APPS_SESSIONS_ALL_PATH = "/appform/ws/api/apps/sessions/all";
/**
* 使用参数查询会话列表
*/
public static final String APPS_SESSIONS_PATH = "/appform/ws/api/apps/sessions";
/**
* 根据会话id列表查询会话列表
*/
public static final String APPS_SESSIONS_IDS_PATH = "/appform/ws/api/apps/listBySessionIds";
/**
* 根据会话名称查询会话列表
*/
public static final String APPS_SESSIONS_NAME_PATH = "/appform/ws/api/apps/listBySessionName";
/**
* 会话共享
*/
public static final String APPS_SESSIONS_SHARE_PATH = "/appform/ws/api/apps/sessions/{sessionId}/share";
/**
* 取消会话共享
*/
public static final String APPS_SESSIONS_CANCEL_SHARE_PATH = "/appform/ws/api/apps/sessions/{sessionId}/share_cancel";
/**
* 传递会话的操作权
*/
public static final String APPS_SESSIONS_OPERATION_TRANSFER_PATH = "/appform/ws/api/apps/sessions/{sessionId}/operation_transfer";
/**
* 连接会话
*/
public static final String APPS_SESSIONS_CONNECT_JHAPP_PATH = "/appform/ws/api/apps/sessions/{sessionId}/connect";
/**
* 断开会话连接(作业/应用)
*/
public static final String APPS_SESSIONS_DISCONNECT_PATH = "/appform/ws/api/apps/sessions/{sessionId}/disconnect";
/**
* 批量断开会话
*/
public static final String APPS_SESSIONS_DISCONNECT_IDS_PATH = "/appform/ws/api/apps/sessions/disconnect";
/**
* 注销会话
*/
public static final String APPS_SESSIONS_DESTROY_PATH = "/appform/ws/api/apps/sessions/{sessionId}/close";
/**
* 批量注销会话
*/
public static final String APPS_SESSIONS_DESTROY_IDS_PATH = "/appform/ws/api/apps/sessions/close";
/**
* 查询应用列表
*/
public static final String APPS_LIST_PATH = "/appform/ws/api/apps";
/**
* 获取应用链接URL
*/
public static final String APPS_GET_URL_PATH = "/appform/ws/api/apps/{appName}/url";
/**
* WEB启动会话URL
*/
public static final String WEB_SESSION_URL_PATH = "/pageapi/apps/webclient/gui/{desktopId}";
/**
* 根据用途查询应用
* <p/>
* 该接口目前在Solutions下面维护未经过产品的测试
*/
public static final String APP_USE_LABEL_PATH = "/appform/ws/api/app/use_label/apps";
/**
* 根据文件后缀查询应用
* <p/>
* 该接口目前在Solutions下面维护未经过产品的测试
*/
public static final String APPS_SUFFIXES_PATH = "/appform/ws/api/apps/suffixes";
}

View File

@@ -34,4 +34,9 @@ public class AppStartedInfo {
* 作业id有可能出现但不是太明白 * 作业id有可能出现但不是太明白
*/ */
private String jobId; private String jobId;
/**
* WEB 启动会话URL
*/
private String webSessionUrl;
} }

View File

@@ -0,0 +1,121 @@
package com.jhinno.sdk.openapi.api.app;
import lombok.Data;
/**
* 应用
*/
@Data
public class AppstoreAppInfo {
/**
* 应ID
*/
private String id;
/**
* 应用名称
*/
private String name;
/**
* 应用图标
*/
private String image;
/**
* 应用类型
*/
private String type;
/**
* 应用版本
*/
private String version;
/**
* 应用状态
*/
private Boolean status;
/**
* 是否 使用
*/
private Boolean isUsed;
/**
* CPU使用
*/
private String cpuUsage;
/**
* 空闲内存
*/
private String idleMem;
/**
*
*/
private String idleTime;
/**
* 应用路径
*/
private String appPath;
/**
* 工作路径
*/
private String appCwd;
/**
* 发布时间
*/
private String appReleaseTime;
/**
* 启动选项
*/
private String appStartOpt;
/**
* 启动前缀
*/
private String appStartPrefix;
/**
* 启动后缀
*/
private String appStartSuffix;
/**
* 应用详情
*/
private String appDetail;
/**
* 启动数量
*/
private String startNum;
/**
* 用途英文名
*/
private String useLabelEnStr;
/**
* 用途中文名
*/
private String useLabelCnStr;
/**
* 应用系统
*/
private String appOs;
/**
* 申请状态
*/
private String applyStatus;
}

View File

@@ -1,15 +1,18 @@
package com.jhinno.sdk.openapi.api.app; package com.jhinno.sdk.openapi.api.app;
import cn.hutool.core.collection.CollectionUtil;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.jhinno.sdk.openapi.ArgsException; import com.jhinno.sdk.openapi.ArgsException;
import com.jhinno.sdk.openapi.AuthType;
import com.jhinno.sdk.openapi.CommonConstant; import com.jhinno.sdk.openapi.CommonConstant;
import com.jhinno.sdk.openapi.JHApiExecution;
import com.jhinno.sdk.openapi.ServiceException; import com.jhinno.sdk.openapi.ServiceException;
import com.jhinno.sdk.openapi.api.JHApiExecution; import com.jhinno.sdk.openapi.api.JHRequestExecution;
import com.jhinno.sdk.openapi.api.ResponseResult; import com.jhinno.sdk.openapi.api.ResponseResult;
import com.jhinno.sdk.openapi.client.JHApiClient; import com.jhinno.sdk.openapi.client.JHApiClient;
import com.jhinno.sdk.openapi.utils.CollectionUtil;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -20,21 +23,20 @@ import java.util.Map;
* @author yanlongqi * @author yanlongqi
* @date 2024/2/1 16:26 * @date 2024/2/1 16:26
*/ */
public class JHAppApiExecution extends JHApiExecution { public class JHAppApiExecution implements JHApiExecution {
/** private JHRequestExecution execution;
* 获取一个执行器的实例
* public void init(JHRequestExecution execution) {
* @param jhApiClient 请求的客户端 this.execution = execution;
*/
public JHAppApiExecution(JHApiClient jhApiClient) {
super(jhApiClient);
} }
/** /**
* 启动一个会话 * 启动一个会话
*
* <h4>通过JHClient启动</h4>
* <p> * <p>
* 方法返回一个重要的参数{@link AppStartedInfo#getJhappUrl()}拉起景行客户端协议的URL * 方法返回一个重要的参数{@link AppStartedInfo#getJhappUrl()}拉起景行客户端协议的URL
* <p> * <p>
* 测试将该URL复制粘贴到浏览器的地址栏进行访问即可启动会话 * 测试将该URL复制粘贴到浏览器的地址栏进行访问即可启动会话
* *
@@ -46,12 +48,14 @@ public class JHAppApiExecution extends JHApiExecution {
* <li>使用HTML的iframe标签的src</li> * <li>使用HTML的iframe标签的src</li>
* </ul> * </ul>
* 以下是使用的伪代码 * 以下是使用的伪代码
*
* <pre class="code"> * <pre class="code">
* // 使用a标签实例代码 * // 使用a标签实例代码
* var a = document.createElement("a"); * var a = document.createElement("a");
* a.href = "{@link AppStartedInfo#getJhappUrl()}"; * a.href = "{@link AppStartedInfo#getJhappUrl()}";
* a.click(); * a.click();
* </pre> * </pre>
*
* <pre class="code"> * <pre class="code">
* // 使用iframe标签实例代码 * // 使用iframe标签实例代码
* var iframe = document.createElement("iframe"); * var iframe = document.createElement("iframe");
@@ -59,6 +63,17 @@ public class JHAppApiExecution extends JHApiExecution {
* iframe.src = "{@link AppStartedInfo#getJhappUrl()}"; * iframe.src = "{@link AppStartedInfo#getJhappUrl()}";
* </pre> * </pre>
* *
* <p>
* 注意如果使用JHAppClient启动应用的并且没有做浏览器端和服务器没有做时间同步
* 那么 {@link AppStartRequest#setCurrentTimestamp(String)} 参数必传
* 并使用js生产的时间具体的参数见 {@link AppStartRequest#setCurrentTimestamp(String)}
*
* <h4>通过浏览器启动</h4>
*
* <pre class="code">
* window.open("{@link AppStartedInfo#getWebSessionUrl()}}")
* </pre>
*
* @param username 用户名 * @param username 用户名
* @param appId 应用拆 * @param appId 应用拆
* @param appStartRequest 启动参数 * @param appStartRequest 启动参数
@@ -66,12 +81,32 @@ public class JHAppApiExecution extends JHApiExecution {
*/ */
public AppStartedInfo desktopStart(String username, String appId, AppStartRequest appStartRequest) { public AppStartedInfo desktopStart(String username, String appId, AppStartRequest appStartRequest) {
String path = AppPathConstant.APPS_START_PATH.replace("{appId}", appId); String path = AppPathConstant.APPS_START_PATH.replace("{appId}", appId);
List<AppStartedInfo> data = post(path, username, appStartRequest, new TypeReference<ResponseResult<List<AppStartedInfo>>>() { List<AppStartedInfo> data = execution.post(path, username, appStartRequest,
new TypeReference<ResponseResult<List<AppStartedInfo>>>() {
}); });
if (CollectionUtil.isEmpty(data)) { if (CollectionUtil.isEmpty(data)) {
throw new ServiceException(path, 500, "获取到的会话信息为空"); throw new ServiceException(path, 500, "获取到的会话信息为空");
} }
return data.get(0); AppStartedInfo appStartedInfo = data.get(0);
appStartedInfo.setWebSessionUrl(getWebSessionUrl(username, appStartedInfo.getDesktopId()));
return appStartedInfo;
}
public String getWebSessionUrl(String username, String desktopId) {
String webSessionUrlPath = AppPathConstant.WEB_SESSION_URL_PATH.replace("{desktopId}", desktopId);
String url = execution.getJhApiClient().getUrl(webSessionUrlPath);
Map<String, Object> params = new HashMap<>();
AuthType authType = execution.getAuthType();
if (authType == AuthType.TOKEN_MODE) {
params.put(CommonConstant.TOKEN, execution.getToken(username));
} else if (authType == AuthType.ACCESS_SECRET_MODE) {
params.put(CommonConstant.USERNAME, username);
params.put(CommonConstant.ACCESS_KEY, execution.getAccessKey());
String currentTimeMillis = execution.getCurrentTimeMillis();
params.put(CommonConstant.CURRENT_TIME_MILLIS, currentTimeMillis);
params.put(CommonConstant.SIGNATURE, execution.getsSignature(username, currentTimeMillis));
}
return JHApiClient.getUrl(url, params);
} }
/** /**
@@ -96,11 +131,11 @@ public class JHAppApiExecution extends JHApiExecution {
* @return 会话列表 * @return 会话列表
*/ */
public List<SessionInfo> getDesktopList(String username) { public List<SessionInfo> getDesktopList(String username) {
return get(AppPathConstant.APPS_SESSIONS_ALL_PATH, username, new TypeReference<ResponseResult<List<SessionInfo>>>() { return execution.get(AppPathConstant.APPS_SESSIONS_ALL_PATH, username,
new TypeReference<ResponseResult<List<SessionInfo>>>() {
}); });
} }
/** /**
* 使用参数查询会话列表 * 使用参数查询会话列表
* <ul> * <ul>
@@ -122,11 +157,10 @@ public class JHAppApiExecution extends JHApiExecution {
params.put("sessionName", sessionName); params.put("sessionName", sessionName);
} }
String path = JHApiClient.getUrl(AppPathConstant.APPS_SESSIONS_PATH, params); String path = JHApiClient.getUrl(AppPathConstant.APPS_SESSIONS_PATH, params);
return get(path, username, new TypeReference<ResponseResult<List<SessionInfo>>>() { return execution.get(path, username, new TypeReference<ResponseResult<List<SessionInfo>>>() {
}); });
} }
/** /**
* 根据会话列表查询会话列表 * 根据会话列表查询会话列表
* <p> * <p>
@@ -144,7 +178,7 @@ public class JHAppApiExecution extends JHApiExecution {
} }
params.put("sessionIds", String.join(CommonConstant.NORMAL_CHARACTER_COMMA, ids)); params.put("sessionIds", String.join(CommonConstant.NORMAL_CHARACTER_COMMA, ids));
String path = JHApiClient.getUrl(AppPathConstant.APPS_SESSIONS_IDS_PATH, params); String path = JHApiClient.getUrl(AppPathConstant.APPS_SESSIONS_IDS_PATH, params);
return get(path, username, new TypeReference<ResponseResult<List<SessionInfo>>>() { return execution.get(path, username, new TypeReference<ResponseResult<List<SessionInfo>>>() {
}); });
} }
@@ -166,7 +200,7 @@ public class JHAppApiExecution extends JHApiExecution {
} }
params.put("sessionName", sessionName); params.put("sessionName", sessionName);
String path = JHApiClient.getUrl(AppPathConstant.APPS_SESSIONS_NAME_PATH, params); String path = JHApiClient.getUrl(AppPathConstant.APPS_SESSIONS_NAME_PATH, params);
return get(path, username, new TypeReference<ResponseResult<List<SessionInfo>>>() { return execution.get(path, username, new TypeReference<ResponseResult<List<SessionInfo>>>() {
}); });
} }
@@ -184,7 +218,8 @@ public class JHAppApiExecution extends JHApiExecution {
* @param interacts 协作者列表 非必填 * @param interacts 协作者列表 非必填
* @param isTransfer 是否传递操作权不确定需要咨询产品非必填 * @param isTransfer 是否传递操作权不确定需要咨询产品非必填
*/ */
public void shareDesktop(String username, String sessionId, List<String> observers, List<String> interacts, String isTransfer) { public void shareDesktop(String username, String sessionId, List<String> observers, List<String> interacts,
String isTransfer) {
if (StringUtils.isBlank(sessionId)) { if (StringUtils.isBlank(sessionId)) {
throw new ArgsException("sessionId为必填字段"); throw new ArgsException("sessionId为必填字段");
} }
@@ -198,11 +233,11 @@ public class JHAppApiExecution extends JHApiExecution {
if (StringUtils.isBlank(isTransfer)) { if (StringUtils.isBlank(isTransfer)) {
params.put("isTransfer", isTransfer); params.put("isTransfer", isTransfer);
} }
String path = JHApiClient.getUrl(AppPathConstant.APPS_SESSIONS_SHARE_PATH.replace("{sessionId}", sessionId), params); String path = JHApiClient.getUrl(AppPathConstant.APPS_SESSIONS_SHARE_PATH.replace("{sessionId}", sessionId),
post(path, username); params);
execution.post(path, username);
} }
/** /**
* 取消会话共享 * 取消会话共享
* <ul> * <ul>
@@ -218,7 +253,7 @@ public class JHAppApiExecution extends JHApiExecution {
throw new ArgsException("sessionId为必填字段"); throw new ArgsException("sessionId为必填字段");
} }
String path = AppPathConstant.APPS_SESSIONS_CANCEL_SHARE_PATH.replace("{sessionId}", sessionId); String path = AppPathConstant.APPS_SESSIONS_CANCEL_SHARE_PATH.replace("{sessionId}", sessionId);
put(path, username); execution.put(path, username);
} }
/** /**
@@ -243,10 +278,9 @@ public class JHAppApiExecution extends JHApiExecution {
Map<String, Object> params = new HashMap<>(1); Map<String, Object> params = new HashMap<>(1);
params.put("interact", interact); params.put("interact", interact);
path = JHApiClient.getUrl(path, params); path = JHApiClient.getUrl(path, params);
put(path, username); execution.put(path, username);
} }
/** /**
* 连接会话 * 连接会话
* *
@@ -259,14 +293,17 @@ public class JHAppApiExecution extends JHApiExecution {
throw new ArgsException("sessionId为必填字段"); throw new ArgsException("sessionId为必填字段");
} }
String path = AppPathConstant.APPS_SESSIONS_CONNECT_JHAPP_PATH.replace("{sessionId}", sessionId); String path = AppPathConstant.APPS_SESSIONS_CONNECT_JHAPP_PATH.replace("{sessionId}", sessionId);
List<AppStartedInfo> list = get(path, username, new TypeReference<ResponseResult<List<AppStartedInfo>>>() { List<AppStartedInfo> list = execution.get(path, username,
new TypeReference<ResponseResult<List<AppStartedInfo>>>() {
}); });
if (CollectionUtil.isEmpty(list)) { if (CollectionUtil.isEmpty(list)) {
throw new ServiceException(path, 500, "获取到的会话信息为空"); throw new ServiceException(path, 500, "获取到的会话信息为空");
} }
return list.get(0);
}
AppStartedInfo appStartedInfo = list.get(0);
appStartedInfo.setWebSessionUrl(getWebSessionUrl(username, sessionId));
return appStartedInfo;
}
/** /**
* 断开会话连接作业/应用 * 断开会话连接作业/应用
@@ -282,10 +319,9 @@ public class JHAppApiExecution extends JHApiExecution {
throw new ArgsException("sessionId为必填字段"); throw new ArgsException("sessionId为必填字段");
} }
String path = AppPathConstant.APPS_SESSIONS_DISCONNECT_PATH.replace("{sessionId}", sessionId); String path = AppPathConstant.APPS_SESSIONS_DISCONNECT_PATH.replace("{sessionId}", sessionId);
put(path, username); execution.put(path, username);
} }
/** /**
* 通过应用id批量断开会话作业/应用 * 通过应用id批量断开会话作业/应用
* <p> * <p>
@@ -302,10 +338,9 @@ public class JHAppApiExecution extends JHApiExecution {
Map<String, Object> params = new HashMap<>(1); Map<String, Object> params = new HashMap<>(1);
params.put("sessionIds", String.join(CommonConstant.NORMAL_CHARACTER_COMMA, sessionIds)); params.put("sessionIds", String.join(CommonConstant.NORMAL_CHARACTER_COMMA, sessionIds));
String path = JHApiClient.getUrl(AppPathConstant.APPS_SESSIONS_DISCONNECT_IDS_PATH, params); String path = JHApiClient.getUrl(AppPathConstant.APPS_SESSIONS_DISCONNECT_IDS_PATH, params);
put(path, username); execution.put(path, username);
} }
/** /**
* 注销会话 * 注销会话
* <p> * <p>
@@ -320,10 +355,9 @@ public class JHAppApiExecution extends JHApiExecution {
throw new ArgsException("sessionId为必填字段"); throw new ArgsException("sessionId为必填字段");
} }
String path = AppPathConstant.APPS_SESSIONS_DESTROY_PATH.replace("{sessionId}", sessionId); String path = AppPathConstant.APPS_SESSIONS_DESTROY_PATH.replace("{sessionId}", sessionId);
put(path, username); execution.put(path, username);
} }
/** /**
* 批量注销会话 * 批量注销会话
* *
@@ -337,10 +371,9 @@ public class JHAppApiExecution extends JHApiExecution {
Map<String, Object> params = new HashMap<>(1); Map<String, Object> params = new HashMap<>(1);
params.put("sessionIds", String.join(CommonConstant.NORMAL_CHARACTER_COMMA, sessionIds)); params.put("sessionIds", String.join(CommonConstant.NORMAL_CHARACTER_COMMA, sessionIds));
String path = JHApiClient.getUrl(AppPathConstant.APPS_SESSIONS_DESTROY_IDS_PATH, params); String path = JHApiClient.getUrl(AppPathConstant.APPS_SESSIONS_DESTROY_IDS_PATH, params);
put(path, username); execution.put(path, username);
} }
/** /**
* 获取当前用户的应用列表 * 获取当前用户的应用列表
* *
@@ -348,15 +381,15 @@ public class JHAppApiExecution extends JHApiExecution {
* @return 应用列表 * @return 应用列表
*/ */
public List<AppInfo> getAppList(String username) { public List<AppInfo> getAppList(String username) {
return get(AppPathConstant.APPS_LIST_PATH, username, new TypeReference<ResponseResult<List<AppInfo>>>() { return execution.get(AppPathConstant.APPS_LIST_PATH, username,
new TypeReference<ResponseResult<List<AppInfo>>>() {
}); });
} }
/** /**
* 获取应用链接 * 获取应用链接
* *
* @param username 户名 * @param username 户名
* @param appName 应用名 * @param appName 应用名
* @return 应用链接地址 * @return 应用链接地址
*/ */
@@ -365,11 +398,68 @@ public class JHAppApiExecution extends JHApiExecution {
throw new ArgsException("appName为必填字段"); throw new ArgsException("appName为必填字段");
} }
String path = AppPathConstant.APPS_GET_URL_PATH.replace("{appName}", appName); String path = AppPathConstant.APPS_GET_URL_PATH.replace("{appName}", appName);
List<Map<String, String>> apps = get(path, username, new TypeReference<ResponseResult<List<Map<String, String>>>>() { List<Map<String, String>> apps = execution.get(path, username,
new TypeReference<ResponseResult<List<Map<String, String>>>>() {
}); });
if (CollectionUtil.isEmpty(apps)) { if (CollectionUtil.isEmpty(apps)) {
throw new ServiceException(path, 500, "应用信息为空!"); throw new ServiceException(path, 500, "应用信息为空!");
} }
return apps.get(0).get("url"); return apps.get(0).get("url");
} }
/**
* 根据文件后缀查询应用
*
* @param username 用户名
* @param suffixes 文件后缀列表
* @return 应用列表
*/
public List<AppstoreAppInfo> getAppInfoSuffixList(String username, String... suffixes) {
return getAppInfoSuffixList(username, Arrays.asList(suffixes));
}
/**
* 根据文件后缀查询应用
*
* @param username 用户名
* @param suffixes 文件后缀列表
* @return 应用列表
*/
public List<AppstoreAppInfo> getAppInfoSuffixList(String username, List<String> suffixes) {
Map<String, Object> params = new HashMap<>(1);
if (CollectionUtil.isNotEmpty(suffixes)) {
params.put("suffixes", String.join(CommonConstant.NORMAL_CHARACTER_COMMA, suffixes));
}
String path = JHApiClient.getUrl(AppPathConstant.APPS_SUFFIXES_PATH, params);
return execution.get(path, username, new TypeReference<ResponseResult<List<AppstoreAppInfo>>>() {
});
}
/**
* 根据用途查询应用
*
* @param username 用户名
* @param labels 用途列表
* @return 应用列表
*/
public List<UseLabelInfo> getUseLabelList(String username, String... labels) {
return getUseLabelList(username, Arrays.asList(labels));
}
/**
* 根据用途查询应用
*
* @param username 用户名
* @param labels 用途列表
* @return 应用列表
*/
public List<UseLabelInfo> getUseLabelList(String username, List<String> labels) {
Map<String, Object> params = new HashMap<>(1);
if (CollectionUtil.isNotEmpty(labels)) {
params.put("use_labels", String.join(CommonConstant.NORMAL_CHARACTER_COMMA, labels));
}
String path = JHApiClient.getUrl(AppPathConstant.APP_USE_LABEL_PATH, params);
return execution.get(path, username, new TypeReference<ResponseResult<List<UseLabelInfo>>>() {
});
}
} }

View File

@@ -0,0 +1,28 @@
package com.jhinno.sdk.openapi.api.app;
import lombok.Data;
import java.util.List;
@Data
public class UseLabelInfo {
/**
* 用途id
*/
private String useLabelId;
/**
* 用途名称
*/
private String useLabelName;
/**
* 用途图片
*/
private String useLabelIcon;
/**
* 用途app列表
*/
private List<AppstoreAppInfo> apps;
}

View File

@@ -0,0 +1,32 @@
package com.jhinno.sdk.openapi.api.auth;
/**
* 鉴权相关接口路径
*
* @author yanlongqi
* @date 2024/1/29 10:32
*/
public class AuthPathConstant {
/**
* 获取用户token
*/
public static final String AUTH_TOKEN_PATH = "/appform/ws/api/auth/token";
/**
* 注销token
*/
public static final String AUTH_LOGOUT = "/appform/ws/api/auth/logout";
/**
* 用户注册
*/
public static final String AUTH_REGISTER = "/appform/ws/api/auth/register";
/**
* 测试服务器是否可用
*/
public static final String PING = "/appform/ws/api/ping";
}

View File

@@ -11,32 +11,32 @@ public class DataPathConstant {
/** /**
* 根据用户scope查询数据目录列表 * 根据用户scope查询数据目录列表
*/ */
public static final String DATA_SPOOLERS_PATH = "/ws/api/spoolers"; public static final String DATA_SPOOLERS_PATH = "/appform/ws/api/spoolers";
/** /**
* 根据作业id查数据目录信息 * 根据作业id查数据目录信息
*/ */
public static final String DATA_SPOOLER_JOB_ID_PATH = "/ws/api/spooler/{jobId}"; public static final String DATA_SPOOLER_JOB_ID_PATH = "/appform/ws/api/spooler/{jobId}";
/** /**
* 根据作业id集合查询数据目录列表 * 根据作业id集合查询数据目录列表
*/ */
public static final String DATA_SPOOLERS_LIST_PATH = "/ws/api/spoolers/list"; public static final String DATA_SPOOLERS_LIST_PATH = "/appform/ws/api/spoolers/list";
/** /**
* 根据数据目录名称查询数据目录列表 * 根据数据目录名称查询数据目录列表
*/ */
public static final String DATA_SPOOLERS_NAME_PATH = "/ws/api/spoolers/name"; public static final String DATA_SPOOLERS_NAME_PATH = "/appform/ws/api/spoolers/name";
/** /**
* 立即删除数据目录 * 立即删除数据目录
*/ */
public static final String DATA_SPOOLERS_DELETE_ID_PATH = "/ws/api/spooler/del/{id}"; public static final String DATA_SPOOLERS_DELETE_ID_PATH = "/appform/ws/api/spooler/del/{id}";
/** /**
* 设置过期时间删除数据目录 * 设置过期时间删除数据目录
*/ */
public static final String DATA_SPOOLERS_PURGE_PATH = "/ws/api/spooler/purge"; public static final String DATA_SPOOLERS_PURGE_PATH = "/appform/ws/api/spooler/purge";
} }

View File

@@ -1,13 +1,15 @@
package com.jhinno.sdk.openapi.api.data; package com.jhinno.sdk.openapi.api.data;
import cn.hutool.core.collection.CollectionUtil;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.jhinno.sdk.openapi.ArgsException; import com.jhinno.sdk.openapi.ArgsException;
import com.jhinno.sdk.openapi.CommonConstant; import com.jhinno.sdk.openapi.CommonConstant;
import com.jhinno.sdk.openapi.JHApiExecution;
import com.jhinno.sdk.openapi.ServiceException; import com.jhinno.sdk.openapi.ServiceException;
import com.jhinno.sdk.openapi.api.JHApiExecution; import com.jhinno.sdk.openapi.api.JHRequestExecution;
import com.jhinno.sdk.openapi.api.ResponseResult; import com.jhinno.sdk.openapi.api.ResponseResult;
import com.jhinno.sdk.openapi.client.JHApiClient; import com.jhinno.sdk.openapi.client.JHApiClient;
import com.jhinno.sdk.openapi.utils.CollectionUtil;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.Date; import java.util.Date;
@@ -21,15 +23,13 @@ import java.util.Map;
* @author yanlongqi * @author yanlongqi
* @date 2024/2/4 17:09 * @date 2024/2/4 17:09
*/ */
public class JHDataApiExecution extends JHApiExecution { @NoArgsConstructor
public class JHDataApiExecution implements JHApiExecution {
/** private JHRequestExecution execution;
* 获取一个执行器的实例
* public void init(JHRequestExecution execution) {
* @param jhApiClient 请求的客户端 this.execution = execution;
*/
public JHDataApiExecution(JHApiClient jhApiClient) {
super(jhApiClient);
} }
/** /**
@@ -39,11 +39,11 @@ public class JHDataApiExecution extends JHApiExecution {
* @return 用户数据目录列表 * @return 用户数据目录列表
*/ */
public List<SpoolerDataInfo> getSpoolersData(String username) { public List<SpoolerDataInfo> getSpoolersData(String username) {
return get(DataPathConstant.DATA_SPOOLERS_PATH, username, new TypeReference<ResponseResult<List<SpoolerDataInfo>>>() { return execution.get(DataPathConstant.DATA_SPOOLERS_PATH, username,
new TypeReference<ResponseResult<List<SpoolerDataInfo>>>() {
}); });
} }
/** /**
* 根据作业id查作业数据目录信息 * 根据作业id查作业数据目录信息
* *
@@ -56,7 +56,8 @@ public class JHDataApiExecution extends JHApiExecution {
throw new ArgsException("jobId不能为空"); throw new ArgsException("jobId不能为空");
} }
String path = DataPathConstant.DATA_SPOOLER_JOB_ID_PATH.replace("{jobId}", jobId); String path = DataPathConstant.DATA_SPOOLER_JOB_ID_PATH.replace("{jobId}", jobId);
List<SpoolerDataInfo> list = get(path, username, new TypeReference<ResponseResult<List<SpoolerDataInfo>>>() { List<SpoolerDataInfo> list = execution.get(path, username,
new TypeReference<ResponseResult<List<SpoolerDataInfo>>>() {
}); });
if (CollectionUtil.isEmpty(list)) { if (CollectionUtil.isEmpty(list)) {
throw new ServiceException(path, 500, "作业数据目录信息为空!"); throw new ServiceException(path, 500, "作业数据目录信息为空!");
@@ -78,7 +79,7 @@ public class JHDataApiExecution extends JHApiExecution {
Map<String, Object> params = new HashMap<>(1); Map<String, Object> params = new HashMap<>(1);
params.put("jobIds", String.join(CommonConstant.NORMAL_CHARACTER_COMMA, jobIds)); params.put("jobIds", String.join(CommonConstant.NORMAL_CHARACTER_COMMA, jobIds));
String path = JHApiClient.getUrl(DataPathConstant.DATA_SPOOLERS_LIST_PATH, params); String path = JHApiClient.getUrl(DataPathConstant.DATA_SPOOLERS_LIST_PATH, params);
return get(path, username, new TypeReference<ResponseResult<List<SpoolerDataInfo>>>() { return execution.get(path, username, new TypeReference<ResponseResult<List<SpoolerDataInfo>>>() {
}); });
} }
@@ -96,7 +97,8 @@ public class JHDataApiExecution extends JHApiExecution {
Map<String, Object> params = new HashMap<>(1); Map<String, Object> params = new HashMap<>(1);
params.put("name", dataName); params.put("name", dataName);
String path = JHApiClient.getUrl(DataPathConstant.DATA_SPOOLERS_NAME_PATH, params); String path = JHApiClient.getUrl(DataPathConstant.DATA_SPOOLERS_NAME_PATH, params);
List<SpoolerDataInfo> list = get(path, username, new TypeReference<ResponseResult<List<SpoolerDataInfo>>>() { List<SpoolerDataInfo> list = execution.get(path, username,
new TypeReference<ResponseResult<List<SpoolerDataInfo>>>() {
}); });
if (CollectionUtil.isEmpty(list)) { if (CollectionUtil.isEmpty(list)) {
throw new ServiceException(path, 500, "作业数据目录信息为空!"); throw new ServiceException(path, 500, "作业数据目录信息为空!");
@@ -104,7 +106,6 @@ public class JHDataApiExecution extends JHApiExecution {
return list.get(0); return list.get(0);
} }
/** /**
* 立即删除作业数据目录 * 立即删除作业数据目录
* *
@@ -116,11 +117,10 @@ public class JHDataApiExecution extends JHApiExecution {
throw new ArgsException("jobId不能为空"); throw new ArgsException("jobId不能为空");
} }
String path = DataPathConstant.DATA_SPOOLERS_DELETE_ID_PATH.replace("{id}", jobId); String path = DataPathConstant.DATA_SPOOLERS_DELETE_ID_PATH.replace("{id}", jobId);
get(path, username, new TypeReference<ResponseResult<Object>>() { execution.get(path, username, new TypeReference<ResponseResult<Object>>() {
}); });
} }
/** /**
* 设置用户数据目录的过期时间也给以通过设置过期时间来删除用户数据区 * 设置用户数据目录的过期时间也给以通过设置过期时间来删除用户数据区
* *
@@ -139,7 +139,7 @@ public class JHDataApiExecution extends JHApiExecution {
params.put("id", jobId); params.put("id", jobId);
params.put("expiration_time", expirationTime); params.put("expiration_time", expirationTime);
String path = JHApiClient.getUrl(DataPathConstant.DATA_SPOOLERS_PURGE_PATH, params); String path = JHApiClient.getUrl(DataPathConstant.DATA_SPOOLERS_PURGE_PATH, params);
get(path, username, new TypeReference<ResponseResult<Object>>() { execution.get(path, username, new TypeReference<ResponseResult<Object>>() {
}); });
} }

View File

@@ -0,0 +1,123 @@
package com.jhinno.sdk.openapi.api.file;
import lombok.Data;
import java.util.Date;
/**
* 文件信息
*
* @author yanlongqi
* @date 2024/2/5 10:47
*/
@Data
public class FileInfo {
/**
* 绝对路径
*/
private String absolutePath;
/**
* 是否为空
*/
private Boolean empty;
/**
* 文件密级
*/
private Integer fileConfLevel;
/**
* 文件ID
*/
private String fileId;
/**
* 是否文件夹
*/
private Boolean folder;
/**
* ID
*/
private Long id;
/**
* 最后修改时间
*/
private Date lastModified;
/**
* 权限
*/
private String permission;
/**
* 文件大小
*/
private Long size;
/**
* 文件名
*/
private String fileName;
/**
* 文件路径
*/
private String path;
/**
* 文件类型
* <ul>
* <li>directory文件夹</li>
* <li>file文件</li>
* </ul>
*/
private String fileType;
/**
* 名称
*/
private String name;
/**
* 文件属主
*/
private String owner;
/**
* 组
*/
private String group;
/**
* 其他
*/
private String other;
/**
* 是否可读
*/
private Boolean read;
/**
* 是否可写
*/
private Boolean write;
/**
* 是否可执行
*/
private Boolean execute;
/**
* 是否软链接
*/
private Integer link;
}

View File

@@ -0,0 +1,67 @@
package com.jhinno.sdk.openapi.api.file;
/**
* 文件请求路径
*
* @author yanlongqi
* @date 2024/2/4 18:59
*/
public class FilePathConstant {
/**
* 重命名文件
*/
public static final String FILE_RENAME_PATH = "/appform/ws/api/files/rename";
/**
* 删除文件
*/
public static final String FILE_DELETE_PATH = "/appform/ws/api/files/delete";
/**
* 拷贝文件
*/
public static final String FILE_COPY_PATH = "/appform/ws/api/files/copy";
/**
* 获取文件列表
*/
public static final String FILE_LIST_PATH = "/appform/ws/api/files";
/**
* 创建文件夹
*/
public static final String FILE_MKDIR_PATH = "/appform/ws/api/files/mkdir";
/**
* 创建文件
*/
public static final String FILE_MKFILE_PATH = "/appform/ws/api/files/mkfile";
/**
* 文件上传
*/
public static final String FILE_UPLOAD_PATH = "/appform/ws/api/files/upload";
/**
* 文件下载
*/
public static final String FILE_DOWNLOAD_PATH = "/appform/ws/api/files/download";
/**
* 压缩文件
*/
public static final String FILE_COMPRESS_PATH = "/appform/ws/api/files/compress";
/**
* 解压文件
*/
public static final String FILE_UNCOMPRESS_PATH = "/appform/ws/api/files/uncompress";
}

View File

@@ -1,21 +1,22 @@
package com.jhinno.sdk.openapi.api.file; package com.jhinno.sdk.openapi.api.file;
import cn.hutool.core.collection.CollectionUtil;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.jhinno.sdk.openapi.ArgsException; import com.jhinno.sdk.openapi.ArgsException;
import com.jhinno.sdk.openapi.CommonConstant; import com.jhinno.sdk.openapi.CommonConstant;
import com.jhinno.sdk.openapi.JHApiExecution;
import com.jhinno.sdk.openapi.ServiceException; import com.jhinno.sdk.openapi.ServiceException;
import com.jhinno.sdk.openapi.api.JHApiExecution; import com.jhinno.sdk.openapi.api.JHRequestExecution;
import com.jhinno.sdk.openapi.api.ResponseResult; import com.jhinno.sdk.openapi.api.ResponseResult;
import com.jhinno.sdk.openapi.client.JHApiClient; import com.jhinno.sdk.openapi.client.JHApiClient;
import com.jhinno.sdk.openapi.utils.CollectionUtil;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -26,13 +27,15 @@ import java.util.Map;
* @author yanlongqi * @author yanlongqi
* @date 2024/2/4 18:58 * @date 2024/2/4 18:58
*/ */
public class JHFileApiExecution extends JHApiExecution { @NoArgsConstructor
public class JHFileApiExecution implements JHApiExecution {
public JHFileApiExecution(JHApiClient jhApiClient) { private JHRequestExecution execution;
super(jhApiClient);
public void init(JHRequestExecution execution) {
this.execution = execution;
} }
/** /**
* 重命名文件 * 重命名文件
* *
@@ -50,10 +53,9 @@ public class JHFileApiExecution extends JHApiExecution {
Map<String, Object> body = new HashMap<>(2); Map<String, Object> body = new HashMap<>(2);
body.put("oldFileName", sourceFileNamePath); body.put("oldFileName", sourceFileNamePath);
body.put("newFileName", targetFileName); body.put("newFileName", targetFileName);
put(FilePathConstant.FILE_RENAME_PATH, username, body); execution.put(FilePathConstant.FILE_RENAME_PATH, username, body);
} }
/** /**
* 删除文件 * 删除文件
* *
@@ -67,10 +69,9 @@ public class JHFileApiExecution extends JHApiExecution {
Map<String, Object> params = new HashMap<>(1); Map<String, Object> params = new HashMap<>(1);
params.put("fileName", sourceFilePath); params.put("fileName", sourceFilePath);
String path = JHApiClient.getUrl(FilePathConstant.FILE_DELETE_PATH, params); String path = JHApiClient.getUrl(FilePathConstant.FILE_DELETE_PATH, params);
delete(path, username); execution.delete(path, username);
} }
/** /**
* 拷贝文件到目标文件夹 * 拷贝文件到目标文件夹
* *
@@ -88,10 +89,9 @@ public class JHFileApiExecution extends JHApiExecution {
Map<String, Object> body = new HashMap<>(2); Map<String, Object> body = new HashMap<>(2);
body.put("sourceFileName", sourceFilePath); body.put("sourceFileName", sourceFilePath);
body.put("targetDirectory", targetDirectoryPath); body.put("targetDirectory", targetDirectoryPath);
put(FilePathConstant.FILE_COPY_PATH, username, body); execution.put(FilePathConstant.FILE_COPY_PATH, username, body);
} }
/** /**
* 获取文件列表 * 获取文件列表
* *
@@ -106,11 +106,10 @@ public class JHFileApiExecution extends JHApiExecution {
Map<String, Object> params = new HashMap<>(1); Map<String, Object> params = new HashMap<>(1);
params.put("dir", dirPath); params.put("dir", dirPath);
String path = JHApiClient.getUrl(FilePathConstant.FILE_LIST_PATH, params); String path = JHApiClient.getUrl(FilePathConstant.FILE_LIST_PATH, params);
return get(path, username, new TypeReference<ResponseResult<List<FileInfo>>>() { return execution.get(path, username, new TypeReference<ResponseResult<List<FileInfo>>>() {
}); });
} }
/** /**
* 创建文件夹 * 创建文件夹
* *
@@ -128,7 +127,8 @@ public class JHFileApiExecution extends JHApiExecution {
if (isForce != null) { if (isForce != null) {
body.put("isForce", isForce.toString()); body.put("isForce", isForce.toString());
} }
Map<String, String> result = post(FilePathConstant.FILE_MKDIR_PATH, username, body, new TypeReference<ResponseResult<Map<String, String>>>() { Map<String, String> result = execution.post(FilePathConstant.FILE_MKDIR_PATH, username, body,
new TypeReference<ResponseResult<Map<String, String>>>() {
}); });
if (CollectionUtil.isEmpty(result)) { if (CollectionUtil.isEmpty(result)) {
return null; return null;
@@ -136,7 +136,6 @@ public class JHFileApiExecution extends JHApiExecution {
return result.get("dirPath"); return result.get("dirPath");
} }
/** /**
* 新建文件夹默认不强制新建 * 新建文件夹默认不强制新建
* *
@@ -148,7 +147,6 @@ public class JHFileApiExecution extends JHApiExecution {
return mkdir(username, dirPath, null); return mkdir(username, dirPath, null);
} }
/** /**
* 创建文件 * 创建文件
* *
@@ -162,7 +160,8 @@ public class JHFileApiExecution extends JHApiExecution {
} }
Map<String, Object> body = new HashMap<>(1); Map<String, Object> body = new HashMap<>(1);
body.put("filePath", filePath); body.put("filePath", filePath);
Map<String, String> result = post(FilePathConstant.FILE_MKFILE_PATH, username, body, new TypeReference<ResponseResult<Map<String, String>>>() { Map<String, String> result = execution.post(FilePathConstant.FILE_MKFILE_PATH, username, body,
new TypeReference<ResponseResult<Map<String, String>>>() {
}); });
if (CollectionUtil.isEmpty(result)) { if (CollectionUtil.isEmpty(result)) {
return null; return null;
@@ -181,35 +180,60 @@ public class JHFileApiExecution extends JHApiExecution {
* @param fileName 文件名称 * @param fileName 文件名称
* @param uploadPath 上传路径 * @param uploadPath 上传路径
* @param isCover 是否覆盖非必填默认false * @param isCover 是否覆盖非必填默认false
* @param fileConf 密级只有开启了密级才需要此参数可以是密级的中文名也可以是密级的中文名英文名或者密级的key
*/ */
public void uploadFile(String username, InputStream is, String fileName, String uploadPath, Boolean isCover) { public void uploadFile(String username, InputStream is, String fileName, String uploadPath, Boolean isCover, String fileConf) {
if (is == null) { if (is == null) {
throw new ArgsException("is是必填参数"); throw new ArgsException("is是必填参数");
} }
if (StringUtils.isBlank(uploadPath)) { if (StringUtils.isBlank(uploadPath)) {
throw new ArgsException("uploadPath是必填参数"); throw new ArgsException("uploadPath是必填参数");
} }
MultipartEntityBuilder builder = MultipartEntityBuilder.create(); Map<String, Object> body = new HashMap<>(3);
builder.setCharset(StandardCharsets.UTF_8);
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody("file", is, ContentType.MULTIPART_FORM_DATA, fileName);
if (isCover != null) { if (isCover != null) {
builder.addTextBody("isCover", isCover.toString()); body.put("isCover", isCover);
} }
builder.addTextBody("uploadPath", uploadPath); if (StringUtils.isNotBlank(fileConf)) {
HttpPost httpPost = new HttpPost(jhApiClient.getUrl(FilePathConstant.FILE_UPLOAD_PATH)); body.put("fileConf", fileConf);
httpPost.setEntity(builder.build()); }
ResponseResult<Object> result = jhApiClient.request(httpPost, getHeaders(username, false), new TypeReference<ResponseResult<Object>>() { body.put("uploadPath", uploadPath);
ResponseResult<Object> result = execution.getJhApiClient().upload(
FilePathConstant.FILE_UPLOAD_PATH,
"file",
fileName,
is,
execution.getHeaders(username, false),
body,
new TypeReference<ResponseResult<Object>>() {
}); });
if (StringUtils.equals(result.getResult(), CommonConstant.FAILED)) { if (StringUtils.equals(result.getResult(), CommonConstant.FAILED)) {
throw new ServiceException(FilePathConstant.FILE_UPLOAD_PATH, result.getCode(), result.getMessage()); throw new ServiceException(FilePathConstant.FILE_UPLOAD_PATH, result.getCode(), result.getMessage());
} }
} }
/**
* 上传文件
* <p>
* 如果isCover为空或者为false源文件目录下存在相同文件则会报错
* </p>
*
* @param username 用户名
* @param is 文件流
* @param fileName 文件名称
* @param uploadPath 上传路径
* @param isCover 是否覆盖非必填默认false
*/
public void uploadFile(String username, InputStream is, String fileName, String uploadPath, Boolean isCover) {
uploadFile(username, is, fileName, uploadPath, isCover, null);
}
/** /**
* 上传文件不覆盖源文件 * 上传文件不覆盖源文件
* <p>源文件目录下存在相同文件则会报错</p> * <p>
* 源文件目录下存在相同文件则会报错
* </p>
* *
* @param username 用户名 * @param username 用户名
* @param is 文件流 * @param is 文件流
@@ -220,6 +244,66 @@ public class JHFileApiExecution extends JHApiExecution {
uploadFile(username, is, fileName, uploadPath, null); uploadFile(username, is, fileName, uploadPath, null);
} }
/**
* 上传一个本地的路径
*
* @param username 用户名
* @param path 本地文件路径
* @param fileName 文件名
* @param uploadPath 上传路径服务器路径
* @param isCover 是否覆盖非必填默认false
*/
public void uploadFile(String username, String path, String fileName, String uploadPath, Boolean isCover)
throws FileNotFoundException {
if (StringUtils.isBlank(path)) {
throw new ArgsException("path是必填参数");
}
File file = new File(path);
FileInputStream fileInputStream = new FileInputStream(file);
uploadFile(username, fileInputStream, fileName, uploadPath, isCover);
}
/**
* 上传一个本地的路径不覆盖源文件
* <p>
* 源文件目录下存在相同文件则会报错
* </p>
*
* @param username 用户名
* @param path 本地文件路径
* @param fileName 文件名
* @param uploadPath 上传路径服务器路径
*/
public void uploadFile(String username, String path, String fileName, String uploadPath)
throws FileNotFoundException {
uploadFile(username, path, fileName, uploadPath, null);
}
/**
* 上传一个本地的路径
*
* @param username 用户名
* @param path 本地文件路径
* @param uploadPath 上传路径服务器路径
* @param isCover 是否覆盖非必填默认false
*/
public void uploadFile(String username, String path, String uploadPath, Boolean isCover)
throws FileNotFoundException {
File file = new File(path);
uploadFile(username, path, file.getName(), uploadPath, isCover);
}
/**
* 上传一个本地的路径不覆盖源文件
*
* @param username 用户名
* @param path 本地文件路径
* @param uploadPath 上传路径服务器路径
*/
public void uploadFile(String username, String path, String uploadPath) throws FileNotFoundException {
File file = new File(path);
uploadFile(username, path, file.getName(), uploadPath, null);
}
/** /**
* 获取文件下载地址 * 获取文件下载地址
@@ -229,13 +313,27 @@ public class JHFileApiExecution extends JHApiExecution {
* @return 文件地址信息 * @return 文件地址信息
*/ */
public String getFileDownloadUrl(String username, String filePath) { public String getFileDownloadUrl(String username, String filePath) {
return getFileDownloadUrl(username, filePath, null);
}
/**
* 获取文件下载地址
*
* @param username 用户名
* @param filePath 文件路径
* @param forceDownload 是否强制下载打开密级之后未标密的文件无法下载可以通过设置当前参数为true来强制下载默认false
* @return 文件地址信息
*/
public String getFileDownloadUrl(String username, String filePath, Boolean forceDownload) {
if (StringUtils.isBlank(filePath)) { if (StringUtils.isBlank(filePath)) {
throw new ArgsException("filePath不能为空"); throw new ArgsException("filePath不能为空");
} }
Map<String, Object> params = new HashMap<>(1); Map<String, Object> params = new HashMap<>(1);
params.put("filePath", filePath); params.put("filePath", filePath);
params.put("forceDownload", forceDownload);
String path = JHApiClient.getUrl(FilePathConstant.FILE_DOWNLOAD_PATH, params); String path = JHApiClient.getUrl(FilePathConstant.FILE_DOWNLOAD_PATH, params);
Map<String, String> downloadInfo = get(path, username, new TypeReference<ResponseResult<Map<String, String>>>() { Map<String, String> downloadInfo = execution.get(path, username,
new TypeReference<ResponseResult<Map<String, String>>>() {
}); });
if (CollectionUtil.isEmpty(downloadInfo)) { if (CollectionUtil.isEmpty(downloadInfo)) {
return null; return null;
@@ -243,6 +341,32 @@ public class JHFileApiExecution extends JHApiExecution {
return downloadInfo.get("url"); return downloadInfo.get("url");
} }
/**
* 获取文件输入流
*
* @param username 用户名
* @param filePath 文件路径
* @return 文件流
* @throws IOException
*/
public InputStream getFileInputStream(String username, String filePath) throws IOException {
return getFileInputStream(username, filePath, null);
}
/**
* 获取文件输入流
*
* @param username 用户名
* @param filePath 文件路径
* @param forceDownload 是否强制下载打开密级之后未标密的文件无法下载可以通过设置当前参数为true来强制下载默认false
* @return 文件流
* @throws IOException
*/
public InputStream getFileInputStream(String username, String filePath, Boolean forceDownload) throws IOException {
String fileUrl = getFileDownloadUrl(username, filePath, forceDownload);
return execution.getJhApiClient().getApiHttpClient().get(fileUrl, null);
}
/** /**
* 文件压缩 * 文件压缩
* *
@@ -265,10 +389,9 @@ public class JHFileApiExecution extends JHApiExecution {
params.put("compressType", compressType); params.put("compressType", compressType);
} }
String path = JHApiClient.getUrl(FilePathConstant.FILE_COMPRESS_PATH, params); String path = JHApiClient.getUrl(FilePathConstant.FILE_COMPRESS_PATH, params);
post(path, username); execution.post(path, username);
} }
/** /**
* 文件压缩 * 文件压缩
* *
@@ -290,7 +413,8 @@ public class JHFileApiExecution extends JHApiExecution {
* @param password 密码 * @param password 密码
* @param compressType 压缩类型 未使用以后扩展 * @param compressType 压缩类型 未使用以后扩展
*/ */
public void uncompress(String username, String sourceFilePath, String targetDirPath, Boolean isCover, String password, String compressType) { public void uncompress(String username, String sourceFilePath, String targetDirPath, Boolean isCover,
String password, String compressType) {
if (StringUtils.isBlank(sourceFilePath)) { if (StringUtils.isBlank(sourceFilePath)) {
throw new ArgsException("sourceFilePath不能为空"); throw new ArgsException("sourceFilePath不能为空");
} }
@@ -310,10 +434,9 @@ public class JHFileApiExecution extends JHApiExecution {
params.put("compressType", compressType); params.put("compressType", compressType);
} }
String path = JHApiClient.getUrl(FilePathConstant.FILE_UNCOMPRESS_PATH, params); String path = JHApiClient.getUrl(FilePathConstant.FILE_UNCOMPRESS_PATH, params);
post(path, username); execution.post(path, username);
} }
/** /**
* 解压文件 * 解压文件
* *
@@ -323,7 +446,8 @@ public class JHFileApiExecution extends JHApiExecution {
* @param isCover 是否覆盖 * @param isCover 是否覆盖
* @param password 密码 * @param password 密码
*/ */
public void uncompress(String username, String sourceFilePath, String targetDirPath, Boolean isCover, String password) { public void uncompress(String username, String sourceFilePath, String targetDirPath, Boolean isCover,
String password) {
uncompress(username, sourceFilePath, targetDirPath, isCover, password, null); uncompress(username, sourceFilePath, targetDirPath, isCover, password, null);
} }
@@ -350,5 +474,3 @@ public class JHFileApiExecution extends JHApiExecution {
uncompress(username, sourceFilePath, targetDirPath, null); uncompress(username, sourceFilePath, targetDirPath, null);
} }
} }

View File

@@ -1,16 +1,18 @@
package com.jhinno.sdk.openapi.api.job; package com.jhinno.sdk.openapi.api.job;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.jhinno.sdk.openapi.ArgsException; import com.jhinno.sdk.openapi.ArgsException;
import com.jhinno.sdk.openapi.CommonConstant; import com.jhinno.sdk.openapi.CommonConstant;
import com.jhinno.sdk.openapi.JHApiExecution;
import com.jhinno.sdk.openapi.ServiceException; import com.jhinno.sdk.openapi.ServiceException;
import com.jhinno.sdk.openapi.api.JHApiExecution; import com.jhinno.sdk.openapi.api.JHRequestExecution;
import com.jhinno.sdk.openapi.api.ResponseResult; import com.jhinno.sdk.openapi.api.ResponseResult;
import com.jhinno.sdk.openapi.api.file.FileInfo; import com.jhinno.sdk.openapi.api.file.FileInfo;
import com.jhinno.sdk.openapi.client.JHApiClient; import com.jhinno.sdk.openapi.client.JHApiClient;
import com.jhinno.sdk.openapi.utils.JsonUtil;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import com.jhinno.sdk.openapi.utils.CollectionUtil;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -20,15 +22,13 @@ import java.util.Map;
* @author yanlongqi * @author yanlongqi
* @date 2024/2/5 18:44 * @date 2024/2/5 18:44
*/ */
public class JHJobApiExecution extends JHApiExecution { @NoArgsConstructor
public class JHJobApiExecution implements JHApiExecution {
/** private JHRequestExecution execution;
* 获取一个执行器的实例
* public void init(JHRequestExecution execution) {
* @param jhApiClient 请求的客户端 this.execution = execution;
*/
public JHJobApiExecution(JHApiClient jhApiClient) {
super(jhApiClient);
} }
/** /**
@@ -48,9 +48,10 @@ public class JHJobApiExecution extends JHApiExecution {
} }
Map<String, Object> map = new HashMap<>(2); Map<String, Object> map = new HashMap<>(2);
map.put("appId", appId); map.put("appId", appId);
map.put("params", JSONUtil.toJsonStr(params)); map.put("params", JsonUtil.objectToString(params));
String path = JHApiClient.getUrl(JobPathConstant.JOB_SUBMIT_PATH, map); String path = JHApiClient.getUrl(JobPathConstant.JOB_SUBMIT_PATH, map);
List<Map<String, String>> result = post(path, username, new TypeReference<ResponseResult<List<Map<String, String>>>>() { List<Map<String, String>> result = execution.post(path, username,
new TypeReference<ResponseResult<List<Map<String, String>>>>() {
}); });
if (CollectionUtil.isEmpty(result)) { if (CollectionUtil.isEmpty(result)) {
throw new ServiceException(path, 500, "作业提交返回为空!"); throw new ServiceException(path, 500, "作业提交返回为空!");
@@ -70,13 +71,15 @@ public class JHJobApiExecution extends JHApiExecution {
throw new ArgsException("jobId不能为空"); throw new ArgsException("jobId不能为空");
} }
String path = JobPathConstant.JOB_FIND_JOB_FILES_PATH.replace("{jobId}", jobId); String path = JobPathConstant.JOB_FIND_JOB_FILES_PATH.replace("{jobId}", jobId);
return get(path, username, new TypeReference<ResponseResult<List<FileInfo>>>() { return execution.get(path, username, new TypeReference<ResponseResult<List<FileInfo>>>() {
}); });
} }
/** /**
* 分页查询作业列表 * 分页查询作业列表
* <p>作业名作业状态等为非必填自动如果为空则没有添加该查询条件</p> * <p>
* namestatuscondition均为删选条件condition为 高级筛选
* </p>
* *
* @param username 用户名 * @param username 用户名
* @param page 页码非必填默认1 * @param page 页码非必填默认1
@@ -87,7 +90,8 @@ public class JHJobApiExecution extends JHApiExecution {
* @return 作业列表 * @return 作业列表
* @see JobStatusEnum * @see JobStatusEnum
*/ */
public PageJobInfo getJobPage(String username, Integer page, Integer pageSize, String name, JobStatusEnum status, Map<String, Object> condition) { public PageJobInfo getJobPage(String username, Integer page, Integer pageSize, String name, JobStatusEnum status,
Map<String, Object> condition) {
Map<String, Object> params = new HashMap<>(5); Map<String, Object> params = new HashMap<>(5);
if (page != null) { if (page != null) {
params.put("page", page); params.put("page", page);
@@ -102,16 +106,18 @@ public class JHJobApiExecution extends JHApiExecution {
params.put("status", status.getStatus()); params.put("status", status.getStatus());
} }
if (CollectionUtil.isNotEmpty(condition)) { if (CollectionUtil.isNotEmpty(condition)) {
params.put("condition", JSONUtil.toJsonStr(params)); params.put("condition", JsonUtil.objectToString(params));
} }
String path = JHApiClient.getUrl(JobPathConstant.JOB_PAGE_PATH, params); String path = JHApiClient.getUrl(JobPathConstant.JOB_PAGE_PATH, params);
return get(path, username, new TypeReference<ResponseResult<PageJobInfo>>() { return execution.get(path, username, new TypeReference<ResponseResult<PageJobInfo>>() {
}); });
} }
/** /**
* 分页查询作业列表 * 分页查询作业列表
* <p>作业名作业状态等为非必填自动如果为空则没有添加该查询条件</p> * <p>
* namestatuscondition均为删选条件condition为 高级筛选
* </p>
* *
* @param username 用户名 * @param username 用户名
* @param page 页码非必填默认1 * @param page 页码非必填默认1
@@ -122,10 +128,71 @@ public class JHJobApiExecution extends JHApiExecution {
* @return 作业列表 * @return 作业列表
* @see JobStatusEnum * @see JobStatusEnum
*/ */
public PageJobInfo getJobPage(String username, Integer page, Integer pageSize, String name, String status, Map<String, Object> condition) { public PageJobInfo getJobPage(String username, Integer page, Integer pageSize, String name, String status,
Map<String, Object> condition) {
return getJobPage(username, page, pageSize, name, JobStatusEnum.getJobStatus(status), condition); return getJobPage(username, page, pageSize, name, JobStatusEnum.getJobStatus(status), condition);
} }
/**
* 分页查询作业列表
* <p>
* namestatuscondition均为删选条件condition为 高级筛选
* </p>
*
* @param username 用户名
* @param page 页码非必填默认1
* @param pageSize 每页大小非必填默认20
* @param name 作业名非必填
* @param status 作业名非必填
* @param condition 作业状态非必填取值见{@link JobStatusEnum#getJobStatus(String)}
* @return 作业列表
* @see JobStatusEnum
*/
public PageJobInfo getHistoryJobs(String username, Integer page, Integer pageSize, String name,
JobStatusEnum status, Map<String, Object> condition) {
Map<String, Object> params = new HashMap<>(5);
if (page != null) {
params.put("page", page);
}
if (pageSize != null) {
params.put("pageSize", pageSize);
}
if (StringUtils.isNotBlank(name)) {
params.put("jobName", name);
}
if (status != null) {
params.put("status", status.getStatus());
}
if (CollectionUtil.isNotEmpty(condition)) {
params.put("condition", JsonUtil.objectToString(params));
}
String path = JHApiClient.getUrl(JobPathConstant.JOB_HISTORY_JOBS_PATH, params);
return execution.get(path, username, new TypeReference<ResponseResult<PageJobInfo>>() {
});
}
/**
* 分页查询作业列表
* <p>
* namestatuscondition均为删选条件condition为 高级筛选
* </p>
*
* @param username 用户名
* @param page 页码非必填默认1
* @param pageSize 每页大小非必填默认20
* @param name 作业名非必填
* @param status 作业名非必填
* @param condition 作业状态非必填取值见{@link JobStatusEnum#getJobStatus(String)}
* @return 作业列表
* @see JobStatusEnum
*/
public PageJobInfo getHistoryJobs(String username, Integer page, Integer pageSize, String name, String status,
Map<String, Object> condition) {
return getHistoryJobs(username, page, pageSize, name, JobStatusEnum.getJobStatus(status), condition);
}
/** /**
* 查询作业详情 * 查询作业详情
* *
@@ -138,11 +205,10 @@ public class JHJobApiExecution extends JHApiExecution {
throw new ArgsException("jobId不能为空"); throw new ArgsException("jobId不能为空");
} }
String path = JobPathConstant.JOB_DETAIL_INFO_PATH.replace("{jobId}", jobId); String path = JobPathConstant.JOB_DETAIL_INFO_PATH.replace("{jobId}", jobId);
return get(path, username, new TypeReference<ResponseResult<JobInfo>>() { return execution.get(path, username, new TypeReference<ResponseResult<JobInfo>>() {
}); });
} }
/** /**
* 分页检索作业名称查询作业信息 * 分页检索作业名称查询作业信息
* *
@@ -166,11 +232,10 @@ public class JHJobApiExecution extends JHApiExecution {
} }
String path = JHApiClient.getUrl(JobPathConstant.JOB_LIST_BY_NAME_PATH, params); String path = JHApiClient.getUrl(JobPathConstant.JOB_LIST_BY_NAME_PATH, params);
return get(path, username, new TypeReference<ResponseResult<List<JobInfo>>>() { return execution.get(path, username, new TypeReference<ResponseResult<List<JobInfo>>>() {
}); });
} }
/** /**
* 分页检索作业状态 * 分页检索作业状态
* <p> * <p>
@@ -193,12 +258,12 @@ public class JHJobApiExecution extends JHApiExecution {
if (pageSize != null) { if (pageSize != null) {
params.put("pageSize", pageSize); params.put("pageSize", pageSize);
} }
String path = JHApiClient.getUrl(JobPathConstant.JOB_LIST_BY_STATUS_PATH.replace("{status}", status.getStatus()), params); String path = JHApiClient
return get(path, username, new TypeReference<ResponseResult<List<JobInfo>>>() { .getUrl(JobPathConstant.JOB_LIST_BY_STATUS_PATH.replace("{status}", status.getStatus()), params);
return execution.get(path, username, new TypeReference<ResponseResult<List<JobInfo>>>() {
}); });
} }
/** /**
* 作业的状态必填 * 作业的状态必填
* *
@@ -213,7 +278,6 @@ public class JHJobApiExecution extends JHApiExecution {
return getJobsByStatus(username, JobStatusEnum.getJobStatus(status), page, pageSize); return getJobsByStatus(username, JobStatusEnum.getJobStatus(status), page, pageSize);
} }
/** /**
* 通过作业id列表查询作业列表 * 通过作业id列表查询作业列表
* *
@@ -228,14 +292,15 @@ public class JHJobApiExecution extends JHApiExecution {
Map<String, Object> params = new HashMap<>(1); Map<String, Object> params = new HashMap<>(1);
params.put("jobIds", String.join(CommonConstant.NORMAL_CHARACTER_COMMA, jobIds)); params.put("jobIds", String.join(CommonConstant.NORMAL_CHARACTER_COMMA, jobIds));
String path = JHApiClient.getUrl(JobPathConstant.JOB_LIST_BY_IDS_PATH, params); String path = JHApiClient.getUrl(JobPathConstant.JOB_LIST_BY_IDS_PATH, params);
return get(path, username, new TypeReference<ResponseResult<List<JobInfo>>>() { return execution.get(path, username, new TypeReference<ResponseResult<List<JobInfo>>>() {
}); });
} }
/** /**
* 操作作业 * 操作作业
* <p> * <p>
* {@link JobActionEnum} 中的 静态方法{@link JobActionEnum#getJobAction(String)}可以将前端的字符转换为{@link JobActionEnum}对象 * {@link JobActionEnum} 中的
* 静态方法{@link JobActionEnum#getJobAction(String)}可以将前端的字符转换为{@link JobActionEnum}对象
* <p> * <p>
* 或者使用{@link #action(String, String, String)}直接操作但最终还是调的这个方法我们只不过是内部做了转换而已 * 或者使用{@link #action(String, String, String)}直接操作但最终还是调的这个方法我们只不过是内部做了转换而已
* *
@@ -252,7 +317,7 @@ public class JHJobApiExecution extends JHApiExecution {
throw new ArgsException("jobId不能为空"); throw new ArgsException("jobId不能为空");
} }
String path = JobPathConstant.JOB_ACTION_PATH.replace("{jobId}", jobId).replace("{action}", action.getAction()); String path = JobPathConstant.JOB_ACTION_PATH.replace("{jobId}", jobId).replace("{action}", action.getAction());
put(path, username); execution.put(path, username);
} }
/** /**
@@ -266,11 +331,11 @@ public class JHJobApiExecution extends JHApiExecution {
action(username, JobActionEnum.getJobAction(action), jobId); action(username, JobActionEnum.getJobAction(action), jobId);
} }
/** /**
* 批量操作作业 * 批量操作作业
* <p> * <p>
* {@link JobsActionEnum} 中的 静态方法{@link JobsActionEnum#getJobAction(String)}可以将前端的字符转换为{@link JobsActionEnum}对象 * {@link JobsActionEnum} 中的
* 静态方法{@link JobsActionEnum#getJobAction(String)}可以将前端的字符转换为{@link JobsActionEnum}对象
* <p> * <p>
* 或者使用{@link #actions(String, String, List)}直接操作但最终还是调的这个方法我们只不过是内部做了转换而已 * 或者使用{@link #actions(String, String, List)}直接操作但最终还是调的这个方法我们只不过是内部做了转换而已
* *
@@ -287,8 +352,9 @@ public class JHJobApiExecution extends JHApiExecution {
} }
Map<String, Object> params = new HashMap<>(1); Map<String, Object> params = new HashMap<>(1);
params.put("jobIds", String.join(CommonConstant.NORMAL_CHARACTER_COMMA, jobIds)); params.put("jobIds", String.join(CommonConstant.NORMAL_CHARACTER_COMMA, jobIds));
String path = JHApiClient.getUrl(JobPathConstant.JOB_ACTION_IDS_PATH.replace("{action}", action.getAction()), params); String path = JHApiClient.getUrl(JobPathConstant.JOB_ACTION_IDS_PATH.replace("{action}", action.getAction()),
put(path, username); params);
execution.put(path, username);
} }
/** /**
@@ -302,7 +368,6 @@ public class JHJobApiExecution extends JHApiExecution {
actions(username, JobsActionEnum.getJobAction(action), jobIds); actions(username, JobsActionEnum.getJobAction(action), jobIds);
} }
/** /**
* 查询制定作业的作业历史 * 查询制定作业的作业历史
* *
@@ -315,7 +380,8 @@ public class JHJobApiExecution extends JHApiExecution {
throw new ArgsException("jobId不能为空"); throw new ArgsException("jobId不能为空");
} }
String path = JobPathConstant.JOB_HISTORY_PATH.replace("{jobId}", jobId); String path = JobPathConstant.JOB_HISTORY_PATH.replace("{jobId}", jobId);
List<JobHistoryInfo> list = get(path, username, new TypeReference<ResponseResult<List<JobHistoryInfo>>>() { List<JobHistoryInfo> list = execution.get(path, username,
new TypeReference<ResponseResult<List<JobHistoryInfo>>>() {
}); });
if (CollectionUtil.isEmpty(list)) { if (CollectionUtil.isEmpty(list)) {
throw new ServiceException(path, 500, "历史作业信息不存在!"); throw new ServiceException(path, 500, "历史作业信息不存在!");
@@ -323,7 +389,6 @@ public class JHJobApiExecution extends JHApiExecution {
return list.get(0); return list.get(0);
} }
/** /**
* 通过多个id查询作业历史列表 * 通过多个id查询作业历史列表
* *
@@ -338,7 +403,7 @@ public class JHJobApiExecution extends JHApiExecution {
Map<String, Object> params = new HashMap<>(1); Map<String, Object> params = new HashMap<>(1);
params.put("jobIds", String.join(CommonConstant.NORMAL_CHARACTER_COMMA, jobIds)); params.put("jobIds", String.join(CommonConstant.NORMAL_CHARACTER_COMMA, jobIds));
String path = JHApiClient.getUrl(JobPathConstant.JOB_HISTORY_IDS_PATH, params); String path = JHApiClient.getUrl(JobPathConstant.JOB_HISTORY_IDS_PATH, params);
return get(path, username, new TypeReference<ResponseResult<List<JobHistoryInfo>>>() { return execution.get(path, username, new TypeReference<ResponseResult<List<JobHistoryInfo>>>() {
}); });
} }
@@ -354,7 +419,8 @@ public class JHJobApiExecution extends JHApiExecution {
throw new ArgsException("jobId不能为空"); throw new ArgsException("jobId不能为空");
} }
String path = JobPathConstant.JOB_PEEK_PATH.replace("{jobId}", jobId); String path = JobPathConstant.JOB_PEEK_PATH.replace("{jobId}", jobId);
ResponseResult<String> result = jhApiClient.get(path, getHeaders(username), new TypeReference<ResponseResult<String>>() { ResponseResult<String> result = execution.getJhApiClient().get(path, execution.getHeaders(username),
new TypeReference<ResponseResult<String>>() {
}); });
if (StringUtils.equals(result.getResult(), CommonConstant.FAILED)) { if (StringUtils.equals(result.getResult(), CommonConstant.FAILED)) {
throw new ServiceException(path, result.getCode(), result.getMessage()); throw new ServiceException(path, result.getCode(), result.getMessage());
@@ -366,7 +432,6 @@ public class JHJobApiExecution extends JHApiExecution {
return result.getMessage(); return result.getMessage();
} }
/** /**
* 连接作业会话 * 连接作业会话
* *
@@ -379,7 +444,22 @@ public class JHJobApiExecution extends JHApiExecution {
throw new ArgsException("jobId不能为空"); throw new ArgsException("jobId不能为空");
} }
String path = JobPathConstant.JOB_CONNECT_SESSION_PATH.replace("{jobId}", jobId); String path = JobPathConstant.JOB_CONNECT_SESSION_PATH.replace("{jobId}", jobId);
return post(path, username, new TypeReference<ResponseResult<Object>>() { return execution.post(path, username, new TypeReference<ResponseResult<Object>>() {
});
}
/**
* 查询用户作业表单信息
*
* @param username 用户名
* @param appId 用户ID
*/
public List<JobAppFormItemInfo> getSimulationAppForm(String username, String appId) {
if (StringUtils.isBlank(appId)) {
throw new ArgsException("appId不能为空");
}
String path = JobPathConstant.JOB_GET_APP_FORM_PATH.replace("{appId}", appId);
return execution.get(path, username, new TypeReference<ResponseResult<List<JobAppFormItemInfo>>>() {
}); });
} }

View File

@@ -0,0 +1,64 @@
package com.jhinno.sdk.openapi.api.job;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
public class JobAppFormItemInfo {
/**
* 参数描述
*/
private String valueDesc;
/**
* 参数key
*/
private String valueKey;
/**
* 参数正则
*/
private String validateRegXp;
/**
* 参数类型
* 从参数范围内多选(多个值用英文逗号隔开)还是单选,
* string、singleSelect、multiSelect
* <ol>
* <li>选择: select</li>
* <li>开关: switch</li>
* <li>值: text</li>
* <li>文件: upload</li>
* </ol>
*/
private String valueType;
/**
* 参数范围
*/
private List<ParamsValueScope> valueScope;
/**
* 是否必填
*/
private boolean required;
/**
* 默认值
*/
private String valueDefault;
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class ParamsValueScope {
private String name;
private String value;
}
}

View File

@@ -0,0 +1,87 @@
package com.jhinno.sdk.openapi.api.job;
/**
* 作业相关接口路径
*
* @author yanlongqi
* @date 2024/2/5 18:44
*/
public class JobPathConstant {
/**
* 提交作业
*/
public static final String JOB_SUBMIT_PATH = "/appform/ws/api/jobs/jsub";
/**
* 使用作业id查询作业列表
*/
public static final String JOB_FIND_JOB_FILES_PATH = "/appform/ws/api/jobs/{jobId}/files";
/**
* 分页查询作业列表
*/
public static final String JOB_PAGE_PATH = "/appform/ws/api/jobs/page";
/**
* 查询历史作业列表
*/
public static final String JOB_HISTORY_JOBS_PATH = "/appform/ws/api/jobs/historyPage";
/**
* 查询作业详情
*/
public static final String JOB_DETAIL_INFO_PATH = "/appform/ws/api/jobs/{jobId}";
/**
* 分页检索作业名
*/
public static final String JOB_LIST_BY_NAME_PATH = "/appform/ws/api/jobs/byName";
/**
* 作业号检索作业列表
*/
public static final String JOB_LIST_BY_STATUS_PATH = "/appform/ws/api/jobs/byStatus/{status}";
/**
* 通过作业号查询作业列表
*/
public static final String JOB_LIST_BY_IDS_PATH = "/appform/ws/api/jobs/list";
/**
* 作业操作
*/
public static final String JOB_ACTION_PATH = "/appform/ws/api/jobs/{jobId}/{action}";
/**
* 批量操作作业
*/
public static final String JOB_ACTION_IDS_PATH = "/appform/ws/api/jobs/{action}";
/**
* 获取作业历史
*/
public static final String JOB_HISTORY_PATH = "/appform/ws/api/jobs/{jobId}/hist";
/**
* 通过多个作业号查询作业历史
*/
public static final String JOB_HISTORY_IDS_PATH = "/appform/ws/api/jobs/hist";
/**
* 获取作业动态输出
*/
public static final String JOB_PEEK_PATH = "/appform/ws/api/jobs/{jobId}/peek";
/**
* 连接作业会话
*/
public static final String JOB_CONNECT_SESSION_PATH = "/appform/ws/api/jobs/{jobId}/connect";
/**
* 获取作业表单
* <p/>
* 该接口目前在Solutions下面维护未经过产品的测试
*/
public static final String JOB_GET_APP_FORM_PATH = "/appform/ws/api/jobs/{appId}/form_params";
}

View File

@@ -28,7 +28,6 @@ public enum JobStatusEnum {
EXIT("EXIT", "退出"), EXIT("EXIT", "退出"),
UNKNOWN_UNKWN("UNKNOWN#UNKWN", "状态不明"); UNKNOWN_UNKWN("UNKNOWN#UNKWN", "状态不明");
/** /**
* 状态标识 * 状态标识
*/ */
@@ -39,7 +38,6 @@ public enum JobStatusEnum {
*/ */
private final String name; private final String name;
/** /**
* 使用标号获得JobStatusEnum对象 * 使用标号获得JobStatusEnum对象
* *
@@ -49,7 +47,7 @@ public enum JobStatusEnum {
*/ */
public static JobStatusEnum getJobStatus(String status) { public static JobStatusEnum getJobStatus(String status) {
if (StringUtils.isBlank(status)) { if (StringUtils.isBlank(status)) {
throw new ArgsException("作业状态不能为空!"); return null;
} }
for (JobStatusEnum value : values()) { for (JobStatusEnum value : values()) {
if (StringUtils.equals(status, value.getStatus())) { if (StringUtils.equals(status, value.getStatus())) {

View File

@@ -11,11 +11,11 @@ public class DepartmentPathConstant {
/** /**
* 组织 * 组织
*/ */
public static final String DEPARTMENT_PATH = "/ws/api/deps"; public static final String DEPARTMENT_PATH = "/appform/ws/api/deps";
/** /**
* 组织名称操作组织 * 组织名称操作组织
*/ */
public static final String DEPARTMENT_NAME_PATH = "/ws/api/deps/{depName}"; public static final String DEPARTMENT_NAME_PATH = "/appform/ws/api/deps/{depName}";
} }

View File

@@ -2,9 +2,10 @@ package com.jhinno.sdk.openapi.api.organization;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.jhinno.sdk.openapi.ArgsException; import com.jhinno.sdk.openapi.ArgsException;
import com.jhinno.sdk.openapi.api.JHApiExecution; import com.jhinno.sdk.openapi.JHApiExecution;
import com.jhinno.sdk.openapi.api.JHRequestExecution;
import com.jhinno.sdk.openapi.api.ResponseResult; import com.jhinno.sdk.openapi.api.ResponseResult;
import com.jhinno.sdk.openapi.client.JHApiClient; import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.List; import java.util.List;
@@ -18,18 +19,15 @@ import java.util.Map;
* @author yanlongqi * @author yanlongqi
* @date 2024/2/6 17:37 * @date 2024/2/6 17:37
*/ */
public class JHDepartmentApiExecution extends JHApiExecution { @NoArgsConstructor
public class JHDepartmentApiExecution implements JHApiExecution {
/** private JHRequestExecution execution;
* 获取一个执行器的实例
* public void init(JHRequestExecution execution) {
* @param jhApiClient 请求的客户端 this.execution = execution;
*/
public JHDepartmentApiExecution(JHApiClient jhApiClient) {
super(jhApiClient);
} }
/** /**
* 查询用户列表 * 查询用户列表
* *
@@ -37,11 +35,11 @@ public class JHDepartmentApiExecution extends JHApiExecution {
* @return 用户列表 * @return 用户列表
*/ */
public List<Map<String, Object>> getDepartmentList(String username) { public List<Map<String, Object>> getDepartmentList(String username) {
return get(DepartmentPathConstant.DEPARTMENT_PATH, username, new TypeReference<ResponseResult<List<Map<String, Object>>>>() { return execution.get(DepartmentPathConstant.DEPARTMENT_PATH, username,
new TypeReference<ResponseResult<List<Map<String, Object>>>>() {
}); });
} }
/** /**
* 添加部门 * 添加部门
* *
@@ -49,10 +47,9 @@ public class JHDepartmentApiExecution extends JHApiExecution {
* @param departmentInfo 部门信息 * @param departmentInfo 部门信息
*/ */
public void addDepartment(String username, AddUpdateDepartment departmentInfo) { public void addDepartment(String username, AddUpdateDepartment departmentInfo) {
post(DepartmentPathConstant.DEPARTMENT_PATH, username, departmentInfo); execution.post(DepartmentPathConstant.DEPARTMENT_PATH, username, departmentInfo);
} }
/** /**
* 修改部门信息 * 修改部门信息
* *
@@ -64,10 +61,9 @@ public class JHDepartmentApiExecution extends JHApiExecution {
throw new ArgsException("departmentInfo中的depName不能为空"); throw new ArgsException("departmentInfo中的depName不能为空");
} }
String path = DepartmentPathConstant.DEPARTMENT_NAME_PATH.replace("{depName}", departmentInfo.getDepName()); String path = DepartmentPathConstant.DEPARTMENT_NAME_PATH.replace("{depName}", departmentInfo.getDepName());
put(path, username, departmentInfo); execution.put(path, username, departmentInfo);
} }
/** /**
* 删除部门信息 * 删除部门信息
* *
@@ -79,6 +75,6 @@ public class JHDepartmentApiExecution extends JHApiExecution {
throw new ArgsException("departmentName不能为空"); throw new ArgsException("departmentName不能为空");
} }
String path = DepartmentPathConstant.DEPARTMENT_NAME_PATH.replace("{depName}", departmentName); String path = DepartmentPathConstant.DEPARTMENT_NAME_PATH.replace("{depName}", departmentName);
delete(path, username); execution.delete(path, username);
} }
} }

View File

@@ -2,10 +2,12 @@ package com.jhinno.sdk.openapi.api.organization;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.jhinno.sdk.openapi.ArgsException; import com.jhinno.sdk.openapi.ArgsException;
import com.jhinno.sdk.openapi.api.JHApiExecution; import com.jhinno.sdk.openapi.JHApiExecution;
import com.jhinno.sdk.openapi.api.JHRequestExecution;
import com.jhinno.sdk.openapi.api.PageResult; import com.jhinno.sdk.openapi.api.PageResult;
import com.jhinno.sdk.openapi.api.ResponseResult; import com.jhinno.sdk.openapi.api.ResponseResult;
import com.jhinno.sdk.openapi.client.JHApiClient; import com.jhinno.sdk.openapi.client.JHApiClient;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.util.HashMap; import java.util.HashMap;
@@ -19,16 +21,14 @@ import java.util.Map;
* @author yanlongqi * @author yanlongqi
* @date 2024/2/6 17:37 * @date 2024/2/6 17:37
*/ */
public class JHUserApiExecution extends JHApiExecution { @NoArgsConstructor
/** public class JHUserApiExecution implements JHApiExecution {
* 获取一个执行器的实例
*
* @param jhApiClient 请求的客户端
*/
public JHUserApiExecution(JHApiClient jhApiClient) {
super(jhApiClient);
}
private JHRequestExecution execution;
public void init(JHRequestExecution execution) {
this.execution = execution;
}
/** /**
* 分页查询用户列表 * 分页查询用户列表
@@ -51,7 +51,7 @@ public class JHUserApiExecution extends JHApiExecution {
params.put("userConf", userConf); params.put("userConf", userConf);
} }
String path = JHApiClient.getUrl(UserPathConstant.USERS_PATH, params); String path = JHApiClient.getUrl(UserPathConstant.USERS_PATH, params);
return get(path, username, new TypeReference<ResponseResult<PageResult<UserInfo>>>() { return execution.get(path, username, new TypeReference<ResponseResult<PageResult<UserInfo>>>() {
}); });
} }
@@ -62,7 +62,7 @@ public class JHUserApiExecution extends JHApiExecution {
* @param userInfo 用户信息 * @param userInfo 用户信息
*/ */
public void addUser(String username, AddUpdateUserInfo userInfo) { public void addUser(String username, AddUpdateUserInfo userInfo) {
post(UserPathConstant.USERS_PATH, username, userInfo); execution.post(UserPathConstant.USERS_PATH, username, userInfo);
} }
/** /**
@@ -76,10 +76,9 @@ public class JHUserApiExecution extends JHApiExecution {
throw new ArgsException("userInfo中userName的值不能为空"); throw new ArgsException("userInfo中userName的值不能为空");
} }
String path = UserPathConstant.USERS_USERNAME_PATH.replace("{username}", userInfo.getUserName()); String path = UserPathConstant.USERS_USERNAME_PATH.replace("{username}", userInfo.getUserName());
put(path, username, userInfo); execution.put(path, username, userInfo);
} }
/** /**
* 修改或重置用户密码 * 修改或重置用户密码
* *
@@ -96,7 +95,8 @@ public class JHUserApiExecution extends JHApiExecution {
* @param password 新密码 * @param password 新密码
* @param type 类型非必填取值见{@link UpdateUserPasswordType} * @param type 类型非必填取值见{@link UpdateUserPasswordType}
*/ */
public void updateUserPassword(String username, String updatePasswordUsername, String oldPassword, String password, String type) { public void updateUserPassword(String username, String updatePasswordUsername, String oldPassword, String password,
String type) {
if (StringUtils.isBlank(updatePasswordUsername)) { if (StringUtils.isBlank(updatePasswordUsername)) {
throw new ArgsException("updatePasswordUsername不能为空"); throw new ArgsException("updatePasswordUsername不能为空");
} }
@@ -109,10 +109,9 @@ public class JHUserApiExecution extends JHApiExecution {
params.put("type", type); params.put("type", type);
} }
params.put("password", password); params.put("password", password);
put(path, username, params); execution.put(path, username, params);
} }
/** /**
* 修改用户的密码 * 修改用户的密码
* *
@@ -121,7 +120,8 @@ public class JHUserApiExecution extends JHApiExecution {
* @param oldPassword 旧密码 * @param oldPassword 旧密码
* @param password 新密码 * @param password 新密码
*/ */
public void updateUserPassword(String username, String updatePasswordUsername, String oldPassword, String password) { public void updateUserPassword(String username, String updatePasswordUsername, String oldPassword,
String password) {
updateUserPassword(username, updatePasswordUsername, oldPassword, password, null); updateUserPassword(username, updatePasswordUsername, oldPassword, password, null);
} }
@@ -133,7 +133,8 @@ public class JHUserApiExecution extends JHApiExecution {
* @param password 新的用户密码 * @param password 新的用户密码
*/ */
public void resetForceUpdatePassword(String username, String updatePasswordUsername, String password) { public void resetForceUpdatePassword(String username, String updatePasswordUsername, String password) {
updateUserPassword(username, updatePasswordUsername, null, password, UpdateUserPasswordType.FORCE_UPDATE_PASSWORD_TYPE); updateUserPassword(username, updatePasswordUsername, null, password,
UpdateUserPasswordType.FORCE_UPDATE_PASSWORD_TYPE);
} }
/** /**
@@ -144,10 +145,10 @@ public class JHUserApiExecution extends JHApiExecution {
* @param password 新的用户密码 * @param password 新的用户密码
*/ */
public void resetPassword(String username, String updatePasswordUsername, String password) { public void resetPassword(String username, String updatePasswordUsername, String password) {
updateUserPassword(username, updatePasswordUsername, null, password, UpdateUserPasswordType.RESET_UPDATE_PASSWORD_TYPE); updateUserPassword(username, updatePasswordUsername, null, password,
UpdateUserPasswordType.RESET_UPDATE_PASSWORD_TYPE);
} }
/** /**
* 删除用户 * 删除用户
* *
@@ -158,7 +159,7 @@ public class JHUserApiExecution extends JHApiExecution {
if (StringUtils.isBlank(deleteUsername)) { if (StringUtils.isBlank(deleteUsername)) {
throw new ArgsException("deleteUsername不能为空"); throw new ArgsException("deleteUsername不能为空");
} }
delete(UserPathConstant.USERS_USERNAME_PATH.replace("{username}", deleteUsername), username); execution.delete(UserPathConstant.USERS_USERNAME_PATH.replace("{username}", deleteUsername), username);
} }
} }

View File

@@ -11,18 +11,18 @@ public class UserPathConstant {
/** /**
* 查询用户和修改用户 * 查询用户和修改用户
*/ */
public static final String USERS_PATH = "/ws/api/users"; public static final String USERS_PATH = "/appform/ws/api/users";
/** /**
* 修改用户和删除用户 * 修改用户和删除用户
*/ */
public static final String USERS_USERNAME_PATH = "/ws/api/users/{username}"; public static final String USERS_USERNAME_PATH = "/appform/ws/api/users/{username}";
/** /**
* 用户密码操作 * 用户密码操作
*/ */
public static final String USERS_RESET_PASSWORD_PATH = "/ws/api/users/{username}/password/password_reset"; public static final String USERS_RESET_PASSWORD_PATH = "/appform/ws/api/users/{username}/password/password_reset";
} }

View File

@@ -0,0 +1,58 @@
package com.jhinno.sdk.openapi.client;
/**
* 默认的HTTP客户端请求配置
*
* @author yanlongqi
* @date 2024/1/30 18:12
*/
public class DefaultHttpClientConfig {
/**
* 默认设置最大连接数
*/
public static int MAX_TOTAL = 200;
/**
* 默认服务每次能并行接收的请求数量
*/
public static int MAX_PER_ROUTE = 20;
/**
* 默认socket连接超时的时间(单位:毫秒)
*/
public static final int SOCKET_TIMEOUT = 5000;
/**
* 默认连接超时的时间(单位:毫秒)
*/
public static final int CONNECT_TIMEOUT = 5000;
/**
* 默认请求超时的时间(单位:毫秒)
*/
public static final int CONNECTION_REQUEST_TIMEOUT = 5000;
/**
* 是否使用服务器的时间
*/
public static final boolean DEFAULT_IS_USED_SERVER_TIME = false;
/**
* 默认不强制获取token
*/
public static final boolean DEFAULT_IS_FORCE_GET_TOKEN = false;
/**
* 默认的token有效时间单位分钟
*/
public static final int DEFAULT_TOKEN_EFFECTIVE_TIME = 30;
/**
* token 默认剩余时间
*/
public static final int DEFAULT_TOKEN_RESIDUE_TIME = 5;
}

View File

@@ -0,0 +1,332 @@
package com.jhinno.sdk.openapi.client;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jhinno.sdk.openapi.ArgsException;
import com.jhinno.sdk.openapi.ClientErrorCode;
import com.jhinno.sdk.openapi.ClientException;
import com.jhinno.sdk.openapi.CommonConstant;
import com.jhinno.sdk.openapi.api.ResponseResult;
import com.jhinno.sdk.openapi.api.auth.AuthPathConstant;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.TimeZone;
/**
* 提供请求的工具
*
* @author yanlongqi
* @date 2024/1/29 10:31
*/
@Data
public class JHApiClient {
/**
* 基础的请求URL地址
* <p>
* 如https:// 192.168.3.12/appform
* </p>
*/
private String baseUrl;
/**
* 设置自定义的jackson序列化配置
*/
private ObjectMapper mapper;
/**
* API HTTP 客户端
*/
private JHApiHttpClient apiHttpClient;
public JHApiClient(String baseUrl) {
if (StringUtils.isBlank(baseUrl)) {
throw new ClientException("服务器的BaseUrl不能为空");
}
if (baseUrl.endsWith("/")) {
baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
}
this.baseUrl = baseUrl;
mapper = new ObjectMapper();
mapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
mapper.setDateFormat(new SimpleDateFormat(CommonConstant.NORM_DATETIME_PATTERN));
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
public void initDefaultApiClient() {
JHApiHttpClientImpl jhApiHttpClient = new JHApiHttpClientImpl();
jhApiHttpClient.init();
jhApiHttpClient.createHttpClients();
this.apiHttpClient = jhApiHttpClient;
}
/**
* 发送一个get请求
*
* @param path 接口路径
* @param headers 请求头
* @param type 返回数据类型
* @param <T> 返回数据类型
* @return 返回数据
*/
public <T> T get(String path, Map<String, Object> headers, TypeReference<T> type) {
if (StringUtils.isBlank(path)) {
throw new ArgsException("url不能为空");
}
try {
InputStream content = apiHttpClient.get(getUrl(path), headers);
return mapper.readValue(content, type);
} catch (IOException e) {
throw new ClientException(e.getMessage(), e);
}
}
/**
* 发起一个get请求
*
* @param path 接口地址
* @param type 返回数据的类型
* @param <T> 返回数据的类型
* @return 请求的数据
*/
public <T> T get(String path, TypeReference<T> type) {
return get(path, null, type);
}
/**
* 获的一个url
*
* @param path 请求地址
* @param params 请求参数
* @return 添加路径参数后的URL
*/
public static String getUrl(String path, Map<String, Object> params) {
if (StringUtils.isBlank(path)) {
throw new ClientException("path不能为空");
}
if (params == null || params.isEmpty()) {
return path;
}
StringBuilder urlBuilder = new StringBuilder(path + "?");
for (Map.Entry<String, Object> entry : params.entrySet()) {
try {
Object value = entry.getValue();
// 如果值为空,则不添加该字段
if (value == null) {
continue;
}
urlBuilder.append(entry.getKey()).append("=");
if (value instanceof String) {
urlBuilder.append(URLEncoder.encode((String) value, StandardCharsets.UTF_8.name()));
} else if (value instanceof Date) {
SimpleDateFormat format = new SimpleDateFormat(CommonConstant.NORM_DATETIME_PATTERN);
urlBuilder.append(URLEncoder.encode(format.format(value), StandardCharsets.UTF_8.name()));
} else {
urlBuilder.append(value);
}
urlBuilder.append("&");
} catch (UnsupportedEncodingException e) {
throw new ClientException("url参数编码失败", ClientErrorCode.UNKNOWN, e);
}
}
urlBuilder.setLength(urlBuilder.length() - 1);
return urlBuilder.toString();
}
/**
* 获取完整的请求路径
*
* @param path 文件路径
* @return 请求URL
*/
public String getUrl(String path) {
return baseUrl + path;
}
/**
* 发送post请求
*
* @param path 请求地址
* @param body 请求体
* @param headers 请求头
* @param type 请求数据类型
* @param <T> t 返回的数据的类型
* @param <K> k body的类型
* @return t
*/
public <T, K> T post(String path, K body, Map<String, Object> headers, TypeReference<T> type) {
if (StringUtils.isBlank(path)) {
throw new ArgsException("path不能为空");
}
try {
String bodyStr = null;
if (body != null) {
bodyStr = mapper.writeValueAsString(body);
}
InputStream content = apiHttpClient.post(getUrl(path), bodyStr, headers);
return mapper.readValue(content, type);
} catch (IOException e) {
throw new ClientException(e.getMessage(), e);
}
}
/**
* 发起put请求
*
* @param path 请求地址
* @param params 请求参数
* @param body 请求体
* @param headers 请求头
* @param type 请求数据类型
* @param <T> t 返回的数据的类型
* @param <K> k body的类型
* @return 请求返回的数据
*/
public <T, K> T put(String path, Map<String, Object> params, K body, Map<String, Object> headers, TypeReference<T> type) {
if (StringUtils.isBlank(path)) {
throw new ArgsException("path不能为空");
}
try {
String bodyStr = null;
if (body != null) {
bodyStr = mapper.writeValueAsString(body);
}
InputStream content = apiHttpClient.put(getUrl(path), bodyStr, headers);
return mapper.readValue(content, type);
} catch (IOException e) {
throw new ClientException(e.getMessage(), e);
}
}
/**
* 发起put请求
*
* @param path 请求地址
* @param body 请求体
* @param headers 请求头
* @param type 请求数据类型
* @param <T> t 返回的数据的类型
* @param <K> k body的类型
* @return 请求返回的数据
*/
public <T, K> T put(String path, K body, Map<String, Object> headers, TypeReference<T> type) {
return put(path, null, body, headers, type);
}
/**
* 发起put请求
*
* @param path 请求地址
* @param body 请求体
* @param type 请求数据类型
* @param <T> t 返回的数据的类型
* @param <K> k body的类型
* @return 请求返回的数据
*/
public <T, K> T put(String path, K body, TypeReference<T> type) {
return put(path, body, null, type);
}
/**
* @param path 请求地址
* @param body 请求体
* @param type 响应类型
* @param <T> 相应返回数据类型
* @param <K> 请求体数据类型
* @return 响应数据
*/
public <T, K> T post(String path, K body, TypeReference<T> type) {
return post(path, body, null, type);
}
/**
* 发起delete请求
*
* @param path 请求地址
* @param headers 请求头
* @param type 响应类型
* @param <T> 响应数据类型
* @return 响应数据
*/
public <T> T delete(String path, Map<String, Object> headers, TypeReference<T> type) {
if (StringUtils.isBlank(path)) {
throw new ArgsException("path不能为空");
}
try {
InputStream content = apiHttpClient.delete(getUrl(path), headers);
return mapper.readValue(content, type);
} catch (IOException e) {
throw new ClientException(e.getMessage(), e);
}
}
/**
* 发起delete请求
*
* @param path 请求地址
* @param type 响应类型
* @param <T> 响应数据类型
* @return 响应数据
*/
public <T> T delete(String path, TypeReference<T> type) {
return delete(path, null, type);
}
/**
* @param path 请求路径
* @param keyName 文件key
* @param fileName 文件名
* @param is 文件流
* @param headers 请求头
* @param body 请求体其他数据
* @param type 返回数据类型
* @return 请求类型
*/
public ResponseResult<Object> upload(String path,
String keyName,
String fileName,
InputStream is,
Map<String, Object> headers,
Map<String, Object> body,
TypeReference<ResponseResult<Object>> type) {
if (StringUtils.isBlank(path)) {
throw new ArgsException("path不能为空");
}
try {
InputStream content = apiHttpClient.upload(getUrl(path), keyName, fileName, is, body, headers);
return mapper.readValue(content, type);
} catch (IOException e) {
throw new ClientException(e.getMessage(), e);
}
}
public String getAppformServerCurrentTimeMillis() {
try {
long currentTimeMillis = apiHttpClient.getAppformServerCurrentTimeMillis(getUrl(AuthPathConstant.PING));
return String.valueOf(currentTimeMillis);
} catch (IOException e) {
throw new ClientException(e.getMessage(), e);
}
}
}

View File

@@ -0,0 +1,84 @@
package com.jhinno.sdk.openapi.client;
import com.jhinno.sdk.openapi.AuthType;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
/**
* 该接口用户实现发送HTTP请求的方法
*/
public interface JHApiHttpClient {
/**
* 发起一个get请求
*
* @param url 请求url
* @param headers 请求头
* @return 数据流
* @throws IOException io异常
*/
InputStream get(String url, Map<String, Object> headers) throws IOException;
/**
* 发起一个post请求
*
* @param url 请求url
* @param body 请求体
* @param headers 请求头
* @return 数据流
* @throws IOException io异常
*/
InputStream post(String url, String body, Map<String, Object> headers) throws IOException;
/**
* 发起一个put请求
*
* @param url 请求url
* @param body 请求体
* @param headers 请求头
* @return 数据流
* @throws IOException io异常
*/
InputStream put(String url, String body, Map<String, Object> headers) throws IOException;
/**
* 发起一个GET请求
*
* @param url 请求url
* @param headers 请求头
* @return 数据流
* @throws IOException io异常
*/
InputStream delete(String url, Map<String, Object> headers) throws IOException;
/**
* 文件上传
*
* @param url 请求url
* @param keyName 文件key
* @param is 文件流
* @param body 请求体
* @param headers 请求头
* @return 响应
* @throws IOException io异常
*/
InputStream upload(String url, String keyName, String fileName, InputStream is, Map<String, Object> body, Map<String, Object> headers) throws IOException;
/**
* 获取Appform服务器当前的时间
* <p/>
* {@link AuthType#TOKEN_MODE}模式,并且打开了获取服务器时间的开关需要实现改方法
*
* @return 服务器的时间
*/
default long getAppformServerCurrentTimeMillis(String url) throws IOException {
return System.currentTimeMillis();
}
}

View File

@@ -0,0 +1,233 @@
package com.jhinno.sdk.openapi.client;
import com.jhinno.sdk.openapi.ClientErrorCode;
import com.jhinno.sdk.openapi.ClientException;
import com.jhinno.sdk.openapi.CommonConstant;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.*;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.util.Map;
@Data
@NoArgsConstructor
public class JHApiHttpClientImpl implements JHApiHttpClient {
/**
* HTTP的连接客户端
*/
private CloseableHttpClient closeableHttpClient;
/**
* <p>
* 每次发送请求的配置,如果该配置未进行设置则走 {@link DefaultHttpClientConfig 中的默认配置
* </p>
*
* <p>
* {@link JHApiClient 默认只配置了 socket连接超时的时间(socketTimeout) 、连接超时的时间(connectTimeout)、
* 请求超时的时间(connectionRequestTimeout)这三项,其默认配置在{@link DefaultHttpClientConfig 中。
* 如果你要自定义你自己的配置,则可以通过{@link HttpClients 构建自己的RequestConfig来请求接口
* </p>
*
* @param requestConfig HTTP请求的配置
*/
private RequestConfig requestConfig;
/**
* Socket连接超时的时间(单位:毫秒,默认:{@link DefaultHttpClientConfig#SOCKET_TIMEOUT})
*/
private int socketTimeout = DefaultHttpClientConfig.SOCKET_TIMEOUT;
/**
* 连接超时的时间(单位:毫秒,默认:{@link DefaultHttpClientConfig#CONNECT_TIMEOUT})
*/
private int connectTimeout = DefaultHttpClientConfig.CONNECT_TIMEOUT;
/**
* 默认请求超时的时间(单位:毫秒,默认:{@link DefaultHttpClientConfig#CONNECTION_REQUEST_TIMEOUT})
*/
private int connectRequestTimeout = DefaultHttpClientConfig.CONNECTION_REQUEST_TIMEOUT;
/**
* 设置最大连接数(默认:{@link DefaultHttpClientConfig#MAX_TOTAL})
*/
private int maxTotal = DefaultHttpClientConfig.MAX_TOTAL;
/**
* 服务每次能并行接收的请求数量(默认:{@link DefaultHttpClientConfig#MAX_PER_ROUTE})
*/
private int maxPerRoute = DefaultHttpClientConfig.MAX_PER_ROUTE;
/**
* 初始化一个HTTP客户端实例
*
* @return 返回一个可关闭的HTTP客户端示例
*/
public void createHttpClients() {
SSLContextBuilder builder = new SSLContextBuilder();
try {
builder.loadTrustMaterial(null, (x509Certificates, s) -> true);
SSLConnectionSocketFactory sslref = new SSLConnectionSocketFactory(builder.build(), NoopHostnameVerifier.INSTANCE);
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", new PlainConnectionSocketFactory()).register("https", sslref).build();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
cm.setMaxTotal(maxTotal);
cm.setDefaultMaxPerRoute(maxPerRoute);
closeableHttpClient = HttpClients.custom().setSSLSocketFactory(sslref).setConnectionManager(cm).setConnectionManagerShared(true).build();
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
throw new ClientException(e.getMessage(), ClientErrorCode.SSL_EXCEPTION, e);
}
}
/**
* 初始化客户端
*/
public void init() {
this.requestConfig = RequestConfig.custom()
.setSocketTimeout(socketTimeout)
.setConnectTimeout(connectTimeout)
.setConnectionRequestTimeout(connectRequestTimeout)
.build();
}
/**
* 原始发送请求
*
* @param httpRequest 请求体
* @param headers 请求头
* @return 响应体
*/
public HttpEntity request(HttpRequestBase httpRequest, Map<String, Object> headers) {
if (requestConfig == null) {
throw new ClientException("请配置requestConfig");
}
if (httpRequest == null) {
throw new ClientException("httpRequest不能为空");
}
httpRequest.setConfig(requestConfig);
// 添加请求头
if (headers != null && !headers.isEmpty()) {
for (Map.Entry<String, Object> entry : headers.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (value == null) {
continue;
}
httpRequest.setHeader(key, value.toString());
}
}
try {
HttpResponse response = closeableHttpClient.execute(httpRequest);
int statusCode = response.getStatusLine().getStatusCode();
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
httpRequest.releaseConnection();
throw new ClientException("发送HTTP请求失败请求码" + statusCode, ClientErrorCode.REQUEST_ERROR);
}
return response.getEntity();
} catch (IOException e) {
httpRequest.releaseConnection();
throw new ClientException(e.getMessage());
}
}
@Override
public InputStream get(String url, Map<String, Object> headers) throws IOException {
HttpGet httpGet = new HttpGet(url);
return request(httpGet, headers).getContent();
}
@Override
public InputStream post(String url, String body, Map<String, Object> headers) throws IOException {
HttpPost httpPost = new HttpPost(url);
if (StringUtils.isNotBlank(body)) {
httpPost.setEntity(new StringEntity(body, StandardCharsets.UTF_8));
}
return request(httpPost, headers).getContent();
}
@Override
public InputStream put(String url, String body, Map<String, Object> headers) throws IOException {
HttpPut httpPut = new HttpPut(url);
if (StringUtils.isNotBlank(body)) {
httpPut.setEntity(new StringEntity(body, StandardCharsets.UTF_8));
}
return request(httpPut, headers).getContent();
}
@Override
public InputStream delete(String url, Map<String, Object> headers) throws IOException {
HttpDelete httpDelete = new HttpDelete(url);
return request(httpDelete, headers).getContent();
}
@Override
public InputStream upload(String url, String keyName, String fileName, InputStream is, Map<String, Object> body, Map<String, Object> headers) throws IOException {
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setCharset(StandardCharsets.UTF_8);
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody(keyName, is, ContentType.MULTIPART_FORM_DATA, fileName);
if (body != null && !body.isEmpty()) {
for (Map.Entry<String, Object> entry : body.entrySet()) {
builder.addTextBody(entry.getKey(), entry.getValue().toString());
}
}
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(builder.build());
return request(httpPost, headers).getContent();
}
@Override
public long getAppformServerCurrentTimeMillis(String url) throws IOException {
HttpGet httpGet = new HttpGet(url);
httpGet.setConfig(requestConfig);
try {
HttpResponse response = closeableHttpClient.execute(httpGet);
Header header = response.getFirstHeader("Date");
if (header == null) {
throw new ClientException("获取时间戳响应为空!");
}
String value = header.getValue();
if (StringUtils.isBlank(value)) {
throw new ClientException("获取时间戳响应头为空!");
}
return CommonConstant.HTTP_DATETIME_FORMAT.parse(value).getTime();
} catch (ParseException e) {
throw new ClientException("时间格式获取失败,失败原因:" + e.getMessage(), e);
}finally {
httpGet.releaseConnection();
}
}
}

View File

@@ -0,0 +1,48 @@
package com.jhinno.sdk.openapi.utils;
import java.util.Collection;
import java.util.Map;
public class CollectionUtil {
/**
* Map是否为空
*
* @param map 集合
* @return 是否为空
*/
public static boolean isEmpty(Map<?, ?> map) {
return map == null || map.isEmpty();
}
/**
* Map是否为非空
*
* @param map 集合
* @return 是否为非空
*/
public static boolean isNotEmpty(Map<?, ?> map) {
return !isEmpty(map);
}
/**
* Collection是否为空
*
* @param collection 集合
* @return 是否为非空
*/
public static boolean isEmpty(Collection<?> collection) {
return collection == null || collection.isEmpty();
}
/**
* Collection是否为非空
*
* @param collection 集合
* @return 是否为非空
*/
public static boolean isNotEmpty(Collection<?> collection) {
return !isEmpty(collection);
}
}

View File

@@ -0,0 +1,54 @@
package com.jhinno.sdk.openapi.utils;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jhinno.sdk.openapi.CommonConstant;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
public class JsonUtil {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
static {
OBJECT_MAPPER.setTimeZone(TimeZone.getTimeZone("GMT+8"));
OBJECT_MAPPER.setDateFormat(new SimpleDateFormat(CommonConstant.NORM_DATETIME_PATTERN));
OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
@SneakyThrows
public static <T> T stringToObject(String str, Class<T> cls) {
if (StringUtils.isBlank(str)) {
return null;
}
return OBJECT_MAPPER.readValue(str, cls);
}
@SneakyThrows
public static <T> T stringToObject(String str, TypeReference<T> type) {
if (StringUtils.isBlank(str)) {
return null;
}
return OBJECT_MAPPER.readValue(str, type);
}
@SneakyThrows
public static <T> T isToObject(InputStream is, Class<T> cls) {
if (is == null) {
return null;
}
return OBJECT_MAPPER.readValue(is, cls);
}
@SneakyThrows
public static String objectToString(Object object) {
return OBJECT_MAPPER.writeValueAsString(object);
}
}

View File

@@ -0,0 +1,43 @@
package com.jhinno.sdk.openapi.test;
import com.jhinno.sdk.openapi.AuthType;
import com.jhinno.sdk.openapi.JHApiExecutionManage;
import com.jhinno.sdk.openapi.api.app.JHAppApiExecution;
import com.jhinno.sdk.openapi.api.data.JHDataApiExecution;
import com.jhinno.sdk.openapi.api.file.JHFileApiExecution;
import com.jhinno.sdk.openapi.api.job.JHJobApiExecution;
import com.jhinno.sdk.openapi.api.organization.JHDepartmentApiExecution;
import com.jhinno.sdk.openapi.api.organization.JHUserApiExecution;
import com.jhinno.sdk.openapi.client.JHApiClient;
import java.util.HashMap;
import java.util.Map;
/**
* SDK Client 的配置
*
* @author yanlongqi
* @date 2024/2/4 17:11
*/
public class JHClientConfig {
/**
* 创建一个API执行器管理器
*/
public static final JHApiExecutionManage API_EXECUTRON_MANAGE = new JHApiExecutionManage(
"https://192.168.87.24");
public static final String ACCESS_KEY = "e2544957e53b4377bb4f8203a094e50b";
public static final String ACCESS_KEY_SECRET = "52d18cf7163047b78ea48756b8b40d28";
static {
API_EXECUTRON_MANAGE.configureApiExecution(t -> {
// 默认为使用Token模式如何使用的Token模式则不需要配置ACCESS_KEY和ACCESS_KEY SECRET
t.setAuthType(AuthType.ACCESS_SECRET_MODE);
t.setAccessKey(ACCESS_KEY);
t.setAccessKeySecret(ACCESS_KEY_SECRET);
});
}
}

View File

@@ -1,6 +1,5 @@
package com.jhinno.sdk.openapi.test.app; package com.jhinno.sdk.openapi.test.app;
import cn.hutool.core.lang.ConsoleTable;
import com.jhinno.sdk.openapi.api.app.*; import com.jhinno.sdk.openapi.api.app.*;
import com.jhinno.sdk.openapi.test.JHClientConfig; import com.jhinno.sdk.openapi.test.JHClientConfig;
import org.junit.Test; import org.junit.Test;
@@ -17,11 +16,11 @@ import java.util.List;
public class AppApiTest { public class AppApiTest {
/** /**
* 获得一个调用应用接口的执行器 * 获得一个调用应用接口的执行器
*/ */
public static final JHAppApiExecution jhAppApiExecution = new JHAppApiExecution(JHClientConfig.client); public static final JHAppApiExecution jhAppApiExecution = JHClientConfig.API_EXECUTRON_MANAGE
.getApiExecution(JHAppApiExecution.class);
/** /**
* 测测试使用自定义的参数启动jhadmin的Linux桌面 * 测测试使用自定义的参数启动jhadmin的Linux桌面
@@ -43,7 +42,6 @@ public class AppApiTest {
System.out.println(appStartedInfo); System.out.println(appStartedInfo);
} }
/** /**
* 测试获取用户jhadmin的会话列表 * 测试获取用户jhadmin的会话列表
*/ */
@@ -62,13 +60,13 @@ public class AppApiTest {
System.out.println(desktopList); System.out.println(desktopList);
} }
/** /**
* 测试根据会话列表查询会话列表 * 测试根据会话列表查询会话列表
*/ */
@Test @Test
public void testGetDesktopsById() { public void testGetDesktopsById() {
List<SessionInfo> desktopList = jhAppApiExecution.getDesktopsById("jhadmin", Arrays.asList("7649", "7637", "123")); List<SessionInfo> desktopList = jhAppApiExecution.getDesktopsById("jhadmin",
Arrays.asList("7649", "7637", "123"));
System.out.println(desktopList); System.out.println(desktopList);
} }
@@ -81,7 +79,6 @@ public class AppApiTest {
System.out.println(desktopList); System.out.println(desktopList);
} }
/** /**
* 测试会话共享 * 测试会话共享
*/ */
@@ -106,7 +103,6 @@ public class AppApiTest {
jhAppApiExecution.transferOperatorRight("jhadmin", "7649", "123"); jhAppApiExecution.transferOperatorRight("jhadmin", "7649", "123");
} }
/** /**
* 测试链接会话 * 测试链接会话
*/ */
@@ -116,7 +112,6 @@ public class AppApiTest {
System.out.println(appStartedInfo); System.out.println(appStartedInfo);
} }
/** /**
* 测试断开会话的连接 * 测试断开会话的连接
*/ */
@@ -133,16 +128,14 @@ public class AppApiTest {
jhAppApiExecution.disconnectSessionByIds("jhadmin", Arrays.asList("123", "456")); jhAppApiExecution.disconnectSessionByIds("jhadmin", Arrays.asList("123", "456"));
} }
/** /**
* 测试注销会话 * 测试注销会话
*/ */
@Test @Test
public void testDestroySession() { public void testDestroySession() {
jhAppApiExecution.destroySession("jhadmin", "4856"); jhAppApiExecution.destroySession("jhadmin", "63");
} }
/** /**
* 测试批量注销会话 * 测试批量注销会话
*/ */
@@ -157,16 +150,8 @@ public class AppApiTest {
@Test @Test
public void testGetAppList() { public void testGetAppList() {
List<AppInfo> appList = jhAppApiExecution.getAppList("jhadmin"); List<AppInfo> appList = jhAppApiExecution.getAppList("jhadmin");
System.out.println(appList);
ConsoleTable consoleTable = ConsoleTable.create();
consoleTable.setSBCMode(false);
consoleTable.addHeader("id", "name", "type", "category", "protocol");
for (AppInfo appInfo : appList) {
consoleTable.addBody(appInfo.getId(), appInfo.getName(), appInfo.getType(), appInfo.getCategory(), appInfo.getProtocol());
} }
consoleTable.print();
}
/** /**
* 测试获取应用链接 * 测试获取应用链接
@@ -176,4 +161,19 @@ public class AppApiTest {
System.out.println(jhAppApiExecution.getAppUrl("jhadmin", "myjobmana")); System.out.println(jhAppApiExecution.getAppUrl("jhadmin", "myjobmana"));
} }
/**
* 测试根据文件后缀取应用列表
*/
@Test
public void testGetAppInfoSuffixList() {
System.out.println(jhAppApiExecution.getAppInfoSuffixList("test", ".sh"));
}
/**
* 测试根据用途获取应用列表
*/
@Test
public void testGetUseLabelList() {
System.out.println(jhAppApiExecution.getUseLabelList("jhadmin"));
}
} }

View File

@@ -14,7 +14,8 @@ import java.util.Arrays;
*/ */
public class DataApiTest { public class DataApiTest {
public static final JHDataApiExecution execution = new JHDataApiExecution(JHClientConfig.client); public static final JHDataApiExecution execution =JHClientConfig.API_EXECUTRON_MANAGE
.getApiExecution(JHDataApiExecution.class);
/** /**
* 测试获取作业数据区目录列表 * 测试获取作业数据区目录列表

View File

@@ -1,10 +1,10 @@
package com.jhinno.sdk.openapi.test.file; package com.jhinno.sdk.openapi.test.file;
import cn.hutool.core.lang.ConsoleTable;
import com.jhinno.sdk.openapi.api.file.FileInfo; import com.jhinno.sdk.openapi.api.file.FileInfo;
import com.jhinno.sdk.openapi.api.file.JHFileApiExecution; import com.jhinno.sdk.openapi.api.file.JHFileApiExecution;
import com.jhinno.sdk.openapi.test.JHClientConfig; import com.jhinno.sdk.openapi.test.JHClientConfig;
import org.junit.Test; import org.junit.Test;
import java.io.InputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@@ -17,8 +17,8 @@ import java.util.List;
*/ */
public class FileApiTest { public class FileApiTest {
private static final JHFileApiExecution execution = new JHFileApiExecution(JHClientConfig.client); private static final JHFileApiExecution execution = JHClientConfig.API_EXECUTRON_MANAGE
.getApiExecution(JHFileApiExecution.class);
/** /**
* 测试重命名文件或文件夹 * 测试重命名文件或文件夹
@@ -44,20 +44,13 @@ public class FileApiTest {
execution.copyFile("lqyan", "/apps/JHDP/lqyan/PSUserService.class", "/apps/JHDP/lqyan/temp"); execution.copyFile("lqyan", "/apps/JHDP/lqyan/PSUserService.class", "/apps/JHDP/lqyan/temp");
} }
/** /**
* 测试获取文件列表 * 测试获取文件列表
*/ */
@Test @Test
public void testGetFileList() { public void testGetFileList() {
List<FileInfo> fileList = execution.getFileList("lqyan", "$HOME"); List<FileInfo> fileList = execution.getFileList("jhadmin", "$HOME");
ConsoleTable consoleTable = ConsoleTable.create(); System.out.println(fileList);
consoleTable.setSBCMode(false);
consoleTable.addHeader("fileName", "fileType", "owner", "read", "write", "execute", "path");
for (FileInfo fileInfo : fileList) {
consoleTable.addBody(fileInfo.getFileName(), fileInfo.getFileType(), fileInfo.getOwner(), fileInfo.getRead().toString(), fileInfo.getWrite().toString(), fileInfo.getExecute().toString(), fileInfo.getPath());
}
consoleTable.print();
} }
/** /**
@@ -65,10 +58,9 @@ public class FileApiTest {
*/ */
@Test @Test
public void testMkdir() { public void testMkdir() {
System.out.println(execution.mkdir("jhadmin", "$HOME/test", true)); System.out.println(execution.mkdir("jhadmin", "$HOMEtest1", true));
} }
/** /**
* 新建文件夹不强制新建 * 新建文件夹不强制新建
*/ */
@@ -77,7 +69,6 @@ public class FileApiTest {
System.out.println(execution.mkdir("lqyan", "/apps/JHDP/lqyan/temp/bbb/ddd")); System.out.println(execution.mkdir("lqyan", "/apps/JHDP/lqyan/temp/bbb/ddd"));
} }
/** /**
* 测试新建文件接口执行失败 * 测试新建文件接口执行失败
*/ */
@@ -86,26 +77,35 @@ public class FileApiTest {
System.out.println(execution.mkFile("lqyan", "/apps/JHDP/lqyan/temp/ddd.txt")); System.out.println(execution.mkFile("lqyan", "/apps/JHDP/lqyan/temp/ddd.txt"));
} }
/** /**
* 测试文件上传 (是否覆盖存在问题) * 测试文件上传 (是否覆盖存在问题)
*/ */
@Test @Test
public void testUploadFile() throws IOException { public void testUploadFile() throws IOException {
File file = new File("C:\\Users\\yanlongqi\\Desktop\\双色球.xls"); File file = new File("C:\\Users\\yanlongqi\\Desktop\\LdapAdminv1830.exe");
FileInputStream fileInputStream = new FileInputStream(file); FileInputStream fileInputStream = new FileInputStream(file);
execution.uploadFile("jhadmin", fileInputStream, file.getName(), "$HOME/temp", true); execution.uploadFile("jhadmin", fileInputStream, file.getName(), "$HOME", true);
} }
/** /**
* 测试上传文件不覆盖源文件如果isCover是true上传后的文件有数字下标 * 测试上传文件不覆盖源文件如果isCover是true上传后的文件有数字下标
*/ */
@Test @Test
public void testUploadFileNoCover() throws IOException { public void testUploadFileNoCover() throws IOException {
File file = new File("C:\\Users\\yanlongqi\\Desktop\\双色球.xls"); File file = new File("C:\\Users\\yanlongqi\\Desktop\\Hash.exe");
FileInputStream fileInputStream = new FileInputStream(file); FileInputStream fileInputStream = new FileInputStream(file);
execution.uploadFile("jhadmin", fileInputStream, file.getName(), "$HOME/temp"); execution.uploadFile("lqyan", fileInputStream, file.getName(), "$HOME/temp");
}
/**
* 测试上传文件开启密级的情况
*/
@Test
public void testUploadFileConf() throws IOException {
File file = new File("C:\\Users\\yanlongqi\\Desktop\\Hash.exe");
FileInputStream fileInputStream = new FileInputStream(file);
execution.uploadFile("lqyan", fileInputStream, file.getName(), "$HOME/temp111", false,"public");
} }
/** /**
@@ -116,13 +116,20 @@ public class FileApiTest {
System.out.println(execution.getFileDownloadUrl("jhadmin", "$HOME/aa2a.sh")); System.out.println(execution.getFileDownloadUrl("jhadmin", "$HOME/aa2a.sh"));
} }
@Test
public void testGetFileStream() throws IOException {
InputStream in = execution.getFileInputStream("jhadmin", "$HOME/aaa.sh");
byte[] bytes = new byte[1024];
while (in.read(bytes) != -1) {
System.out.println(new String(bytes));
}
}
@Test @Test
public void testCompress() { public void testCompress() {
execution.compress("jhadmin", "$HOME/temp", "$HOME/temp.zip"); execution.compress("jhadmin", "$HOME/temp", "$HOME/temp.zip");
} }
@Test @Test
public void testUncompress() { public void testUncompress() {
execution.uncompress("jhadmin", "$HOME/temp.zip", "$HOME/test"); execution.uncompress("jhadmin", "$HOME/temp.zip", "$HOME/test");

View File

@@ -1,9 +1,6 @@
package com.jhinno.sdk.openapi.test.job; package com.jhinno.sdk.openapi.test.job;
import com.jhinno.sdk.openapi.api.job.JHJobApiExecution; import com.jhinno.sdk.openapi.api.job.*;
import com.jhinno.sdk.openapi.api.job.JobHistoryInfo;
import com.jhinno.sdk.openapi.api.job.JobStatusEnum;
import com.jhinno.sdk.openapi.api.job.PageJobInfo;
import com.jhinno.sdk.openapi.test.JHClientConfig; import com.jhinno.sdk.openapi.test.JHClientConfig;
import org.junit.Test; import org.junit.Test;
@@ -20,7 +17,8 @@ import java.util.Map;
*/ */
public class JobApiTest { public class JobApiTest {
private static final JHJobApiExecution execution = new JHJobApiExecution(JHClientConfig.client); private static final JHJobApiExecution execution = JHClientConfig.API_EXECUTRON_MANAGE
.getApiExecution(JHJobApiExecution.class);
/** /**
* 测试提交作业 * 测试提交作业
@@ -33,7 +31,6 @@ public class JobApiTest {
System.out.println(execution.submit("jhadmin", "common_sub", params)); System.out.println(execution.submit("jhadmin", "common_sub", params));
} }
/** /**
* 测试根据作业id查询作业文件列表 * 测试根据作业id查询作业文件列表
*/ */
@@ -42,14 +39,22 @@ public class JobApiTest {
System.out.println(execution.getJobFilesById("jhadmin", "42")); System.out.println(execution.getJobFilesById("jhadmin", "42"));
} }
/** /**
* 测试分页查询作业列表 * 测试分页查询作业列表
*/ */
@Test @Test
public void testGetJobPage() { public void testGetJobPage() {
PageJobInfo jhadmin = execution.getJobPage("jhadmin", 1, 5, null, JobStatusEnum.DONE, null); PageJobInfo pages = execution.getJobPage("jhadmin", 1, 5, null, JobStatusEnum.DONE, null);
System.out.println(jhadmin); System.out.println(pages);
}
/**
* 测试查询历史作业列表
*/
@Test
public void testGetHistoryJobs() {
PageJobInfo pages = execution.getHistoryJobs("jhadmin", 1, 5, null, JobStatusEnum.DONE, null);
System.out.println(pages);
} }
/** /**
@@ -60,7 +65,6 @@ public class JobApiTest {
System.out.println(execution.getJobDetail("jhadmin", "42")); System.out.println(execution.getJobDetail("jhadmin", "42"));
} }
/** /**
* 测试使用作业名称检索 * 测试使用作业名称检索
*/ */
@@ -77,7 +81,6 @@ public class JobApiTest {
System.out.println(execution.getJobsByStatus("jhadmin", JobStatusEnum.DONE, 1, 10)); System.out.println(execution.getJobsByStatus("jhadmin", JobStatusEnum.DONE, 1, 10));
} }
/** /**
* 测试使用作业拆id列表查询作业 * 测试使用作业拆id列表查询作业
*/ */
@@ -86,7 +89,6 @@ public class JobApiTest {
System.out.println(execution.getJobsByIds("jhadmin", Arrays.asList("42", "41"))); System.out.println(execution.getJobsByIds("jhadmin", Arrays.asList("42", "41")));
} }
/** /**
* 测试查询作业历史 * 测试查询作业历史
*/ */
@@ -96,7 +98,6 @@ public class JobApiTest {
System.out.println(result); System.out.println(result);
} }
/** /**
* 测试通过多个子哦也好查询作业历史 * 测试通过多个子哦也好查询作业历史
*/ */
@@ -115,7 +116,6 @@ public class JobApiTest {
System.out.println("peek = " + peek); System.out.println("peek = " + peek);
} }
/** /**
* 测试会话连接目前没有测试条件 * 测试会话连接目前没有测试条件
*/ */
@@ -125,4 +125,13 @@ public class JobApiTest {
System.out.println(o); System.out.println(o);
} }
/**
* 测试获取作业表单
*/
@Test
public void testGetSimulationAppForm() {
List<JobAppFormItemInfo> simulationAppForm = execution.getSimulationAppForm("jhadmin", "common_sub");
System.out.println(simulationAppForm);
}
} }

View File

@@ -13,7 +13,8 @@ import org.junit.Test;
*/ */
public class DepartmentApiTest { public class DepartmentApiTest {
private static final JHDepartmentApiExecution execution = new JHDepartmentApiExecution(JHClientConfig.client); private static final JHDepartmentApiExecution execution = JHClientConfig.API_EXECUTRON_MANAGE
.getApiExecution(JHDepartmentApiExecution.class);
/** /**

View File

@@ -15,7 +15,8 @@ import org.junit.Test;
*/ */
public class UserApiTest { public class UserApiTest {
private static final JHUserApiExecution execution = new JHUserApiExecution(JHClientConfig.client); private static final JHUserApiExecution execution = JHClientConfig.API_EXECUTRON_MANAGE
.getApiExecution(JHUserApiExecution.class);
/** /**

View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cim.jhinno</groupId>
<artifactId>jhinno-openapi-sdk-spring-boot-example</artifactId>
<version>2.0.5</version>
<packaging>jar</packaging>
<name>Jhinno OpenAPI SDK for Java SpringBoot Example</name>
<description>The Jhinno OpenAPI SDK for Java used for accessing Jhinno OpenApi Service</description>
<url>http://jhinno.com</url>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
</parent>
<dependencies>
<dependency>
<groupId>com.jhinno</groupId>
<artifactId>jhinno-openapi-sdk-spring-boot-starter</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
</plugins>
</build>
<developers>
<developer>
<id>lqyan</id>
<name>lqyan</name>
<email>lqyan@jhinno.com</email>
</developer>
</developers>
<licenses>
<license>
<name>The Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
</project>

View File

@@ -0,0 +1,13 @@
package com.jhinno.sdk.openapi.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ExampleApplication {
public static void main(String[] args) {
SpringApplication.run(ExampleApplication.class, args);
}
}

View File

@@ -0,0 +1,19 @@
package com.jhinno.sdk.openapi.example.api.extend;
public enum FileEnvType {
HOME_ENV{
@Override
public String getEnv() {
return "home";
}
},
SPOOLER_ENV{
@Override
public String getEnv() {
return "spooler";
}
};
public abstract String getEnv();
}

View File

@@ -0,0 +1,13 @@
package com.jhinno.sdk.openapi.example.api.extend;
import lombok.Data;
@Data
public class FilePath {
/**
* 文件路径
*/
private String path;
}

View File

@@ -0,0 +1,24 @@
package com.jhinno.sdk.openapi.example.api.extend;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum FileSystemType {
SYSTEM_TYPE_LINUX {
@Override
public String getType() {
return "linux";
}
},
SYSTEM_TYPE_WINDOWS {
@Override
public String getType() {
return "windows";
}
};
public abstract String getType();
}

View File

@@ -0,0 +1,40 @@
package com.jhinno.sdk.openapi.example.api.extend;
import com.fasterxml.jackson.core.type.TypeReference;
import com.jhinno.sdk.openapi.JHApiExecution;
import com.jhinno.sdk.openapi.api.JHRequestExecution;
import com.jhinno.sdk.openapi.api.ResponseResult;
import com.jhinno.sdk.openapi.client.JHApiClient;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
public class JHFileApiExtendExecution implements JHApiExecution {
private JHRequestExecution execution;
@Override
public void init(JHRequestExecution execution) {
this.execution = execution;
}
public static String GET_FILE_ENV_PATH = "/appform/ws/api/files/path/{env}";
public FilePath getFileEnvPath(String username, FileEnvType env, FileSystemType type) {
Map<String, Object> params = new HashMap<>(1);
if (StringUtils.isNotBlank(type.getType())) {
params.put("type", type.getType());
}
String url = JHApiClient.getUrl(GET_FILE_ENV_PATH.replace("{env}", env.getEnv()), params);
return execution.get(url, username, new TypeReference<ResponseResult<FilePath>>() {
});
}
public FilePath getFileHomeEnvPath(String username, FileSystemType type) {
return getFileEnvPath(username, FileEnvType.HOME_ENV, type);
}
}

View File

@@ -0,0 +1,6 @@
jhinno:
openapi:
server-url: https://192.168.0.22
auth-type: token_mode
access-key: 3f03747f147942bd8debd81b6c9c6a80
access-key-secret: e0681859b91c499eb1d2c8e09cea3242

View File

@@ -0,0 +1,29 @@
package com.jhinno.sdk.openapi.example.test.extend;
import com.jhinno.sdk.openapi.example.api.extend.FileSystemType;
import com.jhinno.sdk.openapi.example.api.extend.JHFileApiExtendExecution;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.jhinno.sdk.openapi.api.app.JHAppApiExecution;
@SpringBootTest
public class JHFileApiExtendTest {
@Autowired
private JHFileApiExtendExecution jhFileApiExtendExecution;
@Autowired
private JHAppApiExecution jhAppApiExecution;
@Test
void testGetFileHomeEnvPath() {
System.out.println(jhFileApiExtendExecution.getFileHomeEnvPath("jhadmin", FileSystemType.SYSTEM_TYPE_LINUX));
}
@Test
void testStartApp() {
jhAppApiExecution.desktopStart("jhadmin","linux_desktop");
}
}

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>jhinno-openapi-sdk-spring-boot-starter</artifactId>
<version>2.0.5</version>
<packaging>jar</packaging>
<name>Jhinno OpenAPI SDK for Java SpringBoot Starter</name>
<description>The Jhinno OpenAPI SDK for Java used for accessing Jhinno OpenApi Service</description>
<url>http://jhinno.com</url>
<parent>
<groupId>com.jhinno</groupId>
<artifactId>jhinno-openapi-java-sdk-parent</artifactId>
<version>2.0.5</version>
</parent>
<dependencies>
<dependency>
<groupId>com.jhinno</groupId>
<artifactId>jhinno-openapi-java-sdk</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,50 @@
package com.jhinno.sdk.openapi.autoconfigure;
import com.jhinno.sdk.openapi.api.JHRequestExecution;
import com.jhinno.sdk.openapi.client.JHApiClient;
import com.jhinno.sdk.openapi.client.JHApiHttpClientImpl;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* openapi客户端自动配置
*
* @author yanlongqi
* @date 2024/6/4 16:01
*/
@Configuration
@EnableConfigurationProperties(JHOpenapiProperties.class)
public class JHOpenapiClientAutoConfigure {
@Bean
@ConditionalOnMissingBean
public JHApiClient jhApiClient(JHOpenapiProperties properties) {
JHApiClient jhApiClient = new JHApiClient(properties.getServerUrl());
JHApiHttpClientImpl jhApiHttpClient = new JHApiHttpClientImpl();
jhApiHttpClient.setMaxPerRoute(properties.getMaxPerRout());
jhApiHttpClient.setSocketTimeout(properties.getSocketTimeout());
jhApiHttpClient.setMaxTotal(properties.getMaxTotal());
jhApiHttpClient.setConnectTimeout(properties.getConnectTimeout());
jhApiHttpClient.setConnectRequestTimeout(properties.getConnectRequestTimeout());
jhApiHttpClient.init();
jhApiHttpClient.createHttpClients();
jhApiClient.setApiHttpClient(jhApiHttpClient);
return jhApiClient;
}
@Bean
public JHRequestExecution requestExecution(JHApiClient jhApiClient, JHOpenapiProperties properties) {
JHRequestExecution requestExecution = new JHRequestExecution(jhApiClient);
requestExecution.setForceGetToken(properties.isForceGetToken());
requestExecution.setAuthType(properties.getAuthType());
requestExecution.setAccessKey(properties.getAccessKey());
requestExecution.setAccessKeySecret(properties.getAccessKeySecret());
requestExecution.setTokenTimeout(properties.getTokenTimeout());
requestExecution.setTokenResidueTime(properties.getTokenResidueTime());
requestExecution.setUsedServerTime(properties.isUsedServerTime());
return requestExecution;
}
}

View File

@@ -0,0 +1,66 @@
package com.jhinno.sdk.openapi.autoconfigure;
import com.jhinno.sdk.openapi.JHApiExecution;
import com.jhinno.sdk.openapi.api.JHRequestExecution;
import com.jhinno.sdk.openapi.api.app.JHAppApiExecution;
import com.jhinno.sdk.openapi.api.data.JHDataApiExecution;
import com.jhinno.sdk.openapi.api.file.JHFileApiExecution;
import com.jhinno.sdk.openapi.api.job.JHJobApiExecution;
import com.jhinno.sdk.openapi.api.organization.JHDepartmentApiExecution;
import com.jhinno.sdk.openapi.api.organization.JHUserApiExecution;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* openapi执行器自动配置
*
* @author yanlongqi
* @date 2024/6/4 17:27
*/
@Configuration
@RequiredArgsConstructor
public class JHOpenapiExecutionAutoconfigure implements BeanPostProcessor {
private final JHRequestExecution jhRequestExecution;
public Object postProcessBeforeInitialization(Object bean, String beanName) {
if (bean instanceof JHApiExecution) {
((JHApiExecution) bean).init(jhRequestExecution);
}
return bean;
}
@Bean
public JHAppApiExecution appApiExecution() {
return new JHAppApiExecution();
}
@Bean
public JHDataApiExecution dataApiExecution() {
return new JHDataApiExecution();
}
@Bean
public JHFileApiExecution fileApiExecution() {
return new JHFileApiExecution();
}
@Bean
public JHJobApiExecution jobApiExecution() {
return new JHJobApiExecution();
}
@Bean
public JHDepartmentApiExecution departmentApiExecution() {
return new JHDepartmentApiExecution();
}
@Bean
public JHUserApiExecution userApiExecution() {
return new JHUserApiExecution();
}
}

View File

@@ -0,0 +1,87 @@
package com.jhinno.sdk.openapi.autoconfigure;
import com.jhinno.sdk.openapi.AuthType;
import com.jhinno.sdk.openapi.client.DefaultHttpClientConfig;
import com.jhinno.sdk.openapi.constant.CommonConstants;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author yanlongqi
* @date 2024/6/4 16:03
*/
@Data
@ConfigurationProperties(prefix = CommonConstants.CONFIG_PREFIX)
public class JHOpenapiProperties {
/**
* 接口服务的BaseURL, 列如https://192.168.87.20
*/
private String serverUrl;
/**
* 设置连接池的最大连接数,默认{@link DefaultHttpClientConfig#MAX_TOTAL}
*/
private int maxTotal = DefaultHttpClientConfig.MAX_TOTAL;
/**
* 设置服务每次能并行接收的请求数量,默认{@link DefaultHttpClientConfig#MAX_PER_ROUTE}
*/
private int maxPerRout = DefaultHttpClientConfig.MAX_PER_ROUTE;
/**
* 设置服务socket连接超时的时间(单位:毫秒),默认{@link DefaultHttpClientConfig#SOCKET_TIMEOUT}
*/
private int socketTimeout = DefaultHttpClientConfig.SOCKET_TIMEOUT;
/**
* 设置服务连接超时的时间(单位:毫秒),默认{@link DefaultHttpClientConfig#CONNECT_TIMEOUT}
*/
private int connectTimeout = DefaultHttpClientConfig.CONNECT_TIMEOUT;
/**
* 设置服务请求超时的时间(单位:毫秒),默认{@link DefaultHttpClientConfig#CONNECTION_REQUEST_TIMEOUT}
*/
private int connectRequestTimeout = DefaultHttpClientConfig.CONNECTION_REQUEST_TIMEOUT;
/**
* token的超时时间单位分钟
*/
private int tokenTimeout = DefaultHttpClientConfig.DEFAULT_TOKEN_EFFECTIVE_TIME;
/**
* token提前获取的时间单位分钟
*/
private int tokenResidueTime = DefaultHttpClientConfig.DEFAULT_TOKEN_RESIDUE_TIME;
/**
* 是否使用服务器时间
*/
private boolean usedServerTime = DefaultHttpClientConfig.DEFAULT_IS_USED_SERVER_TIME;
/**
* 是否强制获取用户的token默认{@link DefaultHttpClientConfig#DEFAULT_IS_FORCE_GET_TOKEN},
* 如果强制获取token则每次请求都去获取token
*/
private boolean isForceGetToken = DefaultHttpClientConfig.DEFAULT_IS_FORCE_GET_TOKEN;
/**
* 接口请求的认证类型
*/
private AuthType authType = AuthType.ACCESS_SECRET_MODE;
/**
* 访问密钥
*/
private String accessKey;
/**
* 访问密钥密码
*/
private String accessKeySecret;
}

View File

@@ -0,0 +1,14 @@
package com.jhinno.sdk.openapi.constant;
/**
* @author yanlongqi
* @date 2024/6/4 16:12
*/
public class CommonConstants {
/**
* 配置的前缀
*/
public static final String CONFIG_PREFIX = "jhinno.openapi";
}

View File

@@ -0,0 +1,3 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.jhinno.sdk.openapi.autoconfigure.JHOpenapiClientAutoConfigure,\
com.jhinno.sdk.openapi.autoconfigure.JHOpenapiExecutionAutoconfigure

View File

@@ -0,0 +1,2 @@
com.jhinno.sdk.openapi.autoconfigure.JHOpenapiClientAutoConfigure
com.jhinno.sdk.openapi.autoconfigure.JHOpenapiExecutionAutoconfigure

203
pom.xml
View File

@@ -5,12 +5,12 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.jhinno</groupId> <groupId>com.jhinno</groupId>
<artifactId>jhinno-openapi-java-sdk</artifactId> <artifactId>jhinno-openapi-java-sdk-parent</artifactId>
<version>1.0.0</version> <version>2.0.5</version>
<packaging>jar</packaging> <packaging>pom</packaging>
<name>Jhinno OpenAPI SDK for Java</name> <name>Jhinno OpenAPI SDK for Java parent</name>
<description>The Jhinno OpenAPI SDK for Java used for accessing Jhinno OpenApi Service</description> <description>The Jhinno OpenAPI SDK for Java used for accessing Jhinno OpenApi Service</description>
<url>http://jhinno.com</url> <url>https://github.com/yanlongqi/jhinno-openapi-java-sdk</url>
<properties> <properties>
@@ -21,143 +21,86 @@
<maven.test.skip>true</maven.test.skip> <maven.test.skip>true</maven.test.skip>
</properties> </properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
</parent>
<dependencies> <modules>
<dependency> <module>jhinno-openapi-java-sdk</module>
<groupId>org.apache.commons</groupId> <module>jhinno-openapi-sdk-spring-boot-starter</module>
<artifactId>commons-lang3</artifactId> </modules>
<version>3.13.0</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
<exclusions>
<exclusion>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.15.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.25</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<distributionManagement>
<repository>
<id>jhinno-releases</id>
<url>http://192.168.87.22:8081/repository/maven-releases</url>
</repository>
</distributionManagement>
<build> <build>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.2</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
</plugin>
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>1.18.0.0</version>
<configuration>
<encoding>UTF-8</encoding>
<sourceDirectory>src/main/java</sourceDirectory>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<configuration>
<sourcepath>target/generated-sources/delombok</sourcepath>
<encoding>${project.build.sourceEncoding}</encoding>
<docencoding>${project.build.sourceEncoding}</docencoding>
<charset>${project.build.sourceEncoding}</charset>
<doclint>none</doclint>
<tags>
<tag>
<name>date</name>
<placement>X</placement>
</tag>
</tags>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId> <artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version> <version>3.1.0</version>
<executions> <executions>
<execution> <execution>
<id>attach-sources</id> <phase>package</phase>
<goals> <goals>
<goal>jar-no-fork</goal> <goal>jar-no-fork</goal>
</goals> </goals>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<show>private</show>
<nohelp>true</nohelp>
<charset>UTF-8</charset>
<encoding>UTF-8</encoding>
<docencoding>UTF-8</docencoding>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
<configuration>
<gpgArguments>
<arg>--pinentry-mode</arg>
<arg>loopback</arg>
</gpgArguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonatype.central</groupId>
<artifactId>central-publishing-maven-plugin</artifactId>
<version>0.7.0</version>
<extensions>true</extensions>
<configuration>
<publishingServerId>central</publishingServerId>
<autoPublish>true</autoPublish>
</configuration>
</plugin>
</plugins> </plugins>
</build> </build>
<developers> <developers>
<developer> <developer>
<id>lqyan</id> <id>lqyan</id>
@@ -173,4 +116,16 @@
</license> </license>
</licenses> </licenses>
<issueManagement>
<system>github</system>
<url>https://github.com/yanlongqi/jhinno-openapi-java-sdk/issues</url>
</issueManagement>
<scm>
<connection>scm:git:https://github.com/yanlongqi/jhinno-openapi-java-sdk.git</connection>
<developerConnection>scm:git:https://github.com/yanlongqi/jhinno-openapi-java-sdk.git</developerConnection>
<url>https://github.com/yanlongqi/jhinno-openapi-java-sdk</url>
</scm>
</project> </project>

View File

@@ -1,40 +0,0 @@
package com.jhinno.sdk.openapi;
/**
* @author yanlongqi
* @date 2024/1/31 10:17
*/
public class CommonConstant {
/**
* 请求成功时的标识
*/
public static final String SUCCESS = "success";
/**
* 请求失败时的标识
*/
public static final String FAILED = "failed";
/**
* 默认的token有效时间单位分钟
*/
public static final int DEFAULT_TOKEN_EFFECTIVE_TIME = 30;
/**
* token 默认剩余时间
*/
public static final int DEFAULT_TOKEN_RESIDUE_TIME = 5;
/**
* 获取token时AES加密的默认key
*/
public static final String DEFAULT_AES_KEY = "jin5no@aqec8gtw6";
/**
* 字符逗号
*/
public static final String NORMAL_CHARACTER_COMMA = ",";
}

View File

@@ -1,94 +0,0 @@
package com.jhinno.sdk.openapi.api.app;
/**
* 关于会话请求路径的path
*
* @author yanlongqi
* @date 2024/2/1 16:27
*/
public class AppPathConstant {
/**
* 申请会话
*/
public static final String APPS_START_PATH = "/ws/api/apps/{appId}/start";
/**
* 查询会列表
*/
public static final String APPS_SESSIONS_ALL_PATH = "/ws/api/apps/sessions/all";
/**
* 使用参数查询会话列表
*/
public static final String APPS_SESSIONS_PATH = "/ws/api/apps/sessions";
/**
* 根据会话id列表查询会话列表
*/
public static final String APPS_SESSIONS_IDS_PATH = "/ws/api/apps/listBySessionIds";
/**
* 根据会话名称查询会话列表
*/
public static final String APPS_SESSIONS_NAME_PATH = "/ws/api/apps/listBySessionName";
/**
* 会话共享
*/
public static final String APPS_SESSIONS_SHARE_PATH = "/ws/api/apps/sessions/{sessionId}/share";
/**
* 取消会话共享
*/
public static final String APPS_SESSIONS_CANCEL_SHARE_PATH = "/ws/api/apps/sessions/{sessionId}/share_cancel";
/**
* 传递会话的操作权
*/
public static final String APPS_SESSIONS_OPERATION_TRANSFER_PATH = "/ws/api/apps/sessions/{sessionId}/operation_transfer";
/**
* 连接会话
*/
public static final String APPS_SESSIONS_CONNECT_JHAPP_PATH = "/ws/api/apps/sessions/{sessionId}/connect";
/**
* 断开会话连接(作业/应用)
*/
public static final String APPS_SESSIONS_DISCONNECT_PATH = "/ws/api/apps/sessions/{sessionId}/disconnect";
/**
* 批量断开会话
*/
public static final String APPS_SESSIONS_DISCONNECT_IDS_PATH = "/ws/api/apps/sessions/disconnect";
/**
* 注销会话
*/
public static final String APPS_SESSIONS_DESTROY_PATH = "/ws/api/apps/sessions/{sessionId}/close";
/**
* 批量注销会话
*/
public static final String APPS_SESSIONS_DESTROY_IDS_PATH = "/ws/api/apps/sessions/close";
/**
* 查询应用列表
*/
public static final String APPS_LIST_PATH = "/ws/api/apps";
/**
* 获取应用链接URL
*/
public static final String APPS_GET_URL_PATH = "/ws/api/apps/{appName}/url";
}

View File

@@ -1,28 +0,0 @@
package com.jhinno.sdk.openapi.api.auth;
/**
* 鉴权相关接口路径
*
* @author yanlongqi
* @date 2024/1/29 10:32
*/
public class AuthPathConstant {
/**
* 获取用户token
*/
public static final String AUTH_TOKEN_PATH = "/ws/api/auth/token";
/**
* 注销token
*/
public static final String AUTH_LOGOUT = "/ws/api/auth/logout";
/**
* 用户注册
*/
public static final String AUTH_REGISTER = "/ws/api/auth/register";
}

View File

@@ -1,53 +0,0 @@
package com.jhinno.sdk.openapi.api.file;
import lombok.Data;
/**
* 文件信息
*
* @author yanlongqi
* @date 2024/2/5 10:47
*/
@Data
public class FileInfo {
/**
* 文件名
*/
private String fileName;
/**
* 文件路径
*/
private String path;
/**
* 文件类型
* <ul>
* <li>directory文件夹</li>
* <li>file文件</li>
* </ul>
*/
private String fileType;
/**
* 文件属主
*/
private String owner;
/**
* 是否可读
*/
private Boolean read;
/**
* 是否可写
*/
private Boolean write;
/**
* 是否可执行
*/
private Boolean execute;
}

View File

@@ -1,67 +0,0 @@
package com.jhinno.sdk.openapi.api.file;
/**
* 文件请求路径
*
* @author yanlongqi
* @date 2024/2/4 18:59
*/
public class FilePathConstant {
/**
* 重命名文件
*/
public static final String FILE_RENAME_PATH = "/ws/api/files/rename";
/**
* 删除文件
*/
public static final String FILE_DELETE_PATH = "/ws/api/files/delete";
/**
* 拷贝文件
*/
public static final String FILE_COPY_PATH = "/ws/api/files/copy";
/**
* 获取文件列表
*/
public static final String FILE_LIST_PATH = "/ws/api/files";
/**
* 创建文件夹
*/
public static final String FILE_MKDIR_PATH = "/ws/api/files/mkdir";
/**
* 创建文件
*/
public static final String FILE_MKFILE_PATH = "/ws/api/files/mkfile";
/**
* 文件上传
*/
public static final String FILE_UPLOAD_PATH = "/ws/api/files/upload";
/**
* 文件下载
*/
public static final String FILE_DOWNLOAD_PATH = "/ws/api/files/download";
/**
* 压缩文件
*/
public static final String FILE_COMPRESS_PATH = "/ws/api/files/compress";
/**
* 解压文件
*/
public static final String FILE_UNCOMPRESS_PATH = "/ws/api/files/uncompress";
}

View File

@@ -1,85 +0,0 @@
package com.jhinno.sdk.openapi.api.job;
/**
* 作业相关接口路径
*
* @author yanlongqi
* @date 2024/2/5 18:44
*/
public class JobPathConstant {
/**
* 提交作业
*/
public static final String JOB_SUBMIT_PATH = "/ws/api/jobs/jsub";
/**
* 使用作业id查询作业列表
*/
public static final String JOB_FIND_JOB_FILES_PATH = "/ws/api/jobs/{jobId}/files";
/**
* 分页查询作业列表
*/
public static final String JOB_PAGE_PATH = "/ws/api/jobs/page";
/**
* 查询作业详情
*/
public static final String JOB_DETAIL_INFO_PATH = "/ws/api/jobs/{jobId}";
/**
* 分页检索作业名
*/
public static final String JOB_LIST_BY_NAME_PATH = "/ws/api/jobs/byName";
/**
* 作业号检索作业列表
*/
public static final String JOB_LIST_BY_STATUS_PATH = "/ws/api/jobs/byStatus/{status}";
/**
* 通过作业号查询作业列表
*/
public static final String JOB_LIST_BY_IDS_PATH = "/ws/api/jobs/list";
/**
* 作业操作
*/
public static final String JOB_ACTION_PATH = "/ws/api/jobs/{jobId}/{action}";
/**
* 批量操作作业
*/
public static final String JOB_ACTION_IDS_PATH = "/ws/api/jobs/{action}";
/**
* 获取作业历史
*/
public static final String JOB_HISTORY_PATH = "/ws/api/jobs/{jobId}/hist";
/**
* 通过多个作业号查询作业历史
*/
public static final String JOB_HISTORY_IDS_PATH = "/ws/api/jobs/hist";
/**
* 获取作业动态输出
*/
public static final String JOB_PEEK_PATH = "/ws/api/jobs/{jobId}/peek";
/**
* 连接作业会话
*/
public static final String JOB_CONNECT_SESSION_PATH = "/ws/api/jobs/{jobId}/connect";
}

View File

@@ -1,36 +0,0 @@
package com.jhinno.sdk.openapi.client;
/**
* 默认的HTTP客户端请求配置
*
* @author yanlongqi
* @date 2024/1/30 18:12
*/
public class DefaultHttpClientConfig {
/**
* 默认设置最大连接数
*/
public static int MAX_TOTAL = 200;
/**
* 默认服务每次能并行接收的请求数量
*/
public static int MAX_PER_ROUT = 20;
/**
* 默认socket连接超时的时间(单位:秒)
*/
public static final int SOCKET_TIMEOUT = 5000;
/**
* 默认连接超时的时间(单位:秒)
*/
public static final int CONNECT_TIMEOUT = 5000;
/**
* 默认请求超时的时间(单位:秒)
*/
public static final int CONNECTION_REQUEST_TIMEOUT = 5000;
}

View File

@@ -1,441 +0,0 @@
package com.jhinno.sdk.openapi.client;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jhinno.sdk.openapi.ArgsException;
import com.jhinno.sdk.openapi.ClientErrorCode;
import com.jhinno.sdk.openapi.ClientException;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.*;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.TimeZone;
/**
* 提供请求的工具
*
* @author yanlongqi
* @date 2024/1/29 10:31
*/
public class JHApiClient {
/**
* 基础的请求URL地址
* <p>
* 如:<a href="https://192.168.3.12/appform">https://192.168.3.12/appform</a>
* </p>
*/
private final String baseUrl;
/**
* 对象转换器
*/
private ObjectMapper mapper;
/**
* 初始化一个JHApiClient的实例可使用自定义的客户端
*
* @param baseUrl 景行接口服务的基础地址
* @param closeableHttpClient 可关闭的HTTP客户端
*/
private JHApiClient(CloseableHttpClient closeableHttpClient, String baseUrl) {
this.baseUrl = baseUrl.endsWith("/") ? baseUrl.substring(0, baseUrl.length() - 1) : baseUrl;
this.closeableHttpClient = closeableHttpClient;
this.requestConfig = RequestConfig.custom().setSocketTimeout(DefaultHttpClientConfig.SOCKET_TIMEOUT).setConnectTimeout(DefaultHttpClientConfig.CONNECT_TIMEOUT).setConnectionRequestTimeout(DefaultHttpClientConfig.CONNECTION_REQUEST_TIMEOUT).build();
mapper = new ObjectMapper();
mapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
mapper.setDateFormat(new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN));
}
/**
* HTTP的连接客户端
*/
private final CloseableHttpClient closeableHttpClient;
/**
* 每次发送请求的配置,如果该配置未进行设置则走 {@link DefaultHttpClientConfig 中的默认配置
*/
private RequestConfig requestConfig;
/**
* 通过最大连接数和服务每次能并行接收的请求数量构建一个JHApiClient实例
*
* @param maxTotal 最大连接数
* @param maxPerRout 服务每次能并行接收的请求数量
* @param baseUrl 景行接口服务的基础地址
* @return JHApiClient的实例
*/
public static JHApiClient build(int maxTotal, int maxPerRout, String baseUrl) {
return build(createHttpClients(maxTotal, maxPerRout), baseUrl);
}
/**
* 通过{@link DefaultHttpClientConfig默认配置的最大连接数和服务每次能并行接收的请求数量构建一个JHApiClient实例
* <p>
*
* @param baseUrl 景行接口服务的基础地址
* @return JHApiClient的实例
*/
public static JHApiClient build(String baseUrl) {
return build(createHttpClients(DefaultHttpClientConfig.MAX_TOTAL, DefaultHttpClientConfig.MAX_PER_ROUT), baseUrl);
}
/**
* 通过外部传入的{@link CloseableHttpClient构建一个请求客户端.
* <p>
*
* @param httpClient 请求连接池
* @param baseUrl 景行接口服务的基础地址
* @return JHApiClient的实例
*/
public static JHApiClient build(CloseableHttpClient httpClient, String baseUrl) {
return new JHApiClient(httpClient, baseUrl);
}
/**
* 初始化一个HTTP客户端实例
*
* @param maxTotal 设置最大连接数
* @param maxPerRoute 服务每次能并行接收的请求数量
* @return 返回一个可关闭的HTTP客户端示例
*/
public static CloseableHttpClient createHttpClients(int maxTotal, int maxPerRoute) {
SSLContextBuilder builder = new SSLContextBuilder();
try {
builder.loadTrustMaterial(null, (x509Certificates, s) -> true);
SSLConnectionSocketFactory sslref = new SSLConnectionSocketFactory(builder.build(), NoopHostnameVerifier.INSTANCE);
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", new PlainConnectionSocketFactory()).register("https", sslref).build();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
cm.setMaxTotal(maxTotal);
cm.setDefaultMaxPerRoute(maxPerRoute);
return HttpClients.custom().setSSLSocketFactory(sslref).setConnectionManager(cm).setConnectionManagerShared(true).build();
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
throw new ClientException(e.getMessage(), ClientErrorCode.SSL_EXCEPTION, e);
}
}
/**
* 关闭JHApiClient实例 (释放所有资源)
* 调用JHApiClient实例的shutdown() 后JHApiClient实例不可用。
* 如果客户端不存在则不进行任何操作
*/
public void shutdown() {
try {
if (closeableHttpClient != null) {
closeableHttpClient.close();
}
} catch (IOException e) {
throw new ClientException("关闭JHApiClient失败", e);
}
}
/**
* 设置自定义的jackson序列化配置
*
* @param mapper 序列化器
*/
public void setMapper(ObjectMapper mapper) {
this.mapper = mapper;
}
/**
* <p>
* 设置一个HTTP请求的配置
* </p>
*
* <p>
* {@link JHApiClient 默认只配置了 socket连接超时的时间(socketTimeout) 、连接超时的时间(connectTimeout)、
* 请求超时的时间(connectionRequestTimeout)这三项,其默认配置在{@link DefaultHttpClientConfig 中。
* 如果你要自定义你自己的配置,则可以通过{@link HttpClients构建自己的RequestConfig来请求接口
* </p>
*
* @param requestConfig HTTP请求的配置
*/
public void setRequestConfig(RequestConfig requestConfig) {
this.requestConfig = requestConfig;
}
/**
* 原始发送请求
*
* @param httpRequest 请求体
* @param headers 请求头
* @return 响应体
*/
public HttpEntity request(HttpRequestBase httpRequest, Map<String, String> headers) {
if (requestConfig == null) {
throw new ClientException("请配置requestConfig");
}
if (httpRequest == null) {
throw new ClientException("httpRequest不能为空");
}
httpRequest.setConfig(requestConfig);
// 添加请求头
if (CollectionUtil.isNotEmpty(headers)) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
httpRequest.setHeader(entry.getKey(), entry.getValue());
}
}
try {
HttpResponse response = closeableHttpClient.execute(httpRequest);
int statusCode = response.getStatusLine().getStatusCode();
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
httpRequest.releaseConnection();
throw new ClientException("发送HTTP请求失败请求码" + statusCode, ClientErrorCode.REQUEST_ERROR);
}
return response.getEntity();
} catch (IOException e) {
throw new ClientException(e.getMessage());
}
}
/**
* 发送请求
*
* @param httpRequest HttpRequestBase
* @param headers 请求头
* @param type 返回数据类型
* @param <T> 返回的数据类型
* @return 返回的接口数据
*/
public <T> T request(HttpRequestBase httpRequest, Map<String, String> headers, TypeReference<T> type) {
try {
InputStream content = request(httpRequest, headers).getContent();
return mapper.readValue(content, type);
} catch (IOException e) {
throw new ClientException(e.getMessage());
}
}
/**
* 发送一个get请求
*
* @param path 接口地址
* @param headers 请求头
* @param type 请求返回值类型
* @param <T> t
* @return t
*/
public <T> T get(String path, Map<String, String> headers, TypeReference<T> type) {
if (StringUtils.isBlank(path)) {
throw new ArgsException("url不能为空");
}
HttpGet httpGet = new HttpGet(getUrl(path));
return request(httpGet, headers, type);
}
/**
* 发起一个get请求
*
* @param path 接口地址
* @param type 返回数据的类型
* @param <T> 返回数据的类型
* @return 请求的数据
*/
public <T> T get(String path, TypeReference<T> type) {
return get(path, null, type);
}
/**
* 获的一个url
*
* @param path 请求地址
* @param params 请求参数
* @return 添加路径参数后的URL
*/
public static String getUrl(String path, Map<String, Object> params) {
if (StringUtils.isBlank(path)) {
throw new ClientException("path不能为空");
}
if (params == null || params.isEmpty()) {
return path;
}
StringBuilder urlBuilder = new StringBuilder(path + "?");
for (Map.Entry<String, Object> entry : params.entrySet()) {
try {
Object value = entry.getValue();
// 如果值为空,则不添加该字段
if (value == null) {
continue;
}
urlBuilder.append(entry.getKey()).append("=");
if (value instanceof String) {
urlBuilder.append(URLEncoder.encode((String) value, StandardCharsets.UTF_8.name()));
} else if (value instanceof Date) {
SimpleDateFormat format = new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN);
urlBuilder.append(URLEncoder.encode(format.format(value), "utf-8"));
} else {
urlBuilder.append(value);
}
urlBuilder.append("&");
} catch (UnsupportedEncodingException e) {
throw new ClientException("url参数编码失败", ClientErrorCode.UNKNOWN, e);
}
}
urlBuilder.setLength(urlBuilder.length() - 1);
return urlBuilder.toString();
}
/**
* 获取完整的请求路径
*
* @param path 文件路径
* @return 请求URL
*/
public String getUrl(String path) {
return baseUrl + path;
}
/**
* 发送post请求
*
* @param path 请求地址
* @param body 请求体
* @param headers 请求头
* @param type 请求数据类型
* @param <T> t 返回的数据的类型
* @param <K> k body的类型
* @return t
*/
public <T, K> T post(String path, K body, Map<String, String> headers, TypeReference<T> type) {
if (StringUtils.isBlank(path)) {
throw new ArgsException("path不能为空");
}
HttpPost httpPost = new HttpPost(getUrl(path));
try {
if (body != null) {
String bodyStr = mapper.writeValueAsString(body);
httpPost.setEntity(new StringEntity(bodyStr, "utf-8"));
}
return request(httpPost, headers, type);
} catch (Exception e) {
throw new ClientException(e.getMessage());
}
}
/**
* 发起put请求
*
* @param path 请求地址
* @param body 请求体
* @param headers 请求头
* @param type 请求数据类型
* @param <T> t 返回的数据的类型
* @param <K> k body的类型
* @return 请求返回的数据
*/
public <T, K> T put(String path, K body, Map<String, String> headers, TypeReference<T> type) {
if (StringUtils.isBlank(path)) {
throw new ArgsException("url不能为空");
}
HttpPut httpPost = new HttpPut(getUrl(path));
try {
if (body != null) {
String bodyStr = mapper.writeValueAsString(body);
httpPost.setEntity(new StringEntity(bodyStr, "utf-8"));
}
return request(httpPost, headers, type);
} catch (Exception e) {
throw new ClientException(e.getMessage());
}
}
/**
* 发起put请求
*
* @param path 请求地址
* @param body 请求体
* @param type 请求数据类型
* @param <T> t 返回的数据的类型
* @param <K> k body的类型
* @return 请求返回的数据
*/
public <T, K> T put(String path, K body, TypeReference<T> type) {
return put(path, body, null, type);
}
/**
* @param path 请求地址
* @param body 请求体
* @param type 响应类型
* @param <T> 相应返回数据类型
* @param <K> 请求体数据类型
* @return 响应数据
*/
public <T, K> T post(String path, K body, TypeReference<T> type) {
return post(path, body, null, type);
}
/**
* 发起delete请求
*
* @param path 请求地址
* @param headers 请求头
* @param type 响应类型
* @param <T> 响应数据类型
* @return 响应数据
*/
public <T> T delete(String path, Map<String, String> headers, TypeReference<T> type) {
if (StringUtils.isBlank(path)) {
throw new ArgsException("url不能为空");
}
HttpDelete httpDelete = new HttpDelete(getUrl(path));
return request(httpDelete, headers, type);
}
/**
* 发起delete请求
*
* @param path 请求地址
* @param type 响应类型
* @param <T> 响应数据类型
* @return 响应数据
*/
public <T> T delete(String path, TypeReference<T> type) {
return delete(path, null, type);
}
}

View File

@@ -1,18 +0,0 @@
package com.jhinno.sdk.openapi.test;
import com.jhinno.sdk.openapi.client.JHApiClient;
/**
* SDK Client 的配置
*
* @author yanlongqi
* @date 2024/2/4 17:11
*/
public class JHClientConfig {
/**
* 初始化JHApi客户端
*/
public static final JHApiClient client = JHApiClient.build("https://192.168.87.25/appform");
}

View File

@@ -1,33 +0,0 @@
package com.jhinno.sdk.openapi.test.auth;
import com.jhinno.sdk.openapi.api.app.JHAppApiExecution;
import com.jhinno.sdk.openapi.test.JHClientConfig;
import org.junit.Test;
/**
* 鉴权相关测试累类
*
* @author yanlongqi
* @date 2024/2/1 18:06
*/
public class AuthApiTest {
JHAppApiExecution jhAppApiExecution = new JHAppApiExecution(JHClientConfig.client);
/**
* 测试获取token
*/
@Test
public void testGetToken() {
String token = jhAppApiExecution.getToken("jhadmin");
System.out.println("token:" + token);
}
/**
* 测试退出登录
*/
@Test
public void testLogout(){
jhAppApiExecution.logout("lqyan");
}
}