欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

自定義@RequestBody注解如何獲取JSON數(shù)據(jù)

 更新時(shí)間:2023年04月10日 14:23:42   作者:明淵陶向反01  
這篇文章主要介紹了自定義@RequestBody注解如何獲取JSON數(shù)據(jù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Spring MVC 的 @RequestBody 注解只能將請(qǐng)求體中的 JSON 數(shù)據(jù)封裝成 Bean,而無(wú)法對(duì)單一字段實(shí)施管理(例如 required、name 等屬性),這篇文章記錄了我的自定義注解 @JsonArg。

自定義注解

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

  • 設(shè)置該字段的必選性(required)
  • 設(shè)置該字段在請(qǐng)求體 JSON 中的 key 值(name、value)
  • 設(shè)置該字段的默認(rèn)值(defaultValue)

于是我們的注解類(lèi) @JsonArg 至少應(yīng)該長(zhǎng)這樣:

@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) 聲明我們需要在運(yùn)行期動(dòng)態(tài)地獲取它地信息
  • @Target(ElementType.PARAMETER) 聲明這個(gè)注解只能作用在方法參數(shù)

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

自定義解析器

單純的定義注解類(lèi)程序是無(wú)法知道我們要它做什么的,所以我們要告訴程序在遇到這個(gè)注解時(shí)該做什么。

public class JsonArgMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver {
? ? /**
? ? ?* 表示關(guān)于 namedValue 的信息,包括名稱(chēng)、是否需要它以及默認(rèn)值。
? ? ?*
? ? ?* @param parameter 待處理的方法參數(shù)
? ? ?* @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 待處理的方法參數(shù)
? ? ?* @return 解析出來(lái)的值
? ? ?*/
? ? @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);
? ? }

? ? /**
? ? ?* 是否支持該方法參數(shù)
? ? ?*
? ? ?* @param parameter 待處理的方法參數(shù)
? ? ?*/
? ? @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 類(lèi)型是 ContentCachingRequestWrapper。

這是因?yàn)槟J(rèn)的 request 只能讀取一次請(qǐng)求體,而我們的解析器在解析每個(gè)方法參數(shù)時(shí)都需要讀取一次請(qǐng)求體。

包裝請(qǐng)求

添加過(guò)濾器將我們的請(qǐng)求轉(zhuǎn)換為所需要的 ContentCachingRequestWrapper。

/*
? ? 將request包裝成ContentCachingRequest,以反復(fù)讀取請(qǐng)求體
?*/
@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);
? ? ? ? }
? ? }
}

注冊(cè)解析器

最后,將自定義的解析器注冊(cè)到 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;
}

總結(jié)

大功告成!

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java使用html2image將html生成縮略圖圖片的實(shí)現(xiàn)示例

    Java使用html2image將html生成縮略圖圖片的實(shí)現(xiàn)示例

    本文主要介紹了Java使用html2image將html生成縮略圖圖片的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-12-12
  • java實(shí)現(xiàn)快速打字游戲

    java實(shí)現(xiàn)快速打字游戲

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)快速打字游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • java判斷一個(gè)文件是否為二進(jìn)制文件的方法

    java判斷一個(gè)文件是否為二進(jìn)制文件的方法

    這篇文章主要介紹了java判斷一個(gè)文件是否為二進(jìn)制文件的方法,涉及java針對(duì)文件的讀取及編碼判斷技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07
  • 詳解Spring Boot 異步執(zhí)行方法

    詳解Spring Boot 異步執(zhí)行方法

    這篇文章主要介紹了Spring Boot 異步執(zhí)行方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • Java回調(diào)機(jī)制解讀

    Java回調(diào)機(jī)制解讀

    本文主要介紹了Java回調(diào)機(jī)制的相關(guān)知識(shí),具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-02-02
  • Spring詳細(xì)講解7種事務(wù)傳播方式

    Spring詳細(xì)講解7種事務(wù)傳播方式

    Spring事務(wù)傳播機(jī)制是指,包含多個(gè)事務(wù)的方法在相互調(diào)用時(shí),事務(wù)是如何在這些方法間傳播的。本文通過(guò)示例詳細(xì)介紹了Spring的事務(wù)傳播機(jī)制,需要的可以參考一下
    2023-01-01
  • 詳解Java如何優(yōu)雅的使用裝飾器模式

    詳解Java如何優(yōu)雅的使用裝飾器模式

    裝飾器設(shè)計(jì)模式大家肯定都聽(tīng)說(shuō)過(guò),但是有沒(méi)有使用過(guò)呢,今天本君就跟大家分享一下裝飾器模式應(yīng)該如何使用,感興趣的小伙伴可以學(xué)習(xí)一下
    2022-09-09
  • MyBatis與MyBatis-Plus的區(qū)別詳解

    MyBatis與MyBatis-Plus的區(qū)別詳解

    本文主要介紹了MyBatis與MyBatis-Plus的區(qū)別詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • Java自帶定時(shí)任務(wù)ScheduledThreadPoolExecutor實(shí)現(xiàn)定時(shí)器和延時(shí)加載功能

    Java自帶定時(shí)任務(wù)ScheduledThreadPoolExecutor實(shí)現(xiàn)定時(shí)器和延時(shí)加載功能

    今天小編就為大家分享一篇關(guān)于Java自帶定時(shí)任務(wù)ScheduledThreadPoolExecutor實(shí)現(xiàn)定時(shí)器和延時(shí)加載功能,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-12-12
  • java實(shí)現(xiàn)一個(gè)簡(jiǎn)單TCPSocket聊天室功能分享

    java實(shí)現(xiàn)一個(gè)簡(jiǎn)單TCPSocket聊天室功能分享

    這篇文章主要為大家分享了java實(shí)現(xiàn)的一個(gè)簡(jiǎn)單TCPSocket聊天室功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-04-04

最新評(píng)論