feat 节点通讯 http 模块

This commit is contained in:
bwcx_jzy 2022-12-24 21:16:11 +08:00
parent 9aa2e5eb99
commit 421937c1cd
No known key found for this signature in database
GPG Key ID: 5E48E9372088B9E5
48 changed files with 941 additions and 465 deletions

View File

@ -8,6 +8,10 @@
2. 【all】升级 fastjson 升级为 fastjson2
3. 【all】升级 SpringBoot 2.7.7
### ❌ 不兼容功能
1. 【server】取消 兼容低版本插件端的 websocket 授权信息传输方式(低版本插件端请同步升级到最新)
------
## 2.10.4 (2022-12-23)

View File

@ -53,6 +53,12 @@
<artifactId>slf4j-api</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@ -22,6 +22,9 @@
*/
package top.jpom.transform;
import com.alibaba.fastjson2.TypeReference;
import top.jpom.transport.INodeInfo;
/**
* 消息转换服务
*
@ -30,5 +33,34 @@ package top.jpom.transform;
*/
public interface TransformServer {
<T> T transform(String data);
/**
* 数据类型转换
*
* @param data 数据
* @param tTypeReference 类型
* @param <T> 范型
* @return data
*/
<T> T transform(String data, TypeReference<T> tTypeReference);
/**
* 数据类型转换,只返回成功的数据
*
* @param data 数据
* @param tClass 类型
* @param <T> 范型
* @return data
*/
<T> T transformOnlyData(String data, Class<T> tClass);
/**
* 转换异常
*
* @param e 请求的异常
* @param nodeInfo 节点信息
* @return 转换后的异常
*/
default Exception transformException(Exception e, INodeInfo nodeInfo) {
return e;
}
}

View File

@ -0,0 +1,72 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Code Technology Studio
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package top.jpom.transform;
import cn.hutool.core.lang.Singleton;
import cn.hutool.core.util.ServiceLoaderUtil;
import lombok.extern.slf4j.Slf4j;
/**
* @author bwcx_jzy
* @since 2022/12/24
*/
@Slf4j
public class TransformServerFactory {
/**
* 获得单例的 TransformServer
*
* @return 单例的 TransformServer
*/
public static TransformServer get() {
return Singleton.get(TransformServer.class.getName(), TransformServerFactory::doCreate);
}
/**
* 根据用户引入的 Transform 客户端引擎jar自动创建对应的拼音引擎对象<br>
* 推荐创建的引擎单例使用此方法每次调用会返回新的引擎
*
* @return {@code TransformServer}
*/
public static TransformServer of() {
final TransformServer transportServer = doCreate();
log.debug("Use [{}] Agent Transport As Default.", transportServer.getClass().getSimpleName());
return transportServer;
}
/**
* 根据用户引入的拼音引擎jar自动创建对应的拼音引擎对象<br>
* 推荐创建的引擎单例使用此方法每次调用会返回新的引擎
*
* @return {@code EngineFactory}
*/
private static TransformServer doCreate() {
final TransformServer engine = ServiceLoaderUtil.loadFirstAvailable(TransformServer.class);
if (null != engine) {
return engine;
}
throw new RuntimeException("No jpom agent transform jar found ! Please add one of it to your project !");
}
}

View File

@ -0,0 +1,37 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Code Technology Studio
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package top.jpom.transport;
import lombok.NoArgsConstructor;
/**
* @author bwcx_jzy
* @since 2022/12/24
*/
@NoArgsConstructor
public class AgentException extends RuntimeException {
public AgentException(String message) {
super(message);
}
}

View File

@ -0,0 +1,40 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Code Technology Studio
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package top.jpom.transport;
/**
* 请求数据传输类型
*
* @author bwcx_jzy
* @since 2022/12/24
*/
public enum DataContentType {
/**
* URL
*/
FORM_URLENCODED,
/**
* JSON
*/
JSON
}

View File

@ -0,0 +1,43 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Code Technology Studio
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package top.jpom.transport;
import lombok.Builder;
import lombok.Data;
import java.io.InputStream;
/**
* @author bwcx_jzy
* @since 2022/12/24
*/
@Builder
@Data
public class DownloadCallback {
private String contentDisposition;
private String contentType;
private InputStream inputStream;
}

View File

@ -22,6 +22,8 @@
*/
package top.jpom.transport;
import java.net.Proxy;
/**
* 节点通讯的 接口
*
@ -30,6 +32,13 @@ package top.jpom.transport;
*/
public interface INodeInfo {
/**
* 节点名称
*
* @return 名称
*/
String name();
/**
* 节点 url
* <p>
@ -47,16 +56,17 @@ public interface INodeInfo {
String scheme();
/**
* 节点用户
* 节点 授权信息
* sha1(user@pwd)
*
* @return 用户
*/
String user();
String authorize();
/**
* 节点密码
* 节点通讯代理
*
* @return 密码
* @return proxy
*/
String password();
Proxy proxy();
}

View File

@ -40,5 +40,19 @@ public interface IUrlItem {
*
* @return 超时时间
*/
int timeout();
Integer timeout();
/**
* 当前工作空间id
*
* @return 工作空间
*/
String workspaceId();
/**
* 请求类型
*
* @return contentType
*/
DataContentType contentType();
}

View File

@ -22,7 +22,10 @@
*/
package top.jpom.transport;
import java.util.Map;
import com.alibaba.fastjson2.TypeReference;
import top.jpom.transform.TransformServerFactory;
import java.util.function.Consumer;
/**
* 插件端消息传输服务
@ -32,6 +35,60 @@ import java.util.Map;
*/
public interface TransportServer {
String execute(INodeInfo nodeInfo, IUrlItem urlItem, Map<String, String> map);
/**
* 请求 header
*/
String WORKSPACE_ID_REQ_HEADER = "workspaceId";
String JPOM_AGENT_AUTHORIZE = "Jpom-Agent-Authorize";
/**
* 执行请求
*
* @param nodeInfo 节点信息
* @param urlItem 请求 item
* @param data 参数
* @return 响应的字符串
*/
String execute(INodeInfo nodeInfo, IUrlItem urlItem, Object data);
/**
* 执行请求返回响应的所有数据
*
* @param nodeInfo 节点信息
* @param urlItem 请求 item
* @param data 参数
* @param tTypeReference 返回的泛型
* @param <T> 泛型
* @return 响应的字符串
*/
default <T> T executeToType(INodeInfo nodeInfo, IUrlItem urlItem, Object data, TypeReference<T> tTypeReference) {
String body = this.execute(nodeInfo, urlItem, data);
return TransformServerFactory.get().transform(body, tTypeReference);
}
/**
* 执行请求,仅返回成功的数据
*
* @param nodeInfo 节点信息
* @param urlItem 请求 item
* @param data 参数
* @param tClass 返回的泛型
* @param <T> 泛型
* @return 响应的字符串
*/
default <T> T executeToTypeOnlyData(INodeInfo nodeInfo, IUrlItem urlItem, Object data, Class<T> tClass) {
String body = this.execute(nodeInfo, urlItem, data);
return TransformServerFactory.get().transformOnlyData(body, tClass);
}
/**
* 下载文件
*
* @param nodeInfo 节点信息
* @param urlItem 请求 item
* @param data 参数
* @param consumer 回调
*/
void download(INodeInfo nodeInfo, IUrlItem urlItem, Object data, Consumer<DownloadCallback> consumer);
}

