개발하는 삶

[Spring] HTTP Method 본문

Spring

[Spring] HTTP Method

삶_ 2022. 7. 11. 21:33

 

HTTP 요청 데이터

 

GET - 쿼리 파라미터

  • /url?username=hello&age=20
  • 메시지 바디 없이, URL 속 쿼리 파라미터에 데이터를 포함해서 전달
  • ex ) 검색, 필터, 페이징 등

POST - HTML Form

  • content-type : application/x-www-form-urlencoded
  • 메시지 바디에 쿼리 파라미터 형식으로 전달
  • 회원 가입, 상품 주문 등 사용

HTTP message body

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

request.getParameter()

  • 쿼리 파라미터, HTML Form. 두가지 요청 파라미터를 조회할 수 있음

 

 

 

GET - 쿼리 파라미터

  • 쿼리 파라미터는 URL에 다음과 같이 ? 를 시작으로 보낼 수 있다. 추가 파라미터는 & 로 구분하면 된다. http://localhost:8080/request-param?username=hello&age=20
  • HttpServletRequest 가 제공하는 메서드들로 쿼리 파라미터를 편리하게 조회 가능
  • getParameter() 의 반환 기본값은 문자열임

 

쿼리 파라미터 조회 메서드

  • ?username=hello&age=20 을 URL 뒤에 붙여 HTTP 요청을 할 시,
  • username => 키, hello => 값 으로 생각하면 편함
  • 값을 구한다고 보면 된다
  • 복수 파라미터에서 단일 파라미터 조회하기
    • username=hello&username=kim 과 같이 파라미터 한개. 값이 중복 일때,
    • request.getParameterValues("username") 사용!
      • request.getParameter("username") 는 1개 파라미터에 단 하나의 값이 있을때만 써야 함
      • 안그러면 딱 첫번째 값만 반환함. (=hello)
String username = request.getParameter("username"); //단일 파라미터 조회
Enumeration<String> parameterNames = request.getParameterNames(); //파라미터 이름들
모두 조회
Map<String, String[]> parameterMap = request.getParameterMap(); //파라미터를 Map
으로 조회
String[] usernames = request.getParameterValues("username"); //복수 파라미터 조회

 

 

 

HTTP 요청 - POST HTML Form

  • GET 쿼리 파라미터 형식과 같은 점
    • request.getParameter() 로 편리하게 GET URL 쿼리 파라미터 형식, POST HTML Form 형식도 지원함
  • 다른점
    • GET URL 쿼리 파라미터 형식
      • 클라이언트에서 서버로 데이터를 전달 시,
      • HTTP 메시지 바디(<html></html>...)를 사용하지 않아서 content-type 이 없음
    • POST HTML Form 형식
      • HTTP 메시지 바디에 해당 데이터를 포함해서 보냄
      • 바디에 포함된 데이터가 어떤 형식인지 content-type을 꼭 지정해야 함
      • 이렇게 폼으로 전송하는 형식 : application/x-www-form-urlencoded
//요청 URL이 http://localhost:8080/request-param 일 때,
//content-type 은 아래와 같다 (GET 쿼리 파라미터 조회 메서드를 그대로 사용)
content-type: application/x-www-form-urlencoded

 

 

 

HTTP 요청 - API 메시지 바디 (JSON)

  • content-type : application/json
  • JSON 형식으로 파싱 추가하기
// JSON 형식 전송
@WebServlet(name = "requestBodyJsonServlet", urlPatterns = "/request-body-json")
public class RequestBodyJsonServlet extends HttpServlet {

	// JSON 결과를 파싱해서 사용할 수 있는 자바 객체로 변환하기
    // Jackson (JSON 라이브러리 = ObjectMapper)을 추가해서 사용해야 함
	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);
 		
        // readValue(a, type(보통 클래스 객체)) : 지정된 type으로 변환하는 a
        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");
 }
}

}

 

 

 

그 외 용어

@AfterEach

  • @Test 메서드 실행 후 무조건 실행됨
  • 초기화할때 보통 사용

