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

溫馨提示×

溫馨提示×

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

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

如何解決Spring Cloud中使用Feign,@RequestBody無法繼承問題

發布時間:2021-10-22 10:09:48 來源:億速云 閱讀:534 作者:iii 欄目:開發技術

本篇內容主要講解“如何解決Spring Cloud中使用Feign,@RequestBody無法繼承問題”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何解決Spring Cloud中使用Feign,@RequestBody無法繼承問題”吧!

目錄
  • Spring Cloud中使用Feign,@RequestBody無法繼承的問題

    • 原因分析

    • 解決方案

  • spring cloud 使用feign遇到的問題

    • 1、示例

    • 2、首次訪問超時問題

    • 3、FeignClient接口中,如果使用到@PathVariable,必須指定其value

Spring Cloud中使用Feign,@RequestBody無法繼承的問題

根據官網FeignClient的例子,編寫一個簡單的updateUser接口,定義如下

@RequestMapping("/user")
public interface UserService {
    @RequestMapping(value = "/{userId}", method = RequestMethod.GET)
    UserDTO findUserById(@PathVariable("userId") Integer userId);
    @RequestMapping(value = "/update", method = RequestMethod.POST)
    boolean updateUser(@RequestBody UserDTO user);
}

實現類

 @Override
    public boolean updateUser(UserDTO user)
    {   
        LOGGER.info("===updateUser, id = " + user.getId() + " ,name= " + user.getUsername());
        return false;
    }

執行單元測試,發現沒有獲取到預期的輸入參數

2018-09-07 15:35:38,558 [http-nio-8091-exec-5] INFO [com.springboot.user.controller.UserController] {} - ===updateUser, id = null ,name= null

原因分析

SpringMVC中使用RequestResponseBodyMethodProcessor類進行入參、出參的解析。以下方法根據參數是否有@RequestBody注解判斷是否進行消息體的轉換。

@Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(RequestBody.class);
    }

解決方案

既然MVC使用RequestResponseBodyMethodProcessor進行參數解析,可以實現一個定制化的Processor,修改supportParameter的判斷方法。

 @Override
    public boolean supportsParameter(MethodParameter parameter)
    {
        //springcloud的接口入參沒有寫@RequestBody,并且是自定義類型對象 也按JSON解析
        if (AnnotatedElementUtils.hasAnnotation(parameter.getContainingClass(), FeignClient.class) && isCustomizedType(parameter.getParameterType())) {
            return true;
        }
        return super.supportsParameter(parameter);
    }

此處的判斷邏輯可以根據實際框架進行定義,目的是判斷到為Spring Cloud定義的接口,并且是自定義對象時,使用@RequestBody相同的內容轉換器。

實現定制化的Processor后,還需要讓自定義的配置生效,有兩種方案可選:

  • 直接替換RequestResponseBodyMethodProcessor,在SpringBoot下需要自定義RequestMappingHandlerAdapter。

  • 實現WebMvcConfigurer中的addArgumentResolvers接口

這里采用較為簡單的第二種方式,初始化時的消息轉換器根據需要進行加載:

public class XXXWebMvcConfig implements WebMvcConfigurer
{
@Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers)
    {
        StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
        stringHttpMessageConverter.setWriteAcceptCharset(false);
        List<HttpMessageConverter<?>> messageConverters = new ArrayList<>(5);
        messageConverters.add(new ByteArrayHttpMessageConverter());
        messageConverters.add(stringHttpMessageConverter);
        messageConverters.add(new SourceHttpMessageConverter<>());
        messageConverters.add(new AllEncompassingFormHttpMessageConverter());
        CustomizedMappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new CustomizedMappingJackson2HttpMessageConverter();
        jackson2HttpMessageConverter.setObjectMapper(defaultObjectMapper());
        messageConverters.add(jackson2HttpMessageConverter);
        ViomiMvcRequestResponseBodyMethodProcessor resolver = new ViomiMvcRequestResponseBodyMethodProcessor(messageConverters);
        resolvers.add(resolver);
    }

修改完成后,微服務的實現類即可去掉@RequestBody注解。

