관리 메뉴

거니의 velog

(19) 서블릿 확장 API 사용하기 2 본문

Java_Servlet

(19) 서블릿 확장 API 사용하기 2

Unlimited00 2023. 8. 26. 17:12

3. dispatch를 이용한 포워드 방법

* 이번에는 dispatch를 이용해 포워드하는 방법을 알아보자.


(1) dispatch를 이용한 포워딩 과정

* dispatch를 이용한 포워딩 과정이 redirect 방법과 다른 점은 클라이언트의 웹 브라우저를 거치지 않고 바로 서버에서 포워딩이 진행된다는 것이다. 따라서 웹 브라우저 주소창의 URL이 변경되지 않는다. 즉, 클라이언트 측에서는 포워드가 진행되었는지 알 수 없다.

1. 클라이언트의 웹 브라우저에서 첫 번째 서블릿에 요청한다.
2. 첫 번째 서블릿은 RequestDispatcher를 이용해 두 번째 서블릿으로 포워드한다.


(2) 서블릿을 이용한 dispatch 포워딩 실습

* 이번에는 dispatch 방법으로 포워딩 기능을 구현해 보자.
1. sec03.ex01 패키지에 다음과 같이 두 개의 서블릿 클래스를 추가한다.

2. FirstServlet 클래스를 다음과 같이 작성한다. RequestDispatcher 클래스를 이용해 두 번째 서블릿인 second를 지정한 후 forward() 메서드를 이용해 포워드한다.

package sec03.ex01;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
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("/first")
public class FirstServlet extends HttpServlet{
	protected void doGet(HttpServletRequest request, HttpServletResponse response)  throws  ServletException, IOException { 
      response.setContentType("text/html;charset=utf-8");
      RequestDispatcher dispatch = request.getRequestDispatcher("second?name=lee"); // GET 방식으로 데이터를 전달한다.
      dispatch.forward(request, response); // dispatch 방법을 이용해 second로 전달한다.
   }
}

3. 두 번째 서블릿인 SecondServlet 클래스를 다음과 같이 작성한다.

package sec03.ex01;

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

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("/second")
public class SecondServlet extends HttpServlet{
	protected void doGet(HttpServletRequest request, HttpServletResponse response)  throws  ServletException, IOException {
      response.setContentType("text/html;charset=utf-8");
      PrintWriter out = response.getWriter();
      
      String name=request.getParameter("name"); // 다른 서블릿에서 전달된 데이터를 가져온다.
      out.println("<html><body>");
      out.println("이름:"+name);
      out.println("<br>");
      out.println("dispatch를 이용한 forward 실습입니다.");
      out.println("</body></html>");   

   }
}

4. 실행해 보면 웹 브라우저 주소 창의 URL이 변경되지 않고 그대로이다. 이는 서블릿의 포워드가 서버에서 수행되었기 때문이다.

5. 이처럼 GET 방식으로 dispatch를 이용해 데이터를 전달해도 웹 브라우저의 URL은 변경되지 않는다.


4. 바인딩

* 앞에서는 서블릿에서 다른 서블릿으로 포워딩할 때 GET 방식으로 데이터를 전달하는 방법을 보았다. 전달하는 데이터 양이 적을 때는 이 방법이 편리하다. 그러나 서블릿에서 조회한 대량의 상품 정보를 JSP로 전달할 때는 GET 방식이 불편하다. 따라서 서블릿에서 다른 서블릿 또는 JSP로 대량의 데이터를 공유하거나 전달하고 싶을 때는 바인딩(binding) 기능을 사용한다.
* 바인딩의 사전적 의미는 "두 개를 하나로 묶는다"는 것이다. 이는 웹 프로그램 실행 시 자원(데이터)을 서블릿 관련 객체에 저장하는 방법으로, 주로 HttpServletRequest, HttpSession, ServletContext 객체에서 사용되며 저장된 자원(데이터)은 프로그램 실행 시 서블릿이나 JSP에서 공유하여 사용한다.
* 실제 모델2, 스트릿츠, 스프링 프레임워크로 구현하는 웹 프로그램은 이 바인딩 기능을 이용해 서블릿이나 각 JSP 간 데이터를 전달하고 공유한다.
<서블릿 객체에서 사용되는 바인딩 관련 메서드>

관련 메서드 기능
setAttribute(String name, Object obj) 자원(데이터)을 각 객체에 바인딩한다.
getAttribute(String name) 각 객체에 바인딩된 자원(데이터)을 name으로 가져온다.
removeAttribute(String name) 각 객체에 바인딩된 자원(데이터)을 name으로 제거한다.

