본문 바로가기
[패스트캠퍼스] Spring/스프링의 정석 : 남궁성과 끝까지 간다

Ch.02 Spring MVC (13~16)

by 엑츄얼리 2022. 5. 23.

13. Servlet과 JSP(1)

 Spring은 Servlet을 향상시킨 것이기 때문에 Servlet을 기반으로 작동

 

1. Servlet과 Controller 비교

Servlet

@WebServlet("/rollDice2")
public class TwoDiceServlet extends HttpServlet{
    @Override
    public void service(HttpServletRequest req, HttpServletResponse resp)
    throws IOException{
    .
    .
    .

 

Controller

@Controller
public class TwoDice{
    @RequestMapping("/rollDice2")
    public void main(HttpServletResponse response){
    .
    .
    .

 

 - @WebServlet("URL") = @Controller + @RequestMapping (Spring)

   "URL"은 Servlet과 Mapping할 URL

 

 - @WebServlet은 HttpServlet을 상속받지만 @Controller은 상속받지 않음

    Java는 단일 상속이므로 가능하면 상속이 없는게 좋음

 

 - @WebServlet은 Service method에 파라미터로 HttpServletRequest와 HttpServletResponse가 고정이지만, 

   @Controller는 필요한 매개변수만 작성하여 사용할 수 있음

 

 * Servlet은     URL을 Class단위로 Mapping하기 때문에 URL 개수만큼 Class를 만들어야 하지만,

   Controller는 URL을 Method단위로 Mapping하기 때문에 Class 1개에서 모든 URL을 처리 가능

 

 

2. Servlet의 생명 주기

 Servlet은 3개의 Method로 이루어짐

 

 1) init()

  - Servlet이 생성될 때 Servlet을 초기화

 

 2) service()

  - 실질적인 작업 처리 부분 (ServletContainer가 자동으로 호출, 사용자의 조작 필요 X)

 

 3) destroy()

  - Servlet이 종료될 때 (메모리에서 제거될 때, Server가 종료될 때) 실행

 

 - Servlet Context 작동 방식

 

 * Servlet은 SingleTon 방식

    a) 1개의 Instance를 만들어 재활용 (Spring도 동일, Bean)

    b) 사용자마다 각자의 Instance를 만들 필요가 없음

 

 

3. JSP(Java Server Page)

 - HTML 안에 Java 코드가 있는 것

 

 

4. JSP와 Servlet의 비교

 - JSP 파일을 Servlet으로 변환하여 실행

 

 - JSP페이지를 처음 실행 시 Servlet으로 변환해야해서 처음에는 시간이 더 걸림(init하는데 걸리는 시간)

 

twoDice.jsp

왼쪽과 같은 JSP파일을 Server에서 실행시에는 오른쪽과 같이 Servlet으로 변환하여 실행

 

 * SingleTon의 2가지 방식

  1) lazy-init (Servlet)

    - Request가 오면 초기화(init)

 

 2) early-init (Spring)

   - Server 실행 시 초기화 (Bean일 듯...?)

 

 

5. JSP의 호출 과정

 

 

6. JSP와 Servlet으로 변환된 JSP의 비교

 TwoDice.jsp의 Class 이름이 twoDice_jsp.class (extends org.apache.jasper.runtime.HttpJspBase......)

 

 

7. JSP의 기본 객체

 - 생성없이 사용할 수 있는 객체 (선언부 없이 사용)

 

 - Servlet Instance의 _JspService method에 지역변수로 선언되어 있음

.
.
.
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = nulli;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
.
.
.

 

 

 

14. 서블릿과 JSP(2)

8. 유효 범위(Scope)와 속성(Attribute)

 - Http 특징

    상태 정보를 저장하지 않는다.(StateLess) <=> 상태 정보 저장 (StateFul)

    따라서 데이터를 저장하기 위해 4개의 저장소(Map 형태)가 구비되어 있으며

    1)접근범위, 2)생존기간에 따라 알맞은 저장소에 저장(setAttribute(), getAttribute())

 

 1) PageContext

  - Local Variable 저장 (request, response)

 

  - 해당 Page 내부에서만 유효하며, 읽기 쓰기 가능 (Request마다 초기화)

 

  - 필요한 이유 : EL tag는 LocalVariable에 접근하지 못함

                      => request.setAttribute와 같은 방식으로 저장소에 접근해주어야 접근 가능

   * EL tag : ${ }

 

 

 2) Application

  - Web전체에 접근가능한 저장소 (Server당 1개)

 

 

 3) Session

  - Client마다 1개씩 존재하는 개별 저장소 (Client만 사용하는 개별 정보 저장)

  ex. 각자 로그인하여 글쓰기가 가능하도록 해줌

 

  - Client개수만큼 생성되므로 Server에 Memory부담이 크기때문에 최소한의 데이터만 저장

 

 

 4) request

  - 요청 시 마다 생기며 일반적으로 1개의 Jsp에서만 사용되고 소멸 (요청이 처리되는 동안만 존재)

 

  - Dispatcher(forward) : Request가 다음 Jsp에서도 사용될 수 있도록 Request정보를 다음 Jsp에게 그대로 전달

  

 

 

 

15. 서블릿과 JSP(3)

9. URL 패턴

