Spring常用注解及http數(shù)據(jù)轉(zhuǎn)換教程
注意:本節(jié)內(nèi)容需要結(jié)合spring常用注解開發(fā)一個RESTful接口示例 內(nèi)容聯(lián)合起來一起看,然后理解
一、HTTP協(xié)議的四種傳參方式
HTTP協(xié)議組成 | 協(xié)議內(nèi)容示例 | 對應(yīng)Spring注解 |
---|---|---|
path info傳參 | /articles/12 (查詢id為12的文章,12是參數(shù)) | @PathVariable |
URL Query String傳參 | /articles?id=12 | @RequestParam |
Body 傳參 | Content-Type: multipart/form-data | @RequestParam |
Body 傳參 | Content-Type: application/json,或其他自定義格式 | @RequestBody |
Headers 傳參 | @RequestHeader |
二、常用注解回顧
2.1 @RequestBody與@ResponseBody
//注意并不要求@RequestBody與@ResponseBody成對使用。 public @ResponseBody AjaxResponse saveArticle(@RequestBody ArticleVO article)
如上代碼所示:
- @RequestBody修飾請求參數(shù),注解用于接收HTTP的body,默認(rèn)是使用JSON的格式
- @ResponseBody修飾返回值,注解用于在HTTP的body中攜帶響應(yīng)數(shù)據(jù),默認(rèn)是使用JSON的格式。如果不加該注解,spring響應(yīng)字符串類型,是跳轉(zhuǎn)到模板頁面或jsp頁面的開發(fā)模式。說白了:加上這個注解你開發(fā)的是一個數(shù)據(jù)接口,不加這個注解你開發(fā)的是一個頁面跳轉(zhuǎn)控制器。
在使用@ResponseBody注解之后程序不會再走視圖解析器,也就不再做html視圖渲染,而是直接將對象以數(shù)據(jù)的形式(默認(rèn)JSON)返回給請求發(fā)送者。那么我們有一個問題:如果我們想接收或XML數(shù)據(jù)該怎么辦?我們想響應(yīng)excel的數(shù)據(jù)格式該怎么辦?我們后文來回答這個問題。
2.2. @RequestMapping注解
@RequestMapping注解是所有常用注解中,最有看點(diǎn)的一個注解,用于標(biāo)注HTTP服務(wù)端點(diǎn)。它的很多屬性對于豐富我們的應(yīng)用開發(fā)方式方法,都有很重要的作用。如:
value
: 應(yīng)用請求端點(diǎn),最核心的屬性,用于標(biāo)志請求處理方法的唯一性;
method
: HTTP協(xié)議的method類型, 如:GET、POST、PUT、DELETE等;
consumes
: HTTP協(xié)議請求內(nèi)容的數(shù)據(jù)類型(Content-Type),例如application/json, text/html;
produces
: HTTP協(xié)議響應(yīng)內(nèi)容的數(shù)據(jù)類型。下文會詳細(xì)講解。
params
: HTTP請求中必須包含某些參數(shù)值的時候,才允許被注解標(biāo)注的方法處理請求。
headers
: HTTP請求中必須包含某些指定的header值,才允許被注解標(biāo)注的方法處理請求。
@RequestMapping(value = "/article", method = POST) @PostMapping(value = "/article")
上面代碼中兩種寫法起到的是一樣的效果,也就是PostMapping等同于@RequestMapping的method等于POST。同理:@GetMapping、@PutMapping、@DeleteMapping也都是簡寫的方式。
2.3. @RestController與@Controller
@Controller
注解是開發(fā)中最常使用的注解,它的作用有兩層含義:
- 一是告訴Spring,被該注解標(biāo)注的類是一個Spring的Bean,需要被注入到Spring的上下文環(huán)境中。
- 二是該類里面所有被RequestMapping標(biāo)注的注解都是HTTP服務(wù)端點(diǎn)。
@RestController
相當(dāng)于 @Controller和@ResponseBody結(jié)合。它有兩層含義:
- 一是作為Controller的作用,將控制器類注入到Spring上下文環(huán)境,該類RequestMapping標(biāo)注方法為HTTP服務(wù)端點(diǎn)。
- 二是作為ResponseBody的作用,請求響應(yīng)默認(rèn)使用的序列化方式是JSON,而不是跳轉(zhuǎn)到j(luò)sp或模板頁面。
2.4. @PathVariable 與@RequestParam
PathVariable用于URI上的{參數(shù)},如下方法用于刪除一篇文章,其中id為文章id。如:我們的請求URL為“/article/1”,那么將匹配DeleteMapping并且PathVariable接收參數(shù)id=1。而RequestParam用于接收普通表單方式或者ajax模擬表單提交的參數(shù)數(shù)據(jù)。
@DeleteMapping("/article/{id}") public @ResponseBody AjaxResponse deleteArticle(@PathVariable Long id) { @PostMapping("/article") public @ResponseBody AjaxResponse deleteArticle(@RequestParam Long id) {
二、接收復(fù)雜嵌套對象參數(shù)
有一些朋友可能還無法理解RequestBody注解存在的真正意義,表單數(shù)據(jù)提交用RequestParam就好了,為什么還要搞出來一個RequestBody注解呢?RequestBody注解的真正意義在于能夠使用對象或者嵌套對象接收前端數(shù)據(jù)。
仔細(xì)看上面的代碼,是一個paramData對象里面包含了一個bestFriend對象。這種數(shù)據(jù)結(jié)構(gòu)使用RequestParam就無法接收了,RequestParam只能接收平面的、一對一的參數(shù)。像上文中這種數(shù)據(jù)結(jié)構(gòu)的參數(shù),就需要我們在java服務(wù)端定義兩個類,一個類是ParamData,一個類是BestFriend.
public class ParamData { private String name; private int id; private String phone; private BestFriend bestFriend; public static class BestFriend { private String address; private String sex; } }
- 注意上面代碼中省略了GET、SET方法等必要的java plain model元素。
- 注意成員變量名稱一定要和JSON屬性名稱對應(yīng)上。
- 注意接收不同類型的參數(shù),使用不同的成員變量類型
完成以上動作,我們就可以使用@RequestBody ParamData paramData
,一次性的接收以上所有的復(fù)雜嵌套對象參數(shù)了,參數(shù)對象的所有屬性都將被賦值。
三、Http數(shù)據(jù)轉(zhuǎn)換的原理
大家現(xiàn)在使用JSON都比較普遍了,其方便易用、表達(dá)能力強(qiáng),是絕大部分?jǐn)?shù)據(jù)接口式應(yīng)用的首選。那么如何響應(yīng)其他的類型的數(shù)據(jù)?其中的判別原理又是什么?下面就來給大家介紹一下:
- 當(dāng)一個HTTP請求到達(dá)時是一個InputStream,通過HttpMessageConverter轉(zhuǎn)換為java對象,從而進(jìn)行參數(shù)接收。
- 當(dāng)對一個HTTP請求進(jìn)行響應(yīng)時,我們首先輸出的是一個java對象,然后由HttpMessageConverter轉(zhuǎn)換為OutputStream輸出。
當(dāng)我們在Spring Boot應(yīng)用中集成了jackson的類庫之后,如下的一些HttpMessageConverter將會被加載。
實(shí)現(xiàn)類 | 功能說明 |
---|---|
StringHttpMessageConverter | 將請求信息轉(zhuǎn)為字符串 |
FormHttpMessageConverter | 將表單數(shù)據(jù)讀取到MultiValueMap中 |
XmlAwareFormHttpMessageConverter | 擴(kuò)展與FormHttpMessageConverter,如果部分表單屬性是XML數(shù)據(jù),可用該轉(zhuǎn)換器進(jìn)行讀取 |
ResourceHttpMessageConverter | 讀寫org.springframework.core.io.Resource對象 |
BufferedImageHttpMessageConverter | 讀寫B(tài)ufferedImage對象 |
ByteArrayHttpMessageConverter | 讀寫二進(jìn)制數(shù)據(jù) |
SourceHttpMessageConverter | 讀寫java.xml.transform.Source類型的對象 |
MarshallingHttpMessageConverter | 通過Spring的org.springframework,xml.Marshaller和Unmarshaller讀寫XML消息 |
Jaxb2RootElementHttpMessageConverter | 通過JAXB2讀寫XML消息,將請求消息轉(zhuǎn)換為標(biāo)注的XmlRootElement和XmlType連接的類中 |
MappingJacksonHttpMessageConverter | 利用Jackson開源包的ObjectMapper讀寫JSON數(shù)據(jù) |
RssChannelHttpMessageConverter | 讀寫RSS種子消息 |
AtomFeedHttpMessageConverter | 和RssChannelHttpMessageConverter能夠讀寫RSS種子消息 |
根據(jù)HTTP協(xié)議的Accept和Content-Type屬性,以及參數(shù)數(shù)據(jù)類型來判別使用哪一種HttpMessageConverter。當(dāng)使用RequestBody或ResponseBody時,再結(jié)合前端發(fā)送的Accept數(shù)據(jù)類型,會自動判定優(yōu)先使用MappingJacksonHttpMessageConverter作為數(shù)據(jù)轉(zhuǎn)換器。但是,不僅JSON可以表達(dá)對象數(shù)據(jù)類型,XML也可以。如果我們希望使用XML格式該怎么告知Spring呢,那就要使用到produces屬性了。
@GetMapping(value ="/demo",produces = MediaType.APPLICATION_XML_VALUE)
這里我們明確的告知了返回的數(shù)據(jù)類型是xml,就會使用Jaxb2RootElementHttpMessageConverter作為默認(rèn)的數(shù)據(jù)轉(zhuǎn)換器。當(dāng)然實(shí)現(xiàn)XML數(shù)據(jù)響應(yīng)比JSON還會更復(fù)雜一些,還需要結(jié)合@XmlRootElement、@XmlElement等注解實(shí)體類來使用。同理consumes屬性你是不是也會用了呢。
四、自定義HttpMessageConverter
其實(shí)絕大多數(shù)的數(shù)據(jù)格式都不需要我們自定義HttpMessageConverter,都有第三方類庫可以幫助我們實(shí)現(xiàn)(包括下文代碼中的Excel格式)。但有的時候,有些數(shù)據(jù)的輸出格式并沒有類似于Jackson這種類庫幫助我們處理,需要我們自定義數(shù)據(jù)格式。該怎么做?
下面我們就以Excel數(shù)據(jù)格式為例,寫一個自定義的HTTP類型轉(zhuǎn)換器。實(shí)現(xiàn)的效果就是,當(dāng)我們返回AjaxResponse這種數(shù)據(jù)類型的話,就自動將AjaxResponse轉(zhuǎn)成Excel數(shù)據(jù)響應(yīng)給客戶端。
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.9</version> </dependency>
@Service public class ResponseToXlsConverter extends AbstractHttpMessageConverter<AjaxResponse> { private static final MediaType EXCEL_TYPE = MediaType.valueOf("application/vnd.ms-excel"); ResponseToXlsConverter() { super(EXCEL_TYPE); } @Override protected AjaxResponse readInternal(final Class<? extends AjaxResponse> clazz, final HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { return null; } //針對AjaxResponse類型返回值,使用下面的writeInternal方法進(jìn)行消息類型轉(zhuǎn)換 @Override protected boolean supports(final Class<?> clazz) { return (AjaxResponse.class == clazz); } @Override protected void writeInternal(final AjaxResponse ajaxResponse, final HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { final Workbook workbook = new HSSFWorkbook(); final Sheet sheet = workbook.createSheet(); final Row row = sheet.createRow(0); row.createCell(0).setCellValue(ajaxResponse.getMessage()); row.createCell(1).setCellValue(ajaxResponse.getData().toString()); workbook.write(outputMessage.getBody()); } }
- 實(shí)現(xiàn)AbstractHttpMessageConverter接口
- 指定該轉(zhuǎn)換器是針對哪種數(shù)據(jù)格式的?如上文代碼中的"application/vnd.ms-excel"
- 指定該轉(zhuǎn)換器針對那些對象數(shù)據(jù)類型?如上文代碼中的supports函數(shù)
- 使用writeInternal對數(shù)據(jù)進(jìn)行輸出處理,上例中是輸出為Excel格式。
以上就是Spring常用注解及http數(shù)據(jù)轉(zhuǎn)換教程的詳細(xì)內(nèi)容,更多關(guān)于Spring注解及http數(shù)據(jù)轉(zhuǎn)換的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java多線程之 FutureTask:帶有返回值的函數(shù)定義和調(diào)用方式
這篇文章主要介紹了Java多線程之 FutureTask:帶有返回值的函數(shù)定義和調(diào)用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07JDK 5 提供的注解:Target、Inherited和Documented的區(qū)別
這篇文章主要介紹了JDK 5 提供的注解:Target、Inherited和Documented的區(qū)別,需要的朋友可以參考下2016-02-02淺談Java中OutOfMemoryError問題產(chǎn)生原因
本文主要介紹了淺談Java中OutOfMemoryError問題產(chǎn)生原因,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06Java 帶參數(shù)與帶返回值的方法的定義和調(diào)用
在java中,方法就是用來完成解決某件事情或?qū)崿F(xiàn)某個功能的辦法。方法實(shí)現(xiàn)的過程中,會包含很多條語句用于完成某些有意義的功能——通常是處理文本,控制輸入或計(jì)算數(shù)值,這篇文章我們來探究一下帶參數(shù)與帶返回值的方法的定義和調(diào)用2022-04-04解決Java導(dǎo)入excel大量數(shù)據(jù)出現(xiàn)內(nèi)存溢出的問題
今天小編就為大家分享一篇解決Java導(dǎo)入excel大量數(shù)據(jù)出現(xiàn)內(nèi)存溢出的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-06-06java根據(jù)不同的參數(shù)調(diào)用不同的實(shí)現(xiàn)類操作
這篇文章主要介紹了java根據(jù)不同的參數(shù)調(diào)用不同的實(shí)現(xiàn)類操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09Java中Controller、Service、Dao/Mapper層的區(qū)別與用法
在Java開發(fā)中,通常會采用三層架構(gòu)(或稱MVC架構(gòu))來劃分程序的職責(zé)和功能,分別是Controller層、Service層、Dao/Mapper層,本文將詳細(xì)給大家介紹了三層的區(qū)別和用法,需要的朋友可以參考下2023-05-05