View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
The MIT License (MIT)
Copyright (c) 2019 Code Technology Studio
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-->
<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>
<parent>
<groupId>io.jpom.agent-transport</groupId>
<artifactId>jpom-agent-transport-parent</artifactId>
<version>2.10.4</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>agent-transport-http</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>io.jpom.agent-transport</groupId>
<artifactId>agent-transport-common</artifactId>
<version>${pom.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,129 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Code Technology Studio
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package top.jpom.transport;
import cn.hutool.core.net.url.UrlBuilder;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.*;
import com.alibaba.fastjson2.JSONObject;
import lombok.Lombok;
import lombok.extern.slf4j.Slf4j;
import top.jpom.transform.TransformServerFactory;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
/**
* 插件端消息传输服务
*
* @author bwcx_jzy
* @since 2022/12/18
*/
@Slf4j
public class HttpTransportServer implements TransportServer {
private HttpRequest createRequest(INodeInfo nodeInfo, IUrlItem urlItem, Method method) {
String url = StrUtil.format("{}://{}/", nodeInfo.scheme(), nodeInfo.url());
UrlBuilder urlBuilder = UrlBuilder.of(url).addPath(urlItem.path());
HttpRequest httpRequest = HttpRequest.of(urlBuilder);
httpRequest.setMethod(method);
Optional.ofNullable(urlItem.timeout()).ifPresent(integer -> httpRequest.timeout(integer * 1000));
httpRequest.header(TransportServer.JPOM_AGENT_AUTHORIZE, nodeInfo.authorize());
//
httpRequest.header(TransportServer.WORKSPACE_ID_REQ_HEADER, urlItem.workspaceId());
Optional.ofNullable(nodeInfo.proxy()).ifPresent(httpRequest::setProxy);
return httpRequest;
}
private HttpRequest createRequest(INodeInfo nodeInfo, IUrlItem urlItem) {
return createRequest(nodeInfo, urlItem, Method.POST);
}
@SuppressWarnings("unchecked")
private void appendRequestData(HttpRequest httpRequest, IUrlItem urlItem, Object data) {
DataContentType dataContentType = urlItem.contentType();
Optional.ofNullable(data).ifPresent(o -> {
if (dataContentType == DataContentType.FORM_URLENCODED) {
if (o instanceof Map) {
httpRequest.form((Map<String, Object>) o);
} else {
throw new IllegalArgumentException("不支持的类型:" + o.getClass());
}
} else if (dataContentType == DataContentType.JSON) {
httpRequest.body(JSONObject.toJSONString(o), cn.hutool.http.ContentType.JSON.getValue());
} else {
throw new IllegalArgumentException("不支持的 contentType");
}
});
}
private String executeRequest(HttpRequest httpRequest, INodeInfo nodeInfo, IUrlItem urlItem) {
//
if (log.isDebugEnabled()) {
log.debug("{}[{}] -> {} {}", nodeInfo.name(), httpRequest.getUrl(), urlItem.workspaceId(), Optional.ofNullable((Object) httpRequest.form()).orElse("-"));
}
return httpRequest.thenFunction(response -> {
int status = response.getStatus();
String body = response.body();
log.debug("Completed {}", body);
if (status != HttpStatus.HTTP_OK) {
log.warn("{} 响应异常 状态码错误:{} {}", nodeInfo.name(), status, body);
throw new AgentException(nodeInfo.name() + " 节点响应异常,状态码错误:" + status);
}
return body;
});
}
@Override
public String execute(INodeInfo nodeInfo, IUrlItem urlItem, Object data) {
HttpRequest httpRequest = this.createRequest(nodeInfo, urlItem);
this.appendRequestData(httpRequest, urlItem, data);
try {
return this.executeRequest(httpRequest, nodeInfo, urlItem);
} catch (Exception e) {
throw Lombok.sneakyThrow(TransformServerFactory.get().transformException(e, nodeInfo));
}
}
@Override
public void download(INodeInfo nodeInfo, IUrlItem urlItem, Object data, Consumer<DownloadCallback> consumer) {
HttpRequest httpRequest = this.createRequest(nodeInfo, urlItem, Method.GET);
httpRequest.setFollowRedirects(true);
this.appendRequestData(httpRequest, urlItem, data);
try (HttpResponse response1 = httpRequest.execute()) {
String contentDisposition = response1.header(Header.CONTENT_DISPOSITION);
String contentType = response1.header(Header.CONTENT_TYPE);
DownloadCallback build = DownloadCallback.builder()
.contentDisposition(contentDisposition).contentType(contentType).inputStream(response1.bodyStream())
.build();
consumer.accept(build);
} catch (Exception e) {
throw Lombok.sneakyThrow(TransformServerFactory.get().transformException(e, nodeInfo));
}
}
}

View File

@ -0,0 +1 @@
top.jpom.transport.HttpTransportServer

View File

@ -35,6 +35,7 @@
<packaging>pom</packaging>
<modules>
<module>agent-transport-common</module>
<module>agent-transport-http</module>
</modules>
<modelVersion>4.0.0</modelVersion>
<version>2.10.4</version>

View File

@ -45,9 +45,6 @@ public abstract class BaseAgentController extends BaseJpomController {
@Resource
protected ProjectInfoService projectInfoService;
protected String getUserName() {
return getUserName(getRequest());
}
/**
* 获取server 端操作人

View File

@ -67,7 +67,7 @@ public class AgentAuthorize implements InitializingBean {
}
public String getAuthorize() {
throw new UnsupportedOperationException("不能调用此方法");
return null;
}
private final JpomApplication configBean;

View File

@ -47,7 +47,6 @@
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>${fastjson2.version}</version>
</dependency>
<dependency>

View File

@ -73,6 +73,10 @@ public class JsonMessage<T> implements Serializable {
this(code, msg, null);
}
public boolean success() {
return this.code == DEFAULT_SUCCESS_CODE;
}
/**
* 将data 转换为对应实体
*
@ -81,13 +85,7 @@ public class JsonMessage<T> implements Serializable {
* @return Object
*/
public <E> E getData(Class<E> tClass) {
if (data == null) {
return null;
}
if (tClass.isAssignableFrom(data.getClass())) {
return (E) data;
}
return JSONObject.parseObject(data.toString(), tClass);
return JSON.to(tClass, this.data);
}
/**

View File

@ -125,6 +125,12 @@
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.jpom.agent-transport</groupId>
<artifactId>agent-transport-http</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<resources>

View File

@ -487,7 +487,7 @@ public class ReleaseManage implements Runnable {
String directory = this.buildExtraModule.getProjectSecondaryDirectory();
directory = Opt.ofBlankAble(directory).orElse(StrUtil.SLASH);
jsonObject.put("dir", directory);
JsonMessage<JSONObject> requestBody = NodeForward.requestBody(nodeModel, NodeUrl.MANAGE_FILE_DIFF_FILE, this.userModel, jsonObject);
JsonMessage<JSONObject> requestBody = NodeForward.requestBody(nodeModel, NodeUrl.MANAGE_FILE_DIFF_FILE, jsonObject);
if (requestBody.getCode() != HttpStatus.HTTP_OK) {
throw new JpomRuntimeException("对比项目文件失败:" + requestBody);
}
@ -504,7 +504,7 @@ public class ReleaseManage implements Runnable {
// 清空发布才先执行删除
if (delSize > 0 && clearOld) {
jsonObject.put("data", del);
requestBody = NodeForward.requestBody(nodeModel, NodeUrl.MANAGE_FILE_BATCH_DELETE, this.userModel, jsonObject);
requestBody = NodeForward.requestBody(nodeModel, NodeUrl.MANAGE_FILE_BATCH_DELETE, jsonObject);
if (requestBody.getCode() != HttpStatus.HTTP_OK) {
throw new JpomRuntimeException("删除项目文件失败:" + requestBody);
}
@ -519,7 +519,7 @@ public class ReleaseManage implements Runnable {
startPath = FileUtil.normalize(startPath + StrUtil.SLASH + directory);
//
JsonMessage<String> jsonMessage = OutGivingRun.fileUpload(file, startPath,
projectId, false, last ? afterOpt : AfterOpt.No, nodeModel, this.userModel, false,
projectId, false, last ? afterOpt : AfterOpt.No, nodeModel, false,
this.buildExtraModule.getProjectUploadCloseFirst());
if (jsonMessage.getCode() != HttpStatus.HTTP_OK) {
throw new JpomRuntimeException("同步项目文件失败:" + jsonMessage);
@ -563,7 +563,7 @@ public class ReleaseManage implements Runnable {
projectId,
unZip,
afterOpt,
nodeModel, this.userModel, clearOld, this.buildExtraModule.getProjectUploadCloseFirst());
nodeModel, clearOld, this.buildExtraModule.getProjectUploadCloseFirst());
if (jsonMessage.getCode() == HttpStatus.HTTP_OK) {
logRecorder.info("发布项目包成功:" + jsonMessage);
} else {

View File

@ -0,0 +1,54 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Code Technology Studio
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package io.jpom.common.forward;
import com.alibaba.fastjson2.TypeReference;
import io.jpom.common.JsonMessage;
import top.jpom.transform.TransformServer;
import top.jpom.transport.INodeInfo;
/**
* json 消息转换
*
* @author bwcx_jzy
* @since 2022/12/24
*/
public class JsonMessageTransformServer implements TransformServer {
@Override
public <T> T transform(String data, TypeReference<T> tTypeReference) {
return NodeForward.toJsonMessage(data, tTypeReference);
}
@Override
public <T> T transformOnlyData(String data, Class<T> tClass) {
JsonMessage<T> transform = this.transform(data, new TypeReference<JsonMessage<T>>() {
});
return transform.getData(tClass);
}
@Override
public Exception transformException(Exception e, INodeInfo nodeInfo) {
return NodeForward.responseException(e, nodeInfo);
}
}

View File

@ -24,17 +24,18 @@ package io.jpom.common.forward;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.resource.BytesResource;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.net.url.UrlQuery;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.*;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import io.jpom.common.BaseServerController;
import io.jpom.common.Const;
import io.jpom.common.JsonMessage;
import io.jpom.model.data.NodeModel;
@ -43,20 +44,21 @@ import io.jpom.service.node.NodeService;
import io.jpom.system.AgentException;
import io.jpom.system.AuthorizeException;
import io.jpom.system.ServerConfig;
import lombok.Lombok;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import top.jpom.transport.DataContentType;
import top.jpom.transport.INodeInfo;
import top.jpom.transport.IUrlItem;
import top.jpom.transport.TransportServerFactory;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.Proxy;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
/**
* 节点请求转发
@ -67,6 +69,72 @@ import java.util.function.Function;
@Slf4j
public class NodeForward {
/**
* 创建节点 url
*
* @param nodeModel 节点信息
* @param nodeUrl 节点功能 url
* @param dataContentType 传输的数据类型
* @return item
*/
private static IUrlItem createUrlItem(NodeModel nodeModel, NodeUrl nodeUrl, DataContentType dataContentType) {
// 修正节点密码
if (StrUtil.isEmpty(nodeModel.getLoginPwd())) {
NodeService nodeService = SpringUtil.getBean(NodeService.class);
NodeModel model = nodeService.getByKey(nodeModel.getId(), false);
nodeModel.setLoginPwd(model.getLoginPwd());
nodeModel.setLoginName(model.getLoginName());
}
//
return new IUrlItem() {
@Override
public String path() {
return nodeUrl.getUrl();
}
@Override
public Integer timeout() {
if (nodeUrl.isFileTimeout()) {
ServerConfig serverConfig = SpringUtil.getBean(ServerConfig.class);
ServerConfig.NodeConfig configNode = serverConfig.getNode();
return configNode.getUploadFileTimeoutMilliseconds();
} else {
return Optional.of(nodeUrl.getTimeout())
.flatMap(timeOut -> {
if (timeOut == 0) {
// 读取节点配置的超时时间
return Optional.ofNullable(nodeModel.getTimeOut());
}
// < 0 url 指定不超时
return timeOut > 0 ? Optional.of(timeOut) : Optional.empty();
})
.map(timeOut -> {
if (timeOut <= 0) {
return null;
}
// 超时时间不能小于 2
return Math.max(timeOut, 2);
})
.orElse(null);
}
}
@Override
public String workspaceId() {
return nodeModel.getWorkspaceId();
}
@Override
public DataContentType contentType() {
return dataContentType;
}
};
}
private static IUrlItem createUrlItem(NodeModel nodeModel, NodeUrl nodeUrl) {
return createUrlItem(nodeModel, nodeUrl, DataContentType.FORM_URLENCODED);
}
/**
* 普通消息转发
*
@ -77,7 +145,10 @@ public class NodeForward {
* @return JSON
*/
public static <T> JsonMessage<T> request(NodeModel nodeModel, HttpServletRequest request, NodeUrl nodeUrl) {
return request(nodeModel, request, nodeUrl, true, null, null, null, null);
Map<String, String> map = Optional.ofNullable(request).map(ServletUtil::getParamMap).orElse(null);
IUrlItem urlItem = createUrlItem(nodeModel, nodeUrl);
return TransportServerFactory.get().executeToType(nodeModel, urlItem, map, new TypeReference<JsonMessage<T>>() {
});
}
/**
@ -86,25 +157,33 @@ public class NodeForward {
* @param nodeModel 节点
* @param nodeUrl 节点的url
* @param jsonObject 数据
* @param userModel user
* @return JSON
*/
public static JsonMessage<String> request(NodeModel nodeModel, NodeUrl nodeUrl, UserModel userModel, JSONObject jsonObject) {
return request(nodeModel, null, nodeUrl, true, userModel, jsonObject, null, null);
public static <T> JsonMessage<T> request(NodeModel nodeModel, NodeUrl nodeUrl, JSONObject jsonObject) {
IUrlItem urlItem = createUrlItem(nodeModel, nodeUrl);
return TransportServerFactory.get().executeToType(nodeModel, urlItem, jsonObject, new TypeReference<JsonMessage<T>>() {
});
}
/**
* 普通消息转发
*
* @param nodeModel 节点
* @param nodeUrl 节点的url
* @param pName 主参数名
* @param pVal 主参数值
* @param val 其他参数
* @param nodeModel 节点
* @param nodeUrl 节点的url
* @param pName 主参数名
* @param pVal 主参数值
* @param parameters 其他参数
* @return JSON
*/
public static <T> JsonMessage<T> requestBySys(NodeModel nodeModel, NodeUrl nodeUrl, String pName, Object pVal, Object... val) {
return request(nodeModel, null, nodeUrl, false, null, null, pName, pVal, val);
public static <T> JsonMessage<T> request(NodeModel nodeModel, NodeUrl nodeUrl, String pName, Object pVal, Object... parameters) {
Map<String, Object> parametersMap = MapUtil.of(pName, pVal);
for (int i = 0; i < parameters.length; i += 2) {
parametersMap.put(parameters[i].toString(), parameters[i + 1]);
}
IUrlItem urlItem = createUrlItem(nodeModel, nodeUrl);
return TransportServerFactory.get().executeToType(nodeModel, urlItem, parametersMap, new TypeReference<JsonMessage<T>>() {
});
}
/**
@ -112,95 +191,15 @@ public class NodeForward {
*
* @param nodeModel 节点
* @param nodeUrl 节点的url
* @param userModel 用户
* @param jsonData 数据
* @param <T> 泛型
* @return JSON
*/
public static <T> JsonMessage<T> requestBody(NodeModel nodeModel,
NodeUrl nodeUrl,
UserModel userModel,
JSONObject jsonData) {
String url = nodeModel.getRealUrl(nodeUrl);
HttpRequest httpRequest = HttpUtil.createPost(url);
public static <T> JsonMessage<T> requestBody(NodeModel nodeModel, NodeUrl nodeUrl, JSONObject jsonData) {
addUser(httpRequest, nodeModel, nodeUrl, userModel);
httpRequest.body(jsonData.toString(), ContentType.JSON.getValue());
try (HttpResponse response = httpRequest.execute()) {
//
return parseBody(httpRequest, response, nodeModel);
} catch (Exception e) {
throw NodeForward.responseException(e, nodeModel);
}
}
/**
* 普通消息转发
*
* @param nodeModel 节点
* @param request 请求
* @param nodeUrl 节点的url
* @param pVal 主参数值
* @param pName 主参数名
* @param userModel 用户
* @param jsonData 数据
* @param mustUser 是否必须需要user
* @param val 其他参数
* @param <T> 泛型
* @return JSON
*/
@SuppressWarnings({"rawtypes"})
private static <T> JsonMessage<T> request(NodeModel nodeModel,
HttpServletRequest request,
NodeUrl nodeUrl,
boolean mustUser,
UserModel userModel,
JSONObject jsonData,
String pName,
Object pVal,
Object... val) {
String url = nodeModel.getRealUrl(nodeUrl);
HttpRequest httpRequest = HttpUtil.createPost(url);
//
if (mustUser) {
if (userModel == null) {
userModel = BaseServerController.getUserModel();
}
}
//
addUser(httpRequest, nodeModel, nodeUrl, userModel);
Optional.ofNullable(request).map((Function<HttpServletRequest, Map>) ServletRequest::getParameterMap).ifPresent(httpRequest::form);
httpRequest.form(pName, pVal, val);
//
if (jsonData != null) {
boolean hasFile = false;
// 参数 URL 编码避免 特殊符号 不生效
Set<Map.Entry<String, Object>> entries = jsonData.entrySet();
for (Map.Entry<String, Object> entry : entries) {
Object value = entry.getValue();
if (value instanceof File) {
// 标记上传文件
hasFile = true;
break;
}
}
httpRequest.form(jsonData);
if (hasFile) {
ServerConfig serverConfig = SpringUtil.getBean(ServerConfig.class);
ServerConfig.NodeConfig configNode = serverConfig.getNode();
httpRequest.timeout(configNode.getUploadFileTimeoutMilliseconds());
}
}
try (HttpResponse response = httpRequest.execute()) {
//
return parseBody(httpRequest, response, nodeModel);
} catch (Exception e) {
throw NodeForward.responseException(e, nodeModel);
}
IUrlItem urlItem = createUrlItem(nodeModel, nodeUrl, DataContentType.JSON);
return TransportServerFactory.get().executeToType(nodeModel, urlItem, jsonData, new TypeReference<JsonMessage<T>>() {
});
}
/**
@ -209,25 +208,25 @@ public class NodeForward {
* @param exception 异常
* @param nodeModel 插件端
*/
private static AgentException responseException(Exception exception, NodeModel nodeModel) {
public static AgentException responseException(Exception exception, INodeInfo nodeModel) {
String message = exception.getMessage();
Throwable cause = exception.getCause();
log.error("node [{}] connect failed...message: [{}]", nodeModel.getName(), message);
log.error("node [{}] connect failed...message: [{}]", nodeModel.name(), message);
if (exception instanceof IORuntimeException) {
if (cause instanceof java.net.ConnectException || cause instanceof java.net.SocketTimeoutException) {
return new AgentException(nodeModel.getName() + "节点网络连接异常或超时,请优先检查插件端运行状态再检查 IP 地址、" +
return new AgentException(nodeModel.name() + "节点网络连接异常或超时,请优先检查插件端运行状态再检查 IP 地址、" +
"端口号是否配置正确,防火墙规则," +
"云服务器的安全组配置等网络相关问题排查定位。" + message);
}
} else if (exception instanceof cn.hutool.http.HttpException) {
if (cause instanceof java.net.SocketTimeoutException) {
return new AgentException(nodeModel.getName() + "节点网络连接超时,请优先检查插件端运行状态再检查节点超时时间配置是否合理,上传文件超时时间配置是否合理。" + message);
return new AgentException(nodeModel.name() + "节点网络连接超时,请优先检查插件端运行状态再检查节点超时时间配置是否合理,上传文件超时时间配置是否合理。" + message);
}
if (cause instanceof IOException && StrUtil.containsIgnoreCase(message, "Error writing to server")) {
return new AgentException(nodeModel.getName() + "节点上传失败,请优先检查限制上传大小配置是否合理。" + message);
return new AgentException(nodeModel.name() + "节点上传失败,请优先检查限制上传大小配置是否合理。" + message);
}
}
return new AgentException(nodeModel.getName() + "节点异常:" + message);
return new AgentException(nodeModel.name() + "节点异常:" + message);
}
/**
@ -241,38 +240,11 @@ public class NodeForward {
* @return T
*/
public static <T> T requestData(NodeModel nodeModel, NodeUrl nodeUrl, HttpServletRequest request, Class<T> tClass) {
JsonMessage<T> jsonMessage = request(nodeModel, request, nodeUrl);
return jsonMessage.getData(tClass);
}
/**
* 普通消息转发,并解析数据
*
* @param nodeModel 节点
* @param nodeUrl 节点的url
* @param tClass 要解析的类
* @param <T> 泛型
* @param name 参数名
* @param parameters 其他参数
* @param value
* @return T
*/
public static <T> T requestData(NodeModel nodeModel, NodeUrl nodeUrl, Class<T> tClass, String name, Object value, Object... parameters) {
String url = nodeModel.getRealUrl(nodeUrl);
//
HttpRequest httpRequest = HttpUtil.createPost(url);
if (name != null && value != null) {
httpRequest.form(name, value, parameters);
}
//
addUser(httpRequest, nodeModel, nodeUrl);
try (HttpResponse response = httpRequest.execute();) {
//
JsonMessage<T> jsonMessage = parseBody(httpRequest, response, nodeModel);
return jsonMessage.getData(tClass);
} catch (Exception e) {
throw NodeForward.responseException(e, nodeModel);
}
Map<String, String> map = Optional.ofNullable(request).map(ServletUtil::getParamMap).orElse(null);
IUrlItem urlItem = createUrlItem(nodeModel, nodeUrl);
return TransportServerFactory.get().executeToTypeOnlyData(nodeModel, urlItem, map, tClass);
// JsonMessage<T> jsonMessage = request(nodeModel, request, nodeUrl);
// return jsonMessage.getData(tClass);
}
@ -286,58 +258,21 @@ public class NodeForward {
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public static JsonMessage<String> requestMultipart(NodeModel nodeModel, MultipartHttpServletRequest request, NodeUrl nodeUrl) {
String url = nodeModel.getRealUrl(nodeUrl);
HttpRequest httpRequest = HttpUtil.createPost(url);
addUser(httpRequest, nodeModel, nodeUrl);
IUrlItem urlItem = createUrlItem(nodeModel, nodeUrl);
//
Map params = ServletUtil.getParams(request);
httpRequest.form(params);
Map params = ServletUtil.getParamMap(request);
//
Map<String, MultipartFile> fileMap = request.getFileMap();
fileMap.forEach((s, multipartFile) -> {
try {
httpRequest.form(s, multipartFile.getBytes(), multipartFile.getOriginalFilename());
params.put(s, new BytesResource(multipartFile.getBytes(), multipartFile.getOriginalFilename()));
} catch (IOException e) {
log.error("转发文件异常", e);
throw Lombok.sneakyThrow(e);
}
});
// @author jzy add timeout
ServerConfig serverConfig = SpringUtil.getBean(ServerConfig.class);
ServerConfig.NodeConfig configNode = serverConfig.getNode();
httpRequest.timeout(configNode.getUploadFileTimeoutMilliseconds());
try (HttpResponse response = httpRequest.execute()) {
return parseBody(httpRequest, response, nodeModel);
} catch (Exception e) {
throw NodeForward.responseException(e, nodeModel);
}
}
/**
* 上传文件消息转发
*
* @param nodeModel 节点
* @param fileName 文件字段名
* @param file 上传的文件
* @param nodeUrl 节点的url
* @return json
*/
public static JsonMessage<String> requestMultipart(NodeModel nodeModel, String fileName, File file, NodeUrl nodeUrl) {
String url = nodeModel.getRealUrl(nodeUrl);
HttpRequest httpRequest = HttpUtil.createPost(url);
addUser(httpRequest, nodeModel, nodeUrl);
//
httpRequest.form(fileName, file);
// @author jzy add timeout
ServerConfig serverConfig = SpringUtil.getBean(ServerConfig.class);
ServerConfig.NodeConfig configNode = serverConfig.getNode();
httpRequest.timeout(configNode.getUploadFileTimeoutMilliseconds());
try (HttpResponse response = httpRequest.execute()) {
return parseBody(httpRequest, response, nodeModel);
} catch (Exception e) {
throw NodeForward.responseException(e, nodeModel);
}
return TransportServerFactory.get().executeToType(nodeModel, urlItem, params, new TypeReference<JsonMessage<String>>() {
});
}
/**
@ -348,86 +283,16 @@ public class NodeForward {
* @param response 响应
* @param nodeUrl 节点的url
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public static void requestDownload(NodeModel nodeModel, HttpServletRequest request, HttpServletResponse response, NodeUrl nodeUrl) {
String url = nodeModel.getRealUrl(nodeUrl);
HttpRequest httpRequest = HttpUtil.createGet(url, true);
addUser(httpRequest, nodeModel, nodeUrl);
IUrlItem urlItem = createUrlItem(nodeModel, nodeUrl);
//
Map params = ServletUtil.getParams(request);
httpRequest.form(params);
// @author jzy add timeout
ServerConfig serverConfig = SpringUtil.getBean(ServerConfig.class);
ServerConfig.NodeConfig configNode = serverConfig.getNode();
httpRequest.timeout(configNode.getUploadFileTimeoutMilliseconds());
//
try (HttpResponse response1 = httpRequest.execute()) {
String contentDisposition = response1.header("Content-Disposition");
response.setHeader("Content-Disposition", contentDisposition);
String contentType = response1.header("Content-Type");
response.setContentType(contentType);
ServletUtil.write(response, response1.bodyStream());
} catch (Exception e) {
throw NodeForward.responseException(e, nodeModel);
}
}
private static void addUser(HttpRequest httpRequest, NodeModel nodeModel, NodeUrl nodeUrl) {
UserModel userModel = BaseServerController.getUserModel();
addUser(httpRequest, nodeModel, nodeUrl, userModel);
}
/**
* 添加agent 授权信息header
*
* @param httpRequest request
* @param nodeModel 节点
* @param userModel 用户
*/
private static void addUser(HttpRequest httpRequest, NodeModel nodeModel, NodeUrl nodeUrl, UserModel userModel) {
// 判断开启状态
if (!nodeModel.isOpenStatus()) {
throw new AgentException(nodeModel.getName() + "节点未启用");
}
if (userModel != null) {
httpRequest.header(Const.JPOM_SERVER_USER_NAME, URLUtil.encode(userModel.getId()));
// httpRequest.header(ConfigBean.JPOM_SERVER_SYSTEM_USER_ROLE, userModel.getUserRole(nodeModel).name());
}
if (StrUtil.isEmpty(nodeModel.getLoginPwd())) {
NodeService nodeService = SpringUtil.getBean(NodeService.class);
NodeModel model = nodeService.getByKey(nodeModel.getId(), false);
nodeModel.setLoginPwd(model.getLoginPwd());
nodeModel.setLoginName(model.getLoginName());
}
httpRequest.header(Const.JPOM_AGENT_AUTHORIZE, nodeModel.toAuthorize());
httpRequest.header(Const.WORKSPACEID_REQ_HEADER, nodeModel.getWorkspaceId());
// 配置超时时间
if (nodeUrl.isFileTimeout()) {
ServerConfig serverConfig = SpringUtil.getBean(ServerConfig.class);
ServerConfig.NodeConfig configNode = serverConfig.getNode();
httpRequest.timeout(configNode.getUploadFileTimeoutMilliseconds());
} else {
Optional.of(nodeUrl.getTimeout())
.flatMap(timeOut -> {
if (timeOut == 0) {
// 读取节点配置的超时时间
return Optional.ofNullable(nodeModel.getTimeOut());
}
// < 0 url 指定不超时
return timeOut > 0 ? Optional.of(timeOut) : Optional.empty();
})
.map(timeOut -> {
if (timeOut <= 0) {
return null;
}
// 超时时间不能小于 2
return Math.max(timeOut, 2);
})
.ifPresent(timeOut -> httpRequest.timeout(timeOut * 1000));
}
// 添加 http proxy
Proxy proxy = nodeModel.proxy();
httpRequest.setProxy(proxy);
Map<String, String> params = ServletUtil.getParamMap(request);
TransportServerFactory.get().download(nodeModel, urlItem, params, downloadCallback -> {
Opt.ofBlankAble(downloadCallback.getContentDisposition())
.ifPresent(s -> response.setHeader(HttpHeaders.CONTENT_DISPOSITION, s));
response.setContentType(downloadCallback.getContentType());
ServletUtil.write(response, downloadCallback.getInputStream());
});
}
/**
@ -464,41 +329,26 @@ public class NodeForward {
}
}
// 兼容旧版本-节点升级 @author jzy
urlQuery.add("name", URLUtil.encode(nodeModel.getLoginName()));
urlQuery.add("password", URLUtil.encode(nodeModel.getLoginPwd()));
//urlQuery.add("name", URLUtil.encode(nodeModel.getLoginName()));
//urlQuery.add("password", URLUtil.encode(nodeModel.getLoginPwd()));
String format = StrUtil.format("{}://{}{}?{}", ws, nodeModel.getUrl(), nodeUrl.getUrl(), urlQuery.toString());
log.debug("web socket url:{}", format);
return format;
}
/**
* 解析结果
*
* @param response 响应
* @return json
*/
private static <T> JsonMessage<T> parseBody(HttpRequest httpRequest, HttpResponse response, NodeModel nodeModel) {
int status = response.getStatus();
String body = response.body();
if (log.isDebugEnabled()) {
log.debug("{}[{}] -> {} {} {} {}", nodeModel.getName(), nodeModel.getWorkspaceId(), httpRequest.getUrl(), httpRequest.getMethod(), Optional.ofNullable((Object) httpRequest.form()).orElse("-"), body);
}
if (status != HttpStatus.HTTP_OK) {
log.warn("{} 响应异常 状态码错误:{} {}", nodeModel.getName(), status, body);
throw new AgentException(nodeModel.getName() + " 节点响应异常,状态码错误:" + status);
}
return toJsonMessage(body);
}
private static <T> JsonMessage<T> toJsonMessage(String body) {
public static <T> T toJsonMessage(String body, TypeReference<T> tTypeReference) {
if (StrUtil.isEmpty(body)) {
throw new AgentException("agent 端响应内容为空");
}
JsonMessage<T> jsonMessage = JSON.parseObject(body, new TypeReference<JsonMessage<T>>() {
});
if (jsonMessage.getCode() == Const.AUTHORIZE_ERROR) {
throw new AuthorizeException(new JsonMessage<>(jsonMessage.getCode(), jsonMessage.getMsg()));
T data = JSON.parseObject(body, tTypeReference);
if (data instanceof JsonMessage) {
JsonMessage<?> jsonMessage = (JsonMessage<?>) data;
if (jsonMessage.getCode() == Const.AUTHORIZE_ERROR) {
throw new AuthorizeException(new JsonMessage<>(jsonMessage.getCode(), jsonMessage.getMsg()));
}
} else {
throw new IllegalStateException("消息转换异常");
}
return jsonMessage;
return data;
}
}

View File

@ -101,7 +101,7 @@ public enum NodeUrl {
Manage_File_GetFileList("/manage/file/getFileList"),
MANAGE_FILE_BACKUP_LIST_BACKUP("/manage/file/list-backup"),
MANAGE_FILE_BACKUP_LIST_ITEM_FILES("/manage/file/backup-item-files"),
MANAGE_FILE_BACKUP_DOWNLOAD("/manage/file/backup-download"),
MANAGE_FILE_BACKUP_DOWNLOAD("/manage/file/backup-download", true),
MANAGE_FILE_BACKUP_DELETE("/manage/file/backup-delete"),
MANAGE_FILE_BACKUP_RECOVER("/manage/file/backup-recover"),
/**
@ -127,7 +127,7 @@ public enum NodeUrl {
MANAGE_FILE_NEW_FILE_FOLDER("/manage/file/new_file_folder.json"),
MANAGE_FILE_RENAME_FILE_FOLDER("/manage/file/rename.json"),
Manage_File_Download("/manage/file/download"),
Manage_File_Download("/manage/file/download", true),
Manage_Log_LogSize("/manage/log/logSize"),
@ -136,16 +136,16 @@ public enum NodeUrl {
Manage_Log_logBack_delete("/manage/log/logBack_delete"),
Manage_Log_logBack_download("/manage/log/logBack_download"),
Manage_Log_logBack_download("/manage/log/logBack_download", true),
Manage_Log_logBack("/manage/log/logBack"),
Manage_Log_export("/manage/log/export.html"),
Manage_Log_export("/manage/log/export.html", true),
Manage_internal_data("/manage/internal_data"),
Manage_internal_stack("/manage/internal_stack"),
Manage_internal_ram("/manage/internal_ram"),
Manage_internal_threadInfos("/manage/threadInfos"),
// Manage_internal_data("/manage/internal_data"),
// Manage_internal_stack("/manage/internal_stack"),
// Manage_internal_ram("/manage/internal_ram"),
// Manage_internal_threadInfos("/manage/threadInfos"),
// /**
// * jdk
@ -173,7 +173,7 @@ public enum NodeUrl {
System_Certificate_saveCertificate("/system/certificate/saveCertificate"),
System_Certificate_getCertList("/system/certificate/getCertList"),
System_Certificate_delete("/system/certificate/delete"),
System_Certificate_export("/system/certificate/export"),
System_Certificate_export("/system/certificate/export", true),
Script_List("/script/list.json"),
SCRIPT_PULL_EXEC_LOG("/script/pull_exec_log"),
@ -225,11 +225,11 @@ public enum NodeUrl {
DelSystemLog("/system/log_del.json"),
DownloadSystemLog("/system/log_download"),
DownloadSystemLog("/system/log_download", true),
/**
* 更新系统jar包
*/
SystemUploadJar("/system/uploadJar.json"),
SystemUploadJar("/system/uploadJar.json", true),
/**
* 更新系统jar包
*/
@ -237,7 +237,7 @@ public enum NodeUrl {
/**
* 远程升级
*/
REMOTE_UPGRADE("/system/remote_upgrade.json"),
REMOTE_UPGRADE("/system/remote_upgrade.json", true),
CHANGE_LOG("/system/change_log"),
/**

View File

@ -95,8 +95,10 @@ public class LogBackController extends BaseServerController {
@RequestMapping(value = "logSize", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public JsonMessage<JSONObject> logSize(String id, String copyId) {
JSONObject info = projectInfoCacheService.getLogSize(getNode(), id, copyId);
return JsonMessage.success("", info);
// JSONObject info = projectInfoCacheService.getLogSize(getNode(), id, copyId);
return NodeForward.request(getNode(), NodeUrl.Manage_Log_LogSize, "id", id, "copyId", copyId);
// return requestData.getData();
// return JsonMessage.success("", info);
}
/**

View File

@ -20,68 +20,90 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package io.jpom.controller.node.monitor;
import io.jpom.common.BaseServerController;
import io.jpom.common.forward.NodeForward;
import io.jpom.common.forward.NodeUrl;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* 内存查看
*
* @author Administrator
*/
@Controller
@RequestMapping(value = "/node/manage/")
public class InternalController extends BaseServerController {
/**
* 获取内存信息接口
* get InternalData
*
* @return json
* @author Hotstrip
*/
@RequestMapping(value = "getInternalData", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String getInternalData() {
return NodeForward.request(getNode(), getRequest(), NodeUrl.Manage_internal_data).toString();
//log.info("data: {}", data == null ? "" : data.toString());
// return JsonMessage.success( "success", data);
}
/**
* 查询监控线程列表
*
* @return json
*/
@RequestMapping(value = "threadInfos", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String threadInfos() {
return NodeForward.request(getNode(), getRequest(), NodeUrl.Manage_internal_threadInfos).toString();
}
/**
* 导出堆栈信息
*/
@RequestMapping(value = "stack", method = RequestMethod.GET)
@ResponseBody
public void stack() {
NodeForward.requestDownload(getNode(), getRequest(), getResponse(), NodeUrl.Manage_internal_stack);
}
/**
* 导出内存信息
*/
@RequestMapping(value = "ram", method = RequestMethod.GET)
@ResponseBody
public void ram() {
NodeForward.requestDownload(getNode(), getRequest(), getResponse(), NodeUrl.Manage_internal_ram);
}
}
///*
// * The MIT License (MIT)
// *
// * Copyright (c) 2019 Code Technology Studio
// *
// * Permission is hereby granted, free of charge, to any person obtaining a copy of
// * this software and associated documentation files (the "Software"), to deal in
// * the Software without restriction, including without limitation the rights to
// * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// * the Software, and to permit persons to whom the Software is furnished to do so,
// * subject to the following conditions:
// *
// * The above copyright notice and this permission notice shall be included in all
// * copies or substantial portions of the Software.
// *
// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// */
//package io.jpom.controller.node.monitor;
//
//import io.jpom.common.BaseServerController;
//import io.jpom.common.forward.NodeForward;
//import io.jpom.common.forward.NodeUrl;
//import org.springframework.http.MediaType;
//import org.springframework.stereotype.Controller;
//import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.RequestMethod;
//import org.springframework.web.bind.annotation.ResponseBody;
//
///**
// * 内存查看
// *
// * @author Administrator
// */
//@Controller
//@RequestMapping(value = "/node/manage/")
//public class InternalController extends BaseServerController {
//
//
// /**
// * 获取内存信息接口
// * get InternalData
// *
// * @return json
// * @author Hotstrip
// */
// @RequestMapping(value = "getInternalData", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
// @ResponseBody
// public String getInternalData() {
// return NodeForward.request(getNode(), getRequest(), NodeUrl.Manage_internal_data).toString();
// //log.info("data: {}", data == null ? "" : data.toString());
//// return JsonMessage.success( "success", data);
// }
//
// /**
// * 查询监控线程列表
// *
// * @return json
// */
// @RequestMapping(value = "threadInfos", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
// @ResponseBody
// public String threadInfos() {
// return NodeForward.request(getNode(), getRequest(), NodeUrl.Manage_internal_threadInfos).toString();
// }
//
// /**
// * 导出堆栈信息
// */
// @RequestMapping(value = "stack", method = RequestMethod.GET)
// @ResponseBody
// public void stack() {
// NodeForward.requestDownload(getNode(), getRequest(), getResponse(), NodeUrl.Manage_internal_stack);
// }
//
// /**
// * 导出内存信息
// */
// @RequestMapping(value = "ram", method = RequestMethod.GET)
// @ResponseBody
// public void ram() {
// NodeForward.requestDownload(getNode(), getRequest(), getResponse(), NodeUrl.Manage_internal_ram);
// }
//}

View File

@ -94,7 +94,7 @@ public class NodeScriptTriggerApiController extends BaseJpomController {
JSONObject reqData = new JSONObject();
reqData.put("id", item.getScriptId());
reqData.put("params", JSONObject.toJSONString(ServletUtil.getParamMap(getRequest())));
JsonMessage<String> jsonMessage = NodeForward.request(nodeModel, NodeUrl.SCRIPT_EXEC, userModel, reqData);
JsonMessage<String> jsonMessage = NodeForward.request(nodeModel, NodeUrl.SCRIPT_EXEC, reqData);
//
JSONObject jsonObject = new JSONObject();
if (jsonMessage.getCode() == 200) {
@ -158,7 +158,7 @@ public class NodeScriptTriggerApiController extends BaseJpomController {
NodeModel nodeModel = nodeService.getByKey(item.getNodeId());
JSONObject reqData = new JSONObject();
reqData.put("id", item.getScriptId());
JsonMessage<String> jsonMessage = NodeForward.request(nodeModel, NodeUrl.SCRIPT_EXEC, userModel, reqData);
JsonMessage<String> jsonMessage = NodeForward.request(nodeModel, NodeUrl.SCRIPT_EXEC, reqData);
//
if (jsonMessage.getCode() == 200) {
jsonObject.put("logId", jsonMessage.getData());

View File

@ -90,7 +90,7 @@ public class ProjectTriggerApiController extends BaseJpomController {
NodeUrl resolveAction = this.resolveAction(action);
//
NodeModel nodeModel = nodeService.getByKey(item.getNodeId());
return NodeForward.requestBySys(nodeModel, resolveAction,
return NodeForward.request(nodeModel, resolveAction,
"id", item.getProjectId(), "getCopy", "true");
}

View File

@ -43,7 +43,6 @@ import io.jpom.model.data.NodeModel;
import io.jpom.model.enums.BuildReleaseMethod;
import io.jpom.model.outgiving.OutGivingModel;
import io.jpom.model.outgiving.OutGivingNodeProject;
import io.jpom.model.user.UserModel;
import io.jpom.permission.ClassFeature;
import io.jpom.permission.Feature;
import io.jpom.permission.MethodFeature;
@ -234,7 +233,6 @@ public class OutGivingController extends BaseServerController {
OutGivingModel outGivingServerItem = outGivingServer.getByKey(id, request);
UserModel userModel = getUser();
// 解除项目分发独立分发属性
List<OutGivingNodeProject> outGivingNodeProjectList = outGivingServerItem.outGivingNodeProjectList();
if (outGivingNodeProjectList != null) {
@ -242,7 +240,8 @@ public class OutGivingController extends BaseServerController {
NodeModel item = nodeService.getByKey(outGivingNodeProject.getNodeId());
JSONObject jsonObject = new JSONObject();
jsonObject.put("id", outGivingNodeProject.getProjectId());
NodeForward.request(item, NodeUrl.Manage_ReleaseOutGiving, userModel, jsonObject);
JsonMessage<String> message = NodeForward.request(item, NodeUrl.Manage_ReleaseOutGiving, jsonObject);
Assert.state(message.success(), "释放节点项目失败:" + message.getMsg());
});
}

View File

@ -125,7 +125,7 @@ public class OutGivingProjectController extends BaseServerController {
JSONObject projectInfo = null;
try {
projectInfo = projectInfoCacheService.getItem(nodeModel, outGivingNodeProject.getProjectId());
projectStatus = NodeForward.requestBySys(nodeModel, NodeUrl.Manage_GetProjectStatus, "id", outGivingNodeProject.getProjectId()).toJson();
projectStatus = NodeForward.request(nodeModel, NodeUrl.Manage_GetProjectStatus, "id", outGivingNodeProject.getProjectId()).toJson();
} catch (Exception e) {
jsonObject.put("errorMsg", "error " + e.getMessage());
}

View File

@ -45,7 +45,6 @@ import io.jpom.model.data.ServerWhitelist;
import io.jpom.model.enums.BuildReleaseMethod;
import io.jpom.model.outgiving.OutGivingModel;
import io.jpom.model.outgiving.OutGivingNodeProject;
import io.jpom.model.user.UserModel;
import io.jpom.permission.ClassFeature;
import io.jpom.permission.Feature;
import io.jpom.permission.MethodFeature;
@ -132,13 +131,12 @@ public class OutGivingProjectEditController extends BaseServerController {
//
Assert.state(outGivingModel.outGivingProject(), "该项目不是节点分发项目,不能在此次删除");
UserModel userModel = getUser();
List<OutGivingNodeProject> deleteNodeProject = outGivingModel.outGivingNodeProjectList();
if (deleteNodeProject != null) {
// 删除实际的项目
for (OutGivingNodeProject outGivingNodeProject1 : deleteNodeProject) {
NodeModel nodeModel = nodeService.getByKey(outGivingNodeProject1.getNodeId());
JsonMessage<String> jsonMessage = this.deleteNodeProject(nodeModel, userModel, outGivingNodeProject1.getProjectId(), thorough);
JsonMessage<String> jsonMessage = this.deleteNodeProject(nodeModel, outGivingNodeProject1.getProjectId(), thorough);
if (jsonMessage.getCode() != HttpStatus.HTTP_OK) {
return new JsonMessage<>(406, nodeModel.getName() + "节点失败:" + jsonMessage.getMsg());
}
@ -190,7 +188,6 @@ public class OutGivingProjectEditController extends BaseServerController {
// }
// return JsonMessage.getString(405, "数据异常,请重新操作");
// }
UserModel userModel = getUser();
List<Tuple> success = new ArrayList<>();
boolean fail = false;
try {
@ -198,7 +195,7 @@ public class OutGivingProjectEditController extends BaseServerController {
NodeModel nodeModel = tuple.get(0);
JSONObject data = tuple.get(1);
//
JsonMessage<String> jsonMessage = this.sendData(nodeModel, userModel, data, true);
JsonMessage<String> jsonMessage = this.sendData(nodeModel, data, true);
if (jsonMessage.getCode() != HttpStatus.HTTP_OK) {
if (!edit) {
fail = true;
@ -221,7 +218,7 @@ public class OutGivingProjectEditController extends BaseServerController {
if (fail) {
try {
for (Tuple entry : success) {
deleteNodeProject(entry.get(0), userModel, outGivingModel.getId(), null);
deleteNodeProject(entry.get(0), outGivingModel.getId(), null);
}
} catch (Exception e) {
log.error("还原项目失败", e);
@ -235,15 +232,15 @@ public class OutGivingProjectEditController extends BaseServerController {
* 删除项目
*
* @param nodeModel 节点
* @param userModel 用户
* @param project 判断id
* @param thorough 是否彻底删除
* @return json
*/
private JsonMessage<String> deleteNodeProject(NodeModel nodeModel, UserModel userModel, String project, String thorough) {
private JsonMessage<String> deleteNodeProject(NodeModel nodeModel, String project, String thorough) {
JSONObject data = new JSONObject();
data.put("id", project);
data.put("thorough", thorough);
JsonMessage<String> request = NodeForward.request(nodeModel, NodeUrl.Manage_DeleteProject, userModel, data);
JsonMessage<String> request = NodeForward.request(nodeModel, NodeUrl.Manage_DeleteProject, data);
if (request.getCode() == HttpStatus.HTTP_OK) {
// 同步项目信息
projectInfoCacheService.syncNode(nodeModel, project);
@ -339,7 +336,6 @@ public class OutGivingProjectEditController extends BaseServerController {
outGivingModel.setAfterOpt(afterOpt1.getCode());
JSONObject defData = getDefData(outGivingModel, edit);
UserModel userModel = getUser();
//
List<OutGivingModel> outGivingModels = outGivingServer.list();
List<OutGivingNodeProject> outGivingNodeProjects = new ArrayList<>();
@ -399,12 +395,12 @@ public class OutGivingProjectEditController extends BaseServerController {
allData.put("name_" + copyId, nameArgs);
}
}
JsonMessage<String> jsonMessage = this.sendData(nodeModel, userModel, allData, false);
JsonMessage<String> jsonMessage = this.sendData(nodeModel, allData, false);
Assert.state(jsonMessage.getCode() == HttpStatus.HTTP_OK, nodeModel.getName() + "节点失败:" + jsonMessage.getMsg());
tuples.add(new Tuple(nodeModel, allData));
}
// 删除已经删除的项目
deleteProject(outGivingModel, outGivingNodeProjects, userModel);
deleteProject(outGivingModel, outGivingNodeProjects);
outGivingModel.outGivingNodeProjectList(outGivingNodeProjects);
//
@ -422,9 +418,8 @@ public class OutGivingProjectEditController extends BaseServerController {
*
* @param outGivingModel 分发项目
* @param outGivingNodeProjects 新的节点项目
* @param userModel 用户
*/
private void deleteProject(OutGivingModel outGivingModel, List<OutGivingNodeProject> outGivingNodeProjects, UserModel userModel) {
private void deleteProject(OutGivingModel outGivingModel, List<OutGivingNodeProject> outGivingNodeProjects) {
Assert.state(CollUtil.size(outGivingNodeProjects) >= 1, "至少选择一个节点及以上");
// 删除
List<OutGivingNodeProject> deleteNodeProject = outGivingModel.getDelete(outGivingNodeProjects);
@ -435,18 +430,18 @@ public class OutGivingProjectEditController extends BaseServerController {
NodeModel nodeModel = nodeService.getByKey(outGivingNodeProject1.getNodeId());
//outGivingNodeProject1.getNodeData(true);
// 调用彻底删除
jsonMessage = this.deleteNodeProject(nodeModel, userModel, outGivingNodeProject1.getProjectId(), "thorough");
jsonMessage = this.deleteNodeProject(nodeModel, outGivingNodeProject1.getProjectId(), "thorough");
Assert.state(jsonMessage.getCode() == HttpStatus.HTTP_OK, nodeModel.getName() + "节点失败:" + jsonMessage.getMsg());
}
}
}
private JsonMessage<String> sendData(NodeModel nodeModel, UserModel userModel, JSONObject data, boolean save) {
private JsonMessage<String> sendData(NodeModel nodeModel, JSONObject data, boolean save) {
if (save) {
data.remove("previewData");
}
data.put("outGivingProject", true);
// 发起预检查数据
return NodeForward.request(nodeModel, NodeUrl.Manage_SaveProject, userModel, data);
return NodeForward.request(nodeModel, NodeUrl.Manage_SaveProject, data);
}
}

View File

@ -139,12 +139,12 @@ public class ScriptController extends BaseServerController {
return JsonMessage.success("修改成功");
}
private void syncDelNodeScript(ScriptModel scriptModel, UserModel user, Collection<String> delNode) {
private void syncDelNodeScript(ScriptModel scriptModel, Collection<String> delNode) {
for (String s : delNode) {
NodeModel byKey = nodeService.getByKey(s, getRequest());
JSONObject jsonObject = new JSONObject();
jsonObject.put("id", scriptModel.getId());
JsonMessage<String> request = NodeForward.request(byKey, NodeUrl.Script_Del, user, jsonObject);
JsonMessage<String> request = NodeForward.request(byKey, NodeUrl.Script_Del, jsonObject);
Assert.state(request.getCode() == 200, "处理 " + byKey.getName() + " 节点删除脚本失败" + request.getMsg());
nodeScriptServer.syncNode(byKey);
}
@ -154,9 +154,8 @@ public class ScriptController extends BaseServerController {
List<String> oldNodeIds = StrUtil.splitTrim(oldNode, StrUtil.COMMA);
List<String> newNodeIds = StrUtil.splitTrim(scriptModel.getNodeIds(), StrUtil.COMMA);
Collection<String> delNode = CollUtil.subtract(oldNodeIds, newNodeIds);
UserModel user = getUser();
// 删除
this.syncDelNodeScript(scriptModel, user, delNode);
this.syncDelNodeScript(scriptModel, delNode);
// 更新
for (String newNodeId : newNodeIds) {
NodeModel byKey = nodeService.getByKey(newNodeId, getRequest());
@ -169,8 +168,8 @@ public class ScriptController extends BaseServerController {
jsonObject.put("description", scriptModel.getDescription());
jsonObject.put("name", scriptModel.getName());
jsonObject.put("workspaceId", scriptModel.getWorkspaceId());
JsonMessage<String> request = NodeForward.request(byKey, NodeUrl.Script_Save, user, jsonObject);
Assert.state(request.getCode() == 200, "处理 " + byKey.getName() + " 节点同步脚本失败" + request.getMsg());
JsonMessage<String> request = NodeForward.request(byKey, NodeUrl.Script_Save, jsonObject);
Assert.state(request.success(), "处理 " + byKey.getName() + " 节点同步脚本失败" + request.getMsg());
nodeScriptServer.syncNode(byKey);
}
}
@ -187,7 +186,7 @@ public class ScriptController extends BaseServerController {
// 删除节点中的脚本
String nodeIds = server.getNodeIds();
List<String> delNode = StrUtil.splitTrim(nodeIds, StrUtil.COMMA);
this.syncDelNodeScript(server, getUser(), delNode);
this.syncDelNodeScript(server, delNode);
scriptServer.delByKey(id, request);
//
scriptExecuteLogServer.delByWorkspace(request, entity -> entity.set("scriptId", id));

View File

@ -45,7 +45,6 @@ import io.jpom.common.validator.ValidatorItem;
import io.jpom.model.data.NodeModel;
import io.jpom.model.data.SystemIpConfigModel;
import io.jpom.model.node.NodeAgentWhitelist;
import io.jpom.model.user.UserModel;
import io.jpom.permission.ClassFeature;
import io.jpom.permission.Feature;
import io.jpom.permission.MethodFeature;
@ -302,11 +301,10 @@ public class SystemConfigController extends BaseServerController {
systemParametersServer.upsert(format, agentWhitelist, format);
//
List<String> nodeIdsStr = StrUtil.splitTrim(nodeIds, StrUtil.COMMA);
UserModel user = getUser();
for (String s : nodeIdsStr) {
NodeModel byKey = nodeService.getByKey(s, httpServletRequest);
JSONObject jsonObject = (JSONObject) JSON.toJSON(agentWhitelist);
JsonMessage<String> request = NodeForward.request(byKey, NodeUrl.WhitelistDirectory_Submit, user, jsonObject);
JsonMessage<String> request = NodeForward.request(byKey, NodeUrl.WhitelistDirectory_Submit, jsonObject);
Assert.state(request.getCode() == 200, "分发 " + byKey.getName() + " 节点配置失败" + request.getMsg());
}
return JsonMessage.success("保存成功");
@ -339,13 +337,12 @@ public class SystemConfigController extends BaseServerController {
systemParametersServer.upsert(id, jsonObject, id);
//
List<String> nodeIdsStr = StrUtil.splitTrim(nodeIds, StrUtil.COMMA);
UserModel user = getUser();
for (String s : nodeIdsStr) {
NodeModel byKey = nodeService.getByKey(s, httpServletRequest);
JSONObject reqData = new JSONObject();
reqData.put("content", content);
reqData.put("restart", restart);
JsonMessage<String> request = NodeForward.request(byKey, NodeUrl.SystemSaveConfig, user, reqData);
JsonMessage<String> request = NodeForward.request(byKey, NodeUrl.SystemSaveConfig, reqData);
Assert.state(request.getCode() == 200, "分发 " + byKey.getName() + " 节点配置失败" + request.getMsg());
}
return JsonMessage.success("修改成功");

View File

@ -38,7 +38,6 @@ import io.jpom.common.validator.ValidatorRule;
import io.jpom.model.PageResultDto;
import io.jpom.model.data.NodeModel;
import io.jpom.model.data.WorkspaceEnvVarModel;
import io.jpom.model.user.UserModel;
import io.jpom.permission.ClassFeature;
import io.jpom.permission.Feature;
import io.jpom.permission.MethodFeature;
@ -149,14 +148,14 @@ public class WorkspaceEnvVarController extends BaseServerController {
return JsonMessage.success("操作成功");
}
private void syncDelNodeEnvVar(String name, UserModel user, Collection<String> delNode, String workspaceId) {
private void syncDelNodeEnvVar(String name, Collection<String> delNode, String workspaceId) {
for (String s : delNode) {
NodeModel byKey = nodeService.getByKey(s);
Assert.state(StrUtil.equals(workspaceId, byKey.getWorkspaceId()), "选择节点错误");
JSONObject jsonObject = new JSONObject();
jsonObject.put("name", name);
JsonMessage<String> jsonMessage = NodeForward.request(byKey, NodeUrl.Workspace_EnvVar_Delete, user, jsonObject);
Assert.state(jsonMessage.getCode() == 200, "处理 " + byKey.getName() + " 节点删除脚本失败" + jsonMessage.getMsg());
JsonMessage<String> jsonMessage = NodeForward.request(byKey, NodeUrl.Workspace_EnvVar_Delete, jsonObject);
Assert.state(jsonMessage.success(), "处理 " + byKey.getName() + " 节点删除脚本失败" + jsonMessage.getMsg());
}
}
@ -165,9 +164,8 @@ public class WorkspaceEnvVarController extends BaseServerController {
List<String> newNodeIds = StrUtil.splitTrim(workspaceEnvVarModel.getNodeIds(), StrUtil.COMMA);
List<String> oldNodeIds = StrUtil.splitTrim(oldNode, StrUtil.COMMA);
Collection<String> delNode = CollUtil.subtract(oldNodeIds, newNodeIds);
UserModel user = getUser();
// 删除
this.syncDelNodeEnvVar(workspaceEnvVarModel.getName(), user, delNode, workspaceId);
this.syncDelNodeEnvVar(workspaceEnvVarModel.getName(), delNode, workspaceId);
// 更新
for (String newNodeId : newNodeIds) {
NodeModel byKey = nodeService.getByKey(newNodeId);
@ -182,7 +180,7 @@ public class WorkspaceEnvVarController extends BaseServerController {
WorkspaceEnvVarModel byKeyExits = workspaceEnvVarService.getByKey(workspaceEnvVarModel.getId());
jsonObject.put("value", byKeyExits.getValue());
}
JsonMessage<String> jsonMessage = NodeForward.request(byKey, NodeUrl.Workspace_EnvVar_Update, user, jsonObject);
JsonMessage<String> jsonMessage = NodeForward.request(byKey, NodeUrl.Workspace_EnvVar_Update, jsonObject);
Assert.state(jsonMessage.getCode() == 200, "处理 " + byKey.getName() + " 节点同步脚本失败" + jsonMessage.getMsg());
}
}
@ -219,7 +217,7 @@ public class WorkspaceEnvVarController extends BaseServerController {
Assert.state(StrUtil.equals(workspaceId, byKey.getWorkspaceId()), "选择工作空间错误");
String oldNodeIds = byKey.getNodeIds();
List<String> delNode = StrUtil.splitTrim(oldNodeIds, StrUtil.COMMA);
this.syncDelNodeEnvVar(byKey.getName(), getUser(), delNode, workspaceId);
this.syncDelNodeEnvVar(byKey.getName(), delNode, workspaceId);
// 删除信息
workspaceEnvVarService.delByKey(id);
return JsonMessage.success("删除成功");

View File

@ -33,6 +33,7 @@ import io.jpom.service.h2db.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import top.jpom.transport.INodeInfo;
import java.net.InetSocketAddress;
import java.net.Proxy;
@ -48,7 +49,7 @@ import java.util.List;
@TableName(value = "NODE_INFO", name = "节点信息")
@Data
@NoArgsConstructor
public class NodeModel extends BaseGroupModel {
public class NodeModel extends BaseGroupModel implements INodeInfo {
private String url;
private String loginName;
@ -115,11 +116,32 @@ public class NodeModel extends BaseGroupModel {
return StrUtil.format("{}://{}{}", getProtocol().toLowerCase(), getUrl(), nodeUrl.getUrl());
}
@Override
public String name() {
return this.getName();
}
@Override
public String url() {
return this.getUrl();
}
@Override
public String scheme() {
return getProtocol();
}
@Override
public String authorize() {
return this.toAuthorize();
}
/**
* 获取节点的代理
*
* @return proxy
*/
@Override
public Proxy proxy() {
String httpProxy = this.getHttpProxy();
if (StrUtil.isNotEmpty(httpProxy)) {

View File

@ -31,7 +31,6 @@ import cn.hutool.cron.task.Task;
import cn.hutool.db.sql.Direction;
import cn.hutool.db.sql.Order;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HttpStatus;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import io.jpom.common.JsonMessage;
@ -119,8 +118,8 @@ public class MonitorItem implements Task {
String context;
try {
//查询项目运行状态
JsonMessage<JSONObject> jsonMessage = NodeForward.requestBySys(nodeModel, NodeUrl.Manage_GetProjectStatus, "id", id, "getCopy", true);
if (jsonMessage.getCode() == HttpStatus.HTTP_OK) {
JsonMessage<JSONObject> jsonMessage = NodeForward.request(nodeModel, NodeUrl.Manage_GetProjectStatus, "id", id, "getCopy", true);
if (jsonMessage.success()) {
JSONObject jsonObject = jsonMessage.getData();
int pid = jsonObject.getIntValue("pId");
boolean runStatus = this.checkNotify(monitorModel, nodeModel, id, null, pid > 0);
@ -198,8 +197,8 @@ public class MonitorItem implements Task {
if (monitorModel.autoRestart()) {
// 执行重启
try {
JsonMessage<String> reJson = NodeForward.requestBySys(nodeModel, NodeUrl.Manage_Restart, "id", id, "copyId", copyId);
if (reJson.getCode() == HttpStatus.HTTP_OK) {
JsonMessage<String> reJson = NodeForward.request(nodeModel, NodeUrl.Manage_Restart, "id", id, "copyId", copyId);
if (reJson.success()) {
// 重启成功
runStatus = true;
title = StrUtil.format("【{}】节点的【{}】项目{}已经停止,已经执行重启操作,结果成功", nodeModel.getName(), id, copyMsg);

View File

@ -113,7 +113,7 @@ public class OutGivingItemRun implements Callable<OutGivingNodeProject.Status> {
this.outGivingNodeProject.getProjectId(),
unzip,
afterOpt,
this.nodeModel, this.userModel, this.clearOld,
this.nodeModel, this.clearOld,
this.sleepTime, this.closeFirst);
if (jsonMessage.getCode() == HttpStatus.HTTP_OK) {
result = OutGivingNodeProject.Status.Ok;

View File

@ -114,7 +114,6 @@ public class OutGivingRun {
* @param unzip 是否需要解压
* @param afterOpt 是否需要重启
* @param nodeModel 节点
* @param userModel 操作用户
* @param clearOld 清空发布
* @param levelName 文件夹层级
* @param closeFirst 保存项目文件前先关闭项目
@ -124,9 +123,9 @@ public class OutGivingRun {
boolean unzip,
AfterOpt afterOpt,
NodeModel nodeModel,
UserModel userModel,
boolean clearOld, Boolean closeFirst) {
return fileUpload(file, levelName, projectId, unzip, afterOpt, nodeModel, userModel, clearOld, null, closeFirst);
return fileUpload(file, levelName, projectId, unzip, afterOpt, nodeModel, clearOld, null, closeFirst);
}
/**
@ -137,7 +136,6 @@ public class OutGivingRun {
* @param unzip 是否需要解压
* @param afterOpt 是否需要重启
* @param nodeModel 节点
* @param userModel 操作用户
* @param clearOld 清空发布
* @param levelName 文件夹层级
* @param sleepTime 休眠时间
@ -148,7 +146,6 @@ public class OutGivingRun {
boolean unzip,
AfterOpt afterOpt,
NodeModel nodeModel,
UserModel userModel,
boolean clearOld,
Integer sleepTime,
Boolean closeFirst) {
@ -171,6 +168,6 @@ public class OutGivingRun {
data.put("after", afterOpt.getCode());
}
data.put("closeFirst", closeFirst);
return NodeForward.request(nodeModel, NodeUrl.Manage_File_Upload, userModel, data);
return NodeForward.request(nodeModel, NodeUrl.Manage_File_Upload, data);
}
}

View File

@ -30,7 +30,6 @@ import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Entity;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.extra.spring.SpringUtil;
import io.jpom.common.Const;
import io.jpom.common.JpomManifest;
import io.jpom.common.JsonMessage;
@ -93,7 +92,7 @@ public class NodeService extends BaseGroupService<NodeModel> {
// 检查是否可用默认为5秒避免太长时间无法连接一直等待
nodeModel.setTimeOut(5);
//
JsonMessage<JpomManifest> objectJsonMessage = NodeForward.requestBySys(nodeModel, NodeUrl.Info, "nodeId", nodeModel.getId());
JsonMessage<JpomManifest> objectJsonMessage = NodeForward.request(nodeModel, NodeUrl.Info, "nodeId", nodeModel.getId());
try {
JpomManifest jpomManifest = objectJsonMessage.getData(JpomManifest.class);
Assert.notNull(jpomManifest, "节点连接失败,请检查节点是否在线");

View File

@ -25,6 +25,7 @@ package io.jpom.service.node;
import cn.hutool.db.Entity;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import io.jpom.common.JsonMessage;
import io.jpom.common.forward.NodeForward;
import io.jpom.common.forward.NodeUrl;
import io.jpom.model.data.NodeModel;
@ -58,7 +59,8 @@ public class ProjectInfoCacheService extends BaseNodeService<ProjectInfoCacheMod
*/
@Override
public JSONObject getItem(NodeModel nodeModel, String id) {
return NodeForward.requestData(nodeModel, NodeUrl.Manage_GetProjectItem, JSONObject.class, "id", id);
JsonMessage<JSONObject> request = NodeForward.request(nodeModel, NodeUrl.Manage_GetProjectItem, "id", id);
return request.getData();
}
public boolean exists(String workspaceId, String nodeId, String id) {
@ -77,14 +79,16 @@ public class ProjectInfoCacheService extends BaseNodeService<ProjectInfoCacheMod
return this.exists(nodeModel.getWorkspaceId(), nodeId, id);
}
public JSONObject getLogSize(NodeModel nodeModel, String id, String copyId) {
return NodeForward.requestData(nodeModel, NodeUrl.Manage_Log_LogSize, JSONObject.class, "id", id, "copyId", copyId);
}
// public JSONObject getLogSize(NodeModel nodeModel, String id, String copyId) {
//
//// return requestData;
// }
@Override
public JSONArray getLitDataArray(NodeModel nodeModel) {
return NodeForward.requestData(nodeModel, NodeUrl.Manage_GetProjectInfo, JSONArray.class, "notStatus", "true");
JsonMessage<JSONArray> tJsonMessage = NodeForward.request(nodeModel, NodeUrl.Manage_GetProjectInfo, "notStatus", "true");
return tJsonMessage.getData();
}
@Override

View File

@ -75,8 +75,8 @@ public class NodeScriptExecuteLogServer extends BaseNodeService<ScriptExecuteLog
@Override
public JSONArray getLitDataArray(NodeModel nodeModel) {
JsonMessage<?> jsonMessage = NodeForward.requestBySys(nodeModel, NodeUrl.SCRIPT_PULL_EXEC_LOG, "pullCount", 100);
if (jsonMessage.getCode() != HttpStatus.HTTP_OK) {
JsonMessage<?> jsonMessage = NodeForward.request(nodeModel, NodeUrl.SCRIPT_PULL_EXEC_LOG, "pullCount", 100);
if (!jsonMessage.success()) {
throw new AgentException(jsonMessage.toString());
}
Object data = jsonMessage.getData();
@ -153,7 +153,7 @@ public class NodeScriptExecuteLogServer extends BaseNodeService<ScriptExecuteLog
executeLogModel -> {
try {
NodeModel nodeModel = nodeService.getByKey(executeLogModel.getNodeId());
JsonMessage<Object> jsonMessage = NodeForward.requestBySys(nodeModel, NodeUrl.SCRIPT_DEL_LOG,
JsonMessage<Object> jsonMessage = NodeForward.request(nodeModel, NodeUrl.SCRIPT_DEL_LOG,
"id", executeLogModel.getScriptId(), "executeId", executeLogModel.getId());
if (jsonMessage.getCode() != HttpStatus.HTTP_OK) {
log.warn("{} {} {}", executeLogModel.getNodeId(), executeLogModel.getScriptName(), jsonMessage);

View File

@ -150,10 +150,10 @@ public class NodeStatService extends BaseWorkspaceService<NodeStatModel> impleme
JSONObject nodeTopInfo = this.getNodeTopInfo(nodeModel);
//
long timeMillis = SystemClock.now();
JsonMessage<Object> jsonMessage = NodeForward.requestBySys(nodeModel, NodeUrl.Status, "nodeId", nodeModel.getId());
JsonMessage<Object> jsonMessage = NodeForward.request(nodeModel, NodeUrl.Status, "nodeId", nodeModel.getId());
int networkTime = (int) (System.currentTimeMillis() - timeMillis);
JSONObject jsonObject;
if (jsonMessage.getCode() == 200) {
if (jsonMessage.success()) {
jsonObject = jsonMessage.getData(JSONObject.class);
} else {
// 状态码错

View File

@ -24,6 +24,7 @@ package io.jpom.socket.handler;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.FileResource;
import cn.hutool.core.lang.Tuple;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
@ -213,7 +214,9 @@ public class NodeUpdateHandler extends BaseProxyHandler {
private void updateNodeItemHttp(NodeModel nodeModel, WebSocketSession session, AgentFileModel agentFileModel) {
File file = FileUtil.file(agentFileModel.getSavePath());
JsonMessage<String> message = NodeForward.requestMultipart(nodeModel, "file", file, NodeUrl.SystemUploadJar);
JSONObject jsonObject = new JSONObject();
jsonObject.put("file", new FileResource(file));
JsonMessage<String> message = NodeForward.request(nodeModel, NodeUrl.SystemUploadJar, jsonObject);
String id = nodeModel.getId();
WebSocketMessageModel callbackRestartMessage = new WebSocketMessageModel("restart", id);
callbackRestartMessage.setData(message.getMsg());
@ -226,8 +229,8 @@ public class NodeUpdateHandler extends BaseProxyHandler {
++retryCount;
try {
ThreadUtil.sleep(1000L);
JsonMessage<Object> jsonMessage = NodeForward.requestBySys(nodeModel, NodeUrl.Info, "nodeId", id);
if (jsonMessage.getCode() == HttpStatus.HTTP_OK) {
JsonMessage<Object> jsonMessage = NodeForward.request(nodeModel, NodeUrl.Info, "nodeId", id);
if (jsonMessage.success()) {
this.sendMsg(callbackRestartMessage.setData("重启完成"), session);
return;
}

View File

@ -113,7 +113,7 @@ public class CheckMonitor implements InitializingBean {
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("ids", strings);
JsonMessage<Object> jsonMessage = NodeForward.requestBody(nodeModel, NodeUrl.SCRIPT_DEL_EXEC_LOG, null, jsonObject);
JsonMessage<Object> jsonMessage = NodeForward.requestBody(nodeModel, NodeUrl.SCRIPT_DEL_EXEC_LOG, jsonObject);
if (jsonMessage.getCode() != HttpStatus.HTTP_OK) {
log.error("删除脚本模版执行数据错误:{}", jsonMessage);
}

View File

@ -0,0 +1 @@
io.jpom.common.forward.JsonMessageTransformServer

View File

@ -84,4 +84,10 @@
<level value="INFO"/>
<appender-ref ref="LOG-ROOT"/>
</logger>
<logger name="top.jpom" additivity="false">
<!--建议使用 info 级别-->
<level value="INFO"/>
<appender-ref ref="LOG-ROOT"/>
</logger>
</configuration>

View File

@ -88,4 +88,10 @@
<appender-ref ref="LOG-ROOT"/>
<appender-ref ref="STDOUT"/>
</logger>
<logger name="top.jpom" additivity="false">
<level value="debug"/>
<appender-ref ref="LOG-ROOT"/>
<appender-ref ref="STDOUT"/>
</logger>
</configuration>

View File

@ -100,6 +100,12 @@
<!-- 注意这里是import -->
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>${fastjson2.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>