본문 바로가기
Java , Spring/Spring

스프링 MVC 1 - 서블릿 servlet (2)

by 방배킹 2023. 7. 2.

Hello 서블릿

프로젝트를 생성한뒤 코드를 작성해 보자.

 

먼저 spring boot에서 servlet을 사용하려면

@ServletComponentScan

 

를 통해 자동으로 servlet을 등록해준다.

 

hello.servlet.basic에 HelloServlet 클래스를 만든다.

@WebServlet(name = "helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("HelloServlet.service");
    }
}

이때 ctrl+o를 통해 메서드를 자동으로 만들수 있다.

잘 실행이 된다.

 

@WebServlet(name = "helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
    @Override
    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");
        response.setCharacterEncoding("utf-8");
        response.getWriter().write("hello " + username);
    }
}

 

  • @WebServlet 서블릿 애노테이션
    • name: 서블릿 이름
    • urlPatterns: URL 매핑

application.properties에 logging.level.org.apache.coyote.http11=debug를 추가해주면

서버가 받은 HTTP 요청 메시지를 출력하는것을 확인할 수 있다.

 

welcome page 만들기

main.webapp에 index.html을 만들면 localhost:8080을 호출하면 index.html 페이지가 열린다.

 

HttpServletRequest - 개요

서블릿은 개발자가 HTTP 요청 메시지를 편리하게 사용할 수 있도록 개발자 대신에 HTTP 요청 메시지를 파싱한다.

해당 결과를 HttpServletRequest 객체에 담아서 제공한다.

 

HttpServletRequest - 기본 사용법

hello.servlet.basic.request에 RequestHeaderServlet 클래스를 만들자.

@WebServlet(name = "requestHeaderServlet", urlPatterns = "/request-header")
public class RequestHeaderServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        printStartLine(request);
        printHeaders(request);
        printHeaderUtils(request);
        printEtc(request);
    }
}

start-line 정보, 헤더 정보,Header 편리한 조회, 기타정보 조회가 가능하다.

HTTP 요청 데이터 - 개요

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

 

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

username=hello와 age=20을 전달한다고 하면

http://localhost:8080/request-param?username=hello&age=20 다음과 같이 전달하면된다.

?로 시작을 하고 &로 추가 파라미터를 구분한다.

 

/**
 * 1. 파라미터 전송
 * http://localhost:8080/request-param?username=hello&age=20
 */
@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("[단일 파라미터 조회] - start");
        String username = request.getParameter("username");
        String age = request.getParameter("age");

        System.out.println("username = " + username);
        System.out.println("age = " + age);

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

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

각각의 방법으로 전체 파라미터 조회, 단일 파라미터 조회, 중복되는 복수의 파라미터를 조회 할 수 있다.

 

HTTP 요청 데이터 -  POST HTML Form

content-type은 다음과 같다

application/x-www-form-urlencoded

get방식과 같이 쿼리 파라미터 방식으로 전달한다. ex) username=hello&age=20

<form action="/request-param" method="post">
 username: <input type="text" name="username" />
 age: <input type="text" name="age" />
 <button type="submit">전송</button>
</form>

위와 같이 입력창을 만든다. 해당 form은 action이 /request-param으로 넘어가고 

전체 파라미터 조회, 단일 파라미터 조회, 중복되는 복수의 파라미터가 출력된다.

결과적으로 POST 방식은 GET 방식의 쿼리 파라미터 방법과 같은 형식으로 전송이된다.

 

POST 방식은 content-type은 application/x-www-form-urlencoded 이고, message body는 username=hello&age=20 이다.

반면에 GET 쿼리 파라미터 방식은 HTTP 메시지 바디를 사용하지 않기 때문에 content-type이 없다.

 

형식이 똑같기 때문에 request.getparameter를 통해 둘다(get,post) 꺼낼수 있다.

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

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

 

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

content-type: text/plain

message body: hello

결과: messageBody = hello

@WebServlet(name = "eequestBodyStringServlet",urlPatterns = "/request-body-string")
public class RequestBodyStringServlet 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);

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

postman을 이용해서 text전송을 해보자

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}

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

.

JSON 결과를 파싱해서 사용할 수 있는 자바 객체로 변환하려면 Jackson, Gson 같은 JSON 변환 라이브러리를 추가해서 사용해야 한다.

스프링 부트로 Spring MVC를 선택하면 기본으로 Jackson 라이브러리( ObjectMapper )를 함께 제공한다.

 

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

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

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

setHeader를 통해 응답코드(HttpServletResponse.SC_OK)와 응답헤더(Content-Type 등등)를 설정 할 수 있다.

response.setStatus(HttpServletResponse.SC_BAD_REQUEST);

SC_BAD_REQUEST를 사용하면 아래와 같이 상태코드가 400이 된다.

response.setHeader("Content-Type", "text/plain;charset=utf-8");

 

 

 

위에서 사용한 해당 코드는 아래의 코드로 변경 할 수 있다.

response.setContentType("text/plain");
response.setCharacterEncoding("utf-8");

 

cookie도 setHeader 함수를 통해 설정 할 수 있지만, cookie 객체를 통해 더 쉽게 설정 할 수 있다.

Cookie cookie = new Cookie("myCookie", "good");
cookie.setMaxAge(600); //600초
response.addCookie(cookie);

 

HttpServletResponse - HTML 응답

HTTP 응답으로 HTML을 반환할 때는 content-type을 text/html 로 지정해야 한다.

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

HTTP 응답으로 JSON을 반환할 때는 content-type을 application/json 로 지정해야 한다

//Content-Type: application/json
response.setHeader("content-type", "application/json");
response.setCharacterEncoding("utf-8");
HelloData helloData = new HelloData();
helloData.setUsername("kim");
helloData.setAge(20);

//{"username":"kim","age":20}
String result = objectMapper.writeValueAsString(helloData);
response.getWriter().write(result);

 

댓글