From 7abd8bbed9778bddb4435e12fdd62c2301060576 Mon Sep 17 00:00:00 2001 From: liuy <37787198+LiuyCodes@users.noreply.github.com> Date: Mon, 19 May 2025 11:49:10 +0800 Subject: [PATCH] =?UTF-8?q?feat(nifi-client):=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=A4=84=E7=90=86=E5=99=A8=E8=AF=A6=E6=83=85=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E3=80=81=E6=9B=B4=E6=96=B0=E5=92=8C=E5=88=A0=E9=99=A4=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增处理器详情查询、更新和删除相关的 API 接口 - 添加处理器信息和版本相关的新模型类 - 优化错误处理,使用 StrUtil 格式化错误信息 --- .../hzya/frame/nifi/client/NifiClient.java | 3 +- .../model/joinupdateprocessor/Revision17.java | 16 +++++++++ .../RunStatusOrStop17.java | 17 ++++++++++ .../resultprocessorsinfo/Component16.java | 21 ++++++++++++ .../model/resultprocessorsinfo/Config16.java | 31 ++++++++++++++++++ .../ProcessorsInfo16.java | 18 ++++++++++ .../resultprocessorsinfo/Revision16.java | 16 +++++++++ .../frame/nifi/service/NifiApiService.java | 30 +++++++++++++++++ .../hzya/frame/nifi/client/NifiClient.class | Bin 12667 -> 12973 bytes .../frame/nifi/service/NifiApiService.class | Bin 9226 -> 11927 bytes 10 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 fw-nifi/src/main/java/com/hzya/frame/nifi/model/joinupdateprocessor/Revision17.java create mode 100644 fw-nifi/src/main/java/com/hzya/frame/nifi/model/joinupdateprocessor/RunStatusOrStop17.java create mode 100644 fw-nifi/src/main/java/com/hzya/frame/nifi/model/resultprocessorsinfo/Component16.java create mode 100644 fw-nifi/src/main/java/com/hzya/frame/nifi/model/resultprocessorsinfo/Config16.java create mode 100644 fw-nifi/src/main/java/com/hzya/frame/nifi/model/resultprocessorsinfo/ProcessorsInfo16.java create mode 100644 fw-nifi/src/main/java/com/hzya/frame/nifi/model/resultprocessorsinfo/Revision16.java diff --git a/fw-nifi/src/main/java/com/hzya/frame/nifi/client/NifiClient.java b/fw-nifi/src/main/java/com/hzya/frame/nifi/client/NifiClient.java index 9fd0b7fb..9b09872b 100644 --- a/fw-nifi/src/main/java/com/hzya/frame/nifi/client/NifiClient.java +++ b/fw-nifi/src/main/java/com/hzya/frame/nifi/client/NifiClient.java @@ -1,5 +1,6 @@ package com.hzya.frame.nifi.client; +import cn.hutool.core.util.StrUtil; import com.fasterxml.jackson.databind.ObjectMapper; import com.hzya.frame.nifi.config.NifiServiceConfig; import okhttp3.*; @@ -157,7 +158,7 @@ public class NifiClient { String responseBody = response.body().string(); logger.info("响应体:" + responseBody); if (!response.isSuccessful()) { - throw new IOException("意外的响应码: " + responseBody); + throw new IOException(StrUtil.format("意外的响应码: {}", responseBody)); } return objectMapper.readValue(responseBody, responseType); } diff --git a/fw-nifi/src/main/java/com/hzya/frame/nifi/model/joinupdateprocessor/Revision17.java b/fw-nifi/src/main/java/com/hzya/frame/nifi/model/joinupdateprocessor/Revision17.java new file mode 100644 index 00000000..384d1ccc --- /dev/null +++ b/fw-nifi/src/main/java/com/hzya/frame/nifi/model/joinupdateprocessor/Revision17.java @@ -0,0 +1,16 @@ +package com.hzya.frame.nifi.model.joinupdateprocessor; + +import lombok.Data; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.nifi.model.joinupdateprocessor + * @Project:fw-nifi + * @name:Revision17 + * @Date:2025/5/19 11:26 + * @Filename:Revision17 + */ +@Data +public class Revision17 { + private String version; +} diff --git a/fw-nifi/src/main/java/com/hzya/frame/nifi/model/joinupdateprocessor/RunStatusOrStop17.java b/fw-nifi/src/main/java/com/hzya/frame/nifi/model/joinupdateprocessor/RunStatusOrStop17.java new file mode 100644 index 00000000..cdefd927 --- /dev/null +++ b/fw-nifi/src/main/java/com/hzya/frame/nifi/model/joinupdateprocessor/RunStatusOrStop17.java @@ -0,0 +1,17 @@ +package com.hzya.frame.nifi.model.joinupdateprocessor; + +import lombok.Data; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.nifi.model.joinupdateprocessor + * @Project:fw-nifi + * @name:RunStatusOrStop + * @Date:2025/5/19 11:25 + * @Filename:RunStatusOrStop + */ +@Data +public class RunStatusOrStop17 { + private String state; + private Revision17 revision; +} diff --git a/fw-nifi/src/main/java/com/hzya/frame/nifi/model/resultprocessorsinfo/Component16.java b/fw-nifi/src/main/java/com/hzya/frame/nifi/model/resultprocessorsinfo/Component16.java new file mode 100644 index 00000000..4e75e98d --- /dev/null +++ b/fw-nifi/src/main/java/com/hzya/frame/nifi/model/resultprocessorsinfo/Component16.java @@ -0,0 +1,21 @@ +package com.hzya.frame.nifi.model.resultprocessorsinfo; + +import lombok.Data; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.nifi.model.resultprocessorsinfo + * @Project:fw-nifi + * @name:Component16 + * @Date:2025/5/19 10:05 + * @Filename:Component16 + */ +@Data +public class Component16 { + private String id; + private String parentGroupId; + private String name; + private String type; + private String state; + private Config16 config; +} diff --git a/fw-nifi/src/main/java/com/hzya/frame/nifi/model/resultprocessorsinfo/Config16.java b/fw-nifi/src/main/java/com/hzya/frame/nifi/model/resultprocessorsinfo/Config16.java new file mode 100644 index 00000000..a3819377 --- /dev/null +++ b/fw-nifi/src/main/java/com/hzya/frame/nifi/model/resultprocessorsinfo/Config16.java @@ -0,0 +1,31 @@ +package com.hzya.frame.nifi.model.resultprocessorsinfo; + +import lombok.Data; + +import java.util.Map; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.nifi.model.resultprocessorsinfo + * @Project:fw-nifi + * @name:Config16 + * @Date:2025/5/19 10:06 + * @Filename:Config16 + */ +@Data +public class Config16 { + private Map properties; + private String schedulingPeriod; + private String schedulingStrategy; + private String executionNodel; + private String penaltyDuration; + private String yieldDuration; + private String bulletinLevel; + private String runDurationMillis; + private String concurrentlySchedulableTaskCount; + private String comments; + private String lossTolerant; + private String retryCount; + private String backoffMechanism; + private String maxBackoffPeriod; +} diff --git a/fw-nifi/src/main/java/com/hzya/frame/nifi/model/resultprocessorsinfo/ProcessorsInfo16.java b/fw-nifi/src/main/java/com/hzya/frame/nifi/model/resultprocessorsinfo/ProcessorsInfo16.java new file mode 100644 index 00000000..62fbc248 --- /dev/null +++ b/fw-nifi/src/main/java/com/hzya/frame/nifi/model/resultprocessorsinfo/ProcessorsInfo16.java @@ -0,0 +1,18 @@ +package com.hzya.frame.nifi.model.resultprocessorsinfo; + +import lombok.Data; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.nifi.model.resultprocessorsinfo + * @Project:fw-nifi + * @name:ProcessorsInfo + * @Date:2025/5/19 10:03 + * @Filename:ProcessorsInfo + */ +@Data +public class ProcessorsInfo16 { + private String id; + private Component16 component; + private Revision16 revision; +} diff --git a/fw-nifi/src/main/java/com/hzya/frame/nifi/model/resultprocessorsinfo/Revision16.java b/fw-nifi/src/main/java/com/hzya/frame/nifi/model/resultprocessorsinfo/Revision16.java new file mode 100644 index 00000000..b6b3bb88 --- /dev/null +++ b/fw-nifi/src/main/java/com/hzya/frame/nifi/model/resultprocessorsinfo/Revision16.java @@ -0,0 +1,16 @@ +package com.hzya.frame.nifi.model.resultprocessorsinfo; + +import lombok.Data; + +/** + * @Author:liuyang + * @Package:com.hzya.frame.nifi.model.resultprocessorsinfo + * @Project:fw-nifi + * @name:Revision16 + * @Date:2025/5/19 10:04 + * @Filename:Revision16 + */ +@Data +public class Revision16 { + private String version; +} diff --git a/fw-nifi/src/main/java/com/hzya/frame/nifi/service/NifiApiService.java b/fw-nifi/src/main/java/com/hzya/frame/nifi/service/NifiApiService.java index 628077fb..7d321a3f 100644 --- a/fw-nifi/src/main/java/com/hzya/frame/nifi/service/NifiApiService.java +++ b/fw-nifi/src/main/java/com/hzya/frame/nifi/service/NifiApiService.java @@ -11,6 +11,7 @@ import com.hzya.frame.nifi.model.joinprocessgroups.ProcessGroupsJoin; import com.hzya.frame.nifi.model.joinsnippetinstance.SnippetInstanceJoin; import com.hzya.frame.nifi.model.joinsnippets.SnippetsJoin; import com.hzya.frame.nifi.model.joinstartorstopprocessgroup.StartOrStopProcessGroupsInfoJoin10; +import com.hzya.frame.nifi.model.joinupdateprocessor.RunStatusOrStop17; import com.hzya.frame.nifi.model.nifitemplates.NifiTemplates; import com.hzya.frame.nifi.model.processgroupid.ProcessGroupsId; import com.hzya.frame.nifi.model.processgrouproot.ProcessGroupsRoot; @@ -21,6 +22,7 @@ import com.hzya.frame.nifi.model.resultcreatetemplate.NewNifiTemplatete14; import com.hzya.frame.nifi.model.resultparametercontexts.ParameterContextsResult; import com.hzya.frame.nifi.model.resultprocessgroups.ProcessgroupsResult; import com.hzya.frame.nifi.model.resultprocessgroupsinfo.ProcessGroupsInfoResult9; +import com.hzya.frame.nifi.model.resultprocessorsinfo.ProcessorsInfo16; import com.hzya.frame.nifi.model.resultsnippets.SnippetResult13; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -212,4 +214,32 @@ public class NifiApiService { public CreateProcess16 createProcessor(String groupId, CreateProcessorJoin15 createProcessorJoin15) throws Exception { return client.post(StrUtil.format("/process-groups/{}/processors", groupId), createProcessorJoin15, CreateProcess16.class); } + + /** + * 查询处理器详情 + */ + public ProcessorsInfo16 getProcessor(String processId) throws Exception { + return client.get(StrUtil.format("/processors/{}", processId), ProcessorsInfo16.class); + } + + /** + * 更新处理器参数,如果处理器正在运行则无法更新 + */ + public ProcessorsInfo16 updateProcessor(String processId, ProcessorsInfo16 processorsInfo16) throws Exception { + return client.put(StrUtil.format("/processors/{}", processId), processorsInfo16, ProcessorsInfo16.class); + } + + /** + * 启用/停止处理器 + */ + public ProcessorsInfo16 runStatusOrStop(String processId, RunStatusOrStop17 runStatusOrStop17) throws Exception { + return client.put(StrUtil.format("/processors/{}/run-status", processId), runStatusOrStop17, ProcessorsInfo16.class); + } + + /** + * 删除处理器详情,如果处理器正在运行则无法删除 + */ + public ProcessorsInfo16 deleteProcessor(String processId, Map queryParams) throws Exception { + return client.delete(StrUtil.format("/processors/{}", processId), queryParams, ProcessorsInfo16.class); + } } \ No newline at end of file diff --git a/fw-nifi/target/classes/com/hzya/frame/nifi/client/NifiClient.class b/fw-nifi/target/classes/com/hzya/frame/nifi/client/NifiClient.class index 61e1ebf007acdaabe44318642163772d47adc0b6..8efeb1d2e5b79f355e278cb234e61bd7c4c7d894 100644 GIT binary patch literal 12973 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 literal 12667 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 i|9eoxDn79m`f?aVA~ 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 delta 2364 zcma)-+jkRH6vn@q6lOAO>`ka?im^0pN|M$HR>fMm)KUs+ky3(GqQ;WaN?Sq*m5L?c z4a5t=Q4tlzD_&`9+Jd!3m%gbl{slhy;BvWKKKSZ#pEEHzg~_TbE0c3h&iU=VzrD|% z(~;wCsUQBCz6_uN-x$#Gq!T_oW#DN%qvKf(NBQuWj^{KSH}E`O(D0&;mo%KY zqyZDBbTB@Dg+E@^@tTIyI$qas#=sjm#aG`n@D|P*c$;s2N5eTC@9KC@FUR{DKG5+Y z-}I4=^Ey7(@QH>`$HxX0<+Jn+>TiXvMcs*5G#P8}>*?!^4aECtoQx^xVB-s}W$lHP z?DvxERew00F7Ybth^xKWkIzliVwr|7Ox%nH_KPdxxPVc%x;*3@Gck@Y6|7`?3*2mn zYO=HCLyj~iSeZNMn?!?xvQRvlhz^jIM1A+3!DQ?}a$o4+h>0nT^2bHC%l%WyB@SLAa9b;As?e_Gj74O_GB#FLMsKdaw~mr!%9wK z^;MP2xqsHFM(I?M?Wx;&tn5%#ur+sTtrU$r8;u){xPvU^tY+eBBy$RyaHl~1S+!I` zwMnSrEUFl*u-Xo_N}$$Ytw4pnAqllfLV2<%522d#qwYeBK>g^I0}M+jIly)H0j?8X zwPL+MHC6jJa;*%J?Fg>JgA&e_^~{BNaBY;lARDc&OXZ~BDNvPU2&l-SDzHI##@9CD zZZdoi{cjZmU%8i7=BCA|(h<;KKs$X^Y$A>B!)6|VSX(H(ck^m1WnDFHN$A~DII=n& z_Ud#HPr(*+3U#Jy>N<1bB=Ur_H5*PC+w7d*O3<(X-;eD=r$(Qw)9}3D|E&`@mD8z< zVtD{NGCFn8J>qxTW9js(&m-w{Skg%@$OsjL%{7ULa2~?LLZ=P24MHcYijGnrIwpnW z&8FUqC>|l4PO0ZbaAl&YuS5m78#@K~=UTbaPe?w>xs2K8GA2+x*d=xkf=77)53+~52K5)MP4`Pofl4ieLB5pzM{vs}IO~)tT(d3r8neo8hML$cQv3~LwH~>P z{nvV27{=rI(l9JMIEW`Q9<)$8_{Av}9#jWQYsl`msJZgB_PrEnll+1h!66cLZd0RL RA0eiSlz1M_zD