@RequestMapping(value="URL", option, option)
consumes: Client에게 request를 제한하는 용도로 사용해요
Client의 header정보(Content-Type)를 토대로 제한하게 됩니다.
Data를 보내는 방식
GET 방식: url뒤에 query string으로 실어 보내는 방식
POST 방식: request body안에 들어가요
consumes를 사용하면 GET방식은 사용할 수 없어요.
Get방식은 header에 query-string으로 data가 전달되기 때문에 header의 Content-Type이 없어요
Content-type은 data가 body에 담길경우에 설정할 수 있는 header이기 때문이에요
POST를 통해서 request를 보내줬어요
기본적인 Content-type은
application/x-www-form-urlencoded였어요
내가 허락해줄 Content-type은 application/json타입 뿐이었으니까 415 error를 response했어요
RESTful 방식으로 서버를 설계하기 위해서 사용해요
Content-type: application/json등으로 Content type을 제한해서 Ajax요청으로 request를 받을 수 있게 할수 있으니까 좋아요
보통의 request는 특별한 경우가 아닌 이상 요청을 제한하는 경우가 거의 없어요.
요청을 제한하는 경우보다 요청을 처리한 다음 서버에서 데이터를 전달할 때 해당 data가 일반적인 html, json, xml인지를 정해주는 경우가 많아요.
response의 header에 data type을 정해서 알려줘요
data 형식에 따라 정해져 있는 데이터의 형식을 문자로 표현한 문자열
클라이언트에게 반환(return)하는 data의 Content type을 지정하는 역할을 합니다.
브라우저는 Data가 어떤 형식이 올지 모르니까 결과에 대한 Data형식을 파악하고 이 형식으로 Data를 적절히 처리하는 일이 필요합니다.
return 하는 data의 Content type을 지정하는(알려주는) 것이지 명시한 Data의 형식으로 data를 변환해주는 역할을 하지는 않아요!
Gson을 사용하면서 받아왔는데 이건 외부 Library이고, Stateless하니까 Bean으로 등록해서 사용해 줄꺼에요
common
LibraryComponent.java
Application Context가 스캔할 수 있도록 인식시켜줘야 해요
@Configuration을 사용해줘요
// 수동으로 Bean을 Application Context에 등록하려면.
// @Bean이라는 Annotation을 이용해야 해요
@Configuration // @Component의 하위 속성이에요
public class LibraryComponent {
}
// 수동으로 Bean을 Application Context에 등록하려면.
// @Bean이라는 Annotation을 이용해야 해요
@Configuration // @Component의 하위 속성이에요
public class LibraryComponent {
@Bean
public Gson getGson() {
return new Gson();
}
}
// 메서드의 이름 getGson이 Bean id로 등록 됩니다.
@Controller
public class RequestMapingProducesController {
Logger log = LogManager.getLogger("case3");
@Autowired
private Gson gson;
@RequestMapping(value = "testProduces4", produces = "application/json; charset=UTF-8")
public void method04(HttpServletResponse response) {
try {
response.setContentType("application/json; charset=UTF-8");
PrintWriter out = response.getWriter();
// 데이터를 만들어요
Map<String, String> map = new HashMap<String, String>();
map.put("userName","홍길동");
map.put("userAge","20");
map.put("userAddr","서울");
// 이 데이터를 JSON 문자열로 변형해야 해요
String str = gson.toJson(map);
// 그리고 나서 Stream을 통해 client에게 보내주면 됩니다.
out.println(str);
out.close();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
Bean을 수동으로 등록해주었습니다.
Autowired를 사용하지 않는 방법이에용
Spring에서 우리에게 interface를 제공 해줘요
ApplicationContextAware
구현한 구현체를 Bean으로 등록해야 해요
ApplicationContextProvider.java
@Component
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext ctx;
public static ApplicationContext getApplicationContext() {
return ctx;
}
// Spring이 관리하는 ApplicationContext가 인자로 들어오는것을 볼 수 있어요
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.ctx = applicationContext;
}
}
@RequestMapping(value = "testProduces4_1", produces = "application/json; charset=UTF-8")
public void method04_1(HttpServletResponse response) {
try {
response.setContentType("application/json; charset=UTF-8");
PrintWriter out = response.getWriter();
// 데이터를 만들어요
Map<String, String> map = new HashMap<String, String>();
map.put("userName","홍길동");
map.put("userAge","20");
map.put("userAddr","서울");
// 이 데이터를 JSON 문자열로 변형해야 해요
// String str = gson.toJson(map);
ApplicationContext ctx = ApplicationContextProvider.getApplicationContext();
Gson gson = ctx.getBean("getGson", Gson.class);
String str = gson.toJson(map);
// 그리고 나서 Stream을 통해 client에게 보내주면 됩니다.
out.println(str);
out.close();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
@RequestBody와 결합해서 사용해요
Http의 기본 통신 방식
request를 보내고 Response를 받는 아주 단순한 구조에요HttpRequest
1. Start Line: 어떤 Method를 사용하는지 알려줘요
방식: POST
URL: /springweb/aka
Http version: Http/1.1
Headers: data의 형식 등의 정보를 알려줘요
Body(Request Body): 실제 전송하는 data
HttpResponse
1. Status Line :
상태 코드: 어떤 상태로 요청이 처리되었는지 응답하는 코드 값
2. headers
3. body(Response Body)
Spring은 Request Body, Response Body를 구현합니다.
저기에 Data를 어떻게 넣을 것인지 컨트롤 해 줄 수 있어요Request Body
Request Body를 이용하면 Spring에서 Client가 Request를 보낼때 Post 방식으로 Json을 줘요.
Json방식의 Request Body를 통해서 Vo로 바로 변환할 수 있어요.(제약사항이 있어서 많이 사용되지는 않아요)Response Body
Response에 대한 정보를 내가 직접 만들어서 넣어줄 수 있어서 많이 사용되어요.
XML, Json data를 넣어서 보낼 수 있어요
Ajax구현할 때 이렇게 사용해요!
Body부분에 내가 직접 데이터를 넣을 때는 어떤 데이터를 넣는지 내가 직접 명시를 해야해요 그래서Produces
가 필요한거에용!!!
이제는 Controller가 2가지로 나뉘어요
Rest 기반의 API : 결과 Data만 보내주는 방식
기존 방식: JSP를 보내주는 방식
request를 Dispatcher Servlet이 받아서 처리해요
Dispatcher Servlet(Front Controller)
Dispacther Servlet-> Handler Mapping -> Controller
SOAP 기반의 web Service
(Simple Object Access Protocol)
이 프로토콜을 이용하면 보안, 데이터 무결성의 장점이 있어요
protocol 자체가 복잡한 단점이 있어요
Web의 CS구조와 잘 맞지 않아요
일반적인 Enterprise Application에 사용되어요
HTTP 기반의 Web Service
web의 구조와 잘 맞아서 지금도 사용되고 있습니다.
HTTP protocol의 개발자중의 한명이 protocol을 잘 사용할 수 있는 방식의 Guide를 제시하였습니다.
Architecture => REST
HTTP, Web을 조금 더 잘 사용하기 위한 Architecture
URI(Uniform Resource Identifier): 식별자
URL(Uniform Resource Locater): 위치를 식별하기 위한것
URI는 Resources를 표현하는 수단이어야 합니다.
예시 - 멤버 삭제
GET /member/delete/3 - 이건 잘못된 형태에요(동작을 지칭하면 안됩니다)
DELETE /member/3 - 이런식으로 하나의 리소스를 지칭해야 해요
URI의 마지막은 '/'로 끝나지 않아요
특수문자는 URI에 사용하면 안됩니다.
/member/student_score ( X ) 언더바
는 사용하지 않습니다
/member/student-score ( O ) '-'을 사용합니다.
소문자로 URI를 작성합니다.
확장자는 URI에 포함하지 않습니다.
/member/flower.gif ( X ) 확장자 Accept-hader에 명시
REST 원칙에 따라 서버는 Client에게 상태정보를 보내야 해요
(ex: 200, 201, 404)
@RestController
@RequestMapping(value = "/rest/user")
public class MyRestController {
Logger log = LogManager.getLogger("case3");
@GetMapping
public ResponseEntity<?> method01(String id, String name){
log.debug("GET 방식으로 호출 되었어요 ");
log.debug("id={}",id);
log.debug("name={}",name);
// 값이 제대로 들어와요
return null;
}
@DeleteMapping
public ResponseEntity<?> method02(String id, String name){
log.debug("DELETE 방식으로 호출 되었어요 ");
log.debug("id={}",id);
log.debug("name={}",name);
// null 이에요
// Data가 Body안에 들어간채로 들어와요
// Body안에 있는 Data를 꺼내는 것을 파싱이라고 하는데 파싱을 톰켓이 알아서 해줘요
// POST는 TOMCAT이 파싱을 잘해주는데
// DELETE, PUT은 TOMCAT이 파싱을 안해줘요
return null;
}
// 해결방법
// 1. 톰캣 설정 바꾸기
// 2.
}
64번째줄
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
변환하기
<Connector connectionTimeout="20000" port="8080"
parseBodyMethods="POST, PUT, DELETE" protocol="HTTP/1.1" redirectPort="8443"/>
parseBodyMethods="POST, PUT, DELETE"
추가된 부분