서블릿(2)

2024. 10. 11. 15:38Web Development/스프링 MVC 1편

HttpServletRequest - 개요

1. HttpServletRequest 역할

HTTP 요청 메시지를 개발자가 직접 파싱해서 사용해도 되지만, 매우 불편할 것이다.

서블릿은 개발자가 HTTP 요청 메시지를 편리하게 사용할 수 있도록 개발자 대신에 HTTP 요청 메시지를 파싱한다. 그리고 그 결과를 'HttpServletRequest' 객체에 담아서 제공한다.

 

HttpServletRequest를 사용하면 다음과 같은 HTTP 요청 메시지를 편리하게 조회할 수 있다.

 

2. 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 데이터 직접 조회

 

HttpServletRequest 객체는 추가로 여러가지 부가기능도 함께 제공한다.

 

3. 임시 저장소 기능

- 해당 HTTP 요청이 시작부터 끝날 때까지 유지되는 임시 저장소 기능

    - 저장 : request.setAttribute(name, value)

    - 조회 : request.getAttribute(name)

 

4. 세션 관리 기능

- request.getSession(create:true)

 

⭐중요

: HttpServletRequest, HttpServletResponse를 사용할 때 가장 중요한 점은 이 객체들이 HTTP 요청 메시지, HTTP 응답 메시지를 편리하게 사용하도록 도와주는 객체라는 점이다. 따라서 이 기능에 대해서 깊이있는 이해를 하려면 HTTP 스펙이 제공하는 요청, 응답메시지 자체를 이해해야한다.

 


 

HttpServletRequest - 기본사용법

 

Main> java> basic 아래 request 패키지 생성, 그 아래에 RequestHeaderServlet.java 파일 생성 

package hello.servlet.basic.request;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

@WebServlet(name="requestHeaderServlet", urlPatterns = "/request-header")
public class RequestHeaderServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //urlpattern "/request-header" 호출 시 자동실행되는 service 메소드
	printStartLine(request);
        //printHeaders(request);
        //printHeaderUtils(request);
        //printEtc(request);
        response.getWriter().write("ok");
    }

    
}

 

 

1. start Line

//start line 정보
    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-header
        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();

    }

 

결과 확인

 

 

2. Header 정보 확인

//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();
    }

 

 

결과확인

 

 

3. Header 편리한 조회

//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();
    }

 

결과확인

- Accept-Language 

: 브라우저에서 언어 지원 순서를 설정,

request.getLocale() 메소드로 가장 우선순위의 언어를 가져올 수 있다.

 

* 이 때, request.getContentType 이 null 인 이유는 GET 방식 요청이기 때문

-> POSTMAN 을 활용하여 POST 방식으로 요청해보자.

 

 

결과 확인

 

 

4. 기타 정보 조회

//기타 정보
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();
}

 

결과확인

 

 


 

HTTP 요청 데이터 - 개요

HTTP 요청 메시지를 통해 클라이언트에서 서버로 데이터를 전달하는 방법을 알아보자.

 

주로 다음 세가지 방법을 사용한다.

 

1. GET - 쿼리 파라미터

- /url?username=suyeon&age=26

- 메시지 바디 없이, URL의 쿼리 파라미터에 데이터를 포함해서 전달

- 예) 검색, 필터, 페이징등에서 많이 사용하는 방식

 

2. POST - HTML Form

- content-type: application/x-www-form-urlencoded

- 메시지 바디에 쿼리 파라미터 형식으로 전달 username=suyeon&age=26

- 예) 회원 가입, 상품 주문, HTML Form 사용

 

3. HTTP message body 에 데이터를 직접 담아서 요청

- HTTP API에서 주로 사용, JSON, XML, TEXT

- 데이터 형식은 주로 JSON 사용

- POST, PUT, PATCH

 

 


HTTP 요청 데이터 - GET 쿼리 파라미터

다음 데이터를 클라이언트에서 서버로 전송해보자.

 

전달 데이터

- username=suyeon

- age=26

메시지 바디 없이, URL의 "쿼리 파라미터"를 사용해 데이터를 전달하자.

예) 검색, 필터, 페이징 등에서 많이 사용하는 방식

 

쿼리 파라미터는 URL에 다음과 같이 "?"를 시작으로 보낼 수 있다. 추가 파라미터는 "&"로 구분하면 된다.

- http://localhost:8080/request-param?username=suyeon&age=26

 

서버에서는 HttpServletRequest 가 제공하는 다음 메서드를 통해 쿼리 파라미터를 편리하게 조회할 수 있다.

 

쿼리 파라미터 조회 메서드

String username = request.getParameter("username"); //단일 파라미터 조회

Enumeration<String> parameterNames = request.getParameterNames(); //파라미터 이름을 모두 조회
Map<String, String[]> parameterMap = request.getParameterMap(); //파라미터를 Map으로 조회
String[] usernames = request.getParameterValues("username"); //개수 파라미터 조회

 

 

(실습)

RequestParamServlet.java 생성

package hello.servlet.basic.request;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.Enumeration;

/**
 * 1. 파라미터 전송 기능
 * http://localhost:8080/request-param?username=suyeon&age=26
 *
 */
@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");
    }
}

 

결과확인

 

+ 이름이 같은 복수 파라미터 조회

 

* username=hello&username=kim 과 같이 파라미터 이름은 하나인데, 값이 중복이면 어떻게 될까?

request.getParameter() 는 하나의 파라미터 이름에 대해서 단 하나의 값만 있을 때 사용해야 한다. 

지금처럼 중복일 때는 request.getParameterValues() 를 사용해야 한다.

참고) 이렇게 중복일 때 request.getParameter() 를 사용하면 request.getParameterValues() 의 첫 번째 값을 반환한다.

	System.out.println("[이름이 같은 복수 파라미터 조회]-START");
        String[] usernames = request.getParameterValues("username");
        for(String name : usernames) {
            System.out.println("username = "+name);
        }
        System.out.println("[이름이 같은 복수 파라미터 조회]-END");

 

- http://localhost:8080/request-param?username=suyeon&age=26&username=suyeon2

 

결과확인

 

 

'Web Development > 스프링 MVC 1편' 카테고리의 다른 글

서블릿, JSP, MVC 패턴(2)  (1) 2024.10.20
서블릿, JSP, MVC 패턴(1)  (0) 2024.10.14
서블릿(3)  (1) 2024.10.13
서블릿(1)  (7) 2024.10.10
웹 애플리케이션 이해  (0) 2024.07.06