一、openfeign自带的注解,有以下三个,均实现接口org.springframework.cloud.openfeign.AnnotatedParameterProcessor。
1、RequestHeaderParameterProcessor
2、RequestParamParameterProcessor
3、PathVariableParameterProcessor
这里就不贴源码了。
二、自定义方法参数注解
1、实现接口AnnotatedParameterProcessor
import feign.MethodMetadata;
import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import static feign.Util.emptyToNull;
public class FormParamParameterProcessor implements AnnotatedParameterProcessor {
private static final Class<FormParam> ANNOTATION = FormParam.class;
@Override
public Class<? extends Annotation> getAnnotationType() {
return ANNOTATION;
}
@Override
public boolean processArgument(AnnotatedParameterContext context, Annotation annotation, Method method) {
FormParam formParam = ANNOTATION.cast(annotation);
String name = formParam.value();
if (emptyToNull(name) != null) {
context.setParameterName(name);
MethodMetadata data = context.getMethodMetadata();
data.formParams().add(name);
}
return true;
}
}
import java.lang.annotation.*;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FormParam {
String value() default "";
}
2、注册
@Bean
public FormParamParameterProcessor formParamParameterProcessor(){
return new FormParamParameterProcessor();
}
但是上述做法,会存在问题,具体原因见SpringMvcContract。
public SpringMvcContract(List<AnnotatedParameterProcessor> annotatedParameterProcessors, ConversionService conversionService) {
this.processedMethods = new HashMap();
this.resourceLoader = new DefaultResourceLoader();
Assert.notNull(annotatedParameterProcessors, "Parameter processors can not be null.");
Assert.notNull(conversionService, "ConversionService can not be null.");
Object processors;
if (!annotatedParameterProcessors.isEmpty()) {
// 需要注意走这个分支,所以解决办法是手动追加默认注解和自定义注解。
processors = new ArrayList(annotatedParameterProcessors);
} else {
// 遍历默认注解
processors = this.getDefaultAnnotatedArgumentsProcessors();
}
this.annotatedArgumentProcessors = this.toAnnotatedArgumentProcessorMap((List)processors);
this.conversionService = conversionService;
this.expander = new SpringMvcContract.ConvertingExpander(conversionService);
}
private List<AnnotatedParameterProcessor> getDefaultAnnotatedArgumentsProcessors() {
List<AnnotatedParameterProcessor> annotatedArgumentResolvers = new ArrayList();
annotatedArgumentResolvers.add(new PathVariableParameterProcessor());
annotatedArgumentResolvers.add(new RequestParamParameterProcessor());
annotatedArgumentResolvers.add(new RequestHeaderParameterProcessor());
return annotatedArgumentResolvers;
}
3、解决办法:把自定义参数注解追加到列表里。
public SpringMvcContract(List<AnnotatedParameterProcessor> annotatedParameterProcessors) {
this(annotatedParameterProcessors, new DefaultConversionService());
}
@Bean
public Contract springMvcContract() {
List<AnnotatedParameterProcessor> processors = new ArrayList<>();
// 自定义注解
processors.add(new FormParamParameterProcessor());
//openfeign自带的三个注解
processors.add(new PathVariableParameterProcessor());
processors.add(new RequestHeaderParameterProcessor());
processors.add(new RequestParamParameterProcessor());
return new SpringMvcContract(processors);
}
三、自定义参数注解的使用
注意方法中的自定义注解@FormParam("K")
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
//FeignServiceConfiguration见上一篇文章
@FeignClient(name = "user-service", url = "${user-service.url:}", configuration = FeignServiceConfiguration.class)
public interface UserApi {
@RequestMapping(value = "/login", method = {RequestMethod.POST},
consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE},
produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
LoginResponse login(@FormParam("K") String request);
}
网友评论