bboks.net™

Java Ext JS를 이용한 RESTful 구현 본문

Java/Java

Java Ext JS를 이용한 RESTful 구현

bboks.net 2012. 11. 1. 14:34

1. STS(Spring Tool Suite)에서 Spring MVC 프로젝트를 생성한다.


2. Ext JS RESTful 예제 사이트를 참고해 필요한 시타일시트와 스크립트 파일을 준비한다.

필요한 스타일시트 파일

ext-all.css
example.css
restful.css

필요한 자바스크립트 파일

ext-all.js
examples.js
restful.js


3. 필요한 시타일시트와 스크립트 파일을 Home.jsp에 링크한다.

restful.js는 파일을 링크를 하던지 아니면 페이지내에 직접 작성한다.


4. Ext.define 메소드를 이용해 원하는 객체 이름과 컬럼을 구성한다.

Ext.define('Book', {
        extend : 'Ext.data.Model',
        fields : [ {
            name : 'id',
            type : 'int',
            useNull : true
        }, 'isbn', 'title', 'writer' ],
        validations : [ {
            type : 'length',
            field : 'isbn',
            min : 1
        }, {
            type : 'length',
            field : 'title',
            min : 1
        }, {
            type : 'length',
            field : 'writer',
            min : 1
        } ]
    });


5. Ext.onReady의 url을 컨트롤러의 url 패턴을 연결한다.

Ext.onReady(function() {
        var store = Ext.create('Ext.data.Store', {
            autoLoad : true,
            autoSync : true,
            model : 'Book',
            proxy : {
                type : 'rest',
                url : 'book',
                reader : {
                    type : 'json',
                    root : 'data' //Controller에서 반환하는 JSON의 root명
                },
                writer : {
                    type : 'json'
                }
            }
        });


6. 행을 추가하는 메소드의 파라미터를 앞서 정의한 타입으로 변경한다.

text : 'Add',
iconCls : 'icon-add',
handler : function() {
    // empty record
    store.insert(0, new Book());
    rowEditing.startEdit(0, 0);
}


7. 서버에서 상태를 저장을 위해 클래스를 추가한다.

package net.bboks.app.model;

public class Book {
    int id;
    String isbn;
    String title;
    String writer;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getIsbn() {
        return isbn;
    }

    public void setIsbn(String isbn) {
        this.isbn = isbn;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getWriter() {
        return writer;
    }

    public void setWriter(String writer) {
        this.writer = writer;
    }
}


8. REST 요청을 받기위한 컨트롤러를 작성한다.
Spring MVC 프로젝트 생성시 제공하는 컨트롤러에 REST를 처리하는 메소드를 추가한다.

8.1 GET

@RequestMapping(value = "/book", method = RequestMethod.GET)
public void getBooks(HttpServletResponse response) {
    //JSON 형태로 리턴하기 위해 JSONObject와 JSONArray를 사용한다
    JSONObject obj = new JSONObject();
   
    try {
        JSONArray array = new JSONArray();
       
        for(int i=0; i<books.size(); i++) {
            JSONObject obj2 = new JSONObject();
            obj2.put("id", books.get(i).getId());
            obj2.put("isbn", books.get(i).getIsbn());
            obj2.put("title", books.get(i).getTitle());
            obj2.put("writer", books.get(i).getWriter());
           
            array.put(obj2);
        }
       
        obj.put("data", array);
       
        response.setContentType("text/html; charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println(obj.toString());
    }
    catch(Exception ex) {
       
    }
}


8.2 POST

//Ext Js의 POST의 경우 RequestBody에 실려 전송되기 때문에 RequestBody 전체를 받는다
@RequestMapping(value = "/book", method = RequestMethod.POST)
public void postBook(@RequestBody String body, HttpServletResponse response) {
    //전송된 JSON을 Book 객체로 바로 변환하기 위해 Jackson의 ObjectMapper를 이용한다.
    ObjectMapper mapper = new ObjectMapper();
   
    try {
        Book book = mapper.readValue(body, Book.class);
        book.setId(seq++);
       
        books.add(book);
       
        writeResponse(book, response);
    }
    catch(Exception ex) {
       
    }
}


8.3 DELETE

//DELETE의 경우 Key로 지정한 값만 전송된다.
@RequestMapping(value = "/book/{id}", method = RequestMethod.DELETE)
public void deleteBook(@PathVariable int id) {
    for(int i=0; i<books.size(); i++) {
        if(books.get(i).getId() == id) {
            books.remove(i);
            break;
        }
    }
}


8.4 PUT

//PUT의 경우 POST와 동일하게 JSON은 RequestBody에 실려 전송이 되며, 더불어 Key이 동시에 전송된다.
@RequestMapping(value = "/book/{id}", method = RequestMethod.PUT)
public void updateBook(@PathVariable int id, @RequestBody String body, HttpServletResponse response) {
    ObjectMapper mapper = new ObjectMapper();
   
    try {
        Book book = mapper.readValue(body, Book.class);
       
        Book targetBook = findBook(id);
       
        targetBook.setIsbn(book.getIsbn());
        targetBook.setTitle(book.getTitle());
        targetBook.setWriter(book.getWriter());
       
        writeResponse(targetBook, response);
    }
    catch(Exception ex) {
       
    }
}


주의할 점은 REST를 호출 후 JSON 형태의 Response를 전달해줘야 클라이언트와 sync가 되며, JSON의 구조는  Ext.create 메소드의 Root 명을 포함해야한다.

기타 유틸 메소드

//ArrayList에서 id에 해당하는 Book 객체를 찾아 반환한다.
private Book findBook(int id) {
    Book book = null;
   
    for(int i=0; i<books.size(); i++) {
        if(books.get(i).getId() == id) {
            book = books.get(i);
        }
    }
   
    return book;
}

//Book 객체를 이용해 Ext JS에 정의된 JSON 형태로 만들어 HttpServletResponse을 이용해 반환한다.
private void writeResponse(Book book, HttpServletResponse response) {
    try {
        JSONObject obj = new JSONObject();
       
        JSONArray array = new JSONArray();
        JSONObject obj2 = new JSONObject();
        obj2.put("id", book.getId());
        obj2.put("isbn", book.getIsbn());
        obj2.put("title", book.getTitle());
        obj2.put("writer", book.getWriter());
       
        array.put(obj2);
       
        obj.put("data", array);
       
        response.setContentType("text/html; charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println(obj.toString());
    }
    catch(Exception ex) {
       
    }
}


[참고] Rest Proxy Example