이번에는 HTTP API에서 주로 사용하는 JSON 형식으로 데이터를 전달해보자.

 

JSON 형식 전송

POST httmp://localhost:8080/request-body-json

content-type : application/json

message body : {"username": "hello", "age": 20}

결과 messageBody = {"username": "hello", "age": 20}

 

JSON 형식으로 파싱할 수 있게 객체를 하나 생성해야한다.

package hello.servlet.Basic;

import lombok.Getter;
import lombok.Setter;

@Getter @Setter
public class HelloData {

    private String username;
    private int age;


}

Lombok 라이브러리 덕분에 getter, setter를 안만들어줘도 된다.

package hello.servlet.Basic.request;

import com.fasterxml.jackson.databind.ObjectMapper;
import hello.servlet.Basic.HelloData;
import org.springframework.util.StreamUtils;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
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.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);


        System.out.println("HelloData.username = " + helloData.getUsername());
        System.out.println("helloDat.age = " + helloData.getAge());

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

처음에는 messageBody만 콘솔에 찍어보는데 저번에 했던 바디에 메시지 적는 방식과 동일하다 그 이유는

JSON도 텍스트이기 때문이다. 

하지만 Jackson라이브러리를 사용하여 미리 만든 클래스에 매핑시켜 파싱을 한 후 get해보았더니 Json 형태로

알아볼 수 있었다.

 

HTTP 요청 데이터를 웹 브라우저에서 사용하는 방식이 아닌

HTTP message body에 직접 데이터를 담아서 요청하는 방식을 공부해보았다.

 

먼저 가장 단순한 텍스트 메시지를 HTTTP 메시지 바디에 담아서 전송해보았다.

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

 

package hello.servlet.Basic.request;

import org.springframework.util.StreamUtils;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
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.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();
        String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
        System.out.println("messageBody = " + messageBody);
        response.getWriter().write("ok");
    }
}

메시지 바디에 hello를 넣고 (포스트맨 이용)

보내보았더니

ok를 확인할 수 있었다.

보통은 JSON형식으로 주고받는다.

HTML의 Form을 사용해서 클라이언트에서 서버로 데이터 전송을 해보았다.

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

 

특징

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

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

Title
username: age:

html을 하나 만들어주고 전시간에 만들었던 action 값에 request-param을 넣어주면서

전송하였다.

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

쿼리 파라미터 조회 메서드를 그대로 사용하면 된다.

클라이언트 입장에서는 두 방식에 차이가 있지만 서버 입장에서는 둘의 형식이 동일하므로

request.getParameter() 로 구분없이 조회가능하다.

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

 

전달 데이터 

 - username=hello

 - age = 20

 

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

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

 

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

- http://localhost:8080/request-param?username=hello&age=20

 

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

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;

@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");
        System.out.println("username = " + username);
        String age = request.getParameter("age");
        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);
        }

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

1. 전체 파라미터 조회

getParameterNames()을 asIterator를 통해 모두 조회하면서

출력하는것을 확인 할 수 있었다.

 

2. 단일 파라미터 조회

getParamete()에 매개변수로 파라미터이름을 주면 파라미터에대한 데이터를 반환한다.

 

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

만일 이름이 같은 파라미터가 생길 경우 전체 파라미터를 조회하니 하나밖에 뱉지않았다.

이때 getParameterValues()를 사용하면 문자열 배열로 받을 수 있다는 사실을 알았다.

포이치문을 통해 출력해보았다.

 

복수파라미터에서 단일 파라미터 조회

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

중복일 때는 getParameterValues()를 사용해야한다.

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

 

주로 3가지 방법을 사용하는데!

GET - 쿼리 파라미터

 - /url?username=hello&age=20

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

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

 

POST - HTML Form

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

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

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

 

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

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

데이터 형식은 주로  JSON 사용

 - POST, PUT, PATCH

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;

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

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

        String method = request.getMethod();
        String protocol = request.getProtocol();
        printStartLine(request);
        printHeaders(request);


    }

    private void printStartLine(HttpServletRequest request) {
        System.out.println("--- REQUEST-LINE - start ---");
        System.out.println("request.getMethod() = " + request.getMethod()); //GET
        System.out.println("request.getProtocal() = " + 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();
    }

    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 + ": " + headerName);
        }*/

        request.getHeaderNames().asIterator()
                .forEachRemaining(headerName -> System.out.println("headerName = " + headerName));
    }
}

