HTTP 요청 메시지를 통해 클라이언트에서 서버로 데이터를 전달하는 방법을 알아보자.
주로 3가지 방법을 사용합니다.
POST-HTML FORM 예시
다음 데이터를 클라이언트에서 서버로 전송해보자.
전달 데이터
앞서 말씀드렸듯이, 쿼리 파라미터는 URL에 다음과 같이 ?를 시작으로 보낼 수있습니다 .추가 파라미터는 &로 구분하면 됩니다.
@WebServlet(name = "requestParamServlet", urlPatterns = "/request-param")
public class RequestParamServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("[전체 파라미터 조회]");
request.getParameterNames().asIterator()
.forEachRemaining(paramName-> System.out.println("paramName = " + request.getParameter(paramName)));
System.out.println("[전체 파라미터 조회] - end");
System.out.println();
System.out.println("[단일 파라미터 조회]");
String username = request.getParameter("username");
String age = request.getParameter("age");
System.out.println("age = " + age);
System.out.println("username = " + username);
System.out.println();
System.out.println("[이름이 같은 복수 파라미터 조회]");
String[] usernames = request.getParameterValues("username");
for (String name : usernames) {
System.out.println("username = " + name);
}
response.getWriter().write("ok");
}
getParameterNames().asIterator().forEachRemaining
request.getParameter("username") : 단일 파라미터 조회
request.getParameterNames() : 파라미터 이름들 모두 조회
request.getParameterValues("username") : 복수 파라미터 조회
결과
[전체 파라미터 조회] - start
username=hello
age=20
[전체 파라미터 조회] - end
[단일 파라미터 조회] request.getParameter(username) = hello request.getParameter(age) = 20
[이름이 같은 복수 파라미터 조회] request.getParameterValues(username) username=hello
username=hello&username=kim 과 같이 파라미터 이름은 하나인데, 값이 중복이면 어떻게 될까?
request.getParameter() 는 하나의 파라미터 이름에 대해서 단 하나의 값만 있을 때 사용해야 한다. 지금처럼 중복일 때는 request.getParameterValues() 를 사용해야 한다. 참고로 이렇게 중복일 때 request.getParameter() 를 사용하면 request.getParameterValues() 의 첫 번째 값을 반환한다.
주로 회원가입, 상품 주문에서 사용하는 방식이다.
특징
POST의 HTML Form을 전송하면 웹 브라우저는 다음 형식으로 HTTP 메시지를 만든다. (웹 브라우저 개발자 모드 확인)
application/x-www-form-urlencoded 형식은 앞서 GET에서 살펴본 쿼리 파라미터 형식과 같다. 따라서 쿼리 파라미터 조회 메서드를 그대로 사용하면 된다.
클라이언트(웹 브라우저) 입장에서는 두 방식에 차이가 있지만, 서버 입장에서는 둘의 형식이 동일하므로, request.getParameter() 로 편리하게 구분없이 조회할 수 있다.
request.getParameter() 는 GET URL 쿼리 파라미터 형식도 지원하고, POST HTML Form 형식도 둘 다 지원한다.
참고
content-type은 HTTP 메시지 바디의 데이터 형식을 지정한다.
GET URL 쿼리 파라미터 형식으로 클라이언트에서 서버로 데이터를 전달할 때는 HTTP 메시지 바디를 사용하지 않기 때문에 content-type이 없다.
POST HTML Form 형식으로 데이터를 전달하면 HTTP 메시지 바디에 해당 데이터를 포함해서 보내기때문에 바디에 포함된 데이터가 어떤 형식인지 content-type을 꼭 지정해야 한다. 이렇게 폼으로 데이터를 전송하는 형식을 application/x-www-form-urlencoded 라 한다.
테스트는 POSTMAN을 사용해서 각자 해봅시다!
Postman 테스트 주의사항
HTTP message body에 데이터를 직접 담아서 요청
먼저 가장 단순한 텍스트 메시지를 HTTP 메시지 바디에 담아서 전송하고, 읽어보자. HTTP 메시지 바디의 데이터를 InputStream을 사용해서 직접 읽을 수 있다.
RequestBodyStringServlet
@WebServlet(name="requestBodyStringServlet", urlPatterns = "/request-body-string")
public class RequestBodyStringServlet extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletInputStream inputStream = request.getInputStream(); //메세지 body의 내용을 바이트 코드로 바로 얻을수 있다.
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
System.out.println("messageBody = " + messageBody);
response.getWriter().write("ok");
}
}
코드설명
문자 전송
JSON형식의 데이터는 주로 HTTP API에서 사용한다.
코드를 통해 알아봅시다.
JSON 형식 전송
HelloData : JSON 형식으로 파싱할 객체
@Getter @Setter
public class HelloData {
private String username;
private int age;
}
RequestBodyJsonServlet
@WebServlet(name="requestBodyJsonServlet", urlPatterns = "/request-body-json")
public class RequestBodyJsonServlet extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletInputStream inputStream = request.getInputStream();
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
System.out.println("messageBody = " + messageBody);
//json data 객체로 변환
HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);
System.out.println("helloData.getUsername() = " + helloData.getUsername());
System.out.println("helloData.getAge() = " + helloData.getAge());
response.getWriter().write("ok");
}
}
코드설명