本篇内容主要讲解“Feign怎么利用自定义注解实现路径转义”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Feign怎么利用自定义注解实现路径转义”吧!背景近期由于项目中需要,所以需要通过Feig
本篇内容主要讲解“Feign怎么利用自定义注解实现路径转义”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Feign怎么利用自定义注解实现路径转义”吧!
近期由于项目中需要,所以需要通过Feign封装一个对Harbor操作的sdk信息。
在调用的过程中发现,当请求参数中带有"/"时,Feign默认会将"/"当成路径去解析,而不是当成完整的一个参数解析,实例如下
请求路径为:api/v2.0/projects/{projectName}/repositories
注解参数为:@PathVariable("projectName")
正常请求为:api/v2.0/projects/test/repositories
异常路径为:api/v2.0/projects/test/pro/repositories
相信细心的同学已经发现上面的差异了,正常的{projectName}中对应的值为test,而异常的却对应为test/pro,所以当异常的请求打到harbor的机器时,被解析为api/v2.0/projects/test/pro/repositories,所以会直接返回404
以上就是背景了,所以接下来我们讨论一下解决方案
首先我们知道SpringBoot中默认是带有几种注释参数处理器的
@MatrixVariableParameterProcessor@PathVariableParameterProcessor@QueryMapParameterProcessor@RequestHeaderParameterProcessor@RequestParamParameterProcessor@RequestPartParameterProcessor
因为我们的请求参数是在路径中的,所以默认我们会使用@PathVariableParameterProcessor来标识路径参数,而我们需要转义的参数其实也是在路径中,所以我们先来看一下@PathVariableParameterProcessor是如何实现的
public boolean processArgument(AnnotatedParameterProcessor.AnnotatedParameterContext context, Annotation annotation, Method method) { String name = ((PathVariable)ANNOTATION.cast(annotation)).value(); Util.checkState(Util.emptyToNull(name) != null, "PathVariable annotation was empty on param %s.", new Object[]{context.getParameterIndex()}); context.setParameterName(name); MethodMetadata data = context.getMethodMetadata(); String varName = '{' + name + '}'; if (!data.template().url().contains(varName) && !this.searchMapValues(data.template().queries(), varName) && !this.searchMapValues(data.template().headers(), varName)) { data.fORMParams().add(name); } return true; }
其实在源码中,springboot并没有做什么神器的事情,就是获取使用了PathVariable注解的参数,然后再将其添加到fromParams中就可以。
看到这里我们是不是可以想到,既然在这里我们可以拿到对应的参数了,那想做什么事情不都是由我们自己来决定了,接下来说干就干,
首先我们声明一个属于自己的注解,
import org.springframework.core.annotation.AliasFor;import java.lang.annotation.*;@Target(ElementType.PARAMETER)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface SlashPathVariable { @AliasFor("name") String value() default ""; @AliasFor("value") String name() default ""; boolean required() default true;}
声明完注解后,我们就需要来自定义自己的参数解析器了,首先继承AnnotatedParameterProcessor
import feign.MethodMetadata;import feign.Util;import lombok.Data;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;import org.springframework.WEB.bind.annotation.PathVariable;import java.lang.annotation.Annotation;import java.lang.reflect.AnnotatedType;import java.lang.reflect.Method;import java.net.URLEncoder;import java.NIO.charset.Charset;import java.util.Collection;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.stream.Collectors;public class SlashPathVariableParameterProcessor implements AnnotatedParameterProcessor { private static final Class<SlashPathVariable> ANNOTATION=SlashPathVariable.class; @Override public Class<? extends Annotation> getAnnotationType() { return (Class<? extends Annotation>) ANNOTATION; } @Override public boolean processArgument(AnnotatedParameterContext context, Annotation annotation, Method method) { MethodMetadata data = context.getMethodMetadata(); String name = ANNOTATION.cast(annotation).value(); Util.checkState(Util.emptyToNull(name) != null, "SlashPathVariable annotation was empty on param %s.", new Object[]{context.getParameterIndex()}); context.setParameterName(name); data.indexToExpander().put(context.getParameterIndex(),this::expandMap); return true; } private String expandMap(Object object) { String encode = URLEncoder.encode(URLEncoder.encode(object.toString(), Charset.defaultCharset()), Charset.defaultCharset()); return encode; }}
可以看到上面的代码,我们获取到自定义注解的参数后,将当前参数添加打Param后,并且为当前参数指定自定义的编码格式。
最后,我们再通过Bean的形式将对应的注解添加到容器中
import feign.Contract;import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;import org.springframework.cloud.openfeign.support.springMVCContract;import org.springframework.context.annotation.Bean;import org.springframework.stereotype.Component;import java.util.ArrayList;import java.util.List;@Componentpublic class SlashBean { @Bean public Contract feignContract(){ List<AnnotatedParameterProcessor> processors=new ArrayList<>(); processors.add(new SlashPathVariableParameterProcessor()); return new SpringmvcContract(processors); }}
最后我们将上面的参数注解PathVariable换成我们自定义的@SlashPathVariable,就大功告成了
到此,相信大家对“Feign怎么利用自定义注解实现路径转义”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
--结束END--
本文标题: Feign怎么利用自定义注解实现路径转义
本文链接: https://lsjlt.com/news/342130.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0