Fegin 中统一处理调用的结果

背景

项目中,微服务环境下,有很多时候,都需要调用其他服务,而且其他服务基本上都有一个骨架类(如下图),为了不用每次调用都去判断是否成功,所以需要统一处理接口返回的结果 

 

思考

跟踪代码发现,Fegin中有个数据解析器(如下图),默认是使用SpringDecoder实现,我们需要自己封装该类,将逻辑替换

 思路

由此,就展开了,需要自定义解析器,并配置解析器生效的思考,如果这么的路走通了,就能统一处理数据了

骨架类 

package com.a.mybatis.common.response;

import java.io.Serializable;
import java.util.Objects;

public final class ResponseData<T> implements Serializable {
    private static final long serialVersionUID = 7824278330465676943L;
    public static final Integer ERROR = 0;
    public static final Integer SUCCESS = 1;
    private static final String ERROR_MSG = "服务器错误";
    private static final String SUCCESS_MSG = "success";
    private Integer code;
    private String msg;
    private T data;
}

自定义解析类 

package com.a.common.feign.config;

import com.a.mybatis.common.exception.CustomMessageException;
import com.a.mybatis.common.response.ResponseData;
import com.alibaba.fastjson2.JSON;
import feign.FeignException;
import feign.Response;
import feign.codec.Decoder;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import org.springframework.util.Assert;

import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;


public class MyDataDecoder implements Decoder {
    private final SpringDecoder decoder;

    public MyDataDecoder(SpringDecoder decoder) {
        this.decoder = decoder;
    }

    @Override
    public Object decode(Response response, Type type) throws IOException, FeignException {
        ResponseData<?> responseData = JSON.parseObject(response.body().asReader(StandardCharsets.UTF_8), ResponseData.class);
        Assert.notNull(responseData, "feign invoke failed");
        if (ResponseData.SUCCESS.equals(responseData.getCode())) {
            return responseData.getData();
        }
        throw new CustomMessageException("数据解析失败");
    }
}

 配置类

package com.a.common.feign.config;

import feign.codec.Decoder;
import feign.optionals.OptionalDecoder;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.support.HttpMessageConverterCustomizer;
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

 
@Configuration
public class FeignConfig {

    /**
     * 自定义解析器
     *
     * @param msgConverters 信息转换
     * @param customizers   自定义参数
     * @return 解析器
     */
    @Bean
    public Decoder decoder(ObjectFactory<HttpMessageConverters> msgConverters, ObjectProvider<HttpMessageConverterCustomizer> customizers) {
        return new OptionalDecoder((new ResponseEntityDecoder(new MyDataDecoder(new SpringDecoder(msgConverters, customizers)))));
    }
}

 FeginCilent

package com.a.common.feign;

import com.a.common.feign.config.FeignConfig;
import io.swagger.annotations.ApiOperation;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;
import java.util.Map;


@Order(Ordered.HIGHEST_PRECEDENCE)
@Component
@FeignClient(value = "data-accessor-server", url = "http://192.168.0.1:8080", configuration = FeignConfig.class)
public interface DataAccessorFeignClient {
    /**
     * 获取学生的编号
     *
     * @param id 唯一主键
     * @return 学生编号
     */
    @GetMapping(value = "query/student/no")
    @ApiOperation(value = "获取学生的编号")
    String getStudentNo(Long id);
}

 访问类

package com.a.data.controller;

import com.a.common.feign.DataAccessorFeignClient;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;


@RestController
@Api(tags = "Tests-测试-相关接口")
@RequestMapping(value = "/test/test", produces = MediaType.APPLICATION_JSON_VALUE)
public class TestController {
    @Resource
    private DataAccessorFeignClient dataAccessorFeignClient;

    @GetMapping("")
    @ApiOperation(value = "test-测试")
    public Object test(Long id) {
        return dataAccessorFeignClient.getStudentNo(id);
    }
}

此时可以愉快的进行接口调用,而又不需要做多余的判断了 

通用位置配置 

如果把对应的FeignClient放在公共位置,需要对该类是否使用进行配置,能满足该功能的官方注解有两个

1.@ConditionalOnExpression -根据表达式确定是否满足使用
2.@ConditionalOnProperty -根据having值确定是否满足使用

使用@ConditionalOnExpression,发现没有生效,跟踪代码发现,是因为该注解的生效优先级比较低,而 @ConditionalOnProperty 优先级比较高,导致@EnableFeignClients扫描的时候,该注解还没执行,所以要么是使用@ConditionalOnProperty注解,要么是将优先级问题解决掉

 

 记录备查

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Fegin Token统一认证是一种将微服务架构的认证流程整合和统一管理的解决方案。在微服务架构,每个服务都需要进行认证和授权操作,传统的方式是在每个服务都嵌入认证流程,这样会导致代码重复和维护困难。Fegin Token统一认证提供了一种解决方案,通过将认证和授权流程独立出来,让每个微服务只需要调用认证服务获取令牌即可。 Fegin Token统一认证的核心概念是令牌。在整个认证流程,首先用户提供用户名和密码,认证服务对用户进行验证,并生成一个令牌。然后,其他微服务在调用时只需要携带该令牌,认证服务会对令牌进行验证,并返回结果。这样,每个微服务都可以通过令牌来确认用户的身份和权限。 Fegin Token统一认证的优点首先是减少了重复代码的编写和维护工作量。由于整个认证流程被独立出来,每个微服务不再需要自己实现认证逻辑,只需要调用认证服务即可。其次,这种统一的认证方式提高了系统的灵活性和可扩展性。如果有新的认证方式需要添加,只需要在认证服务进行修改,而不需要修改每个微服务。 当然,Fegin Token统一认证也存在一些挑战和注意事项。首先,认证服务的性能和可用性对整个系统至关重要,如果认证服务出现故障或性能瓶颈,将影响到所有微服务的正常运行。因此,认证服务的设计和部署需要特别关注。另外,令牌的生成和验证过程需要进行一定程度的加密和安全保护,以防止令牌被窃取或篡改。 综上所述,Fegin Token统一认证是一种将微服务架构认证流程统一管理的解决方案,通过将认证和授权流程独立出来,提供了代码复用和灵活性的优势。但是,在实际应用需要注意保证认证服务的性能和安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值