
/url**?username=hello&age=20**content-type: application/x-www-form-urlencodedusername=hello&age=20
테스트는 Postman으로 진행
- POST 전송시
- Body ->
x-www-form-urlencoded선택- Headers에서 content-type :
application/x-www-form-urlencoded로 지정된 부분 꼭 확인
전달 데이터
- username=hello
- age=20
메시지 바디 없이, URL의 쿼리 파라미터를 사용해서 데이터를 전달
예) 검색, 필터, 페이징 등에서 많이 사용하는 방식
쿼리 파라미터는 URL에 다음과 같이 ?를 시작으로 보낼 수 있음
서버에서는 HttpServletRequest가 제공하는 다음 메서드를 통해 쿼리 파라미터를 편리하게 조회할 수 있음
String username = request.getParameter("username"); //단일 파라미터 조회
Enumeration<String> parameterNames = request.getParameterNames(); //파라미터 이름들 모두 조회
Map<String, String[]> parameterMap = request.getParameterMap(); //파라미터를 Map으로 조회
String[] usernames = request.getParameterValues("username"); //복수 파라미터 조회
package hello.servlet.basic.request;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
/**
* 1. 파라미터 전송 기능
* http://localhost:8080/request-param?username=hello&age=20
* <p>
* 2. 동일한 파라미터 전송 가능
* http://localhost:8080/request-param?username=hello&username=kim&age=20
*/
@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("[전체 파라미터 조회] - start");
/*
Enumeration<String> parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()) {
String paramName = parameterNames.nextElement();
System.out.println(paramName + "=" +
request.getParameter(paramName));
}
*/
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");
System.out.println("request.getParameter(username) = " + username);
String age = request.getParameter("age");
System.out.println("request.getParameter(age) = " + age);
System.out.println();
System.out.println("[이름이 같은 복수 파라미터 조회]");
System.out.println("request.getParameterValues(username)");
String[] usernames = request.getParameterValues("username");
for (String name : usernames) {
System.out.println("username=" + name);
}
response.getWriter().write("ok");
}
}
http://localhost:8080/request-param?username=hello&age=20
[전체 파라미터 조회] - start
username=hello
age=20
[전체 파라미터 조회] - end
[단일 파라미터 조회]
request.getParameter(username) = hello
request.getParameter(age) = 20
[이름이 같은 복수 파라미터 조회]
request.getParameterValues(username)
username=hello
http://localhost:8080/request-param?username=hello&username=kim&age=20
[전체 파라미터 조회] - start
username=hello
age=20
[전체 파라미터 조회] - end
[단일 파라미터 조회]
request.getParameter(username) = hello
request.getParameter(age) = 20
[이름이 같은 복수 파라미터 조회]
request.getParameterValues(username)
username=hello
username=kim
username=hello&username=kim과 같이 파라미터 이름은 하나인데, 값이 중복이면 어떻게 될까?
request.getParameter()은 하나의 파라미터 이름에 대해서 단 하나의 값만 있을 때 사용해야 함
request.getParameterValues()를 사용해야 함중복인 경우 request.getParameter()을 사용하면 request.getParameterValues()의 첫 번째 값을 반환함
application/x-www-form-urlencodedusername=hello&age=20 <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/request-param" method="post">
username: <input type="text" name="username" />
age: <input type="text" name="age" />
<button type="submit">전송</button>
</form>
</body>
</html>

요청 URL : http://localhost:8080/request-param
content-type : application/x-www-form-urlencoded
message body : username=hello&age=2

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라고 함HTML 코드를 직접 작성해보긴 했지만, Postman으로 테스트를 수행하는 것이 편함
HTTP message body에 데이터를 직접 담아서 요청
가장 단순한 텍스트 메시지를 HTTP 메시지 바디에 담아서 전송하고 읽는 예제 수행
package hello.servlet.basic.request;
import org.springframework.util.StreamUtils;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@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();
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
System.out.println("messageBody = " + messageBody);
response.getWriter().write("ok");
}
}
InputStream을 사용해서 직접 읽을 수 있음 InputStream은 byte 코드를 반환함byte 코드를 우리가 읽을 수 있는 문자(String)로 보려면 문자표(Charset)를 지정해주어야 함UTF-8 Charset을 지정해줌결과:
messageBody = hello
{"username": "hello", "age": 20}결과:
messageBody = {"username": "hello", "age": 20}
package hello.servlet.basic;
import lombok.Getter;
import lombok.Setter;
@Getter @Setter
public class HelloData {
private String username;
private int age;
}
package hello.servlet.basic;
public class HelloData {
private String username;
private int age;
//==== lombok 생성 코드 ====//
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package hello.servlet.basic.request;
import com.fasterxml.jackson.databind.ObjectMapper;
import hello.servlet.basic.HelloData;
import org.springframework.util.StreamUtils;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* http://localhost:8080/request-body-json
*
* JSON 형식 전송
* content-type: application/json
* message body: {"username": "hello", "age": 20}
*
*/
@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);
HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);
System.out.println("helloData.username = " + helloData.getUsername());
System.out.println("helloData.age = " + helloData.getAge());
response.getWriter().write("ok");
}
}
import com.fasterxml.jackson.databind.ObjectMapper;
HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);
ObjectMapper)를 함께 제공함
application/json -> (Body raw, 가장 오른쪽에서 JSON 선택){"username": "hello", "age": 20}messageBody={"username": "hello", "age": 20}
data.username=hello
data.age=20