HttpServletRequest 기본 기능들을 사용해보았다.

 

START LINE정보, 헤더정보들을 확인할 수 있었다.

 

'웹프로그래밍 > 스프링 MVC' 카테고리의 다른 글

11. HTTP 요청 데이터 - GET 쿼리 파라미터  (0) 2022.03.15
10. HTTP 요청 데이터 - 개요  (0) 2022.03.15
8. HttpServletRequest - 개요  (0) 2022.03.15
7. Hello 서블릿  (0) 2022.03.14
6. 프로젝트 생성  (0) 2022.03.14

HttpServletRequest 역할

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

메시지를 편리하게 사용할 수 있도록 개발자 대신에 HTTP 요청 메시지를 파싱한다. 그리고 그결과를 HttpServletRequest

객체에 담아서 제공한다.

 

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

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/lecture/71168?volume=1.00&amp;tab=note&amp;speed=0.75

START LINE

- HTTP 메서드

- URL

- 쿼리 스트링

- 스키마, 프로토콜

 

헤더

 - 헤더 조회

 

바디

- form 파라미터 형식 조회

- message body 데이터 직접 조회

 

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

 

임시 저장소 기능

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

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

 - 조회 : request.getAttribute(name)

 

세션 관리 기능

 - request.getSession(create: true)

 

HttpServletRequest, HttpServletResponse를 사용할 때 가장 중요한 점은 이 객체들이 HTTP

요청메시지, 응답 메시지를 편리하게 사용하도록 도와주는 객체라는 점이다. 따라서 이기능에 대해서

깊이있는 이해를 위해선 HTTP 스펙이 제공하는 요청, 응답메시지 자체를 이해해야 한다.

'웹프로그래밍 > 스프링 MVC' 카테고리의 다른 글

10. HTTP 요청 데이터 - 개요  (0) 2022.03.15
9. HttpServletRequest - 기본 사용법  (0) 2022.03.15
7. Hello 서블릿  (0) 2022.03.14
6. 프로젝트 생성  (0) 2022.03.14
5. 자바 백엔드 웹 기술 역사  (0) 2022.03.14

스프링 부트환경에서 서블릿 등록하고 사용해보자

서블릿과 스프링과 관련이 없지만 

스프링 부트는 톰캣 서버를 내장하고 있으므로, 톰캣 서버 설치 없이 편리하게

하기 위해서 이 방식으로 공부하기로 하였다.

 

package hello.servlet;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@ServletComponentScan // 서블릿 자동 등록
@SpringBootApplication
public class ServletApplication {

	public static void main(String[] args) {
		SpringApplication.run(ServletApplication.class, args);
	}

}

스프링 부트 서블릿 환경 구성을 직접 해보았다.

@ServletComponentScan 을 쓰면 스프링이 자동으로 내 패키지를 포함한

하위 패키지를 뒤져서 서블릿을 다 찾아서 등록하고 실행할 수 있도록 도와준다.

 

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")
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 : 서블릿 애너테이션

 

HTTP 요청이 오면 매핑된 URL이 호출되면 서블릿 컨테이너는 service 메서드를 실행한다.

웹 브라우저에 localhost:8080/hello?username=lee라고 요청하였을때 결과이다.

logging.level.org.apache.coyote.http11=debug

applicaton.properties에 위의 코드를 쓰고 재실행하면 HTTP메서드에 대한 자세한 내용들을

확인할 수 있다. 요청이 제대로 되었는지 확인할 수 있다.

그림으로 확인해보자 

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/lecture/71167?volume=1.00&tab=note&speed=0.75

먼저 스프링 부트를 실행하면서 내장 톰캣 서버를 띄어준다.

톰캣 서버는 내부의 서블릿 컨테이너 기능을 가지고 있는데

이것을 통해 서블릿을 생성해준다. 

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/lecture/71167?volume=1.00&tab=note&speed=0.75