(1) HttpServletRequest를 이용한 redirect 포워딩 시 바인딩

* 먼저 HttpServletRequest 객체를 이용한 바인딩 기능을 알아보자. 브라우저에서 전달 받은 request를 서블릿에서 redirect 방식으로 다른 서블릿에 전달하는 예제이다.
1. 다음과 같이 실습 파일을 준비한다.

2. FirstServlet을 다음과 같이 작성한다. HttpServletRequest의 setAttribute() 메서드를 이용해 (address, "서울시 성북구")를 바인딩한다.

package sec04.ex01;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
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("/first")
public class FirstServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response)  throws  ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		request.setAttribute("address", "서울시 성북구"); // 웹 브라우저에서 요청한 request 객체에 address 값으로 "서울시 성북구"를 바인딩한다.
		response.sendRedirect("second"); // 두 번째 서블릿으로 전달하기 위해 sendRedirect()를 호출한다.
	}
}

3. 두 번째 서블릿에서는 HttpServletRequest의 getAttribute() 메서드를 이용해 전달된 주소를 받는다.

package sec04.ex01;

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

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("/second")
public class SecondServlet extends HttpServlet {
	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 address = (String) request.getAttribute("address"); // 전달된 request에서 getAttribute()를 이용해 address의 값을 가져온다.
		out.println("<html><body>");
		out.println("주소:" + address);
		out.println("<br>");
		out.println("redirect를 이용한 바인딩 실습입니다.");
		out.println("</body></html>");
	}
}

4. 실행 결과를 보면 정상적으로는 '서울시 성북구'가 출력되어야 하는데 null이 출력된다. 왜 그럴까?
- http://localhost:8090/pro08/first

* 그 이유는 redirect 방식 포워드 과정 때문이다. 포워딩 과정 1단계인 웹 브라우저에서 요청할 때 서블릿에 전달되는 첫 번째 request는 웹 브라우저를 통해 재요청되는 3단계의 두 번째 request와 다른 요청이다. 즉, redirect 방식으로는 서블릿에서 바인딩한 데이터를 다른 서블릿으로 전송할 수 없다는 것이다.
* 그럼 이런 의문이 들 수 있다. 앞서 redirect 방식을 실습했을 때처럼 GET 방식으로 전송하면 되지 않느냐? 물론 전달하고자 하는 데이터가 보안과 상관이 없으며, 데이터 양이 적다면 그렇게 해도 괜찮다. 하지만 데이터베이스에서 조회된 수십 개의 회원 정보나 상품 정보를 전달해야 한다면 확실히 redirect 방식에는 문제가 있다.


(2) HttpServletRequest를 이용한 dispatch 포워딩 시 바인딩

* 이번에는 dispatch 방법으로 바인딩 기능을 사용해 보자.
1. 다음과 같이 실습 파일을 준비한다.

2. FirstServlet 클래스를 다음과 같이 작성한다. 브라우저에서 전달된 request에 주소를 바인딩 한 후 dispatch 방법을 이용해 다른 서블릿으로 포워딩한다.

package sec04.ex02;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
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("/first")
public class FirstServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response)  throws  ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		request.setAttribute("address", "서울시 성북구"); // 웹 브라우저의 최초 요청 request에 바인딩한다.
		RequestDispatcher dispatch = request.getRequestDispatcher("second"); // 바인딩된 request를 다시 두 번째 서블릿으로 포워드한다.
		dispatch.forward(request, response);
	}
}

3. SecondServlet 클래스를 다음과 같이 작성한다. 전달된 request에서 주소를 받은 후 브라우저로 출력한다.

package sec04.ex02;

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

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("/second")
public class SecondServlet extends HttpServlet {
	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 address = (String) request.getAttribute("address"); // 전달된 request에서 getAttribute()를 이용해 주소를 받아 온다.
		out.println("<html><body>");
		out.println("주소:" + address);
		out.println("<br>");
		out.println("dispatch를 이용한 바인딩 실습입니다.");
		out.println("</body></html>");
	}
}

4. 이번에는 화면에 정상적으로 주소가 출력된다. 

* 이 포워딩 과정을 보면 첫 번째 서블릿에서 두 번째 서블릿으로 전달되는 request가 브라우저를 거치지 않고 바로 전달되었다. 따라서 첫 번째 서블릿의 request에 바인딩된 데이터가 그대로 전달된 것이다.
* 모델2, 스트릿츠, 스프링 프레임워크로 개발할 때는 dispatch 방식으로 바인딩된 데이터를 서블릿이나 JSP로 전달한다.


