// REST(Representational State Transfer) API, RESTful Service
- 웹상의 자원(문서, 이미지, 동영상, 데이터 등)을 자원명으로 표시해서 자원의 상태를 주고받는 행위
- HTTP URI를 통해서 자원을 명시하고, HTTP Method를 통해서 자원에 대한 CRUD 처리하는 방식
// 게시판 구현
1. 여태 사용한 구현 방식 > URI 표현
- 목록보기 GET http://localhost/board/list.do
- 추가하기 POST http://localhost/board/add.do
- 수정하기 POST http://localhost/board/edit.do
- 삭제하기 POST http://localhost/board/del.do
- 검색하기 GET http://localhost/board/list.do?word=검색어
2. REST 방식
- 목록보기 GET http://localhost/board
- 추가하기 POST http://localhost/board + 데이터(패킷 저장)
- 수정하기 PUT http://localhost/board/1 + 데이터(패킷 저장)
- 삭제하기 DELETE http://localhost/board/1
- 검색하기 GET http://localhost/board/검색어
// REST API 설계 규칙
1. URI에 자원을 표시한다. > 마지막 단어가 자원 표현
2. URI에 동사를 표시하지 않는다.
3. HTTP Method를 사용해서 행동을 표현한다.
a. GET : 리소스 요청
b. POST : 데이터 전달 + 서버측 생성
c. PUT : 데이터 전달 + 수정(전체 수정 > 레코드의 모든 컬럼 수정)
d. PATCH : 데이터 전달 + 수정(전체 수정 > 레코드의 일부 컬럼 수정)
e. DELETE : 데이터 삭제
4. URI + HTTP Method = REST API
5. 구분자는 '/'를 사용한다.
6. URI의 마지막에 '/'를 적지 않는다.
7. '-' 사용이 가능하다.(가끔)
8. '_' 사용하지 않는다.
9. 소문자로만 작성한다.
10. 확장자를 작성하지 않는다. > 자원명으로 끝나기 때문(확장자 의미X)
~ "com.test.domain" > BoardDTO.java
package com.test.domain;
import lombok.Data;
@Data
public class BoardDTO {
private String seq;
private String subject;
private String content;
private String regdate;
private String id;
}
~ "com.text.mapper" > BoardMapper.java
package com.test.mapper;
import java.util.List;
import com.test.domain.BoardDTO;
public interface BoardMapper {
int add(BoardDTO dto);
List<BoardDTO> list();
BoardDTO get(String seq);
int edit(BoardDTO dto);
int del(String seq);
}
~ root-context.xml > mybatis scan
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
xsi:schemaLocation="http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
<property name="driverClassName"
value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"></property>
<property name="jdbcUrl"
value="jdbc:log4jdbc:oracle:thin:@localhost:1521:xe"></property>
<property name="username" value="hr"></property>
<property name="password" value="java1234"></property>
</bean>
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource"
destroy-method="close">
<constructor-arg ref="hikariConfig"></constructor-arg>
</bean>
<bean id="sessionfactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
</bean>
<mybatis-spring:scan base-package="com.test.mapper"/>
</beans>
~ "com.test.controller" > TestController.java > add()
~ Insomnia > 게시판 글쓰기(http://localhost/rest/board) > POST
package com.test.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.test.domain.BoardDTO;
import com.test.mapper.BoardMapper;
@RestController
public class TestController {
@Autowired
private BoardMapper mapper;
//Board > CRUD
//글쓰기
//1. http://localhost/rest/board
//2. POST
//3. return int
//@RequestMapping(value="/board", method=RequestMethod.POST)
//REST 서비스 > 테스트 > 클라이언트 툴(Postman, Insomnia, VS Code, 크롬 확장 프로그램 등)
@PostMapping("/board")
public int add(@RequestBody BoardDTO dto) {
int result = mapper.add(dto);
return result;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.test.mapper.BoardMapper">
<insert id="add">
insert into tblBoard(seq, subject, content, regdate, id)
values (seqBoard.nextVal, #{subject}, #{content}, default, #{id})
</insert>
</mapper>
~ "com.test.controller" > TestController.java > list()
~ Insomnia > 게시판 목록 보기(http://localhost/rest/board) > GET
package com.test.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.test.domain.BoardDTO;
import com.test.mapper.BoardMapper;
@RestController
public class TestController {
//글쓰기
//1. http://localhost/rest/board
//2. POST
//3. return int
//@RequestMapping(value="/board", method=RequestMethod.POST)
//REST 서비스 > 테스트 > 클라이언트 툴(Postman, Insomnia, VS Code, 크롬 확장 프로그램 등)
@PostMapping("/board")
public int add(@RequestBody BoardDTO dto) {
int result = mapper.add(dto);
return result;
}
//목록 가져오기
//1. http://localhost/rest/board
//2. GET
//3. List<DTO> -> JSON 변환
@GetMapping("/board")
public List<BoardDTO> list() {
return mapper.list();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.test.mapper.BoardMapper">
<select id="list" resultType="com.test.domain.BoardDTO">
select
seq, subject, regdate, id
from tblBoard
order by seq desc
</select>
</mapper>
~ "com.test.controller" > TestController.java > edit()
~ Insomnia > 게시판 수정하기(http://localhost/rest/board/5) > PUT
package com.test.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.test.domain.BoardDTO;
import com.test.mapper.BoardMapper;
@RestController
public class TestController {
@Autowired
private BoardMapper mapper;
//글쓰기
//1. http://localhost/rest/board
//2. POST
//3. return int
//@RequestMapping(value="/board", method=RequestMethod.POST)
//REST 서비스 > 테스트 > 클라이언트 툴(Postman, Insomnia, VS Code, 크롬 확장 프로그램 등)
@PostMapping("/board")
public int add(@RequestBody BoardDTO dto) {
int result = mapper.add(dto);
return result;
}
//목록 가져오기
//1. http://localhost/rest/board
//2. GET
//3. List<DTO> -> JSON 변환
@GetMapping("/board")
public List<BoardDTO> list() {
return mapper.list();
}
//요소 수정하기
//1. http://localhost/rest/board/5
//2. PUT or PATCH(보통 PUT)
//3. return int
@PutMapping("/board/{seq}") //경로 변수(PathVariable)
public int edit(@RequestBody BoardDTO dto, @PathVariable("seq") String seq) {
dto.setSeq(seq);
return mapper.edit(dto);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.test.mapper.BoardMapper">
<update id="edit">
update tblBoard set
subject = #{subject},
content = #{content}
where seq = #{seq}
</update>
</mapper>
~ "com.test.controller" > TestController.java > del()
~ Insomnia > 게시판 삭제하기(http://localhost/rest/board/5) > DELETE
package com.test.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.test.domain.BoardDTO;
import com.test.mapper.BoardMapper;
@RestController
public class TestController {
@Autowired
private BoardMapper mapper;
//글쓰기
//1. http://localhost/rest/board
//2. POST
//3. return int
//@RequestMapping(value="/board", method=RequestMethod.POST)
//REST 서비스 > 테스트 > 클라이언트 툴(Postman, Insomnia, VS Code, 크롬 확장 프로그램 등)
@PostMapping("/board")
public int add(@RequestBody BoardDTO dto) {
int result = mapper.add(dto);
return result;
}
//목록 가져오기
//1. http://localhost/rest/board
//2. GET
//3. List<DTO> -> JSON 변환
@GetMapping("/board")
public List<BoardDTO> list() {
return mapper.list();
}
//요소 수정하기
//1. http://localhost/rest/board/5
//2. PUT or PATCH(보통 PUT)
//3. return int
@PutMapping("/board/{seq}") //경로 변수(PathVariable)
public int edit(@RequestBody BoardDTO dto, @PathVariable("seq") String seq) {
dto.setSeq(seq);
return mapper.edit(dto);
}
//삭제하기
//1. http://localhost/rest/board/6
//2. DELETE
//3. return int
@DeleteMapping("/board/{seq}")
public int del(@PathVariable("seq") String seq) {
return mapper.del(seq);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.test.mapper.BoardMapper">
<delete id="del">
delete from tblBoard
where seq = #{seq}
</delete>
</mapper>
~ "com.test.controller" > TestController.java > get()
~ Insomnia > 게시판 상세보기(http://localhost/rest/board/5) > GET
package com.test.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.test.domain.BoardDTO;
import com.test.mapper.BoardMapper;
@RestController
public class TestController {
@Autowired
private BoardMapper mapper;
//글쓰기
//1. http://localhost/rest/board
//2. POST
//3. return int
//@RequestMapping(value="/board", method=RequestMethod.POST)
//REST 서비스 > 테스트 > 클라이언트 툴(Postman, Insomnia, VS Code, 크롬 확장 프로그램 등)
@PostMapping("/board")
public int add(@RequestBody BoardDTO dto) {
int result = mapper.add(dto);
return result;
}
//목록 가져오기
//1. http://localhost/rest/board
//2. GET
//3. List<DTO> -> JSON 변환
@GetMapping("/board")
public List<BoardDTO> list() {
return mapper.list();
}
//요소 수정하기
//1. http://localhost/rest/board/5
//2. PUT or PATCH(보통 PUT)
//3. return int
@PutMapping("/board/{seq}") //경로 변수(PathVariable)
public int edit(@RequestBody BoardDTO dto, @PathVariable("seq") String seq) {
dto.setSeq(seq);
return mapper.edit(dto);
}
//삭제하기
//1. http://localhost/rest/board/6
//2. DELETE
//3. return int
@DeleteMapping("/board/{seq}")
public int del(@PathVariable("seq") String seq) {
return mapper.del(seq);
}
//상세보기
//1. http://localhost/rest/board/6
//2. GET
//3. return DTO
@GetMapping("/board/{seq}")
public BoardDTO get(@PathVariable("seq") String seq) {
return mapper.get(seq);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.test.mapper.BoardMapper">
<select id="get" resultType="com.test.domain.BoardDTO">
select
*
from tblBoard
where seq = #{seq}
</select>
</mapper>
@RestController를 사용하면 메소드마다 @ResponseBody를 붙여주지 않아도 된다.
@RequestBody 붙여주기(JSON으로 받을 때...)
'서버 > Spring' 카테고리의 다른 글
[스프링(Spring)] WebSocket (2) | 2023.06.23 |
---|---|
[Spring Security] 권한 체크 (0) | 2023.06.22 |
[Spring Security] 회원가입, 자동 로그인 (0) | 2023.06.22 |
[Spring Security] 로그인, 로그아웃, 계정 정보 (0) | 2023.06.21 |
[스프링(Spring)] 파일 업로드 / 다운로드 (0) | 2023.06.20 |