package com.hotent.feign.mockmvc; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import com.hotent.feign.mockmvc.client.MockMvcClient; import org.springframework.cloud.openfeign.FeignContext; import feign.Client; import org.springframework.util.AntPathMatcher; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; public class MockMvcFeignContext extends FeignContext { private final MockMvcFeignObjectWrapper mockMvcFeignObjectWrapper; private final FeignContext delegate; public MockMvcFeignContext(MockMvcFeignObjectWrapper mockMvcFeignObjectWrapper, FeignContext delegate) { this.mockMvcFeignObjectWrapper = mockMvcFeignObjectWrapper; this.delegate = delegate; } /** * 指定的feignclient 使用mockmvc进行转发,其他的feignclient使用http的方式转发 * @param name * @param type * @return * @param */ @SuppressWarnings("unchecked") @Override public T getInstance(String name, Class type) { T object = this.delegate.getInstance(name, type); if (object instanceof Client) { if(mockmvcContextId(name)){ return (T) object; } if(object instanceof MockMvcClient){ MockMvcClient mockMvcClient = (MockMvcClient) object; return (T) mockMvcClient.getDelegate(); } } return (T) this.mockMvcFeignObjectWrapper.wrap(object); } private boolean mockmvcContextId(String name){ // 可以指定哪些feignClient 使用MockMvcClient进行转发。 List mockmvcContextIdList = mockMvcFeignObjectWrapper.getApplicationContext().getEnvironment().getProperty("feign.mockmvcclient",List.class); return matchContextId(name, mockmvcContextIdList); } /** * 匹配contextId, 匹配上的 需要进行mock方式转发feign请求 * @param name * @param mockmvcContextIdList * @return */ private static boolean matchContextId(String name, List mockmvcContextIdList) { if(CollectionUtils.isEmpty(mockmvcContextIdList)) { return false; } AntPathMatcher antPathMatcher = new AntPathMatcher(); // 支持antPathMatcher方式配置 for (String contextId : mockmvcContextIdList) { if(antPathMatcher.match(contextId, name)){ return true; } } return false; } @SuppressWarnings("unchecked") @Override public Map getInstances(String name, Class type) { Map instances = this.delegate.getInstances(name, type); if (instances == null) { return null; } Map convertedInstances = new HashMap<>(); for (Map.Entry entry : instances.entrySet()) { if (entry.getValue() instanceof Client) { convertedInstances.put(entry.getKey(), entry.getValue()); } else { convertedInstances.put(entry.getKey(), (T) this.mockMvcFeignObjectWrapper.wrap(entry.getValue())); } } return convertedInstances; } }