(3) 두 서블릿 간 회원 정보 조회 바인딩 실습

* 이번에는 데이터베이스에서 조회된 회원 정보를 화면 기능을 담당하는 서블릿에 전달해서 웹 브라우저에 출력해 보자.
1. 다음과 같이 MemberDAO와 MemberVO 클래스를 만들고, 데이터베이스 연동을 위한 Datasource 기능도 설정한다.


2. MemberServlet 클래스를 다음과 같이 작성한다. 첫 번째 서블릿에서 조회한 회원 정보를 List에 저장한 후 다시 바인딩하여 두 번째 서블릿으로 전달한다.

package sec04.ex03;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.RequestDispatcher;
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("/member")
public class MemberServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doHandle(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doHandle(request, response);
	}

	private void doHandle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		MemberDAO dao = new MemberDAO();
		List membersList = dao.listMembers();
		request.setAttribute("membersList", membersList); // 조회한 회원 정보를 ArrayList의 객체에 저장한 후 request에 바인딩한다.
		RequestDispatcher dispatch = request.getRequestDispatcher("viewMembers");
		dispatch.forward(request, response); // 바인딩한 request를 viewMembers 서블릿으로 포워딩 한다.
	}
}


3. ViewServlet 클래스를 다음과 같이 작성한다. getAttribute() 메서드를 이용해 첫 번째 서블릿에서 바인딩한 회원 정보를 List로 가져온다.

package sec04.ex03;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.List;

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("/viewMembers")
public class ViewServlet extends HttpServlet {
	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();
		List membersList = (List) request.getAttribute("membersList"); // 바인딩해서 넘어온 request에서 회원 정보를 가져온다.
		out.print("<html><body>");
		out.print("<table border=1><tr align='center' bgcolor='lightgreen'>");
		out.print("<td>아이디</td><td>비밀번호</td><td>이름</td><td>이메일</td><td>가입일</td><td>삭제</td></tr>");
		for (int i = 0; i < membersList.size(); i++) {
			MemberVO memberVO = (MemberVO) membersList.get(i);
			String id = memberVO.getId();
			String pwd = memberVO.getPwd();
			String name = memberVO.getName();
			String email = memberVO.getEmail();
			Date joinDate = memberVO.getJoinDate();
			out.print("<tr><td>" + id + "</td><td>" + pwd + "</td><td>" + name + "</td><td>" + email + "</td><td>"
					+ joinDate + "</td><td>" + "<a href='/pro08/member3?command=delMember&id=" + id
					+ "'>삭제 </a></td></tr>");

		}
		out.print("</table></body></html>");
		out.print("<a href='/pro08/memberForm.html'>새 회원 등록하기</a>");
	}
}


4. http://localhost:8090/pro08/member로 요청하여 실행 결과를 확인한다.


* ViewServlet 클래스는 웹 브라우저에서 화면 기능을 담당하는데 이러한 기능을 하는 서블릿이 분화되어 발전된 것이 바로 JSP이다.


5. ServletContext와 ServletConfig 사용법

* 이번에는 서블릿과 더불어 웹 프로그래밍 개발 시 유용한 기능을 제공하는 클래스들을 알아보자.


(1) ServletContext 클래스

* ServletContext 클래스는 톰캣 컨테이너 실행 시 각 컨텍스트(웹 애플리케이션)마다 한 개씩 ServletContext 객체를 생성한다. 그리고 톰캣 컨테이너가 종료하면 ServletContext 객체 역시 소멸된다. ServletContext 객체는 웹 애플리케이션이 실행되면서 애플리케이션 전체의 공통 자원이나 정보를 미리 바인딩해서 서블릿들이 공유하여 사용한다.

* ServletContext 클래스의 특징은 다음과 같다.

- javax.servlet.ServletContext로 정의되어 있다.

- 서블릿과 컨테이너 간의 연동을 위해 사용한다.

- 컨텍스트(웹 애플리케이션)마다 하나의 ServletContext가 생성된다.

- 서블릿끼리 자원(데이터)을 공유하는 데 사용한다.

- 컨테이너 실행 시 생성되고 컨테이너 종료 시 소멸된다.
* ServletContext 가 제공하는 기능은 다음과 같다.

- 서블릿에서 파일 접근 기능

- 자원 바인딩 기능

- 로그 파일 기능

- 컨텍스트에서 제공하는 설정 정보 제공 기능

