서블릿 init paramter는 servlet이 초기화되기전엔 사용할 수 없다.
container가 init()을 호출한 뒤에야 쓸 수 있음.
init(ServletConfig)
라고 servletconfig를 넘겨주는 경우가 있는데 이건 ServletConfig를 Override한 경우 사용한다.뭐 어쨌든 그 뒤에 사용을 한다 치자. 문제는 모든 servlet에 attribute를 하나하나 DD에 설정해서 넣어줘야 하나? 공통적으로 써야할 것 까지도?
global 하게 써야 할 방법을 생각해보자.
global...
<context-param>
<param-name>adminEmail</param-name>
<param-value>google@naver.com</param-value>
</context-param>
out.println(getServletContext().getInitParameter("adminEmail"));
getServletContext()
메소드를 가지고 있음을 알아두자.참고
ServletConfig는 servlet당 하나. ServletContext는 web app당 하나다.
global한 설정은 ServletContext에 해준다는 것을 명심.
해결책은 Listener!
ServletContextListener
가 한다.ServletContext
로부터 init parameter들을 얻어온다.package com.example.servlet;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
public class MyServletListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent event){
//database 연결하는 코드
}
public void contextDestroyed(ServletContext event) {
//database 연결 끊는 코드
}
}
<listener> 및 <context-param>
등등)ServletContext
를 생성한다.contextInitialized()
메소드를 호출한다. 이때 new ServletContextEvent
를 parameter로 전달해준다.ServletContextEvent
에게 ServletContext
의 reference를 요청한다.ServletContext
에 init parameter "breed"를 요청한다.ServletConfig
+ init
) 이해안되면 전에 쓴거 보고오기HttpSessionBindingListener
와 HttpSessionAttributeListener
가 뭔 차이인지 모를 수 있음.HttpSessionAttributeListener
는 모든 타입의 attribute가 session에서 add, remove, replace될 때 체크HttpSessionBindingListener
는 자신이 session에서 add되거나 remove될 때만 체크 -> implement한 놈들만.package com.example.servlet;
public class Dog implements HttpSessionBindingListener {
private String breed;
public Dog(String breed){
this.breed = breed;
}
public String getBreed(){
return breed;
}
public void valueBound(HttpSessionBindingEvent event){
//자신이 session내에 있다는 것을 인지했을 때 실행하는 코드를 작성
}
public void valueUnbound(HttpSessionBindingEvent event){
// session에서 벗어나는 순간 실행하는 코드를 작성.
}
}
getAttribute(String name)
getInitParameter(String name)
public synchronized void doGet ...
이것으로는 context attribute를 지킬 수 없다.
이걸 써버리면, 동일한 servlet을 사용하는 요청을 다른 클라이언트가 했을 때 그 요청들이 아예 막혀버린다.
게다가, 동일하지 않은 다른 servlet 사용시 context scope의 attribute들이 수정가능하다는 큰 문제가 생김.
2. context를 lock한다.
정확히는 context object에 synchronizing한다.
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
synchronized(getServletContext()){
//blabla.
}
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
...
HttpSession session = request.getSession();
synchronized(session) {
session.setAttribute("foo", "22");
...
}
}
그냥 둘다 안좋다.
결국 좋은 서블릿 디자인은 instance 변수를 사용하지 않는 디자인.
RequestDispatcher
를 사용한다.//code in a doGet()
BeerExpert be = new BeerExpert();
ArrayList result = be.getBrands(c);
//request scope에 model data 집어넣는다.
request.setAttribute("styles", result);
//view JSP에 대한 dispatcher 얻음
RequestDispatcher view = request.getRequestDispatcher("result.jsp");
//JSP에게 request와 response object를 넘기겠다고 말함.
view.forward(request, response);
RequestDispatcher는 딱 두가지 메소드만 있다.
forward()
include()
RequestDispatcher를 쓸 때 주의할점은 다음과 같다.
IllegalStateException
이 발생한다.