개발하는 삶
[Spring] HTTP Method 본문
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
- GET URL 쿼리 파라미터 형식
//요청 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 |