본문 바로가기
국비학원

[국비지원] KH 정보교육원 76일차

by 도전하는 개발자 2022. 7. 15.

서블릿 핵심 클래스

* Servlet Lifecycle
1) NEW       ==> init 메소드 호출(callback) (by web 컨테이너)
2) READY     ==> service 메소드 호출(callback) (by web 컨테이너)
3) DESTROY  ==> destroy 메소드 호출(callback) (by web 컨테이너)

1. ServletConfig API를 활용한 초기화 파라미터 사용 


 서블릿이 초기화될 때 web.xml에서 설정하면 재컴파일 없이 변경된 정보를 참조할 수 있기 때문에 유지보수가 쉬워진다. 

이렇게 web.xml에 설정된 설정 값을 ‘초기화 파라미터(Initialization Parameter)라고 하며ServletConfig API를 이용해서 접근할 수 있다. 특징은 여러 서블릿에서 공유해서 사용하지 못하고 <init-param>으로 등록된 서블릿에서만 사용 가능하다는 점이다. 또한 서블릿 코드 내에서 @WebInitParam 어노테이션을 이용하여 초기화 파라미터를 등록할 수도 있다

다음은 ServletConfig API의 계층 구조이다.


---

web.xml에 초기화 파라미터 등록

<servlet> 태그 안에서 <init-param> 태그를 사용하여 지정한다.
다수의 태그 등록이 가능하고, name/value 쌍으로 설정된다.

<init-param>
   <param-name>초기화파라미터 이름</param-name>
   <param-value>초기화파라미터 값</param-value>
</init-param>

<init-param>
  <param-name>초기화파라미터 이름</param-name>
  <param-value>초기화파라미터 값</param-value>
</init-param>

이렇게 설정된 초기화 파라미터는 ServletConfig를 사용하여 참조할 수 있다. 
다음은 ServletConfig의 핵심 메서드이다


---

web.xml에 초기화 파리미터를 설정하고, 서블릿에서 ServletConfig를 이용하여 참조해보자

 

 

@Log4j2
@NoArgsConstructor

//어노테이션 말고 web.xml에 직접 등록 해보자
//@WebServlet("/InitParam") 
public class InitParamServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse res) 
			throws ServletException, IOException {
		log.trace("service(req, res) invoked.");
		
		try {			
			
			// 1. GenericServlet의 getInitParameter(name) 메서드를 사용하여 web.xml에 설정한 초기화 파라미터를 얻자.
			String dirPath = this.getInitParameter("dirPath"); // 상속받은 메소드는 그냥 사용도 가능하지만 클래스.메소드로 써줘야한다 
			String userid = this.getInitParameter("userid");   // 상속받으면 내꺼니까 this. 붙여주면 된다.
			
			log.info("\t+ dirPath : {}, userid: {}", dirPath, userid);
			
			// 2. 응답문서 생성
			res.setContentType("text/html; charset=UTF-8");
			@Cleanup
			PrintWriter out = res.getWriter();
			
			out.println("<html><body>");
			out.println("디렉토리 경로 :" + dirPath + "<br>");
			out.println("아이디 값 : " + userid + "<br>");
			out.println("</body></html>");			
			out.flush();
		} catch(Exception e) {
			throw new IOException();
		} // try-catch
 
	} // service
	
} // end class


InitParamServlet.java 

-> 현재 web.xml에 <init-param> 등록 안 되어있음!
->  이클립스에서 밑의 코드도 확인해보자 JDBC 바인딩 개념도 있다.



* 이것이 자바다 2권 자바 입출력 Serializable 다시 한번 읽어보기!

---


2. @WebInitParam 어노테이션을 이용한 초기화 파라미터 등록

이니셜라이제이션 파라미터를 클래스 생성 위저드에서 해보자

 

 

@Log4j2
@NoArgsConstructor

@WebServlet( // 아래 내용은 직접 코딩하는게 아니고 위저드에서 작성해주면 된다
		urlPatterns = { "/InitParamAnno" }, 
		initParams = { // 위저드에서 입력한 대로 initialization parameters가 배열의 원소 형태로 입력된다. 
				@WebInitParam(name = "dirPath", value = "_DIRPATH_", description = "디렉토리경로"), 
				@WebInitParam(name = "userid", value = "아이디")
		})
