FeignClient接口类用自定义注解添加统一的入参字段或者处理参数

9 篇文章 0 订阅

远程调用第三方系统的接口,都需要传sign签字字段,而此字段一般是用密钥和入参根据约定的算法生成的字符串。为了代码简洁快捷,所以通过注解的方式去实现。

首先定义一个注解

package com.yulisao.common;

import java.lang.annotation.*;

@Inherited // 子类也会继承这个注解
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AddSignAnnotation {
}

添加注解的实现类

package com.yulisao.common;

import com.yulisao.utils.SignUtils;
import com.yulisao.dto.TradeInfoDTO;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;


@Aspect
@Component
public class AddSignInterceptor {

    @Value("${spring.appid}")
    private String appid;

    @Value("${spring.secret}")
    private String appSecret;

    // 表明这个类的功能为谁而执行(已指明了详细的包路径)
    @Pointcut("@within(com.yulisao.common.AddSignAnnotation)")
    private void execute() {
    }

    // 功能具体实现逻辑
    @Around("execute()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        Object[] paramValues = pjp.getArgs(); // 获取请求参数, get 和psot 请求都可以获取到
        for (int i = 0; i < paramValues.length; i++) { // 遍历请求参数
            if (paramValues[i] instanceof TradeInfoDTO) { // 若请求对象中包含TradeInfoDTO这个对象。为了复用性,建议新建一个base对象里面就只有sign这个字段,全部接口的入参对象都继承base对象。这样这里就不用写很多的 if instanceof 了
                TradeInfoDTO reqBody = (TradeInfoDTO) paramValues[i]; // 取出请求参数
                String sign = SignUtils.sign(reqBody); // 自行实现签名细节
                reqBody.setSign(sign); // 给签名字段赋值
                paramValues[i] = reqBody; // 处理完成返回
            }
            // 思考题:get请求,可以尝试在url上统一的拼接某个参数,实现方式略
        }
        return pjp.proceed(paramValues);
    }
}

fegin调用demo

package com.yulisao.client;

import com.alibaba.fastjson.JSONObject;
import com.yulisao.common.AddSignAnnotation;
import com.yulisao.dto.TradeInfoDTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;


@FeignClient(name = "trande-service", url = "${spring.baseurl}") // 设定第三方接口的baseurl
@AddSignAnnotation // 添加此注解 发送请求之前会拦截,给请求参数做处理(添加签名字段到请求参数中)
public interface TradeClient {


    /**
     * 发起交易
     * @param param
     * @return
     */
    @PostMapping("/trade/pay")
    JSONObject pay(@RequestBody TradeInfoDTO param);

    /**
     * 查询用户交易记录
     * @param userId
     * @param userName
     * @return
     */
    @GetMapping("/query/tradeList")
    JSONObject tradeList(@RequestParam(name = "userId")String userId, @RequestParam(name = "userName")String userName);

}

请求对象dto

package com.yulisao.dto;

import lombok.Data;

import java.math.BigDecimal;

@Data
public class TradeInfoDTO {

    private Long userId;
    private BigDecimal amount;
    // 这个公共字段 建议放一个专门的base对象,然后 TradeInfoDTO extends base对象
    private String sign;
}

题外话,若对方接口要求请求头里面有某个固定的参数,比如token,实现方法可参考如下

先创建一个请求拦截器

package com.yulisao.common;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

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


@Configuration
public class AddToken {

    //@Value("${client.tokenid}")
    //private String tokenId;

    @Bean
    public RequestInterceptor headerInterceptor() {
        return new RequestInterceptor(){

            @Override
            public void apply(RequestTemplate template) {
                JSONObject params = new JSONObject();
                params.put("token", "1234567890"); // token的获取自行实现
                List<String> authorizationList = Lists.newArrayList(params.toJSONString());
                List<String> contentTypeList = Lists.newArrayList("application/x-www-form-urlencoded;charset=utf-8");
                Map<String, Collection<String>> headers = ImmutableMap.of("Authorization", authorizationList,"Content-Type", contentTypeList); // header头里面的参数名称是Authorization
                template.headers(headers);
            }
        };
    }
}

fegin接口调用此拦截

@FeignClient(name = "trande-service", url = "${spring.baseurl}", configuration = AddToken.class) // 通过拦截器统一设置请求头
@AddSignAnnotation
public interface TradeClient {
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值