관리 메뉴

거니의 velog

(20) 서블릿 확장 API 사용하기 3 본문

Java_Servlet

(20) 서블릿 확장 API 사용하기 3

Unlimited00 2023. 8. 28. 20:22

(5) ServletConfig

* 이번에는 다른 서블릿 확장 API인 ServletConfig에 대해 알아보자.

* ServletConfig는 각 Servlet 객체에 대해 생성된다. 그리고 서블릿 API 계층 구조를 보면 ServletConfig 인터페이스를 GenericServlet 클래스가 실제로 구현하고 있다.

* ServletConfig에서 제공하는 여러 가지 메서드를 이용해 서블릿에 관련된 기능을 사용할 수 있다. 대표적인 기능이 앞에서 실습한 ServletContext 객체를 가져오는 기능이다.

* ServletConfig는 javax.servlet 패키지에 인터페이스로 선언되어 있으며, 서블릿에 대한 여러 가지 기능을 제공한다. 각 서블릿에서만 접근할 수 있으며 공유는 불가능하다. ServletConfig는 서블릿과 동일하게 생성되고 서블릿이 소멸되면 같이 소멸된다.

* ServletConfig가 제공하는 기능은 다음과 같다.

- ServletContext 객체를 얻는 기능

- 서블릿에 대한 초기화 작업 기능

* 이번에는 서블릿에서 사용할 설정 정보를 읽어 들여와 초기화하는 기능을 알아보자. 서블릿에서 초기화하는 기능을 알아보자. 서블릿에서 초기화하는 방법으로는 @WebServlet 애너테이션을 이용하는 방법과 web.xml에 설정하는 방법이 있다. 먼저 애너테이션을 이용하는 방법을 알아보자.


(6) @WebServlet 애너테이션을 이용한 서블릿 설정

<@WebServlet의 중요한 구성 요소들>

요소 설명
urlPatterns 웹 브라우저에서 서블릿 요청 시 사용하는 매핑 이름
name 서블릿 이름
loadOnStartUp 컨테이너 실행 시 서블릿이 로드되는 순서 지정
initParams @WebInitParam 애너테이션 이용해 매개변수를 추가하는 기능
description 서블릿에 대한 설명

* 이클립스에서 서블릿을 생성할 때 @WebServlet의 값들을 편리하게 설정할 수 있다. @WebServlet으로 서블릿을 생성할 때 사용할 매개변수를 설정해 보자.

1. sec06.ex01 패키지를 생성하고 마우스 오른쪽 버튼을 클릭한 후 New > Servlet을 선택한다.

2. 클래스 이름으로 InitParamServlet을 입력한 후 Next를 클릭한다.

3. Initialization parameters 항목의 Add... 를 클릭한다.

4. Name과 value에 email과 admin@jweb.com을 입력한 후 OK를 클릭한다.

5. 다시 Add... 를 클릭한 후 Name에 tel, Value에 010-1111-2222를 입력하고 OK를 클릭한다.

6. 두 개의 서블릿 매개변수가 추가되었음을 확인한 후 URL mappings의 /initParamServlet을 선택하고 Remove를 클릭해 삭제한다.

7. 새로운 매핑 이름을 추가하기 위해 Add...를 클릭한다.

8. 첫 번째 매핑 이름은 /sInit으로, 두 번째 매핑 이름은 /sInit2로 입력하고 각각 OK를 클릭한다.

9. 두 개의 서블릿 매핑 이름이 추가된 것을 확인하고 Next를 클릭한다.

10. Inherited abstract methods와 doGet 옵션 체크 박스에 체크한 후 Finish를 클릭한다.

11. 이클립스에서 확인하면 설정한 대로 @WebServlet으로 표시되는 것을 확인할 수 있다.

12. InitParamServlet 클래스를 다음과 같이 작성한다. getInitParameter() 메서드에 애너테이션으로 매개변수를 설정할 때 지정한 email과 name을 인자로 전달하여 각 값을 가져온다.

package sec06.ex01;

import java.io.IOException;
import java.io.PrintWriter;

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

@WebServlet(name="initParamServlet",
        urlPatterns = { "/sInit", "/sInit2" }, // urlPatterns를 이용해 매핑 이름을 여러 개 설정할 수 있다.
        initParams = {@WebInitParam(name = "email", value = "admin@jweb.com"), 
        			  @WebInitParam(name = "tel", value = "010-1111-2222") }) // @WebInitParam을 이용해 여러 개의 매개변수를 설정할 수 있다.
public class InitParamServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		String email = getInitParameter("email");
		String tel = getInitParameter("tel"); // 설정한 매개변수의 name으로 값을 가져온다.
		out.print("<html><body>");
		out.print("<table><tr>");
		out.print("<td>email: </td><td>" + email + "</td></tr>");
		out.print("<tr><td>휴대전화: </td><td>" + tel + "</td>");
		out.print("</tr></table></body></html>");

	}
}

12. 브라우저에서 각각 매핑 이름으로 요청한다. 동일한 결과가 출력되는 것을 확인할 수 있다.

- http://localhost:8090/pro08/sInit

- http://localhost:8090/pro08/sInit2


6. load-on-startup 기능 사용하기

* 서블릿은 브라우저에서 최초 요청 시 init() 메서드를 실행한 후 메모리에 로드되어 기능을 수행한다. 따라서 최초 요청에 대해서는 실행 시간이 길어질 수밖에 없다. 이런 단점을 보완하기 위해 이용하는 기능이 load-on-startup이다.

* load-on-startup의 특징은 다음과 같다.

- 톰캣 컨테이너가 실행되면서 미리 서블릿을 실행한다.

