diff --git a/README.md b/README.md index 1d7f40a..f6e77d2 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ # open-JSD-9468 -JSD-9468 定时调度消息推送 \ No newline at end of file +JSD-9468 定时调度消息推送\ +免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ +仅作为开发者学习参考使用!禁止用于任何商业用途!\ +为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系hugh处理。 \ No newline at end of file diff --git a/doc/JSD-9468配置使用文档.docx b/doc/JSD-9468配置使用文档.docx new file mode 100644 index 0000000..56a73a0 Binary files /dev/null and b/doc/JSD-9468配置使用文档.docx differ diff --git a/doc/JSD-9797配置使用文档.docx b/doc/JSD-9797配置使用文档.docx new file mode 100644 index 0000000..07c8d18 Binary files /dev/null and b/doc/JSD-9797配置使用文档.docx differ diff --git a/doc/jsd-9468任务需求文档v1.docx b/doc/jsd-9468任务需求文档v1.docx new file mode 100644 index 0000000..7dc4e81 Binary files /dev/null and b/doc/jsd-9468任务需求文档v1.docx differ diff --git a/doc/jsd-9797-任务需求文档v1.docx b/doc/jsd-9797-任务需求文档v1.docx new file mode 100644 index 0000000..0c2e8bc Binary files /dev/null and b/doc/jsd-9797-任务需求文档v1.docx differ diff --git a/lib/finekit-10.0.jar b/lib/finekit-10.0.jar new file mode 100644 index 0000000..f4482fc Binary files /dev/null and b/lib/finekit-10.0.jar differ diff --git a/plugin.xml b/plugin.xml new file mode 100644 index 0000000..6ac0eeb --- /dev/null +++ b/plugin.xml @@ -0,0 +1,29 @@ + + + com.fr.plugin.idfh.v10 + + yes + 1.3.2 + 10.0 + 2018-07-31 + fr.open + + + 定时调度数据接口处理,实现提交数据给HTTP接口功能。
+ ]]>
+ com.fr.plugin.idfh + + com.fanruan.api + + + + + + + + + + + +
\ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idfh/Constants.java b/src/main/java/com/fr/plugin/idfh/Constants.java new file mode 100644 index 0000000..bf729fe --- /dev/null +++ b/src/main/java/com/fr/plugin/idfh/Constants.java @@ -0,0 +1,19 @@ + /* + * Copyright (C), 2018-2021 + * Project: starter + * FileName: Constants + * Author: Louis + * Date: 2021/2/21 16:11 + */ + package com.fr.plugin.idfh; + + /** + *
+ * + * + * @author fr.open + * @since 1.0.0 + */ + public class Constants { + public static final String PLUGIN_ID = "com.fr.plugin.idfh.v10"; + } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idfh/LocaleFinder.java b/src/main/java/com/fr/plugin/idfh/LocaleFinder.java new file mode 100644 index 0000000..c127fd6 --- /dev/null +++ b/src/main/java/com/fr/plugin/idfh/LocaleFinder.java @@ -0,0 +1,30 @@ + /* + * Copyright (C), 2018-2020 + * Project: starter + * FileName: LocaleFinder + * Author: Louis + * Date: 2020/8/31 22:19 + */ + package com.fr.plugin.idfh; + + import com.fr.stable.fun.impl.AbstractLocaleFinder; + + /** + *
+ * + * + * @author fr.open + * @since 1.0.0 + */ + public class LocaleFinder extends AbstractLocaleFinder { + + @Override + public String find() { + return "com/fr/plugin/idfh/locale/lang"; + } + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } + } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idfh/action/AbstractDataOutput.java b/src/main/java/com/fr/plugin/idfh/action/AbstractDataOutput.java new file mode 100644 index 0000000..01fc934 --- /dev/null +++ b/src/main/java/com/fr/plugin/idfh/action/AbstractDataOutput.java @@ -0,0 +1,64 @@ + /* + * Copyright (C), 2018-2021 + * Project: starter + * FileName: AbstractDataOutput + * Author: Louis + * Date: 2021/4/12 15:13 + */ + package com.fr.plugin.idfh.action; + + import com.fanruan.api.i18n.I18nKit; + import com.fanruan.api.util.StringKit; + import com.fr.schedule.feature.output.OutputActionHandler; + + import java.util.HashMap; + import java.util.Map; + + /** + *
+ * + * + * @author fr.open + * @since 1.0.0 + */ + public abstract class AbstractDataOutput extends OutputActionHandler { + @Override + public void doAction(OutputHttp outputHttp, Map taskParams) throws Exception { + this.checkOutputHttp(outputHttp); + Map bodyParams = getHttpParams(outputHttp.getBodyParameters()); + if (bodyParams.isEmpty()) { + return; + } + Map headers = getHttpParams(outputHttp.getHeaders()); + checkHeader(headers); + operation(outputHttp, taskParams, bodyParams, headers); + } + + /** + * 根据参数名在定时调度任务参数结果中,提取参数值信息 + * + * @return + * @throws Exception + */ + private Map getHttpParams(String paramsStr) { + String[] params = paramsStr.split(";"); + String[] keyAndValue; + Map result = new HashMap<>(); + for (String content : params) { + keyAndValue = content.split("="); + result.put(keyAndValue[0], keyAndValue[1]); + } + return result; + } + + public void checkOutputHttp(OutputHttp outputHttp) throws Exception { + if (outputHttp == null || StringKit.isBlank(outputHttp.getApiUrl())) { + throw new Exception(I18nKit.getLocText("Plugin-httpaction_Link_Valid")); + } + } + + public void checkHeader(Map headers) throws Exception { + } + + public abstract void operation(OutputHttp outputHttp, Map taskParams, Map bodyParams, Map headers) throws Exception; + } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idfh/action/GetOutput.java b/src/main/java/com/fr/plugin/idfh/action/GetOutput.java new file mode 100644 index 0000000..c025c77 --- /dev/null +++ b/src/main/java/com/fr/plugin/idfh/action/GetOutput.java @@ -0,0 +1,30 @@ + /* + * Copyright (C), 2018-2021 + * Project: starter + * FileName: GetOutput + * Author: Louis + * Date: 2021/4/12 15:16 + */ + package com.fr.plugin.idfh.action; + + import com.fanruan.api.log.LogKit; + import com.fr.plugin.idfh.kit.HttpKit; + + import java.util.Map; + + /** + *
+ * + * + * @author fr.open + * @since 1.0.0 + */ + public class GetOutput extends AbstractDataOutput { + + @Override + public void operation(OutputHttp outputHttp, Map taskParams, Map bodyParams, Map headers) throws Exception { + LogKit.info("httpaction-GetOutput-operation-bodyParams:{}, headers:{}", bodyParams, headers); + String response = HttpKit.get(outputHttp.getApiUrl(), bodyParams, headers); + LogKit.info("httpaction-GetOutput-operation-response:{}", response); + } + } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idfh/action/OutputHttp.java b/src/main/java/com/fr/plugin/idfh/action/OutputHttp.java new file mode 100644 index 0000000..dcc0fbf --- /dev/null +++ b/src/main/java/com/fr/plugin/idfh/action/OutputHttp.java @@ -0,0 +1,119 @@ + /* + * Copyright (C), 2018-2021 + * Project: starter + * FileName: OutputHttp + * Author: Louis + * Date: 2021/4/6 15:45 + */ + package com.fr.plugin.idfh.action; + + import com.fr.plugin.idfh.entity.OutputHttpEntity; + import com.fr.schedule.base.bean.Format; + import com.fr.schedule.base.bean.output.BaseOutputAction; + import com.fr.schedule.base.constant.ScheduleConstants; + import com.fr.schedule.base.entity.AbstractScheduleEntity; + import com.fr.schedule.base.type.RunType; + import com.fr.third.fasterxml.jackson.annotation.JsonSubTypes; + + import java.util.List; + + /** + *
+ * + * + * @author fr.open + * @since 1.0.0 + */ + @JsonSubTypes.Type(value = OutputHttp.class, name = "OutputHttp") + public class OutputHttp extends BaseOutputAction { + private static final long serialVersionUID = 2894577893249191611L; + + private String httpType = null; + private String apiUrl; + private String bodyContent; + private String headers; + private String bodyParameters; + private boolean previewAttach; + + public OutputHttp() { + } + + public boolean willExecuteByUser() { + return true; + } + + public RunType runType() { + return RunType.CUSTOM_CLASS; + } + + public Class outputActionEntityClass() { + return OutputHttpEntity.class; + } + + public AbstractScheduleEntity createOutputActionEntity() { + OutputHttpEntity httpEntity = new OutputHttpEntity(); + httpEntity.setId(this.getId()); + httpEntity.setHttpType(this.getHttpType()); + httpEntity.setApiUrl(this.getApiUrl()); + httpEntity.setBodyContent(this.getBodyContent()); + httpEntity.setHeaders(this.getHeaders()); + httpEntity.setBodyParameters(this.getBodyParameters()); + httpEntity.setPreviewAttach(this.isPreviewAttach()); + return httpEntity; + } + + @Override + public void modifyFormats(List formats) { + if (this.isPreviewAttach()) { + formats.add(new Format(ScheduleConstants.OUTPUTPNG_FORMAT_NUM)); + } + } + + public String getHttpType() { + return httpType; + } + + public void setHttpType(String httpType) { + this.httpType = httpType; + } + + public String getApiUrl() { + return apiUrl; + } + + public void setApiUrl(String apiUrl) { + this.apiUrl = apiUrl; + } + + public String getBodyContent() { + return bodyContent; + } + + public void setBodyContent(String bodyContent) { + this.bodyContent = bodyContent; + } + + public String getHeaders() { + return headers; + } + + public void setHeaders(String headers) { + this.headers = headers; + } + + public String getBodyParameters() { + return bodyParameters; + } + + public void setBodyParameters(String bodyParameters) { + this.bodyParameters = bodyParameters; + } + + public boolean isPreviewAttach() { + return previewAttach; + } + + public void setPreviewAttach(boolean previewAttach) { + this.previewAttach = previewAttach; + } + } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idfh/action/PostJsonOutput.java b/src/main/java/com/fr/plugin/idfh/action/PostJsonOutput.java new file mode 100644 index 0000000..30b924c --- /dev/null +++ b/src/main/java/com/fr/plugin/idfh/action/PostJsonOutput.java @@ -0,0 +1,217 @@ + /* + * Copyright (C), 2018-2021 + * Project: starter + * FileName: PostJsonOutput + * Author: Louis + * Date: 2021/4/15 10:45 + */ + package com.fr.plugin.idfh.action; + + import com.fanruan.api.i18n.I18nKit; + import com.fanruan.api.log.LogKit; + import com.fanruan.api.net.http.rs.HttpRequestType; + import com.fanruan.api.util.StringKit; + import com.fr.decision.system.bean.message.MessageUrlType; + import com.fr.decision.webservice.v10.message.MessageService; + import com.fr.general.ComparatorUtils; + import com.fr.general.DateUtils; + import com.fr.io.utils.ResourceIOUtils; + import com.fr.json.JSONArray; + import com.fr.json.JSONObject; + import com.fr.plugin.idfh.kit.HttpKit; + import com.fr.schedule.base.constant.ScheduleConstants; + import com.fr.stable.StringUtils; + import com.fr.third.org.apache.http.HttpEntity; + import com.fr.third.org.apache.http.entity.StringEntity; + import com.fr.third.org.apache.http.entity.mime.HttpMultipartMode; + import com.fr.third.org.apache.http.entity.mime.MultipartEntityBuilder; + import com.fr.third.org.apache.http.entity.mime.content.FileBody; + import com.fr.third.springframework.web.util.HtmlUtils; + + import java.io.File; + import java.nio.charset.StandardCharsets; + import java.util.*; + + /** + *
+ * + * + * @author fr.open + * @since 1.0.0 + */ + public class PostJsonOutput extends AbstractDataOutput { + public static final String KEY = "PostJsonOutput"; + public static final String USERNAME = "username"; + public static final String VALIDATE_CODE = "validateCode"; + public static final String LOGIN_URL = "loginUrl"; + + @Override + public void checkHeader(Map headers) throws Exception { + if (!headers.containsKey("Content-Type")) { + headers.put("Content-Type", "application/json"); + } + if (!ComparatorUtils.equalsIgnoreCase(headers.get("Content-Type"), "application/json")) { + throw new Exception(I18nKit.getLocText("Plugin-httpaction_Header_Content-Type_Valid")); + } + } + + @Override + public void operation(OutputHttp outputHttp, Map taskParams, Map bodyParams, Map headers) throws Exception { + LogKit.info("idfh-PostJsonOutput-operation-bodyParams:{}, taskParams:{}", bodyParams, taskParams); + JSONObject msgEntity = createMsgEntity(bodyParams, outputHttp.getBodyContent()); + headers.put("Authorization", "Bearer " + getAPIToken(bodyParams)); + LogKit.info("idfh-PostJsonOutput-operation-headers:{}", headers); + List attachFiles = uploadFiles(taskParams, bodyParams.get("uploadUrl"), headers.get("Authorization")); + LogKit.info("idfh-PostJsonOutput-operation-attachFiles:{}", attachFiles); + if (outputHttp.isPreviewAttach()) { + handleContent(attachFiles, msgEntity); + } + String[] usernames = getUserNames(taskParams); + JSONArray msgList = JSONArray.create(); + for (String username : usernames) { + msgEntity.put("originalMsgId", UUID.randomUUID()); + msgEntity.put("employeeNo", username); + for (int i = 0; i < Math.min(attachFiles.size(), 5); i++) { + if (attachFiles.get(i).endsWith(ScheduleConstants.Suffix.PNG)) { + continue; + } + msgEntity.put("attachFile" + (i + 1), attachFiles.get(i)); + } + msgList.add(msgEntity.copy()); + } + JSONObject requestJo = JSONObject.create(); + requestJo.put("msgList", msgList); + LogKit.info("idfh-PostJsonOutput-operation-requestJo:{}", requestJo.encode()); + StringEntity stringEntity = new StringEntity(requestJo.encode(), "UTF-8"); + String response = HttpKit.executeAndParse(com.fanruan.api.net.http.rs.HttpRequest.custom() + .url(outputHttp.getApiUrl()).post(stringEntity).headers(headers).build()); + LogKit.info("idfh-PostJsonOutput-operation-response:{}", response); + sendTemplateMessage(HtmlUtils.htmlUnescape(response), PostJsonOutput.KEY); + } + + private JSONObject createMsgEntity(Map bodyParams, String bodyContent) { + JSONObject msgEntity = JSONObject.create(); + msgEntity.put("srcSystem", bodyParams.get("srcSystem")); + msgEntity.put("keyword", bodyParams.get("keyword")); + msgEntity.put("dbSource", bodyParams.get("dbSource")); + msgEntity.put("target", bodyParams.get("target")); + msgEntity.put("msgContent", bodyContent); + msgEntity.put("createTime", DateUtils.getDate2LStr(new Date())); + bodyParams.remove("srcSystem"); + bodyParams.remove("keyword"); + bodyParams.remove("dbSource"); + bodyParams.remove("target"); + return msgEntity; + } + + /** + * 消息内容加入图片HTML + * + * @param attachFiles + * @param msgEntity + */ + private void handleContent(List attachFiles, JSONObject msgEntity) { + StringBuilder msgContent = new StringBuilder(); + msgContent.append(msgEntity.getString("msgContent")).append("
"); + for (String file : attachFiles) { + if (file.endsWith(ScheduleConstants.Suffix.PNG)) { + msgContent.append(""); + } + } + msgEntity.put("msgContent", msgContent); + } + + /** + * 上传附件操作 + * + * @param taskParams + * @param url + * @param authorization + * @return + */ + private List uploadFiles(Map taskParams, String url, String authorization) { + List attachFiles = new ArrayList<>(); + Map headers = new HashMap<>(); + headers.put("Authorization", authorization); + String[] outputFiles = (String[]) taskParams.get(ScheduleConstants.OUTPUT_FILES); + MultipartEntityBuilder builder; + String filePath; + File file; + FileBody fileBody; + HttpEntity httpEntity; + String response; + JSONObject result; + for (String outputFile : outputFiles) { + try { + LogKit.info("idfh-PostJsonOutput-uploadFiles-outputFile:{}", outputFile); + builder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.BROWSER_COMPATIBLE); + filePath = ResourceIOUtils.getRealPath(outputFile); + file = new File(filePath); + fileBody = new FileBody(file); + builder.addPart("file", fileBody); + builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); + httpEntity = builder.setCharset(StandardCharsets.UTF_8).build(); + response = HttpKit.uploadFile(url, httpEntity, StandardCharsets.UTF_8, headers, HttpRequestType.POST); + LogKit.info("idfh-PostJsonOutput-uploadFiles-response:{}", response); + result = new JSONObject(response); + if (ComparatorUtils.equals(result.getInt("code"), 0)) { + attachFiles.add(result.getString("data")); + } + } catch (Exception e) { + LogKit.error(e.getMessage(), e); + } + } + return attachFiles; + } + + /** + * 获取定时任务发送用户 + * + * @param taskParams + * @return + */ + private String[] getUserNames(Map taskParams) { + String username = (String) taskParams.get(ScheduleConstants.USERNAME); + if (StringUtils.isNotEmpty(username)) { + return new String[]{username}; + } else { + String[] usernames = (String[]) taskParams.get(ScheduleConstants.USERNAMES); + return usernames != null ? usernames : new String[0]; + } + } + + /** + * 获取调用后续接口的凭证 + * + * @param params + */ + private String getAPIToken(Map params) throws Exception { + Map bodyParams = new HashMap<>(); + bodyParams.put(USERNAME, params.get(USERNAME)); + bodyParams.put(VALIDATE_CODE, params.get(VALIDATE_CODE)); + String bodyContent = JSONObject.mapFrom(bodyParams).encode(); + StringEntity stringEntity = new StringEntity(bodyContent, "UTF-8"); + Map loginHeaders = new HashMap<>(); + loginHeaders.put("Content-Type", "application/json"); + String response = HttpKit.executeAndParse(com.fanruan.api.net.http.rs.HttpRequest.custom() + .url(params.get(LOGIN_URL)).post(stringEntity).headers(loginHeaders).build()); + JSONObject result = new JSONObject(response); + if (ComparatorUtils.equals(result.getInt("code"), 0)) { + return result.getJSONObject("data").getString("apiToken"); + } + return StringKit.EMPTY; + } + + /** + * 接口返回结果发送消息 + * + * @param response + */ + public static void sendTemplateMessage(String response, String type) { + String content = I18nKit.getLocText("Plugin-httpaction") + "-" + + type + "-" + + I18nKit.getLocText("Plugin-httpaction_Result_Message") + + response; + MessageService.getInstance().sendMessage2SupperRole(content, StringUtils.EMPTY, MessageUrlType.NONE); + } + } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idfh/action/PostOutput.java b/src/main/java/com/fr/plugin/idfh/action/PostOutput.java new file mode 100644 index 0000000..05d2c28 --- /dev/null +++ b/src/main/java/com/fr/plugin/idfh/action/PostOutput.java @@ -0,0 +1,30 @@ + /* + * Copyright (C), 2018-2021 + * Project: starter + * FileName: PostOutput + * Author: Louis + * Date: 2021/4/15 10:43 + */ + package com.fr.plugin.idfh.action; + + import com.fanruan.api.log.LogKit; + import com.fr.plugin.idfh.kit.HttpKit; + + import java.util.Map; + + /** + *
+ * + * + * @author fr.open + * @since 1.0.0 + */ + public class PostOutput extends AbstractDataOutput { + + @Override + public void operation(OutputHttp outputHttp, Map taskParams, Map bodyParams, Map headers) throws Exception { + LogKit.info("httpaction-PostOutput-operation-bodyParams:{}, headers:{}", bodyParams, headers); + String response = HttpKit.post(outputHttp.getApiUrl(), bodyParams, headers); + LogKit.info("httpaction-PostOutput-operation-response:{}", response); + } + } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idfh/action/SoapOutput.java b/src/main/java/com/fr/plugin/idfh/action/SoapOutput.java new file mode 100644 index 0000000..136bf65 --- /dev/null +++ b/src/main/java/com/fr/plugin/idfh/action/SoapOutput.java @@ -0,0 +1,60 @@ + /* + * Copyright (C), 2018-2021 + * Project: starter + * FileName: SoapOutput + * Author: Louis + * Date: 2021/4/15 11:11 + */ + package com.fr.plugin.idfh.action; + + import com.fanruan.api.i18n.I18nKit; + import com.fanruan.api.log.LogKit; + import com.fanruan.api.util.StringKit; + import com.fr.base.TemplateUtils; + import com.fr.general.ComparatorUtils; + import com.fr.plugin.idfh.kit.HttpKit; + import com.fr.script.Calculator; + import com.fr.third.org.apache.http.entity.StringEntity; + + import java.util.Map; + + /** + *
+ * + * + * @author fr.open + * @since 1.0.0 + */ + public class SoapOutput extends AbstractDataOutput { + + @Override + public void checkOutputHttp(OutputHttp outputHttp) throws Exception { + super.checkOutputHttp(outputHttp); + if (StringKit.isBlank(outputHttp.getBodyContent())) { + throw new Exception(I18nKit.getLocText("Plugin-httpaction_Body_Content_Valid")); + } + } + + @Override + public void checkHeader(Map headers) throws Exception { + if (!headers.containsKey("Content-Type")) { + headers.put("Content-Type", "text/xml;charset=UTF-8"); + } + if (!ComparatorUtils.equalsIgnoreCase(headers.get("Content-Type"), "application/soap+xml;charset=UTF-8") + && !ComparatorUtils.equalsIgnoreCase(headers.get("Content-Type"), "text/xml;charset=UTF-8")) { + throw new Exception(I18nKit.getLocText("Plugin-httpaction_Header_Content-Type_Valid")); + } + if (StringKit.isBlank(headers.get("SOAPAction"))) { + throw new Exception(I18nKit.getLocText("Plugin-httpaction_Header_SOAPAction_Valid")); + } + } + + @Override + public void operation(OutputHttp outputHttp, Map taskParams, Map bodyParams, Map headers) throws Exception { + String soapXml = TemplateUtils.render(outputHttp.getBodyContent(), bodyParams, Calculator.createCalculator()); + LogKit.info("httpaction-SoapOutput-operation-soapXml:{}, headers:{}", soapXml, headers); + StringEntity stringEntity = new StringEntity(soapXml, "UTF-8"); + String response = HttpKit.executeAndParse(com.fanruan.api.net.http.rs.HttpRequest.custom().url(outputHttp.getApiUrl()).post(stringEntity).headers(headers).build()); + LogKit.info("httpaction-SoapOutput-operation-response:{}", response); + } + } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idfh/dao/OutputHttpDAO.java b/src/main/java/com/fr/plugin/idfh/dao/OutputHttpDAO.java new file mode 100644 index 0000000..461c2cd --- /dev/null +++ b/src/main/java/com/fr/plugin/idfh/dao/OutputHttpDAO.java @@ -0,0 +1,42 @@ + /* + * Copyright (C), 2018-2021 + * Project: starter + * FileName: OutputHttpDAO + * Author: Louis + * Date: 2021/4/14 15:38 + */ + package com.fr.plugin.idfh.dao; + + import com.fr.plugin.idfh.entity.OutputHttpEntity; + import com.fr.stable.db.dao.BaseDAO; + import com.fr.stable.db.dao.DAOProvider; + import com.fr.stable.db.session.DAOSession; + + /** + *
+ * + * + * @author fr.open + * @since 1.0.0 + */ + public class OutputHttpDAO extends BaseDAO { + public final static DAOProvider DAO = new DAOProvider() { + @Override + public Class getEntityClass() { + return OutputHttpEntity.class; + } + + @Override + public Class getDAOClass() { + return OutputHttpDAO.class; + } + }; + + public OutputHttpDAO(DAOSession daoSession) { + super(daoSession); + } + + protected Class getEntityClass() { + return OutputHttpEntity.class; + } + } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idfh/entity/OutputHttpEntity.java b/src/main/java/com/fr/plugin/idfh/entity/OutputHttpEntity.java new file mode 100644 index 0000000..c58f06e --- /dev/null +++ b/src/main/java/com/fr/plugin/idfh/entity/OutputHttpEntity.java @@ -0,0 +1,110 @@ + /* + * Copyright (C), 2018-2021 + * Project: starter + * FileName: OutputHttpEntity + * Author: Louis + * Date: 2021/4/6 15:55 + */ + package com.fr.plugin.idfh.entity; + + import com.fr.plugin.idfh.action.OutputHttp; + import com.fr.schedule.base.entity.AbstractScheduleEntity; + import com.fr.stable.db.entity.TableAssociation; + import com.fr.third.javax.persistence.Column; + import com.fr.third.javax.persistence.Entity; + import com.fr.third.javax.persistence.Table; + + /** + *
+ * + * + * @author fr.open + * @since 1.0.0 + */ + @Entity + @Table(name = "fine_output_httpaction") + @TableAssociation(associated = true) + public class OutputHttpEntity extends AbstractScheduleEntity { + public static final String COLUMN_HTTP_TYPE = "httpType"; + public static final String COLUMN_API_URL = "apiUrl"; + public static final String COLUMN_BODY_CONTENT = "bodyContent"; + public static final String COLUMN_HEADERS = "headers"; + public static final String COLUMN_BODY_PARAMETERS = "bodyParameters"; + public static final String COLUMN_PREVIEW_ATTACH = "previewAttach"; + private static final long serialVersionUID = -7540903658511807256L; + @Column(name = COLUMN_HTTP_TYPE, length = 65536) + private String httpType = null; + @Column(name = COLUMN_API_URL, length = 65536) + private String apiUrl = null; + @Column(name = COLUMN_BODY_CONTENT, length = 65536) + private String bodyContent = null; + @Column(name = COLUMN_HEADERS, length = 65536) + private String headers = null; + @Column(name = COLUMN_BODY_PARAMETERS, length = 65536) + private String bodyParameters = null; + @Column(name = COLUMN_PREVIEW_ATTACH, length = 65536) + private boolean previewAttach = false; + + public OutputHttpEntity() { + } + + public OutputHttp createBean() { + OutputHttp outputHttp = new OutputHttp(); + outputHttp.setId(this.getId()); + outputHttp.setHttpType(this.getHttpType()); + outputHttp.setApiUrl(this.getApiUrl()); + outputHttp.setBodyContent(this.getBodyContent()); + outputHttp.setHeaders(this.getHeaders()); + outputHttp.setBodyParameters(this.getBodyParameters()); + outputHttp.setPreviewAttach(this.isPreviewAttach()); + return outputHttp; + } + + public String getHttpType() { + return httpType; + } + + public void setHttpType(String httpType) { + this.httpType = httpType; + } + + public String getApiUrl() { + return apiUrl; + } + + public void setApiUrl(String apiUrl) { + this.apiUrl = apiUrl; + } + + public String getBodyContent() { + return bodyContent; + } + + public void setBodyContent(String bodyContent) { + this.bodyContent = bodyContent; + } + + public String getHeaders() { + return headers; + } + + public void setHeaders(String headers) { + this.headers = headers; + } + + public String getBodyParameters() { + return bodyParameters; + } + + public void setBodyParameters(String bodyParameters) { + this.bodyParameters = bodyParameters; + } + + public boolean isPreviewAttach() { + return previewAttach; + } + + public void setPreviewAttach(boolean previewAttach) { + this.previewAttach = previewAttach; + } + } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idfh/interfaces/ActionLifeCycleMonitor.java b/src/main/java/com/fr/plugin/idfh/interfaces/ActionLifeCycleMonitor.java new file mode 100644 index 0000000..1dba03f --- /dev/null +++ b/src/main/java/com/fr/plugin/idfh/interfaces/ActionLifeCycleMonitor.java @@ -0,0 +1,48 @@ + /* + * Copyright (C), 2018-2021 + * Project: starter + * FileName: ActionLifeCycleMonitor + * Author: Louis + * Date: 2021/4/6 15:34 + */ + package com.fr.plugin.idfh.interfaces; + + import com.fr.plugin.context.PluginContext; + import com.fr.plugin.idfh.action.OutputHttp; + import com.fr.plugin.idfh.entity.OutputHttpEntity; + import com.fr.plugin.idfh.web.HttpOutputActionHandler; + import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor; + import com.fr.schedule.feature.ScheduleOutputActionEntityRegister; + import com.fr.schedule.feature.output.OutputActionHandler; + + /** + *
+ * + * + * @author fr.open + * @since 1.0.0 + */ + public class ActionLifeCycleMonitor extends AbstractPluginLifecycleMonitor { + + public ActionLifeCycleMonitor() { + } + + @Override + public void afterRun(PluginContext pluginContext) { + this.registerOutputHandler(); + } + + @Override + public void beforeStop(PluginContext pluginContext) { + ScheduleOutputActionEntityRegister.getInstance().removeClass(OutputHttpEntity.class); + } + + /** + * 注册handler + */ + private void registerOutputHandler() { + OutputActionHandler.registerHandler(new HttpOutputActionHandler(), OutputHttp.class.getName()); + ScheduleOutputActionEntityRegister.getInstance().removeClass(OutputHttpEntity.class); + ScheduleOutputActionEntityRegister.getInstance().addClass(OutputHttpEntity.class); + } + } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idfh/interfaces/HttpDecisionDBAccess.java b/src/main/java/com/fr/plugin/idfh/interfaces/HttpDecisionDBAccess.java new file mode 100644 index 0000000..782ff36 --- /dev/null +++ b/src/main/java/com/fr/plugin/idfh/interfaces/HttpDecisionDBAccess.java @@ -0,0 +1,41 @@ + /* + * Copyright (C), 2018-2021 + * Project: starter + * FileName: HttpDecisionDBAccess + * Author: Louis + * Date: 2021/4/14 15:33 + */ + package com.fr.plugin.idfh.interfaces; + + import com.fr.decision.plugin.db.AbstractDecisionDBAccessProvider; + import com.fr.plugin.idfh.dao.OutputHttpDAO; + import com.fr.stable.db.accessor.DBAccessor; + import com.fr.stable.db.dao.DAOProvider; + + /** + *
+ * + * + * @author fr.open + * @since 1.0.0 + */ + public class HttpDecisionDBAccess extends AbstractDecisionDBAccessProvider { + private static DBAccessor accessor; + + public HttpDecisionDBAccess() { + } + + public static DBAccessor getAccessor() { + return accessor; + } + + public DAOProvider[] registerDAO() { + return new DAOProvider[]{ + OutputHttpDAO.DAO + }; + } + + public void onDBAvailable(DBAccessor dbAccessor) { + accessor = dbAccessor; + } + } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idfh/interfaces/HttpFormulaProvider.java b/src/main/java/com/fr/plugin/idfh/interfaces/HttpFormulaProvider.java new file mode 100644 index 0000000..cce0bb2 --- /dev/null +++ b/src/main/java/com/fr/plugin/idfh/interfaces/HttpFormulaProvider.java @@ -0,0 +1,39 @@ + /* + * Copyright (C), 2018-2021 + * Project: starter + * FileName: HttpFormulaProvider + * Author: Louis + * Date: 2021/4/19 22:08 + */ + package com.fr.plugin.idfh.interfaces; + + import com.fr.main.workbook.ResultWorkBook; + import com.fr.plugin.idfh.action.OutputHttp; + import com.fr.schedule.base.provider.impl.AbstractOutputFormulaProvider; + import com.fr.schedule.extension.report.util.ScheduleParameterUtils; + + import java.util.List; + import java.util.Map; + + /** + *
+ * + * + * @author fr.open + * @since 1.0.0 + */ + public class HttpFormulaProvider extends AbstractOutputFormulaProvider { + public HttpFormulaProvider() { + } + + public void dealWithFormulaParam(OutputHttp outputHttp, ResultWorkBook resultWorkBook, List> list) throws Exception { + outputHttp.setApiUrl(ScheduleParameterUtils.dealWithParameter(outputHttp.getApiUrl(), list.get(0), resultWorkBook)); + outputHttp.setBodyContent(ScheduleParameterUtils.dealWithParameter(outputHttp.getBodyContent(), list.get(0), resultWorkBook)); + outputHttp.setHeaders(ScheduleParameterUtils.dealWithParameter(outputHttp.getHeaders(), list.get(0), resultWorkBook)); + outputHttp.setBodyParameters(ScheduleParameterUtils.dealWithParameter(outputHttp.getBodyParameters(), list.get(0), resultWorkBook)); + } + + public String getActionClassName() { + return OutputHttp.class.getName(); + } + } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idfh/interfaces/HttpWebResourceProvider.java b/src/main/java/com/fr/plugin/idfh/interfaces/HttpWebResourceProvider.java new file mode 100644 index 0000000..0f3bb29 --- /dev/null +++ b/src/main/java/com/fr/plugin/idfh/interfaces/HttpWebResourceProvider.java @@ -0,0 +1,58 @@ + /* + * Copyright (C), 2018-2021 + * Project: starter + * FileName: HttpWebResourceProvider + * Author: Louis + * Date: 2021/4/6 16:08 + */ + package com.fr.plugin.idfh.interfaces; + + import com.fr.decision.fun.impl.AbstractWebResourceProvider; + import com.fr.decision.web.MainComponent; + import com.fr.intelli.record.Focus; + import com.fr.intelli.record.Original; + import com.fr.plugin.context.PluginContexts; + import com.fr.record.analyzer.EnableMetrics; + import com.fr.stable.fun.Authorize; + import com.fr.web.struct.Atom; + import com.fr.web.struct.Component; + import com.fr.web.struct.browser.RequestClient; + import com.fr.web.struct.category.ParserType; + import com.fr.web.struct.category.ScriptPath; + + import static com.fr.plugin.idfh.Constants.PLUGIN_ID; + + /** + *
+ * + * + * @author fr.open + * @since 1.0.0 + */ + @EnableMetrics + @Authorize(callSignKey = PLUGIN_ID) + public class HttpWebResourceProvider extends AbstractWebResourceProvider { + public HttpWebResourceProvider() { + } + + @Override + public Atom attach() { + return MainComponent.KEY; + } + + @Override + @Focus(id = PLUGIN_ID, text = "Plugin-httpaction", source = Original.PLUGIN) + public Atom[] clients() { + if (PluginContexts.currentContext().isAvailable()) { + return new Atom[]{ + new Component() { + @Override + public ScriptPath script(RequestClient client) { + return ScriptPath.build("com/fr/plugin/idfh/web/dist/js/httpaction.min.js", ParserType.DYNAMIC); + } + } + }; + } + return super.clients(); + } + } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idfh/kit/HttpKit.java b/src/main/java/com/fr/plugin/idfh/kit/HttpKit.java new file mode 100644 index 0000000..2203456 --- /dev/null +++ b/src/main/java/com/fr/plugin/idfh/kit/HttpKit.java @@ -0,0 +1,722 @@ + /* + * Copyright (C), 2018-2021 + * Project: starter + * FileName: HttpKit + * Author: Louis + * Date: 2021/3/17 14:19 + */ + package com.fr.plugin.idfh.kit; + + import com.fanruan.api.log.LogKit; + import com.fanruan.api.macro.EncodeConstants; + import com.fanruan.api.net.http.rs.HttpRequest; + import com.fanruan.api.net.http.rs.*; + import com.fr.third.guava.collect.Maps; + import com.fr.third.org.apache.http.*; + import com.fr.third.org.apache.http.client.HttpRequestRetryHandler; + import com.fr.third.org.apache.http.client.config.RequestConfig; + import com.fr.third.org.apache.http.client.entity.UrlEncodedFormEntity; + import com.fr.third.org.apache.http.client.methods.CloseableHttpResponse; + import com.fr.third.org.apache.http.client.methods.HttpEntityEnclosingRequestBase; + import com.fr.third.org.apache.http.client.methods.HttpRequestBase; + import com.fr.third.org.apache.http.client.protocol.HttpClientContext; + import com.fr.third.org.apache.http.client.utils.URIBuilder; + import com.fr.third.org.apache.http.config.Registry; + import com.fr.third.org.apache.http.config.RegistryBuilder; + import com.fr.third.org.apache.http.conn.routing.HttpRoute; + import com.fr.third.org.apache.http.conn.socket.ConnectionSocketFactory; + import com.fr.third.org.apache.http.conn.socket.LayeredConnectionSocketFactory; + import com.fr.third.org.apache.http.conn.socket.PlainConnectionSocketFactory; + import com.fr.third.org.apache.http.conn.ssl.SSLConnectionSocketFactory; + import com.fr.third.org.apache.http.entity.FileEntity; + import com.fr.third.org.apache.http.entity.mime.HttpMultipartMode; + import com.fr.third.org.apache.http.entity.mime.MultipartEntityBuilder; + import com.fr.third.org.apache.http.impl.client.CloseableHttpClient; + import com.fr.third.org.apache.http.impl.client.HttpClients; + import com.fr.third.org.apache.http.impl.conn.PoolingHttpClientConnectionManager; + import com.fr.third.org.apache.http.message.BasicNameValuePair; + import com.fr.third.org.apache.http.protocol.HttpContext; + import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; + + import javax.net.ssl.*; + import java.io.*; + import java.net.URI; + import java.net.URISyntaxException; + import java.net.URLEncoder; + import java.net.UnknownHostException; + import java.nio.charset.Charset; + import java.security.KeyManagementException; + import java.security.NoSuchAlgorithmException; + import java.security.cert.CertificateException; + import java.util.ArrayList; + import java.util.Collections; + import java.util.List; + import java.util.Map; + + import static com.fanruan.api.net.http.rs.HttpRequestType.POST; + + /** + * @author richie + * @version 10.0 + * Created by richie on 2019-08-29 + *

+ * http请求工具类,封装了用于http请求的各种方法 + * 新增https忽略证书功能 Update By louis on 2021-03-17 + *

+ */ + public class HttpKit { + + private static final int RETRY_TIMES = 5; + private final static Object SYNC_LOCK = new Object(); + private static CloseableHttpClient httpClient = null; + + /** + * 根据请求地址创建HttpClient对象 + * + * @param url 请求地址 + * @return HttpClient对象 + */ + public static CloseableHttpClient getHttpClient(String url) { + String hostname = url.split("/")[2]; + int port = 80; + if (hostname.contains(":")) { + String[] arr = hostname.split(":"); + hostname = arr[0]; + port = Integer.parseInt(arr[1]); + } + if (httpClient == null) { + synchronized (SYNC_LOCK) { + if (httpClient == null) { +// httpClient = createHttpClient(hostname, port, SSLContexts.createDefault()); + try { + httpClient = createHttpClient(hostname, port, createIgnoreVerifySSL()); + } catch (NoSuchAlgorithmException e) { + LogKit.error(e.getMessage(), e); + } catch (KeyManagementException e) { + LogKit.error(e.getMessage(), e); + } + } + } + } + return httpClient; + } + + /** + * 新增了https 请求绕过证书认证 + * + * @return + * @throws NoSuchAlgorithmException + * @throws KeyManagementException + */ + public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException { + SSLContext sc = SSLContext.getInstance("SSLv3"); + // 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法 + X509TrustManager trustManager = new X509TrustManager() { + @Override + public void checkClientTrusted( + java.security.cert.X509Certificate[] paramArrayOfX509Certificate, + String paramString) throws CertificateException { + } + + @Override + public void checkServerTrusted( + java.security.cert.X509Certificate[] paramArrayOfX509Certificate, + String paramString) throws CertificateException { + } + + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + }; + sc.init(null, new TrustManager[]{trustManager}, null); + return sc; + } + + public static CloseableHttpClient createHttpClient(String hostname, int port, SSLContext sslContext) { + return createHttpClient(200, 40, 100, hostname, port, sslContext); + } + + private static CloseableHttpClient createHttpClient(int maxTotal, + int maxPerRoute, + int maxRoute, + String hostname, + int port, + SSLContext sslContext) { + ConnectionSocketFactory socketFactory = PlainConnectionSocketFactory.getSocketFactory(); + LayeredConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext); + Registry registry = RegistryBuilder + .create() + .register("http", socketFactory) + .register("https", sslConnectionSocketFactory) + .build(); + PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry); + // 将最大连接数增加 + cm.setMaxTotal(maxTotal); + // 将每个路由基础的连接增加 + cm.setDefaultMaxPerRoute(maxPerRoute); + HttpHost httpHost = new HttpHost(hostname, port); + // 将目标主机的最大连接数增加 + cm.setMaxPerRoute(new HttpRoute(httpHost), maxRoute); + + // 请求重试处理 + HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() { + @Override + public boolean retryRequest(IOException exception, int executionCount, HttpContext context) { + if (executionCount >= RETRY_TIMES) {// 如果已经重试了5次,就放弃 + return false; + } + if (exception instanceof NoHttpResponseException) {// 如果服务器丢掉了连接,那么就重试 + return true; + } + if (exception instanceof SSLHandshakeException) {// 不要重试SSL握手异常 + return false; + } + if (exception instanceof InterruptedIOException) {// 超时 + return false; + } + if (exception instanceof UnknownHostException) {// 目标服务器不可达 + return false; + } + if (exception instanceof SSLException) {// SSL握手异常 + return false; + } + + HttpClientContext clientContext = HttpClientContext.adapt(context); + HttpRequest request = clientContext.getRequest(); + // 如果请求是幂等的,就再次尝试 + return !(request instanceof HttpEntityEnclosingRequest); + } + }; + + return HttpClients.custom() + .setConnectionManager(cm) + .setRetryHandler(httpRequestRetryHandler) + .build(); + } + + /** + * 设置 httpEntity + * + * @param requestBase 请求体 + * @param httpRequest 请求 + */ + private static void setHttpEntity(@NotNull HttpEntityEnclosingRequestBase requestBase, @NotNull HttpRequest httpRequest) { + HttpEntity httpEntity = httpRequest.getHttpEntity(); + if (httpEntity != null) { + // 如果存在 httpEntity 直接设置 + requestBase.setEntity(httpEntity); + return; + } + Map params = httpRequest.getParams(); + if (params == null || params.isEmpty()) { + return; + } + List pairs = new ArrayList(); + for (Map.Entry entry : params.entrySet()) { + pairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); + } + try { + requestBase.setEntity(new UrlEncodedFormEntity(pairs, httpRequest.getEncoding())); + } catch (UnsupportedEncodingException e) { + LogKit.error(e.getMessage(), e); + } + } + + private static Map transformMap(Map oldMap) { + if (oldMap == null) { + return null; + } + return Maps.transformEntries(oldMap, new Maps.EntryTransformer() { + @Override + public String transformEntry(@Nullable String key, @Nullable V value) { + return value == null ? null : value.toString(); + } + }); + } + + /** + * 发起POST请求并获取返回的文本 + * + * @param url 响应请求的的服务器地址 + * @param params POST请求的参数 + * @return 服务器返回的文本内容 + */ + public static String post(String url, Map params) throws IOException { + return executeAndParse(HttpRequest + .custom() + .url(url) + .post(transformMap(params)) + .build()); + } + + /** + * 发起POST请求并获取返回的文本 + * + * @param url 响应请求的的服务器地址 + * @param params POST请求的参数 + * @param responseType 返回类型 + * @return 服务器返回的文本内容 + * @see com.fanruan.api.net.http.HttpKit#execute(HttpRequest) + */ + @Deprecated + public static T post(String url, Map params, HttpResponseType responseType) throws IOException { + CloseableHttpResponse response = execute(HttpRequest + .custom() + .url(url) + .post(transformMap(params)) + .build()); + return responseType.result(response, null); + } + + /** + * 发起POST请求并获取返回的文本 + * + * @param url 响应请求的的服务器地址 + * @param params POST请求的参数 + * @param headers 请求头 + * @return 服务器返回的文本内容 + * @see com.fanruan.api.net.http.HttpKit#executeAndParse(HttpRequest) + */ + @Deprecated + public static String post(String url, Map params, Map headers) throws IOException { + return executeAndParse(HttpRequest + .custom() + .url(url) + .post(transformMap(params)) + .headers(headers) + .build()); + } + + /** + * 发起POST请求并获取返回的文本 + * + * @param url 响应请求的的服务器地址 + * @param params POST请求的参数 + * @param headers 请求头 + * @param responseType 返回类型 + * @return 服务器返回的文本内容 + * @see com.fanruan.api.net.http.HttpKit#execute(HttpRequest) + */ + @Deprecated + public static T post(String url, Map params, Map headers, HttpResponseType responseType) throws IOException { + CloseableHttpResponse response = execute(HttpRequest + .custom() + .url(url) + .post(transformMap(params)) + .headers(headers) + .build()); + return responseType.result(response, null); + } + + /** + * 发起POST请求并获取返回的文本 + * + * @param url 响应请求的的服务器地址 + * @param params POST请求的参数 + * @param responseEncoding 响应的文本的编码 + * @return 服务器返回的文本内容 + * @see com.fanruan.api.net.http.HttpKit#executeAndParse(HttpRequest, BaseHttpResponseHandle) + */ + @Deprecated + public static String post(String url, Map params, String responseEncoding) throws IOException { + return executeAndParse(HttpRequest + .custom() + .url(url) + .post(transformMap(params)) + .build(), + new TextResponseHandle(responseEncoding)); + } + + /** + * 发起POST请求并获取返回的文本 + * + * @param url 响应请求的的服务器地址 + * @param params POST请求的参数 + * @param responseEncoding 响应的文本的编码 + * @param headers 请求头 + * @return 服务器返回的文本内容 + * @see com.fanruan.api.net.http.HttpKit#executeAndParse(HttpRequest, BaseHttpResponseHandle) + */ + @Deprecated + public static String post(String url, Map params, String responseEncoding, Map headers) throws IOException { + return executeAndParse(HttpRequest + .custom() + .url(url) + .post(transformMap(params)) + .headers(headers) + .build(), + new TextResponseHandle(responseEncoding)); + } + + + /** + * 发起POST请求并获取返回的文本 + * + * @param url 响应请求的的服务器地址 + * @param params POST请求的参数 + * @param responseEncoding 响应的文本的编码 + * @param paramsEncoding 参数编码 + * @param headers 请求头 + * @return 服务器返回的文本内容 + * @see com.fanruan.api.net.http.HttpKit#executeAndParse(HttpRequest, BaseHttpResponseHandle) + */ + public static String post(String url, Map params, String responseEncoding, String paramsEncoding, Map headers) throws IOException { + return executeAndParse(HttpRequest + .custom() + .url(url) + .post(transformMap(params)) + .encoding(paramsEncoding) + .headers(headers) + .build(), + new TextResponseHandle(responseEncoding)); + } + + /** + * 发起POST请求并获取返回的文本 + * + * @param url 响应请求的的服务器地址 + * @param params POST请求的参数 + * @param responseEncoding 响应的文本的编码 + * @param paramsEncoding 参数编码 + * @param headers 请求头 + * @param responseType 返回值类型 + * @return 服务器返回的文本内容 + * @see com.fanruan.api.net.http.HttpKit#execute(HttpRequest) + */ + public static T post(String url, Map params, String responseEncoding, String paramsEncoding, Map headers, HttpResponseType responseType) throws IOException { + CloseableHttpResponse response = execute(HttpRequest + .custom() + .url(url) + .post(transformMap(params)) + .encoding(paramsEncoding) + .headers(headers) + .build()); + return responseType.result(response, responseEncoding); + } + + /** + * 发起GET请求并获取返回的文本 + * + * @param url 响应请求的的服务器地址 + * @return 服务器返回的文本内容 + */ + public static String get(String url) throws IOException { + return executeAndParse(HttpRequest.custom().url(url).build()); + } + + /** + * 发起GET请求并获取返回的文本 + * + * @param url 响应请求的的服务器地址 + * @param params 参数 + * @return 服务器返回的文本内容 + */ + public static String get(String url, Map params) throws IOException { + return executeAndParse(HttpRequest.custom().url(url).params(params).build()); + } + + /** + * 发起GET请求并获取返回的文本 + * + * @param url 响应请求的的服务器地址 + * @param params 参数 + * @param headers 请求头 + * @return 服务器返回的文本内容 + * @see com.fanruan.api.net.http.HttpKit#executeAndParse(HttpRequest, BaseHttpResponseHandle) + */ + public static String get(String url, Map params, Map headers) throws IOException { + return executeAndParse(HttpRequest.custom().url(url).params(params).headers(headers).build()); + } + + /** + * 发起GET请求并获取返回的文本 + * + * @param url 响应请求的的服务器地址 + * @param params 参数 + * @param responseEncoding 返回的文本的编码 + * @return 服务器返回的文本内容 + * @see com.fanruan.api.net.http.HttpKit#executeAndParse(HttpRequest, BaseHttpResponseHandle) + */ + public static String get(String url, Map params, String responseEncoding) throws IOException { + return executeAndParse(HttpRequest + .custom() + .url(url) + .params(params) + .build(), + new TextResponseHandle(responseEncoding)); + } + + /** + * 发起GET请求并获取返回的文本 + * + * @param url 响应请求的的服务器地址 + * @param params 参数 + * @param responseEncoding 返回的文本的编码 + * @return 服务器返回的文本内容 + * @see com.fanruan.api.net.http.HttpKit#executeAndParse(HttpRequest, BaseHttpResponseHandle) + */ + public static String get(String url, Map params, String responseEncoding, Map headers) throws IOException { + return executeAndParse(HttpRequest + .custom() + .url(url) + .params(params) + .headers(headers) + .build(), + new TextResponseHandle(responseEncoding)); + } + + /** + * 从指定的地址下载文件 + * + * @param url 文件下载地址 + * @return 文件的字节流 + * @throws IOException 下载过程中出现错误则抛出此异常 + */ + public static ByteArrayInputStream download(String url) throws IOException { + return executeAndParse(HttpRequest.custom().url(url).build(), StreamResponseHandle.DEFAULT); + } + + /** + * 从指定的地址下载文件 + * + * @param url 文件下载地址 + * @param params 参数对 + * @param responseEncoding 响应的文件编码 + * @param headers 请求头 + * @return 文件的字节流 + * @throws IOException 下载过程中出现错误则抛出此异常 + */ + public static ByteArrayInputStream download(String url, Map params, String responseEncoding, Map headers) throws IOException { + return executeAndParse(HttpRequest + .custom() + .url(url) + .params(params) + .headers(headers) + .build(), + new StreamResponseHandle(responseEncoding)); + } + + /** + * 上传文件到指定的服务器 + * + * @param url 接收文件的服务器地址 + * @param file 要上传的文件,默认的文件编码为utf-8 + * @throws IOException 上传中出现错误则抛出此异常 + */ + public static void upload(String url, File file) throws IOException { + upload(url, file, Charset.forName("utf-8")); + } + + /** + * 上传文件到指定的服务器 + * + * @param url 接收文件的服务器地址 + * @param file 要上传的文件 + * @param charset 文件的编码 + * @throws IOException 上传中出现错误则抛出此异常 + */ + public static void upload(String url, File file, Charset charset) throws IOException { + upload(url, new FileEntity(file), charset); + } + + /** + * 上传文件到指定的服务器 + * + * @param url 接收文件的服务器地址 + * @param builder 附件构造器 + * @param charset 文件的编码 + * @throws IOException 上传中出现错误则抛出此异常 + */ + public static void upload(String url, MultipartEntityBuilder builder, Charset charset) throws IOException { + upload(url, builder, charset, Collections.emptyMap(), POST); + } + + /** + * 上传文件到指定的服务器 + * + * @param url 接收文件的服务器地址 + * @param fileEntity 文件实体 + * @param charset 文件的编码 + * @throws IOException 上传中出现错误则抛出此异常 + */ + public static void upload(String url, FileEntity fileEntity, Charset charset) throws IOException { + upload(url, fileEntity, charset, Collections.emptyMap(), POST); + } + + /** + * 上传多文件到指定的服务器 + * + * @param url 接收文件的服务器地址 + * @param builder 附件构造器 + * @param charset 文件的编码 + * @param headers 请求头 + * @param httpRequestType 请求类型 + * @throws IOException 上传中出现错误则抛出此异常 + */ + public static void upload(String url, MultipartEntityBuilder builder, Charset charset, Map headers, HttpRequestType httpRequestType) throws IOException { + // richie:采用浏览器模式,防止出现乱码 + builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); + HttpEntity reqEntity = builder.setCharset(charset).build(); + upload(url, reqEntity, charset, headers, httpRequestType); + } + + /** + * 上传文件到指定的服务器 + * + * @param url 接收文件的服务器地址 + * @param reqEntity 请求实体 + * @param charset 文件的编码 + * @param headers 请求头 + * @param httpRequestType 请求类型 + * @throws IOException 上传中出现错误则抛出此异常 + */ + public static void upload(String url, HttpEntity reqEntity, Charset charset, Map headers, HttpRequestType httpRequestType) throws IOException { + executeAndParse(HttpRequest + .custom() + .url(url) + .headers(headers) + .method(httpRequestType) + .httpEntity(reqEntity) + .encoding(charset.toString()) + .build(), + UploadResponseHandle.DEFAULT); + } + + public static String uploadFile(String url, HttpEntity httpEntity, Charset charset, Map map, HttpRequestType httpRequestType) throws IOException { + return executeAndParse(HttpRequest + .custom() + .url(url) + .headers(map) + .method(httpRequestType) + .httpEntity(httpEntity) + .encoding(charset.toString()) + .build(), + TextResponseHandle.DEFAULT); + } + + /** + * 请求资源或服务,使用默认文本http解析器,UTF-8编码 + * + * @param httpRequest httpRequest + * @return 返回处理结果 + */ + public static String executeAndParse(HttpRequest httpRequest) throws IOException { + return executeAndParse(httpRequest, TextResponseHandle.DEFAULT); + } + + /** + * 请求资源或服务,自请求参数,并指定 http 响应处理器 + * 例: + *
+      *      String res = HttpToolbox.executeAndParse(HttpRequest
+      *              .custom()
+      *              .url("")
+      *              .build(),
+      *          TextResponseHandle.DEFAULT);
+      * 
+ * + * @param httpRequest httpRequest + * @param handle http 解析器 + * @return 返回处理结果 + */ + public static T executeAndParse(HttpRequest httpRequest, BaseHttpResponseHandle handle) throws IOException { + return handle.parse(execute(httpRequest)); + } + + /** + * 请求资源或服务,传入请求参数 + * + * @param httpRequest httpRequest + * @return 返回处理结果 + */ + public static CloseableHttpResponse execute(HttpRequest httpRequest) throws IOException { + return execute(getHttpClient(httpRequest.getUrl()), httpRequest); + } + + /** + * 请求资源或服务,自定义client对象,传入请求参数 + * + * @param httpClient http客户端 + * @param httpRequest httpRequest + * @return 返回处理结果 + */ + public static CloseableHttpResponse execute(CloseableHttpClient httpClient, HttpRequest httpRequest) throws IOException { + String url = httpRequest.getUrl(); + + // 创建请求对象 + HttpRequestBase httpRequestBase = httpRequest.getMethod().createHttpRequest(url); + + // 设置header信息 + httpRequestBase.setHeader("User-Agent", "Mozilla/5.0"); + Map headers = httpRequest.getHeaders(); + if (headers != null && !headers.isEmpty()) { + for (Map.Entry entry : headers.entrySet()) { + httpRequestBase.setHeader(entry.getKey(), entry.getValue()); + } + } + + // 配置请求的设置 + RequestConfig requestConfig = httpRequest.getConfig(); + if (requestConfig != null) { + httpRequestBase.setConfig(requestConfig); + } + + // 判断是否支持设置entity(仅HttpPost、HttpPut、HttpPatch支持) + if (HttpEntityEnclosingRequestBase.class.isAssignableFrom(httpRequestBase.getClass())) { + setHttpEntity((HttpEntityEnclosingRequestBase) httpRequestBase, httpRequest); + } else { + Map params = httpRequest.getParams(); + if (params != null && !params.isEmpty()) { + // 注意get等不支持设置entity需要更新拼接之后的URL,但是url变量没有更新 + httpRequestBase.setURI(URI.create(buildUrl(url, params, httpRequest.getEncoding()))); + } + } + + return httpClient.execute(httpRequestBase); + } + + /** + * 构建 Url + * + * @param url 请求地址 + * @param params 参数 + * @return 拼接之后的地址 + */ + public static String buildUrl(String url, Map params) { + try { + return buildUrl(url, params, EncodeConstants.ENCODING_UTF_8); + } catch (UnsupportedEncodingException ignore) { + } + return url; + } + + + /** + * 构建 Url + * + * @param url 请求地址 + * @param params 参数 + * @return 拼接之后的地址 + * @throws UnsupportedEncodingException 不支持的编码 + */ + private static String buildUrl(String url, Map params, String paramsEncoding) throws UnsupportedEncodingException { + if (params == null || params.isEmpty()) { + return url; + } + URIBuilder builder; + try { + builder = new URIBuilder(url); + for (Map.Entry entry : params.entrySet()) { + String key = URLEncoder.encode(entry.getKey(), paramsEncoding); + String value = URLEncoder.encode(entry.getValue(), paramsEncoding); + builder.setParameter(key, value); + } + return builder.build().toString(); + } catch (URISyntaxException e) { + LogKit.debug("Error to build url, please check the arguments."); + } + return url; + } + } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idfh/web/HttpOutputActionHandler.java b/src/main/java/com/fr/plugin/idfh/web/HttpOutputActionHandler.java new file mode 100644 index 0000000..9528e8d --- /dev/null +++ b/src/main/java/com/fr/plugin/idfh/web/HttpOutputActionHandler.java @@ -0,0 +1,49 @@ + /* + * Copyright (C), 2018-2021 + * Project: starter + * FileName: HttpOutputActionHandler + * Author: Louis + * Date: 2021/4/6 15:43 + */ + package com.fr.plugin.idfh.web; + + import com.fanruan.api.i18n.I18nKit; + import com.fr.general.GeneralUtils; + import com.fr.plugin.context.PluginContexts; + import com.fr.plugin.idfh.action.*; + import com.fr.schedule.feature.output.OutputActionHandler; + + import java.util.LinkedHashMap; + import java.util.Map; + + /** + *
+ * + * + * @author fr.open + * @since 1.0.0 + */ + public class HttpOutputActionHandler extends OutputActionHandler { + public static final Map httpTypeMap = new LinkedHashMap() { + private static final long serialVersionUID = -5593329532670407219L; + + { + put(I18nKit.getLocText("Plugin-httpaction_ClassName_Get"), new GetOutput()); + put(I18nKit.getLocText("Plugin-httpaction_ClassName_Post"), new PostOutput()); + put(I18nKit.getLocText("Plugin-httpaction_ClassName_Post_Json"), new PostJsonOutput()); + put(I18nKit.getLocText("Plugin-httpaction_ClassName_Soap"), new SoapOutput()); + } + }; + + public HttpOutputActionHandler() { + } + + @Override + public void doAction(OutputHttp outputHttp, Map params) throws Exception { + if (!PluginContexts.currentContext().isAvailable()) { + return; + } + AbstractDataOutput outputActionHandler = httpTypeMap.get(outputHttp.getHttpType()); + outputActionHandler.doAction(outputHttp, params); + } + } \ No newline at end of file diff --git a/src/main/resources/com/fr/plugin/idfh/locale/lang.properties b/src/main/resources/com/fr/plugin/idfh/locale/lang.properties new file mode 100644 index 0000000..f780744 --- /dev/null +++ b/src/main/resources/com/fr/plugin/idfh/locale/lang.properties @@ -0,0 +1,17 @@ +Plugin-httpaction=Schedule Http Action +Plugin-httpaction_ClassPath_Title=Submit Method +Plugin-httpaction_Url=API Url +Plugin-httpaction_Header_Property=Header Property +Plugin-httpaction_Body_Property=Body Property +Plugin-httpaction_Body_Content=Body Content +Plugin-httpaction_ClassName_Get_Submit=Get +Plugin-httpaction_ClassName_Post_Submit=Post +Plugin-httpaction_ClassName_Post_Json_Submit=PostJson +Plugin-httpaction_ClassName_Soap_Submit=Soap +Plugin-httpaction_Handing_Way=HTTP API +Plugin-httpaction_Link_Valid=URL is not empty +Plugin-httpaction_Body_Content_Valid=Body Template is not empty +Plugin-httpaction_Body_Content_Format_Valid=body Template Error +Plugin-httpaction_Header_Content-Type_Valid=Header Content-Type Error +Plugin-httpaction_Header_SOAPAction_Valid=Header SOAPAction Error +Plugin-httpaction_Result_Message=Result: \ No newline at end of file diff --git a/src/main/resources/com/fr/plugin/idfh/locale/lang_zh_CN.properties b/src/main/resources/com/fr/plugin/idfh/locale/lang_zh_CN.properties new file mode 100644 index 0000000..6544502 --- /dev/null +++ b/src/main/resources/com/fr/plugin/idfh/locale/lang_zh_CN.properties @@ -0,0 +1,17 @@ +Plugin-httpaction=\u5B9A\u65F6\u8C03\u5EA6\u6570\u636E\u63A5\u53E3\u5904\u7406 +Plugin-httpaction_ClassPath_Title=\u63D0\u4EA4\u65B9\u5F0F +Plugin-httpaction_Url=\u63A5\u53E3\u5730\u5740 +Plugin-httpaction_Header_Property=Header\u53C2\u6570 +Plugin-httpaction_Body_Property=Body\u53C2\u6570 +Plugin-httpaction_Body_Content=Body\u5185\u5BB9 +Plugin-httpaction_ClassName_Get=Get +Plugin-httpaction_ClassName_Post=Post +Plugin-httpaction_ClassName_Post_Json=PostJson +Plugin-httpaction_ClassName_Soap=Soap +Plugin-httpaction_Handing_Way=HTTP\u63A5\u53E3 +Plugin-httpaction_Link_Valid=\u94FE\u63A5\u4E0D\u80FD\u4E3A\u7A7A +Plugin-httpaction_Body_Content_Valid=body\u6A21\u677F\u4E0D\u80FD\u4E3A\u7A7A +Plugin-httpaction_Body_Content_Format_Valid=body\u6A21\u677F\u683C\u5F0F\u9519\u8BEF +Plugin-httpaction_Header_Content-Type_Valid=Header\u53C2\u6570Content-Type\u4E3A\u7A7A\u6216\u9519\u8BEF +Plugin-httpaction_Header_SOAPAction_Valid=Header\u53C2\u6570SOAPAction\u4E3A\u7A7A\u6216\u9519\u8BEF +Plugin-httpaction_Result_Message=\u7ED3\u679C: \ No newline at end of file diff --git a/src/main/resources/com/fr/plugin/idfh/web/dist/js/httpaction.js b/src/main/resources/com/fr/plugin/idfh/web/dist/js/httpaction.js new file mode 100644 index 0000000..5b0f9c4 --- /dev/null +++ b/src/main/resources/com/fr/plugin/idfh/web/dist/js/httpaction.js @@ -0,0 +1,259 @@ +!(function () { + var HttpAction = BI.inherit(BI.Widget, { + props: { + baseCls: "" + }, + _store: function () { + return BI.Models.getModel("dec.model.schedule.task.file.handling.httpaction") + }, + watch: { + httpType: function (e) { + this.httpType.setValue(e); + }, + apiUrl: function (e) { + this.apiUrl.setValue(e) + }, + headers: function (e) { + this.headers.setValue(e) + }, + bodyParameters: function (e) { + this.bodyParameters.setValue(e) + }, + bodyContent: function (e) { + this.bodyContent.setValue(e) + }, + previewAttach: function (e) { + this.previewAttach.setSelected(e) + } + }, + mounted: function () { + var e = this.options.value; + BI.isEmpty(e) || this.setValue(e) + }, + render: function () { + var self = this; + return { + type: "bi.vertical", + tgap: 15, + items: [{//提交方式 + type: "bi.horizontal", + items: [{ + type: "bi.label", + cls: "dec-font-weight-bold", + width: 115, + height: 24, + textAlign: "left", + text: BI.i18nText("Plugin-httpaction_ClassPath_Title") + }, + { + type: "bi.text_value_combo", + width: 300, + value: self.model.httpType, + ref: function (e) { + self.httpType = e + }, + listeners: [{ + eventName: BI.TextValueCombo.EVENT_CHANGE, + action: function () { + var e = this.getValue()[0]; + self.store.setHttpType(e) + } + }], + items: [{ + text: BI.i18nText("Plugin-httpaction_ClassName_Post_Json"), + value: BI.i18nText("Plugin-httpaction_ClassName_Post_Json") + }] + }] + }, + {//接口地址 + type: "dec.label.editor.item", + text: BI.i18nText("Plugin-httpaction_Url"), + textCls: "dec-font-weight-bold", + textWidth: 115, + editorWidth: 300, + watermark: BI.i18nText("Dec-Basic_Support_Formula_Input"), + ref: function (e) { + self.apiUrl = e + }, + allowBlank: false, + bubbleError: false, + errorText: BI.i18nText("Plugin-httpaction_Link_Valid"), + listeners: [{ + eventName: BI.Editor.EVENT_CHANGE, + action: function () { + self.store.setApiUrl(this.getValue()); + } + }] + }, + {//header参数 + type: "dec.label.editor.item", + text: BI.i18nText("Plugin-httpaction_Header_Property"), + textCls: "dec-font-weight-bold", + textWidth: 115, + editorWidth: 300, + watermark: BI.i18nText("Dec-Basic_Support_Formula_Input"), + ref: function (e) { + self.headers = e + }, + allowBlank: false, + bubbleError: false, + errorText: BI.i18nText("Dec-Error_Null"), + listeners: [{ + eventName: BI.Editor.EVENT_CHANGE, + action: function () { + self.store.setHeaders(this.getValue()); + } + }] + }, + {//body参数 + type: "dec.label.editor.item", + text: BI.i18nText("Plugin-httpaction_Body_Property"), + textCls: "dec-font-weight-bold", + textWidth: 115, + editorWidth: 300, + watermark: BI.i18nText("Dec-Basic_Support_Formula_Input"), + ref: function (e) { + self.bodyParameters = e + }, + allowBlank: false, + bubbleError: false, + errorText: BI.i18nText("Dec-Error_Null"), + listeners: [{ + eventName: BI.Editor.EVENT_CHANGE, + action: function () { + self.store.setBodyParameters(this.getValue()); + } + }] + }, + {//bodyContent + type: "dec.label.textarea.item", + text: BI.i18nText("Plugin-httpaction_Body_Content"), + textCls: "dec-font-weight-bold", + watermark: BI.i18nText("Dec-Basic_Support_Formula_Input"), + textWidth: 100, + editorWidth: 390, + editorHeight: 100, + ref: function (e) { + self.bodyContent = e + }, + allowBlank: false, + bubbleError: false, + errorText: BI.i18nText("Plugin-httpaction_Body_Content_Valid"), + listeners: [{ + eventName: BI.Editor.EVENT_CHANGE, + action: function () { + self.store.setBodyContent(this.getValue()); + } + }] + }, + {//PreviewTemplate + type: "bi.multi_select_item", + selected: self.model.previewAttach, + logic: { + dynamic: !0 + }, + text: BI.i18nText("Dec-Task_Preview_Template_Content"), + ref: function (e) { + self.previewAttach = e + }, + listeners: [{ + eventName: BI.MultiSelectItem.EVENT_CHANGE, + action: function () { + self.store.setPreviewAttach(this.isSelected()); + } + }] + }] + }; + }, + /** + * 设定各项值 + */ + setValue: function (e) { + var self = this; + BI.map(e, function (e, t) { + self.store.setHttpType(t.httpType); + self.store.setApiUrl(t.apiUrl); + self.store.setHeaders(t.headers); + self.store.setBodyParameters(t.bodyParameters); + self.store.setBodyContent(t.bodyContent); + self.store.setPreviewAttach(t.previewAttach); + }); + }, + /** + * 校验函数,可选 + * 返回值当前处理方式是否通过校验 + * @returns {boolean} + */ + validation: function () { + return true; + }, + /** + * 取值函数,必选 + * 返回的值放到outputActionList中 + * @returns {{}} + */ + getValue: function () { + var self = this; + return { + OutputHttp: BI.extend(self.value, { + "@class": "com.fr.plugin.idfh.action.OutputHttp", + actionName: "com.fr.plugin.idfh.action.OutputHttp", + httpType: self.model.httpType, + apiUrl: self.model.apiUrl, + headers: self.model.headers, + bodyParameters: self.model.bodyParameters, + bodyContent: self.model.bodyContent, + previewAttach: self.model.previewAttach + }) + }; + } + }); + BI.shortcut("dec.schedule.task.file.handling.httpaction", HttpAction); +}) (); +!(function() { + var HttpActionModel = BI.inherit(Fix.Model, { + context: ["currTask"], + state: function() { + return { + httpType: BI.i18nText("Plugin-httpaction_ClassName_Get"), + apiUrl: '', + headers: '', + bodyParameters: '', + bodyContent: '', + previewAttach: false + } + }, + actions: { + setHttpType: function (e) { + this.model.httpType = e + }, + setApiUrl: function (e) { + this.model.apiUrl = e + }, + setHeaders: function (e) { + this.model.headers = e + }, + setBodyParameters: function (e) { + this.model.bodyParameters = e + }, + setBodyContent: function (e) { + this.model.bodyContent = e + }, + setPreviewAttach: function (e) { + e ? this.model.currTask.scheduleOutput.formats = BI.union(this.model.currTask.scheduleOutput.formats, [DecCst.Schedule.Template.Accessory.PREVIEW]) : BI.remove(this.model.currTask.scheduleOutput.formats, DecCst.Schedule.Template.Accessory.PREVIEW) + this.model.previewAttach = e; + } + } + }); + BI.model("dec.model.schedule.task.file.handling.httpaction", HttpActionModel); +}) (); +!(function () { + BI.config("dec.provider.schedule", function (provider) { + provider.registerHandingWay({ + text: BI.i18nText("Plugin-httpaction_Handing_Way"), + value: "com.fr.plugin.idfh.action.OutputHttp", + cardType: "dec.schedule.task.file.handling.httpaction", + actions: [] + }, [DecCst.Schedule.TaskType.DEFAULT, DecCst.Schedule.TaskType.REPORT, DecCst.Schedule.TaskType.BI]); + }); +}) (); diff --git a/src/main/resources/com/fr/plugin/idfh/web/dist/js/httpaction.min.js b/src/main/resources/com/fr/plugin/idfh/web/dist/js/httpaction.min.js new file mode 100644 index 0000000..467a23b --- /dev/null +++ b/src/main/resources/com/fr/plugin/idfh/web/dist/js/httpaction.min.js @@ -0,0 +1,2 @@ +/** com.fr.plugin.httpaction 22-03-23 00:31:53 */ +!function(){var t=BI.inherit(BI.Widget,{props:{baseCls:""},_store:function(){return BI.Models.getModel("dec.model.schedule.task.file.handling.httpaction")},watch:{httpType:function(t){this.httpType.setValue(t)},apiUrl:function(t){this.apiUrl.setValue(t)},headers:function(t){this.headers.setValue(t)},bodyParameters:function(t){this.bodyParameters.setValue(t)},bodyContent:function(t){this.bodyContent.setValue(t)},previewAttach:function(t){this.previewAttach.setSelected(t)}},mounted:function(){var t=this.options.value;BI.isEmpty(t)||this.setValue(t)},render:function(){var e=this;return{type:"bi.vertical",tgap:15,items:[{type:"bi.horizontal",items:[{type:"bi.label",cls:"dec-font-weight-bold",width:115,height:24,textAlign:"left",text:BI.i18nText("Plugin-httpaction_ClassPath_Title")},{type:"bi.text_value_combo",width:300,value:e.model.httpType,ref:function(t){e.httpType=t},listeners:[{eventName:BI.TextValueCombo.EVENT_CHANGE,action:function(){var t=this.getValue()[0];e.store.setHttpType(t)}}],items:[{text:BI.i18nText("Plugin-httpaction_ClassName_Post_Json"),value:BI.i18nText("Plugin-httpaction_ClassName_Post_Json")}]}]},{type:"dec.label.editor.item",text:BI.i18nText("Plugin-httpaction_Url"),textCls:"dec-font-weight-bold",textWidth:115,editorWidth:300,watermark:BI.i18nText("Dec-Basic_Support_Formula_Input"),ref:function(t){e.apiUrl=t},allowBlank:!1,bubbleError:!1,errorText:BI.i18nText("Plugin-httpaction_Link_Valid"),listeners:[{eventName:BI.Editor.EVENT_CHANGE,action:function(){e.store.setApiUrl(this.getValue())}}]},{type:"dec.label.editor.item",text:BI.i18nText("Plugin-httpaction_Header_Property"),textCls:"dec-font-weight-bold",textWidth:115,editorWidth:300,watermark:BI.i18nText("Dec-Basic_Support_Formula_Input"),ref:function(t){e.headers=t},allowBlank:!1,bubbleError:!1,errorText:BI.i18nText("Dec-Error_Null"),listeners:[{eventName:BI.Editor.EVENT_CHANGE,action:function(){e.store.setHeaders(this.getValue())}}]},{type:"dec.label.editor.item",text:BI.i18nText("Plugin-httpaction_Body_Property"),textCls:"dec-font-weight-bold",textWidth:115,editorWidth:300,watermark:BI.i18nText("Dec-Basic_Support_Formula_Input"),ref:function(t){e.bodyParameters=t},allowBlank:!1,bubbleError:!1,errorText:BI.i18nText("Dec-Error_Null"),listeners:[{eventName:BI.Editor.EVENT_CHANGE,action:function(){e.store.setBodyParameters(this.getValue())}}]},{type:"dec.label.textarea.item",text:BI.i18nText("Plugin-httpaction_Body_Content"),textCls:"dec-font-weight-bold",watermark:BI.i18nText("Dec-Basic_Support_Formula_Input"),textWidth:100,editorWidth:390,editorHeight:100,ref:function(t){e.bodyContent=t},allowBlank:!1,bubbleError:!1,errorText:BI.i18nText("Plugin-httpaction_Body_Content_Valid"),listeners:[{eventName:BI.Editor.EVENT_CHANGE,action:function(){e.store.setBodyContent(this.getValue())}}]},{type:"bi.multi_select_item",selected:e.model.previewAttach,logic:{dynamic:!0},text:BI.i18nText("Dec-Task_Preview_Template_Content"),ref:function(t){e.previewAttach=t},listeners:[{eventName:BI.MultiSelectItem.EVENT_CHANGE,action:function(){e.store.setPreviewAttach(this.isSelected())}}]}]}},setValue:function(t){var i=this;BI.map(t,function(t,e){i.store.setHttpType(e.httpType),i.store.setApiUrl(e.apiUrl),i.store.setHeaders(e.headers),i.store.setBodyParameters(e.bodyParameters),i.store.setBodyContent(e.bodyContent),i.store.setPreviewAttach(e.previewAttach)})},validation:function(){return!0},getValue:function(){var t=this;return{OutputHttp:BI.extend(t.value,{"@class":"com.fr.plugin.idfh.action.OutputHttp",actionName:"com.fr.plugin.idfh.action.OutputHttp",httpType:t.model.httpType,apiUrl:t.model.apiUrl,headers:t.model.headers,bodyParameters:t.model.bodyParameters,bodyContent:t.model.bodyContent,previewAttach:t.model.previewAttach})}}});BI.shortcut("dec.schedule.task.file.handling.httpaction",t)}(),function(){var t=BI.inherit(Fix.Model,{context:["currTask"],state:function(){return{httpType:BI.i18nText("Plugin-httpaction_ClassName_Get"),apiUrl:"",headers:"",bodyParameters:"",bodyContent:"",previewAttach:!1}},actions:{setHttpType:function(t){this.model.httpType=t},setApiUrl:function(t){this.model.apiUrl=t},setHeaders:function(t){this.model.headers=t},setBodyParameters:function(t){this.model.bodyParameters=t},setBodyContent:function(t){this.model.bodyContent=t},setPreviewAttach:function(t){t?this.model.currTask.scheduleOutput.formats=BI.union(this.model.currTask.scheduleOutput.formats,[DecCst.Schedule.Template.Accessory.PREVIEW]):BI.remove(this.model.currTask.scheduleOutput.formats,DecCst.Schedule.Template.Accessory.PREVIEW),this.model.previewAttach=t}}});BI.model("dec.model.schedule.task.file.handling.httpaction",t)}(),BI.config("dec.provider.schedule",function(t){t.registerHandingWay({text:BI.i18nText("Plugin-httpaction_Handing_Way"),value:"com.fr.plugin.idfh.action.OutputHttp",cardType:"dec.schedule.task.file.handling.httpaction",actions:[]},[DecCst.Schedule.TaskType.DEFAULT,DecCst.Schedule.TaskType.REPORT,DecCst.Schedule.TaskType.BI])}); \ No newline at end of file diff --git a/src/main/resources/com/fr/plugin/idfh/web/dist/js/schedule.js b/src/main/resources/com/fr/plugin/idfh/web/dist/js/schedule.js new file mode 100644 index 0000000..5b0f9c4 --- /dev/null +++ b/src/main/resources/com/fr/plugin/idfh/web/dist/js/schedule.js @@ -0,0 +1,259 @@ +!(function () { + var HttpAction = BI.inherit(BI.Widget, { + props: { + baseCls: "" + }, + _store: function () { + return BI.Models.getModel("dec.model.schedule.task.file.handling.httpaction") + }, + watch: { + httpType: function (e) { + this.httpType.setValue(e); + }, + apiUrl: function (e) { + this.apiUrl.setValue(e) + }, + headers: function (e) { + this.headers.setValue(e) + }, + bodyParameters: function (e) { + this.bodyParameters.setValue(e) + }, + bodyContent: function (e) { + this.bodyContent.setValue(e) + }, + previewAttach: function (e) { + this.previewAttach.setSelected(e) + } + }, + mounted: function () { + var e = this.options.value; + BI.isEmpty(e) || this.setValue(e) + }, + render: function () { + var self = this; + return { + type: "bi.vertical", + tgap: 15, + items: [{//提交方式 + type: "bi.horizontal", + items: [{ + type: "bi.label", + cls: "dec-font-weight-bold", + width: 115, + height: 24, + textAlign: "left", + text: BI.i18nText("Plugin-httpaction_ClassPath_Title") + }, + { + type: "bi.text_value_combo", + width: 300, + value: self.model.httpType, + ref: function (e) { + self.httpType = e + }, + listeners: [{ + eventName: BI.TextValueCombo.EVENT_CHANGE, + action: function () { + var e = this.getValue()[0]; + self.store.setHttpType(e) + } + }], + items: [{ + text: BI.i18nText("Plugin-httpaction_ClassName_Post_Json"), + value: BI.i18nText("Plugin-httpaction_ClassName_Post_Json") + }] + }] + }, + {//接口地址 + type: "dec.label.editor.item", + text: BI.i18nText("Plugin-httpaction_Url"), + textCls: "dec-font-weight-bold", + textWidth: 115, + editorWidth: 300, + watermark: BI.i18nText("Dec-Basic_Support_Formula_Input"), + ref: function (e) { + self.apiUrl = e + }, + allowBlank: false, + bubbleError: false, + errorText: BI.i18nText("Plugin-httpaction_Link_Valid"), + listeners: [{ + eventName: BI.Editor.EVENT_CHANGE, + action: function () { + self.store.setApiUrl(this.getValue()); + } + }] + }, + {//header参数 + type: "dec.label.editor.item", + text: BI.i18nText("Plugin-httpaction_Header_Property"), + textCls: "dec-font-weight-bold", + textWidth: 115, + editorWidth: 300, + watermark: BI.i18nText("Dec-Basic_Support_Formula_Input"), + ref: function (e) { + self.headers = e + }, + allowBlank: false, + bubbleError: false, + errorText: BI.i18nText("Dec-Error_Null"), + listeners: [{ + eventName: BI.Editor.EVENT_CHANGE, + action: function () { + self.store.setHeaders(this.getValue()); + } + }] + }, + {//body参数 + type: "dec.label.editor.item", + text: BI.i18nText("Plugin-httpaction_Body_Property"), + textCls: "dec-font-weight-bold", + textWidth: 115, + editorWidth: 300, + watermark: BI.i18nText("Dec-Basic_Support_Formula_Input"), + ref: function (e) { + self.bodyParameters = e + }, + allowBlank: false, + bubbleError: false, + errorText: BI.i18nText("Dec-Error_Null"), + listeners: [{ + eventName: BI.Editor.EVENT_CHANGE, + action: function () { + self.store.setBodyParameters(this.getValue()); + } + }] + }, + {//bodyContent + type: "dec.label.textarea.item", + text: BI.i18nText("Plugin-httpaction_Body_Content"), + textCls: "dec-font-weight-bold", + watermark: BI.i18nText("Dec-Basic_Support_Formula_Input"), + textWidth: 100, + editorWidth: 390, + editorHeight: 100, + ref: function (e) { + self.bodyContent = e + }, + allowBlank: false, + bubbleError: false, + errorText: BI.i18nText("Plugin-httpaction_Body_Content_Valid"), + listeners: [{ + eventName: BI.Editor.EVENT_CHANGE, + action: function () { + self.store.setBodyContent(this.getValue()); + } + }] + }, + {//PreviewTemplate + type: "bi.multi_select_item", + selected: self.model.previewAttach, + logic: { + dynamic: !0 + }, + text: BI.i18nText("Dec-Task_Preview_Template_Content"), + ref: function (e) { + self.previewAttach = e + }, + listeners: [{ + eventName: BI.MultiSelectItem.EVENT_CHANGE, + action: function () { + self.store.setPreviewAttach(this.isSelected()); + } + }] + }] + }; + }, + /** + * 设定各项值 + */ + setValue: function (e) { + var self = this; + BI.map(e, function (e, t) { + self.store.setHttpType(t.httpType); + self.store.setApiUrl(t.apiUrl); + self.store.setHeaders(t.headers); + self.store.setBodyParameters(t.bodyParameters); + self.store.setBodyContent(t.bodyContent); + self.store.setPreviewAttach(t.previewAttach); + }); + }, + /** + * 校验函数,可选 + * 返回值当前处理方式是否通过校验 + * @returns {boolean} + */ + validation: function () { + return true; + }, + /** + * 取值函数,必选 + * 返回的值放到outputActionList中 + * @returns {{}} + */ + getValue: function () { + var self = this; + return { + OutputHttp: BI.extend(self.value, { + "@class": "com.fr.plugin.idfh.action.OutputHttp", + actionName: "com.fr.plugin.idfh.action.OutputHttp", + httpType: self.model.httpType, + apiUrl: self.model.apiUrl, + headers: self.model.headers, + bodyParameters: self.model.bodyParameters, + bodyContent: self.model.bodyContent, + previewAttach: self.model.previewAttach + }) + }; + } + }); + BI.shortcut("dec.schedule.task.file.handling.httpaction", HttpAction); +}) (); +!(function() { + var HttpActionModel = BI.inherit(Fix.Model, { + context: ["currTask"], + state: function() { + return { + httpType: BI.i18nText("Plugin-httpaction_ClassName_Get"), + apiUrl: '', + headers: '', + bodyParameters: '', + bodyContent: '', + previewAttach: false + } + }, + actions: { + setHttpType: function (e) { + this.model.httpType = e + }, + setApiUrl: function (e) { + this.model.apiUrl = e + }, + setHeaders: function (e) { + this.model.headers = e + }, + setBodyParameters: function (e) { + this.model.bodyParameters = e + }, + setBodyContent: function (e) { + this.model.bodyContent = e + }, + setPreviewAttach: function (e) { + e ? this.model.currTask.scheduleOutput.formats = BI.union(this.model.currTask.scheduleOutput.formats, [DecCst.Schedule.Template.Accessory.PREVIEW]) : BI.remove(this.model.currTask.scheduleOutput.formats, DecCst.Schedule.Template.Accessory.PREVIEW) + this.model.previewAttach = e; + } + } + }); + BI.model("dec.model.schedule.task.file.handling.httpaction", HttpActionModel); +}) (); +!(function () { + BI.config("dec.provider.schedule", function (provider) { + provider.registerHandingWay({ + text: BI.i18nText("Plugin-httpaction_Handing_Way"), + value: "com.fr.plugin.idfh.action.OutputHttp", + cardType: "dec.schedule.task.file.handling.httpaction", + actions: [] + }, [DecCst.Schedule.TaskType.DEFAULT, DecCst.Schedule.TaskType.REPORT, DecCst.Schedule.TaskType.BI]); + }); +}) (); diff --git a/src/main/resources/com/fr/plugin/idfh/web/dist/js/schedule.min.js b/src/main/resources/com/fr/plugin/idfh/web/dist/js/schedule.min.js new file mode 100644 index 0000000..467a23b --- /dev/null +++ b/src/main/resources/com/fr/plugin/idfh/web/dist/js/schedule.min.js @@ -0,0 +1,2 @@ +/** com.fr.plugin.httpaction 22-03-23 00:31:53 */ +!function(){var t=BI.inherit(BI.Widget,{props:{baseCls:""},_store:function(){return BI.Models.getModel("dec.model.schedule.task.file.handling.httpaction")},watch:{httpType:function(t){this.httpType.setValue(t)},apiUrl:function(t){this.apiUrl.setValue(t)},headers:function(t){this.headers.setValue(t)},bodyParameters:function(t){this.bodyParameters.setValue(t)},bodyContent:function(t){this.bodyContent.setValue(t)},previewAttach:function(t){this.previewAttach.setSelected(t)}},mounted:function(){var t=this.options.value;BI.isEmpty(t)||this.setValue(t)},render:function(){var e=this;return{type:"bi.vertical",tgap:15,items:[{type:"bi.horizontal",items:[{type:"bi.label",cls:"dec-font-weight-bold",width:115,height:24,textAlign:"left",text:BI.i18nText("Plugin-httpaction_ClassPath_Title")},{type:"bi.text_value_combo",width:300,value:e.model.httpType,ref:function(t){e.httpType=t},listeners:[{eventName:BI.TextValueCombo.EVENT_CHANGE,action:function(){var t=this.getValue()[0];e.store.setHttpType(t)}}],items:[{text:BI.i18nText("Plugin-httpaction_ClassName_Post_Json"),value:BI.i18nText("Plugin-httpaction_ClassName_Post_Json")}]}]},{type:"dec.label.editor.item",text:BI.i18nText("Plugin-httpaction_Url"),textCls:"dec-font-weight-bold",textWidth:115,editorWidth:300,watermark:BI.i18nText("Dec-Basic_Support_Formula_Input"),ref:function(t){e.apiUrl=t},allowBlank:!1,bubbleError:!1,errorText:BI.i18nText("Plugin-httpaction_Link_Valid"),listeners:[{eventName:BI.Editor.EVENT_CHANGE,action:function(){e.store.setApiUrl(this.getValue())}}]},{type:"dec.label.editor.item",text:BI.i18nText("Plugin-httpaction_Header_Property"),textCls:"dec-font-weight-bold",textWidth:115,editorWidth:300,watermark:BI.i18nText("Dec-Basic_Support_Formula_Input"),ref:function(t){e.headers=t},allowBlank:!1,bubbleError:!1,errorText:BI.i18nText("Dec-Error_Null"),listeners:[{eventName:BI.Editor.EVENT_CHANGE,action:function(){e.store.setHeaders(this.getValue())}}]},{type:"dec.label.editor.item",text:BI.i18nText("Plugin-httpaction_Body_Property"),textCls:"dec-font-weight-bold",textWidth:115,editorWidth:300,watermark:BI.i18nText("Dec-Basic_Support_Formula_Input"),ref:function(t){e.bodyParameters=t},allowBlank:!1,bubbleError:!1,errorText:BI.i18nText("Dec-Error_Null"),listeners:[{eventName:BI.Editor.EVENT_CHANGE,action:function(){e.store.setBodyParameters(this.getValue())}}]},{type:"dec.label.textarea.item",text:BI.i18nText("Plugin-httpaction_Body_Content"),textCls:"dec-font-weight-bold",watermark:BI.i18nText("Dec-Basic_Support_Formula_Input"),textWidth:100,editorWidth:390,editorHeight:100,ref:function(t){e.bodyContent=t},allowBlank:!1,bubbleError:!1,errorText:BI.i18nText("Plugin-httpaction_Body_Content_Valid"),listeners:[{eventName:BI.Editor.EVENT_CHANGE,action:function(){e.store.setBodyContent(this.getValue())}}]},{type:"bi.multi_select_item",selected:e.model.previewAttach,logic:{dynamic:!0},text:BI.i18nText("Dec-Task_Preview_Template_Content"),ref:function(t){e.previewAttach=t},listeners:[{eventName:BI.MultiSelectItem.EVENT_CHANGE,action:function(){e.store.setPreviewAttach(this.isSelected())}}]}]}},setValue:function(t){var i=this;BI.map(t,function(t,e){i.store.setHttpType(e.httpType),i.store.setApiUrl(e.apiUrl),i.store.setHeaders(e.headers),i.store.setBodyParameters(e.bodyParameters),i.store.setBodyContent(e.bodyContent),i.store.setPreviewAttach(e.previewAttach)})},validation:function(){return!0},getValue:function(){var t=this;return{OutputHttp:BI.extend(t.value,{"@class":"com.fr.plugin.idfh.action.OutputHttp",actionName:"com.fr.plugin.idfh.action.OutputHttp",httpType:t.model.httpType,apiUrl:t.model.apiUrl,headers:t.model.headers,bodyParameters:t.model.bodyParameters,bodyContent:t.model.bodyContent,previewAttach:t.model.previewAttach})}}});BI.shortcut("dec.schedule.task.file.handling.httpaction",t)}(),function(){var t=BI.inherit(Fix.Model,{context:["currTask"],state:function(){return{httpType:BI.i18nText("Plugin-httpaction_ClassName_Get"),apiUrl:"",headers:"",bodyParameters:"",bodyContent:"",previewAttach:!1}},actions:{setHttpType:function(t){this.model.httpType=t},setApiUrl:function(t){this.model.apiUrl=t},setHeaders:function(t){this.model.headers=t},setBodyParameters:function(t){this.model.bodyParameters=t},setBodyContent:function(t){this.model.bodyContent=t},setPreviewAttach:function(t){t?this.model.currTask.scheduleOutput.formats=BI.union(this.model.currTask.scheduleOutput.formats,[DecCst.Schedule.Template.Accessory.PREVIEW]):BI.remove(this.model.currTask.scheduleOutput.formats,DecCst.Schedule.Template.Accessory.PREVIEW),this.model.previewAttach=t}}});BI.model("dec.model.schedule.task.file.handling.httpaction",t)}(),BI.config("dec.provider.schedule",function(t){t.registerHandingWay({text:BI.i18nText("Plugin-httpaction_Handing_Way"),value:"com.fr.plugin.idfh.action.OutputHttp",cardType:"dec.schedule.task.file.handling.httpaction",actions:[]},[DecCst.Schedule.TaskType.DEFAULT,DecCst.Schedule.TaskType.REPORT,DecCst.Schedule.TaskType.BI])}); \ No newline at end of file