[spring] REST API

sang·2024년 4월 28일

REST API

REST 방식으로 제공되는 API

REST

Repressentational State Transfer
하나의 URI가 고유한 리소스를 처리하는 공통 방식
스프링에서 모바일 기기와 연동할 때 사용

모바일 페이지 특징

모바일 기기의 적은 네트워크 전송량
화면은 그대로 유지하면서 필요한 데이터만 전송받아 빠르게 표시



@RestController

문자열 전달

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 전달

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 전달

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 전달

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;
  }
}


@PathVariable

브라우저 요청 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 연동 기능

@RequestBody

브라우저: 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>

@ResponseBody

컨트롤러: 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");
  }
}


@ResponseEntity

세밀한 예외 처리
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); //데이터 전달
  }
}

HTTP 상태코드

정보 응답
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



REST 방식 URI

HTTP 메소드

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>


*자바 웹을 다루는 기술

profile
CS 메모장

0개의 댓글