REST 방식으로 제공되는 API
Repressentational State Transfer
하나의 URI가 고유한 리소스를 처리하는 공통 방식
스프링에서 모바일 기기와 연동할 때 사용
모바일 기기의 적은 네트워크 전송량
화면은 그대로 유지하면서 필요한 데이터만 전송받아 빠르게 표시
String -> text/html
pro29/src/main/java/com/myspring/pro29/ex01/TestController.java
package com.myspring.pro29.ex01;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/test/*")
public class TestController {
@RequestMapping("/hello")
public String hello() {
return "Hello REST!!";
}
}
VO -> JSON
pro29/pom.xml
...
<!-- JSON 관련 라이브러리 추가 설정 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.4</version>
</dependency>
...
pro29/src/main/java/com/myspring/pro29/ex01/TestController.java
package com.myspring.pro29.ex01;
...
@RestController
@RequestMapping("/test/*")
public class TestController {
...
@RequestMapping("/member")
public MemberVO member() {
MemberVO vo = new MemberVO();
vo.setId("hong");
vo.setPwd("1234");
vo.setName("홍길동");
vo.setEmail("hong@test.com");
return vo;
}
}
pro29/src/main/java/com/myspring/pro29/ex01/MemberVO.java
package com.myspring.pro29.ex01;
public class MemberVO {
private String id;
private String pwd;
private String name;
private String email;
@Override
public String toString() { //회원 정보 출력
String info = id+", "+ pwd+", "+ name+", "+ email;
return info;
}
/* getter/setter */
...
}
Collection -> JSON
pro29/src/main/java/com/myspring/pro29/ex01/TestController.java
package com.myspring.pro29.ex01;
...
@RestController
@RequestMapping("/test/*")
public class TestController {
...
@RequestMapping("/membersList")
public List<MemberVO> listMembers () {
List<MemberVO> list = new ArrayList<MemberVO>();
for (int i = 0; i < 10; i++) {
MemberVO vo = new MemberVO();
vo.setId("hong"+i);
vo.setPwd("123"+i);
vo.setName("홍길동"+i);
vo.setEmail("hong"+i+"@test.com");
list.add(vo);
}
return list;
}
}
Map -> JSON
pro29/src/main/java/com/myspring/pro29/ex01/TestController.java
package com.myspring.pro29.ex01;
...
@RestController
@RequestMapping("/test/*")
public class TestController {
...
@RequestMapping("/membersMap")
public Map<Integer, MemberVO> membersMap() {
Map<Integer, MemberVO> map = new HashMap<Integer, MemberVO>();
for (int i = 0; i < 10; i++) {
MemberVO vo = new MemberVO();
vo.setId("hong" + i);
vo.setPwd("123"+i);
vo.setName("홍길동" + i);
vo.setEmail("hong"+i+"@test.com");
map.put(i, vo);
}
return map;
}
}
브라우저 요청 URL 매개변수 가져오기
pro29/src/main/java/com/myspring/pro29/ex01/TestController.java
package com.myspring.pro29.ex01;
...
@RestController
@RequestMapping("/test/*")
public class TestController {
...
@RequestMapping(value= "/notice/{num}" , method = RequestMethod.GET) //num이 포함된 요청
public int notice(@PathVariable("num") int num) throws Exception { //num 처리
return num;
}
}
REST - Ajax 연동 기능
브라우저: JSON -> 컨트롤러: VO
pro29/src/main/java/com/myspring/pro29/ex01/TestController.java
JSON -> MemberVO
package com.myspring.pro29.ex01;
...
@RestController
@RequestMapping("/test/*")
public class TestController {
static Logger logger = LoggerFactory.getLogger(TestController.class);
...
@RequestMapping(value= "/info", method = RequestMethod.POST)
public void modify(@RequestBody MemberVO vo) { //자동 변환
logger.info(vo.toString());
}
}
pro29/src/main/java/com/myspring/pro29/HomeController.java
package com.myspring.pro29;
...
@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
return "JSONTest";
}
}
pro29/src/main/webapp/WEB-INF/views/JSONTest.jsp
...
<title>Home</title>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
/* JSON 회원 정보 */
$(function() {
$("#checkJson").click(function() {
var member = { id:"park", name:"박지성", pwd:"1234", email:"park@test.com" };
$.ajax({
type:"post",
url:"${contextPath}/test/info",
contentType: "application/json",
data :JSON.stringify(member),
success:function (data,textStatus) { },
error:function(data,textStatus) { alert("에러가 발생했습니다."); },
complete:function(data,textStatus) { }
});
});
});
</script>
</head>
<body>
<input type="button" id="checkJson" value="회원 정보 보내기"/><br><br>
<div id="output"></div>
</body>
</html>
컨트롤러: VO -> 브라우저: JSON
pro29/src/main/java/com/myspring/pro29/ex02/ResController.java
package com.myspring.pro29.ex02;
...
@Controller
public class ResController {
@RequestMapping(value = "/res1")
@ResponseBody
public Map<String, Object> res1() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("id", "hong");
map.put("name", "홍길동");
return map;
}
@RequestMapping(value = "/res2")
public ModelAndView res2() {
return new ModelAndView("home");
}
}
세밀한 예외 처리
http 상태코드 이용
html, js 전송 가능
pro29/src/main/java/com/myspring/pro29/ex01/TestController.java
package com.myspring.pro29.ex01;
...
@RestController
@RequestMapping("/test/*")
public class TestController {
...
@RequestMapping("/membersList2")
public ResponseEntity<List<MemberVO>> listMembers2() {
List<MemberVO> list = new ArrayList<MemberVO>();
for (int i = 0; i < 10; i++) {
MemberVO vo = new MemberVO();
vo.setId("lee" + i);
vo.setPwd("123"+i);
vo.setName("이순신" + i);
vo.setEmail("lee"+i+"@test.com");
list.add(vo);
}
return new ResponseEntity(list, HttpStatus.INTERNAL_SERVER_ERROR); //상태 코드 반환
}
@RequestMapping(value = "/res3")
public ResponseEntity res3() {
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add("Content-Type", "text/html; charset=utf-8");
/* 전송할 js 코드 */
String message = "<script>";
message += " alert('새 회원을 등록합니다.');";
message += " location.href='/pro29/test/membersList2'; ";
message += " </script>";
return new ResponseEntity(message, responseHeaders, HttpStatus.CREATED); //데이터 전달
}
}
정보 응답
100 CONTINUE
101 SWITCHING_PROTOCOL
성공 응답
200 OK
201 CREATED
202 ACCEPTED
리다이렉션 메세지
300 MULTIPLE_CHOICE
301 MOVED_PERMANENTLY
302 FOUND
303 SEE_OTHER
클라이언트 오류 응답
400 BAD_REQUEST
401 UNAUTHORIZED
403 FORBIDEN
404 NOT_FOUND
서버 오류 응답
500 INTERNAL_SERVER_ERROR
501 NOT_IMPLEMENTED
503 SERVICE_UNAVAILABLE
POST: create
GET: select
PUT: update
DELETE: delete
게시판 URL??????????
pro29/src/main/java/com/myspring/pro29/ex03/BoardController.java
package com.myspring.pro29.ex03;
...
@RestController
@RequestMapping("/boards")
public class BoardController {
static Logger logger = LoggerFactory.getLogger(BoardController.class);
@RequestMapping(value = "/all", method = RequestMethod.GET) //GET(조회), 전체 대상
public ResponseEntity<List<ArticleVO>> listArticles() {
logger.info("listArticles 메서드 호출");
List<ArticleVO> list = new ArrayList<ArticleVO>();
for (int i = 0; i < 10; i++) {
ArticleVO vo = new ArticleVO();
vo.setArticleNO(i);
vo.setWriter("이순신"+i);
vo.setTitle("안녕하세요"+i);
vo.setContent("새 상품을 소개합니다."+i);
list.add(vo);
}
return new ResponseEntity(list, HttpStatus.OK);
}
@RequestMapping(value = "/{articleNO}", method = RequestMethod.GET) //GET(조회), 전달된 번호의 글 대상
public ResponseEntity<ArticleVO> findArticle ( @PathVariable("articleNO") Integer articleNO ) {
logger.info("findArticle 메서드 호출");
ArticleVO vo = new ArticleVO();
vo.setArticleNO(articleNO);
vo.setWriter("홍길동");
vo.setTitle("안녕하세요");
vo.setContent("홍길동 글입니다");
return new ResponseEntity(vo,HttpStatus.OK);
}
@RequestMapping(value = "", method = RequestMethod.POST) //POST(생성), 전달된 JSON 객체 대상
public ResponseEntity<String> addArticle (@RequestBody ArticleVO articleVO) {
ResponseEntity<String> resEntity = null;
try {
logger.info("addArticle 메서드 호출");
logger.info(articleVO.toString());
resEntity =new ResponseEntity("ADD_SUCCEEDED",HttpStatus.OK);
} catch(Exception e) {
resEntity = new ResponseEntity(e.getMessage(),HttpStatus.BAD_REQUEST);
}
return resEntity;
}
@RequestMapping(value = "/{articleNO}", method = RequestMethod.PUT) //PUT(수정), 전달된 번호의 글 대상
public ResponseEntity<String> modArticle(@PathVariable("articleNO") Integer articleNO, @RequestBody ArticleVO articleVO) {
ResponseEntity<String> resEntity = null;
try {
logger.info("modArticle 메서드 호출");
logger.info(articleVO.toString());
resEntity = new ResponseEntity("MOD_SUCCEEDED",HttpStatus.OK);
} catch(Exception e) {
resEntity = new ResponseEntity(e.getMessage(),HttpStatus.BAD_REQUEST);
}
return resEntity;
}
@RequestMapping(value = "/{articleNO}", method = RequestMethod.DELETE) //DELETE(삭제), 전달된 번호의 글 대상
public ResponseEntity<String> removeArticle (@PathVariable("articleNO") Integer articleNO) {
ResponseEntity<String> resEntity = null;
try {
logger.info("removeArticle 메서드 호출");
logger.info(articleNO.toString());
resEntity = new ResponseEntity("REMOVE_SUCCEEDED",HttpStatus.OK);
} catch(Exception e) {
resEntity = new ResponseEntity(e.getMessage(),HttpStatus.BAD_REQUEST);
}
return resEntity;
}
}
pro29/src/main/webapp/WEB-INF/views/JSONTest2.jsp
...
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
$(function() {
$("#checkJson").click(function() {
var article = { articleNO:"114", writer:"박지성", title:"안녕하세요", content:"상품 소개 글입니다." }; //글 정보
$.ajax({
/* 생성 요청 */
type:"POST",
url:"${contextPath}/boards",
/* 수정 요청
type:"PUT",
url:"${contextPath}/boards/114", */
contentType: "application/json",
data:JSON.stringify(article), //전송 형식 JSON 지정
success:function (data,textStatus) { alert(data); },
error:function(data,textStatus) { alert("에러가 발생했습니다."); },
complete:function(data,textStatus) { }
});
});
});
</script>
</head>
<body>
<input type="button" id="checkJson" value="새글 쓰기"/><br><br>
<div id="output"></div>
</body>
*자바 웹을 다루는 기술