getInstance()

  • A a = A.getInstance();
  • 싱글톤 인스턴스를 만들 때 사용 (스프링 컨테이너 정의 시 기본값 =  싱글톤)
  • 한번만 생성된 객체의 메모리를 계속 쓰기위해 씀

assertThat

  • Assertions.assertThat()
  • 어떤 조건이 참/거짓인지 확인하는 구문
  • assertThat(a).isEqualTo(b) : a와 b는 내용이 같다
  • assertThat(a).isNotEqualTo(b) : a와 b는 내용이 같지 않다

 

 

 

MVC 프레임워크 - 프론트 컨트롤러 패턴

 

JSP와 Servlet으로만 만든 MVC 패턴의 한계점

 

MVC 패턴 방식

  • 뷰와 서비스는 무조건 컨트롤러를 거친다
  • 클라이언트 ▶ 컨트롤러 ▶ 뷰 or 서비스 로직

Servlet = 컨트롤러, JSP = 뷰

  • JSP
    • Model은 HttpServletRequest 객체를 사용
    • request.setAttribute("객체명", 객체) , request.getAttribute("객체명", 객체)
      • 데이터를 보관/꺼냄
  • Servlet
    • String viewPath = "/WEB-INF/views/new-form.jsp";  //보여지는 사이트는 이것이다
    • RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
      dispatcher.forward(request, response);  //다른 서블릿/JSP으로 항목들 전달

한계점

  • 로직이 중복되거나 공통처리가 어려움
  • -> 프론트 컨트롤러 패턴 도입해서 해결하기

 

 

전체적인 패턴

  • 프론트 컨트롤러 -> ( 컨트롤러 인터페이스를 상속 ) 각자 기능을 가진 컨트롤러 클래스들 -> 뷰 객체 공유
    • return new MyView("도메인 제외하고~파일이름까지 경로");
  • 프론트 컨트롤러 인터페이스의 서블릿 하나로 클라이언트 요청을 받고,
  • 요청에 맞는 컨트롤러를 찾아 호출

 

MyView

  • 여러 객체가 뷰를 공유할 수 있게 뷰 객체를 만듬
public class MyView {
 	private String viewPath;
    
 	public MyView(String viewPath) {
 		this.viewPath = viewPath;
 	}
    
    //컨트롤러들이 공유할 뷰객체 소환
    //forward 로직 수행 후 JSP 실행
 	public void render(HttpServletRequest request, HttpServletResponse 
	response) throws ServletException, IOException {
		RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
 		dispatcher.forward(request, response);
 	}
}
//프론트 컨트롤러에 대한 내용

@WebServlet(name = "frontControllerServletV2", urlPatterns = "/frontcontroller/v2/*")
public class FrontControllerServletV2 extends HttpServlet {

 	private Map<String, ControllerV2> controllerMap = new HashMap<>();
 	public FrontControllerServletV2() {
    
 	controllerMap.put("/front-controller/v2/members/new-form", new MemberFormControllerV2());
 	controllerMap.put("/front-controller/v2/members/save", new MemberSaveControllerV2());
 	controllerMap.put("/front-controller/v2/members", new MemberListControllerV2());
 }
 
 @Override
 protected void service(HttpServletRequest request, HttpServletResponse response)
 throws ServletException, IOException {

        String requestURI = request.getRequestURI();
        ControllerV2 controller = controllerMap.get(requestURI);

        if (controller == null) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        
		//MyView의 render() 을 사용
        MyView view = controller.process(request, response);
        view.render(request, response);
 	}
}

 

 

 

출처

'Spring' 카테고리의 다른 글

[Spring] HTTP 요청/응답  (0) 2022.07.23
[Spring] 스프링 MVC  (0) 2022.07.20
[Spring] 웹서버  (0) 2022.07.09
[Spring] 스코프, 프록시  (0) 2022.07.06
spring (3) - 의존관계 주입  (0) 2022.07.05