当前位置:网站首页>Feign通过自定义注解实现路径的转义
Feign通过自定义注解实现路径的转义
2022-06-28 04:21:00 【qq_43479892】
优质资源分享
| 学习路线指引(点击解锁) | 知识定位 | 人群定位 |
|---|---|---|
| 🧡 Python实战微信订餐小程序 🧡 | 进阶级 | 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。 |
| Python量化交易实战 | 入门级 | 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统 |

本文主要讲解如果通过注解实现对路由中的路径进行自定义编码
背景
近期由于项目中需要,所以需要通过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.*;
/**
* @CreateAt: 2022/6/11 0:46
* @ModifyAt: 2022/6/11 0:46
* @Version 1.0
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SlashPathVariable {
/**
* Alias for {@link #name}.
*/
@AliasFor("name")
String value() default "";
/**
* The name of the path variable to bind to.
* @since 4.3.3
*/
@AliasFor("value")
String name() default "";
/**
* Whether the path variable is required.
* <p>Defaults to {@code true}, leading to an exception being thrown if the path
* variable is missing in the incoming request. Switch this to {@code false} if
* you prefer a {@code null} or Java 8 {@code java.util.Optional} in this case.
* e.g. on a {@code ModelAttribute} method which serves for different requests.
* @since 4.3.3
*/
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;
/**
* @CreateAt: 2022/6/11 0:36
* @ModifyAt: 2022/6/11 0:36
* @Version 1.0
*/
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;
/**
* @CreateAt: 2022/6/11 0:48
* @ModifyAt: 2022/6/11 0:48
* @Version 1.0
*/
@Component
public class SlashBean {
@Bean
public Contract feignContract(){
List<AnnotatedParameterProcessor> processors=new ArrayList<>();
processors.add(new SlashPathVariableParameterProcessor());
return new SpringMvcContract(processors);
}
}
最后我们将上面的参数注解PathVariable换成我们自定义的@SlashPathVariable,就大功告成了
最后
通过以上的形式进行注入的话,会注入到Spring全局,所以在使用的过程中需要考虑是否符合场景
如有哪里讲得不是很明白或是有错误,欢迎指正
如您喜欢的话不妨点个赞收藏一下吧
边栏推荐
- [Matlab bp regression prediction] GA Optimized BP regression prediction (including comparison before optimization) [including source code 1901]
- MySQL gets the current date of the year
- Congratulations to myself, official account has more than ten thousand fans
- Sword finger offer 47 Maximum gift value (DP)
- Live online source code, JS dynamic effect, sidebar scrolling fixed effect
- Project practice! Teach you JMeter performance test hand in hand
- 快速下载JDK,除了官方Oracle下载,还有国内可以有最新版本的下载地址吗
- Is the securities account opened by qiniu safe? How to open an account
- Why are cloud vendors targeting this KPI?
- S32ds jump to defaultisr
猜你喜欢

MySQL gets the current date of the year

2022年中國音頻市場年度綜合分析

Severe tire damage: the first rock band in the world to broadcast live on the Internet

Oracledata installation problems

From meeting a big guy to becoming a big guy, shengteng AI developer creation day brings infinite possibilities to developers

Matlab exercises -- routine operation of matrix
![[applet] solution document using font awesome Font Icon (picture and text)](/img/1b/d1b738e6e35e59cc4a417df4ea0e8d.png)
[applet] solution document using font awesome Font Icon (picture and text)

Multi thread implementation rewrites run (), how to inject and use mapper file to operate database

浅析搭建视频监控汇聚平台的必要性及场景应用

Simple factory mode
随机推荐
The SQL of filincdc always reports this error when there are multiple tables. How can I solve it
Win10 how to delete the large file hiberfil sys
Principle and implementation of SSD for target detection
[proteus simulation] timer 1 external counting interrupt
控制器的功能和工作原理
[NOIP2002 普及组] 过河卒
Analysis of distributed transaction solution Seata golang
Analyse complète annuelle du marché chinois de l'audio en 2022
Are test / development programmers really young? The world is fair. We all speak by strength
Mise en place d'un cadre d'essai d'automatisation de l'interface utilisateur - - rédaction d'une application d'automatisation
Idle interrupt cannot be cleared
The growth summer challenge is coming | learn and create two major tracks, and start the tutor registration!
filinCdc 的sql,多表的时候总报这个错,请问下该怎么解决呀
Is it true that qiniu business school gives away securities accounts? Is it safe to open an account
27 years, Microsoft IE is over!
Light collector, Yunnan Baiyao!
Principle of event delegation
Excel knowledge and skills summary
IP数据报的发送和转发过程
A bit of knowledge - online resources on Chinese Learning