首頁 > 軟體

Spring常用註解及http資料轉換教學

2022-03-17 19:00:20

注意:本節內容需要結合spring常用註解開發一個RESTful介面範例 內容聯合起來一起看,然後理解

一、HTTP協定的四種傳參方式

HTTP協定組成協定內容範例對應Spring註解
path info傳參/articles/12 (查詢id為12的文章,12是引數)@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修飾請求引數,註解用於接收HTTP的body,預設是使用JSON的格式
  • @ResponseBody修飾返回值,註解用於在HTTP的body中攜帶響應資料,預設是使用JSON的格式。如果不加該註解,spring響應字串型別,是跳轉到模板頁面或jsp頁面的開發模式。說白了:加上這個註解你開發的是一個資料介面,不加這個註解你開發的是一個頁面跳轉控制器。

在使用@ResponseBody註解之後程式不會再走檢視解析器,也就不再做html檢視渲染,而是直接將物件以資料的形式(預設JSON)返回給請求傳送者。那麼我們有一個問題:如果我們想接收或XML資料該怎麼辦?我們想響應excel的資料格式該怎麼辦?我們後文來回答這個問題。

2.2. @RequestMapping註解

@RequestMapping註解是所有常用註解中,最有看點的一個註解,用於標註HTTP伺服器端點。它的很多屬性對於豐富我們的應用開發方式方法,都有很重要的作用。如:

value: 應用請求端點,最核心的屬性,用於標誌請求處理方法的唯一性;

method: HTTP協定的method型別, 如:GET、POST、PUT、DELETE等;

consumes: HTTP協定請求內容的資料型別(Content-Type),例如application/json, text/html;

produces: HTTP協定響應內容的資料型別。下文會詳細講解。

params: HTTP請求中必須包含某些引數值的時候,才允許被註解標註的方法處理請求。

headers: HTTP請求中必須包含某些指定的header值,才允許被註解標註的方法處理請求。

@RequestMapping(value = "/article", method = POST)
@PostMapping(value = "/article")

上面程式碼中兩種寫法起到的是一樣的效果,也就是PostMapping等同於@RequestMapping的method等於POST。同理:@GetMapping、@PutMapping、@DeleteMapping也都是簡寫的方式。

2.3. @RestController與@Controller

@Controller註解是開發中最常使用的註解,它的作用有兩層含義:

  • 一是告訴Spring,被該註解標註的類是一個Spring的Bean,需要被注入到Spring的上下文環境中。
  • 二是該類裡面所有被RequestMapping標註的註解都是HTTP伺服器端點。

@RestController相當於 @Controller和@ResponseBody結合。它有兩層含義:

  • 一是作為Controller的作用,將控制器類注入到Spring上下文環境,該類RequestMapping標註方法為HTTP伺服器端點。
  • 二是作為ResponseBody的作用,請求響應預設使用的序列化方式是JSON,而不是跳轉到jsp或模板頁面。

2.4. @PathVariable 與@RequestParam

PathVariable用於URI上的{引數},如下方法用於刪除一篇文章,其中id為文章id。如:我們的請求URL為“/article/1”,那麼將匹配DeleteMapping並且PathVariable接收引數id=1。而RequestParam用於接收普通表單方式或者ajax模擬表單提交的引數資料。