request, response 객체를 만들어서 helloServlet을 호출해준다(Service)

필요한 작업을하고 response에 데이터를 넣으면 WAS서버가 response정보를 가지고

HTTP응답 메시지를 만들어서 반환해준다.

'웹프로그래밍 > 스프링 MVC' 카테고리의 다른 글

9. HttpServletRequest - 기본 사용법  (0) 2022.03.15
8. HttpServletRequest - 개요  (0) 2022.03.15
6. 프로젝트 생성  (0) 2022.03.14
5. 자바 백엔드 웹 기술 역사  (0) 2022.03.14
4. HTML, HTTP API, CSR, SSR  (0) 2022.03.12

 

프로젝트를 생성하기위해 start.spring.io에서 옵션들과 dependency를 선택하고

생성하였다.

 

정상 동작까지 확인하였다.

 

API 테스트를 위한 Postman에 가입하고 설치까지 완료하였다.

'웹프로그래밍 > 스프링 MVC' 카테고리의 다른 글

8. HttpServletRequest - 개요  (0) 2022.03.15
7. Hello 서블릿  (0) 2022.03.14
5. 자바 백엔드 웹 기술 역사  (0) 2022.03.14
4. HTML, HTTP API, CSR, SSR  (0) 2022.03.12
3. 동시 요청 - 멀티 쓰레드  (0) 2022.03.12

자바 웹 기술 역사

과거 기술

 

서블릿 - 1997

 - HTML 생성이 어려움

 

JSP - 1999

- HTML 생성은 편리하지만, 비즈니스 로직까지 너무 많은 역할 담당

 

서블릿, JSP 조합 MVC 패턴 사용

- 모델, 뷰 컨트롤러로 역할을 나누어 개발

 

 MVC 프레임워크 춘추 전국 시대 - 2000년 초 ~2010년 초

- MVC 패턴 자동화, 복잡한 웹 기술을 편리하게 사용할 수 있는 다영한 기능 지원

- 스트럿츠, 웹워크, 스프링 MVC


자바 웹 기술 역사

현재 사용 기술

 

애노테이션 기반의 스프링 MVC 등장

- @Controller

- MVC 프레임워크의 춘추 전국 시대 마무리

 

스프링 부트의 등장

- 스프링 부트는 서버를 내장

- 과거에는 서버에 WAS를 직접 설치하고, 소스는 War 파일을 만들어서 설치한 WAS에 배포

- 스프링 부트는 빌드 결과(Jar)에 WAS 서버 포함 -> 빌드 배포 단순화


자바 웹 기술 역사

최신 기술 - 스프링 웹 기술의 분화

 

Web Servlet - Spring MVC

Web Reactive - Spring WebFlux


스프링 웹 플럭스

 

특징

- 비동기 넌 블러킹 처리

- 최소 쓰레드로 최대 성능 - 쓰레드 컨텍스트 스위칭 비용 효율화

- 함수형 스타일로 개발 - 동시처리 코드 효율화

- 서블릿 기술 사용X

 

그런데

- 웹 플럭스는 기술적 난이도 매우 높음

- 아직은 RDB 지원 부족

- 일반 MVC의 쓰레드 모델도 충분히 빠르다.

- 실무에서 아직 많이 사용하지는 않음


자바 뷰 템플릿 역사

HTML을 편리하게 생성하는 뷰 기능

 

JSP

- 속도 느림, 기능 부족

 

프리마커, 벨로시티

- 속도 문제 해결, 다양한 기능

 

타임리프

- 내추럴 템플릿 :  HTML의 모양을 유지하면서 뷰 템플릿 적용 가능

- 스프링 MVC와 강력한 기능 통합

- 최선의 선택, 단 성능은 프리마커, 벨로시티가 더 빠름

'웹프로그래밍 > 스프링 MVC' 카테고리의 다른 글

7. Hello 서블릿  (0) 2022.03.14
6. 프로젝트 생성  (0) 2022.03.14
4. HTML, HTTP API, CSR, SSR  (0) 2022.03.12
3. 동시 요청 - 멀티 쓰레드  (0) 2022.03.12
2. 서블릿  (0) 2022.03.11

+ Recent posts