2022년 7월 23일 토요일

JSP 11강 - 서블릿(Servlet)

1. 서블릿이란?

JSP가 나오기 전 자바로 웹 애플리케이션을 개발할 수 있도록 만든 기술.

서버 단에서 클라이언트의 요청을 받아 처리한 후 응답하는 역할.

-서블릿의 특징-

  • 클라이언트의 요청에 대해 동적으로 작동하는 웹 애플리케이션 컴포넌트.
  • MVC 모델에서 컨트롤러 역할
  • 모든 메서드는 쓰레드로 동작
  • javax.servlet.http 패키지의 HttpServlet 클래스를 상속받음
2. 서블릿 컨테이너
서블릿의 수명주기를 관리하고, 요청이 오면 스레드를 생성해 처리 해주고, 클라이언트의 요청을 받아서 응답을 보낼 수 있도록 통신 지원
  • 통신 지원 : 클라이언트와 통신하려면 서버는 특정 포트로 소켓을 열고 I/O 스트림을 생성 해주는 과정을 API 제공으로 간단히 해결
  • 수명주기 관리 : 서블릿을 인스턴스화한 후 초기화 하고, 요청에 맞는 적절한 메서드를 호출한다. 응답한 후에는 가비지 컬렉션을 통해 객체를 소멸시킨다.
  • 멀티스레딩 관리 : 서블릿 요청들은 스레드를 생성해 처리합니다. 즉, 멀티스레드 방식으로 여러 요청을 동시에 처리
  • 선언적인 보안 관리 및 JSP 지원 : 서블릿 컨테이너는 보안 기능을 지원한다.
3. 서블릿의 동작 방식
  1. 클라이언트의 요청을 받는다.
  2. 분석 후 요청을 처리할 서블릿을 찾는다.
  3. 비즈니스 서비스 로직을 호출한다.
  4. model 로부터 그 결과 값을 받는다
  5. request 나 session 영역에 저장한 후 결과 값을 출력할 view를 선택한다.
  6. view(JSP 페이지)에 결과 값을 출력한 후 요청한 클라이언트에 응답한다.
4. 서블릿 작성 규칙
  1. javax.servlet, javax.servlet.http, java.io 패키지를 임포트 한다.
  2. 서블릿 클래스는 반드시 public로 선언해야 하고, HttpServlet를 상속해야 한다.
  3. 사용자 요청을 처리하기 위해 doGet() 메서드나 doPost() 메서드를 반드시 오버라이딩 해야 한다.
  4. doGet() 또는 doPost() 메서드는 ServletException 과 IOException 예외를 던지도록 (throws) 선언한다.
  5. doGet() 또는 doPost() 메서드를 호출할 때의 매개변수는 HttpServletRequest 와 HttpServletResponse 를 사용한다.
5. 서블릿 작성
1)  web.xml 에서 매핑

  <servlet>  <!-- 서블릿 등록 -->
    <servlet-name>서블릿명</servlet-name>
    <servlet-class>패키지를 포함한 서블릿 클래스명</servlet-class>
  </servlet>
  <servlet-mapping>  <!-- 서블릿과 요청명 매핑 -->
    <servlet-name>서블릿명</servlet-name>
    <url-pattern>클라이언트 요청 URL</url-pattern>
  </servlet-mapping>
예제) 요청을 처리할 서블릿 클래스
package servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        req.setAttribute("message", "서블릿은 web-inf에 등록하고 해야하네.");
        req.getRequestDispatcher("/13Servlet/HelloServlet.jsp").forward(req, resp);
    }
}
2) @WebServlet 애너테이션으로 매핑
package servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/13Servlet/AnnoMapping.do")
public class AnnoMapping extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    req.setAttribute("message", "@WebServlet으로 매핑");
    req.getRequestDispatcher("/13Servlet/AnnoMapping.jsp").forward(req, resp);
    }
}
6. 서블릿의 수명주기 메서드
  • @Postconstruct : 객체 생성 직후 호출, 애너테이션을 사용하므로 메서드명은 개발자가 정함
  • init() : 서블릿의 초기화 작업을 수행하기 위해 호출, 최초 요청시 딱 한번만 호출
  • service() : 클라이언트의 요청을 처리 하기 위해 호출
  • destroy() : 서블릿이 새롭게 컴파일 되거나, 서버가 종료될 때 호출
  • @PreDestroy : 서블릿 객체를 제거하는 과정에서 호출
예제) 수명 주기 메서드 동작 확인
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>LifeCycle.jsp</title>
</head>
<body>
    <script>
    function requestAction(frm, met) {
        if (met == 1) {
            frm.method = 'get';
        }
        else {
            frm.method = 'post';
        }
        frm.submit();
    }
    </script>

    <h2>서블릿 수명주기(Life Cycle) 메서드</h2>
    <form action="./LifeCycle.do">
        <input type="button" value="Get 방식 요청하기" onclick="requestAction(this.form, 1);" />
        <input type="button" value="Post 방식 요청하기" onclick="requestAction(this.form, 2);" />
    </form>
</body>
</html>

예제) 수명주기 메서드 동작 확인용 서블릿
package servlet;

import java.io.IOException;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/13Servlet/LifeCycle.do")
public class LifeCycle extends HttpServlet {

    @PostConstruct
    public void myPostConstruct() {
        System.out.println("myPostConstruct() 호출");
    }

    @Override
    public void init() throws ServletException {
        System.out.println("init() 호출");
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        System.out.println("service() 호출");
        super.service(req, resp);
    }        

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        System.out.println("doGet() 호출");
        req.getRequestDispatcher("/13Servlet/LifeCycle.jsp").forward(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        System.out.println("doPost() 호출");
        req.getRequestDispatcher("/13Servlet/LifeCycle.jsp").forward(req, resp);
    }

    @Override
    public void destroy() {
        System.out.println("destroy() 호출");
    }

    @PreDestroy
    public void myPreDestroy() {
        System.out.println("myPreDestroy() 호출");
    }
}

댓글 없음:

댓글 쓰기