当前位置: 首页 > news >正文

OpenFeign返回参数统一处理

自定义解码器

package com.itheima.feign;import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itheima.exception.BusinessException;
import feign.Response;
import feign.Util;
import feign.codec.Decoder;
import org.springframework.core.ResolvableType;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Supplier;/*** @author 阿呆* @desciption:* @since 2023/4/23 23:09*/
public abstract class AbstractCustomDecoder <T> implements Decoder{protected final Class<T> targetClazz;protected Set<Class> clazzSet;protected ObjectMapper objectMapper;protected AbstractCustomDecoder(ObjectMapper objectMapper) {this.targetClazz = retrieveAnnotationType();this.objectMapper = objectMapper;this.clazzSet = new HashSet<>();this.clazzSet.add(this.targetClazz);this.fillTargetClazz(this.clazzSet);}protected abstract <D> Supplier<D> getData(T obj);protected abstract <C> Supplier<C> getCode(T obj);protected abstract <M> Supplier<M> getMes(T obj);protected abstract boolean isSuccess(T obj);protected abstract void fillTargetClazz(Set<Class> clazzSet);@Overridepublic Object decode(Response response, Type type) throws IOException {return customDecoder(response, type);}/*** 检索泛型对应的实际类型* @return*/private Class<T> retrieveAnnotationType(){Type type = getClass().getGenericSuperclass();if (type instanceof ParameterizedType) {ParameterizedType parameterizedType = (ParameterizedType) type;for (Type actualTypeArgument : parameterizedType.getActualTypeArguments()) {if (actualTypeArgument instanceof Class) {return (Class) actualTypeArgument;}}}return null;}protected Object customDecoder(Response response, Type type) throws IOException {String body = Util.toString(response.body().asReader(StandardCharsets.UTF_8));Class<?> clazz = ResolvableType.forType(type).getRawClass();if (this.clazzSet.contains(clazz)){return this.objectMapper.readValue(body,clazz);}try{return this.objectMapper.readValue(body,clazz);}catch (Exception e){JavaType paramterType = this.objectMapper.getTypeFactory().constructType(type);JavaType resultType = this.objectMapper.getTypeFactory().constructParametricType(this.targetClazz, paramterType);T data = (T)this.objectMapper.readValue(body,resultType);if (isSuccess(data)){return getData(data).get();}throw new BusinessException(Integer.valueOf(getCode(data).get().toString()),getMes(data).get().toString());}}}package com.itheima.feign;import com.fasterxml.jackson.databind.ObjectMapper;
import com.itheima.common.entry.FeignResponse;
import com.itheima.common.entry.Result;
import feign.codec.Decoder;
import feign.optionals.OptionalDecoder;
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.Set;
import java.util.function.Supplier;/*** @author 阿呆* @desciption: @Configuration 加入 该注解后 全局有效 , 替换 SpringDecoder 没有 局部引用也会生效* @since 2023/4/23 23:27*/public class CustomDecoderConfig extends AbstractCustomDecoder<FeignResponse> {protected CustomDecoderConfig(ObjectMapper objectMapper) {super(objectMapper);}@Overrideprotected Supplier getData(FeignResponse obj) {return obj::getData;}@Overrideprotected Supplier<String> getCode(FeignResponse obj) {return obj::getCode;}@Overrideprotected Supplier<String> getMes(FeignResponse obj) {return obj::getMsg;}@Overrideprotected boolean isSuccess(FeignResponse obj) {return obj.isSuccess();}@Overrideprotected void fillTargetClazz(Set<Class> clazzSet) {clazzSet.add(Result.class);}}package com.itheima.feign;import com.fasterxml.jackson.databind.ObjectMapper;
import com.itheima.common.entry.FeignResponse;
import com.itheima.common.entry.Result;
import feign.codec.Decoder;
import feign.optionals.OptionalDecoder;
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.Set;
import java.util.function.Supplier;/*** @author 阿呆* @desciption: @Configuration 加入 该注解后 全局有效 , 替换 SpringDecoder 没有 局部引用也会生效* @since 2023/4/23 23:27*/
@Configuration
public class FeignClientCustomDecoderConfig {@Beanpublic Decoder decoder(ObjectMapper objectMapper) {// 方法入口:feign.InvocationContext , 默认执行链: ResponseEntityDecoder、OptionalDecoder、SpringDecoderreturn new ResponseEntityDecoder(new OptionalDecoder(new CustomDecoderConfig(objectMapper)));}
}

局部、全价有效

全价有效,FeignClientCustomDecoderConfig需要配置@Configuration 进行标记,局部有效则去掉。没有配置的默认使用SpringDecoder 进行解码

package com.itheima.client;import com.itheima.common.entry.FeignResponse;
import com.itheima.common.entry.User;
import com.itheima.feign.FeignClientCustomDecoderConfig;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;/*** 局部有效,FeignClientCustomDecoderConfig 不要注入bean , 不然会替换掉默认的SpringDecode 解码器* value 服务名称   contextId  bean名称 */
@FeignClient(value = "nacos-client-feign", contextId = "nacosClientFeignWrapper", configuration = FeignClientCustomDecoderConfig.class)
public interface NacosClientFeignWrapper {@RequestMapping("/findWrapUsers")List<User> findWrapUsers(@RequestBody User user);@RequestMapping("/updateWrapperUser")User updateWrapperUser(@RequestBody User user);@RequestMapping("/findWrapUsers")FeignResponse<List<User>> findWrapUsers2(@RequestBody User user);@RequestMapping("/updateWrapperUser")FeignResponse<User> updateWrapperUser2(@RequestBody User user);@RequestMapping("/handlerError")FeignResponse<User> handlerError(@RequestBody User user);}

Feign接口编写,继承实现方式

package com.itheima.client;import com.itheima.common.entry.FeignResponse;
import com.itheima.common.entry.User;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;import java.util.List;# 共有类/*** @author 阿呆* @desciption:* @since 2024/10/26 20:26*/
public interface UserWebApi {@RequestMapping("/user/findWrapUsers")List<User> findWrapUsers(@RequestBody User user);@RequestMapping("/user/updateWrapperUser")User updateWrapperUser(@RequestBody User user);@RequestMapping("/user/findWrapUsers")FeignResponse<List<User>> findWrapUsers2(@RequestBody User user);@RequestMapping("/user/updateWrapperUser")FeignResponse<User> updateWrapperUser2(@RequestBody User user);@RequestMapping("/user/handlerError")FeignResponse<User> handlerError(@RequestBody User user);}# 调用方 实现接口package com.itheima.client;import com.itheima.feign.FeignClientCustomDecoderConfig;
import org.springframework.cloud.openfeign.FeignClient;/*** @author 阿呆* @desciption:* @since 2024/10/26 20:27*/
@FeignClient(value = "nacos-client-feign", contextId = "nacosClientFeignWrapper", configuration = FeignClientCustomDecoderConfig.class)
public interface UserFeignApi extends UserWebApi{}# 提供方服务器接口实现package com.itheima.client;import com.itheima.common.entry.FeignResponse;
import com.itheima.common.entry.User;
import org.springframework.web.bind.annotation.RestController;import java.util.List;/*** @author 阿呆* @desciption:* @since 2024/10/26 20:28*/
@RestController
public class UserController implements UserWebApi{@Overridepublic List<User> findWrapUsers(User user) {return null;}@Overridepublic User updateWrapperUser(User user) {return null;}@Overridepublic FeignResponse<List<User>> findWrapUsers2(User user) {return null;}@Overridepublic FeignResponse<User> updateWrapperUser2(User user) {return null;}@Overridepublic FeignResponse<User> handlerError(User user) {return null;}
}


http://www.mrgr.cn/news/59186.html

相关文章:

