서블릿과 JSP (1)

SOLEE_DEV·2023년 1월 18일
0

서블릿과 JSP

  • 서블릿을 발전시킨게 Spring!
  • DispatcherServlet = spring

1. 서블릿과 컨트롤러 비교

package com.fastcampus.ch2;

import java.io.*;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;

@WebServlet("/rollDice2")
// 1. @Controller + @RequestMapping 합친거랑 동일한 효과!
public class TwoDiceServlet extends HttpServlet {
	// 2. HttpServlet을 상속 받아야함! (java는 단일상속!)
	public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
		// 3. service 메소드로 변경! (기존은 main) 고정메소드
		int idx1 = (int) (Math.random() * 6) + 1;
		int idx2 = (int) (Math.random() * 6) + 2;
		
		response.setContentType("text/html");
		response.setCharacterEncoding("utf-8");
		
		PrintWriter out = response.getWriter();
		out.println("<html>");
		out.println("<head>");
		out.println("</head>");
		out.println("<body>");
		out.println("<h1>안녕하세요?</h1>");
		out.println("</body>");
		out.println("</html>");
	}
}

차이점

  1. 상속을 안받음
  2. 매개변수도 필요한것만 받음
  3. 어노테이션도 나눠서 처리!
    4-1. webservlet은 매핑을 클래스 하나 당으로 처리하기 땨문에 매핑 하나 당 클래스를 만들어야 함
    4-2. 컨트롤러는 메소드에다가 매핑을 해서 하나의 클래스에 새로운 메소드를 만들기만 하면 가능!

2. 서블릿의 생명주기

package com.fastcampus.ch2;

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("/hello")
public class HelloServlet extends HttpServlet {
	public void init() throws ServletException {
		// 서블릿 초기화 - 서블릿이 생성 또는 리로딩 때, 단 한번만 수행됨.
		System.out.println("[HelloServlet] init()");
	}
	
	@Override // 호출될 때 마다 반복적으로 수행됨.
	public void service(HttpServletRequest request, HttpServletResponse response) {
//		1. 입력
//		2. 처리
//		3. 출력
		System.out.println("[HelloServlet] service()");
	}
	
	public void destroy() {
		// 뒷 정리 작업 - 서블릿이 메모리상에서 제거(unload)될 때, 단 한번만 수행됨
		System.out.println("[HelloServlet] destroy()");
	}
}

2. 생명주기 관리

ServletContainer

  • 이런 메소드들은 서블릿 컨테이너가 자동으로 호출하며, 서블릿을 만들 때
    메소드의 내용만 채워주면 됨.

생명주기

[Servlet Context]
1. 요청 → 서블릿 인스턴스 존재? (children을 보고 확인)
1-1. (Yes) service() 메소드 실행
1-2. (No) 서블릿 클래스 로딩 & 인스턴스 생성 → init() 메소드 실행 후 service() 메소드 제공
2. 프로그램 변경, 웹 App이 종료돼서 Servlet이 메모리에 변경될 때 Destroy() 호출!

[Servlet Context > children]

  • 서블릿의 정보가 Map 형태로 구성되어 있음
  • Key : 서블릿 이름
  • Value : 서블릿

서블릿

  1. Single Tone 형태 (요청하는 사람마다 동일한 작업을 수행!)
    • 사용자마다 다른 일을 할 필요가 없음
  2. 한 개의 인스턴스만 만들고 재활용함

3. JSP란?

  • JSP : Java Server Pages = servlet (변환됨) / html 안에 java 코드가 있는 것
// in jsp 값 출력할 때
<img src='resource/img/dice<%=idx1%>.jpg'>
<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="utf-8"%>
<%@ page import="java.util.Random" %>
<!-- 클래스 영역 -->
<%!
	int getRandomInt(int range) {
		return new Random().nextInt(range)+1;
	}
%>
<!-- 메서드 영역 - service()의 내부 -->
<%
	int idx1 = getRandomInt(6);
	int idx2 = getRandomInt(6);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>twoDice.jsp</title>
</head>
<body>
	<img src='resource/img/dice<%=idx1%>.jpg'>
	<img src='resource/img/dice<%=idx2%>.jpg'>
</body>
</html>

-> 아래 메서드 영역부분이 다 webServlet의 service 메서드 안에 들어감

  • <%<%!의 차이
    1. <% : 지역 변수
    1. <%! : 인스턴스 변수, 상수 선언 -> 서비스 메서드가 아닌 클래스 안에 들어감
  • .jsp 파일의 경로
    : src/main/webApp/ ...

4. JSP의 호출 과정

절차

  1. *.jsp 요청 → JspServlet
    (서블릿 인스턴스 존재?)
    1-1. (Yes) 서블릿 인스턴스 _jspService()
    1-2. (No) .jsp → servlet으로 변환 & 서블릿 소스파일 컴파일 → 서블릿 클래스 파일 → 인스턴스 생성 _jspInit() (초기화) → 서블릿 인스턴스 _jspService()
    -> 처음 호출할 때는 시간 지연이 있음
  2. 서블릿 인스턴스가 응답! (서비스 메서드가 응답)
  3. *.jsp 변경시 변환과정 동일하게 진행

