Top Banner
Servlets & JSP 5장
39

HeadFisrt Servlet&JSP Chapter 5

Aug 08, 2015

Download

Documents

J B
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: HeadFisrt Servlet&JSP Chapter 5

Servlets & JSP5장

Page 2: HeadFisrt Servlet&JSP Chapter 5

속성과 리스너

• 5장 스터디 범위

Page 3: HeadFisrt Servlet&JSP Chapter 5

초기화 파라미터(1)• 하나의 서블릿 내에서 계속해서 참조하고자 하는 정보가

있음 (책에서는 admin email을 예시로 제시함)

• DD(=배포서술자) web.xml에서

<servlet> .... 코드 생략 .... <init-param> <param-name>adminEmail</param-name> <param-value>[email protected]</param-value> </init-param> </servlet>

Page 4: HeadFisrt Servlet&JSP Chapter 5

초기화 파라미터(2)• DD(=배포서술자) web.xml에서

• 서블릿 코드에서는

out.println(getServletConfig().getInitParameter("adminEmail"));

<servlet> .... 코드 생략 .... <init-param> <param-name>adminEmail</param-name> <param-value>[email protected]</param-value> </init-param> </servlet>

Page 5: HeadFisrt Servlet&JSP Chapter 5

초기화 파라미터(3)• 아래 코드가 의미하는 바는

• 이미 servletConfig 객체가 가 있다는 뜻이겠죠?

• 이 일은 서블릿이 초기화 될때 -> init(servletConfig) 때 생성됩니다

out.println(getServletConfig().getInitParameter("adminEmail"));

Page 6: HeadFisrt Servlet&JSP Chapter 5

이를 절차적으로 표현하면• 1. 컨테이너가 배포서술자를 읽었는데 <init-param> 이 있으면 -> 2.

ServletConfig 인스턴스를 만들어 줍니다(서블릿당 한개씩)서블릿당 한개씩 == <servlet></servlet> 개수 만큼 인스턴스 생성

• 3. 컨테이너는 <init-param> 내에 있는 이름과 값을 확인한 후 ServletConfig 객체에 저장해 주고

• 4. 이후 컨테이너가 서블릿 클래스 인스턴스를 생성하고

• 5. 생성한 후에 init의 인자로 ServletConfig(=> init(ServletConfig) )를 진행함으로써 서블릿 초기화 파라미터를 공유할 수 있게 됨

Page 7: HeadFisrt Servlet&JSP Chapter 5

컨텍스트 초기화 파라미터(1)• 이전 초기화 파라미터를 활용하면 이런것이 가능하겠죠?

<servlet> —- 위 생략 —- // 메일 관련 servlet <context-param> <param-name>MailHelp</param-name> <param-value>[email protected]</param-value> </context-param> </servlet>

<servlet> // 카페 관련 servlet <context-param> <param-name>CafeHelp</param-name> <param-value>[email protected]</param-value> </context-param> </servlet> —- 아래 생략 —-

Page 8: HeadFisrt Servlet&JSP Chapter 5

컨텍스트 초기화 파라미터(2)• 근데 만약 한개의 통합된 help 이메일을 제공하고 싶다면?

<servlet> —- 위 생략 —- // 메일 관련 servlet <context-param> <param-name>help_intergrated</param-name> <param-value>[email protected]</param-value> </context-param> </servlet>

<servlet> // 카페 관련 servlet <context-param> <param-name>help_intergrated</param-name> <param-value>[email protected]</param-value> </context-param> </servlet> —- 아래 생략 —-

?????????

Page 9: HeadFisrt Servlet&JSP Chapter 5

컨텍스트 초기화 파라미터(3)• 지금 우리가 생각한것?

어 코드중복이다

한번의 수고로 프로그램을 제어하고 싶다

해결책?? ->> 다음장

Page 10: HeadFisrt Servlet&JSP Chapter 5

• 지금까지 4번 등장한

컨텍스트 초기화 파라미터(4)

컨텍스트 초기화 파라미터 가 답입니다

Page 11: HeadFisrt Servlet&JSP Chapter 5

How To Use 컨텍스트 초기화 파라미터?(5)

• 왼쪽을 오른쪽과 같이 만들어 주면 됩니다

<servlet> —- 위 생략 —- // 메일 관련 servlet <context-param> <param-name>help_intergrated</param-name> <param-value>[email protected]</param-value> </context-param> </servlet>

<servlet> // 카페 관련 servlet <context-param> <param-name>help_intergrated</param-name> <param-value>[email protected]</param-value> </context-param> </servlet> —- 아래 생략 —-

