서블릿(3)

2024. 10. 13. 17:19Web Development/스프링 MVC 1편

HTTP 요청 데이터 - POST HTML Form

이번에는 HTML의 Form을 사용해서 클라이언트에서 서버로 데이터를 전송해보자.

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

 

특징

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

- 메시지바디에 쿼리 파라미터 형식으로 데이터를 전달한다. ex) username=suyeon&age=26

 

webapp> basic> hello-form.html 생성

 

Title
username: age:

 

실행결과

 

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 을 활용한 테스트 

 

 


 

 

 

HTTP 요청 데이터 - API 메시지바디 - 단순 텍스트

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

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

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

- POST, PUT, PATCH

 

1. 가장 단순한 텍스트 메시지를 HTTP 메시지 바디에 담아서 전송하고 읽어보기

- HTTP 메시지바디의 데이터를 InputStream을 사용해서 직접 읽을 수 있다.

 

main> java> basic> request 아래

RequestBodyStringServlet.java 생성

package hello.servlet.basic.request;

import jakarta.servlet.ServletException;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.util.StreamUtils;

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();    //메시지바디의 내용을 byte code로 얻을 수 있다.

        String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);  //byte code -> String
        System.out.println("messageBody = " + messageBody);

        response.getWriter().write("ok");

    }
}

 

 

* POST방식이라 postman을 사용해야함

(url창에서 호출하면 get방식)

 

실행결과

 

 

문자 전송 POST

http://localhost:8080/request-body-string

content-type: text/plain

message body: hello

 

결과: messageBody = hello

 

-> 일반 text보다 주로 JSON을 사용

JSON으로 전달해보자 !


 

HTTP 요청 데이터 - API 메시지바디 - JSON

HTTP 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}

서블릿 생성

package hello.servlet.basic.request;

import jakarta.servlet.ServletException;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.util.StreamUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

@WebServlet(name = "requestBodyJsonServlet", urlPatterns = "/request-body-json")
public class RequestBodyJsonServlet 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);
    }
}

 

 

실행결과

- text 형식으로 일단 받아올 수 있음

-> json형식으로 파싱해보자 !

 

+ JSON 형식 파싱 추가

JSON 형식으로 파싱할 수 있게 객체를 하나 생성하자

'hello.servlet.basic.HelloData'

package hello.servlet.basic;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class HelloData {

    private String username;
    private int age;
}

 

 

RequestBodyJsonServlet.java

package hello.servlet.basic.request;

import com.fasterxml.jackson.databind.ObjectMapper;
import hello.servlet.basic.HelloData;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.logging.log4j.message.Message;
import org.springframework.util.StreamUtils;

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);   //HelloData로 매핑
        System.out.println("helloData.getUsername = " + helloData.getUsername());
        System.out.println("helloData.getAge = " + helloData.getAge());

        response.getWriter().write("ok");
    }
}

 

실행결과

 

 

 


 

HttpServletResponse - 기본 사용법

HttpServletResponse 역할

1. HTTP 응답메시지 생성

- HTTP 응답코드 지정

- 헤더 생성

- 바디 생성

 

2. 편의 기능 제공

- Content-Type, 쿠키, Redirect

 

HttpServletResponse 기본사용법

main> java> hello.servlet.basic.response

ResponseHeaderServlet.java

package hello.servlet.basic.response;

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.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] 200 OK
        response.setStatus(HttpServletResponse.SC_OK);

        //[response-headers]
        response.setHeader("content-type", "text/plain");
        response.setHeader("cache-control", "no-cache, no-store, must-revalidate");    //캐시정보- 캐시무효화
        response.setHeader("Pragma", "no-cache");   //과거버전까지 캐시삭제
        response.setHeader("my-header", "hello");

        PrintWriter writer = response.getWriter();
        writer.println("ok");
    }
}

 

실행결과

 

 

 

* 400 Error 

- setStatus() 변경

: HttpServletResponse 에 정의된 상수를 사용하면 한눈에 보기쉽고 편리함

 

- content-type에 인코딩 "utf-8" 지정하면 한글 사용가능

package hello.servlet.basic.response;

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.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] 400
        response.setStatus(HttpServletResponse.SC_BAD_REQUEST);

        //[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");

        PrintWriter writer = response.getWriter();
        writer.println("안녕하세요.");
    }
}

 

 

* Header 편의 메소드

 

Cookie

package hello.servlet.basic.response;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.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] 200 ok
        response.setStatus(HttpServletResponse.SC_OK);

        //[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);

        //[messageBody]
        PrintWriter writer = response.getWriter();
        writer.print("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); //(생략시 content body로 자동 생성)
    }

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

 

실행결과

 

Redirect

- /basic/hello-form.html로 redirect

package hello.servlet.basic.response;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.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] 200 ok
        response.setStatus(HttpServletResponse.SC_OK);

        //[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);

        //[messageBody]
        PrintWriter writer = response.getWriter();
        writer.print("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); //(생략시 content body로 자동 생성)
    }

    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

 

- 단순 텍스트 응답

ex) writer.println("ok");

- HTML 응답

- HTTP API- MessageBody JSON 응답

 

HttpServletResponse - HTML 응답

hello.servlet.web.response.ResponseHtmlServlet

package hello.servlet.basic.response;

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.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 응답 데이터 - API JSON

hello.servlet.web.response.ResponseJsonServlet

package hello.servlet.basic.response;

import com.fasterxml.jackson.databind.ObjectMapper;
import hello.servlet.basic.HelloData;
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="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.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");

        HelloData helloData = new HelloData();
        helloData.setUsername("choi");
        helloData.setAge(26);
        
        //{"username":"choi", "age":26};
        //json형태로 변경
        String result = objectMapper.writeValueAsString(helloData);
        response.getWriter().write(result);
    }
}

 

실행결과

 

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

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