김영한님의 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술(유료강의)을 보면서 공부한 내용입니다.
스프링 프로젝트를 생성하기 위해 스프링 부트 스타터에서 다음과 같이 설정한다.
💡 jar가 아닌 war로 설정하는 이유?
→ war로 해야 JSP를 사용가능하다. war는 톰캣서버를 별도로 쓰거나 내장할 때 사용 가능하다.
인텔리제이를 킨 후 열어야할 파일의 build.gradle
을 클릭해서 폴더를 연다.
추가로 Lombok
또한 File → Settings → plugins
에서 따로 설치해야 된다.
ServletApplication
에 @ServletComponentScan
어노테이션을 작성한다.
해당 어노테이션은 스프링이 자동으로 현재 나의 패키지를 포함한 모든 하위패키지에 있는 서블릿을 찾아 서블릿 등록하도록 도와준다. 즉, 서블릿을 자동 등록해준다.
@ServletComponentScan // 자동으로 서블릿을 등록해서 사용할 수 있도록 도와줌
@SpringBootApplication
public class ServletApplication {
public static void main(String[] args) {
SpringApplication.run(ServletApplication.class, args);
}
}
package hello.servlet.basic.HelloServlet
클래스를 생성한다.
서블릿으로 등록하기 위해 @WebServlet
어노테이션을 실행한다.
// name : 서블릿 이름 urlPatterns : URL 매핑
// "/hello"를 실행하면 서블릿 컨테이너는 해당 메서드를 실행한다.
@WebServlet(name="helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
Ctrl + O
를 눌러 열쇠가 있는 service
메소드를 선택한다.
쿼리 파라미터를 요청해 응답값을 확인한다.
String username = request.getParameter("username"); // 요청된 쿼리 파라미터 확인
// 쿼리 파라미터 값 (응답값)
response.setContentType("text/plain");
response.setCharacterEncoding("utf-8");
response.getWriter().write("hello " + username);
HTTP 요청 메세지를 파싱한 결과를 HttpServletRequest
객체에 담아서 전송하여, 편리하게 조회할 수 있다.
* HTTP 요청 메세지 *
POST /save HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
username=kim&age=20
START LINE
- HTTP 메소드, URL, 쿼리 스트링, 스키마, 프로토콜
헤더
- 헤더 조회
바디
- form 파라미터 형식 조회, message body 데이터 직접 조회
💡 HttpServletRequest 객체는 임시 저장소, 세션 관리 기능 또한 제공한다.
package hello.servlet.basic.request.RequestHeaderServlet
클래스를 생성한 후 서블릿 어노테이션을 추가한다.
START LINE 정보
HEADER 정보
HTTP 요청 메시지의 모든 헤더의 내용을 출력하기 위한 메서드를 만들어 내용을 확인한다.
HEADER 편의 조회
서버이름, 포트, 언어, 쿠키 등 원하는 헤더의 내용 또한 조회 가능하다.
기타 조회
HTTP 정보가 아닌 내부에서 이뤄진 네트워크 커넥션에 대한 정보들
HTTP 요청 메시지를 통해 클라이언트에서 서버로 데이터를 전달하는 방법은 주로 3가지 방법이 있다.
- GET - 쿼리 파라미터
- /url?username=hello&age=20
- 메시지 바디 없이, URL의 쿼리 파라미터에 데이터를 포함해서 전달
- EX) 검색, 필터, 페이징 등
- POST - HTML Form
- content-type : application/x-www-form-urlencoded
- 메시지 바디에 쿼리 파리미터 형식으로 전달 username=hello&age=20
- EX) 회원 가입, 상품 주문, HTML Form 사용
- HTTP message body에 데이터를 직접 담아서 요청
- HTTP API에서 주로 사용, JSON, XML, TEXT
- 데이터 형식은 주로 JSON 사용- POST, PUT, PATCH
메세지 바디 없이, 쿼리 파라미터를 사용해서 데이터를 전달한다.
쿼리 파라미터는 URL에 ?
를 시작으로 보낼 수 있고, 추가 파라미터는 &
로 구분하면 된다.
package hello.servlet.basic.request.RequestParamServlet
클래스를 생성한 후 서블릿 어노테이션을 추가한다.
request.getParameterNames().asIterator()
.forEachRemaining(paramName -> System.out.println(paramName + " = " + request.getParameter(paramName)));
String username = request.getParameter("username");
String age = request.getParameter("age");
하나의 파라미터 이름에 여러값을 넘길 수 있다.
http://localhost:9090/request-param?username=hello&age=20&username=hello2
String[] usernames = request.getParameterValues("username");
for (String name : usernames) {
System.out.println("username = " + name);
}
💡 중복일 때 getParameter()을 사용하면 첫 번째 값을 반환한다.
HTML의 Form을 사용해서 클라이언트에서 서버로 데이터를 전송한다. 주로 회원 가입, 상품 주문 등에서 사용하는 방식이다.
- Content-Type: application/x-www-form-urlencoded
- 메시지 바디에 쿼리 파리미터 형식으로 데이터를 전달
ex) username=hello&age=20
src/main/webapp/basic/hello-form.html
에 html Form을 추가하여 /request-param 으로 데이터를 보내도록 코드를 작성한다.
전송을 누르면 RequestParamServlet
메서드가 실행돼서 입력한 값들이 아래와 같이 조회된다.
웹 입장에서는 두 방식에 차이가 있지만, 서버 입장에서는 둘의 형식이 동일하므로, request.getParameter()
로 편리하게 구분없이 조회할 수 있다.
💡
request.getParameter()
는 GET, POST 둘 다 지원한다.
- HTTP message body에 데이터를 직접 담아서 요청
- HTTP API에서 주로 사용, JSON, XML, TEXT
- 데이터 형식은 주로 JSON 사용
- POST, PUT, PATCH
package hello.servlet.basic.request.RequestBodyStringServlet
클래스를 생성한 후 서블릿 어노테이션을 추가한다.
ServletInputStream inputStream = request.getInputStream();
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
포스트맨을 통해서 파라미터 값을 전송하면 content-Type이 text/plain
인 것을 확인할 수 있다.
결과값
JSON형식으로 파싱할 수 있게 HelloData
객체를 생성한다.
package hello.servlet.basic.request.RequestBodyJsonServlet
클래스를 생성한 후 서블릿 어노테이션을 추가한다.
ServletInputStream inputStream = request.getInputStream();
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
결과값
JSON 결과를 파싱해서 HelloData
객체로 변환시키기 위해서는 JSON 변환 라이브러리인 ObjectMapper
을 추가해야 한다.
private ObjectMapper objectMapper = new ObjectMapper();
HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);
결과값
HttpServletResponse 역할
- HTTP 응답 메시지 생성: HTTP 응답코드 지정, 헤더 생성, 바디 생성
- 편의 기능 제공: Content-Type, 쿠키, Redirect
package hello.servlet.basic.reponse.ResponseHeaderServlet
클래스를 생성한 후 서블릿 어노테이션을 추가한다.
HTTP 응답 메세지를 작성한다.
// [STATUS-LINE]
response.setStatus(HttpServletResponse.SC_OK); // 상수로 정의되어 있는 HTTP 응답 코드
// [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"); // http 응답에 나옴
작성 후 아래 로컬 주소에 들어가면 응답 메세지 값을 확인할 수 있다.
http://localhost:9090/response-header
기본 메서드보다 간편하게 작성할 수 있는 방법이다.
1. 기본 Content-Type 메서드
response.setContentType("text/plain");
response.setCharacterEncoding("utf-8");
2. 쿠키 편의 메서드
Cookie cookie = new Cookie("myCookie", "good");
cookie.setMaxAge(600); //600초
response.addCookie(cookie);
3. Redirect 편의 메서드
response.sendRedirect("/basic/hello-form.html");
응답 메세지 결과값
package hello.servlet.basic.reponse.ResponseHtmlServlet
클래스를 생성한 후 서블릿 어노테이션을 추가한다.
응답 메세지 Header 값에 Content-type을 정해준다.
// Content-Type : text/html;charset=utf-8
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
message body로 HTML 응답을 보내준다.
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
로 지정해야 한다. 페이지 소스보기를 사용하면 결과 HTML을 확인할 수 있다.
package hello.servlet.basic.reponse.ResponseJsonServlet
클래스를 생성한 후 서블릿 어노테이션을 추가한다.
응답 메세지 Header 값에 Content-type을 정해준다.
// Content-Type : application/json
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
HelloDate 객체에 응답 값을 넣는다.
HelloData helloData = new HelloData();
helloData.setUsername("kim");
helloData.setAge(20);
객체를 JSON 형식으로 변경하기 위해 JSON 변환 라이브러리인 ObjectMapper를 사용하여 값을 변경한다.
// {"username":"kim", "age:20}
String result = objectMapper.writeValueAsString(helloData); // 객체를 JSON문자로 변경
response.getWriter().write(result);
HTTP 응답으로 JSON을 반환할 때는 content-type을 application/json
로 지정해야 한다.
Jackson 라이브러리가 제공하는 objectMapper.writeValueAsString() 를 사용하면 객체를 JSON문자로 변경할 수 있다.