<context-param> —- 위 생략 —- <param-name>help_intergrated</param-name> <param-value>[email protected]</param-value> </context-param>

<servlet> // 메일 관련 servlet </servlet>

<servlet> // 카페 관련 servlet </servlet> —- 아래 생략 —-

Page 12: HeadFisrt Servlet&JSP Chapter 5

그러면 서블릿에서 컨텍스트 초기화 파라미터에

어떻게 접근하나요? (6)• 이렇게요

out.println(getServletContext().getInitParameter("adminEmail"));

읭? 뭐가 달라요?

out.println(getServletConfig().getInitParameter("adminEmail"));

out.println(getServletContext().getInitParameter("adminEmail"));

Page 13: HeadFisrt Servlet&JSP Chapter 5

좋은 방법은 아닌것 같지만 전역변수와 지역변수 개념을 활용해

이해해 보면 . . .

Page 14: HeadFisrt Servlet&JSP Chapter 5

어 근데..? 지난학기에 객체지향적으로 프로그래밍 작성하자고

교수님이 말씀하셨는데??

왜 지금까지 String 타입의 이메일 주소만 공유해?

나 객체 공유할래

Page 15: HeadFisrt Servlet&JSP Chapter 5

객체를 공유해 볼까?• 음 우선 DD에는 문자열 밖에 못들어 간다고 하네?

• 그러면 문자열 받아와서 객체를 생성하게 해주는어떤 친구를 만들면 되겠다

• 음 우리가 배운 MVC 패턴을 고려할 때 C가 이 역할을 담당하면 좋을것 같네??

• 좋아 control 역할을 해주는 서블릿을 만들고 그 서블릿이 객체를 만든 후 객체가 공유될 수 있도록 속성에 묶어두게 하면 되겠네?

Page 16: HeadFisrt Servlet&JSP Chapter 5

우왕 너무 좋은 방법이다

나만 믿고 개발하면 됨 따라와

Page 17: HeadFisrt Servlet&JSP Chapter 5

뭔가 잘못된것 같은데 고쳐볼사람?

저요!서블릿은 자신이 호출 되어야지만

동작할 수 있어요

control 역할을 해줄 서블릿즉 객체를 만든 후 객체가 공유될 수있도록 속성에 묶어줄 서블릿이먼저 호출되지 않으면 문제가 생길것 같아요

Page 18: HeadFisrt Servlet&JSP Chapter 5

그래서 필요한 것이 리스너!• JSP도 아니고 서블릿도 아닌 어떤 자바객체

• 초기화 목적으로 실행될 어떤 객체

•그것이 바로 리스너

Page 19: HeadFisrt Servlet&JSP Chapter 5

ServletContextListener는 뭐해요?

• 컨텍스트가 초기화 되는 것을 알아 차립니다(초기화 = 애플리케이션이 배포됨)

• Servlet Context로 부터 컨텍스트 초기화 파라미터를 읽음

• 데이터 베이스 연결을 위한 초기화 파라미터를 사용함

• 컨텍스트가 종료되는것을 알아요

Page 20: HeadFisrt Servlet&JSP Chapter 5

리스너는 어떻게 만들까요?• 우선 Web.xml에 listener 항목을 추가해 줍니다

<listener> <listener-class> com.example.MyServletContextListener </listener-class> </listener>

앗! 단 해당 클래스는 반드시 ServletContextListener 인터페이스를 상속받고 있어야 해요

Page 21: HeadFisrt Servlet&JSP Chapter 5

이렇게 말이죠

public class MyServletContextListener implements ServletContextListener { public void contextInitialized(ServletContextEvent event){ servletContext sc = event.getServletContext(); String dogBreed = sc.getInitParameter("breed"); Dog d = new Dog(dogBreed); sc.setAttribute("dog", d); } }

Page 22: HeadFisrt Servlet&JSP Chapter 5

이후 그냥 속성에 객체를 속성에 저장해 주면 되요

public class MyServletContextListener implements ServletContextListener { public void contextInitialized(ServletContextEvent event){ servletContext sc = event.getServletContext(); String dogBreed = sc.getInitParameter("breed"); Dog d = new Dog(dogBreed);

sc.setAttribute("dog", d); } }

Page 23: HeadFisrt Servlet&JSP Chapter 5

그러면 서블릿에서는 어떻게 가져오나요?

public class ListenerTester extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, servletException { response.setContentType("text/html"); PrintWriter out = response.getWriter();

Dog dog = (Dog) getServletContext().getAttribute("dog");

out.println("Dog's breed is : "+ dog.getBreed()); } }

