中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Feign怎么利用自定義注解實現路徑轉義

發布時間:2022-06-28 14:06:55 來源:億速云 閱讀:142 作者:iii 欄目:開發技術

本篇內容主要講解“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.*;

/**
  * @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,就大功告成了

到此,相信大家對“Feign怎么利用自定義注解實現路徑轉義”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

富蕴县| 阜南县| 兖州市| 耿马| 昆山市| 呈贡县| 遂溪县| 黑龙江省| 平湖市| 乡宁县| 西畴县| 威海市| 盐池县| 乾安县| 疏附县| 云浮市| 安西县| 宁城县| 贺州市| 青海省| 榆社县| 惠东县| 祁东县| 榆林市| 囊谦县| 邯郸县| 河东区| 宁波市| 济源市| 安乡县| 永顺县| 鄂州市| 巴彦县| 凤城市| 灵武市| 丹凤县| 封开县| 南通市| 临夏县| 柘荣县| 勐海县|