[Spring] MVC 1편 - 02. 서블릿
이 글은 스프링 [스프링 MVC 1편]을 듣고 정리한 내용입니다
📌 프로젝트 생성
- 환경 세팅
- Packing: War (주의)
- JSP 실행하기 위해서 필요함
- 메인 클래스 실행하고, localhost:8080에 Whitelabel Error Page 나오면 정상 동작
- Gradle대신에 InteliJ 에서 자바 직접 실행하는 설정
- 롬복 적용(plugint 롬복 설치, Annotation Processor)
- Postman 설치
📌 Hello 서블릿
- 서블릿 등록하기
package hello.servlet.basic;
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;
@WebServlet(name = "helloServlet", urlPatterns = "/hello") // name: 서블릿 이름, urlPatterns: URL 매핑
public class HelloServlet extends HttpServlet {
@Override // HTTP 요청을 통해 URL이 호출되면 서블릿 컨테이너는 다음 메서드(service)를 실행한다.
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("HelloServlet.service");
System.out.println("request = " + request);
System.out.println("response = " + response);
String username = request.getParameter("username");
System.out.println("username = " + username);
response.setContentType("text/plain"); // http 헤더 정보 - content type
response.setCharacterEncoding("utf-8");// http 헤더 정보 - content type
response.getWriter().write("hello " + username); //http 메시지 바디에 데이터가 들어감
}
}
- HTTP 요청 로그로 확인하기
logging.level.org.apache.coyote.http11=debug
- 다음설정을 추가하면 서버가 받은 HTTP 요청 메세지를 확인 할 수 있다.
서블릿 컨테이너 동작 방식
-
내장 톰캣 서버 생성
-
welcome 페이지 추가(index.html)
-
학습할 내용 안내 페이지 추가(basic.html)
📌 HttpServletRequeset - 개요
HttpServletRequest 역할
- 서블릿은 개발자가 HTTP 요청 메시지를 편리하게 사용할 수 있도록 개발자 대신에 HTTP 요청 메시지를 파싱한다.
- 그리고 그 결과를
HttpServletRequest
객체에 담아서 제공한다.
HTTP 요청 메시지
POST /save HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
username=kim&age=20
- 시작 라인
- HTTP 메소드
- URL
- 쿼리 스트링
- 스키마, 프로토콜
- 헤더
- 헤더 조회
- 바디
- form 파라미터 형식 조회
- message body 데이터 직접 조회
HttpServletRequeset
객체는 추가로 다음 여러가지 부가기능도 제공한다.임시 저장소 기능
- 해당 HTTP 요청이 시작부터 끝날 때까지 유지되는 임시 저장소 기능
- 저장:
request.setAttribute(name,value)
- 조회:
request.getAttribute(name)
- 저장:
중요
- HttpServletRequest, HttpServletResponse 객체들은 HTTP 요청,응답 메세지드를 편리하게 사용하도록 도와주는 개체이다
- HTTP 스펙이 제공하는 요청, 응답 메시지를 잘 이해해야한다.
📌 HttpServletRequest - 기본 사용법
- HttpServletRequest가 제공하는 기본 기능들을 조회 해본다.
package hello.servlet.basic.request;
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.util.Enumeration;
@WebServlet(name= "requestHeaderServlet", urlPatterns = "/request-header")
public class RequestHeaderServlet extends HttpServlet {
@Override //protected인 service를 만들어야 한다.
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
printStartLine(request);
printHeaders(request);
printHeaderUtils(request);
printEtc(request);
}
private void printStartLine(HttpServletRequest request) {
System.out.println("--- REQUEST-LINE - start ---");
System.out.println("request.getMethod() = " + request.getMethod()); //GET
System.out.println("request.getProtocol() = " + request.getProtocol()); //HTTP/1.1
System.out.println("request.getScheme() = " + request.getScheme()); //http
// http://localhost:8080/request-header
System.out.println("request.getRequestURL() = " + request.getRequestURL());
// /request-test
System.out.println("request.getRequestURI() = " + request.getRequestURI());
//username=hi
System.out.println("request.getQueryString() = " +
request.getQueryString());
System.out.println("request.isSecure() = " + request.isSecure()); //https 사용 유무
System.out.println("--- REQUEST-LINE - end ---");
System.out.println();
}
//Header 모든 정보
private void printHeaders(HttpServletRequest request) {
System.out.println("--- Headers - start ---");
/* Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
System.out.println(headerName + ": " + request.getHeader(headerName));
}
*/
request.getHeaderNames().asIterator()
.forEachRemaining(headerName -> System.out.println(headerName + ": " + request.getHeader(headerName)));
System.out.println("--- Headers - end ---");
System.out.println();
}
//Header 편리한 조회
private void printHeaderUtils(HttpServletRequest request) {
System.out.println("--- Header 편의 조회 start ---");
System.out.println("[Host 편의 조회]");
System.out.println("request.getServerName() = " + request.getServerName()); //Host 헤더
System.out.println("request.getServerPort() = " + request.getServerPort()); //Host 헤더
System.out.println();
System.out.println("[Accept-Language 편의 조회]");
request.getLocales().asIterator()
.forEachRemaining(locale -> System.out.println("locale = " +locale));
System.out.println("request.getLocale() = " + request.getLocale());
System.out.println();
System.out.println("[cookie 편의 조회]");
if (request.getCookies() != null) {
for (Cookie cookie : request.getCookies()) {
System.out.println(cookie.getName() + ": " + cookie.getValue());
} }
System.out.println();
System.out.println("[Content 편의 조회]");
System.out.println("request.getContentType() = " +
request.getContentType());
System.out.println("request.getContentLength() = " +
request.getContentLength());
System.out.println("request.getCharacterEncoding() = " +
request.getCharacterEncoding());
System.out.println("--- Header 편의 조회 end ---");
System.out.println();
}
// 기타 정보
// 기타정보는 HTTP 메시지의 정보는 아니다
private void printEtc(HttpServletRequest request) {
System.out.println("--- 기타 조회 start ---");
System.out.println("[Remote 정보]");
System.out.println("request.getRemoteHost() = " +
request.getRemoteHost()); //
System.out.println("request.getRemoteAddr() = " +
request.getRemoteAddr()); //
System.out.println("request.getRemotePort() = " +
request.getRemotePort()); //
System.out.println();
System.out.println("[Local 정보]");
System.out.println("request.getLocalName() = " +
request.getLocalName()); //
System.out.println("request.getLocalAddr() = " +
request.getLocalAddr()); //
System.out.println("request.getLocalPort() = " +
request.getLocalPort()); //
System.out.println("--- 기타 조회 end ---");
System.out.println();
}
}
- 이렇게 HttpServletRequest를 이용하여 HTTP 메시지의 시작라인, header 정보를 조회해보았다.
- 이제 HTTP 요청 데이터 조회하는 방법을 보자
📌 HTTP 요청 데이터 - 개요
- HTTP 요청 메시지를 통해 클라이언트에서 서버로 데이터를 전달하는 방법은 이 3가지가 전부이다!
- GET - 쿼리 파라미터
ex)/url?username=hello&age=24
- 메시지 바디 없이, URL의 쿼리 파라미터에 데이터를 포함해서 전달
사용) 검색, 필터, 페이징 등등
- 메시지 바디 없이, URL의 쿼리 파라미터에 데이터를 포함해서 전달
- POST- HTML Frorm
ex)content-type: application/x-www-form-urlencoded
- 메시지 바디에 쿼리 파라미터 형식으로 전달
username=hello&age=24
사용) 회원 가입, 상품 주문, HTML Form
- 메시지 바디에 쿼리 파라미터 형식으로 전달
- HTTP message body에 데이터를 직접 담아서 요청
- HTTP API에서 주로 사용 -> JSON, XML, TEXT
- 데이터 형식은 주로 JSON 사용
- POST, PUT, PATCH
- POST - HTML Form 예시
📌 HTTP 요청 데이터 - 1.GET 쿼리 파라미터
- 쿼리 파라미터 조회 메서드
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
*
* 2. 동일한 파라미터 전송 가능하다
* http://localhost:8080/request-param?username=hello&age=20&username=hello2
*/
@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("[단일 파라미터 조회]");
String username = request.getParameter("username");
String age = request.getParameter("age");
System.out.println("username = " + username);
System.out.println("age = " + age);
System.out.println();
//이름이 같은 복수 파라미터 조회
System.out.println("[이름이 같은 복수 파라미터 조회]");
String[] usernames = request.getParameterValues("username");
for (String name : usernames) {
System.out.println("name = " + name);
}
System.out.println();
response.getWriter().write("ok");
}
}
- 복수 파라미터에서 단일 파라미터 조회
- 하나의 파라미터에 대해 여러 값이 있으면
request.getParamterValues()
사용해야 한다. - 중복일 때
request.getParameter()
사용하면 첫번째 값을 반환한다.
- 하나의 파라미터에 대해 여러 값이 있으면
📌 HTTP 요청 데이터 - 2. POST HTML Form
- 주로 회원가입, 상품 주문 등에서 사용
- contet-type:
application/x-www-form-urlencoded
- 메시지 바디에 쿼리파라미터 형식으로 데이터 전달한다.
ex)username=hello&age=20
- 서버입장에서는 앞의 GET 쿼리 파라미터 방식과 POST HTML Form 방식 둘의 형식이 동일하다.
requset.getParameter()
는 GET URL 쿼리 파라미터 형식도 지원하고, POST HTML Form형식도 지원한다.
*참고
- content-type: HTTP 메시지 바디의 형식을 지정한다
- GET URL 쿼리 파라미터 방식에서는 메시지 바디를 사용 안하므로, content-type이 없다
- POST HTML Form 방식에서는 메시지 바디에 데이터를 포함해서 보내므로 데이터가 어떤 형식인지 content-type를 지정해야 한다.
(즉 포스트맨에서 body의x-www-form-urlencoded
선택해야함)
- 폼으로 데이터를 전송하는 형식을application/x-www-form-urlencoded
라 한다.
📌 HTTP 요청 데이터 - 3. API 메시지 바디
단순텍스트 방식
쓰다가말음 이어쓰자 ..
Author And Source
이 문제에 관하여([Spring] MVC 1편 - 02. 서블릿), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@somyeong0623/Spring-MVC-1편-02.-서블릿저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)