Notice
suyeonme
[Java] Servlet이란? 본문
Servlet이란?
클라이언트의 요청(request)을 처리하고 응답(response)을 반환하는 Servlet 클래스를 따라는 자바 프로그램이다.
Servlet 특징
- HttpServletRequest로 HTTP 요청을 쉽게 다룰 수 있다. (query string, 메세지 바디 조회등)
- HttpServletResponse로 HTTP 응답을 쉽게 다룰 수 있다. (status code, content-type, cookie, redirect등)
- 개발자는 서블릿을 사용하여 HTTP를 쉽게 핸들링할 수 있다.
Servlet 예시 코드
@WebServlet(name = "requestParamServlet", urlPatterns = "/request-param")
public class RequestServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException {
//...
}
}
Servlet Container
서블릿을 관리해주는 컨테이너로, 클라이언트의 요청을 받고 응답을 할 수 있도록 웹서버와 소켓으로 통신한다. 대표적으로 톰캣(Tomcat)이 있다.
Servlet없이 직접 HTTP 요청을 구현한다면?
만약 Servlet없이 HTTP 요청을 직접 구현한다고 가정하면 아래의 단계를 거칠 것 이다.
Servlet은 복잡한 아래 과정을 대신 처리해준다.
- 서버에서 TCP/IP(or UDT) 연결을 대기하고 소켓을 연결한다.
- http 요청 메세지를 파싱한다. (Content-type 확인 및 Method등 확인, HTTP Body 파싱)
- 저장 프로세스를 실행한다.
- 비즈니스 로직을 실행한다.
- HTTP 응답 메세지를 생성한다.(HTTP Header, Message Body 입력등)
- TCP/IP에 응답을 전달하고 소켓을 종료한다.
HttpServletRequest (요청)
HTTP 요청 파라미터를 조회한다.
1. Query String을 사용하는 경우
- /request-param?username=suyeon&age=27
- request.getParameter을 주로 사용한다.
- HTML Form을 전송하는 경우 동일하게 동작한다.
- content-type: application/x-www-form-urlencoded
- 메세지 바디에 쿼리파라미터 형식으로 전달한다(username=suyeon&age=27)
@WebServlet(name = "requestParamServlet", urlPatterns = "/request-param")
public class RequestServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException {
// 전체 파라미터 조회
req.getParameterNames().asIterator()
.forEachRemaining(paramName -> System.out.println(paramName + "=" + req.getParameter(paramName)));
}
// 개별 파라미터 조회
String username = req.getParameter("username");
// 응답
res.getWriter().write("ok");
}
2. POST의 메세지 바디를 사용하는 경우
- HTTP 메세지 바디의 데이터를 inputStream으로 읽을 수 있다.
- inputStream은 바이트 코드를 반환한다.
@WebServlet(name = "requestBodyStringServlet", urlPatterns = "/request-body-string")
public class RequestBodyStringServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException {
ServletInputStream inputStream = req.getInputStream(); // 바이트코드로 값을 얻음
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8); // 바이트코드를 문자열로 변환
res.getWriter().write("ok");
}
}
3. JSON형식의 메세지 바디를 사용하는 경우
- content-type: application/json
- Jackson 라이브러리를 사용하여 JSON 데이터를 파싱한다.
- Jackson 라이브러리는 스프링에 기본으로 내장되어있다.
- JSON 변환 라이브러리
// 롬복 라이브러리 사용
@Getter @Setter
public class UserData {
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 req, HttpServletResponse res) throws ServletException {
ServletInputStream inputStream = req.getInputStream(); // 바이트코드로 값을 얻음
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8); // 바이트코드를 문자열로 변환
UserData userData = objectMapper.readValue(messageBody, UserData.class); // JSON 데이터를 객체로 변환
System.out.println(userData.getUsername());
res.getWriter().write("ok");
}
}
HttpServletResponse (응답)
HTTP 헤더 설정 및 응답 메세지를 생성한다.
사용 예시
- 텍스트 응답: res.getWriter().write("OK")
@WebServlet(name = "responseHeaderServlet", urlPatterns = "/response-header")
public class responseHeaderServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException {
// [status-line]
res.setStatus(HttpServletResponse.SC_OK); // 200
// [response-headers];
res.setHeader("Content-Type", "text/plain");
// res.setContentType("text/plain"); 위와 동일
res.setCharacterEncoding("utf-8");
res.setHeader("Cache-Control", "no-cache", "no-store", "must-revalidate");
res.setHeader("Pragma", "no-cache");
// [cookie]
Cookie cookie = new Cookie("testCookie", "good");
coockie.setMaxAge(600);
res.addCookie(cookie);
// [redirect]
res.sendRedirect("/test/index.html")
// [message body]
res.getWriter().write("ok");
}
}
1. HTML 응답
- content-type: text/html
- HTML 코드를 아래와 같이 직접 작성하는 것은 불편하다. 따라서 템플릿 엔진을 사용하여 동적으로 HTML을 작성할 수 있다.
- JSP, velocity, thymeleaf, freemarker등
@WebServlet(name = "responseHtmlServlet", urlPatterns = "/response-html")
public class ResponseHtmlServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException {
res.setContentType("text/html");
res.setCharacterEncoding("utf-8");
PrintWriter writer = res.getWriter();
writer.println("<html>");
writer.println("<body>");
writer.println("<div>Hello World</div>");
writer.println("</body>");
writer.println("</html>");
}
}
2. JSON 응답
- content-type: application/json
- 잭슨 라이브러리의 objectMapper.writeValueAsString 를 사용하여 객체를 JSON으로 변환한다.
@WebServlet(name = "responseJsonServlet", urlPatterns = "/response-json")
public class ResponseJsonServlet extends HttpServlet {
private ObjectMapper objectMapper = new ObjectMapper(); // 잭슨 라이브러리
@Override
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException {
res.setContentType("application/json");
res.setCharacterEncoding("utf-8");
UserData userData = new UserData();
userData.setUsername("suyeon");
userData.age(27);
// JSON으로 변환
String result = objectMapper.writeValueAsString(userData);
res.getWriter().write(result);
}
}
'프로그래밍👩🏻💻 > Java' 카테고리의 다른 글
[Java] 람다 표현식(Lamda Expression)과 함수형 인터페이스(Functional Interface) (0) | 2023.03.01 |
---|---|
[Java] Boxing, Unboxing이란? (0) | 2023.03.01 |
[Java] BufferedReader/BufferedWriter (0) | 2022.08.07 |
[Java] Array, ArrayList (0) | 2022.06.06 |
[Java] Scanner란? (0) | 2022.06.05 |
Comments