HttpServletRequest
- 서블릿이 HTTP 요청 메시지를 파싱해 HttpServletRequest 객체에 담아 제공
HTTP 요청 메시지
POST /save HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
username=kim&age=20
- START LINE
- HTTP 메소드, URL, 쿼리 스트링, 스키마, 프로토콜
- 헤더
- 헤더 정보 조회
- 바디
- form 파라미터 형식 조회
- message body 데이터 직접 조회
임시 저장소
- HTTP 요청의 시작 - 끝 동안 유지되는 임시 저장소
- 저장 :
request.setAttribute(name, value)
- 조회 :
request.getAttribute(name)
- 저장 :
세션 관리
request.getSession(create: true)
예제코드
ReqeuestHeaderServlet
package hello.servlet.request.basic;
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;
@WebServlet(name="requestHeaderServlet", urlPatterns = "/request-header")
public class RequestHeaderServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
printStartLine(req);
printHeaders(req);
printHeaderUtils(req);
printEtc(req);
resp.getWriter().write("ok");
}
private void printStartLine(HttpServletRequest req) {
System.out.println("--- REQUEST-LINE - start ---");
System.out.println("req.getMethod() = " + req.getMethod()); // GET
System.out.println("req.getProtocol() = " + req.getProtocol()); // HTTP/1.1
System.out.println("req.getScheme() = " + req.getScheme()); // http
System.out.println("req.getRequestURL() = " + req.getRequestURL()); // http://localhost:8080/request-header
System.out.println("req.getRequestURI() = " + req.getRequestURI()); // request-header
System.out.println("req.getQueryString() = " + req.getQueryString()); // username=hello
System.out.println("req.isSecure() = " + req.isSecure()); // https 사용 유무(false)
System.out.println("--- REQUEST-LINE - end ---");
System.out.println();
}
private void printHeaders(HttpServletRequest req) {
System.out.println("--- Headers - start ---");
req.getHeaderNames().asIterator()
.forEachRemaining(headerName -> System.out.println(headerName + ": " + req.getHeader(headerName)));
System.out.println("--- Headers - end ---");
System.out.println();
}
private void printHeaderUtils(HttpServletRequest req) {
System.out.println("--- Headers 편의 조회 start ---");
System.out.println("[Host 편의 조회]");
System.out.println("req.getServerName() = " + req.getServerName());
System.out.println("req.getServerPort() = " + req.getServerPort());
System.out.println();
System.out.println("[Accept-Language 편의 조회]");
req.getLocales().asIterator()
.forEachRemaining(locale -> System.out.println("locale = " + locale));
System.out.println("req.getLocale() = " + req.getLocale());
System.out.println();
System.out.println("[cookie 편의 조회]");
if(req.getCookies() != null) {
for (Cookie cookie : req.getCookies()) {
System.out.println(cookie.getName() + ": " + cookie.getValue());
}
}
System.out.println();
System.out.println("[Content 편의 조회]");
System.out.println("req.getContentType() = " + req.getContentType());
System.out.println("req.getCharacterEncoding() = " + req.getCharacterEncoding());
System.out.println("--- Headers 편의 조회 end ---");
System.out.println();
}
private void printEtc(HttpServletRequest req) {
System.out.println("--- 기타 조회 start ---");
System.out.println("[Remote 정보]");
System.out.println("req.getRemoteHost() = " + req.getRemoteHost());
System.out.println("req.getRemoteAddr() = " + req.getRemoteAddr());
System.out.println("req.getRemotePort() = " + req.getRemotePort());
System.out.println();
System.out.println("[Locale 정보]");
System.out.println("req.getLocalName() = " + req.getLocalName());
System.out.println("req.getLocalAddr() = " + req.getLocalAddr());
System.out.println("req.getLocalPort() = " + req.getLocalPort());
System.out.println("--- 기타 조회 end ---");
System.out.println();
}
}
결과
--- REQUEST-LINE - start ---
req.getMethod() = GET
req.getProtocol() = HTTP/1.1
req.getScheme() = http
req.getRequestURL() = http://localhost:8080/request-header
req.getRequestURI() = /request-header
req.getQueryString() = null
req.isSecure() = false
--- REQUEST-LINE - end ---
--- Headers - start ---
host: localhost:8080
connection: keep-alive
sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="97", "Chromium";v="97"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
upgrade-insecure-requests: 1
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
sec-fetch-site: same-origin
sec-fetch-mode: navigate
sec-fetch-user: ?1
sec-fetch-dest: document
referer: http://localhost:8080/basic.html
accept-encoding: gzip, deflate, br
accept-language: ko,ko-KR;q=0.9,en;q=0.8,ja;q=0.7
cookie: sidebar_collapsed=false; jenkins-timestamper-offset=-32400000
--- Headers - end ---
--- Headers 편의 조회 start ---
[Host 편의 조회]
req.getServerName() = localhost
req.getServerPort() = 8080
[Accept-Language 편의 조회]
locale = ko
locale = ko_KR
locale = en
locale = ja
req.getLocale() = ko
[cookie 편의 조회]
sidebar_collapsed: false
jenkins-timestamper-offset: -32400000
[Content 편의 조회]
req.getContentType() = null
req.getCharacterEncoding() = UTF-8
--- Headers 편의 조회 end ---
--- 기타 조회 start ---
[Remote 정보]
req.getRemoteHost() = 0:0:0:0:0:0:0:1
req.getRemoteAddr() = 0:0:0:0:0:0:0:1
req.getRemotePort() = 14067
[Locale 정보]
req.getLocalName() = 0:0:0:0:0:0:0:1
req.getLocalAddr() = 0:0:0:0:0:0:0:1
req.getLocalPort() = 8080
--- 기타 조회 end ---
쿼리 파라미터 조회
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
* <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 resp) 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("[단일 파라미터 조회]");
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);
}
resp.getWriter().write("ok");
}
}
실행결과
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
복수 파라미터와 단일 파라미터 조회
- 파라미터 이름은 하나이지만 값이 중복일 경우
request.getParameter()
: 하나의 파라미터 이름에 대해 값 출력, 중복일 경우request.getParameterValues()
의 첫 번째 값 반환reqeust.getParameterValues()
: 값이 중복일 경우 사용, 배열로 값을 반환함
HTML Form으로 데이터 전송
<form action="/request-param" method="post">
username: <input type="text" name="username" />
age: <input type="text" name="age" />
<button type="submit">전송</button>
</form>
- Content-Type:
application/x-www-form-urlencoded
- message body:
username=hello&age=20
- Content-Type은 HTTP 메시지 바디의 데이터 형식 지정, GET 형식은 메시지 바디가 없기 때문에 사용 x
- 메시지 바디에 쿼리 파라미터 형식으로 데이터 전달
JSON으로 데이터 전달
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;
/**
* 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 final 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");
}
}
- Content-Type:
application/json
- message body:
{"username": "hello", "age": 20}
- JSON 결과를 파싱해서 객체로 변환하기 위해 JSON 라이브러리 추가 사용이 필요함
- 스프링 부트는 기본으로 Jackson 라이브러리를 제공함(ObjectMapper)
HttpServletResponse
HTTP 응답 메시지 생성
- HTTP 응답코드 지정
- 헤더 생성
- 바디 생성
편의 기능
- Content-Type, Cookie, Redirect
예제코드
ResponseHeaderServlet
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;
/**
* http://localhost:8080/response-header
*/
@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); //200
//[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");
}
}
- redirect 시 status code 302로 반환 =>
/basic/hello-form.html
로 리다이렉트 됨
응답결과
단순 텍스트, HTML 응답
- 단순 텍스트 응답 :
writer.println("ok");
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>");
}
}
- HTML을 응답으로 반환할 때는 Content-Type을
text/html
로 지정
JSON 응답
ResponseJsonServler
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 final 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);
String result = objectMapper.writeValueAsString(data); //{"username":"kim","age":20}
response.getWriter().write(result);
}
}
- JSON을 응답으로 반환할 때는 Content-Type을
application/json
로 지정
application/json은 스펙상 utf-8형식을 사용하도록 정의되어 있으므로 application/json;charset=utf-8은 의미없는 파라미터를 추가한 것이 된다. 따라서 response.setCharacterEncoding("utf-8"); 부분을 제거하고 추가 파라미터를 자동으로 추가하는 response.getWriter() 대신 response.getOutputStream()을 사용하면 된다.
'Backend' 카테고리의 다른 글
[Spring] 스프링 컨테이너와 스프링 빈 (0) | 2022.01.25 |
---|---|
[Spring] HTTP 요청 파라미터 사용 - @RequestParam과 @ModelAttribue (0) | 2022.01.18 |
[Spring] MVC 패턴 (0) | 2022.01.16 |
[Spring] MVC 패턴의 등장 (0) | 2022.01.15 |
[Spring] Spring Boot에서 Servlet 사용하기 (0) | 2022.01.11 |