最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于@RequestBody注解只能注入對(duì)象和map的解決

 更新時(shí)間:2021年10月22日 14:54:45   作者:WoddenFish  
這篇文章主要介紹了@RequestBody注解只能注入對(duì)象和map的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

@RequestBody注解只能注入對(duì)象和map的問題

前后端分離開發(fā)模式下,前后端數(shù)據(jù)交互全部采用json,所以在后端在采用spring框架的時(shí)候都會(huì)使用@ResponseBody(后端返回參數(shù)封裝為json格式)和@RequestBody(前端請(qǐng)求攜帶json參數(shù)解析)注解。

但是在實(shí)際開發(fā)中,往往@RequestBody的使用會(huì)比較令人難受(超級(jí)難受),因?yàn)樗黶pring官方只支持到將json解析為一個(gè)定義好的對(duì)象或者是一個(gè)通用性的map,而我們實(shí)際項(xiàng)目中經(jīng)常傳遞的參數(shù)僅僅是一個(gè)或者是兩個(gè)參數(shù),這樣的參數(shù)封裝程對(duì)象總是有點(diǎn)大材小用的感覺,并且還消耗性能,而使用map又感覺操作比較繁瑣,那這樣的話可不可以使用簡(jiǎn)單的類似于@PathVariable(value="")這樣的模式取請(qǐng)求數(shù)據(jù)呢????當(dāng)然可以??!

1、自定義一個(gè)適應(yīng)于這種情況的注解@RequestJson

package cn.annotation; 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; 
/**
 * Title:      RequestJson
 * @date       2018年9月10日
 * @version    V1.0
 * Description: 自定義請(qǐng)求json數(shù)據(jù)解析注解(主要解決單參數(shù)傳遞)
 */
@Target(ElementType.PARAMETER)//使用在參數(shù)上
@Retention(RetentionPolicy.RUNTIME)//運(yùn)行時(shí)注解
public @interface RequestJson {
    /**
     * 是否必須出現(xiàn)的參數(shù)
     */
    boolean required() default true;
 
    /**
     * 當(dāng)value的值或者參數(shù)名不匹配時(shí),是否允許解析最外層屬性到該對(duì)象
     */
    boolean parseAllFields() default true;
 
    /**
     * 解析時(shí)用到的JSON的key
     */
    String value() default "";
}

2、自定義RequestJsonHandlerMethodArgumentResolver

實(shí)現(xiàn)HandlerMethodArgumentResolver(spring解析數(shù)據(jù)的接口)

package cn.config; 
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; 
import cn.annotation.RequestJson; 
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer; 
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Set;
 
/**
 * Title:      RequestJsonHandlerMethodArgumentResolver
 * @date       2018年9月10日
 * @version    V1.0
 * Description: 自定義解析json數(shù)據(jù)
 */