@DeleteMapping("/article/{id}")
public @ResponseBody AjaxResponse deleteArticle(@PathVariable Long id) {
@PostMapping("/article")
public @ResponseBody AjaxResponse deleteArticle(@RequestParam Long id) {

二、接收復雜巢狀物件引數

有一些朋友可能還無法理解RequestBody註解存在的真正意義,表單資料提交用RequestParam就好了,為什麼還要搞出來一個RequestBody註解呢?RequestBody註解的真正意義在於能夠使用物件或者巢狀物件接收前端資料。

仔細看上面的程式碼,是一個paramData物件裡面包含了一個bestFriend物件。這種資料結構使用RequestParam就無法接收了,RequestParam只能接收平面的、一對一的引數。像上文中這種資料結構的引數,就需要我們在java伺服器端定義兩個類,一個類是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屬性名稱對應上。
  • 注意接收不同型別的引數,使用不同的成員變數型別

完成以上動作,我們就可以使用@RequestBody ParamData paramData,一次性的接收以上所有的複雜巢狀物件引數了,引數物件的所有屬性都將被賦值。

三、Http資料轉換的原理

大家現在使用JSON都比較普遍了,其方便易用、表達能力強,是絕大部分資料介面式應用的首選。那麼如何響應其他的型別的資料?其中的判別原理又是什麼?下面就來給大家介紹一下:

  • 當一個HTTP請求到達時是一個InputStream,通過HttpMessageConverter轉換為java物件,從而進行引數接收。
  • 當對一個HTTP請求進行響應時,我們首先輸出的是一個java物件,然後由HttpMessageConverter轉換為OutputStream輸出。

當我們在Spring Boot應用中整合了jackson的類庫之後,如下的一些HttpMessageConverter將會被載入。

實現類功能說明
StringHttpMessageConverter將請求資訊轉為字串
FormHttpMessageConverter將表單資料讀取到MultiValueMap中
XmlAwareFormHttpMessageConverter擴充套件與FormHttpMessageConverter,如果部分表單屬性是XML資料,可用該轉換器進行讀取
ResourceHttpMessageConverter讀寫org.springframework.core.io.Resource物件
BufferedImageHttpMessageConverter讀寫BufferedImage物件
ByteArrayHttpMessageConverter讀寫二進位制資料
SourceHttpMessageConverter讀寫java.xml.transform.Source型別的物件
MarshallingHttpMessageConverter通過Spring的org.springframework,xml.Marshaller和Unmarshaller讀寫XML訊息
Jaxb2RootElementHttpMessageConverter通過JAXB2讀寫XML訊息,將請求訊息轉換為標註的XmlRootElement和XmlType連線的類中
MappingJacksonHttpMessageConverter利用Jackson開源包的ObjectMapper讀寫JSON資料
RssChannelHttpMessageConverter讀寫RSS種子訊息
AtomFeedHttpMessageConverter和RssChannelHttpMessageConverter能夠讀寫RSS種子訊息

根據HTTP協定的Accept和Content-Type屬性,以及引數資料型別來判別使用哪一種HttpMessageConverter。當使用RequestBody或ResponseBody時,再結合前端傳送的Accept資料型別,會自動判定優先使用MappingJacksonHttpMessageConverter作為資料轉換器。但是,不僅JSON可以表達物件資料型別,XML也可以。如果我們希望使用XML格式該怎麼告知Spring呢,那就要使用到produces屬性了。

@GetMapping(value ="/demo",produces = MediaType.APPLICATION_XML_VALUE)

這裡我們明確的告知了返回的資料型別是xml,就會使用Jaxb2RootElementHttpMessageConverter作為預設的資料轉換器。當然實現XML資料響應比JSON還會更復雜一些,還需要結合@XmlRootElement、@XmlElement等註解實體類來使用。同理consumes屬性你是不是也會用了呢。

四、自定義HttpMessageConverter

其實絕大多數的資料格式都不需要我們自定義HttpMessageConverter,都有第三方類庫可以幫助我們實現(包括下文程式碼中的Excel格式)。但有的時候,有些資料的輸出格式並沒有類似於Jackson這種類庫幫助我們處理,需要我們自定義資料格式。該怎麼做?

下面我們就以Excel資料格式為例,寫一個自定義的HTTP型別轉換器。實現的效果就是,當我們返回AjaxResponse這種資料型別的話,就自動將AjaxResponse轉成Excel資料響應給使用者端。

<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方法進行訊息型別轉換
    @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());
    }
}
  • 實現AbstractHttpMessageConverter介面
  • 指定該轉換器是針對哪種資料格式的?如上文程式碼中的"application/vnd.ms-excel"
  • 指定該轉換器針對那些物件資料型別?如上文程式碼中的supports函數
  • 使用writeInternal對資料進行輸出處理,上例中是輸出為Excel格式。

以上就是Spring常用註解及http資料轉換教學的詳細內容,更多關於Spring註解及http資料轉換的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com