EX) URL = "http://localhost:8080/ch2/login/hello.do"일 때 위와 같은 4개의 WebServlet Mapping이 존재한다면, 

     우선 순위가 가장 높은 Exact Mapping Servlet이 실행 (1이 없다면 2, 2가 없다면 3, 3이 없다면 4)

 

 - Request 시 URL Mapping 과정

  •    Request가 들어오면 URL을 Servlet Mapping Table을 통해 처리할 Servlet을 확인
       -> Children Table을 확인하여 Servlet Instance 존재 여부 확인 후 처리 (Ch2. part13 2. Servlet의 생명 주기 참고)

 

 

10. EL(Expression Language) : ${ }   

<%
    Person person = new Person();//local variable
    
    //EL Tag를 사용하기 위해 request에 Person을 추가
    request.setAttribute("person", person);
    request.setAttribute("name", "남궁성");
    request.setAttribute("list", new java.util.ArrayList());
%>

   person.getCar().getColor()=<%=person.getCar().getColor()%>
== person.getCar().getColor()=${person.getCar().getColor()}>
== person.getCar().getColor()=${person.car.color}

 - EL tag는 Local Variable에 접근이 불가능하기 때문에

    request의 AttributeMap을 통해 값을 확인(RequestScope)

 

 * STS에서 JSP가 변환된 Servlet 확인하는 방법

   Run -> run Configuration -> Arguments -> VM arguments -> --Dwtp.deploy="~~tmpo\wtpwebapps"

   ->twp0\work\~~jsp\view 디렉토리 내부에 변환된 class파일 존재

   (Intellij는 못찾겠다 ㅠㅠ...)

 

<%=request.getAttribute("name")%>
  
//requestScope : request의 AttributeMap의 이름 
${requestScope.name}

//앞에 아무것도 붙지 않으면 Scope의 저장소를 작은 단위부터 차례대로 검색
//Page(PageContext) -> Request(Request) -> Session(Session) -> Application(Application)
${name}

 

<%=request.getParameter("id")%>

//pageContext : request객체를 메서드로 사용하고 싶을 때
${pageContext.request.getParameter("id")}

//param : request의 ParameterMap
${param.id}

 * EL은 null 출력 X, 연산 시 null을 0으로 변환하여 연산

 

 * Request의 parameter와 attribute의 차이

  Parameter : Client에서 만들어진 정보 (getter만 존재, setter X)

  Attribute  : Server에서 만들어진 정보 (getter, setter 모두 존재)

 

 - EL 연산 예시

${"1"+1}        <!--=2, String to int, JAVA에서는 int to String이되어 결과가 "11"-->
${"1"+"1"}      <!--="11"-->
${"2">1}        <!--true-->
${null+1}       <!--=1-->
${null+null}    <!--=0-->
${""+null}      <!--=0-->
${""-1}         <!--=-1-->
${empty null}   <!--true-->

 

 - 자바의 관계 연산자 ==, != at EL

   ==은 eq, .equals와 같은 의미

   != 은 ne와 같은 의미

 

 

16. 서블릿과 JSP(4)

11.JSTL(JSP Standard Tag Library)

 

 

12. Filter

 Servlet마다 반복되는 1.전 처리와 2.후 처리를 분리하여 Filter로 생성 (반복 : Logging, Encoding)

 * AOP와 유사한 원리

 

PerformanceFilter.java

 - 필터 수행 시간 측정

package com.spring.fastcampus.filter.No16;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;

// 필터를 적용할 요청의 패턴 지정 - 모든 요청에 필터를 적용.
@WebFilter(urlPatterns="/*")
public class PerformanceFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 초기화 작업
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 1. 전처리 작업
        long startTime = System.currentTimeMillis();

        // 2. 서블릿 또는 다음 필터를 호출
        chain.doFilter(request, response);

        // 3. 후처리 작업
        System.out.print("["+((HttpServletRequest)request).getRequestURI()+"]");
        System.out.println(" 소요시간="+(System.currentTimeMillis()-startTime)+"ms");
    }

    @Override
    public void destroy() {
        // 정리 작업
    }
}

 - @WebFilter(urlPatterns="/*")을 통해 Filter를 모든 URL에 적용

 

HelloServlet.java

package com.spring.fastcampus.controller.No13;

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

@WebServlet(urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
    @Override
    public void init() throws ServletException {
        //Servlet이 초기화될 때 자동 호출되는 Method
        //1. Servlet의 초기화 작업 담당
        System.out.println("[HelloServlet] init() is called");
    }

    //새로고침시에 init은 다시 호출되지 않고, service만 호출됨
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 입력
        //2. 처리
        //3. 출력
        System.out.println("[HelloServlet] service() is called!");
        //System.out.println("/");
    }

    @Override
    public void destroy() {
        //3. Servlet이 Memory에서 제거될 때 Servlet Container에 의해서 자동 호출
        System.out.println("[HelloServlet] destroy() is called!");
    }
}

 

 * URL : ~~/hello 입력 및 새로 고침, Server종료

 1) 첫 입력 init()을 통해 Servlet Instance 생성 및 service()를 통해 Servlet 실행

 2) 두 번째부터 : 생성된 Servlet Instance를 통해 service()만 실행

 3) Server 종료 시 : destroy()작업을 통해 Servlet Instance 종료

 

 + HelloServlet.java Filter를 통해 소요시간을 지속적으로 확인 가능하며,

    *.jsp파일 실행 시 첫 실행에 소요시간이 수백ms로 오래 걸리고 (jsp to class 변환)

    그 이후에는 수십ms로 소요시간이 단축됨도 확인가능

Servlet Instance 생성 및 소멸 확인

댓글