[TIL] #2. 서블릿 ②
HTTP
요청 데이터 - GET
쿼리 파라미터
HTTP 요청 데이터 전달 방식 중 GET 쿼리 파라미터 방식에 대해 알아보자!
다음 데이터를 클라이언트에서 서버로 전송해보자.
username = hello
age = 20
메시지 바디 없이, URL의 쿼리 파라미터를 이용해서 데이터를 전달해볼 것이다.
쿼리 파라미터는 URL 뒤에 ?
를 붙여서 보낼 수 있다. 추가 파라미터는 &
를 이용하면 된다.
- Ex)
http://localhost:8080/request-param?username=hello&age=20
✔ 쿼리 파라미터 조회 메서드
String username = request.getParameter("username"); //단일 파라미터 조회
Enumeration<String> parameterNames = request.getParameterNames(); //파라미터 이름들 모두 조회
Map<String, String[]> parameterMap = request.getParameterMap(); //파라미터를 Map으로 조회
String[] usernames = request.getParameterValues("username"); //복수 파라미터 조회
✔ RequestParamServlet
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;
/**
* 1. 파라미터 전송 기능
* http://localhost:8080/request-param?username=hello&age=20
* 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");
request.getParameterNames().asIterator()
.forEachRemaining(paramName -> System.out.println(paramName + "=" + request.getParameter(paramName)));
System.out.println("[전체 파라미터 조회] - end");
System.out.println();
System.out.println("[단일 파라미터 조회] - start");
String username = request.getParameter("username");
String age = request.getParameter("age");
System.out.println("username = " + username);
System.out.println("age = " + age);
System.out.println("[단일 파라미터 조회] - end");
System.out.println();
response.getWriter().write("ok");
}
}
실행 결과
서블릿을 만들고 http://localhost:8080/request-param?username=hello&age=20
파라미터를 전송하면 다음과 같이 출력된다!
[전체 파라미터 조회] - start
username=hello
age=20
[전체 파라미터 조회] - end
[단일 파라미터 조회] - start
username = hello
age = 20
[단일 파라미터 조회] - end
✔ 복수 파라미터에서 단일 파라미터 조회
위에서는 username=hello
처럼 단일 파라미터를 살펴보았다.
이번에는 username=hello&username=bae
처럼 파라미터 이름은 하나인데, 값이 중복인 경우를 살펴보자!
⭐ 주의!
request.getParameter()
는 하나의 파라미터 이름에 대해서 단 하나의 값만 있을 때 사용해야 한다! → 지금처럼 중복일 때는request.getParameterValues()
를 사용해야 한다!- 이렇게 중복일 때
request.getParameter()
를 사용하면request.getParameterValues()
의 첫 번째 값을 반환한다.
아래의 코드를 추가해주자!
System.out.println("[이름이 같은 복수 파라미터 조회]");
System.out.println("request.getParameterValues(username)");
String[] usernames = request.getParameterValues("username");
for (String name : usernames) {
System.out.println("username=" + name);
}
http://localhost:8080/request-param?username=hello&username=bae&age=20
파라미터를 전송해보면 다음과 같이 조회된다.
[전체 파라미터 조회] - start
username=hello
age=20
[전체 파라미터 조회] - end
[단일 파라미터 조회] - start
username = hello
age = 20
[단일 파라미터 조회] - end
[이름이 같은 복수 파라미터 조회]
request.getParameterValues(username)
username=hello
username=bae
HTTP
요청 데이터 - POST HTML Form
이번에는 HTML의 Form을 사용해서 서버로 데이터를 전송해보자.
특징
- content-type:
application/x-www-form-urlencoded
- 메시지 바디에 쿼리 파라미터 형식으로 데이터를 전달한다. (
username=hello&age=20
)
✔ hello-form.html
생성
<!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>
크롬을 켜서 http://localhost:8080/basic/hello-form.html
에 접속하면 다음과 같은 화면이 뜬다.
username
과 age
를 입력한 뒤 전송
버튼을 클릭하면 GET 쿼리 파라미터
때와 동일하게 출력된다!
✔ POST HTML Form
POST의 HTML Form
을 전송하면 웹 브라우저는 다음 형식으로 HTTP 메시지를 만든다.
- 요청 URL:
http://localhost:8080/request-param
- content-type:
application/x-www-form-urlencoded
- message body:
username=hello&age=20
application/x-www-form-urlencoded
형식이 GET 쿼리 파라미터 형식과 같아서 쿼리 파라미터 조회 메서드를 그대로 사용하면 된다.
클라이언트(웹 브라우저) 입장에서는 두 방식에 차이가 있지만, 서버 입장에서는 둘의 형식이 동일하여 request.getParameter()
로 편리하게 구분없이 조회할 수 있다.
📌 정리
request.getParameter()
는GET URL 쿼리 파라미터 형식
도 지원하고,POST HTML Form 형식
도 둘 다 지원한다.
✔ Postman
을 이용한 테스트
위에서 테스트를 하기 위해서 따로 HTML 페이지를 만들었는데 그러면 메번 이렇게 HTML 페이지를 만들어줘야 할까?
그러면 너무너무 귀찮을 것이다..
이렇게 HTML 페이지를 매번 만들지 않고 Postman을 이용하여 간단하게 테스트를 할 수 있다!
위와 같이 설정하고 send
를 클릭하면 잘 작동한다!
HTTP
요청 데이터 - API
메시지 바디 - 단순 텍스트
HTTP message body에 데이터를 직접 담아서 요청해보자.
이 방식은 HTTP API에서 주로 사용하는 방식으로,
JSON, XML, TEXT에 사용되는 방식인데 주로 JSON을 사용한다.
먼저 단순한 텍스트 메시지를 HTTP 메시지 바디에 담아서 전송하고 읽어보자.
✔ RequestBodyStringServlet
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");
}
}
- HTTP message body는
InputStream
을 사용해서 직접 읽을 수 있다.
실행 결과
postman을 이용해서 테스트해보면 잘 나온다!
HTTP 요청 데이터 - API 메시지 바디 - JSON
이번에는 많이 쓰이는 JSON 형식으로 요청해보자!
JSON 형식을 사용하려면 해당 데이터를 파싱해서 객체화해 줄 객체를 만들어줘야 한다!
✔ HelloData
package hello.servlet.basic;
import lombok.Getter;
import lombok.Setter;
@Getter @Setter
public class HelloData {
private String username;
private int age;
}
username
과 age
를 담을 수 있는 JSON 객체가 만들어졌다!
✔ RequestBodyJsonServlet
JSON 방식의 API와 매핑해줄 서블릿 RequestBodyJsonServlet
을 만들어주자.
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;
@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");
}
}
실행 결과
이번에도 Postman을 이용해서 테스트해보자!
JSON 형식에 맞춰서 message body를 작성해주면 된다!
HTTPServletResponse
- 기본 사용법
지금부터는 응답 메시지에 대해 알아보자!
HttpServletResponse
역할
- HTTP 응답 메시지 생성
- HTTP 응답코드 지정
- 헤더 생성
- 바디 생성
- 편의 기능 제공
Content-Type
, 쿠키,Redirect
✔ HttpServletResponse
package hello.servlet.basic.response;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet(name = "responseHeaderServlet", urlPatterns = "/response-header")
public class ResponseHeaderServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// [status-line]
response.setStatus(HttpServletResponse.SC_OK);
// [response-headers]
response.setHeader("Content-Type", "text/plain;charset=utf-8");
response.setHeader("Cache-Control", "no-cache, no-store, mustrevalidate");
response.setHeader("Pragma", "no-cache");
response.setHeader("my-header","hello");
//[Header 편의 메서드]
content(response);
cookie(response);
redirect(response);
//[message body]
PrintWriter writer = response.getWriter();
writer.println("ok");
}
private void content(HttpServletResponse response) {
//Content-Type: text/plain;charset=utf-8
//Content-Length: 2
//response.setHeader("Content-Type", "text/plain;charset=utf-8");
response.setContentType("text/plain");
response.setCharacterEncoding("utf-8");
//response.setContentLength(2); //(생략시 자동 생성)
}
private void cookie(HttpServletResponse response) {
//Set-Cookie: myCookie=good; Max-Age=600;
//response.setHeader("Set-Cookie", "myCookie=good; Max-Age=600");
Cookie cookie = new Cookie("myCookie", "good");
cookie.setMaxAge(600); //600초
response.addCookie(cookie);
}
private void redirect(HttpServletResponse response) throws IOException {
//Status Code 302
//Location: /basic/hello-form.html
//response.setStatus(HttpServletResponse.SC_FOUND); //302
//response.setHeader("Location", "/basic/hello-form.html");
response.sendRedirect("/basic/hello-form.html");
}
}
HttpServletResponse.SC_OK
: 서블릿에서는HttpServletResponse
에서 상태 코드를 코드 자체(Ex. 200/404 등)보다는 의미 있는 상수로 작성해서 오타를 방지하고 가독성을 높일 수 있도록 했다!
🔗 전체 코드 확인
HTTP
응답 데이터 - 단순 텍스트, HTML
HTTP 응답 메시지는 주로 다음 내용을 담아서 전달한다.
- 단순 텍스트 응답 (Ex.
writer.println("ok");
)- HTML 응답
- HTTP API -
MessageBody JSON
응답
✔ ResponseHtmlServlet
package hello.servlet.basic.response;
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.io.PrintWriter;
@WebServlet(name = "responseHtmlServlet", urlPatterns = "/response-html")
public class ResponseHtmlServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//Content-Type: text/html;charset=utf-8
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
PrintWriter writer = response.getWriter();
writer.println("<html>");
writer.println("<body>");
writer.println(" <div>안녕?</div>");
writer.println("</body>");
writer.println("</html>");
}
}
- HTTP 응답으로 HTML을 반환할 때는
content-type
을text/html
로 지정해야 한다.
실행 결과
http://localhost:8080/response-html
로 접속하면 잘 출력되고, 페이지 소스보기를 사용하면 다음과 같이 나타난다.
HTML
응답 데이터 - API JSON
이번에는 응답 메시지의 API JSON 타입에 대해 알아보자!
✔ ResponseJsonServlet
package hello.servlet.basic.response;
import com.fasterxml.jackson.databind.ObjectMapper;
import hello.servlet.basic.HelloData;
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;
/**
* http://localhost:8080/response-json
*
*/
@WebServlet(name = "responseJsonServlet", urlPatterns = "/response-json")
public class ResponseJsonServlet extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//Content-Type: application/json
response.setHeader("content-type", "application/json");
response.setCharacterEncoding("utf-8");
HelloData data = new HelloData();
data.setUsername("kim");
data.setAge(20);
//{"username":"kim","age":20}
String result = objectMapper.writeValueAsString(data);
response.getWriter().write(result);
}
}
ObjectMapper
를 사용해서HelloData
객체를json
으로 만들어주고있다.content-type
을application/json
으로 지정해야 한다.objectMapper.writeValueAsString()
메서드를 사용하면 객체를 JSON 문자로 변경할 수 있다.
실행 결과
http://localhost:8080/response-json
으로 접속하면 JSON 포맷으로 데이터가 잘 출력되는 것을 확인할 수 있다!
Author And Source
이 문제에 관하여([TIL] #2. 서블릿 ②), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@mmy789/TIL-2.-서블릿-343wwh0n저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)