public class InitParamAnnoServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse res) 
			throws ServletException, IOException {
		log.trace("service(req, res) invoked.");
		
		String dirPath = this.getInitParameter("dirPath"); // this. 안 써도 되지만 까먹지 말자 
		String userid = this.getInitParameter("userid");   // this. 안 써도 되지만 까먹지 말자
		
		log.info("\t+ dirPath : {}, userid : {}", dirPath, userid);
		
	} // service

} // end class


InitParamAnnoServlet.java

---

2. ServletContext API

*웹 어플리케이션과 WAS의 생명주기는 같다! (톰캣에서 억지로 죽이는 경우말고)
이러한 웹 어플리케이션에 하나씩 생성되는 객체가 ServletContext이다.

ServletContext는 웹 어플리케이션(Context)마다 하나씩 생성되는 객체로서, 다수의 JSP 파일과 서블릿에서 공유해서 사용할 수 있다. 
또한 ServletContext 객체는 웹 어플리케이션의 LifeCycle과 일치하기 때문에, 웹 어플리케이션이 Tomcat 컨테이너에 존재한다면 계속 사용가능하다. 
이것을 ‘application scope(어플리케이션 영역)’라고 한다.



Servlet- request 받아서 비지니스 로직 처리,  자기 할일 마치면 다른 servlet에 위임하다가 다 끝나면 JSP로 보냄
JSP - Servlet이 보내면 받아서 응답화면 만들고 respond함
servlet은 page scope가 없다. JSP에만 있는 영역. JSP에서도 잘 안 씀 (JSP는 금방 끝나기 때문)

로그인 같은 경우는 Session Scope가 적절
JDBC URL 경우는 Application Scope가 적절

----

다음은 ServletContext 객체를 이용한 핵심 기능이다. 
1) 여러 서블릿에서 사용 가능한 초기화 파라미터를 사용할 수 있다. 
   일반적으로 ‘컨텍스트 파라미터(Context Parameter)’라고 한다. 
2) 서블릿에서 파일을 접근할 수 있다. 읽기 모드만 가능하다. 
3) application scope에 해당되는 속성(Attribute)을 저장하고 조회할 수 있다. 


다음은 ServletContext API의 계층 구조이다. 
GenericServlet을 HttpServlet이 상속받았기 때문에, ServletContext 객체를 얻기 위해서
사용자가 생성한 서블릿에서는 getServletContext() 메서드를 사용한다.



다음은 ServletContext의 핵심 메서드이다.


---

컨텍스트 파라미터(context parameter) 설정
초기화 파라미터 (init parameter)는 특정 서블릿만이 파라미터 값을 사용할 수 있지만, 
컨텍스트 파라미터는 application scope이기 때문에 어플리케이션의 모든 서블릿이 공유해서 사용 가능

pom.xml

 

@Log4j2
@NoArgsConstructor

@WebServlet("/ContextParam")
public class ContextParamServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
    @Override  
	protected void service(HttpServletRequest req, HttpServletResponse res) 
			throws ServletException, IOException {
		log.trace("service(req, res) invoked.");
		
		try {
			// Context Parameters를 얻어보자!!
			// 웹 어플리케이션(=context)마다 생성되는 'ServletContext' 객체가 필요하다
			// HttpServletRequest 타입의 req 객체를 통해 'ServletContext' 타입의 객체를 얻자
			ServletContext sc = req.getServletContext();	
			String driver = sc.getInitParameter("driver");     
			String savePath = sc.getInitParameter("savePath"); 
			
			log.info("driver : {}, savePath : {}", driver, savePath);
			
			// 응답 문서 생성
			res.setContentType("text/html; charset=UTF-8");
			@Cleanup
			PrintWriter out = res.getWriter();
			
			out.println("<html><body>");
			out.println("드라이버명: " + driver +"<br>");
			out.println("저장경로: " + savePath +"<br>");
			out.println("</html></body>");
			
			out.flush();			
			
		} catch(Exception e) {
			throw new IOException();
		} // try-catch 
		
	} // service
    
} // end class


ContextParamServlet.java