Using native Feign is appropriate for SpringMVC projects. The time spent on configuration and a few potholes didn’t feel like it was worth it. Wish there were not so many configurations in the world.
Add dependencies
<! -- Feign client -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
<version>9.7.0</version>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<version>9.7.0</version>
</dependency>
<! -- Jackson serialization () -- Jackson serialization ()
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jackson</artifactId>
<version>9.7.0</version>
</dependency>
<! -- okHTTP is used by the client.
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
<version>11.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.48. Sec06</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>22.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
<scope>provided</scope>
</dependency>
Copy the code
Second, Feign configuration HTTP
/ * * *@author chris wang
* @dateApril 23, 2021 9:17 *@descriptionFeign HTTP configuration */
@Configuration
public class FeignClientConfiguration {
@Autowired
private Contract environmentFeignContract;
@Bean
public Feign feign(a) {
return Feign.builder() // Create the feign builder
.encoder(new JacksonEncoder()) / / JSON encoding
.decoder(new MyDecoder()) / / JSON decode
.options(new Request.Options(1000.3500)) // Set timeout
.retryer(new Retryer.Default(5000.5000.2)).contract(environmentFeignContract).
build(); // Set retry}}Copy the code
/ * * *@author chris wang
* @dateApril 23, 2021 9:16 *@descriptionCustom parse ApiClient annotation placeholder $vipToken */
public abstract class AbstractFeignContract extends Contract.Default {
@Override
protected void processAnnotationOnClass(MethodMetadata data, Class
targetType) {
super.processAnnotationOnClass(data, targetType);
handleHeaders(data);
}
@Override
protected void processAnnotationOnMethod(MethodMetadata data, Annotation annotation, Method method) {
super.processAnnotationOnMethod(data, annotation, method);
handleHeaders(data);
}
@Override
protected boolean processAnnotationsOnParameter(MethodMetadata data, Annotation[] annotations, int paramIndex) {
return super.processAnnotationsOnParameter(data, annotations, paramIndex);
}
private void handleHeaders(MethodMetadata data) {
if (data == null || CollectionUtils.isEmpty(data.template().headers())) return;
for (Map.Entry<String, Collection<String>> entry : data.template().headers().entrySet()) {
if (StringUtils.isEmpty(entry.getKey())) continue;
Collection<String> values = entry.getValue();
if (CollectionUtils.isEmpty(values)) continue;
Collection<String> result = Lists.newArrayList();
Collection<String> exludes = Lists.newArrayList();
for (String val : values) {
exludes.add(val);
if (val.startsWith(PlaceholderConfigurerSupport.DEFAULT_PLACEHOLDER_PREFIX) && val.endsWith(PlaceholderConfigurerSupport.DEFAULT_PLACEHOLDER_SUFFIX)) {
String placeholder = val.substring(val.indexOf(PlaceholderConfigurerSupport.DEFAULT_PLACEHOLDER_PREFIX) + 2, val.indexOf(PlaceholderConfigurerSupport.DEFAULT_PLACEHOLDER_SUFFIX)); val = findProperty(placeholder); } result.add(val); } values.removeAll(exludes); values.addAll(result); }}public abstract String findProperty(String key);
}
Copy the code
/ * * *@author chris wang
* @dateApril 27, 2021 12:55 *@descriptionThe properties for * /
@Configuration
public class EnvironmentFeignContract extends AbstractFeignContract {
@Autowired
private Environment environment;
@Override
public String findProperty(String key) {
returnenvironment.getProperty(key); }}Copy the code
/ * * *@author chris wang
* @dateApril 23, 2021 9:17 *@descriptionDefine decoding rules */
public class MyDecoder extends JacksonDecoder {
@Override
public Object decode(Response response, Type type) throws IOException {
// Wrap an IocResponse
Type wapperType = ParameterizedTypeImpl.make(MyResponse.class, new Type[]{
type
}, null);
Object decodeObj = super.decode(response, wapperType);
if(decodeObj ! =null && decodeObj instanceof MyResponse) {
MyResponse iocResponse = (MyResponse) decodeObj;
if(! iocResponse.isSuccess())throw new RuntimeException(iocResponse.getMessage());
return iocResponse.getData();
}
throw newRuntimeException(JSON.toJSONString(decodeObj)); }}Copy the code
Define an ApiClient
/ * * *@author chris wang
* @dateApril 23, 2021 9:16 *@descriptionAPI client */
public interface ApiClient {
@Headers({"Content-Type: application/json", "Accept: application/json", "viptoken: ${viptoken}"})
@RequestLine("POST /my/api/system_metric/continuous_build")
List<ContinuousBuildResp> getContinuousBuild(ContinuousBuildReq req);
}
Copy the code
Define a Client factory
/ * * *@author chris wang
* @dateApril 23, 2021 9:16 *@descriptionDefine a Client factory */
@Configuration
public class FeignClientApiFactory {
@Value("${myUrl}")
private String myUrl;
@Autowired
private Feign feign;
@Bean
public ApiClient getMyApi(a) {
return feign.newInstance(newTarget.HardCodedTarget<>(ApiClient.class, myUrl)); }}Copy the code
5, generic Response
/ * * *@author chris wang
* @dateApril 27, 2021 9:28 *@descriptionUse a return */ of generics
public class MyResponse<T> {
private String message;
private boolean success;
private T data;
public String getMessage(a) {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public boolean isSuccess(a) {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public T getData(a) {
return data;
}
public void setData(T data) {
this.data = data; }}Copy the code
Other categories
/ * * *@author chris wang
* @dateApril 27, 2021 9:28 *@description* /
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ContinuousBuildResp {
private int ci_num;
private int ci_score;
private int ci_success_num;
private String ci_success_rate;
private String rank;
}
Copy the code
/ * * *@author chris wang
* @dateApril 27, 2021 9:28 *@description* /
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class ContinuousBuildReq {
private String date_type;
private String start_time;
private String end_time;
}
Copy the code
Seven, application properties
MyUrl =http://localhost:8090 vipToken = XXXXXXXXX reference:
www.hicode.club/articles/20… www.cnblogs.com/zby9527/p/1… Blog.csdn.net/weixin_3406…