IT recording...
[스프링 MVC1] 2. 서블릿 본문
원문 링크
https://adorable-aspen-d23.notion.site/MVC1-2-b1a5d20371de45a5a22787c30c3064f5
김영한님의 [스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술] 강의를 듣고 작성한 글입니다.
1. 서블릿
: 동적 웹 페이지를 만들 때 사용되는 자바 기반의 웹 어플리케이션 프로그래밍 기술
- 요청(request)와 응답(response)를 간단한 메서드 호출만으로 다룰 수 있게 해주는 기술
- 웹 서버에서 서블릿 인스턴스를 생성 후 서버에서 실행되다가, 웹 브라우저에서 서버에 요청을 하면 동작을 수행하고 웹 브라우저에 응답하는 방식으로 작동한다.
특징
- 클라이언트의 request에 대해 동적으로 작동하는 웹 어플리케이션 컴포넌트
- html을 이용하여 response한다
- 쓰레드를 이용한다.
서블릿 컨테이너
: 서블릿을 담고 관리해주는 컨테이너
- HttpServletRequest, HttpServletResponse 두 객체를 생성하여 동적인 페이지 생성 후 응답을 보낸다.
- HttpServletRequest
- http프로토콜의 request정보를 servlet에게 전달하기 위한 목적
- 헤더 정보, 파라미터, 쿠키, URI, URL등의 정보를 읽어 들이는 메서드와 Body의 Stream을 읽어 들이는 메서드
- HttpServletResponse
- WAS가 클라이언트에게 응답을 보내기 위해 이 객체를 생성하여 서블릿에게 전달하고, content type, 응답코드, 응답 메시지 등을 전송한다.
- 주요 기능
- 생명주기 관리
- 서블릿의 생명주기를 관리한다. 서블릿 컨테이너가 기동 되는 순간 서블릿 클래스를 로딩해서 인스턴스화하고, 초기화 메서드를 호출하고, 요청이 들어오면 적절한 서블릿 메서드를 찾아 동작한다.
- 서블릿의 생명이 다하는 순간 가비지 컬렉션을 통해 메모리에서 제거한다.
- 통신 지원
- 소켓을 생성하고, 특정 포트를 리스닝하고, 연결 요청이 들어오면 스트림을 생성해서 요청을 받는 과정을 통해 통신을 수행해야하는데,
- 서블릿 컨테이너가 이를 대신 해준다.
- 개발자가 비즈니스 로직에 더 집중할 수 있다.
- 멀티스레딩 관리
- 동시에 여러 요청이 들어와도 멀티스레딩을 이용하여 동시다발적인 작업을 관리할 수 있다.
- 선언적인 보안관리
- 서블릿 컨테이너는 보안 관련 기능을 지원하기 때문에, 서블릿 또는 자바 클래스 안에 보안 관련된 메서드를 구현하지 않아도 된다.
- 생명주기 관리
참고
https://coding-factory.tistory.com/742
2. HttpServletRequest
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 데이터 직접 조회
* HTTP 요청 데이터
- GET - 쿼리 파라미터
- /url?username=hello&age=20
- 메시지 바디 없이 쿼리 파라미터에 데이터를 포함해서 전달
- 검색,필터,페이징 등에서 많이 사용
- POST - HTML Form
- content-type:application/x-www-form-urlencoded
- 메시지 바디에 쿼리 파라미터 형식으로 전달 username=hello&age=20
- 회원가입,상품주문,HTML Form 사용
- HTTP message body에 직접 데이터 담아 요청
- HTTP API에서 사용, JSON, XML, TEXT
- 주로 JSON사용 (POST,PUT,PATCH)
2-1) HTTP request - GET 쿼리 파라미터
<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("[전체 파라미터 조회 - end]");
System.out.println();
System.out.println("[단일 파라미터 조회 - start]");
String username = **request.getParameter**("username");
String age = request.getParameter("age");
System.out.println("age = " + age);
System.out.println("username = " + username);
System.out.println("[단일 파라미터 조회 - end]");
}
}
[전체 파라미터 조회] - start
username=hello
age=20
[전체 파라미터 조회] - end
[단일 파라미터 조회] request.getParameter(username) = hello request.getParameter(age) = 20
[이름이 같은 복수 파라미터 조회] request.getParameterValues(username) username=hello
username=kim
2-2) HTTP request - POST HTML Form
<http://localhost:8080/basic/hello-form.html>
요청 url : <http://localhost:8080/request-param>
content-type : application/x-www-form-urlencoded
message body : username=hello&age=20
- 쿼리 파라미터 조회 형식과 같기 때문에 /request-param을 그대로 사용하면 된다.
2-3) HTTP request - API 메시지 바디 - 단순 text
POST <http://localhost:8080/request-body-string>
@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();** //메시지 바디가 byte값으로 읽어와짐
String messageBody = **StreamUtils.copyToString**(inputStream, StandardCharsets.UTF_8);//바이트를 String으로
System.out.println("messageBody = " + messageBody);
response.getWriter().write("ok");
}
}
2-4) HTTP request - API 메시지 바디 - JSON
POST <http://localhost:8080/request-body-json>
content-type: application/json
message body: {"username": "hello", "age": 20}
결과: messageBody = {"username": "hello", "age": 20}
@Getter
@Setter
public class HelloData {
private String username;
private int age;
}
@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);//기본으로 제공하는 objectMapper를 통해 json을 객체로 바로 매핑
System.out.println("helloData.getUsername() = " + **helloData.getUsername()**);
System.out.println("helloData.getAge() = " + **helloData.getAge()**);
response.getWriter().write("ok");
}
}
3. HttpServletResponse
- 기능
- HTTP 응답코드 지정
- 헤더 생성
- 바디 생성
-
- content-type, 쿠키, redirect
3-1) HTTP response
@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-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");**
//[Header 편의 메서드]
content(response);
cookie(response);
redirect(response);
//[message body]
PrintWriter writer = response.getWriter();
writer.println("ok");
}
}
- content 편의 메서드
private void content(HttpServletResponse response) {
//Content-Type: text/plain;charset=utf-8
//Content-Length: 2
//response.setHeader("Content-Type", "text/plain;charset=utf-8");
response.setContentType("text/plain");
response.setCharacterEncoding("utf-8");
//response.setContentLength(2); //(생략시 자동 생성)
}
- 쿠키 편의 메서드
private void cookie(HttpServletResponse response) {
//Set-Cookie: myCookie=good; Max-Age=600;
//response.setHeader("Set-Cookie", "myCookie=good; Max-Age=600");
Cookie cookie = new Cookie("myCookie", "good");
cookie.setMaxAge(600); //600초
response.addCookie(cookie);
}
- redirect 편의 메서드
private void redirect(HttpServletResponse response) throws IOException {
//Status Code 302
//Location: /basic/hello-form.html
//response.setStatus(HttpServletResponse.SC_FOUND); //302
//response.setHeader("Location", "/basic/hello-form.html");
response.sendRedirect("/basic/hello-form.html");
}
3-2) HTTP response - 단순 텍스트, HTML
- 단순 텍스트
writer.println("ok");
- HTML
<http://localhost:8080/response-html>
@WebServlet(name = "responseHtmlServlet", urlPatterns = "/response-html")
public class ResponseHtmlServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//contentType: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>");
}
}
3-3) HTTP response - JSON
<http://localhost:8080/response-json>
@WebServlet(name = "responseJsonServlet", urlPatterns = "/response-json")
public class ResponseJsonServlet extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//Content-Type:application/json
response.setContentType("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);
}
}
'Spring' 카테고리의 다른 글
[스프링 MVC1] 4. MVC 프론트 컨트롤러 패턴 (0) | 2022.01.14 |
---|---|
[스프링 MVC1] 3. 서블릿,JSP,MVC 패턴 (0) | 2022.01.14 |
[스프링 MVC1] 1. 웹 애플리케이션 이해 (0) | 2022.01.14 |
[Spring] GithubAction + S3 + CodeDeploy + NginX를 이용한 무중단 배포 (0) | 2022.01.13 |
[Spring] 자동배포시 secret 관리 (0) | 2022.01.13 |
Comments