* 톰캣 컨테이너를 실행할 때 각 애플리케이션에서 생성되는 ServletContextServletConfig 객체를 나타내었다. ServletContext 는 컨텍스트당 생성되는 반면에 ServletConfig 는 각 서블릿에 대해 생성된다.

<톰캣 컨테이너의 ServletContext 와 ServletConfig 생성 상태>

<ServletContext에서 제공하는 여러 가지 메서드>

메서드 기능
getAttribute(String name) - 주어진 name을 이용해 바인딩된 value를 가져온다.
- name이 존재하지 않으면 null을 반환한다.
getAttributeNames() - 바인딩된 속성들의 name을 반환한다.
getContext(String uripath) - 지정한 uripath에 해당되는 객체를 반환한다.
getInitParameter(String name) - name에 해당되는 매개변수의 초기화 값을 반환한다.
- name에 해당되는 매개변수가 존재하지 않으면 null을 반환한다.
getInitParameterNames() - 컨텍스트의 초기화 관련 매개변수들의 이름들을 String 객체가 저장된
  Enumeration 타입으로 반환한다.
- 매개변수가 존재하지 않으면 null을 반환한다.
getMajorVersion() - 서블릿 컨테이너가 지원하는 주요 서블릿 API 버전을 반환한다.
getRealPath(String path) - 지정한 path에 해당되는 실제 경로를 반환한다.
getResource(String path) - 지정한 path에 해당되는 Resource를 반환한다.
getServerInfo() - 현재 서블릿이 실행되고 있는 서블릿 컨테이너의 이름과 버전을 반환한다.
getServletContextName() - 해당 애플리케이션의 배치 관리자가 지정한 ServletContext에 대한 해당 웹 애플리케이션의 이름을 반환한다.
log(String name) - 로그 파일에 로그를 기록한다.
removeAttribute(String name) - 해당 name으로 ServletContext에 바인딩된 객체를 제거한다.
setAttribute(String name, Object obj) - 해당 name으로 객체를 ServletContext에 바인딩한다.
setInitParameter(String name, String value) - 주어진 name으로 value를 컨텍스트 초기화 매개변수로 설정한다.

(2) ServletContext 바인딩 기능

* 이번에는 ServletContext의 바인딩 기능을 알아보자.

1. 다음과 같이 GetServletContext, SetServletContext 클래스 파일을 준비한다.

2. SetServletContext 클래스를 다음과 같이 작성한다. getServletContext() 메서드를 이용해 ServletContext 객체에 접근한 다음 ArrayList에 이름과 나이를 저장한 후 다시 ServletContext 객체에 setAttribute() 메서드를 이용해 바인딩한다.

package sec05.ex01;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

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("/cset")
public class SetServletContext extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		ServletContext context = getServletContext(); // ServletContext 객체를 가져온다.

		List member = new ArrayList();
		member.add("이순신");
		member.add(30);
		context.setAttribute("member", member); // ServletContext 객체에 데이터를 바인딩한다.

		out.print("<html><body>");
		out.print("이순신과 30 설정");
		out.print("</body></html>");
	}
}

3. GetServletContext 클래스를 다음과 같이 작성한다. getServletContext() 메서드를 이용해 ServletContext 객체에 접근한다. 그리고 getAttribute() 메서드를 이용해 다른 서블릿에서 바인딩한 ArrayList를 가져와 회원 정보를 출력한다.

package sec05.ex01;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

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("/cget")
public class GetServletContext extends HttpServlet{
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws  ServletException, IOException {
      response.setContentType("text/html;charset=utf-8");
      PrintWriter out = response.getWriter();
	
      ServletContext context = getServletContext();	// ServletContext 객체를 가져온다.		 
      List member = (ArrayList)context.getAttribute("member"); // member로 이전에 바인딩한 회원 정보를 가져온다.
      String name = (String)member.get(0);
      int age = (Integer)member.get(1);
      out.print("<html><body>");
      out.print(name +"<br>");
      out.print(age + "<br>");
      out.print("</body></html>");
   } 
}

4. 크롬 브라우저에서 http://localhost:8090/pro08/cset 으로 요청하면 ServletContext 객체에 데이터를 바인딩한다.

5. 이번에는 인터넷 익스플로러에서 http://localhost:8090/pro08/cget으로 요청한다. 마찬가지로 바인딩된 데이터를 브라우저에 표시한다.

* 이처럼 ServletContext에 바인딩된 데이터는 모든 서블릿들(사용자)이 접근할 수 있다. 따라서 웹 애플리케이션에서 모든 사용자가 공통으로 사용되는 데이터는 ServletContext 에 바인딩해 놓고 사용하면 편리하다.


(3) ServletContext의 매개변수 설정 기능

* 대부분의 웹 애플리케이션에서 메뉴는 공통으로 사용하는 기능이다. 따라서 web.xml에 설정해 놓고 프로그램 시작 시 초기화할 때 가져와서 사용하면 편리하다. 그러면 새로운 메뉴 항목이 생성되거나 기존 메뉴 항목을 추가, 삭제할 때도 쉽게 수정할 수 있다.

1. 다음과 같이 ContextParamServlet 클래스 파일과 web.xml 파일을 준비한다.

2. web.xml에 메뉴 항목을 설정한다. <context-param> 태그 안에 <param-name> 태그와 <param-value> 태그를 이용해 메뉴에 대한 하위 메뉴 항목을 설정한다.

<?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>
</web-app>

3. ContextParamServlet 클래스를 다음과 같이 작성한다. getServletContext() 메서드로 ServletContext 객체에 접근한다. 그리고 getInitParameter() 메서드의 인자로 각각의 메뉴 이름을 전달한 후 메뉴 항목들을 가져와 이를 브라우저로 출력한다.

package sec05.ex02;

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

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("/initMenu")
public class ContextParamServlet extends HttpServlet {	
	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();
      ServletContext context = getServletContext(); // ServletContext 객체를 가져온더.

      String menu_member = context.getInitParameter("menu_member");
      String menu_order = context.getInitParameter("menu_order");
      String menu_goods =context.getInitParameter("menu_goods"); // web.xml의 <param-name> 태그의 이름으로 <param-value> 태그의 값인 메뉴 이름들을 받아 온다.

      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>");	
   }
}

4. 크롬 브라우저에서 http://localhost:8090/pro08/initMenu 로 서블릿을 요청한다.

5. 인터넷 익스플로러에서도 요청해 본다.

* 모든 브라우저에서 같은 메뉴를 출력하는 것을 확인할 수 있다. 즉, 메뉴는 ContextServlet 객체를 통해 접근하므로 모든 웹 브라우저에서 공유하면서 접근할 수 있다.


(4) ServletContext의 파일 입출력 기능

* 이번에는 ServletContext의 파일에서 데이터를 읽어 오는 기능을 알아보자. 먼저 폴더를 하나 생성한다.

1. 프로젝트 pro08의 WebContent/WEB-INF 폴더를 선택하고 마우스 오른쪽 버튼을 클릭한 후 New > Folder를 선택한다.

2. 폴더 이름으로 bin 을 입력하고 Finish를 클릭한다.

3. bin 폴더가 생성된 것을 확인할 수 있다.

4. bin 폴더를 선택하고 마우스 오른쪽 버튼을 클릭한 후 NEW > File을 선택한다.

5. 파일 이름으로 init.txt를 입력하고 Finish를 클릭한다.

6. 생성된 파일에 메뉴 항목을 입력한 후 저장한다.

7. 이제 init.txt에서 메뉴 데이터를 읽어와 출력하는 기능을 구현해 보자. 다음과 같이 ContextFileServlet 클래스를 준비한다.

8. ContextFileServlet 클래스를 다음과 같이 작성한다. getServletContext() 메서드로 ServletContext에 접근하여 getResourceAsStream() 메서드에서 읽어 들일 파일 위치를 지정한 후 파일에서 데이터를 입력 받는다.

package sec05.ex03;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

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("/cfile")
public class ContextFileServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=euc-kr");
		PrintWriter out = response.getWriter();
		ServletContext context = getServletContext();
		InputStream is = context.getResourceAsStream("/WEB-INF/bin/init.txt"); // 해당 위치의 파일을 읽어 들인다.
		BufferedReader buffer = new BufferedReader(new InputStreamReader(is));

		String menu = null;
		String menu_member = null;
		String menu_order = null;
		String menu_goods = null;
		while ((menu = buffer.readLine()) != null) {
			StringTokenizer tokens = new StringTokenizer(menu, ",");
			menu_member = tokens.nextToken();
			menu_order = tokens.nextToken();
			menu_goods = tokens.nextToken();
		} // 콤마(,)를 구분자로 하여 메뉴 항목을 분리한다.
		out.print("<html><body>");
		out.print(menu_member + "<br>");
		out.print(menu_order + "<br>");
		out.print(menu_goods + "<br>");
		out.print("</body></html>");
		out.close();
	}
}

9. http://localhost:8090/pro08/cfile 로 요청하면 다음과 같이 파일의 메뉴 항목을 읽어와 브라우저로 출력한다.