특징

  1. 초기화
  • 서블릿 : lazy-init (지연된 초기화)
  • Spring : early-init (미리 초기화)
  1. 동일한 Single Tone 형태

5. JSP의 기본 객체

  • 생성없이 사용할 수 있는 객체
    request, response, session, pageContext, out
    -> jsp가 servlet으로 객체되니까 생성없이 호출할 수 있음 (service 메서드의 로컬 변수 형태로!)

6. 유효 범위(scope)와 속성(attribute)

HTTP 특징

  • (stateless) 상태 정보를 저장하지 않는다 <-> stateful : 상태 정보 저장 O
    -> 따라서, 4개 저장소 (map형태) 운영 (1) 접근 범위 (2) 생존 기간

4개 저장소 특징

  1. pageContext
    • 목적 : 지역변수, 기본 객체 (request, response, out, session) 저장
    • 범위 : login.jsp (해당 페이지 안에서만 접근 가능) => R/W 가능
    • 예시 : ${idx1}
    • 특징
      1. EL (${}) 에서는 지역 변수에 직접 접근이 불가능함. EL에서 쓰려면 해당 저장소에 먼저 저장을 해야 함. => 따라서, 같은 페이지 안이지만 읽고 쓰기가 가능하기 위해서 해당 저장소를 이용
      2. 요청할 때 마다 새로 초기화
  2. application (전체)
    • 목적 : 공용 저장소
    • 범위 : WebApp 전체에서 접근가능한 저장소 (전체 딱 하나!) map 형태로 저장
    • 메소드 1) 쓰기(저장) : setAttribute() // key = 속성 (attribute)
      2) 읽기(조회) : getAttribute()
    • 특징
      1. 전체 App에서 공용으로 쓰기 때문에, 개별 페이지 속성을 구분하기에는 좋은 저장소가 아님
      1. web app 시작부터 종료까지 context 내부 어디서나 접근 가능
      2. 모든 클라이언트가 공유!
      3. context마다 1개
  3. session (개별 / ★ 가장 편리하지만, 메모리 부담이 큼)
    • 목적 : 개별 저장소 (클라이언트 1:1)
    • 용도 : id, 장바구니 등 사용자 개별 저장소!
    • 특징 1) 사용자마다 하나씩 있는 개별 저장소 * 사용자 수, 최소한의 데이터만 저장!
      2) 서버 부담이 제일 큼!
  4. request 저장소 (★ 가장 부담이 적음 / 요청이 처리되는 동안에만 유지)
    • 목적 : 하나의 요청마다 생김
    • 특징 : a.jsp 거쳐서 b.jsp에 접근해야 될때도 사용 (forward)

속성 관련 메서드

  1. setAttribute() : 지정된 값을 지정된 속성 이름(name)으로 저장 (쓰기)
  2. getAttribute() : 지정된 이름으로 저장된 속성의 값을 반환 (읽기)
  3. removeAttribute() : 지정된 이름의 속성을 삭제
  4. getAttributeNames() : 기본 객체에 저장된 모든 속성의 이름을 반환

7. URL 패턴

  • webServlet으로 서블릿을 URL에 맵핑할 때 사용!
  • loadOnStartup=1 (미리 초기화 / 우선순위)
    - servlet : lazy-init (늦은 초기화)
  1. exact mapping : 정확히 매칭 (/login/hello.do)
  2. path mapping : 경로 매핑 (/login/*)
  3. extension mapping : 확장자 매핑 (*.do) ex) .../hi.do
  4. default mapping : 모든 주소에 매핑됨

servletMappings

[절차]
1. 요청이 들어오면, key값을 확인
2. key값이 존재하면 해당 value가 children(서블릿) key값에 존재하는지 확인
3. value (StandardWrapper) 메모리 값에 따라 서비스를 찾음

ex) /hello, *.jsp = 동적 리소스 (서블릿) / / = 정적 리소스 (default)
=> 요청에 해당하는 서블릿이 없으면 다 dispatcherServlet이 받음!

== 스프링의 경우 jsp, servlet이 없으니까 모~든 요청을 다 dispatcherServlet이 받음!
& dispatcherServlet 내부에 이런 매핑을 다 가지고 있음 (@RequestMapping)

8. EL (Expression Language)

  • <%=값%> => ${값}
  • empty는 null / 빈 컬렉션 배열 일때는 true 반환!

9. JSTL (JSP Standard Tag Library)

  • <% ~ %> : 이런걸 다 없애려고 나옴 (jstl)
    <c:set>,<c:if>,<c:forEach>
  • <c:set> : el값이 지역 변수를 사용하지 못하니까 저장소에 저장하기 위해서 고안
    => scope = "page"

10. Filter

  • 공통적인 요청 전처리와 응답 후처리에 사용 ex) 로깅, 인코딩 (변환) 등
  • 서블릿은 처리 부분만 담당!
  • 필터가 여러 개일 수 있음! filter1 → filter2 -> 서블릿 -> filter2 (후처리) -> filter1
profile
Front-End Developer

0개의 댓글