public class RequestJsonHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
 private static final String JSONBODY_ATTRIBUTE = "JSON_REQUEST_BODY";
  
    /**
     * 設(shè)置支持的方法參數(shù)類型
     * @param parameter 方法參數(shù)
     * @return 支持的類型
     */
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        // 支持帶@RequestJson注解的參數(shù)
        return parameter.hasParameterAnnotation(RequestJson.class);
    }
 
    /**
     * 參數(shù)解析,利用fastjson
     * 注意:非基本類型返回null會(huì)報(bào)空指針異常,要通過反射或者JSON工具類創(chuàng)建一個(gè)空對(duì)象
     */
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
 
        String jsonBody = getRequestBody(webRequest);
 
        JSONObject jsonObject = JSON.parseObject(jsonBody);
        // 根據(jù)@RequestJson注解value作為json解析的key
        RequestJson parameterAnnotation = parameter.getParameterAnnotation(RequestJson.class);
        //注解的value是JSON的key
        String key = parameterAnnotation.value();
        Object value = null;
        // 如果@RequestJson注解沒有設(shè)置value,則取參數(shù)名FrameworkServlet作為json解析的key
        if (StringUtils.isNotEmpty(key)) {
            value = jsonObject.get(key);
            // 如果設(shè)置了value但是解析不到,報(bào)錯(cuò)
            if (value == null && parameterAnnotation.required()) {
                throw new IllegalArgumentException(String.format("required param %s is not present", key));
            }
        } else {
            // 注解為設(shè)置value則用參數(shù)名當(dāng)做json的key
            key = parameter.getParameterName();
            value = jsonObject.get(key);
        }
 
 
        Class<?> parameterType = parameter.getParameterType();
        // 通過注解的value或者參數(shù)名解析,能拿到value進(jìn)行解析
        if (value != null) {
            if (isBasicDataTypes(parameterType)) {
                return value;
            }
            return JSON.parseObject(value.toString(), parameterType);
        }
 
        // 解析不到則將整個(gè)json串解析為當(dāng)前參數(shù)類型
        if (isBasicDataTypes(parameterType)) {
            if (parameterAnnotation.required()) {
                throw new IllegalArgumentException(String.format("required param %s is not present", key));
            } else {
                return null;
            }
        }
 
        Object result = parameterType.newInstance();
        // 非基本類型,不允許解析所有字段,返回null
        if (!parameterAnnotation.parseAllFields()) {
            // 如果是必傳參數(shù)拋異常
            if (parameterAnnotation.required()) {
                throw new IllegalArgumentException(String.format("required param %s is not present", key));
            }
            // 否則返回空對(duì)象
            return result;
        }
       // 非基本類型,允許解析,將外層屬性解析
        result = JSON.parseObject(jsonObject.toString(), parameterType);
        // 如果非必要參數(shù)直接返回,否則如果沒有一個(gè)屬性有值則報(bào)錯(cuò)
        if (!parameterAnnotation.required()) {
                return result;
        }else{
            boolean haveValue = false;
            Field[] declaredFields = parameterType.getDeclaredFields();
            for(Field field : declaredFields){
                field.setAccessible(true);
                if(field.get(result) != null){
                    haveValue = true;
                    break;
                }
            }
            if(!haveValue){
                throw new IllegalArgumentException(String.format("required param %s is not present", key));
            }
            return result;
        }
    }
 
    /**
     * 基本數(shù)據(jù)類型直接返回
     */
    @SuppressWarnings("rawtypes")
    private boolean isBasicDataTypes(Class clazz) {
  Set<Class> classSet = new HashSet<>();
        classSet.add(String.class);
        classSet.add(Integer.class);
        classSet.add(Long.class);
        classSet.add(Short.class);
        classSet.add(Float.class);
        classSet.add(Double.class);
        classSet.add(Boolean.class);
        classSet.add(Character.class);
        return classSet.contains(clazz);
    }
 
    /**
     * 獲取請(qǐng)求體JSON字符串
     */
    private String getRequestBody(NativeWebRequest webRequest) {
        HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
 
        // 有就直接獲取
        String jsonBody = (String) webRequest.getAttribute(JSONBODY_ATTRIBUTE, NativeWebRequest.SCOPE_REQUEST);
        // 沒有就從請(qǐng)求中讀取
        if (jsonBody == null) {
            try {
                jsonBody = IOUtils.toString(servletRequest.getReader());
                webRequest.setAttribute(JSONBODY_ATTRIBUTE, jsonBody, NativeWebRequest.SCOPE_REQUEST);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return jsonBody;
 }
}

3、將上述配置應(yīng)用到spring項(xiàng)目中

重寫addArgumentResolvers方法

package cn.config; 
import java.nio.charset.Charset;
import java.util.List; 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
 
/**
 * Title:      WebConfig
 * @date       2018年9月10日
 * @version    V1.0
 * Description: 將自定義注解配置到spring
 */
 
@Configuration
@SuppressWarnings("deprecation")
public class WebConfig extends WebMvcConfigurerAdapter{
 @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new RequestJsonHandlerMethodArgumentResolver());
    }
 
    @Bean
    public HttpMessageConverter<String> responseBodyConverter() {
        return new StringHttpMessageConverter(Charset.forName("UTF-8"));
    }
 
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        super.configureMessageConverters(converters);
        converters.add(responseBodyConverter());
    }
}

4、配置完成了,簡(jiǎn)單使用

單參數(shù):(不加value默認(rèn)為參數(shù)名)

或者:

多參數(shù):

@RequestBody注解的使用問題

今天遇到的問題:@RequestBody的使用問題

先看一下@RequestBody的作用

在這里插入圖片描述

我想獲取json字符串某個(gè)字段值,看截圖:

在這里插入圖片描述

看一下控制臺(tái)的輸出信息:

在這里插入圖片描述

what ?這什么情況,為什么拿到的是整個(gè)json字符串,然后我繼續(xù)測(cè)試

在這里插入圖片描述

給了一個(gè)400

在這里插入圖片描述

what ?這又是什么情況 (好像只能有一個(gè)@RequestBody)我想?yún)?shù)如果是整形的話能不能獲取,我繼續(xù)進(jìn)行測(cè)試代碼:

在這里插入圖片描述

傳參:

在這里插入圖片描述

