91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

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

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

怎么自定義@RequestBody注解獲取JSON數據

發布時間:2023-04-10 16:05:38 來源:億速云 閱讀:147 作者:iii 欄目:開發技術

這篇文章主要介紹“怎么自定義@RequestBody注解獲取JSON數據”,在日常操作中,相信很多人在怎么自定義@RequestBody注解獲取JSON數據問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么自定義@RequestBody注解獲取JSON數據”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

Spring MVC 的 @RequestBody 注解只能將請求體中的 JSON 數據封裝成 Bean,而無法對單一字段實施管理(例如 required、name 等屬性)。

自定義注解

首先思考,我們需要這個注解做什么?

  • 設置該字段的必選性(required)

  • 設置該字段在請求體 JSON 中的 key 值(name、value)

  • 設置該字段的默認值(defaultValue)

于是我們的注解類 @JsonArg 至少應該長這樣:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface JsonArg {
    @AliasFor("name")
    String value() default "";

    @AliasFor("value")
    String name() default "";

    boolean required() default true;

    String defaultValue() default ValueConstants.DEFAULT_NONE;
}

其中:

  • @Retention(RetentionPolicy.RUNTIME) 聲明我們需要在運行期動態地獲取它地信息

  • @Target(ElementType.PARAMETER) 聲明這個注解只能作用在方法參數

是的,它和 Spring MVC 自帶的 @RequestParam 注解非常像,但 @RequestParam 只能作用于 query parameters 和 form data。

自定義解析器

單純的定義注解類程序是無法知道我們要它做什么的,所以我們要告訴程序在遇到這個注解時該做什么。

public class JsonArgMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver {
    /**
     * 表示關于 namedValue 的信息,包括名稱、是否需要它以及默認值。
     *
     * @param parameter 待處理的方法參數
     * @return {@link JsonArgNamedValueInfo}
     */
    @Override
    protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) {
        JsonArg ann = parameter.getParameterAnnotation(JsonArg.class);
        return (ann != null ? new JsonArgNamedValueInfo(ann) : new JsonArgNamedValueInfo());
    }

    /**
     * 解析方法
     *
     * @param name      待解析的 JSON 的 key
     * @param parameter 待處理的方法參數
     * @return 解析出來的值
     */
    @Override
    protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
        ContentCachingRequestWrapper contentCachingRequestWrapper = request.getNativeRequest(ContentCachingRequestWrapper.class);
        String body;
        assert contentCachingRequestWrapper != null;
        byte[] contentAsByteArray = contentCachingRequestWrapper.getContentAsByteArray();
        if (contentAsByteArray.length == 0) {
            try (BufferedReader reader = contentCachingRequestWrapper.getReader()) {
                body = reader.lines().collect(Collectors.joining(""));
            }
        } else {
            body = new String(contentAsByteArray);
        }
        return JSONObject.parseObject(body).get(name);
    }

    /**
     * 是否支持該方法參數
     *
     * @param parameter 待處理的方法參數
     */
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return true;
    }

    private static class JsonArgNamedValueInfo extends NamedValueInfo {
        public JsonArgNamedValueInfo() {
            super("", false, ValueConstants.DEFAULT_NONE);
        }

        public JsonArgNamedValueInfo(JsonArg annotation) {
            super(annotation.name(), annotation.required(), annotation.defaultValue());
        }
    }
}

注意到在 resolveName() 方法中我們獲取的 request 類型是 ContentCachingRequestWrapper。

這是因為默認的 request 只能讀取一次請求體,而我們的解析器在解析每個方法參數時都需要讀取一次請求體。

包裝請求

添加過濾器將我們的請求轉換為所需要的 ContentCachingRequestWrapper。

/*
    將request包裝成ContentCachingRequest,以反復讀取請求體
 */
@Component
public class CachingRequestBodyFilter extends GenericFilterBean {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        if (servletRequest instanceof HttpServletRequest) {
            filterChain.doFilter(new ContentCachingRequestWrapper((HttpServletRequest) servletRequest), servletResponse);
        } else {
            filterChain.doFilter(servletRequest, servletResponse);
        }
    }
}

注冊解析器

最后,將自定義的解析器注冊到 Spring MVC。

@Configuration
public class SpringMvcConfig implements WebMvcConfigurer {
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new JsonArgMethodArgumentResolver());
    }
}

用法

和 @RequestParam 的用法相似。

public CommonResult<Object> signUp(
            @JsonArg(name = "uname") String username,
            @JsonArg(required = false, name = "pwd", defaultValue = "123") String password
    ) {
        log.info("[Username]: {}, [Password]: {}", username, password);
        return null;
}

到此,關于“怎么自定義@RequestBody注解獲取JSON數據”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

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

AI

赤城县| 股票| 黑龙江省| 克拉玛依市| 涡阳县| 玉门市| 绥芬河市| 洛阳市| 永登县| 当阳市| 孟州市| 林西县| 米易县| 永吉县| 雷山县| 司法| 丽江市| 高尔夫| 平阳县| 晴隆县| 曲阳县| 华安县| 泰和县| 南阳市| 瓮安县| 饶平县| 蕲春县| 福鼎市| 会同县| 阳谷县| 江陵县| 通化市| 昌吉市| 营山县| 五常市| 兴隆县| 什邡市| 黔南| 临澧县| 米泉市| 柘荣县|