spring cloud 使用feign遇到的問題

spring cloud 使用feign 項目的搭建 在這里就不寫了,本文主要講解在使用過程中遇到的問題以及解決辦法

1、示例

@RequestMapping(value = "/generate/password", method = RequestMethod.POST)
KeyResponse generatePassword(@RequestBody String passwordSeed);

在這里 只能使用 @RequestMapping(value = "/generate/password", method = RequestMethod.POST) 注解 不能使用

@PostMapping 否則項目啟動會報

Caused by: java.lang.IllegalStateException: Method generatePassword not annotated with HTTP method type (ex. GET, POST) 異常

2、首次訪問超時問題

原因:Hystrix默認的超時時間是1秒,如果超過這個時間尚未響應,將會進入fallback代碼。

而首次請求往往會比較慢(因為Spring的懶加載機制,要實例化一些類),這個響應時間可能就大于1秒了。

解決方法:

<1:配置Hystrix的超時時間改為5秒

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000

<2:禁用Hystrix的超時時間

hystrix.command.default.execution.timeout.enabled: false

<3:禁用feign的hystrix 功能

feign.hystrix.enabled: false

注:個人推薦 第一 或者第二種 方法

3、FeignClient接口中,如果使用到@PathVariable,必須指定其value

spring cloud feign 使用 Apache HttpClient

問題:1 沒有指定 Content-Type 是情況下 會出現如下異常 ? 這里很納悶?

Caused by: java.lang.IllegalArgumentException: MIME type may not contain reserved characters

在這里有興趣的朋友可以去研究下源碼

ApacheHttpClient.class 
  private ContentType getContentType(Request request) {
    ContentType contentType = ContentType.DEFAULT_TEXT;
    for (Map.Entry<String, Collection<String>> entry : request.headers().entrySet())
    // 這里會判斷 如果沒有指定 Content-Type 屬性 就使用上面默認的 text/plain; charset=ISO-8859-1
    // 問題出在默認的 contentType : 格式 text/plain; charset=ISO-8859-1 
    // 轉到 ContentType.create(entry.getValue().iterator().next(), request.charset()); 方法中看
    if (entry.getKey().equalsIgnoreCase("Content-Type")) {
      Collection values = entry.getValue();
      if (values != null && !values.isEmpty()) {
        contentType = ContentType.create(entry.getValue().iterator().next(), request.charset());
        break;
      }
    }
    return contentType;
  }
ContentType.class
   public static ContentType create(final String mimeType, final Charset charset) {
        final String normalizedMimeType = Args.notBlank(mimeType, "MIME type").toLowerCase(Locale.ROOT);
 // 問題在這 check  中 valid f方法中
        Args.check(valid(normalizedMimeType), "MIME type may not contain reserved characters");
        return new ContentType(normalizedMimeType, charset);
    }
   private static boolean valid(final String s) {
        for (int i = 0; i < s.length(); i++) {
            final char ch = s.charAt(i);
     // 這里 在上面 text/plain;charset=UTF-8 中出現了 分號 導致檢驗沒有通過 
            if (ch == '"' || ch == ',' || ch == ';') {
                return false;
            }
        }
        return true;
    }

解決辦法 :

@RequestMapping(value = "/generate/password", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)

注解中指定: Content-Type 即 指定 consumes 的屬性值 : 這里 consumes 屬性的值在這不做具體講解,有興趣的可以去研究下

到此,相信大家對“如何解決Spring Cloud中使用Feign,@RequestBody無法繼承問題”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

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

AI

西城区| 兖州市| 和平县| 长白| 任丘市| 策勒县| 中牟县| 孝义市| 庆城县| 高密市| 任丘市| 靖江市| 雷州市| 噶尔县| 彩票| 海门市| 高要市| 浦北县| 安多县| 阿图什市| 乌拉特中旗| 保亭| 武强县| 赞皇县| 梨树县| 大同县| 洛扎县| 武宣县| 盘山县| 淮南市| 南和县| 蓝田县| 乾安县| 长宁县| 高唐县| 永和县| 永州市| 都安| 兴城市| 马山县| 疏附县|