又給了一個(gè)400 (好像只能是String類型) 測(cè)試引用類型對(duì)象

在這里插入圖片描述

代碼:

在這里插入圖片描述

傳參:

在這里插入圖片描述

控制臺(tái)打?。?/p>

在這里插入圖片描述

測(cè)試成功。

個(gè)人總結(jié):

1) 一個(gè)方法只能有一個(gè)@RequestBody

2) 如果接收參數(shù)是字符串類型的,獲取的是整個(gè)json字符串

3) 如果接受的參數(shù)是引用對(duì)象,@requestBody User user 會(huì)將json字符串中的值賦予user中對(duì)應(yīng)的屬性上

需要注意的是,json字符串中key必須和User對(duì)象的屬性名對(duì)應(yīng)

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

相關(guān)文章

  • SpringBoot?DataSource數(shù)據(jù)源實(shí)現(xiàn)自動(dòng)配置流程詳解

    SpringBoot?DataSource數(shù)據(jù)源實(shí)現(xiàn)自動(dòng)配置流程詳解

    這篇文章主要介紹了SpringBoot?DataSource數(shù)據(jù)源實(shí)現(xiàn)自動(dòng)配置流程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2022-10-10
  • 解決Spring session(redis存儲(chǔ)方式)監(jiān)聽導(dǎo)致創(chuàng)建大量redisMessageListenerContailner-X線程問題

    解決Spring session(redis存儲(chǔ)方式)監(jiān)聽導(dǎo)致創(chuàng)建大量redisMessageListenerConta

    這篇文章主要介紹了解決Spring session(redis存儲(chǔ)方式)監(jiān)聽導(dǎo)致創(chuàng)建大量redisMessageListenerContailner-X線程問題,需要的朋友可以參考下
    2018-08-08
  • SpringBoot基于Sentinel在服務(wù)上實(shí)現(xiàn)接口限流

    SpringBoot基于Sentinel在服務(wù)上實(shí)現(xiàn)接口限流

    這篇文章主要介紹了SpringBoot基于Sentinel在服務(wù)上實(shí)現(xiàn)接口限流,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-10-10
  • Java雜談之如何優(yōu)化寫出漂亮高效的代碼

    Java雜談之如何優(yōu)化寫出漂亮高效的代碼

    不一致的代碼會(huì)造成認(rèn)知上的負(fù)擔(dān),在一個(gè)系統(tǒng)中,做類似的事情,卻有不同的做法,或者起到類似作用的事物,卻有不同的名字,讓人困惑
    2021-09-09
  • 簡(jiǎn)單了解Java方法的定義和使用實(shí)現(xiàn)

    簡(jiǎn)單了解Java方法的定義和使用實(shí)現(xiàn)

    這篇文章主要給大家介紹了關(guān)于Java中方法使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-06-06
  • Java并發(fā)編程-volatile可見性詳解

    Java并發(fā)編程-volatile可見性詳解

    這篇文章主要介紹了Java并發(fā)編程-volatile可見性詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • Mybatis查詢條件包含List的情況說明

    Mybatis查詢條件包含List的情況說明

    這篇文章主要介紹了Mybatis 查詢條件包含List的情況,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 解決Lombok注解不起作用的問題

    解決Lombok注解不起作用的問題

    這篇文章主要介紹了解決Lombok注解不起作用的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java使用BigDecimal進(jìn)行運(yùn)算封裝的實(shí)際案例

    Java使用BigDecimal進(jìn)行運(yùn)算封裝的實(shí)際案例

    今天小編就為大家分享一篇關(guān)于Java使用BigDecimal進(jìn)行運(yùn)算封裝的實(shí)際案例,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-12-12
  • 使用IDEA搭建ssm框架的詳細(xì)圖文教程

    使用IDEA搭建ssm框架的詳細(xì)圖文教程

    這篇文章主要介紹了使用IDEA搭建ssm框架的詳細(xì)教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09

最新評(píng)論

合江县| 建始县| 杭锦后旗| 广元市| 星座| 尉氏县| 丰原市| 扎鲁特旗| 双峰县| 文山县| 洛扎县| 柞水县| 米泉市| 疏勒县| 吉木乃县| 清原| 沧州市| 凌海市| 宜兰市| 汉中市| 大新县| 桂东县| 福安市| 翁牛特旗| 毕节市| 万山特区| 达拉特旗| 衡阳市| 通化县| 门头沟区| 谢通门县| 凌云县| 讷河市| 临沧市| 凤山市| 调兵山市| 湘乡市| 皋兰县| 积石山| 乌兰浩特市| 昌平区|