API 문서
//목적: 음식 레시피를 응답해주는 서버(GET)
목적: 음식 레시피를 저장(POST)
요청 주소
localhost:8080/blog/test
요청메서드
POST
요청 데이터
키 food
값 (마음대로)
키 method
값 (음식레시피)
요청 데이터의 Content-Type : x-www-form-unlencoded
-> 이게 안필요하면 쿼리 스트링으로 보내는것 (GET방식)
-> 이게 필요하면 요청시 데이터를 바디로 보내라는 것
x-www-form-unlencoded이면 바디에 데이터를 보내야 한다.
이게 안적혀있으면 쿼리스트링으로 보내면 된다.
응답데이터
기본적으로 톰캣의 전략은 text/html으로 응답해서 이를 적어놔야 함
1) text/plain (그냥 평문(예.안녕)으로 보내겠다)
- 알려줘야 할것
응답결과 1 정상
2 실패
2) application/json
응답결과 DB에 insert된 레코드
(food, method)
정상이면 들어간 데이터 출력
{"food": ,"method": }
실패
{"error":"fail"}
(만약 {"error":200}와 같이 에러코드로 표시된다면 Api문서에 100: 정상, 200: 실패, 300: ~~ 와 같은 정보를 다 적어줘야 한다. )
package com.cos.blog.test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//web.xml에 서블릿 맵핑을 따로 안해도 됨 -> 이미 필터가 @WebServlet 이라는 어노테이션 분석해서 서블릿 맵핑을 해주었을 것 = 리플렉션
//localhost:8080/blog/test 로 들어오면 여기로 들어와짐 (Get, Post)
@WebServlet("/test")
public class ApiServerTest extends HttpServlet {
private static final long serialVersionUID = 1L;
public ApiServerTest() {
super();
}
//Get방식으로 들어오면 이 함수 동작 -> 함수의 파라미터를 분석해서 톰캣이 request,response객체를 주입해준 것이다.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response); //Get방식도 되게 하려면
}
//Post방식으로 들어오면 이 함수 동작
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// request.getContentType(); // 할 필요가 없음 -> 왜? 이미 x-www-form-unlencoded로 보내라고 알려줬음
String mime = request.getContentType();
System.out.println(mime);
request.setCharacterEncoding("UTF-8"); //이부분은 나중에 필터에 걸면 된다.
// 이렇게 Content-Type을 분리해놓는 경우는 없음 -> Api문서에 요청할때 json으로 보내라고 적어놔야 한다. -> 그래서 Api문서가 필요하다.
if(mime.equals("application/json")) {
BufferedReader br = request.getReader();
String input;
StringBuffer buffer = new StringBuffer();
while((input = br.readLine()) != null) {
buffer.append(input);
}
System.out.println(buffer.toString());
}else { // x-www-form-unlencoded 로 받음
String food = request.getParameter("food");
String method = request.getParameter("method");
System.out.println(food);
System.out.println(method);
}
//DB에 insert하고 끝
int result = 1; //정상
PrintWriter out = response.getWriter();
// out.println(1);
// out.flush();
// 1) text/plain 으로 응답
// out.println(result);
// out.flush();
// 2) application/json 으로 응답
if(result ==1 ) {
out.println("{\"food\": "+food+",\"method\": "+method+"}");
}else {
out.println("{\"error\":\"fail\"}");
}
}
}
결과
System.out.println(buffer.toString());
위의 코드에 의해서
{"food" : "김치찌게" , "method" : 김치넣고 물넣고 끓이기}
라는 결과가 출력될 것이다.
결과
System.out.println(food); System.out.println(method);
위의 코드에 의해서
김치찌개 물넣고 김치넣고 끓이기
라는 결과가 출력될 것이다.
package com.cos.blog.test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//web.xml에 서블릿 맵핑을 따로 안해도 됨 -> 이미 필터가 @WebServlet 이라는 어노테이션 분석해서 서블릿 맵핑을 해주었을 것 = 리플렉션
//localhost:8080/blog/test 로 들어오면 여기로 들어와짐 (Get, Post)
@WebServlet("/test")
public class ApiServerTest extends HttpServlet {
private static final long serialVersionUID = 1L;
public ApiServerTest() {
super();
}
//Get방식으로 들어오면 이 함수 동작 -> 함수의 파라미터를 분석해서 톰캣이 request,response객체를 주입해준 것이다.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response); //Get방식도 되게 하려면
}
//Post방식으로 들어오면 이 함수 동작
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// request.getContentType(); // 할 필요가 없음 -> 왜? 이미 x-www-form-unlencoded로 보내라고 알려줬음
//브라우저에게 Content-Type을 알려줌
//response.setContentType("application/json; charset=utf-8");
response.setContentType("text/html; charset=utf-8");
//response.sendRedirect("index.jsp");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<body>");
out.println("<h1>안녕</h1>");
out.println("</body>");
out.println("<html>");
out.flush();
}
}
<html>
<body>
<h1>안녕</h1>
</body>
<html>
response.setContentType("text/html; charset=utf-8");
response.setContentType("application/json; charset=utf-8");
응답할 때의
Content-Type
보통 클라이언트(브라우저)에서 서버쪽에 요청할 때에는
Content-Type
정보를 붙일 필요가 없다. 왜냐하면 서버는 Api문서를 통해 어떤 형식으로 데이터가 요청이 될지 알고 있기 때문이다.(api문서내의 요청데이터의Content-Type
)
하지만 서버에서 브라우저에게 응답할때에는Content-Type
을 꼭 붙여야 한다. 기본적으로text/html
을 응답할때는 브라우저가 html해석기로서 그냥 html을 읽으므로 상관없지만, json등의 html형식이 아닌 다른 형식으로 응답할때에는Content-Type(MIME 타입)
을 꼭 붙여줘야 브라우저가 내용을 해석할 수 있다.
Api문서가 있으면 Content-Type이 필요하지 않다.
이유 : 어떤 형식으로 요청해달라고 Api문서에 적어놨기 때문이다.
-> 요청 데이터의Content-Type
:x-www-form-unlencoded
api문서에 요청 데이터의Content-Type
을 써놓지 않으면 요청하는 입장에서 어떤 방식으로 보내야 하는지 모른다.
그러면 어떤 데이터의 타입(MIME타입)으로 요청해야 하는지 몰라서 보내는 사람이 마음대로 보낼 수 있다.
그러면 서버는 이를 제대로 알아보지 못하고 null을 응답한다.
-> 근데 이런 상황에서 헤더에Content-Type
을 넣어도 서버는 제대로 알아보지 못함
-> 그러므로 api 문서에 요청 데이터의Content-Type
을 반드시 명시해야 한다.
요청&응답 시
Content-Type
그런데 요청할때 보통
Content-Type
을 붙일 필요가 없다. 왜냐하면 서버는 이미 뭘 요청할지 알고 있다.
근데 서버쪽에서 브라우저로 응답할때는Content-Type
를 꼭 붙여야 한다.
기본적으로 text/html을 응답할때는 상관없다. 왜냐하면 브라우저가 그냥 text/html을 읽으니까
근데 json 으로 응답할때는 브라우저에게Content-Type(MIME타입)
을 붙여줘야 브라우저가 해석을 할 수 있다.
다시 정리하면,
- 서버쪽에 요청할때는
Content-Type
이 중요하지 않다.
이유: Api문서 만들어놓고 요청하는 타입을 고정해놓기 때문이다.- 근데 응답할때는
Content-Type
이 중요하다.
이유: 응답은 브라우저가 받기 때문이다.Content-Type
이 없으면 브라우저는 어떻게 해석을 해야하는지 결정을 못한다. 그래서 요청 헤더에는Content-Type
이 없어도 되지만, 내가 파일을 응답할때가 아니면 응답 헤더에는Content-Type
을 달아야 한다.
파일을 응답하면 톰캣이 html로 바꿔서 응답해주니까 내가 바꿔도 톰캣에 의해 다시 html로 바꿔서 응답이 된다.
그래서 내가 한것과 같이 데이터로 응답하게 되면(버퍼) 어떻게 해석을 해야 하는Content-Type
으로 알려줘야 한다.