spring cloud openfeign中@RequestMapping和@FeginClient注解不能同时使用的问题

项目启动异常如下

Caused by: java.lang.IllegalArgumentException: @RequestMapping annotation not allowed on @FeignClient interfaces
	at org.springframework.cloud.openfeign.support.SpringMvcContract.processAnnotationOnClass(SpringMvcContract.java:180)
	at feign.Contract$BaseContract.parseAndValidateMetadata(Contract.java:89)
	at org.springframework.cloud.openfeign.support.SpringMvcContract.parseAndValidateMetadata(SpringMvcContract.java:187)
	at feign.Contract$BaseContract.parseAndValidateMetadata(Contract.java:62)
	at feign.ReflectiveFeign$ParseHandlersByName.apply(ReflectiveFeign.java:151)
	at feign.ReflectiveFeign.newInstance(ReflectiveFeign.java:49)
	at feign.Feign$Builder.target(Feign.java:269)
	at org.springframework.cloud.openfeign.DefaultTargeter.target(DefaultTargeter.java:30)
	at org.springframework.cloud.openfeign.FeignClientFactoryBean.loadBalance(FeignClientFactoryBean.java:373)
	at org.springframework.cloud.openfeign.FeignClientFactoryBean.getTarget(FeignClientFactoryBean.java:421)
	at org.springframework.cloud.openfeign.FeignClientFactoryBean.getObject(FeignClientFactoryBean.java:396)
	at org.springframework.cloud.openfeign.FeignClientsRegistrar.lambda$registerFeignClient$0(FeignClientsRegistrar.java:235)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1249)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1191)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
	... 84 common frames omitted

源码如下

org.springframework.cloud.openfeign.support.SpringMvcContract
@Override
	protected void processAnnotationOnClass(MethodMetadata data, Class clz) {
		RequestMapping classAnnotation = findMergedAnnotation(clz, RequestMapping.class);
		if (classAnnotation != null) {
			LOG.error("Cannot process class: " + clz.getName()
					+ ". @RequestMapping annotation is not allowed on @FeignClient interfaces.");
			throw new IllegalArgumentException("@RequestMapping annotation not allowed on @FeignClient interfaces");
		}
	}

项目之前运行没问题,考虑到这个问题是版本升级的问题导致的,首先考虑到的就是契约的问题,没想到确实这样,通过修改 feign 的契约来解决此问题,正好发现了一篇文章是讲这个的。

https://blog.csdn.net/qq_44734154/article/details/128624881

核心点如下

仿照 SpringMvcContract 新建一个类,例如 CustomSpringMvcContract,将 SpringMvcContract 代码全部复制过来,然后把 SpringMvcContract 对应的代码替换为 CustomSpringMvcContract,processAnnotationOnClass() 中最后的代码做一下调整

@Override
    protected void processAnnotationOnClass(MethodMetadata data, Class clz) {
        if (clz.getInterfaces().length == 0) {
            RequestMapping classAnnotation = (RequestMapping) AnnotatedElementUtils.findMergedAnnotation(clz, RequestMapping.class);
            if (classAnnotation != null && classAnnotation.value().length > 0) {
                String pathValue = Util.emptyToNull(classAnnotation.value()[0]);
                pathValue = this.resolve(pathValue);
                if (!pathValue.startsWith("/")) {
                    pathValue = "/" + pathValue;
                }

                // 源码调整,将
                // data.template().insert(0, pathValue);
                // 替换为
                data.template().uri(pathValue);
            }
        }
    }

openfeign 的默认配置位于

org.springframework.cloud.openfeign.FeignClientsConfiguration

其中,需要将 Contract 进行覆盖即可

	@Bean
	@ConditionalOnMissingBean
	public Contract feignContract(ConversionService feignConversionService) {
		boolean decodeSlash = feignClientProperties == null || feignClientProperties.isDecodeSlash();
		return new SpringMvcContract(this.parameterProcessors, feignConversionService, decodeSlash);
	}

如下

import feign.Contract;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.convert.support.DefaultConversionService;

import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.List;

@Configuration(proxyBeanMethods = false)
public class CustomFeignClientsConfiguration {

    private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

    @Autowired(required = false)
    private List parameterProcessors = new ArrayList<>();

    @Bean
    @ConditionalOnMissingBean
    @Primary
    public Contract feignContract() {
        logger.info("feignContract");
        return new CustomSpringMvcContract(this.parameterProcessors, new DefaultConversionService());
    }
}

启动即可。

你可能感兴趣的:(spring,spring,cloud,spring,后端)