getAttribute의 return값은 Object!!!

Page 24: HeadFisrt Servlet&JSP Chapter 5

리스너는 8개가 있다고 해요• 216페이지를 참조하세요

• 우리는 다시 context 이야기로 돌아가도록 합시다

Page 25: HeadFisrt Servlet&JSP Chapter 5

Context 생존범위는 스레드에 안전하지 못하다고 해요

• 그 이유는 서블릿이 멀티 스레드 기반으로 실행되는데요청이 동일한 서블릿으로 부터 온 것인지 다른 서블릿으로 부터 온 것인지 알지 못하기 때문이라고 합니다

Page 26: HeadFisrt Servlet&JSP Chapter 5

책에서 보인 예시• 서블릿1이 A를 10 B를 5로 설정하였다

• 그런데 서블릿2가 와서 A를 7로 바꾸어 놓았다

• 서블릿 1은 A를 불러오면 당연히 10이 return될 것이라 생각했다

• 하지만 7이 왔다

Page 27: HeadFisrt Servlet&JSP Chapter 5

그림으로

10 5

7context

Page 28: HeadFisrt Servlet&JSP Chapter 5

그림으로

10 7context

Page 29: HeadFisrt Servlet&JSP Chapter 5

그림으로

10 5

7context

보호 중

Page 30: HeadFisrt Servlet&JSP Chapter 5

그림으로

10 5

7context

보호 중

컨텍스트에 락이 필요

Page 31: HeadFisrt Servlet&JSP Chapter 5

HowTo컨텍스트 락걸기?

public void doGet(어쩌구 저쩌구) throws 어쩌구, 저쩌구 { ... 코드 ... synchronized(getServletContext()){ getServletContext().setAttribute("foo", "22"); getServletContext().setAttribute("bar", "42");

out.println(getServletContext().getAttribute("foo")); out.println(getServletContext().getAttribute("bar")); } ... 코드 ... }

보호되는 영역

Page 32: HeadFisrt Servlet&JSP Chapter 5

세션도 동기화 문제가 있다고 해요

세션? 하나의 클라이언트와의 대화 상태를 유지하기 위해서 사용

한 시점에 세션에서 작업하는 스레드는 오직 하나

그런데 왜 동기화 문제가 발생?

Page 33: HeadFisrt Servlet&JSP Chapter 5

동일한 클라이언트 하나 이상의 요청

같은 세션에 요청이 들어감 정말 안전한가?

Page 34: HeadFisrt Servlet&JSP Chapter 5

이 문제를 해결하기 위해

public void doGet(어쩌구 저쩌구) throws 어쩌구, 저쩌구 { ... 코드 ... synchronized(session){ getServletContext().setAttribute("foo", "22"); getServletContext().setAttribute("bar", "42");

out.println(getServletContext().getAttribute("foo")); out.println(getServletContext().getAttribute("bar")); } ... 코드 ... }

Page 35: HeadFisrt Servlet&JSP Chapter 5

아 도데체 어떤 것들이 스레드로 부터 안전한가요?

• Request 속성 및 지역변수

Page 36: HeadFisrt Servlet&JSP Chapter 5

3장 스터디에서 보았던 코드

public void doGet(어쩌구 저쩌구) throws 어쩌구, 저쩌구 { JSP단으로 보내줄 데이터를 열심히 가공합니다 JSP단으로 보내줄 데이터를 정말 열심히 열심히 가공합니다 ... 코드 ... JSP단으로 보내줄 데이터를 열심히 가공했어요 RequestDispatcher view = request.getRequestDispatcher("result.jsp"); view.forward(request, response); }

Page 37: HeadFisrt Servlet&JSP Chapter 5

여기에 flush가 들어가면?

public void doGet(어쩌구 저쩌구) throws 어쩌구, 저쩌구 { JSP단으로 보내줄 데이터를 열심히 가공합니다 JSP단으로 보내줄 데이터를 정말 열심히 열심히 가공합니다 ... 코드 ... JSP단으로 보내줄 데이터를 열심히 가공했어요

os.flush(); RequestDispatcher view = request.getRequestDispatcher("result.jsp"); view.forward(request, response); }

IllegalSt

ateExc

eption

Page 38: HeadFisrt Servlet&JSP Chapter 5

flush() 라는 것은

• 클라이언트에게 응답을 보냈다.

• response를 내려 보내라

• 끝났다 라는 뜻이므로

• 이미 request를 쓸 수 없는 상태가 되어 버렸다

IllegalStateException 발생 원인

Page 39: HeadFisrt Servlet&JSP Chapter 5

Q & A