온라인 강의/Spring Framework

[스프링 MVC 1편] 서블릿

코드몬스터 2024. 5. 8. 20:55
728x90

Hello 서블릿

  • 만들어보자.
@WebServlet(name = "requestHeaderServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        System.out.println("req = " + req);
        System.out.println("res = " + res);

        String username = req.getParameter("username");
        System.out.println("username = " + username);

        res.setContentType("text/pain");
        res.setCharacterEncoding("utf-8");
        res.getWriter().write("hello" + username);
    }
}

 

 


HttpServletRequest

 

개요

HTTP 요청 메세지를 파싱한다.

그 결과를 HttpServletRequest 객체에 담아서 제공.

 

  • Start Line
    • HTTP 메소드
    • URL
    • 쿼리 스트링
    • 스키마, 프로토콜
  • 헤더
    • 헤더 조회
  • 바디
    • form 파라미터 형식 조회
    • message body 데이터 직접 조회

 

사용 방법

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

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        printHeaders(req);
        printEtc(req);
    }


    private void printHeaders(HttpServletRequest request) {


        /* 방법 1.
            Enumeration<String> headerNames = request.getHeaderNames();
            while (headerNames.hasMoreElements()) {
                String headerName = headerNames.nextElement();
                System.out.println("headerName = " + headerName);
            }
        */

        // 방법 2.
        request.getHeaderNames().asIterator()
                .forEachRemaining(headerName -> System.out.println("headerNames = " + headerName));

    }


    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 Request(요청)

개요

  • GET - 쿼리 파라미터
    • /url?username=hello&age=20
    • 메시지 바디 없이, URL의 쿼리 파라미터에 데이터를 포함해서 전달
    • 예) 검색, 필터, 페이징등에서 많이 사용하는 방식
  • POST - HTML Form
    • content-type: application/x-www-form-urlencoded
    • 메시지 바디에 쿼리 파리미터 형식으로 전달 username=hello&age=20
    • 예) 회원 가입, 상품 주문, HTML Form 사용
  • HTTP message body에 데이터를 직접 담아서 요청
    • HTTP API에서 주로 사용, JSON, XML, TEXT
    • 데이터 형식은 주로 JSON 사용
    • POST, PUT, PATCH

 

GET - 쿼리 파라미터

 

전달 데이터

  • username=hello
  • age=20

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

 

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

  • http://localhost:8080/request-param?usernmae=kim&age=20
@WebServlet(name = "requestHeaderServlet", urlPatterns = "/request-param")
public class HelloServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        printGetParam(req);
    }


    private void printGetParam(HttpServletRequest request) {

        System.out.println("전체 파라미터 조회 start");

        request.getParameterNames().asIterator()
                .forEachRemaining(paramName -> System.out.println(paramName + " = " + request.getParameter(paramName)));

        System.out.println("전체 파라미터 조회 end");

    }
}

 

 

POST - HTML Form

주로 회원 가입, 상품 주문 등에서 사용하는 방식.

 

특징

  • content-type: application/x-www-form-urlencoded
  • 메세지 바디에 쿼리 파라미터 형식으로 데이터를 전달한다.

 

application/x-www-form-urlencoded 형식은 GET에서 살펴본 쿼리 파라미터 형식과 같다.

클라이언트 입장에서는 두 방식에 차이가 있지만, 서버 입장에서는 둘의 형식이 동일하므로, request.getParameter()로 편리하게 사용 가능.

 

참고 

  • GET URL 쿼리 파라미터 형식으로 클라이언트에서 서버로 데이터를 전달할 때는 HTTP 메시지 바디를
    사용하지 않기 때문에 content-type이 없다.
  • POST HTML Form 형식으로 데이터를 전달하면 HTTP 메시지 바디에 해당 데이터를 포함해서 보내기
    때문에 바디에 포함된 데이터가 어떤 형식인지 content-type을 꼭 지정해야 한다.
    • content-type:application/x-www-form-urlencoded 

 

API 메세지 바디 - 단순 텍스트

  • POST http://localhost:8080/request-body-string
  • content-type: text/plain
  • message body: hello
  • 결과: messageBody = hello

참고

  • inputStream은 byte 코드를 반환한다.
  • byte 코드를 우리가 읽을 수 있는 문자(String)로 보려면 문자표(Charset)를 지정해주어야 한다. 
  • 여기서는 UTF_8 Charset을 지정해주었다.
@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");
}

 

 

API 메세지 바디 - JSON

  • JSON 형식 전송
  • POST http://localhost:8080/request-body-json
  • content-type: application/json
  • message body: {"username": "hello", "age": 20}
  • 결과: messageBody = {"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");
    }
}

 

 

 

 


HttpServletResponse 

 

기본 사용법

  • 만들어보자.
@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, must-revalidate");

        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 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");
    }
}

 

 

HTTP 응답 데이터 - 단순 텍스트, HTML

  • HTTP 응답으로 HTML을 반환할 때는 content-type을 text/html 로 지정

 

HTTP 응답 데이터 - API JSON

  • HTTP API - MessageBody JSON 응답
  • application/json 은 스펙상 utf-8 형식을 사용하도록 정의되어 있다. 
  • 스펙에서 charset=utf-8과 같은 추가 파라미터를 지원하지 않는다.

 

@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);
}