diff --git a/pom.xml b/pom.xml index 837bacebf..058aec6c5 100644 --- a/pom.xml +++ b/pom.xml @@ -60,7 +60,6 @@ 2.5.11 2.3.4 - 0.16.0 3.14.0 @@ -366,12 +365,6 @@ ${rocketmq.version} - - org.apache.fory - fory-core - ${fory.version} - - org.dromara.warm diff --git a/ruoyi-api/pom.xml b/ruoyi-api/pom.xml index f827b1f1f..8b5f0b9e4 100644 --- a/ruoyi-api/pom.xml +++ b/ruoyi-api/pom.xml @@ -22,11 +22,4 @@ ruoyi-api系统接口 - - - org.springframework.cloud - spring-cloud-openfeign-core - - - diff --git a/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteFileService.java b/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteFileService.java index e1e7c754e..3f94c8cf4 100644 --- a/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteFileService.java +++ b/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteFileService.java @@ -1,15 +1,13 @@ package org.dromara.resource.api; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestMapping; import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.annotation.RemoteHttpService; import org.dromara.resource.api.domain.RemoteFile; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; +import org.springframework.web.service.annotation.PostExchange; import java.util.List; @@ -18,8 +16,8 @@ import java.util.List; * * @author Lion Li */ -@FeignClient(contextId = "remoteFileService", name = "ruoyi-resource", path = "/remote/file", - fallbackFactory = RemoteFileServiceFallbackFactory.class, primary = false) +@RemoteHttpService(value = "ruoyi-resource", fallback = RemoteFileServiceFallback.class) +@HttpExchange("/remote/file") public interface RemoteFileService { /** @@ -28,7 +26,7 @@ public interface RemoteFileService { * @param file 文件信息 * @return 结果 */ - @PostMapping("/upload") + @PostExchange("/upload") RemoteFile upload(@RequestParam String name, @RequestParam String originalFilename, @RequestParam String contentType, @RequestBody byte[] file) throws ServiceException; @@ -38,7 +36,7 @@ public interface RemoteFileService { * @param ossIds ossId串逗号分隔 * @return url串逗号分隔 */ - @GetMapping("/select-url-by-ids") + @GetExchange("/select-url-by-ids") String selectUrlByIds(@RequestParam String ossIds); /** @@ -47,7 +45,6 @@ public interface RemoteFileService { * @param ossIds ossId串逗号分隔 * @return 列表 */ - @GetMapping("/select-by-ids") + @GetExchange("/select-by-ids") List selectByIds(@RequestParam String ossIds); } - diff --git a/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteFileServiceFallback.java b/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteFileServiceFallback.java new file mode 100644 index 000000000..1e1de3beb --- /dev/null +++ b/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteFileServiceFallback.java @@ -0,0 +1,53 @@ +package org.dromara.resource.api; + +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.resource.api.domain.RemoteFile; + +import java.util.List; + +/** + * 文件服务熔断降级. + * + * @author Lion Li + */ +@Slf4j +public class RemoteFileServiceFallback implements RemoteFileService { + + /** + * 上传文件 + * + * @param file 文件信息 + * @return 结果 + */ + @Override + public RemoteFile upload(String name, String originalFilename, String contentType, byte[] file) { + log.warn("服务调用异常 -> 降级处理"); + return null; + } + + /** + * 通过ossId查询对应的url + * + * @param ossIds ossId串逗号分隔 + * @return url串逗号分隔 + */ + @Override + public String selectUrlByIds(String ossIds) { + log.warn("服务调用异常 -> 降级处理"); + return StringUtils.EMPTY; + } + + /** + * 通过ossId查询列表 + * + * @param ossIds ossId串逗号分隔 + * @return 列表 + */ + @Override + public List selectByIds(String ossIds) { + log.warn("服务调用异常 -> 降级处理"); + return List.of(); + } + +} diff --git a/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteFileServiceFallbackFactory.java b/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteFileServiceFallbackFactory.java deleted file mode 100644 index 99580dbc8..000000000 --- a/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteFileServiceFallbackFactory.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.dromara.resource.api; - -import lombok.extern.slf4j.Slf4j; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.resource.api.domain.RemoteFile; -import org.springframework.cloud.openfeign.FallbackFactory; - -import java.util.List; - -/** - * 文件服务 fallback factory. - * - * @author Lion Li - */ -@Slf4j -public class RemoteFileServiceFallbackFactory implements FallbackFactory { - - @Override - public RemoteFileService create(Throwable cause) { - return new RemoteFileService() { - @Override - public RemoteFile upload(String name, String originalFilename, String contentType, byte[] file) { - log.warn("文件服务调用失败, 已触发 fallback", cause); - return null; - } - - @Override - public String selectUrlByIds(String ossIds) { - log.warn("文件服务调用失败, 已触发 fallback", cause); - return StringUtils.EMPTY; - } - - @Override - public List selectByIds(String ossIds) { - log.warn("文件服务调用失败, 已触发 fallback", cause); - return List.of(); - } - }; - } -} diff --git a/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteMailService.java b/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteMailService.java index 1cf1c1e23..207822973 100644 --- a/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteMailService.java +++ b/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteMailService.java @@ -1,17 +1,18 @@ package org.dromara.resource.api; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.annotation.RemoteHttpService; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.service.annotation.HttpExchange; +import org.springframework.web.service.annotation.PostExchange; /** * 邮件服务 * * @author Lion Li */ -@FeignClient(contextId = "remoteMailService", name = "ruoyi-resource", path = "/remote/mail", primary = false) +@RemoteHttpService("ruoyi-resource") +@HttpExchange("/remote/mail") public interface RemoteMailService { /** @@ -21,9 +22,7 @@ public interface RemoteMailService { * @param subject 标题 * @param text 内容 */ - @PostMapping("/send") + @PostExchange("/send") void send(@RequestParam String to, @RequestParam String subject, @RequestParam String text) throws ServiceException; } - - diff --git a/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteMessageService.java b/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteMessageService.java index d4cc58ad1..0fa88bb41 100644 --- a/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteMessageService.java +++ b/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteMessageService.java @@ -1,13 +1,10 @@ package org.dromara.resource.api; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestMapping; +import org.dromara.common.core.annotation.RemoteHttpService; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.service.annotation.HttpExchange; +import org.springframework.web.service.annotation.PostExchange; import java.util.List; @@ -16,8 +13,8 @@ import java.util.List; * * @author Lion Li */ -@FeignClient(contextId = "remoteMessageService", name = "ruoyi-resource", path = "/remote/message", - fallbackFactory = RemoteMessageServiceFallbackFactory.class, primary = false) +@RemoteHttpService(value = "ruoyi-resource", fallback = RemoteMessageServiceFallback.class) +@HttpExchange("/remote/message") public interface RemoteMessageService { /** @@ -26,7 +23,7 @@ public interface RemoteMessageService { * @param sessionKey session主键 一般为用户id * @param message 消息文本 */ - @PostMapping("/publish-message") + @PostExchange("/publish-message") void publishMessage(@RequestBody List sessionKey, @RequestParam String message); /** @@ -34,7 +31,6 @@ public interface RemoteMessageService { * * @param message 消息内容 */ - @PostMapping("/publish-all") + @PostExchange("/publish-all") void publishAll(@RequestParam String message); } - diff --git a/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteMessageServiceFallback.java b/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteMessageServiceFallback.java new file mode 100644 index 000000000..573515ac0 --- /dev/null +++ b/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteMessageServiceFallback.java @@ -0,0 +1,35 @@ +package org.dromara.resource.api; + +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + +/** + * 消息服务熔断降级. + * + * @author Lion Li + */ +@Slf4j +public class RemoteMessageServiceFallback implements RemoteMessageService { + + /** + * 发送消息 + * + * @param sessionKey session主键 一般为用户id + * @param message 消息文本 + */ + @Override + public void publishMessage(List sessionKey, String message) { + log.warn("消息服务调用失败, 已触发熔断降级"); + } + + /** + * 发布订阅的消息(群发) + * + * @param message 消息内容 + */ + @Override + public void publishAll(String message) { + log.warn("消息服务调用失败, 已触发熔断降级"); + } +} diff --git a/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteMessageServiceFallbackFactory.java b/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteMessageServiceFallbackFactory.java deleted file mode 100644 index 2aa97ceb2..000000000 --- a/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteMessageServiceFallbackFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.dromara.resource.api; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.cloud.openfeign.FallbackFactory; - -import java.util.List; - -/** - * 消息服务 fallback factory. - * - * @author Lion Li - */ -@Slf4j -public class RemoteMessageServiceFallbackFactory implements FallbackFactory { - - @Override - public RemoteMessageService create(Throwable cause) { - return new RemoteMessageService() { - @Override - public void publishMessage(List sessionKey, String message) { - log.warn("消息服务调用失败, 已触发 fallback", cause); - } - - @Override - public void publishAll(String message) { - log.warn("消息服务调用失败, 已触发 fallback", cause); - } - }; - } -} diff --git a/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteSmsService.java b/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteSmsService.java index 1b17a763f..c0a8e7d8b 100644 --- a/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteSmsService.java +++ b/ruoyi-api/ruoyi-api-resource/src/main/java/org/dromara/resource/api/RemoteSmsService.java @@ -1,16 +1,13 @@ package org.dromara.resource.api; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestMapping; +import org.dromara.common.core.annotation.RemoteHttpService; import org.dromara.resource.api.domain.RemoteSms; import org.dromara.resource.api.domain.RemoteSmsBatch; import org.dromara.resource.api.domain.RemoteSmsDelayBatch; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.service.annotation.HttpExchange; +import org.springframework.web.service.annotation.PostExchange; import java.util.LinkedHashMap; import java.util.List; @@ -20,7 +17,8 @@ import java.util.List; * * @author Feng */ -@FeignClient(contextId = "remoteSmsService", name = "ruoyi-resource", path = "/inner/remote/resource/sms", primary = false) +@RemoteHttpService("ruoyi-resource") +@HttpExchange("/inner/remote/resource/sms") public interface RemoteSmsService { /** @@ -30,7 +28,7 @@ public interface RemoteSmsService { * @param message 短信内容 * @return 封装了短信发送结果的 RemoteSms 对象 */ - @PostMapping("/send-text") + @PostExchange("/send-text") RemoteSms sendMessage(@RequestParam String phone, @RequestParam String message); /** @@ -40,7 +38,7 @@ public interface RemoteSmsService { * @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序 * @return 封装了短信发送结果的 RemoteSms 对象 */ - @PostMapping("/send-vars") + @PostExchange("/send-vars") RemoteSms sendMessage(@RequestParam String phone, @RequestBody LinkedHashMap messages); /** @@ -51,7 +49,7 @@ public interface RemoteSmsService { * @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序 * @return 封装了短信发送结果的 RemoteSms 对象 */ - @PostMapping("/send-template") + @PostExchange("/send-template") RemoteSms sendMessage(@RequestParam String phone, @RequestParam String templateId, @RequestBody LinkedHashMap messages); @@ -62,7 +60,7 @@ public interface RemoteSmsService { * @param message 短信内容 * @return 封装了短信发送结果的 RemoteSms 对象 */ - @PostMapping("/message-texting") + @PostExchange("/message-texting") RemoteSms messageTexting(@RequestBody List phones, @RequestParam String message); /** @@ -73,7 +71,7 @@ public interface RemoteSmsService { * @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序 * @return 封装了短信发送结果的 RemoteSms 对象 */ - @PostMapping("/message-texting-template") + @PostExchange("/message-texting-template") default RemoteSms messageTexting(List phones, String templateId, LinkedHashMap messages) { return messageTextingTemplate(new RemoteSmsBatch(phones, templateId, messages)); } @@ -84,7 +82,7 @@ public interface RemoteSmsService { * @param request 群发模板短信请求 * @return 封装了短信发送结果的 RemoteSms 对象 */ - @PostMapping("/message-texting-template") + @PostExchange("/message-texting-template") RemoteSms messageTextingTemplate(@RequestBody RemoteSmsBatch request); /** @@ -93,7 +91,7 @@ public interface RemoteSmsService { * @param phone 目标手机号 * @param message 短信内容 */ - @PostMapping("/send-async-text") + @PostExchange("/send-async-text") void sendMessageAsync(@RequestParam String phone, @RequestParam String message); /** @@ -103,7 +101,7 @@ public interface RemoteSmsService { * @param templateId 短信模板ID * @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序 */ - @PostMapping("/send-async-template") + @PostExchange("/send-async-template") void sendMessageAsync(@RequestParam String phone, @RequestParam String templateId, @RequestBody LinkedHashMap messages); @@ -114,7 +112,7 @@ public interface RemoteSmsService { * @param message 短信内容 * @param delayedTime 延迟发送时间(毫秒) */ - @PostMapping("/delay-text") + @PostExchange("/delay-text") void delayMessage(@RequestParam String phone, @RequestParam String message, @RequestParam Long delayedTime); /** @@ -125,7 +123,7 @@ public interface RemoteSmsService { * @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序 * @param delayedTime 延迟发送时间(毫秒) */ - @PostMapping("/delay-template") + @PostExchange("/delay-template") void delayMessage(@RequestParam String phone, @RequestParam String templateId, @RequestBody LinkedHashMap messages, @RequestParam Long delayedTime); @@ -136,7 +134,7 @@ public interface RemoteSmsService { * @param message 短信内容 * @param delayedTime 延迟发送时间(毫秒) */ - @PostMapping("/delay-message-texting") + @PostExchange("/delay-message-texting") void delayMessageTexting(@RequestBody List phones, @RequestParam String message, @RequestParam Long delayedTime); /** @@ -147,7 +145,7 @@ public interface RemoteSmsService { * @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序 * @param delayedTime 延迟发送时间(毫秒) */ - @PostMapping("/delay-message-texting-template") + @PostExchange("/delay-message-texting-template") default void delayMessageTexting(List phones, String templateId, LinkedHashMap messages, Long delayedTime) { delayMessageTextingTemplate(new RemoteSmsDelayBatch(phones, templateId, messages, delayedTime)); @@ -158,7 +156,7 @@ public interface RemoteSmsService { * * @param request 延迟群发模板短信请求 */ - @PostMapping("/delay-message-texting-template") + @PostExchange("/delay-message-texting-template") void delayMessageTextingTemplate(@RequestBody RemoteSmsDelayBatch request); /** @@ -166,7 +164,7 @@ public interface RemoteSmsService { * * @param phone 手机号 */ - @PostMapping("/add-blacklist-one") + @PostExchange("/add-blacklist-one") void addBlacklist(@RequestParam String phone); /** @@ -174,7 +172,7 @@ public interface RemoteSmsService { * * @param phones 手机号列表 */ - @PostMapping("/add-blacklist-list") + @PostExchange("/add-blacklist-list") void addBlacklist(@RequestBody List phones); /** @@ -182,7 +180,7 @@ public interface RemoteSmsService { * * @param phone 手机号 */ - @PostMapping("/remove-blacklist-one") + @PostExchange("/remove-blacklist-one") void removeBlacklist(@RequestParam String phone); /** @@ -190,8 +188,7 @@ public interface RemoteSmsService { * * @param phones 手机号 */ - @PostMapping("/remove-blacklist-list") + @PostExchange("/remove-blacklist-list") void removeBlacklist(@RequestBody List phones); } - diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteClientService.java b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteClientService.java index 54a5076ab..4769e8f73 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteClientService.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteClientService.java @@ -1,20 +1,18 @@ package org.dromara.system.api; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestMapping; +import org.dromara.common.core.annotation.RemoteHttpService; import org.dromara.system.api.domain.vo.RemoteClientVo; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; /** * 客户端服务 * * @author Michelle.Chung */ -@FeignClient(contextId = "remoteClientService", name = "ruoyi-system", path = "/remote/client", primary = false) +@RemoteHttpService("ruoyi-system") +@HttpExchange("/remote/client") public interface RemoteClientService { /** @@ -23,8 +21,7 @@ public interface RemoteClientService { * @param clientId 客户端id * @return 客户端对象 */ - @GetMapping("/query-by-client-id") + @GetExchange("/query-by-client-id") RemoteClientVo queryByClientId(@RequestParam String clientId); } - diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteConfigService.java b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteConfigService.java index ede1c82c9..787360ba3 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteConfigService.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteConfigService.java @@ -1,15 +1,12 @@ package org.dromara.system.api; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestMapping; import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.Dict; +import org.dromara.common.core.annotation.RemoteHttpService; import org.dromara.common.json.utils.JsonUtils; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; import java.math.BigDecimal; import java.util.List; @@ -19,14 +16,15 @@ import java.util.List; * * @author Michelle.Chung */ -@FeignClient(contextId = "remoteConfigService", name = "ruoyi-system", path = "/remote/config", primary = false) +@RemoteHttpService("ruoyi-system") +@HttpExchange("/remote/config") public interface RemoteConfigService { /** * 获取注册开关 * @return true开启,false关闭 */ - @GetMapping("/select-register-enabled") + @GetExchange("/select-register-enabled") boolean selectRegisterEnabled(); /** @@ -35,7 +33,7 @@ public interface RemoteConfigService { * @param configKey 参数 key * @return 参数值 */ - @GetMapping("/get-config-value") + @GetExchange("/get-config-value") String getConfigValue(@RequestParam String configKey); /** @@ -123,4 +121,3 @@ public interface RemoteConfigService { } } - diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteDataScopeService.java b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteDataScopeService.java index 16a4b0d6a..710174640 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteDataScopeService.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteDataScopeService.java @@ -1,19 +1,17 @@ package org.dromara.system.api; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestMapping; +import org.dromara.common.core.annotation.RemoteHttpService; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; /** * 数据权限服务 * * @author Lion Li */ -@FeignClient(contextId = "remoteDataScopeService", name = "ruoyi-system", path = "/remote/data-scope", primary = false) +@RemoteHttpService("ruoyi-system") +@HttpExchange("/remote/data-scope") public interface RemoteDataScopeService { /** @@ -22,7 +20,7 @@ public interface RemoteDataScopeService { * @param roleId 角色ID * @return 返回角色的自定义权限语句,如果没有找到则返回 null */ - @GetMapping("/role-custom") + @GetExchange("/role-custom") String getRoleCustom(@RequestParam Long roleId); /** @@ -31,8 +29,7 @@ public interface RemoteDataScopeService { * @param deptId 部门ID * @return 返回部门及其下级的权限语句,如果没有找到则返回 null */ - @GetMapping("/dept-and-child") + @GetExchange("/dept-and-child") String getDeptAndChild(@RequestParam Long deptId); } - diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteDeptService.java b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteDeptService.java index 00ecfa8de..248d332d1 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteDeptService.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteDeptService.java @@ -1,14 +1,12 @@ package org.dromara.system.api; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestMapping; +import org.dromara.common.core.annotation.RemoteHttpService; import org.dromara.system.api.domain.vo.RemoteDeptVo; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; +import org.springframework.web.service.annotation.PostExchange; import java.util.Collection; import java.util.List; @@ -19,7 +17,8 @@ import java.util.Map; * * @author Lion Li */ -@FeignClient(contextId = "remoteDeptService", name = "ruoyi-system", path = "/remote/dept", primary = false) +@RemoteHttpService("ruoyi-system") +@HttpExchange("/remote/dept") public interface RemoteDeptService { /** @@ -28,7 +27,7 @@ public interface RemoteDeptService { * @param deptIds 部门ID串逗号分隔 * @return 部门名称串逗号分隔 */ - @GetMapping("/select-dept-name-by-ids") + @GetExchange("/select-dept-name-by-ids") String selectDeptNameByIds(@RequestParam String deptIds); /** @@ -37,7 +36,7 @@ public interface RemoteDeptService { * @param deptId 部门ID,用于指定需要查询的部门 * @return 返回该部门的负责人ID */ - @GetMapping("/select-dept-leader-by-id") + @GetExchange("/select-dept-leader-by-id") Long selectDeptLeaderById(@RequestParam Long deptId); /** @@ -45,7 +44,7 @@ public interface RemoteDeptService { * * @return 部门列表 */ - @GetMapping("/select-depts-by-list") + @GetExchange("/select-depts-by-list") List selectDeptsByList(); /** @@ -54,8 +53,7 @@ public interface RemoteDeptService { * @param deptIds 部门 ID 列表 * @return Map,其中 key 为部门 ID,value 为对应的部门名称 */ - @PostMapping("/select-dept-names-by-ids") + @PostExchange("/select-dept-names-by-ids") Map selectDeptNamesByIds(@RequestBody Collection deptIds); } - diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteDictService.java b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteDictService.java index 49715f485..1709158d5 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteDictService.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteDictService.java @@ -1,14 +1,11 @@ package org.dromara.system.api; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestMapping; +import org.dromara.common.core.annotation.RemoteHttpService; import org.dromara.system.api.domain.vo.RemoteDictDataVo; import org.dromara.system.api.domain.vo.RemoteDictTypeVo; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; import java.util.List; @@ -17,7 +14,8 @@ import java.util.List; * * @author Lion Li */ -@FeignClient(contextId = "remoteDictService", name = "ruoyi-system", path = "/remote/dict", primary = false) +@RemoteHttpService("ruoyi-system") +@HttpExchange("/remote/dict") public interface RemoteDictService { /** @@ -26,7 +24,7 @@ public interface RemoteDictService { * @param dictType 字典类型 * @return 字典类型 */ - @GetMapping("/select-dict-type-by-type") + @GetExchange("/select-dict-type-by-type") RemoteDictTypeVo selectDictTypeByType(@RequestParam String dictType); /** @@ -35,8 +33,7 @@ public interface RemoteDictService { * @param dictType 字典类型 * @return 字典数据集合信息 */ - @GetMapping("/select-dict-data-by-type") + @GetExchange("/select-dict-data-by-type") List selectDictDataByType(@RequestParam String dictType); } - diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteLogService.java b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteLogService.java index acf60c059..2d9f498e2 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteLogService.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteLogService.java @@ -1,21 +1,19 @@ package org.dromara.system.api; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestMapping; +import org.dromara.common.core.annotation.RemoteHttpService; import org.dromara.system.api.domain.bo.RemoteLoginInfoBo; import org.dromara.system.api.domain.bo.RemoteOperLogBo; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.service.annotation.HttpExchange; +import org.springframework.web.service.annotation.PostExchange; /** * 日志服务 * * @author Lion Li */ -@FeignClient(contextId = "remoteLogService", name = "ruoyi-system", path = "/remote/log", primary = false) +@RemoteHttpService("ruoyi-system") +@HttpExchange("/remote/log") public interface RemoteLogService { /** @@ -23,7 +21,7 @@ public interface RemoteLogService { * * @param sysOperLog 日志实体 */ - @PostMapping("/save-log") + @PostExchange("/save-log") void saveLog(@RequestBody RemoteOperLogBo sysOperLog); /** @@ -31,8 +29,7 @@ public interface RemoteLogService { * * @param sysLoginInfo 访问实体 */ - @PostMapping("/save-login-info") + @PostExchange("/save-login-info") void saveLoginInfo(@RequestBody RemoteLoginInfoBo sysLoginInfo); } - diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemotePermissionService.java b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemotePermissionService.java index 0f2548c72..d90aa9c4e 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemotePermissionService.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemotePermissionService.java @@ -1,12 +1,9 @@ package org.dromara.system.api; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestMapping; +import org.dromara.common.core.annotation.RemoteHttpService; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; import java.util.Set; @@ -15,7 +12,8 @@ import java.util.Set; * * @author Lion Li */ -@FeignClient(contextId = "remotePermissionService", name = "ruoyi-system", path = "/remote/permission", primary = false) +@RemoteHttpService("ruoyi-system") +@HttpExchange("/remote/permission") public interface RemotePermissionService { /** @@ -24,7 +22,7 @@ public interface RemotePermissionService { * @param userId 用户id * @return 角色权限信息 */ - @GetMapping("/role-permission") + @GetExchange("/role-permission") Set getRolePermission(@RequestParam Long userId); /** @@ -33,8 +31,7 @@ public interface RemotePermissionService { * @param userId 用户id * @return 菜单权限信息 */ - @GetMapping("/menu-permission") + @GetExchange("/menu-permission") Set getMenuPermission(@RequestParam Long userId); } - diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemotePostService.java b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemotePostService.java index 5a2f348cd..22b1c4b07 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemotePostService.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemotePostService.java @@ -1,12 +1,9 @@ package org.dromara.system.api; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestMapping; +import org.dromara.common.core.annotation.RemoteHttpService; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.service.annotation.HttpExchange; +import org.springframework.web.service.annotation.PostExchange; import java.util.Collection; import java.util.Map; @@ -16,7 +13,8 @@ import java.util.Map; * * @author Lion Li */ -@FeignClient(contextId = "remotePostService", name = "ruoyi-system", path = "/remote/post", primary = false) +@RemoteHttpService("ruoyi-system") +@HttpExchange("/remote/post") public interface RemotePostService { /** @@ -25,8 +23,7 @@ public interface RemotePostService { * @param postIds 岗位 ID 列表 * @return Map,其中 key 为岗位 ID,value 为对应的岗位名称 */ - @PostMapping("/select-post-names-by-ids") + @PostExchange("/select-post-names-by-ids") Map selectPostNamesByIds(@RequestBody Collection postIds); } - diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteRoleService.java b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteRoleService.java index aaad9740e..7ece23310 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteRoleService.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteRoleService.java @@ -1,12 +1,9 @@ package org.dromara.system.api; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestMapping; +import org.dromara.common.core.annotation.RemoteHttpService; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.service.annotation.HttpExchange; +import org.springframework.web.service.annotation.PostExchange; import java.util.Collection; import java.util.Map; @@ -16,7 +13,8 @@ import java.util.Map; * * @author Lion Li */ -@FeignClient(contextId = "remoteRoleService", name = "ruoyi-system", path = "/remote/role", primary = false) +@RemoteHttpService("ruoyi-system") +@HttpExchange("/remote/role") public interface RemoteRoleService { /** @@ -25,8 +23,7 @@ public interface RemoteRoleService { * @param roleIds 角色 ID 列表 * @return Map,其中 key 为角色 ID,value 为对应的角色名称 */ - @PostMapping("/select-role-names-by-ids") + @PostExchange("/select-role-names-by-ids") Map selectRoleNamesByIds(@RequestBody Collection roleIds); } - diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteSocialService.java b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteSocialService.java index 32fd6b1c4..2b236e671 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteSocialService.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteSocialService.java @@ -1,15 +1,13 @@ package org.dromara.system.api; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestMapping; +import org.dromara.common.core.annotation.RemoteHttpService; import org.dromara.system.api.domain.bo.RemoteSocialBo; import org.dromara.system.api.domain.vo.RemoteSocialVo; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; +import org.springframework.web.service.annotation.PostExchange; import java.util.List; @@ -18,7 +16,8 @@ import java.util.List; * * @author Michelle.Chung */ -@FeignClient(contextId = "remoteSocialService", name = "ruoyi-system", path = "/remote/social", primary = false) +@RemoteHttpService("ruoyi-system") +@HttpExchange("/remote/social") public interface RemoteSocialService { /** @@ -27,7 +26,7 @@ public interface RemoteSocialService { * @param authId 认证id * @return 授权信息 */ - @GetMapping("/select-by-auth-id") + @GetExchange("/select-by-auth-id") List selectByAuthId(@RequestParam String authId); /** @@ -35,7 +34,7 @@ public interface RemoteSocialService { * * @param bo 社会化关系业务对象 */ - @PostMapping("/query-list") + @PostExchange("/query-list") List queryList(@RequestBody RemoteSocialBo bo); /** @@ -43,7 +42,7 @@ public interface RemoteSocialService { * * @param bo 社会化关系业务对象 */ - @PostMapping("/insert-by-bo") + @PostExchange("/insert-by-bo") void insertByBo(@RequestBody RemoteSocialBo bo); /** @@ -51,7 +50,7 @@ public interface RemoteSocialService { * * @param bo 社会化关系业务对象 */ - @PostMapping("/update-by-bo") + @PostExchange("/update-by-bo") void updateByBo(@RequestBody RemoteSocialBo bo); /** @@ -60,8 +59,7 @@ public interface RemoteSocialService { * @param socialId 社会化关系ID * @return 结果 */ - @PostMapping("/delete-with-valid-by-id") + @PostExchange("/delete-with-valid-by-id") Boolean deleteWithValidById(@RequestParam Long socialId); } - diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteTaskAssigneeService.java b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteTaskAssigneeService.java index bd2406aad..4c44181a0 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteTaskAssigneeService.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteTaskAssigneeService.java @@ -1,21 +1,19 @@ package org.dromara.system.api; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestMapping; +import org.dromara.common.core.annotation.RemoteHttpService; import org.dromara.system.api.domain.bo.RemoteTaskAssigneeBo; import org.dromara.system.api.domain.vo.RemoteTaskAssigneeVo; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.service.annotation.HttpExchange; +import org.springframework.web.service.annotation.PostExchange; /** * 工作流设计器获取任务执行人 * * @author Lion Li */ -@FeignClient(contextId = "remoteTaskAssigneeService", name = "ruoyi-system", path = "/remote/task-assignee", primary = false) +@RemoteHttpService("ruoyi-system") +@HttpExchange("/remote/task-assignee") public interface RemoteTaskAssigneeService { /** @@ -24,7 +22,7 @@ public interface RemoteTaskAssigneeService { * @param taskQuery 查询条件 * @return 办理人 */ - @PostMapping("/select-roles") + @PostExchange("/select-roles") RemoteTaskAssigneeVo selectRolesByTaskAssigneeList(@RequestBody RemoteTaskAssigneeBo taskQuery); /** @@ -33,7 +31,7 @@ public interface RemoteTaskAssigneeService { * @param taskQuery 查询条件 * @return 办理人 */ - @PostMapping("/select-posts") + @PostExchange("/select-posts") RemoteTaskAssigneeVo selectPostsByTaskAssigneeList(@RequestBody RemoteTaskAssigneeBo taskQuery); /** @@ -42,7 +40,7 @@ public interface RemoteTaskAssigneeService { * @param taskQuery 查询条件 * @return 办理人 */ - @PostMapping("/select-depts") + @PostExchange("/select-depts") RemoteTaskAssigneeVo selectDeptsByTaskAssigneeList(@RequestBody RemoteTaskAssigneeBo taskQuery); /** @@ -51,8 +49,7 @@ public interface RemoteTaskAssigneeService { * @param taskQuery 查询条件 * @return 办理人 */ - @PostMapping("/select-users") + @PostExchange("/select-users") RemoteTaskAssigneeVo selectUsersByTaskAssigneeList(@RequestBody RemoteTaskAssigneeBo taskQuery); } - diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteUserService.java b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteUserService.java index a25632c68..16866fbca 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteUserService.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteUserService.java @@ -1,19 +1,17 @@ package org.dromara.system.api; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestMapping; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.user.UserException; +import org.dromara.common.core.annotation.RemoteHttpService; import org.dromara.system.api.domain.bo.RemoteUserBo; import org.dromara.system.api.domain.vo.RemoteUserVo; import org.dromara.system.api.model.LoginUser; import org.dromara.system.api.model.XcxLoginUser; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; +import org.springframework.web.service.annotation.PostExchange; import java.util.Collection; import java.util.List; @@ -24,7 +22,8 @@ import java.util.Map; * * @author Lion Li */ -@FeignClient(contextId = "remoteUserService", name = "ruoyi-system", path = "/remote/user", primary = false) +@RemoteHttpService("ruoyi-system") +@HttpExchange("/remote/user") public interface RemoteUserService { /** @@ -33,7 +32,7 @@ public interface RemoteUserService { * @param username 用户名 * @return 结果 */ - @GetMapping("/get-by-username") + @GetExchange("/get-by-username") LoginUser getUserInfo(@RequestParam String username) throws UserException; /** @@ -42,7 +41,7 @@ public interface RemoteUserService { * @param userId 用户id * @return 结果 */ - @GetMapping("/get-by-id") + @GetExchange("/get-by-id") LoginUser getUserInfo(@RequestParam Long userId) throws UserException; /** @@ -60,7 +59,7 @@ public interface RemoteUserService { * @param email 邮箱 * @return 结果 */ - @GetMapping("/get-by-email") + @GetExchange("/get-by-email") LoginUser getUserInfoByEmail(@RequestParam String email) throws UserException; /** @@ -69,7 +68,7 @@ public interface RemoteUserService { * @param openid openid * @return 结果 */ - @GetMapping("/get-by-openid") + @GetExchange("/get-by-openid") XcxLoginUser getUserInfoByOpenid(@RequestParam String openid) throws UserException; /** @@ -78,7 +77,7 @@ public interface RemoteUserService { * @param remoteUserBo 用户信息 * @return 结果 */ - @PostMapping("/register-user-info") + @PostExchange("/register-user-info") Boolean registerUserInfo(@RequestBody RemoteUserBo remoteUserBo) throws UserException, ServiceException; /** @@ -87,7 +86,7 @@ public interface RemoteUserService { * @param userId 用户id * @return 结果 */ - @GetMapping("/select-username-by-id") + @GetExchange("/select-username-by-id") String selectUserNameById(@RequestParam Long userId); /** @@ -96,7 +95,7 @@ public interface RemoteUserService { * @param userId 用户ID * @return 用户昵称 */ - @GetMapping("/select-nickname-by-id") + @GetExchange("/select-nickname-by-id") String selectNicknameById(@RequestParam Long userId); /** @@ -105,7 +104,7 @@ public interface RemoteUserService { * @param userIds 用户ID 多个用逗号隔开 * @return 用户昵称 */ - @GetMapping("/select-nickname-by-ids") + @GetExchange("/select-nickname-by-ids") String selectNicknameByIds(@RequestParam String userIds); /** @@ -114,7 +113,7 @@ public interface RemoteUserService { * @param userId 用户id * @return 用户手机号 */ - @GetMapping("/select-phonenumber-by-id") + @GetExchange("/select-phonenumber-by-id") String selectPhonenumberById(@RequestParam Long userId); /** @@ -123,7 +122,7 @@ public interface RemoteUserService { * @param userId 用户id * @return 用户邮箱 */ - @GetMapping("/select-email-by-id") + @GetExchange("/select-email-by-id") String selectEmailById(@RequestParam Long userId); /** @@ -132,7 +131,7 @@ public interface RemoteUserService { * @param userId 用户ID * @param ip IP地址 */ - @PostMapping("/record-login-info") + @PostExchange("/record-login-info") void recordLoginInfo(@RequestParam Long userId, @RequestParam String ip); /** @@ -141,7 +140,7 @@ public interface RemoteUserService { * @param userIds 用户ids * @return 用户列表 */ - @PostMapping("/select-list-by-ids") + @PostExchange("/select-list-by-ids") List selectListByIds(@RequestBody Collection userIds); /** @@ -150,7 +149,7 @@ public interface RemoteUserService { * @param roleIds 角色ids * @return 用户ids */ - @PostMapping("/select-user-ids-by-role-ids") + @PostExchange("/select-user-ids-by-role-ids") List selectUserIdsByRoleIds(@RequestBody Collection roleIds); /** @@ -159,7 +158,7 @@ public interface RemoteUserService { * @param roleIds 角色ids * @return 用户 */ - @PostMapping("/select-users-by-role-ids") + @PostExchange("/select-users-by-role-ids") List selectUsersByRoleIds(@RequestBody Collection roleIds); /** @@ -168,7 +167,7 @@ public interface RemoteUserService { * @param deptIds 部门ids * @return 用户 */ - @PostMapping("/select-users-by-dept-ids") + @PostExchange("/select-users-by-dept-ids") List selectUsersByDeptIds(@RequestBody Collection deptIds); /** @@ -177,7 +176,7 @@ public interface RemoteUserService { * @param postIds 岗位ids * @return 用户 */ - @PostMapping("/select-users-by-post-ids") + @PostExchange("/select-users-by-post-ids") List selectUsersByPostIds(@RequestBody Collection postIds); /** @@ -186,8 +185,7 @@ public interface RemoteUserService { * @param userIds 用户 ID 列表 * @return Map,其中 key 为用户 ID,value 为对应的用户昵称 */ - @PostMapping("/select-user-nicks-by-ids") + @PostExchange("/select-user-nicks-by-ids") Map selectUserNicksByIds(@RequestBody Collection userIds); } - diff --git a/ruoyi-api/ruoyi-api-workflow/src/main/java/org/dromara/workflow/api/RemoteWorkflowService.java b/ruoyi-api/ruoyi-api-workflow/src/main/java/org/dromara/workflow/api/RemoteWorkflowService.java index e21fc3c37..6dfbbfe9c 100644 --- a/ruoyi-api/ruoyi-api-workflow/src/main/java/org/dromara/workflow/api/RemoteWorkflowService.java +++ b/ruoyi-api/ruoyi-api-workflow/src/main/java/org/dromara/workflow/api/RemoteWorkflowService.java @@ -1,16 +1,14 @@ package org.dromara.workflow.api; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestMapping; +import org.dromara.common.core.annotation.RemoteHttpService; import org.dromara.workflow.api.domain.RemoteCompleteTask; import org.dromara.workflow.api.domain.RemoteStartProcess; import org.dromara.workflow.api.domain.RemoteStartProcessReturn; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; +import org.springframework.web.service.annotation.PostExchange; import java.util.List; import java.util.Map; @@ -21,8 +19,8 @@ import java.util.Map; * @Author ZETA * @Date 2024/6/3 */ -@FeignClient(contextId = "remoteWorkflowService", name = "ruoyi-workflow", path = "/remote/workflow", - fallbackFactory = RemoteWorkflowServiceFallbackFactory.class, primary = false) +@RemoteHttpService(value = "ruoyi-workflow", fallback = RemoteWorkflowServiceFallback.class) +@HttpExchange("/remote/workflow") public interface RemoteWorkflowService { /** @@ -31,7 +29,7 @@ public interface RemoteWorkflowService { * @param businessIds 业务id * @return 结果 */ - @PostMapping("/delete-instance") + @PostExchange("/delete-instance") boolean deleteInstance(@RequestBody List businessIds); /** @@ -40,7 +38,7 @@ public interface RemoteWorkflowService { * @param taskId 任务id * @return 状态 */ - @GetMapping("/business-status-by-task-id") + @GetExchange("/business-status-by-task-id") String getBusinessStatusByTaskId(@RequestParam Long taskId); /** @@ -49,7 +47,7 @@ public interface RemoteWorkflowService { * @param businessId 业务id * @return 状态 */ - @GetMapping("/business-status") + @GetExchange("/business-status") String getBusinessStatus(@RequestParam String businessId); /** @@ -58,7 +56,7 @@ public interface RemoteWorkflowService { * @param instanceId 流程实例id * @param variable 流程变量 */ - @PostMapping("/set-variable") + @PostExchange("/set-variable") void setVariable(@RequestParam Long instanceId, @RequestBody Map variable); /** @@ -66,7 +64,7 @@ public interface RemoteWorkflowService { * * @param instanceId 流程实例id */ - @GetMapping("/instance-variable") + @GetExchange("/instance-variable") Map instanceVariable(@RequestParam Long instanceId); /** @@ -75,7 +73,7 @@ public interface RemoteWorkflowService { * @param businessId 业务id * @return 结果 */ - @GetMapping("/instance-id-by-business-id") + @GetExchange("/instance-id-by-business-id") Long getInstanceIdByBusinessId(@RequestParam String businessId); /** @@ -84,7 +82,7 @@ public interface RemoteWorkflowService { * @param startProcess 参数 * @return 结果 */ - @PostMapping("/start-workflow") + @PostExchange("/start-workflow") RemoteStartProcessReturn startWorkFlow(@RequestBody RemoteStartProcess startProcess); /** @@ -93,7 +91,7 @@ public interface RemoteWorkflowService { * @param completeTask 参数 * @return 结果 */ - @PostMapping("/complete-task") + @PostExchange("/complete-task") boolean completeTask(@RequestBody RemoteCompleteTask completeTask); @@ -104,7 +102,7 @@ public interface RemoteWorkflowService { * @param message 办理意见 * @return 结果 */ - @PostMapping("/complete-task-simple") + @PostExchange("/complete-task-simple") boolean completeTask(@RequestParam Long taskId, @RequestParam String message); /** @@ -113,8 +111,7 @@ public interface RemoteWorkflowService { * @param startProcess 参数 * @return 结果 */ - @PostMapping("/start-complete-task") + @PostExchange("/start-complete-task") boolean startCompleteTask(@RequestBody RemoteStartProcess startProcess); } - diff --git a/ruoyi-api/ruoyi-api-workflow/src/main/java/org/dromara/workflow/api/RemoteWorkflowServiceFallback.java b/ruoyi-api/ruoyi-api-workflow/src/main/java/org/dromara/workflow/api/RemoteWorkflowServiceFallback.java new file mode 100644 index 000000000..4caf87815 --- /dev/null +++ b/ruoyi-api/ruoyi-api-workflow/src/main/java/org/dromara/workflow/api/RemoteWorkflowServiceFallback.java @@ -0,0 +1,78 @@ +package org.dromara.workflow.api; + +import lombok.extern.slf4j.Slf4j; +import org.dromara.workflow.api.domain.RemoteCompleteTask; +import org.dromara.workflow.api.domain.RemoteStartProcess; +import org.dromara.workflow.api.domain.RemoteStartProcessReturn; + +import java.util.List; +import java.util.Map; + +/** + * 工作流服务熔断降级. + * + * @author Lion Li + */ +@Slf4j +public class RemoteWorkflowServiceFallback implements RemoteWorkflowService { + + @Override + public boolean deleteInstance(List businessIds) { + log.warn("服务调用异常 -> 降级处理"); + return false; + } + + @Override + public String getBusinessStatusByTaskId(Long taskId) { + log.warn("服务调用异常 -> 降级处理"); + return null; + } + + @Override + public String getBusinessStatus(String businessId) { + log.warn("服务调用异常 -> 降级处理"); + return null; + } + + @Override + public void setVariable(Long instanceId, Map variable) { + log.warn("服务调用异常 -> 降级处理"); + } + + @Override + public Map instanceVariable(Long instanceId) { + log.warn("服务调用异常 -> 降级处理"); + return null; + } + + @Override + public Long getInstanceIdByBusinessId(String businessId) { + log.warn("服务调用异常 -> 降级处理"); + return null; + } + + @Override + public RemoteStartProcessReturn startWorkFlow(RemoteStartProcess startProcess) { + log.warn("服务调用异常 -> 降级处理"); + return null; + } + + @Override + public boolean completeTask(RemoteCompleteTask completeTask) { + log.warn("服务调用异常 -> 降级处理"); + return false; + } + + @Override + public boolean completeTask(Long taskId, String message) { + log.warn("服务调用异常 -> 降级处理"); + return false; + } + + @Override + public boolean startCompleteTask(RemoteStartProcess startProcess) { + log.warn("服务调用异常 -> 降级处理"); + return false; + } + +} diff --git a/ruoyi-api/ruoyi-api-workflow/src/main/java/org/dromara/workflow/api/RemoteWorkflowServiceFallbackFactory.java b/ruoyi-api/ruoyi-api-workflow/src/main/java/org/dromara/workflow/api/RemoteWorkflowServiceFallbackFactory.java deleted file mode 100644 index b2d7495fc..000000000 --- a/ruoyi-api/ruoyi-api-workflow/src/main/java/org/dromara/workflow/api/RemoteWorkflowServiceFallbackFactory.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.dromara.workflow.api; - -import lombok.extern.slf4j.Slf4j; -import org.dromara.workflow.api.domain.RemoteCompleteTask; -import org.dromara.workflow.api.domain.RemoteStartProcess; -import org.dromara.workflow.api.domain.RemoteStartProcessReturn; -import org.springframework.cloud.openfeign.FallbackFactory; - -import java.util.List; -import java.util.Map; - -/** - * 工作流服务 fallback factory. - * - * @author Lion Li - */ -@Slf4j -public class RemoteWorkflowServiceFallbackFactory implements FallbackFactory { - - @Override - public RemoteWorkflowService create(Throwable cause) { - return new RemoteWorkflowService() { - @Override - public boolean deleteInstance(List businessIds) { - log.warn("工作流服务调用失败, 已触发 fallback", cause); - return false; - } - - @Override - public String getBusinessStatusByTaskId(Long taskId) { - log.warn("工作流服务调用失败, 已触发 fallback", cause); - return null; - } - - @Override - public String getBusinessStatus(String businessId) { - log.warn("工作流服务调用失败, 已触发 fallback", cause); - return null; - } - - @Override - public void setVariable(Long instanceId, Map variable) { - log.warn("工作流服务调用失败, 已触发 fallback", cause); - } - - @Override - public Map instanceVariable(Long instanceId) { - log.warn("工作流服务调用失败, 已触发 fallback", cause); - return null; - } - - @Override - public Long getInstanceIdByBusinessId(String businessId) { - log.warn("工作流服务调用失败, 已触发 fallback", cause); - return null; - } - - @Override - public RemoteStartProcessReturn startWorkFlow(RemoteStartProcess startProcess) { - log.warn("工作流服务调用失败, 已触发 fallback", cause); - return null; - } - - @Override - public boolean completeTask(RemoteCompleteTask completeTask) { - log.warn("工作流服务调用失败, 已触发 fallback", cause); - return false; - } - - @Override - public boolean completeTask(Long taskId, String message) { - log.warn("工作流服务调用失败, 已触发 fallback", cause); - return false; - } - - @Override - public boolean startCompleteTask(RemoteStartProcess startProcess) { - log.warn("工作流服务调用失败, 已触发 fallback", cause); - return false; - } - }; - } -} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/annotation/RemoteHttpService.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/annotation/RemoteHttpService.java new file mode 100644 index 000000000..a9350856f --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/annotation/RemoteHttpService.java @@ -0,0 +1,38 @@ +package org.dromara.common.core.annotation; + +import org.springframework.core.annotation.AliasFor; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 声明远程 HTTP Service 所属服务. + * + * @author Lion Li + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RemoteHttpService { + + /** + * 服务名. + */ + @AliasFor("serviceId") + String value() default ""; + + /** + * 服务名. + */ + @AliasFor("value") + String serviceId() default ""; + + /** + * 远程调用失败时的 fallback 实现. + */ + Class fallback() default void.class; + +} diff --git a/ruoyi-common/ruoyi-common-http/pom.xml b/ruoyi-common/ruoyi-common-http/pom.xml index 0207c7218..a7789a572 100644 --- a/ruoyi-common/ruoyi-common-http/pom.xml +++ b/ruoyi-common/ruoyi-common-http/pom.xml @@ -31,32 +31,15 @@ ruoyi-common-satoken - - org.dromara - ruoyi-common-mybatis - true - - - - org.springframework.cloud - spring-cloud-starter-openfeign - - org.springframework.cloud spring-cloud-starter-loadbalancer - org.springframework.cloud - spring-cloud-starter-circuitbreaker-resilience4j + org.eclipse.jetty + jetty-client - - - org.apache.fory - fory-core - - diff --git a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/annotation/RemoteServiceController.java b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/annotation/RemoteServiceController.java index c398af5e3..c13dab0bd 100644 --- a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/annotation/RemoteServiceController.java +++ b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/annotation/RemoteServiceController.java @@ -1,9 +1,7 @@ package org.dromara.common.http.annotation; import org.springframework.core.annotation.AliasFor; -import org.springframework.context.annotation.Primary; import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.bind.annotation.RequestMapping; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; @@ -20,13 +18,8 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Documented @RestController -@RequestMapping -@Primary public @interface RemoteServiceController { @AliasFor(annotation = RestController.class, attribute = "value") String value() default ""; - - @AliasFor(annotation = RequestMapping.class, attribute = "path") - String[] path() default {}; } diff --git a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/config/RemoteHttpAutoConfiguration.java b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/config/RemoteHttpAutoConfiguration.java index fe94b0744..de6d05170 100644 --- a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/config/RemoteHttpAutoConfiguration.java +++ b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/config/RemoteHttpAutoConfiguration.java @@ -1,35 +1,38 @@ package org.dromara.common.http.config; import cn.dev33.satoken.same.SaSameUtil; -import feign.Logger; -import feign.RequestInterceptor; -import feign.Response; -import feign.codec.ErrorDecoder; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.domain.R; import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.ServletUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.core.annotation.RemoteHttpService; import org.dromara.common.http.annotation.RemoteServiceController; import org.dromara.common.http.log.aspect.RemoteHttpProviderLogAspect; import org.dromara.common.http.handler.RemoteHttpExceptionHandler; -import org.dromara.common.http.log.support.RemoteHttpFeignLogger; +import org.dromara.common.http.properties.RemoteHttpProperties; +import org.dromara.common.http.registrar.RemoteHttpServiceRegistrar; +import org.dromara.common.http.support.RemoteHttpFallbackProxyPostProcessor; +import org.dromara.common.http.log.support.LoggingHttpExchangeAdapter; import org.dromara.common.http.log.support.RemoteHttpLogSupport; import org.dromara.common.json.utils.JsonUtils; -import org.dromara.common.core.utils.ServletUtils; -import org.dromara.common.core.utils.StringUtils; import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.aop.framework.autoproxy.AutoProxyUtils; +import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Bean; -import org.springframework.cloud.openfeign.EnableFeignClients; -import org.springframework.cloud.openfeign.FeignClientFactoryBean; import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.util.StreamUtils; +import org.springframework.web.client.support.RestClientHttpServiceGroupConfigurer; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -40,24 +43,26 @@ import java.nio.charset.StandardCharsets; * 这里把运行时几条链路接起来: * 1. Consumer 发请求前透传认证头和 Seata XID * 2. 远程非 2xx 响应统一转成 ServiceException - * 3. 打开请求日志时,为 consumer/provider 两侧挂统一日志 + * 3. 打开请求日志时,为 consumer/provider 两侧挂日志能力 + * 4. 远程代理失败时按接口声明触发 fallback * * @author Lion Li */ @Slf4j @AutoConfiguration -@EnableFeignClients(basePackages = "org.dromara") +@Import(RemoteHttpServiceRegistrar.class) +@EnableConfigurationProperties(RemoteHttpProperties.class) public class RemoteHttpAutoConfiguration { @Bean - public static BeanDefinitionRegistryPostProcessor remoteHttpControllerProxyCompatibilityPostProcessor() { + public static BeanFactoryPostProcessor remoteHttpControllerProxyCompatibilityPostProcessor() { return new RemoteHttpInfrastructurePostProcessor(); } - @Bean - public RequestInterceptor remoteHttpRequestInterceptor() { - return requestTemplate -> { - HttpHeaders headers = new HttpHeaders(); + @Bean("remoteHttpHeaderInterceptor") + public ClientHttpRequestInterceptor remoteHttpHeaderInterceptor() { + return (request, body, execution) -> { + HttpHeaders headers = request.getHeaders(); HttpServletRequest currentRequest = ServletUtils.getRequest(); if (currentRequest != null) { String authorization = currentRequest.getHeader(HttpHeaders.AUTHORIZATION); @@ -71,29 +76,35 @@ public class RemoteHttpAutoConfiguration { } catch (Exception ignored) { } relaySeataXid(headers); - headers.forEach((key, values) -> values.forEach(value -> requestTemplate.header(key, value))); + return execution.execute(request, body); }; } @Bean - public Logger remoteHttpFeignLogger( + public RestClientHttpServiceGroupConfigurer remoteHttpServiceGroupConfigurer( + ClientHttpRequestInterceptor remoteHttpHeaderInterceptor, RemoteHttpLogSupport remoteHttpLogSupport) { - return new RemoteHttpFeignLogger(remoteHttpLogSupport); + return groups -> groups.forEachGroup((group, clientBuilder, proxyFactoryBuilder) -> { + clientBuilder.requestInterceptor(remoteHttpHeaderInterceptor) + // provider 侧远程接口异常会直接映射成非 2xx,这里只按 HTTP 状态处理即可。 + .defaultStatusHandler(HttpStatusCode::isError, (request, response) -> { + throwServiceException(response.getStatusCode().value(), response.getStatusText(), readResponseBody(response)); + }); + if (remoteHttpLogSupport.isEnabled()) { + // consumer 侧日志挂在 HttpExchangeAdapter 上,避免碰底层 body 重复读取问题。 + proxyFactoryBuilder.exchangeAdapterDecorator(adapter -> new LoggingHttpExchangeAdapter(adapter, remoteHttpLogSupport)); + } + }); } @Bean - public Logger.Level remoteHttpFeignLoggerLevel() { - return Logger.Level.BASIC; + public RemoteHttpFallbackProxyPostProcessor remoteHttpFallbackProxyPostProcessor() { + return new RemoteHttpFallbackProxyPostProcessor(); } @Bean - public ErrorDecoder remoteHttpErrorDecoder() { - return (methodKey, response) -> buildServiceException(response.status(), response.reason(), readResponseBody(response)); - } - - @Bean - public RemoteHttpLogSupport remoteHttpLogSupport() { - return new RemoteHttpLogSupport(); + public RemoteHttpLogSupport remoteHttpLogSupport(RemoteHttpProperties properties) { + return new RemoteHttpLogSupport(properties); } @Bean @@ -122,85 +133,50 @@ public class RemoteHttpAutoConfiguration { } } - private String readResponseBody(Response response) { - if (response.body() == null) { - return null; - } + private String readResponseBody(org.springframework.http.client.ClientHttpResponse response) { try { - return StreamUtils.copyToString(response.body().asInputStream(), StandardCharsets.UTF_8); + return StreamUtils.copyToString(response.getBody(), StandardCharsets.UTF_8); } catch (IOException e) { log.debug("read remote response body failed", e); return null; } } - private ServiceException buildServiceException(int statusCode, String statusText, String responseBody) { + private void throwServiceException(int statusCode, String statusText, String responseBody) { if (StringUtils.isNotBlank(responseBody) && JsonUtils.isJsonObject(responseBody)) { try { // 远程服务如果按 R 返回错误信息,优先还原成更友好的业务异常消息。 R result = JsonUtils.parseObject(responseBody, R.class); if (result != null && (result.getCode() == 0 || R.isSuccess(result))) { - return new ServiceException(StringUtils.defaultIfBlank(statusText, "远程服务调用失败"), statusCode); + return; } if (result != null && StringUtils.isNotBlank(result.getMsg())) { - return new ServiceException(result.getMsg(), result.getCode()); + throw new ServiceException(result.getMsg(), result.getCode()); } + } catch (ServiceException se) { + throw se; } catch (RuntimeException e) { log.debug("parse remote error body failed: {}", responseBody, e); } } String message = StringUtils.firstNonBlank(responseBody, statusText, "远程服务调用失败"); - return new ServiceException(message, statusCode); + throw new ServiceException(message, statusCode); } - private static final class RemoteHttpInfrastructurePostProcessor implements BeanDefinitionRegistryPostProcessor { - - @Override - public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { - for (String beanName : registry.getBeanDefinitionNames()) { - BeanDefinition beanDefinition = registry.getBeanDefinition(beanName); - registerFallbackBeanIfNecessary(registry, beanDefinition, "fallback"); - registerFallbackBeanIfNecessary(registry, beanDefinition, "fallbackFactory"); - } - } + private static final class RemoteHttpInfrastructurePostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { + BeanDefinitionRegistry registry = beanFactory instanceof BeanDefinitionRegistry beanDefinitionRegistry + ? beanDefinitionRegistry : null; + ClassLoader beanClassLoader = beanFactory.getBeanClassLoader(); for (String beanName : beanFactory.getBeanDefinitionNames()) { BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName); preserveRemoteControllerTargetClass(beanDefinition); + registerFallbackBeanDefinition(registry, beanFactory, beanDefinition, beanClassLoader); } } - private void registerFallbackBeanIfNecessary(BeanDefinitionRegistry registry, BeanDefinition beanDefinition, - String propertyName) { - if (!FeignClientFactoryBean.class.getName().equals(beanDefinition.getBeanClassName())) { - return; - } - Object propertyValue = beanDefinition.getPropertyValues().get(propertyName); - if (!(propertyValue instanceof Class fallbackType) || Object.class == fallbackType || void.class == fallbackType) { - return; - } - // fallback/fallbackFactory 常放在 api 模块里,默认应用包扫描不会覆盖到这里, - // 所以在 FeignClient 注册完成后顺手把它补成 Spring Bean。 - String fallbackBeanName = fallbackType.getName(); - if (registry.containsBeanDefinition(fallbackBeanName) || hasBeanClass(registry, fallbackType)) { - return; - } - registry.registerBeanDefinition(fallbackBeanName, - BeanDefinitionBuilder.genericBeanDefinition(fallbackType).getBeanDefinition()); - } - - private boolean hasBeanClass(BeanDefinitionRegistry registry, Class beanClass) { - for (String beanName : registry.getBeanDefinitionNames()) { - BeanDefinition candidate = registry.getBeanDefinition(beanName); - if (beanClass.getName().equals(candidate.getBeanClassName())) { - return true; - } - } - return false; - } - private void preserveRemoteControllerTargetClass(BeanDefinition beanDefinition) { if (!(beanDefinition instanceof AnnotatedBeanDefinition annotatedBeanDefinition)) { return; @@ -210,5 +186,48 @@ public class RemoteHttpAutoConfiguration { } beanDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE); } + + private void registerFallbackBeanDefinition(BeanDefinitionRegistry registry, + ConfigurableListableBeanFactory beanFactory, BeanDefinition beanDefinition, ClassLoader beanClassLoader) { + if (registry == null) { + return; + } + Class serviceInterface = resolveRemoteServiceInterface(beanDefinition, beanClassLoader); + if (serviceInterface == null) { + return; + } + RemoteHttpService remoteHttpService = serviceInterface.getAnnotation(RemoteHttpService.class); + if (remoteHttpService == null || remoteHttpService.fallback() == void.class) { + return; + } + Class fallbackClass = remoteHttpService.fallback(); + if (!serviceInterface.isAssignableFrom(fallbackClass)) { + throw new IllegalStateException("Fallback class must implement remote service interface: " + + fallbackClass.getName() + " -> " + serviceInterface.getName()); + } + if (beanFactory.getBeanNamesForType(fallbackClass, false, false).length > 0) { + return; + } + BeanDefinition fallbackBeanDefinition = BeanDefinitionBuilder.genericBeanDefinition(fallbackClass) + .setLazyInit(true) + .getBeanDefinition(); + // fallback 只给框架内部按具体类型获取使用,不参与业务侧按接口类型自动注入, + // 否则会和真正的远程代理一起成为 RemoteXxxService 的候选 Bean。 + fallbackBeanDefinition.setAutowireCandidate(false); + fallbackBeanDefinition.setPrimary(false); + registry.registerBeanDefinition(fallbackClass.getName(), fallbackBeanDefinition); + } + + private Class resolveRemoteServiceInterface(BeanDefinition beanDefinition, ClassLoader beanClassLoader) { + String beanClassName = beanDefinition.getBeanClassName(); + if (beanClassName == null || beanClassLoader == null) { + return null; + } + Class beanClass = org.springframework.util.ClassUtils.resolveClassName(beanClassName, beanClassLoader); + if (!beanClass.isInterface() || !beanClass.isAnnotationPresent(RemoteHttpService.class)) { + return null; + } + return beanClass; + } } } diff --git a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/config/RemoteHttpDataPermissionAutoConfiguration.java b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/config/RemoteHttpDataPermissionAutoConfiguration.java deleted file mode 100644 index 6448bcaf2..000000000 --- a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/config/RemoteHttpDataPermissionAutoConfiguration.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.dromara.common.http.config; - -import feign.RequestInterceptor; -import org.dromara.common.http.support.RemoteHttpDataPermissionCodec; -import org.dromara.common.http.support.RemoteHttpDataPermissionInterceptor; -import org.dromara.common.http.support.RemoteHttpDataPermissionRequestInterceptor; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.context.annotation.Bean; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -/** - * 数据权限透传自动配置。 - * - * 仅在引入 ruoyi-common-mybatis 后生效。 - */ -@AutoConfiguration -@ConditionalOnClass(name = "org.dromara.common.mybatis.helper.DataPermissionHelper") -public class RemoteHttpDataPermissionAutoConfiguration { - - @Bean - public RemoteHttpDataPermissionCodec remoteHttpDataPermissionCodec() { - return new RemoteHttpDataPermissionCodec(); - } - - @Bean - public RequestInterceptor remoteHttpDataPermissionRequestInterceptor( - RemoteHttpDataPermissionCodec remoteHttpDataPermissionCodec) { - return new RemoteHttpDataPermissionRequestInterceptor(remoteHttpDataPermissionCodec); - } - - @Bean - public RemoteHttpDataPermissionInterceptor remoteHttpDataPermissionInterceptor( - RemoteHttpDataPermissionCodec remoteHttpDataPermissionCodec) { - return new RemoteHttpDataPermissionInterceptor(remoteHttpDataPermissionCodec); - } - - @Bean - public WebMvcConfigurer remoteHttpDataPermissionWebMvcConfigurer( - RemoteHttpDataPermissionInterceptor remoteHttpDataPermissionInterceptor) { - return new WebMvcConfigurer() { - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(remoteHttpDataPermissionInterceptor); - } - }; - } -} diff --git a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/log/aspect/RemoteHttpProviderLogAspect.java b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/log/aspect/RemoteHttpProviderLogAspect.java index c95045dbe..1ca4264d2 100644 --- a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/log/aspect/RemoteHttpProviderLogAspect.java +++ b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/log/aspect/RemoteHttpProviderLogAspect.java @@ -1,19 +1,19 @@ package org.dromara.common.http.log.aspect; import jakarta.servlet.http.HttpServletRequest; -import org.springframework.cloud.openfeign.FeignClient; import lombok.RequiredArgsConstructor; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.dromara.common.core.utils.ServletUtils; +import org.dromara.common.core.annotation.RemoteHttpService; import org.dromara.common.http.log.support.RemoteHttpLogSupport; import org.springframework.http.HttpMethod; +import org.springframework.web.service.annotation.HttpExchange; import org.springframework.aop.support.AopUtils; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.util.StringUtils; -import org.springframework.web.bind.annotation.RequestMapping; import java.lang.reflect.Method; @@ -40,9 +40,9 @@ public class RemoteHttpProviderLogAspect { HttpServletRequest request = ServletUtils.getRequest(); Class remoteInterface = resolveRemoteInterface(targetClass, method); // 真实 HTTP 调用时优先从 servlet 请求拿 method/path; - // 本地注入 provider bean 时再回退到接口上的 Spring MVC 映射注解。 - HttpMethod httpMethod = resolveHttpMethod(request, remoteInterface, targetClass, method); - String path = resolvePath(request, remoteInterface, targetClass, method); + // 本地短路调用时再回退到接口上的 @HttpExchange 注解。 + HttpMethod httpMethod = resolveHttpMethod(request, remoteInterface, method); + String path = resolvePath(request, remoteInterface, method); this.logSupport.logRequest(RemoteHttpLogSupport.PROVIDER, httpMethod, path, arguments); long startTime = System.currentTimeMillis(); try { @@ -55,25 +55,22 @@ public class RemoteHttpProviderLogAspect { } } - private HttpMethod resolveHttpMethod(HttpServletRequest request, Class remoteInterface, Class targetClass, Method method) { + private HttpMethod resolveHttpMethod(HttpServletRequest request, Class remoteInterface, Method method) { if (request != null && StringUtils.hasText(request.getMethod())) { return HttpMethod.valueOf(request.getMethod()); } - RequestMapping methodMapping = resolveMethodMapping(remoteInterface, method); - if (methodMapping != null && methodMapping.method().length > 0) { - return HttpMethod.valueOf(methodMapping.method()[0].name()); + HttpExchange methodExchange = resolveMethodExchange(remoteInterface, method); + if (methodExchange != null && StringUtils.hasText(methodExchange.method())) { + return HttpMethod.valueOf(methodExchange.method()); } - RequestMapping typeMapping = resolveTypeMapping(remoteInterface); - if (typeMapping == null) { - typeMapping = resolveTypeMapping(targetClass); - } - if (typeMapping != null && typeMapping.method().length > 0) { - return HttpMethod.valueOf(typeMapping.method()[0].name()); + HttpExchange typeExchange = resolveTypeExchange(remoteInterface); + if (typeExchange != null && StringUtils.hasText(typeExchange.method())) { + return HttpMethod.valueOf(typeExchange.method()); } return null; } - private String resolvePath(HttpServletRequest request, Class remoteInterface, Class targetClass, Method method) { + private String resolvePath(HttpServletRequest request, Class remoteInterface, Method method) { if (request != null) { String requestUri = request.getRequestURI(); if (StringUtils.hasText(requestUri)) { @@ -84,11 +81,8 @@ public class RemoteHttpProviderLogAspect { return requestUri + '?' + queryString; } } - String typePath = extractPath(resolveTypeMapping(remoteInterface)); - if (!StringUtils.hasText(typePath)) { - typePath = extractPath(resolveTypeMapping(targetClass)); - } - String methodPath = extractPath(resolveMethodMapping(remoteInterface, method)); + String typePath = extractPath(resolveTypeExchange(remoteInterface)); + String methodPath = extractPath(resolveMethodExchange(remoteInterface, method)); if (!StringUtils.hasText(typePath)) { return methodPath; } @@ -101,7 +95,7 @@ public class RemoteHttpProviderLogAspect { private Class resolveRemoteInterface(Class targetClass, Method method) { for (Class interfaceType : targetClass.getInterfaces()) { - if (interfaceType.isAnnotationPresent(FeignClient.class) + if (interfaceType.isAnnotationPresent(RemoteHttpService.class) && org.springframework.util.ReflectionUtils.findMethod(interfaceType, method.getName(), method.getParameterTypes()) != null) { return interfaceType; } @@ -109,14 +103,14 @@ public class RemoteHttpProviderLogAspect { return null; } - private RequestMapping resolveTypeMapping(Class remoteInterface) { + private HttpExchange resolveTypeExchange(Class remoteInterface) { if (remoteInterface == null) { return null; } - return AnnotatedElementUtils.findMergedAnnotation(remoteInterface, RequestMapping.class); + return AnnotatedElementUtils.findMergedAnnotation(remoteInterface, HttpExchange.class); } - private RequestMapping resolveMethodMapping(Class remoteInterface, Method method) { + private HttpExchange resolveMethodExchange(Class remoteInterface, Method method) { if (remoteInterface == null) { return null; } @@ -124,18 +118,18 @@ public class RemoteHttpProviderLogAspect { if (interfaceMethod == null) { return null; } - return AnnotatedElementUtils.findMergedAnnotation(interfaceMethod, RequestMapping.class); + return AnnotatedElementUtils.findMergedAnnotation(interfaceMethod, HttpExchange.class); } - private String extractPath(RequestMapping mapping) { - if (mapping == null) { + private String extractPath(HttpExchange exchange) { + if (exchange == null) { return null; } - if (mapping.path().length > 0 && StringUtils.hasText(mapping.path()[0])) { - return mapping.path()[0]; + if (StringUtils.hasText(exchange.url())) { + return exchange.url(); } - if (mapping.value().length > 0 && StringUtils.hasText(mapping.value()[0])) { - return mapping.value()[0]; + if (StringUtils.hasText(exchange.value())) { + return exchange.value(); } return null; } diff --git a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/log/enums/RequestLogEnum.java b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/log/enums/RequestLogEnum.java new file mode 100644 index 000000000..b8d93b5d8 --- /dev/null +++ b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/log/enums/RequestLogEnum.java @@ -0,0 +1,28 @@ +package org.dromara.common.http.log.enums; + +import lombok.AllArgsConstructor; + +/** + * 请求日志级别. + * + * @author Lion Li + */ +@AllArgsConstructor +public enum RequestLogEnum { + + /** + * 基础信息. + */ + INFO, + + /** + * 参数信息. + */ + PARAM, + + /** + * 全量信息. + */ + FULL + +} diff --git a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/log/support/LoggingHttpExchangeAdapter.java b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/log/support/LoggingHttpExchangeAdapter.java new file mode 100644 index 000000000..87ed90360 --- /dev/null +++ b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/log/support/LoggingHttpExchangeAdapter.java @@ -0,0 +1,114 @@ +package org.dromara.common.http.log.support; + +import org.dromara.common.core.exception.ServiceException; +import org.jspecify.annotations.Nullable; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.util.StringUtils; +import org.springframework.web.service.invoker.HttpExchangeAdapter; +import org.springframework.web.service.invoker.HttpExchangeAdapterDecorator; +import org.springframework.web.service.invoker.HttpRequestValues; + +import java.net.URI; +import java.util.Map; + +/** + * 内部 HTTP Consumer 日志装饰器. + * + * Consumer 侧日志挂在 HttpServiceProxyFactory 的 exchange adapter 上, + * 这样可以直接拿到最终请求 method/path 和解码后的返回值, + * 比直接拦截底层流更稳定,也更容易规避 body 重复读问题。 + * + * @author Lion Li + */ +public class LoggingHttpExchangeAdapter extends HttpExchangeAdapterDecorator { + + private final RemoteHttpLogSupport logSupport; + + public LoggingHttpExchangeAdapter(HttpExchangeAdapter delegate, RemoteHttpLogSupport logSupport) { + super(delegate); + this.logSupport = logSupport; + } + + @Override + public void exchange(HttpRequestValues requestValues) { + invoke(requestValues, () -> { + super.exchange(requestValues); + return null; + }); + } + + @Override + public HttpHeaders exchangeForHeaders(HttpRequestValues requestValues) { + return invoke(requestValues, () -> super.exchangeForHeaders(requestValues)); + } + + @Override + public @Nullable T exchangeForBody(HttpRequestValues requestValues, ParameterizedTypeReference bodyType) { + return invoke(requestValues, () -> super.exchangeForBody(requestValues, bodyType)); + } + + @Override + public ResponseEntity exchangeForBodilessEntity(HttpRequestValues requestValues) { + return invoke(requestValues, () -> super.exchangeForBodilessEntity(requestValues)); + } + + @Override + public ResponseEntity exchangeForEntity(HttpRequestValues requestValues, ParameterizedTypeReference bodyType) { + return invoke(requestValues, () -> super.exchangeForEntity(requestValues, bodyType)); + } + + private T invoke(HttpRequestValues requestValues, ThrowingSupplier supplier) { + HttpMethod httpMethod = requestValues.getHttpMethod(); + String path = resolvePath(requestValues); + Object bodyValue = requestValues.getBodyValue(); + Object[] arguments = bodyValue == null ? new Object[0] : bodyValue instanceof Object[] array ? array : new Object[] {bodyValue}; + this.logSupport.logRequest(RemoteHttpLogSupport.CONSUMER, httpMethod, path, arguments); + long startTime = System.currentTimeMillis(); + try { + T result = supplier.get(); + this.logSupport.logResponse(RemoteHttpLogSupport.CONSUMER, httpMethod, path, + System.currentTimeMillis() - startTime, result); + return result; + } catch (Throwable ex) { + this.logSupport.logException(RemoteHttpLogSupport.CONSUMER, httpMethod, path, + System.currentTimeMillis() - startTime, ex); + switch (ex) { + case ServiceException serviceException -> throw serviceException; + case RuntimeException runtimeException -> throw runtimeException; + case Error error -> throw error; + default -> { + } + } + throw new IllegalStateException(ex); + } + } + + private String resolvePath(HttpRequestValues requestValues) { + URI uri = requestValues.getUri(); + if (uri != null) { + // 能拿到最终 URI 时优先打印最终请求地址,便于线上排查。 + return uri.toString(); + } + String uriTemplate = requestValues.getUriTemplate(); + if (!StringUtils.hasText(uriTemplate)) { + return null; + } + Map uriVariables = requestValues.getUriVariables(); + String path = uriTemplate; + if (uriVariables != null) { + for (Map.Entry entry : uriVariables.entrySet()) { + path = path.replace("{" + entry.getKey() + "}", String.valueOf(entry.getValue())); + } + } + return path; + } + + @FunctionalInterface + private interface ThrowingSupplier { + + T get() throws Throwable; + } +} diff --git a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/log/support/RemoteHttpFeignLogger.java b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/log/support/RemoteHttpFeignLogger.java deleted file mode 100644 index 08d9a0515..000000000 --- a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/log/support/RemoteHttpFeignLogger.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.dromara.common.http.log.support; - -import feign.Logger; -import feign.Request; -import feign.Response; -import feign.Util; -import org.springframework.http.HttpMethod; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -/** - * Feign 原生日志桥接。 - */ -public class RemoteHttpFeignLogger extends Logger { - - private final RemoteHttpLogSupport logSupport; - - public RemoteHttpFeignLogger(RemoteHttpLogSupport logSupport) { - this.logSupport = logSupport; - } - - @Override - protected void log(String configKey, String format, Object... args) { - } - - @Override - protected void logRequest(String configKey, Level logLevel, Request request) { - Object[] arguments = request.body() == null ? new Object[0] : new Object[] {request.body()}; - this.logSupport.logRequest(RemoteHttpLogSupport.CONSUMER, HttpMethod.valueOf(request.httpMethod().name()), request.url(), arguments); - } - - @Override - protected Response logAndRebufferResponse(String configKey, Level logLevel, Response response, long elapsedTime) - throws IOException { - byte[] bodyData = response.body() == null ? null : Util.toByteArray(response.body().asInputStream()); - Object responseBody = bodyData == null ? null : new String(bodyData, StandardCharsets.UTF_8); - HttpMethod httpMethod = response.request() == null ? null : HttpMethod.valueOf(response.request().httpMethod().name()); - String path = response.request() == null ? null : response.request().url(); - this.logSupport.logResponse(RemoteHttpLogSupport.CONSUMER, httpMethod, path, elapsedTime, responseBody); - if (bodyData == null) { - return response; - } - return response.toBuilder().body(bodyData).build(); - } - - @Override - protected IOException logIOException(String configKey, Level logLevel, IOException ioe, long elapsedTime) { - this.logSupport.logException(RemoteHttpLogSupport.CONSUMER, null, configKey, elapsedTime, ioe); - return ioe; - } -} diff --git a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/log/support/RemoteHttpLogSupport.java b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/log/support/RemoteHttpLogSupport.java index 7e690b47a..e9cdd7a4f 100644 --- a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/log/support/RemoteHttpLogSupport.java +++ b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/log/support/RemoteHttpLogSupport.java @@ -1,9 +1,19 @@ package org.dromara.common.http.log.support; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.dromara.common.http.log.enums.RequestLogEnum; +import org.dromara.common.http.properties.RemoteHttpProperties; +import org.dromara.common.json.utils.JsonUtils; import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + /** * 内部 HTTP 日志支持. * @@ -14,22 +24,50 @@ import org.springframework.util.StringUtils; * @author Lion Li */ @Slf4j +@RequiredArgsConstructor public class RemoteHttpLogSupport { public static final String CONSUMER = "CONSUMER"; public static final String PROVIDER = "PROVIDER"; + private final RemoteHttpProperties properties; + + public boolean isEnabled() { + return Boolean.TRUE.equals(properties.getRequestLog()); + } + + public boolean isFullLogEnabled() { + return properties.getLogLevel() == RequestLogEnum.FULL; + } + public void logRequest(String client, HttpMethod httpMethod, String path, Object[] arguments) { + if (!isEnabled()) { + return; + } String baseLog = buildBaseLog(client, httpMethod, path); - log.info("HTTP - 服务调用: {}", baseLog); + if (properties.getLogLevel() == RequestLogEnum.INFO) { + log.info("HTTP - 服务调用: {}", baseLog); + return; + } + log.info("HTTP - 服务调用: {},Parameter={}", baseLog, formatArguments(arguments)); } public void logResponse(String client, HttpMethod httpMethod, String path, long elapsed, Object response) { + if (!isEnabled()) { + return; + } String baseLog = buildBaseLog(client, httpMethod, path); + if (properties.getLogLevel() == RequestLogEnum.FULL) { + log.info("HTTP - 服务响应: {},SpendTime=[{}ms],Response={}", baseLog, elapsed, formatValue(unwrapResponse(response))); + return; + } log.info("HTTP - 服务响应: {},SpendTime=[{}ms]", baseLog, elapsed); } public void logException(String client, HttpMethod httpMethod, String path, long elapsed, Throwable throwable) { + if (!isEnabled()) { + return; + } String baseLog = buildBaseLog(client, httpMethod, path); log.error("HTTP - 服务异常: {},SpendTime=[{}ms],Exception={}", baseLog, elapsed, throwable.getMessage(), throwable); } @@ -44,4 +82,51 @@ public class RemoteHttpLogSupport { ']'; } + private String formatArguments(Object[] arguments) { + return formatValue(arguments == null ? new Object[0] : arguments); + } + + private Object unwrapResponse(Object response) { + if (response instanceof ResponseEntity responseEntity) { + return responseEntity.getBody(); + } + return response; + } + + private String formatValue(Object value) { + try { + return JsonUtils.toJsonString(sanitizeValue(value)); + } catch (RuntimeException ignored) { + return String.valueOf(value); + } + } + + private Object sanitizeValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof byte[] bytes) { + // 文件上传这类场景只记录长度,避免二进制内容直接进日志。 + return "byte[" + bytes.length + "]"; + } + if (value instanceof Object[] array) { + Object[] sanitized = new Object[array.length]; + for (int i = 0; i < array.length; i++) { + sanitized[i] = sanitizeValue(array[i]); + } + return sanitized; + } + if (value instanceof Collection collection) { + return collection.stream().map(this::sanitizeValue).toList(); + } + if (value instanceof Map map) { + Map sanitized = new LinkedHashMap<>(map.size()); + map.forEach((key, item) -> sanitized.put(key, sanitizeValue(item))); + return sanitized; + } + if (ObjectUtils.isArray(value)) { + return ObjectUtils.nullSafeToString(value); + } + return value; + } } diff --git a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/properties/RemoteHttpProperties.java b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/properties/RemoteHttpProperties.java new file mode 100644 index 000000000..d40be4719 --- /dev/null +++ b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/properties/RemoteHttpProperties.java @@ -0,0 +1,26 @@ +package org.dromara.common.http.properties; + +import lombok.Data; +import org.dromara.common.http.log.enums.RequestLogEnum; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * 内部 HTTP 调用配置. + * + * @author Lion Li + */ +@Data +@ConfigurationProperties(prefix = "remote.http") +public class RemoteHttpProperties { + + /** + * 是否开启请求日志. + */ + private Boolean requestLog = Boolean.FALSE; + + /** + * 日志级别. + */ + private RequestLogEnum logLevel = RequestLogEnum.INFO; + +} diff --git a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/registrar/RemoteHttpServiceRegistrar.java b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/registrar/RemoteHttpServiceRegistrar.java new file mode 100644 index 000000000..ff4c077c7 --- /dev/null +++ b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/registrar/RemoteHttpServiceRegistrar.java @@ -0,0 +1,217 @@ +package org.dromara.common.http.registrar; + +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.core.annotation.RemoteHttpService; +import org.dromara.common.http.annotation.RemoteServiceController; +import org.springframework.beans.factory.BeanClassLoaderAware; +import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.context.EnvironmentAware; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.core.type.filter.AnnotationTypeFilter; +import org.springframework.core.env.Environment; +import org.springframework.context.ResourceLoaderAware; +import org.springframework.core.io.ResourceLoader; +import org.springframework.util.AntPathMatcher; +import org.springframework.util.ClassUtils; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.boot.context.properties.bind.Binder; +import org.springframework.web.service.annotation.HttpExchange; +import org.springframework.web.service.registry.AbstractHttpServiceRegistrar; + +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * 按接口声明自动注册远程 HTTP Service. + * + * 这个注册器负责把“接口声明”转成 Spring HTTP Service Client 代理, + * 同时保留一个和 Dubbo 类似的优化: + * 当前服务自己就提供了该接口实现时,不再注册远程代理,直接走本地 Bean。 + * + * @author Lion Li + */ +public class RemoteHttpServiceRegistrar extends AbstractHttpServiceRegistrar + implements EnvironmentAware, ResourceLoaderAware, BeanClassLoaderAware { + + private Environment environment; + private ResourceLoader resourceLoader; + private ClassLoader beanClassLoader; + private static final String SCAN_PACKAGES_PROPERTY = "remote.http.scan-packages"; + private static final AntPathMatcher PACKAGE_MATCHER = new AntPathMatcher("."); + + @Override + public void setEnvironment(Environment environment) { + super.setEnvironment(environment); + this.environment = environment; + } + + @Override + public void setResourceLoader(ResourceLoader resourceLoader) { + super.setResourceLoader(resourceLoader); + this.resourceLoader = resourceLoader; + } + + @Override + public void setBeanClassLoader(ClassLoader beanClassLoader) { + super.setBeanClassLoader(beanClassLoader); + this.beanClassLoader = beanClassLoader; + } + + @Override + protected void registerHttpServices(GroupRegistry registry, AnnotationMetadata importingClassMetadata) { + Set scanPackagePatterns = new LinkedHashSet<>(resolveConfiguredScanPackages()); + if (scanPackagePatterns.isEmpty()) { + return; + } + Set scanBasePackages = resolveScanBasePackages(scanPackagePatterns); + if (scanBasePackages.isEmpty()) { + return; + } + // 先找出当前服务自己已经提供的远程接口,后面这些接口不再注册 HTTP client。 + Set localServiceTypes = resolveLocalServiceTypes(scanBasePackages, scanPackagePatterns); + MultiValueMap groupedServices = resolveRemoteHttpServices(scanBasePackages, scanPackagePatterns, localServiceTypes); + groupedServices.forEach((serviceId, classNames) -> + registry.forGroup(serviceId).registerTypeNames(classNames.toArray(String[]::new))); + } + + private MultiValueMap resolveRemoteHttpServices(Set basePackages, Set scanPackagePatterns, + Set localServiceTypes) { + MultiValueMap groupedServices = new LinkedMultiValueMap<>(); + for (AnnotatedBeanDefinition beanDefinition : scanCandidateComponents(basePackages, RemoteHttpService.class)) { + AnnotationMetadata metadata = beanDefinition.getMetadata(); + if (!metadata.isInterface() || !hasHttpExchange(metadata)) { + continue; + } + String serviceTypeName = metadata.getClassName(); + if (!matchesConfiguredPackage(serviceTypeName, scanPackagePatterns)) { + continue; + } + // 同服务场景直接依赖本地 provider,不再生成 HTTP 代理。 + if (localServiceTypes.contains(serviceTypeName)) { + continue; + } + groupedServices.add(resolveServiceId(metadata), serviceTypeName); + } + return groupedServices; + } + + private Set resolveLocalServiceTypes(Set basePackages, Set scanPackagePatterns) { + MultiValueMap localServiceTypes = new LinkedMultiValueMap<>(); + for (AnnotatedBeanDefinition beanDefinition : scanCandidateComponents(basePackages, RemoteServiceController.class)) { + String className = beanDefinition.getMetadata().getClassName(); + Class beanClass = ClassUtils.resolveClassName(className, this.beanClassLoader); + for (Class interfaceType : ClassUtils.getAllInterfacesForClass(beanClass, this.beanClassLoader)) { + if (interfaceType.isAnnotationPresent(RemoteHttpService.class) + && matchesConfiguredPackage(interfaceType.getName(), scanPackagePatterns)) { + localServiceTypes.add(interfaceType.getName(), className); + } + } + } + // 同一个远程接口只允许一个本地 provider,否则本地短路目标不明确。 + localServiceTypes.forEach((serviceTypeName, providerClassNames) -> { + if (providerClassNames.size() > 1) { + throw new IllegalStateException("Multiple local RemoteServiceController beans found for " + + serviceTypeName + ": " + providerClassNames); + } + }); + return new LinkedHashSet<>(localServiceTypes.keySet()); + } + + private List scanCandidateComponents(Set basePackages, + Class annotationType) { + ClassPathScanningCandidateComponentProvider scanner = createScanner(annotationType); + List beanDefinitions = new ArrayList<>(); + for (String basePackage : basePackages) { + for (BeanDefinition beanDefinition : scanner.findCandidateComponents(basePackage)) { + if (beanDefinition instanceof AnnotatedBeanDefinition annotatedBeanDefinition) { + beanDefinitions.add(annotatedBeanDefinition); + } + } + } + return beanDefinitions; + } + + private ClassPathScanningCandidateComponentProvider createScanner(Class annotationType) { + ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false) { + @Override + protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { + return beanDefinition.getMetadata().isIndependent(); + } + }; + scanner.addIncludeFilter(new AnnotationTypeFilter(annotationType)); + if (this.environment != null) { + scanner.setEnvironment(this.environment); + } + if (this.resourceLoader != null) { + scanner.setResourceLoader(this.resourceLoader); + } + return scanner; + } + + private String resolveServiceId(AnnotationMetadata metadata) { + Map attributes = metadata.getAnnotationAttributes(RemoteHttpService.class.getName()); + String serviceId = attributes != null ? String.valueOf(attributes.get("serviceId")) : StringUtils.EMPTY; + if (StringUtils.isBlank(serviceId)) { + throw new IllegalStateException("RemoteHttpService serviceId must not be blank: " + metadata.getClassName()); + } + return serviceId; + } + + private boolean hasHttpExchange(AnnotationMetadata metadata) { + return metadata.isAnnotated(HttpExchange.class.getName()) || metadata.hasAnnotatedMethods(HttpExchange.class.getName()); + } + + private List resolveConfiguredScanPackages() { + if (this.environment == null) { + return Collections.emptyList(); + } + return Binder.get(this.environment).bind(SCAN_PACKAGES_PROPERTY, org.springframework.boot.context.properties.bind.Bindable.listOf(String.class)) + .orElseGet(Collections::emptyList) + .stream() + .filter(StringUtils::isNotBlank) + .distinct() + .toList(); + } + + private Set resolveScanBasePackages(Set scanPackagePatterns) { + Set basePackages = new LinkedHashSet<>(); + for (String packagePattern : scanPackagePatterns) { + String basePackage = resolveScanBasePackage(packagePattern); + if (StringUtils.isNotBlank(basePackage)) { + basePackages.add(basePackage); + } + } + return basePackages; + } + + private String resolveScanBasePackage(String packagePattern) { + int wildcardIndex = packagePattern.indexOf('*'); + if (wildcardIndex < 0) { + return packagePattern; + } + String packagePrefix = packagePattern.substring(0, wildcardIndex); + packagePrefix = StringUtils.substringBeforeLast(packagePrefix, "."); + return StringUtils.defaultString(packagePrefix); + } + + private boolean matchesConfiguredPackage(String className, Set scanPackagePatterns) { + if (scanPackagePatterns.isEmpty()) { + return true; + } + String packageName = ClassUtils.getPackageName(className); + for (String packagePattern : scanPackagePatterns) { + if (PACKAGE_MATCHER.match(packagePattern, packageName)) { + return true; + } + } + return false; + } +} diff --git a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/support/RemoteHttpDataPermissionCodec.java b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/support/RemoteHttpDataPermissionCodec.java deleted file mode 100644 index a368bf7f2..000000000 --- a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/support/RemoteHttpDataPermissionCodec.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.dromara.common.http.support; - -import org.apache.fory.Fory; -import org.apache.fory.ThreadSafeFory; -import org.apache.fory.config.Language; -import org.dromara.common.core.exception.ServiceException; - -import java.util.Base64; -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * 数据权限上下文编解码器. - * - * 通过 Fory + Base64 把上下文压缩成单个 HTTP Header,避免手工维护复杂类型转换。 - */ -public class RemoteHttpDataPermissionCodec { - - public static final String HEADER_NAME = "X-Remote-Data-Permission"; - - private static final int MAX_HEADER_LENGTH = 6 * 1024; - - private static final ThreadSafeFory FORY = Fory.builder() - .withLanguage(Language.JAVA) - .withRefTracking(true) - .withStringCompressed(true) - .withNumberCompressed(true) - .requireClassRegistration(false) - .buildThreadSafeFory(); - - public String encode(Map context) { - if (context == null || context.isEmpty()) { - return null; - } - try { - byte[] bytes = FORY.serialize(context); - String headerValue = Base64.getEncoder().encodeToString(bytes); - if (headerValue.length() > MAX_HEADER_LENGTH) { - throw new ServiceException("数据权限上下文过大,无法透传"); - } - return headerValue; - } catch (ServiceException e) { - throw e; - } catch (Exception e) { - throw new ServiceException("数据权限上下文序列化失败"); - } - } - - @SuppressWarnings("unchecked") - public Map decode(String headerValue) { - if (headerValue == null || headerValue.isBlank()) { - return Map.of(); - } - try { - byte[] bytes = Base64.getDecoder().decode(headerValue); - Object value = FORY.deserialize(bytes); - if (value instanceof Map map) { - return new LinkedHashMap<>((Map) map); - } - } catch (Exception e) { - throw new ServiceException("数据权限上下文反序列化失败"); - } - throw new ServiceException("数据权限上下文格式非法"); - } -} diff --git a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/support/RemoteHttpDataPermissionInterceptor.java b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/support/RemoteHttpDataPermissionInterceptor.java deleted file mode 100644 index 10857424f..000000000 --- a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/support/RemoteHttpDataPermissionInterceptor.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.dromara.common.http.support; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.dromara.common.core.utils.StringUtils; -import org.springframework.web.servlet.AsyncHandlerInterceptor; - -import java.util.Map; - -/** - * provider 侧恢复数据权限上下文,并在请求结束后清理,避免线程复用污染。 - */ -public class RemoteHttpDataPermissionInterceptor implements AsyncHandlerInterceptor { - - private static final String CONTEXT_ATTRIBUTE = RemoteHttpDataPermissionInterceptor.class.getName() + ".context"; - - private final RemoteHttpDataPermissionCodec codec; - - public RemoteHttpDataPermissionInterceptor(RemoteHttpDataPermissionCodec codec) { - this.codec = codec; - } - - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { - String headerValue = request.getHeader(RemoteHttpDataPermissionCodec.HEADER_NAME); - if (StringUtils.isBlank(headerValue)) { - return true; - } - request.setAttribute(CONTEXT_ATTRIBUTE, RemoteHttpDataPermissionSupport.snapshotContext()); - RemoteHttpDataPermissionSupport.replaceContext(this.codec.decode(headerValue)); - return true; - } - - @Override - public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) { - restoreContext(request); - } - - @Override - public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { - restoreContext(request); - } - - @SuppressWarnings("unchecked") - private void restoreContext(HttpServletRequest request) { - Object context = request.getAttribute(CONTEXT_ATTRIBUTE); - if (!(context instanceof Map previousContext)) { - return; - } - RemoteHttpDataPermissionSupport.replaceContext((Map) previousContext); - request.removeAttribute(CONTEXT_ATTRIBUTE); - } -} diff --git a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/support/RemoteHttpDataPermissionRequestInterceptor.java b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/support/RemoteHttpDataPermissionRequestInterceptor.java deleted file mode 100644 index 637835845..000000000 --- a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/support/RemoteHttpDataPermissionRequestInterceptor.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.dromara.common.http.support; - -import feign.RequestInterceptor; -import feign.RequestTemplate; - -/** - * consumer 侧数据权限透传拦截器。 - */ -public class RemoteHttpDataPermissionRequestInterceptor implements RequestInterceptor { - - private final RemoteHttpDataPermissionCodec codec; - - public RemoteHttpDataPermissionRequestInterceptor(RemoteHttpDataPermissionCodec codec) { - this.codec = codec; - } - - @Override - public void apply(RequestTemplate requestTemplate) { - if (!RemoteHttpDataPermissionSupport.hasContext()) { - return; - } - String headerValue = this.codec.encode(RemoteHttpDataPermissionSupport.snapshotContext()); - if (headerValue != null) { - requestTemplate.header(RemoteHttpDataPermissionCodec.HEADER_NAME, headerValue); - } - } -} diff --git a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/support/RemoteHttpDataPermissionSupport.java b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/support/RemoteHttpDataPermissionSupport.java deleted file mode 100644 index 344bfa623..000000000 --- a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/support/RemoteHttpDataPermissionSupport.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.dromara.common.http.support; - -import org.dromara.common.mybatis.helper.DataPermissionHelper; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * 数据权限上下文访问工具。 - */ -public final class RemoteHttpDataPermissionSupport { - - private RemoteHttpDataPermissionSupport() { - } - - public static boolean hasContext() { - return !DataPermissionHelper.getContext().isEmpty(); - } - - public static Map snapshotContext() { - return new LinkedHashMap<>(DataPermissionHelper.getContext()); - } - - public static void replaceContext(Map context) { - Map currentContext = DataPermissionHelper.getContext(); - currentContext.clear(); - if (context != null && !context.isEmpty()) { - currentContext.putAll(context); - } - } -} diff --git a/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/support/RemoteHttpFallbackProxyPostProcessor.java b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/support/RemoteHttpFallbackProxyPostProcessor.java new file mode 100644 index 000000000..50e4166a3 --- /dev/null +++ b/ruoyi-common/ruoyi-common-http/src/main/java/org/dromara/common/http/support/RemoteHttpFallbackProxyPostProcessor.java @@ -0,0 +1,165 @@ +package org.dromara.common.http.support; + +import org.aopalliance.intercept.MethodInterceptor; +import org.dromara.common.core.annotation.RemoteHttpService; +import org.springframework.aop.framework.ProxyFactory; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanClassLoaderAware; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.util.ClassUtils; +import org.springframework.util.ReflectionUtils; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.UndeclaredThrowableException; + +/** + * 远程 HTTP 代理 fallback 包装器. + * + *

仅包装注册器生成的远程 HTTP 代理 Bean。代理调用报错时, + * 按接口上声明的 fallback 实现兜底,不处理本地 provider Bean。 + * + *

这里故意保持和之前 mock/stub 类似的简单约束: + * fallback 必须实现接口本身,且方法签名与接口保持一致。

+ * + * @author Lion Li + */ +public class RemoteHttpFallbackProxyPostProcessor + implements BeanPostProcessor, BeanFactoryAware, BeanClassLoaderAware { + + private static final String HTTP_SERVICE_GROUP_NAME_ATTRIBUTE = "httpServiceGroupName"; + private static final String FALLBACK_WRAPPED_ATTRIBUTE = "remoteHttpFallbackWrapped"; + + private ConfigurableListableBeanFactory beanFactory; + private ClassLoader beanClassLoader; + + @Override + public void setBeanFactory(org.springframework.beans.factory.BeanFactory beanFactory) throws BeansException { + this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; + } + + @Override + public void setBeanClassLoader(ClassLoader classLoader) { + this.beanClassLoader = classLoader; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) { + if (bean instanceof FallbackDecoratedProxy) { + return bean; + } + Class serviceInterface = resolveRemoteServiceInterface(beanName, bean); + if (serviceInterface == null) { + return bean; + } + RemoteHttpService remoteHttpService = serviceInterface.getAnnotation(RemoteHttpService.class); + if (remoteHttpService == null || remoteHttpService.fallback() == void.class) { + return bean; + } + Class fallbackClass = remoteHttpService.fallback(); + if (!serviceInterface.isAssignableFrom(fallbackClass)) { + throw new IllegalStateException("Fallback class must implement remote service interface: " + + fallbackClass.getName() + " -> " + serviceInterface.getName()); + } + ProxyFactory proxyFactory = new ProxyFactory(bean); + proxyFactory.setInterfaces(ClassUtils.getAllInterfacesForClass(bean.getClass(), this.beanClassLoader)); + proxyFactory.addInterface(FallbackDecoratedProxy.class); + proxyFactory.addAdvice((MethodInterceptor) invocation -> { + Method method = invocation.getMethod(); + if (method.getDeclaringClass() == Object.class) { + return invocation.proceed(); + } + try { + return invocation.proceed(); + } catch (Throwable ex) { + return invokeFallback(serviceInterface, fallbackClass, method, invocation.getArguments(), ex); + } + }); + markWrapped(beanName); + return proxyFactory.getProxy(this.beanClassLoader); + } + + private Class resolveRemoteServiceInterface(String beanName, Object bean) { + if (this.beanFactory == null || !this.beanFactory.containsBeanDefinition(beanName)) { + return null; + } + BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition(beanName); + if (beanDefinition.getAttribute(HTTP_SERVICE_GROUP_NAME_ATTRIBUTE) == null) { + return null; + } + if (Boolean.TRUE.equals(beanDefinition.getAttribute(FALLBACK_WRAPPED_ATTRIBUTE))) { + return null; + } + Class beanClass = resolveBeanClass(beanDefinition); + if (beanClass != null && beanClass.isInterface() && beanClass.isAnnotationPresent(RemoteHttpService.class)) { + return beanClass; + } + for (Class interfaceType : ClassUtils.getAllInterfacesForClass(bean.getClass(), this.beanClassLoader)) { + if (interfaceType.isAnnotationPresent(RemoteHttpService.class)) { + return interfaceType; + } + } + return null; + } + + private Class resolveBeanClass(BeanDefinition beanDefinition) { + String beanClassName = beanDefinition.getBeanClassName(); + return beanClassName == null ? null : ClassUtils.resolveClassName(beanClassName, this.beanClassLoader); + } + + private Object invokeFallback(Class serviceInterface, Class fallbackClass, Method method, Object[] args, Throwable ex) + throws Throwable { + Object fallbackInstance = instantiateFallback(fallbackClass); + Method fallbackMethod = ReflectionUtils.findMethod(fallbackClass, method.getName(), method.getParameterTypes()); + if (fallbackMethod == null) { + throw unwrap(ex); + } + ReflectionUtils.makeAccessible(fallbackMethod); + return invokeMethod(fallbackInstance, fallbackMethod, args); + } + + private Object instantiateFallback(Class fallbackClass) { + if (this.beanFactory == null) { + throw new IllegalStateException("BeanFactory not initialized for remote fallback: " + fallbackClass.getName()); + } + return this.beanFactory.getBean(fallbackClass); + } + + private void markWrapped(String beanName) { + if (this.beanFactory == null || !this.beanFactory.containsBeanDefinition(beanName)) { + return; + } + this.beanFactory.getBeanDefinition(beanName).setAttribute(FALLBACK_WRAPPED_ATTRIBUTE, true); + } + + private Object invokeMethod(Object target, Method method, Object[] args) throws Throwable { + try { + return method.invoke(target, args); + } catch (InvocationTargetException ex) { + throw unwrap(ex.getTargetException()); + } catch (IllegalAccessException ex) { + throw new IllegalStateException("Could not invoke remote fallback method: " + method, ex); + } catch (UndeclaredThrowableException ex) { + throw unwrap(ex); + } catch (RuntimeException ex) { + throw unwrap(ex); + } + } + + private Throwable unwrap(Throwable throwable) { + Throwable current = throwable; + while (current instanceof InvocationTargetException invocationTargetException && invocationTargetException.getTargetException() != null) { + current = invocationTargetException.getTargetException(); + } + while (current instanceof UndeclaredThrowableException undeclaredThrowableException && undeclaredThrowableException.getUndeclaredThrowable() != null) { + current = undeclaredThrowableException.getUndeclaredThrowable(); + } + return current; + } + + private interface FallbackDecoratedProxy { + } +} diff --git a/ruoyi-common/ruoyi-common-http/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-http/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index e7cd7b28b..9b53874f5 100644 --- a/ruoyi-common/ruoyi-common-http/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/ruoyi-common/ruoyi-common-http/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,2 +1 @@ org.dromara.common.http.config.RemoteHttpAutoConfiguration -org.dromara.common.http.config.RemoteHttpDataPermissionAutoConfiguration diff --git a/ruoyi-common/ruoyi-common-redis/pom.xml b/ruoyi-common/ruoyi-common-redis/pom.xml index 5f31a1fe9..f8a5a477f 100644 --- a/ruoyi-common/ruoyi-common-redis/pom.xml +++ b/ruoyi-common/ruoyi-common-redis/pom.xml @@ -68,6 +68,7 @@ org.apache.fory fory-core + 0.13.1 diff --git a/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/remote/RemoteFileServiceImpl.java b/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/remote/RemoteFileServiceImpl.java index 8aad09b6e..6fb2f0e78 100644 --- a/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/remote/RemoteFileServiceImpl.java +++ b/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/remote/RemoteFileServiceImpl.java @@ -28,7 +28,7 @@ import java.util.List; */ @Slf4j @RequiredArgsConstructor -@RemoteServiceController(path = "/remote/file") +@RemoteServiceController public class RemoteFileServiceImpl implements RemoteFileService { private final ISysOssService sysOssService; diff --git a/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/remote/RemoteMailServiceImpl.java b/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/remote/RemoteMailServiceImpl.java index 7aa6c4621..1e3d094a9 100644 --- a/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/remote/RemoteMailServiceImpl.java +++ b/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/remote/RemoteMailServiceImpl.java @@ -14,7 +14,7 @@ import org.dromara.resource.api.RemoteMailService; */ @Slf4j @RequiredArgsConstructor -@RemoteServiceController(path = "/remote/mail") +@RemoteServiceController public class RemoteMailServiceImpl implements RemoteMailService { /** diff --git a/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/remote/RemoteMessageServiceImpl.java b/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/remote/RemoteMessageServiceImpl.java index 1a1118745..45b912f51 100644 --- a/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/remote/RemoteMessageServiceImpl.java +++ b/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/remote/RemoteMessageServiceImpl.java @@ -16,7 +16,7 @@ import java.util.List; */ @Slf4j @RequiredArgsConstructor -@RemoteServiceController(path = "/remote/message") +@RemoteServiceController public class RemoteMessageServiceImpl implements RemoteMessageService { /** diff --git a/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/remote/RemoteSmsServiceImpl.java b/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/remote/RemoteSmsServiceImpl.java index 364de5507..edcc164a5 100644 --- a/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/remote/RemoteSmsServiceImpl.java +++ b/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/remote/RemoteSmsServiceImpl.java @@ -21,7 +21,7 @@ import java.util.List; */ @Slf4j @RequiredArgsConstructor -@RemoteServiceController(path = "/inner/remote/resource/sms") +@RemoteServiceController public class RemoteSmsServiceImpl implements RemoteSmsService { /** diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteClientServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteClientServiceImpl.java index 292f4314e..431df6898 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteClientServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteClientServiceImpl.java @@ -14,7 +14,7 @@ import org.dromara.system.service.ISysClientService; * @author Michelle.Chung */ @RequiredArgsConstructor -@RemoteServiceController(path = "/remote/client") +@RemoteServiceController public class RemoteClientServiceImpl implements RemoteClientService { private final ISysClientService sysClientService; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteConfigServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteConfigServiceImpl.java index d7c6cf732..6ad2c7987 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteConfigServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteConfigServiceImpl.java @@ -15,7 +15,7 @@ import java.util.List; * @author Michelle.Chung */ @RequiredArgsConstructor -@RemoteServiceController(path = "/remote/config") +@RemoteServiceController public class RemoteConfigServiceImpl implements RemoteConfigService { private final ISysConfigService configService; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteDataScopeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteDataScopeServiceImpl.java index 503a56d0e..695d1ebf1 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteDataScopeServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteDataScopeServiceImpl.java @@ -25,7 +25,7 @@ import java.util.List; * @author Lion Li */ @RequiredArgsConstructor -@RemoteServiceController(path = "/remote/data-scope") +@RemoteServiceController public class RemoteDataScopeServiceImpl implements RemoteDataScopeService { private final SysRoleDeptMapper roleDeptMapper; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteDeptServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteDeptServiceImpl.java index 8c025f69d..ca7b9a0c9 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteDeptServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteDeptServiceImpl.java @@ -25,7 +25,7 @@ import java.util.Map; * @author Lion Li */ @RequiredArgsConstructor -@RemoteServiceController(path = "/remote/dept") +@RemoteServiceController public class RemoteDeptServiceImpl implements RemoteDeptService { private final ISysDeptService deptService; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteDictServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteDictServiceImpl.java index 220dcb805..2bf860364 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteDictServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteDictServiceImpl.java @@ -18,7 +18,7 @@ import java.util.List; * @author Lion Li */ @RequiredArgsConstructor -@RemoteServiceController(path = "/remote/dict") +@RemoteServiceController public class RemoteDictServiceImpl implements RemoteDictService { private final ISysDictTypeService sysDictTypeService; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteLogServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteLogServiceImpl.java index fe340bae6..eef9f3156 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteLogServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteLogServiceImpl.java @@ -19,7 +19,7 @@ import org.springframework.web.bind.annotation.PostMapping; * @author Lion Li */ @RequiredArgsConstructor -@RemoteServiceController(path = "/remote/log") +@RemoteServiceController public class RemoteLogServiceImpl implements RemoteLogService { private final ISysOperLogService operLogService; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemotePermissionServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemotePermissionServiceImpl.java index 2f2cacd43..0b64607e9 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemotePermissionServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemotePermissionServiceImpl.java @@ -13,7 +13,7 @@ import java.util.Set; * @author Lion Li */ @RequiredArgsConstructor -@RemoteServiceController(path = "/remote/permission") +@RemoteServiceController public class RemotePermissionServiceImpl implements RemotePermissionService { private final ISysPermissionService permissionService; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemotePostServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemotePostServiceImpl.java index df19215f8..5e64b1ccc 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemotePostServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemotePostServiceImpl.java @@ -20,7 +20,7 @@ import java.util.Map; * @author Lion Li */ @RequiredArgsConstructor -@RemoteServiceController(path = "/remote/post") +@RemoteServiceController public class RemotePostServiceImpl implements RemotePostService { private final SysPostMapper postMapper; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteRoleServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteRoleServiceImpl.java index bbeeb01ac..6875df660 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteRoleServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteRoleServiceImpl.java @@ -20,7 +20,7 @@ import java.util.Map; * @author Lion Li */ @RequiredArgsConstructor -@RemoteServiceController(path = "/remote/role") +@RemoteServiceController public class RemoteRoleServiceImpl implements RemoteRoleService { private final SysRoleMapper roleMapper; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteSocialServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteSocialServiceImpl.java index 2cb5501d2..95d3c9210 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteSocialServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteSocialServiceImpl.java @@ -18,7 +18,7 @@ import java.util.List; * @author Michelle.Chung */ @RequiredArgsConstructor -@RemoteServiceController(path = "/remote/social") +@RemoteServiceController public class RemoteSocialServiceImpl implements RemoteSocialService { private final ISysSocialService sysSocialService; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteTaskAssigneeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteTaskAssigneeServiceImpl.java index dcf3edf3d..9cdcb2533 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteTaskAssigneeServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteTaskAssigneeServiceImpl.java @@ -31,7 +31,7 @@ import java.util.Map; * @author Lion Li */ @RequiredArgsConstructor -@RemoteServiceController(path = "/remote/task-assignee") +@RemoteServiceController public class RemoteTaskAssigneeServiceImpl implements RemoteTaskAssigneeService { // 上级Service注入下级Service 其他Service永远不可能注入当前类 避免循环注入 diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteUserServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteUserServiceImpl.java index d1f7a48cf..168e87514 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteUserServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/remote/RemoteUserServiceImpl.java @@ -41,7 +41,7 @@ import java.util.*; * @author Lion Li */ @RequiredArgsConstructor -@RemoteServiceController(path = "/remote/user") +@RemoteServiceController public class RemoteUserServiceImpl implements RemoteUserService { private final ISysUserService userService; diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/remote/RemoteWorkflowServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/remote/RemoteWorkflowServiceImpl.java index 82a569619..6daf1c7d5 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/remote/RemoteWorkflowServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/remote/RemoteWorkflowServiceImpl.java @@ -17,7 +17,7 @@ import java.util.Map; * @Author ZETA * @Date 2024/6/3 */ -@RemoteServiceController(path = "/remote/workflow") +@RemoteServiceController @RequiredArgsConstructor public class RemoteWorkflowServiceImpl implements RemoteWorkflowService { diff --git a/script/config/nacos/application-common.yml b/script/config/nacos/application-common.yml index 3e5b3939b..64e0c1e4a 100644 --- a/script/config/nacos/application-common.yml +++ b/script/config/nacos/application-common.yml @@ -9,10 +9,20 @@ server: # 最大线程数 max: 256 +remote: + http: + # 远程接口扫描范围,支持 Ant 风格包路径 + scan-packages: + - org.dromara.**.api + # 全局请求log + request-log: true + # info 基础信息 param 参数信息 full 全部 + log-level: info + spring: http: clients: - # Spring HTTP 客户端默认超时配置,供非 Feign 客户端复用 + # 默认 client HTTP 请求超时,供 RestClient / HTTP Service Client 复用 connect-timeout: 3s read-timeout: 10s imperative: @@ -56,9 +66,6 @@ spring: # 允许对象忽略json中不存在的属性 fail_on_unknown_properties: false cloud: - openfeign: - circuitbreaker: - enabled: true inetutils: # 指定全局使用ip网段 preferred-networks: