日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

@RequestBody、@ResponseBody的具体用法和使用时机

發布時間:2025/3/15 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 @RequestBody、@ResponseBody的具体用法和使用时机 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

引言:

接上一篇文章講述處理@RequestMapping的方法參數綁定之后,詳細介紹下@RequestBody、@ResponseBody的具體用法和使用時機;

?

簡介:

@RequestBody

作用:?

??? ? i) 該注解用于讀取Request請求的body部分數據,使用系統默認配置的HttpMessageConverter進行解析,然后把相應的數據綁定到要返回的對象上;

??? ? ii) 再把HttpMessageConverter返回的對象數據綁定到 controller中方法的參數上。

使用時機:

A) GET、POST方式提時, 根據request header Content-Type的值來判斷:

  • ??? application/x-www-form-urlencoded, 可選(即非必須,因為這種情況的數據@RequestParam, @ModelAttribute也可以處理,當然@RequestBody也能處理);
  • ??? multipart/form-data, 不能處理(即使用@RequestBody不能處理這種格式的數據);
  • ??? 其他格式, 必須(其他格式包括application/json, application/xml等。這些格式的數據,必須使用@RequestBody來處理);

B) PUT方式提交時, 根據request header Content-Type的值來判斷:

  • ??? application/x-www-form-urlencoded, 必須;
  • ??? multipart/form-data, 不能處理;
  • ??? 其他格式, 必須;

說明:request的body部分的數據編碼格式由header部分的Content-Type指定;

?

@ResponseBody

?

作用:?

? ? ? 該注解用于將Controller的方法返回的對象,通過適當的HttpMessageConverter轉換為指定格式后,寫入到Response對象的body數據區。

使用時機:

????? 返回的數據不是html標簽的頁面,而是其他某種格式的數據時(如json、xml等)使用;

?

?

HttpMessageConverter

[java]?view plaincopy

  • <span?style="font-family:Microsoft?YaHei;">/**?
  • ?*?Strategy?interface?that?specifies?a?converter?that?can?convert?from?and?to?HTTP?requests?and?responses.?
  • ?*?
  • ?*?@author?Arjen?Poutsma?
  • ?*?@author?Juergen?Hoeller?
  • ?*?@since?3.0?
  • ?*/??
  • public?interface?HttpMessageConverter<T>?{??
  • ??
  • ????/**?
  • ?????*?Indicates?whether?the?given?class?can?be?read?by?this?converter.?
  • ?????*?@param?clazz?the?class?to?test?for?readability?
  • ?????*?@param?mediaType?the?media?type?to?read,?can?be?{@code?null}?if?not?specified.?
  • ?????*?Typically?the?value?of?a?{@code?Content-Type}?header.?
  • ?????*?@return?{@code?true}?if?readable;?{@code?false}?otherwise?
  • ?????*/??
  • ????boolean?canRead(Class<?>?clazz,?MediaType?mediaType);??
  • ??
  • ????/**?
  • ?????*?Indicates?whether?the?given?class?can?be?written?by?this?converter.?
  • ?????*?@param?clazz?the?class?to?test?for?writability?
  • ?????*?@param?mediaType?the?media?type?to?write,?can?be?{@code?null}?if?not?specified.?
  • ?????*?Typically?the?value?of?an?{@code?Accept}?header.?
  • ?????*?@return?{@code?true}?if?writable;?{@code?false}?otherwise?
  • ?????*/??
  • ????boolean?canWrite(Class<?>?clazz,?MediaType?mediaType);??
  • ??
  • ????/**?
  • ?????*?Return?the?list?of?{@link?MediaType}?objects?supported?by?this?converter.?
  • ?????*?@return?the?list?of?supported?media?types?
  • ?????*/??
  • ????List<MediaType>?getSupportedMediaTypes();??
  • ??
  • ????/**?
  • ?????*?Read?an?object?of?the?given?type?form?the?given?input?message,?and?returns?it.?
  • ?????*?@param?clazz?the?type?of?object?to?return.?This?type?must?have?previously?been?passed?to?the?
  • ?????*?{@link?#canRead?canRead}?method?of?this?interface,?which?must?have?returned?{@code?true}.?
  • ?????*?@param?inputMessage?the?HTTP?input?message?to?read?from?
  • ?????*?@return?the?converted?object?
  • ?????*?@throws?IOException?in?case?of?I/O?errors?
  • ?????*?@throws?HttpMessageNotReadableException?in?case?of?conversion?errors?
  • ?????*/??
  • ????T?read(Class<??extends?T>?clazz,?HttpInputMessage?inputMessage)??
  • ????????????throws?IOException,?HttpMessageNotReadableException;??
  • ??
  • ????/**?
  • ?????*?Write?an?given?object?to?the?given?output?message.?
  • ?????*?@param?t?the?object?to?write?to?the?output?message.?The?type?of?this?object?must?have?previously?been?
  • ?????*?passed?to?the?{@link?#canWrite?canWrite}?method?of?this?interface,?which?must?have?returned?{@code?true}.?
  • ?????*?@param?contentType?the?content?type?to?use?when?writing.?May?be?{@code?null}?to?indicate?that?the?
  • ?????*?default?content?type?of?the?converter?must?be?used.?If?not?{@code?null},?this?media?type?must?have?
  • ?????*?previously?been?passed?to?the?{@link?#canWrite?canWrite}?method?of?this?interface,?which?must?have?
  • ?????*?returned?{@code?true}.?
  • ?????*?@param?outputMessage?the?message?to?write?to?
  • ?????*?@throws?IOException?in?case?of?I/O?errors?
  • ?????*?@throws?HttpMessageNotWritableException?in?case?of?conversion?errors?
  • ?????*/??
  • ????void?write(T?t,?MediaType?contentType,?HttpOutputMessage?outputMessage)??
  • ????????????throws?IOException,?HttpMessageNotWritableException;??
  • ??
  • }??
  • </span>??
  • 該接口定義了四個方法,分別是讀取數據時的 canRead(), read() 和 寫入數據時的canWrite(), write()方法。

    在使用 <mvc:annotation-driven />標簽配置時,默認配置了RequestMappingHandlerAdapter(注意是RequestMappingHandlerAdapter不是AnnotationMethodHandlerAdapter,詳情查看Spring 3.1 document “16.14?Configuring Spring MVC”章節),并為他配置了一下默認的HttpMessageConverter:

    ?

    [java]?view plaincopy

  • ByteArrayHttpMessageConverter?converts?byte?arrays.??
  • ??
  • StringHttpMessageConverter?converts?strings.??
  • ??
  • ResourceHttpMessageConverter?converts?to/from?org.springframework.core.io.Resource?for?all?media?types.??
  • ??
  • SourceHttpMessageConverter?converts?to/from?a?javax.xml.transform.Source.??
  • ??
  • FormHttpMessageConverter?converts?form?data?to/from?a?MultiValueMap<String,?String>.??
  • ??
  • Jaxb2RootElementHttpMessageConverter?converts?Java?objects?to/from?XML?—?added?if?JAXB2?is?present?on?the?classpath.??
  • ??
  • MappingJacksonHttpMessageConverter?converts?to/from?JSON?—?added?if?Jackson?is?present?on?the?classpath.??
  • ??
  • AtomFeedHttpMessageConverter?converts?Atom?feeds?—?added?if?Rome?is?present?on?the?classpath.??
  • ??
  • RssChannelHttpMessageConverter?converts?RSS?feeds?—?added?if?Rome?is?present?on?the?classpath.??
  • ?

    ByteArrayHttpMessageConverter: 負責讀取二進制格式的數據和寫出二進制格式的數據;

    ?

    StringHttpMessageConverter:?? 負責讀取字符串格式的數據和寫出二進制格式的數據;

    ?

    ResourceHttpMessageConverter:負責讀取資源文件和寫出資源文件數據;?

    FormHttpMessageConverter:?????? 負責讀取form提交的數據(能讀取的數據格式為 application/x-www-form-urlencoded,不能讀取multipart/form-data格式數據);負責寫入application/x-www-from-urlencoded和multipart/form-data格式的數據;

    ?

    MappingJacksonHttpMessageConverter:? 負責讀取和寫入json格式的數據;

    ?

    SouceHttpMessageConverter:?????????????????? 負責讀取和寫入 xml 中javax.xml.transform.Source定義的數據;

    Jaxb2RootElementHttpMessageConverter:? 負責讀取和寫入xml 標簽格式的數據;

    ?

    AtomFeedHttpMessageConverter:????????????? 負責讀取和寫入Atom格式的數據;

    RssChannelHttpMessageConverter:?????????? 負責讀取和寫入RSS格式的數據;

    ?

    當使用@RequestBody和@ResponseBody注解時,RequestMappingHandlerAdapter就使用它們來進行讀取或者寫入相應格式的數據。

    ?

    HttpMessageConverter匹配過程:

    @RequestBody注解時: 根據Request對象header部分的Content-Type類型,逐一匹配合適的HttpMessageConverter來讀取數據;

    spring 3.1源代碼如下:

    [java]?view plaincopy

  • <span?style="font-family:Microsoft?YaHei;">private?Object?readWithMessageConverters(MethodParameter?methodParam,?HttpInputMessage?inputMessage,?Class?paramType)??
  • ????????????throws?Exception?{??
  • ??
  • ????????MediaType?contentType?=?inputMessage.getHeaders().getContentType();??
  • ????????if?(contentType?==?null)?{??
  • ????????????StringBuilder?builder?=?new?StringBuilder(ClassUtils.getShortName(methodParam.getParameterType()));??
  • ????????????String?paramName?=?methodParam.getParameterName();??
  • ????????????if?(paramName?!=?null)?{??
  • ????????????????builder.append('?');??
  • ????????????????builder.append(paramName);??
  • ????????????}??
  • ????????????throw?new?HttpMediaTypeNotSupportedException(??
  • ????????????????????"Cannot?extract?parameter?("?+?builder.toString()?+?"):?no?Content-Type?found");??
  • ????????}??
  • ??
  • ????????List<MediaType>?allSupportedMediaTypes?=?new?ArrayList<MediaType>();??
  • ????????if?(this.messageConverters?!=?null)?{??
  • ????????????for?(HttpMessageConverter<?>?messageConverter?:?this.messageConverters)?{??
  • ????????????????allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());??
  • ????????????????if?(messageConverter.canRead(paramType,?contentType))?{??
  • ????????????????????if?(logger.isDebugEnabled())?{??
  • ????????????????????????logger.debug("Reading?["?+?paramType.getName()?+?"]?as?\""?+?contentType??
  • ????????????????????????????????+"\"?using?["?+?messageConverter?+?"]");??
  • ????????????????????}??
  • ????????????????????return?messageConverter.read(paramType,?inputMessage);??
  • ????????????????}??
  • ????????????}??
  • ????????}??
  • ????????throw?new?HttpMediaTypeNotSupportedException(contentType,?allSupportedMediaTypes);??
  • ????}</span>??
  • @ResponseBody注解時: 根據Request對象header部分的Accept屬性(逗號分隔),逐一按accept中的類型,去遍歷找到能處理的HttpMessageConverter;

    源代碼如下:

    [java]?view plaincopy

  • <span?style="font-family:Microsoft?YaHei;">private?void?writeWithMessageConverters(Object?returnValue,??
  • ????????????????HttpInputMessage?inputMessage,?HttpOutputMessage?outputMessage)??
  • ????????????????throws?IOException,?HttpMediaTypeNotAcceptableException?{??
  • ????????????List<MediaType>?acceptedMediaTypes?=?inputMessage.getHeaders().getAccept();??
  • ????????????if?(acceptedMediaTypes.isEmpty())?{??
  • ????????????????acceptedMediaTypes?=?Collections.singletonList(MediaType.ALL);??
  • ????????????}??
  • ????????????MediaType.sortByQualityValue(acceptedMediaTypes);??
  • ????????????Class<?>?returnValueType?=?returnValue.getClass();??
  • ????????????List<MediaType>?allSupportedMediaTypes?=?new?ArrayList<MediaType>();??
  • ????????????if?(getMessageConverters()?!=?null)?{??
  • ????????????????for?(MediaType?acceptedMediaType?:?acceptedMediaTypes)?{??
  • ????????????????????for?(HttpMessageConverter?messageConverter?:?getMessageConverters())?{??
  • ????????????????????????if?(messageConverter.canWrite(returnValueType,?acceptedMediaType))?{??
  • ????????????????????????????messageConverter.write(returnValue,?acceptedMediaType,?outputMessage);??
  • ????????????????????????????if?(logger.isDebugEnabled())?{??
  • ????????????????????????????????MediaType?contentType?=?outputMessage.getHeaders().getContentType();??
  • ????????????????????????????????if?(contentType?==?null)?{??
  • ????????????????????????????????????contentType?=?acceptedMediaType;??
  • ????????????????????????????????}??
  • ????????????????????????????????logger.debug("Written?["?+?returnValue?+?"]?as?\""?+?contentType?+??
  • ????????????????????????????????????????"\"?using?["?+?messageConverter?+?"]");??
  • ????????????????????????????}??
  • ????????????????????????????this.responseArgumentUsed?=?true;??
  • ????????????????????????????return;??
  • ????????????????????????}??
  • ????????????????????}??
  • ????????????????}??
  • ????????????????for?(HttpMessageConverter?messageConverter?:?messageConverters)?{??
  • ????????????????????allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());??
  • ????????????????}??
  • ????????????}??
  • ????????????throw?new?HttpMediaTypeNotAcceptableException(allSupportedMediaTypes);??
  • ????????}</span>??
  • ?

    補充:

    MappingJacksonHttpMessageConverter 調用了 objectMapper.writeValue(OutputStream stream, Object)方法,使用@ResponseBody注解返回的對象就傳入Object參數內。若返回的對象為已經格式化好的json串時,不使用@RequestBody注解,而應該這樣處理: 1、response.setContentType("application/json; charset=UTF-8"); 2、response.getWriter().print(jsonStr); 直接輸出到body區,然后的視圖為void。 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

    總結

    以上是生活随笔為你收集整理的@RequestBody、@ResponseBody的具体用法和使用时机的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。