Feign使用示例
Basic Auth调用示例
- 创建配置类
/**
* Feign客户端basicAuth配置
*
* @author Yoko
* @since 2024/10/24 19:27
*/
public class BasicAuthFeignConfig {
@Resource
private IotZdzkProperty zdzkProperty;
@Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor(zdzkProperty.getUsername(), zdzkProperty.getPassword());
}
}
- 创建Feign客户端
import feign.Headers;
import org.jeecg.modules.iot.zdzk.config.BasicAuthFeignConfig;
import org.jeecg.modules.iot.zdzk.vo.ZdzkTokenVO;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.Map;
@ConditionalOnProperty(prefix = "smart-drain-reuse.iot.zdzk", name = "enabled", havingValue = "true")
@FeignClient(name = "iot-zdzk-token-api", url = "${smart-drain-reuse.iot.zdzk.thirdApiUrl}", configuration = BasicAuthFeignConfig.class)
public interface IotZdzkTokenApi {
/**
* 获取token
*
* @author Yoko
* @since 2024/10/24 19:28
* @param formParams form表单参数 form.put("grant_type", "client_credentials");
* @return com.alibaba.fastjson.JSONObject
*/
@PostMapping(value = "/api/xxx/oauth/token", consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
@Headers({"Content-Type: application/x-www-form-urlencoded"})
ZdzkTokenVO getToken(@RequestBody Map<String, ?> formParams);
}
- 使用
public String getToken(boolean refresh) {
String token = (String) redisUtil.get(SmartDrainReuseConstant.REDIS_KEY_ZDZK_TOKEN);
if (null != token && !refresh) {
return token;
}
// 重新获取token
Map<String, Object> form = new HashMap<>();
form.put("grant_type", "client_credentials");
ZdzkTokenVO vo = iotZdzkTokenApi.getToken(form);
Long expiresIn = vo.getExpiresIn();
// 如果token快过期了就重新获取
while (expiresIn - 1 < 0) {
vo = iotZdzkTokenApi.getToken(form);
expiresIn = vo.getExpiresIn();
}
redisUtil.set(SmartDrainReuseConstant.REDIS_KEY_ZDZK_TOKEN, vo.getAccessToken(), expiresIn -1);
return vo.getAccessToken();
}
使用Header
- 普通字段
@PostMapping(value = "/api/xxx")
ZdzkDataResultVO<List<ZdzkDataRiverVO>> getRiverList(@RequestParam ZdzkRiverListQuery query, @RequestHeader("Authorization") String authorization, @RequestHeader("Client-Id") String clientId);
- 通过Map传递
@PostMapping(value = "/api/xxx", consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
ZdzkDataResultVO<List<ZdzkDataTidalVO>> getTidalList(@ModelAttribute ZdzkTidalQuery query, @HeaderMap Map<String, String> headers);
- 设置配置类全局注入
public class BearerFeignConfig {
@Bean
public BearerFeignInterceptor bearerFeignInterceptor() {
return new BearerFeignInterceptor();
}
}
public class BearerFeignInterceptor implements RequestInterceptor {
public final static String HEADER_CLIENT_ID = "Client-Id";
@Override
public void apply(RequestTemplate template) {
template.header(HEADER_CLIENT_ID, "xxxxxx");
}
}
// 这是所有接口都会自动添加Header: Client-Id: xxxxxx
@ConditionalOnProperty(prefix = "smart-drain-reuse.iot.zdzk", name = "enabled", havingValue = "true")
@FeignClient(name = "iot-zdzk-data-api", url = "${smart-drain-reuse.iot.zdzk.thirdApiUrl}", configuration = BearerFeignConfig.class)
public interface IotZdzkDataApi {
@PostMapping(value = "/api/xxx", consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
ZdzkDataResultVO<List<ZdzkDataRiverVO>> getRiverList(@RequestParam Map<String, Object> query);
}
Bearer Token使用示例
- 定义拦截器
import feign.RequestInterceptor;
import feign.RequestTemplate;
import lombok.Getter;
import lombok.Setter;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.config.constant.SmartDrainReuseConstant;
import org.jeecg.config.iot.IotZdzkProperty;
import javax.annotation.Resource;
/**
* Feign客户端Bearer认证配置
*
* @author Yoko
*/
@Setter
@Getter
public class BearerFeignInterceptor implements RequestInterceptor {
public final static String HEADER_CLIENT_ID = "Client-Id";
public final static String HEADER_AUTHORIZATION = "Authorization";
public final static String BEARER_PREFIX = "Bearer ";
@Resource
private IotZdzkProperty iotZdzkProperty;
@Resource
private RedisUtil redisUtil;
/**
* Feign客户端Bearer认证配置
*
* @author Yoko
* @since 2024/10/25 14:57
* @param template 请求模板
*/
@Override
public void apply(RequestTemplate template) {
template.header(HEADER_CLIENT_ID, iotZdzkProperty.getUsername());
template.header(HEADER_AUTHORIZATION, BEARER_PREFIX + redisUtil.get(SmartDrainReuseConstant.REDIS_KEY_ZDZK_TOKEN));
}
}
- 定义配置类
import org.springframework.context.annotation.Bean;
/**
* Feign客户端Bearer认证配置
*
* @author Yoko
*/
public class BearerFeignConfig {
@Bean
public BearerFeignInterceptor bearerFeignInterceptor() {
return new BearerFeignInterceptor();
}
}
- Feign客户端使用,所有接口都会自动添加Header: Client-Id: xxxxxx 和 Authorization: Bearer xxxxx
@ConditionalOnProperty(prefix = "smart-drain-reuse.iot.zdzk", name = "enabled", havingValue = "true")
@FeignClient(name = "iot-zdzk-data-api", url = "${smart-drain-reuse.iot.zdzk.thirdApiUrl}", configuration = BearerFeignConfig.class)
public interface IotZdzkDataApi {
@PostMapping(value = "/api/xxx", consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
ZdzkDataResultVO<List<ZdzkDataRiverVO>> getRiverList(@RequestParam Map<String, Object> query);
@PostMapping(value = "/api/xxx", consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
ZdzkDataResultVO<List<ZdzkDataRainVO>> getRainList(@RequestBody ZdzkRainQuery query);
}
@RequestParam标注Map
测试发现,Query的查询参数,使用Map传递,会自动拼接为key1=value1&key2=value2的形式
// 可以正常处理query参数
@PostMapping(value = "/api/xxx", consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
ZdzkDataResultVO<List<ZdzkDataRainVO>> getRainList(@RequestParam Map<String, Object> query);
// 传入对象时,就无法解析成query查询
@PostMapping(value = "/api/xxx", consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
ZdzkDataResultVO<List<ZdzkDataRainVO>> getRainList(@RequestParam ZdzkRainQuery query);