- 지정한 숫자가 0보다 크면 톰캣 컨테이너가 실행되면서 서블릿이 초기화된다.

- 지정한 숫자는 우선순위를 의미하며 작은 숫자부터 먼저 초기화된다.

* load-on-startup 기능을 구현하는 방법으로는 애너테이션을 이용하는 방법과 web.xml에 설정하는 방법이 있다.


(1) 애너테이션을 이용하는 방법

* 먼저 애너테이션을 이용해 web.xml에서 공통 메뉴를 읽어오는 실습을 해보자.

1. sec06.ex02 패키지를 생성하고 마우스 오른쪽 버튼을 클릭한 후 New > Servlet을 선택한다.

2. 클래스 이름으로 LoadAppConfig를 입력하고 Next를 클릭한다.

3. Name과 URL mappings를 loadConfig로 변경하고 Next를 클릭한다.

4. Inherited abstract methods, init, doGet 옵션 체크박스에 체크한 후 Finish를 클릭한다.

5. LoadAppConfig 클래스를 다음과 같이 작성한다. 애너테이션으로 설정한 매개변수에 loadOnStartup 속성을 추가한 후 우선순위를 1로 설정한다.

package sec06.ex02;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
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(name = "loadConfig", urlPatterns = { "/loadConfig"}, loadOnStartup=1) // loadOnStartup 속성을 추가하고 우선순위를 1로 설정한다.
//@WebServlet(name = "loadConfig", urlPatterns = { "/loadConfig"})
public class LoadAppConfig extends HttpServlet {
	private ServletContext context; // 변수 context를 멤버 변수로 선언한다.
	
	@Override
	public void init(ServletConfig config) throws ServletException {
		System.out.println("LoadAppConfig의 init 메서드 호출");
		context = config.getServletContext(); // init() 메서드에서 ServletContext 객체를 얻는다.
		String menu_member = context.getInitParameter("menu_member");
		String menu_order = context.getInitParameter("menu_order");
		String menu_goods = context.getInitParameter("menu_goods"); // getInitParameter() 메서드로 web.xml의 메뉴 정보를 읽어 들인다.
		
		context.setAttribute("menu_member", menu_member);
		context.setAttribute("menu_order", menu_order);
		context.setAttribute("menu_goods", menu_goods); // 메뉴 정보를 ServletContext 객체에 바인딩한다.
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		
		String menu_member = (String)context.getAttribute("menu_member");
		String menu_order = (String)context.getAttribute("menu_order");
		String menu_goods = (String)context.getAttribute("menu_goods"); // 브라우저에서 요청시 ServletContext 객체의 바인딩된 메뉴 항목을 가져온다.

		out.print("<html><body>");
		out.print("<table border=1 cellspacing=0><tr>메뉴 이름</tr>");
		out.print("<tr><td>" + menu_member + "</td></tr>");
		out.print("<tr><td>" + menu_order + "</td></tr>");
		out.print("<tr><td>" + menu_goods + "</td></tr>");
		out.print("</tr></table></body></html>");
	}

}

* 우선순위는 양의 정수로 지정하여 숫자가 작으면 우선순위가 높으므로 먼저 실행한다.

* 톰캣 실행 시 init() 메서드를 호출하면 getInitParameter() 메서드를 이용해 web.xml의 메뉴 정보를 읽어 들인 후 다시 ServletContext 객체에 setAttribute() 메서드로 바인딩한다. 브라우저에서 요청하면 web.xml이 아니라 ServletContext 객체에서 메뉴 항목을 가져온 후 출력하기 때문에 파일에서 읽어 들여와 출력하는 것보다 빠르게 출력할 수 있다.

6. 브라우저에서 /loadConfig로 최초 요청 시 기다리지 않고 바로 공통 메뉴를 출력한다. 또한 톰캣을 실행하면 서블릿의 init() 메서드를 호출하므로 로그에 메시지가 출력된다.

- http://localhost:8090/pro08/loadConfig


(2) web.xml에 설정하는 방법

* 이번에는 web.xml에 설정해서 사용하는 방법을 알아보자. 애너테이션 방법을 이용하기 전에는 web.xml에 설정해서 사용했다.

1. 다음과 같이 web.xml을 작성한다. <servlet-name> 태그의 값은 반드시 서블릿을 생성할 때 name 으로 지정한 값으로 설정해야 한다.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
  <display-name>pro08</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>

  <!-- 새로 추가된 부분 -->
  <context-param>
  	<param-name>menu_member</param-name>
  	<param-value>회원등록 회원조회 회원수정</param-value>
  </context-param> <!-- <context-param> 태그 안에 다시 <param-name>과 <param-value> 태그로 초기 값을 설정한다. -->
  <context-param>
  	<param-name>menu_order</param-name>
  	<param-value>주문조회 주문등록 주문수정 주문취소</param-value>
  </context-param>
  <context-param>
  	<param-name>menu_goods</param-name>
  	<param-value>상품조회 상품등록 상품수정 상품삭제</param-value>
  </context-param>
  
  <!-- 새로 추가된 부분 -->
  <servlet>
  	<servlet-name>loadConfig</servlet-name> <!-- 애너테이션으로 서블릿 생성 시 name 속성 값으로 설정한다. -->
  	<servlet-class>sec06.ex02.LoadAppConfig</servlet-class> <!-- 패키지 이름까지 포함된 서블릿 클래스 이름을 설정한다. -->
  	<load-on-startup>1</load-on-startup> <!-- 우선순위를 설정한다. -->
  </servlet>
</web-app>

2. 톰캣을 다시 실행한 후 브라우저에서 /loadConfig로 요청한다. 실행 결과는 애너테이션으로 실행했을 때와 같다.