2017年12月29日 星期五

JSON (Spring3.x MVC 七)

※Maven、Gradle

def jacksonVer = '2.9.3'
    
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: "${jacksonVer}"
compile group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: "${jacksonVer}"
// compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: "${jacksonVer}"
-------------------------------------------------------
<properties>
    <jacksonVer>2.9.3</jacksonVer>
</properties>
    
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${jacksonVer}</version>
</dependency>
    
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>${jacksonVer}</version>
</dependency>
    
<!-- <dependency> -->
<!-- <groupId>com.fasterxml.jackson.core</groupId> -->
<!-- <artifactId>jackson-core</artifactId> -->
<!-- <version>${jacksonVer}</version> -->
<!-- </dependency> -->

※使用 @ResponseBody、@RequestBody 註解,不用下載這些 jar 包,還是 import 的到,但是只要其中一包沒下到,執行時都會出 406

※下載 jackson-databind 就會將 3 包都一起下載了,但 jackson-annotations 居然只有 2.9.0,所以我才將 jackson-annotations 加進去



※spring 設定檔

<mvc:default-servlet-handler />
<mvc:annotation-driven />

※一定要加 annotation-driven,不然執行時也會出 406

※default-servlet-handler 視情況加,第四篇有說明



※@ResponseBody

1.將資料轉成 JSON 後,回傳給客戶端
2.只能寫在方法上


※java bean

public class Book {
    private Integer id;
    private String name;
    private Integer price;
    private Date date;
    // setter/getter...
    
    public Book() {}
    
    public Book(Integer id, String name, Integer price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }
}

※注意建構子我沒加 date


※controller

@RequestMapping("resBody")
@ResponseBody
public List<Book> json() {
    List<Book> list = new ArrayList<>();
    list.add(new Book(1, "七龍珠", 50));
    list.add(new Book(2, "寶島少年", 80));
    list.add(new Book(3, "尼羅河的女兒", 70));
    return list;
}

※不加 @ResponseBody,呼叫時會出 404


※測試

$(_ => {
    $("#btn").click(_ => {
        $.ajax({ 
            url:"ooo/xxx/resBody.mvc",
            dataType:"json",
            contentType:"application/json",
            success:function(data){
                for(d of data){
                    console.info(d.id, d.name, d.price);
                    console.info("--------------------");
                }
            }
        });
    });
});
--------------------
<input id="btn" type="button" value="click me" />

※結果會發現不加的 date 也會出現,是null


※@RequestBody

1.前端傳集合過來,可使用這個標籤來接
2.使用時一定要用 POST,否則會出 400
3.只能寫在參數裡


※controller

@ResponseBody
@RequestMapping(value = "reqBody", method = RequestMethod.POST)
public List<Book> json(@RequestBody List<Book> listBook) {
    for (Book b : listBook) {
        System.out.println(b.getId());
        System.out.println(b.getName());
        System.out.println(b.getPrice());
        System.out.println("----------");
    }
    return listBook;
}

※此功能是前端傳集合過來,然後又傳回給客戶端

※@ResponseBody 一定要有,否則無法傳回,會 404



※測試

let array=[];  
array.push({"id":"1","name":"七龍珠", "price":"50"});  
array.push({"id":"2","name":"寶島少年", "price":"80"});         
array.push({"id":"3","name":"尼羅河的女兒", "price":"70"});
    
$("#btn2").click(_ => {
    $.ajax({ 
        url:"ooo/xxx/reqBody.mvc",
        type:"POST",
        dataType:"json",
        contentType:"application/json",
        data:JSON.stringify(array),
        success:function(data){
            for(d of data){
                console.info(d.id, d.name, d.price);
                console.info("--------------------");
            }
        }
    });
});
--------------------
<input id="btn2" type="button" value="按我" />





※HttpEntity

可以塞值到 HTTP Header 裡
不用寫 <mvc:annotation-driven />,也不用下載 jackson


@RequestMapping("resEntity")
public HttpEntity<String> resEntity(HttpServletRequest req) throws IOException {
    HttpHeaders head = new HttpHeaders();
    head.set("xxx", "ooo");
    
    // HttpEntity<byte[]> he = new HttpEntity<>(head);
    HttpEntity<String> he = new HttpEntity<>("bruce", head);
    return he;
}
----------------------------------------------
<a href="ooo/xxx/resEntity.mvc?">resEntity</a>

※注解那一行只有塞到 HTTP Header 裡,沒註解那一行還多一個顯示 bruce 在畫面上



※ResponseEntity

為 HttpEntity 的子類,多個狀態碼
可實現下載功能

@RequestMapping("resEntity")
public ResponseEntity<byte[]> resEntity(HttpServletRequest req) throws IOException {
    InputStream is = req.getServletContext().getResourceAsStream("/WEB-INF/xxx.txt");
    byte[] bArray = new byte[is.available()];
    is.read(bArray);
    
    HttpHeaders head = new HttpHeaders();
    head.add("Content-Disposition", "attachment;filename=downloadName.txt");
    
    return new ResponseEntity<byte[]>(bArray, head, HttpStatus.OK);
}
----------------------------------------------
<a href="ooo/xxx/resEntity.mvc?">resEntity</a>



沒有留言:

張貼留言