8. Cache
• 웹 서버가 응답 데이터마다 캐시 여부를 선언할 수 있어
야 한다.
Stateless
Server
Client
+
Cache
Client
+
Cache
Client
+
Cache
9. Uniform Interface
• Identification of resources (자원 식별)
• Manipulation of resource through
representations (표현을 통한 자원 처리)
• Self-descriptive messages (자기 서술적 메시지)
• HATEOAS
• 같은 인터페이스 제약에 따라 서로 일관성 있게 상호 운
영되어야한다.
10. a. Resource Identifier
• 구성 요소 사이의 상호 작용에 대한 특정 자원을 식별
• URI로 표현 (URL, URN)
• http://스프링캠프/users/kangwoo
12. c. Self-descriptive
messages
• 요청을 처리하는데 필요한 모든 정보가 포함
GET /users/kangwoo HTTP/1.1
User-Agent: Chrome/18
Host: 스프링캠프
Accept: application/xml
13. d. HATEOAS
• Hypermedia as the Engine of Application State
• State transitions (상태 전이)
StateState
State
State
Transition
Transition
Transition
14. d. HATEOAS
• 요청에 대한 응답을 링크 정보를 포함하는 형태로 표현
<사용자들 xmlns:atom=“http://www.w3.org/2005/Atom”>
<atom:link href=“http://스프링캠프/users” rel=“self />
<content>
<사용자>
<links>
<atom:link href=“http://스프링캠프/users/kangwoo” rel=“self />
<atom:link href=“http://스프링캠프/session/RWS” rel=“session />
</links>
<id>kangwoo</id>
<이름>강우</이름>
</사용자>
…
</content>
</사용자들>
15. Layered System
• 웹의 일관된 인터페이스를 사용해서 프락시 또는 게이트웨이
같은 네트워크 기반의 중간매체를 사용할 수 있어야 한다.
Stateless
Server
Client
Stateless
Server
Stateless
Server
Load
BalancerGateway
16. Code-On-Demand
• 선택사항으로 스크립트나 플러그인 같은 실행 가능한 프로그램을
클라이언트에 전송하여, 클라이언트가 실행 할 수 있도록 해야한다.
Stateless
Server
Client
!
!
!Code
18. Resource + Operation
• Resource : 자원을 나타냄. URI로 표현
• http://스프링캠프/users/kangwoo
• Operation : 자원에 대한 행위를 나타냄. Method로 표
현
• GET http://스프링캠프/users/kangwoo
• DELETE http://스프링캠프/users/kangwoo
19. Resource
• 자원을 나타내며, 각각 고유한 URI를 가지고 있다.
• http://스프링캠프/users/kangwoo
• http://스프링캠프/sessions/RWS
• URI는 사람이 이해할 수 있는 형식으로 사용한다.
• 조회시 Query Parameter를 사용할 수 있다.
• http://스프링캠프/sessions?keyword=rest
20. Operation
• HTTP Method를 사용해서 행위(CRUD)를 나타냄
• POST : 새로운 자원을 생성한다. (CREATE)
• POST http://스프링캠프/users
• GET : 자원을 조회한다. (READ)
• GET http://스프링캠프/users
• GET http://스프링캠프/users/kangwoo
21. • PUT :기존에 존재하는 자원을 수정한다. (UPDATE)
• PUT http://스프링캠프/users/kangwoo
• DELETE : 기존에 존재하는 자원을 삭제한다.
(DELETE)
• DELETE http://스프링캠프/users/kangwoo
22. Non-CRUD Operation
• 행위는 CRUD로만 이루어져 있지는 않다.
• 행위 재정의 (메일을 보낸다 -> 메일을 생성한다.)
• POST http://스프링캠프/users/kangwoo/
sendmail
• POST http://스프링캠프/users/kangwoo/
mail
• 기타 : 내부적인 표준 정의
26. URITemplate
• 하나 또는 두개 이상의 변수를 가지는 URI 서식
• http://스프링캠프/users/kangwoo
• /users/kangwoo -> /user/{id}
@RequestMapping(value = “/{id}”, method = RequestMethod.GET)
@ResponseBody
public User getUser(Model model, @PathVariable(“id”) String id) {
User user = userService.getUser(id);
return user;
}
27. ModelAndView
• 기존의 웹 애플리케이션 개발 방법과 동일
• View를 표현형식에 맞게 변경
• XmlView, JsonView
@RequestMapping(value = “/{id}”, method = RequestMethod.GET)
public String getUser(Model model, @PathVariable(“id”) String id) {
User user = userService.getUser(id);
model.addAttribute(“user”, user);
return “xmlView”;
}
28. HTTPMessageConverter
• 자바 객체와 HTTP 요청/응답 바디를 변환
• @RequestBody / @ResponseBody
• @RestController (Spring 4.0)
@RequestMapping(value = “/{id}”, method = RequestMethod.GET)
@ResponseBody
public User getUser(Model model, @PathVariable(“id”) String id) {
User user = userService.getUser(id);
return user;
}
29. HTTPMessageConverter
• @ResponseStatus
@RequestMapping(method = RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED)
@ResponseBody
public User createUser(@RequestBody User user) {
userService.createUser(user);
User selectedUser = userService.getUser(user.getId());
return user;
}
30. HTTPMessageConverter
• ResponseEntity<T>
@RequestMapping(value = “/{id}”, method = RequestMethod.GET)
public ResponseEntity<User> getUser(Model model, @PathVariable(“id”)
String id) {
User user = userService.getUser(id);
HttpHeaders responseHeader = new HttpHeaders();
…
return new ResponseEntity<User>(user, responseHeader,
HttpStatus.OK);
}
33. JSON
• Jackson 라이브러리 추가
• 설정 파일에 MessageConverter 추가
public class RestAppConfig extends WebMvcConfigurerAdapter {
@override
public void configureMessageConverters(List<HttpMessageConverter<?>>
converters) {
converters.add(mappingJacksonHttpMessageConverter());
}
@Bean
public MappingJacksonHttpMessageConverter
mappingJacksonHttpMessageConverter() {
return new MappingJackson2HttpMessageConverter();
}
}
34. JSON
• 조회
• GET http://스프링캠프/users/kangwoo
@RequestMapping(value = “/{id}”, method = RequestMethod.GET)
@ResponseBody
public User getUser(Model model, @PathVariable(“id”) String id) {
User user = userService.getUser(id);
return user;
}
35. JSON
• 등록
• POST http://스프링캠프/users
@RequestMapping(method = RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED)
@ResponseBody
public User createUser(@RequestBody User user) {
userService.createUser(user);
User selectedUser = userService.getUser(user.getId());
return user;
}
36. XML
• MarshallingHttpMessageConverter
• Spring OXM (Object Xml Mapping)
이름 구현체 참고
Castor CastorMarshaller http://www.castor.org
JAXB Jaxb2Marshaller http://jaxb.java.net
JiBix JibxMarshaller http://jibx.sourceforget.net
XmlBeans XmlBeansMarshaller http://xmlbeans.apache.org
XStream XStreamMarshaller http://xstream.codehaus.org
37. XML
• Spring OXM와 구현에 관련 라이브러리 추가
• 설정 파일에 MessageConverter 추가
@Bean
public Jaxb2Marshaller jaxb2Marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
…
return marshaller;
}
@Bean
public MarshallingHtppMessageConverter marshallingHttpMessageConverter() {
MarshallingHtppMessageConverter converter = new
MarshallingHtppMessageConverter();
converter.setMarshaller(jaxb2Marshaller());
converter.setUnmarshaller(jaxb2Marshaller());
return converter.setMarshaller
}
38. XML
• 조회
• GET http://스프링캠프/users/kangwoo
@RequestMapping(value = “/{id}”, method = RequestMethod.GET)
@ResponseBody
public User getUser(Model model, @PathVariable(“id”) String id) {
User user = userService.getUser(id);
return user;
}
39. XML
• 등록
• POST http://스프링캠프/users
@RequestMapping(method = RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED)
@ResponseBody
public User createUser(@RequestBody User user) {
userService.createUser(user);
User selectedUser = userService.getUser(user.getId());
return user;
}
40. Content Negotiation
• 하나의 자원에 대해 여러 형태의 Reprentation
• HTTP Request Header : Accept
• application/json -> json
• application/xml -> xml
42. Content Negotiation
• 설정 추가
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer)
{
configurer
.useJaf(true)
.favorPathExtention(true)
.favorParameter(false)
.ignoreAcceptHeader(false)
.defaultContentType(MediaType.APPLICATION_JSON)
.mediaType(“json”, MediaType.APPLICATION_JSON)
.mediaType(“xml”, MediaType.APPLICATION_XML);
}
43. HTTP Method Conversion
• GET, POST, PUT, DELETE 메소드
• HiddenHttpMethodFilter 클래스
• _method 값을 HTTP Method로 변환
<form method=“post”>
<input type=“hidden” name=“_method” value=“delete”>
<input type=“submit” value=“Delete User”>
</form>
<form:form method=“delete”>
<input type=“submit” value=“Delete User”>
</form:form>
44. ETag Support
• HTTP 1.1 규약에 추가된 응답 Header
• 웹 서버의 자원이 변경되었는지 확인하는 데 사용
• ETag 값이 동일하다면, 자원이 변경되지 않았음을 의미
• ShallowEtagHeaderFilter
45. Spring HATEOAS
• JAXB / JSON integration
• Link
class UserResource extends ResourceSupport {
String name;
}
UserResource resource = new UserResource();
resource.name = “kangwoo”;
resource.add(new Link(“http://스프링캠프/users/kangwoo”));
46. Spring HATEOAS
• Link Builder
@Controller
@RequestMapping(“users”)
class UserController {
@RequestMapping(value = “/{id}”, method = RequestMethod.GET)
@ResponseBody
public UserResource getUser(@PathVariable String id) { … }
}
import static org.sfw.hateoas.mvc.ControllerLinkBuilder.*;
Link link = linkTo(UserController.class).slash(“kangwoo”).withSelfRel();
Method method = UserController.class.getMethod(“getUser”, String.class);
Link link = linkTo(method, “kangwoo”).withSelfRel();
47. 예외처리
• @ControllerAdvice
@ControllerAdvice
public class RestResponseEntityExceptionHandler {
@ExceptionHandler(value = {ResourceNotFoundException})
@ResponseStatus(value = HttpStatus.NOT_FOUND)
@ResponseBody
public RestError handleResourceNotFound(ResourceNotFoundException ex) {
return new RestError(“에러 코드”,“해당 자원을 찾을 수 없습니다.”);
}
}