  • web 应用层接口请求日志
  • 【UE5】将2D切片图渲染为体积纹理,最终实现使用RT实时绘制体积纹理【第七篇-体积纹理绘制】
  • R语言编程
  • C# 的两个list怎么判断是否存在交集
  • SQL实战测试
  • Go语言基础教程:闭包
  • 网络通信与并发编程(六)线程、进程池与线程池
  • 安全见闻1-9---清风
  • 大模型,多模态大模型面试问题记录24/10/25
  • 每日OJ题_牛客_小红的ABC_暴力/找规律_C++_Java
  • 了解AIGC——自然语言处理与生成
  • 大学新生入门编程的推荐路径
  • 神经架构搜索:自动化设计神经网络的方法
  • 深入理解JAVA虚拟机(一)
  • 全面解读 @Transactional 的传播机制:一次搞懂 Spring 事务的各种“传播方式”!
  • 常用设计模式...
  • 【Vulnhub靶场】DC-4
  • 2024高等代数【南昌大学】
  • 用kali入侵 DarkHole_2测试
  • 小白直接冲!一区蛇群优化算法+双向深度学习+注意力机制!SO-BiTCN-BiGRU-Attention多输入单输出回归预测
  • 安全见闻-web安全
  • 【Vue 3】全面解析Composition API的实战技巧
  • Python 从入门到实战40(数据分析概述)
  • C# async-await循环依赖梳理
  • 第四期书生大模型实战营(【入门岛】- 第2关 | Python 基础知识 )
  • 【Linux】SQLite 数据库安装教程(Ubuntu 22.04)