微服务大行其道,新框架一般都基于springboot2.x
系统越来越多,系统间的交互不可避免,feign应用越来越广泛。
那么问题来了:
springboot2如何整合feign呢 , 系统间调用,如何统一验签?往下看
1、如何集成呢?
https://start.spring.io/
initial-springboot.pngApplication中启用@EnableFeignClients
@EnableFeignClients
@SpringBootAApplication
public class XXXApplication {
public static void main(String[] args) {
SpringApplication.run(XXXApplication.class, args);
}
}
声明Feign@FeignClient
@FeignClient(name = "xxxName", url = "${xxx.server.domain}", configuration = CustomFeignConfig.class)
public interface XXXFeign {
@RequestMapping(value = "/api/v/xxx", method = RequestMethod.GET)
String xxx(@RequestParam String x1);
@RequestMapping(value = "/api/xxx2", method = RequestMethod.POST,consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
String xxx2(Map<String,?> map, @RequestHeader(value = "u2at")String u2at);// map中 一定要 ? 此处有坑
}
FeignConfig配置
@Configuration
public class CustomFeignConfig {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
// new一个form编码器,实现支持form表单提交
@Bean
public Encoder feignFormEncoder() {
return new SpringFormEncoder(new SpringEncoder(messageConverters));
}
@Bean
FeignLoggerFactory infoFeignLoggerFactory() {
return new CustomFeignLoggerFactory();
}
static class CustomFeignLoggerFactory implements FeignLoggerFactory {
public Logger create(Class<?> type) {
return new CustomFeignLogger(LoggerFactory.getLogger(type));
}
}
static class CustomFeignLogger extends Logger {
private final org.slf4j.Logger logger;
public CustomFeignLogger(org.slf4j.Logger logger) {
this.logger = logger;
}
@Override
protected void log(String configKey, String format, Object... args) {
if (logger.isInfoEnabled()) {
this.logger.info(String.format(methodTag(configKey) + format, args));
}
}
@Override
protected void logRequest(String configKey, Level logLevel, Request request) {
if (this.logger.isInfoEnabled()) {
super.logRequest(configKey, logLevel, request);
}
}
@Override
protected Response logAndRebufferResponse(String configKey, Level logLevel, Response response,
long elapsedTime) throws IOException {
return this.logger.isInfoEnabled() ? super
.logAndRebufferResponse(configKey, logLevel, response, elapsedTime) : response;
}
}
}
feign超时,必须!!!
受相关系统影响导致宕机!!!亲眼所见多次,really,no kidding
feign.client.config.default.connectTimeout=2000
feign.client.config.default.readTimeout=3000
2、feign如何统一验签呢?
每次调用接口前计算验签、赋值,显然是不可接受的,那么
RequestInterceptor了解一下
接口通过Target#apply发送http请求,在这里你可以拿到参数。
计算后可以写入header、或者query、甚至body
* Zero or more {@code RequestInterceptors} may be configured for purposes such as adding headers to
* all requests. No guarantees are give with regards to the order that interceptors are applied.
* Once interceptors are applied, {@link Target#apply(RequestTemplate)} is called to create the
* immutable http request sent via {@link Client#execute(Request, feign.Request.Options)}.
FeignConfig实现RequestInterceptor#apply
@Configuration
public class CustomFeignConfig implements RequestInterceptor {
@Value("${xxx1.server.appId}")
private String appId1;
@Value("${xxx1.server.secret}")
private String secret1;
@Value("${xxx1.server.domain}")
private String domain1;
@Override
public void apply(RequestTemplate requestTemplate) {
String host = ((Target.HardCodedTarget) requestTemplate.feignTarget()).url();
String sign = "";
if (domain1.equals(host)) {
if ("GET".equals(requestTemplate.method())) {
sign = ztGetSign(requestTemplate);
requestTemplate.header("sign", sign);//如果参数在header中
requestTemplate.header("appId", appId1);
} else if ("POST".equals(requestTemplate.method())) {
// sign = ApiMac.sign(secret1, new String(requestTemplate.body()));
// requestTemplate.header("sign",sign);//如果参数在header中
JSONObject jsonParam = JSONObject.parseObject(new String(requestTemplate.body()));
jsonParam.put("appId", appId1);
jsonParam.put("sign", getParamSign(jsonParam));//如果sign在参数中
requestTemplate.body(jsonParam.toJSONString());
} else {
throw new UnsupportedOperationException(requestTemplate.method() + " 请先实现method sign");
}
} else if (domain2.equals(host)) {
// 验签计算赋值
}
}
private String getSign(RequestTemplate requestTemplate) {
// requestTemplate.queries(); calculate sign
}
}
到这里就完成了feign的整合,是不是觉得很简单。
后续可以想想怎么处理接口返回数据了。
网友评论