내장객체의정리 헷갈리는내장객체들정리하기 - 컨테이너안에서는수많은객체들이스스로의존재목적에따라서일을한다. - ServletContext, ServletConfig 객체는컨텍스트초기화와서블릿초기화정보를가지고있다. - 이외에도다음의객체들이서블릿과 JSP와 EL에서각각의역할을수행한다. 서블릿의객체 JspWriter HttpServletRequest HttpServletResponse HttpSession ServletContext ServletConfig JspException PageContext JSP의객체 out request response session application config exception pagecontext - EL 의내장객체는위와일치하는객체도있지만, 다른기능을하는객체도있다. EL의객체 의미 pagescope page 영역에설정된속성들을키와값의쌍으로가지고있다. 맵객체이다. requestscope request 영역에설정된속성들을키와값의쌍으로가지고있다. 맵객체이다. sessionscope session 영역에설정된속성들을키와값의쌍으로가지고있다. 맵객체이다. applicationscope application 영역에설정된속성들을키와값의쌍으로가지고있다. 맵객체이다. param 웹브라우저로부터입력된데이터. 맵객체이다. request.getparameter() 와동일하다. paramvalues 웹브라우저로부터입력된데이터의집합. 맵객체이다. request.getparametervalues() 와동일하다. header HTTP 요청메시지에있는 HTTP의헤더. 맵객체이다. request.getheader() 와동일하다. headervalues HTTP 요청메시지에있는 HTTP의헤더의집합. 맵객체이다. request.getheadervalues() 와동일하다. cookie 웹브라우저로부터전송된쿠키의집합. 맵객체이다. initparam 컨텍스트초기화파라미터의집합, 맵객체이다. application.getinitparameter() 의결과와동일하다. pagecontext JSP 페이지의환경정보 ( 위의 PageContext에해당하는객체 ) - EL의내장객체는하나만제외하고 키 와 값 의쌍으로저장하는맵 (Map) 객체이다. - JSP 의 config 는서블릿의 ServletConfig 를의미하고있지만, 사실은서블릿의초기화파라미터를보유하고있는객 체가아니라 JSP 의초기화파리미터를보유하고있는객체이다. - 즉, 서블릿에서 ServletConfig 객체는서블릿의초기화파라미터를의미한다. <web-app... > <servlet> <servlet-class> 패키지이름. 클래스이름 </servlet-class> <init-param> <param-name> 파리미터이름 </param-name>
<param-value> 파라미터의값 </param-value> </init-param> </servlet> <servlet-mapping> <url-pattern>/ 매핑문자열 </url-pattern> </servlet-mapping> - 위의예에서 ServletConfig 객체에는 파리미터이름 이초기화파라미터의이름, 파라미터의값 은초기화파라미터의값이다. - 다음은 JSP에서 ServletConfig 객체는 JSP의초기화파라미터를의미한다. <web-app... > <servlet> <jsp-file>/test.jsp</jsp-file> <init-param> <param-name> 파리미터이름 </param-name> <param-value> 파리미터의값 </param-value> </init-param> </servlet> <servlet-mapping> <url-pattern>/ 매핑문자열 </url-pattern> </servlet-mapping> - 다음은 JSP의초기화파라미터를출력하는 JSP <%@ page language="java" contenttype="text/html; charset=euc-kr" pageencoding="euc-kr"%> <html> <head> <title>insert title here</title> </head> <body> JSP 초기화파라미터 : <%= config.getinitparameter("adminmail") %> <br> </body> </html> - 위의예에서 config는 JSP의초기화정보를가지고있는객체이다.
컨텍스트초기화파라미터를이용해서객체를생성할수있을까? - 물론가능하다. 그런데, 객체를누가생성하느냐가문제가된다. - 서블릿에서객체를생성할수도있다. 그러나, 어떤서블릿이사용될지모르기때문에서블릿도적당하지않다. - 즉, 서블릿이생성되기전에누군가가초기화파라미터로객체를생성해서생성한결과를 ServletContext 객체에저장해야한다. - 여기서누가가리스너 (Listener) 이다. - 리스너도자바클래스이므로, 프로그래머가작성할수있다. 즉, 원하는기능을리스너에구현할수있다. - 리스너를구현했으면, web.xml에리스너를등록한다. <web-app...> <listener> 사용자가 _ 작성한 _ 리스너 _ 클래스 _ 이름 </listener> - 리스너를작성하는방법은사용하려는기능 ( 즉, 언제리스너가동작을하는지에따라리스너가다르다 ) 의리스너클래스를상속하기만하면된다. - 다음은리스너의종류사용용도리스너이름이벤트타입 javax.servlet.servletcontextattributelistener 컨텍스트에속성을추가, 제거, 수정했는지알고싶을때세션이생성되거나, 소멸될때데이터처리가필요할때요청 (request) 가입력될때를알고싶을때 Request에속성이추가, 제거, 수정되었는지알고싶을때속성객체가세션에설정되었는지, 제거되었는지알고싶을때세션에속성이추가, 제거, 변경되었는지알고싶을때컨텍스트객체가생성, 소멸되었는지알고싶을때 리스너의위치 attributeadded ServletContextAttributeEvent attributeremoved attributereplaced javax.servlet.http.httpsessionlistener sessioncreated HttpSessionEvent sessiondestroyed javax.servlet.servletrequestlistener requestinitialized ServletRequestEvent requestdestroyed javax.servlet.servletrequestattributelistener attributeadded ServletRequestAttributeEvent attributeremoved attributereplaced javax.servlet.http.httpsessionbindinglistener valuebound HttpSessionBindingEvent valueunbound javax.servlet.http.httpsessionattributelistener attributeadded HttpSessionBindingEvent attributeremoved attributereplaced javax.servlet.servletcontextlistener contextinitialized ServletContextEvent contextdestroyed
- 웹서버는웹환경에서발생하는다양한요청들을 이벤트 형식으로리스너에전달한다. - 즉, 리스너 ( 이벤트리스너 ) 는웹컨테이너 ( 톰캣 ) 에서어떤사건 (event) 가발생했을때자동으로동작하는객체이다. - 리스너는모두 8개이며, 각각의리스너마다인지하는 이벤트 의종류가다르다. 이것은, 자바의 AWT나 Swing에서이벤트리스너마다처리하는이벤트의종류가다른것과그의미가동일한다. 리스너를적용한예 1 - 컨텍스트초기화파라미터로개의품종을지정한다. - 품종을읽어서품종에해당하는객체를생성해서객체를컨텍스트에속성으로설정한다.( 리스너의역할 ) - 서블릿에서컨텍스트에설정되어있는품종의객체를읽어서개의품종을출력한다. - 사용할리스너의종류는컨텍스트가생성되고나서객체를생생해야하므로컨텍스트가생성되었음을인지하는
ServletContextListener를사용한다. - web.xml에리스너와컨텍스트초기화파라미터를등록한다. <web-app...> 어쩌구저쩌구 <context-param> <param-name>breed</param-name> <param-value> 진돗개 </param-value> </context-param> <listener> model.mycontextlistener </listener> - ServletContextListner를상속해서웹에서사용할리스너를작성한다. public class MyContextListener extends ServletContextListener { public void contextinitialized(servletcontextevent e) { ServletContext sc = e.getservletcontext(); String dogbreed = sc.getinitparameter("breed"); 컨텍스트초기화파라미터이름 Dog d = new Dog(dogBreed); 객체생성 sc.setattribute("dog", d); 컨텍스트객체에속성으로 Dog객체를설정한다. - 서블릿에서는리스너가설정한 dog 파라미터를읽는다. public class MyListenerTest extends HttpServlet { public void dopost(httpservletrequest request, HttpServletResponse response) throws IOExceptioin, ServletException { response.setcontenttype("text/html; charset=euc-kr"); PrintWriter out = response.getwriter(); out.print(" 리스너가설정한객체를사용합니다.<br>"); Dog dog = (Dog)getServletContext().getAttribute("dog"); out.print("<br> 개의품종은 : " + dog.getbreed()); - 다음은 Dog 클래스 public class Dog { private String breed; public Dog(String breed) { this.breed = breed; public String getbreed() { return breed;
리스너를적용한예 2 - 동일한웹서비스에접속한요청의갯수를셀수있다. - 사용자로부터의요청 (request) 을서블릿이수신하기전에리스너가먼저해당요청을수신한다. - 사용자요청을수신할때마다카운트를증가한다. - 증가시킨카운트정보를웹서비스전체에서알수있도록, 웹서비스공통정보객체 (ServletContext) 객체에저장한다. - 따라서, 해당웹서비스에서제공하는모든웹페이지에서웹서비스에접속한요청의갯수를파악할수있다. - 사용자로부터의요청 (request) 을감지하는리스너는 ServletRequestListener 이므로, 이클래스를상속해서리스너 클래스를작성한다. public class ReqCountListener implements ServletRequestListener { private static long reqcount; 사용자로부터의접속을카운트하고, 그결과를저장할변수 public ReqCountListener() { 클래스의생성자 public void requestdestroyed(servletrequestevent arg0) { 접속이해제될때자동으로호출되는메서드 public void requestinitialized(servletrequestevent arg0) { // 접속이수신될때자동으로호출되는메서드. 좀더정확히설명하면, 서블릿에대한요청이벤트가발생할때이메서드가자동으로호출된다. ( 이벤트의이름은매개변수에서확인할수있다. 이벤트의이름은 ServletRequestEvent 이다.) 이렇게어떠한이벤트가발생했을때자동으로실행되는메서드를콜백 (Call-Back) 메서드라고한다. ServletContext context = arg0.getservletcontext(); // 발생한이벤트에서모든웹서비스에공통적으로사용할수있는객체인 ServletContext 를불러온다.
ServletRequest request = arg0.getservletrequest(); // 발생한이벤트에서사용자의요청정보를가지고있는요청객체 (ServletRequest, JSP 에서는 request) 를불러온다. synchronized(context){ //ServletContext 객체는웹서비스에서공통으로사용할수있는객체이므로, 여러객체가동시에접근해서데이터 를수정하면, 정확한데이터를유지할수없다. 그러므로, 동기화처리를통해서하나의객체에둘이상의접근이불가능하도록해야한다.! // 동기화의대상은당연히 ServletContext. 따라서, 이객체가저장된변수인 context 를동기화한다. context.setattribute("reqcount", ++reqcount); 카운트값을공통객체에속성으로저장한다. - web.xml에리스너를등록해야한다.( 자동으로등록작업이이루어지므로, 확인만한다.) <web-app...> 어쩌구저쩌구... <listener> <listener-class>counttest.reqcountlistener</listener-class> </listener> - 서블릿을작성해서공통객체에저장된카운트값을읽어서처리한다. public class ReqCountServlet extends HttpServlet { public ReqCountServlet() { super(); protected void doget(httpservletrequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext context = getservletcontext(); 공통객체를불러온다. long reqcount = Long.parseLong(String.valueOf(context.getAttribute("reqCount"))); // 공통객체에저장된정보를읽어서 Long형의정수로바꾼다. response.setcontenttype("text/html; charset=euc-kr"); PrintWriter out = response.getwriter(); out.print(" 접속한요청의갯수는 : " + reqcount + " 입니다.<br />"); // 카운트값을사용자의웹브라우저에직접보여준다. protected void dopost(httpservletrequest request, HttpServletResponse response) throws ServletException, IOException {