💻 Web_Back end/Servlet

서블릿의 필터와 리스너 기능

개발진스 2023. 4. 26. 00:35
728x90

1. 서블릿 속성과 스코프

 

서블릿 속성이란 다음 세 가지 서블릿 API 클래스에 저장되는 객체(정보)이다.

  • ServletContext
  • HttpSession
  • HttpServletRequest

 

서블릿 API의 setAttribute(String name, Object value)로 바인딩하고, 필요할 때 getAttribute(String name)으로 바인딩 된 속성을 가져오면 된다.

또한 removeAttribute(String name)을 이용해 속성을 서블릿 API에서 제거할 수도 있다.

 

 

서블릿의 스코프란 서블릿 API에 바인딩 된 속성에 대한 접근 범위를 의미한다.

 

ServletContext에 바인딩 된 속성은 애플리케이션 전체에서 접근할 수 있으므로 애플리케이션 스코프를 갖는다.

HttpSession에 바인딩 된 속성은 그 HttpSession에 해당하는 브라우저에서만 접근할 수 있으므로 세션스코프를 갖는다.

HttpServletRequest는 해당 요청/응답에 대해서만 접근하므로 리퀘스트 스코프를 갖는다.

 

 

스코프의 기능

  • 로그인 상태 유지 기능
  • 장바구니 기능
  • MVC의 Model과 View의 데이터 전달 기능

 

스코프의 종류와 특징

스코프 종류 해당 서블릿 API 속성의 스코프
애플리케이션 스코프 ServletContext 속성은 애플리케이션 전체에 대해 접근이 가능
세션 스코프 HttpSession 속성은 브라우저에서만 접근이 가능
리퀘스트 스코프 HttpServletRequest 속성은 해당 요청/응답 사이클에서만 접근이 가능

 

setattribute.java

	protected void doGet(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
		response.setContentType("text/html; charset=utf-8");
		PrintWriter out = response.getWriter();
		String ctxMesg = "context에 바인딩됩니다.";
		String sesMesg = "session에 바인딩됩니다.";
		String reqMesg = "request에 바인딩됩니다.";
		// HttpServletContext, HttpSession, HttpServletRequest를 얻은 후 속성을 바인딩
		ServletContext ctx = getServletContext();
		HttpSession session = request.getSession();
		ctx.setAttribute("context", ctxMesg);
		session.setAttribute("session", sesMesg);
		request.setAttribute("request", reqMesg);
		out.print("바인딩을 수행합니다.");
	}

ServletContext, HttpSession, HttpServletRequest 객체의 setAttribute( ) 메서드를 이용해 속성을 바인딩 한다.

 

 

getattribute.java 

	protected void doGet(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
		response.setContentType("text/html; charset=utf-8");
		PrintWriter out = response.getWriter();
		ServletContext ctx = getServletContext();
		HttpSession sess = request.getSession();
		// 각 서블릿 API에서 바인딩 된 속성의 값을 가져옴
		String ctxMesg = (String) ctx.getAttribute("context");
		String sesMesg = (String) sess.getAttribute("session");
		String reqMesg = (String) request.getAttribute("request");
		
		out.print("context값 : " + ctxMesg + "<br>");
		out.print("session값 : " + sesMesg + "<br>");
		out.print("request값 : " + reqMesg + "<br>");
	}

 

set으로 요청 출력 결과

 

get으로 요청 출력 결과

Context와 Session 객체에 바인딩 된 속성은 같은 브라우저에서 접근할 수 있어서 값을 출력하지만, 기존에 바인딩 된 request 객체는 /get으로 요청하여 생성된 request 객체와 다르기 때문에 null이 출력된다.

 

edge브라우저 에서 get으로 요청 출력 결과

edge브라우저에서 /get으로 요청시 크롬 세션 객체에는 접근할 수 없어서 session값은 null을 출력한다.

반면에 context 객체에 바인딩된 데이터는 모든 브라우저에서 같은 결과를 출력한다.

 

 

2. 서블릿의 여러가지 URL 패턴

 

URL 패턴이란 실제 서블릿의 매핑 이름을 말한다.

즉, 서블릿 매핑 시 사용되는 가상의 이름으로, 클라이언트가 브라우저에 요청할 때 사용되며 반드시 /(슬래시)로 시작해야 한다.

 

URL패턴의 종류는 이름이 일치하는지, 디렉터리까지만 일치하는지, 확장자만 일치하는지에 따라 세가지로 나누어진다.

 

 

서블릿에 여러가지 URL 패턴 적용 실습

 

TestServlet1.java

@WebServlet("/first/test") //정확히 이름까지 일치하는 URL 패턴
public class TestServlet1 extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public TestServlet1() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		
		PrintWriter out = response.getWriter();
		String context = request.getContextPath();		//컨텍스트 이름만 가져온다
		String url = request.getRequestURL().toString();//전체 URL을 가져온다
		String mapping = request.getServletPath();		//서블릿 매핑 이름만 가져온다
		String uri = request.getRequestURI();			//URI를 가져온다
		
		out.println("<html>");
		out.println("<head>");
		out.println("<title>Test Servlet1</title>");
		out.println("</head>");
		out.println("<body bgcolor='green'>");
		out.println("<b>TestServlet1입니다.</b><br>");
		out.println("<b>컨텍스트 이름 : " + context + "</b><br>");
		out.println("<b>전체 경로 : " + url + "</b><br>");
		out.println("<b>매핑 이름 : " + mapping + "</b><br>");
		out.println("<b>URI : " + uri + "</b>");
		out.println("</body>");
		out.println("</html>");
		out.close();
	}
}

이 서블릿은 /first/test로 요청할 때 실행 된다.

/first/test로 요청 결과

 

 

TestServlet2.java

@WebServlet("/first/*") //디렉토리 이름만 일치하는 URL패턴
public class TestServlet1 extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
		...
        위의 TestServlet1.java코드와 동일
        ..        
		out.println("<body bgcolor='yellow'>");
		out.println("<b>TestServlet3입니다.</b><br>");
        ...
	}
}

이 서블릿은 /first/ 디렉터리 이름으로 시작되는 요청에 의해 실행된다.

 

/first/base로 요청 결과
/first로 요청 결과
/first/base.do로 요청 결과

 

TestServlet3.java

@WebServlet("*.do*") //확장자만 일치하는 패턴
public class TestServlet1 extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
		...
        위의 TestServlet1.java코드와 동일
        ..        
		out.println("<body bgcolor='red'>");
		out.println("<b>TestServlet3입니다.</b><br>");
        ...
	}
}

이 서블릿은 매핑 이름에 상관 없이 확장자가 .do이면 실행된다.

 

/base.do로 요청 결과
/second/base.do로 요청 결과

/first/base.do로 요청 시 확장자명이 .do로 끝나지만 앞의 디렉터리 이름이 우선하므로 TestServlet2가 실행된다.
반면에 /second/base.do로 요청 시 /second 디렉터리는 존재하지 않으므로 확장자명 .do를 우선하여 TestServlet3이 실행된다.

 

이번에는 ServletTest3.java 클래서의 URL 패턴을 /*로 설정한 후 요청해본다.

@WebServlet("*.do")를 주석처리하고, @WebServlet("/*")를 입력하여 실행한다.

확장자 명 없이 요청한 결과

확장자명을 지정하지 않을 수 있고, do 대신 자신이 원하는 이름으로 지정해서 사용할 수도 있다.

do는 일반적으로 MVC나 프레임워크에서 자주 사용하는 확장자명이다.

 

 

3. Filter API

 

브라우저에서 서블릿에 요청하거나 응답할 때 미리 요청이나 응답과 관련해 여러 가지 작업을 처리하는 기능이다.
프로그래밍을 하다가 한글 인코딩처럼 각 서블릿에서 반복적으로 처리해야 하는 작업이 있을 수 있는데, 이런 경우 서블릿의 공통 작업을 미리 필터에서 처리하면 반복해서 작업할 필요가 없다.

 

 

이전 예제에서는 웹 페이지에 입력한 한글을 서블릿에 전달하려면 위와 같이 setCharacterEncoding() 메서드를 이용해 한글 인코딩 설정을 서블릿마다 상단에 추가했다.

하지만 모든 서블릿에서 공통으로 처리하는 작업을 먼저 필터에서 처리해주면 편리하게 이용이 가능하다.

 

필터의 종류


필터는 용도에 따라 크게 요청 필터와 응답 필터로 나뉘며 다음과 같은 API가 있다.


요청 필터

  • 사용자 인증 및 권한 검사
  • 요청 시 요청 관련 로그 작업
  • 인코딩 기능

 

응답 필터

  • 응답 결과에 대한 암호화 작업
  • 서비스 시간 측정

 

필터 관련 API

  • javax.servlet.Filter
  • javax.servlet.FilterChain
  • javax.servlet.FilterConfig

 

Filter 인터페이스에 선언된 메서드

메서드 기능
destroy( ) 필터 소멸 시 컨테이너에 의해 호출되어 종료 작업을 수행
doFilter( ) 요청/응답 시 컨테이너에 의해 호출되어 기능을 수행
init( ) 필터 생성 시 컨테이너에 의해 호출되어 초기화 작업을 수행

 

FilterConfig의 메서드

메서드 기능
getFilterName( ) 필터 이름을 반환
getInitParameter(String name) 매개변수 name에 대한 값을 반환
getServletContext( ) 서블릿 컨텍스트 객체를 반환

 

 

1) 사용자 정의 Filter 만들기

 

사용자 정의 필터는 반드시 Filter 인터페이스를 구현해야 하고, init( ), doFilter( ), destroy( )의 추상 메서드를 구현해야 한다.사용자 정의 필터를 생성하면 필터를 각각의 요청에 맞게 적용하기 위해 필터 매핑을 해야 하는데, 필터를 매핑하는 방법은 다음 두 가지이다.

 

  • 애너테이션을 이용하는 방법
  • web.xml에 설정하는 방법


일반적으로 애너테이션을 이용하는 방법이 편리하므로 많이 사용한다.

 

login.html

<body>
	<form name="frmLogin" method="post" action="login" encType="UTF-8">
		이름 : <input type="text" name="user_name"><br>
		비밀번호 : <input type="password" name="user_pw"><br>
		<input type="submit" value="로그인">
		<input type="reset" value="다시입력">
	</form>
</body>

 

LoginTest.java

	protected void doPost(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
		response.setContentType("text/html; charset=utf-8");
		PrintWriter out = response.getWriter();
		String user_name = request.getParameter("user_name");
		String user_pw = request.getParameter("user_pw");
		out.println("<html><body>");
		out.println("이름은 " + user_name + "<br>");
		out.println("비밀번호는 " + user_pw + "<br>");
		out.println("</body></html>");
	}

login.html 실행화면
한글이 깨져서 출력

setCharacterEncoding()메서드를 사용하지 않으면 한글이 깨진걸 확인할 수 있다.

 

이번에는 필터를 이용해 한글 인코딩 기능을 구현해 본다.

 

1. 패키지를 선택하고 마우스 오른쪽 버튼을 클릭한 후 New>Filter를 선택한다

 

2. class name 으로 EncoderFilter를 입력하고 Next를 클릭한다.

 

3. Filter mappings에서 /EncoderFilter를 선택한후 Edit를 클릭한다.

 

4. 모든 요청에 필터기능을 수행하도록 Pattern을 /*로 수정한다.

 

5. Finish를 클릭하여 필터 클래스가 생성된 것을 확인한다.

 

EncoderFilter.java

//WebFilter 애너테이션을 이용해 모든 요청이 필터를 거치게 한다.
@WebFilter("/*")

//사용자 정의 필터는 반드시 Filter 인터페이스를 구현해야 한다.
public class EncoderFilter extends HttpFilter implements Filter {
	ServletContext context;

	public void init(FilterConfig fConfig) throws ServletException {
		System.out.println("utf-8 인코딩................");
		context = fConfig.getServletContext();
	}

	// doFilter안에서 실제 필터 기능을 구현한다
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("doFilter 호출");
		// 한글 인코딩 설정 작업을 한다
		request.setCharacterEncoding("utf-8");
		// 웹 어플리케이션의 컨텍스트 이름을 가져온다
		String context = ((HttpServletRequest) request).getContextPath();
		// 웹 브라우저에서 요청한 요청 URI를 가져온다
		String pathinfo = ((HttpServletRequest) request).getRequestURI();
		// 요청 URI의 실제 경로를 가져온다
		String realPath = request.getRealPath(pathinfo);
		String mesg = " Context 정보:" + context + "\n URI 정보 : " + pathinfo + "\n 물리적 경로: " + realPath;
		System.out.println(mesg);

		// 다음 필터로 넘기는 작업을 수행한다.
		chain.doFilter(request, response);
	}

	public void destroy() {
		System.out.println("destroy 호출");
	}

}

브라우저 요청시 doFilter()메서드의 매개변수로 request와 response가 전달되며, doFilter()메서드는 FilterChain타입인 chain을 세번째 매개변수로 가진다.

전달된 request를 이용해 한글 인코딩 작업을 하고, chain.doFilter()메서드를 기준으로 위쪽에 위치한 코드는 요청 필터 기능을 수행한다.

 

실행화면

톰캣을 재실행하고 다시 ID에 한글을 넣으면한글이 깨지지 않는걸 확인 할 수 있다

필터 호출시 console 메세지 출력

 

2) 응답 Filter 사용

 

서블릿에서 요청과 응답에 대한 필터 기능은 동일한 필터가 수행한다.

한 필터에서 요청과 응답 기능을 수행하는 방법은 필터에서 doFilter( ) 메서드를 기준으로 위쪽에 위치한 코드는 요청 필터 기능을 수행하고, 아래에 위치한 코드는 응답 필터 기능을 수행한다.

 

EncoderFilter.java

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("doFilter 호출");
		// 한글 인코딩 설정 작업을 한다
		request.setCharacterEncoding("utf-8");
		// 웹 어플리케이션의 컨텍스트 이름을 가져온다
		String context = ((HttpServletRequest) request).getContextPath();
		// 웹 브라우저에서 요청한 요청 URI를 가져온다
		String pathinfo = ((HttpServletRequest) request).getRequestURI();
		// 요청 URI의 실제 경로를 가져온다
		String realPath = request.getRealPath(pathinfo);
		String mesg = " Context 정보:" + context + "\n URI 정보 : " + pathinfo + "\n 물리적 경로: " + realPath;
		System.out.println(mesg);
		
		//요청 필터에서 요청 처리 전의 시각을 구한다
		long begin = System.currentTimeMillis();
		
		// 다음 필터로 넘기는 작업을 수행한다.
		chain.doFilter(request, response);
		
		//응답 필터에서 요청 처리 후의 시간을 구한다
		long end = System.currentTimeMillis();
		//작업 요청 전 후의 시각 차를 구해 작업 시간을 구한다.
		System.out.println("작업 시간:" + (end - begin)+"ms");
	}

위에 작성한 코드와 동일한코드에 long begin과 end를 추가한다.

실행하면 로그인 요청 작업에 걸린 시간을 콘솔로 표시한다. 로컬 PC에서의 실습이기때문에 너무 빨라 0ms를 표시한다.
이처럼 서블릿이나 JSP에서 공통으로 처리해야 할 작업을 필터에 구현해 놓고 사용하면 편리하게 사용할 수 있다.

 

실행 console 화면

 

 

4. 여러가지 서블릿 관련 Listener API

 

자바 GUI에서는 마우스 클릭과 같은 이벤트 발생 시 여러 가지 이벤트 핸들러를 이용해 화면의 기능을 구현한다.
이처럼 서블릿에서도 아래 표와 같이 서블릿에서 발생하는 이벤트에 대해 적절한 처리를 해주는 여러 가지 리스너를 제공한다.

 

서블릿 관련 여러가지 리스너들

서블릿 관련 Listener 추상 메서드 기능
ServletContextAttributeListener attributeAdded( )
attributeRemoved( )
attributeReplaced( )
Context 객체에 속성 추가/제거/수정 이벤트 발생 시 처리
HttpSessionListener sessionCreated( )
sessionDestroyed( )
세션 객체의 생성/소멸 이벤트 발생 시 처리
ServletRequestListener requestInitialized( )
requestDestroyed( )
클라이언트의 요청 이벤트 발생 시 처리
ServletRequestAttibuteListener attributedAdded( )
attributedRemoved( )
attributeReplaced( )
요청 객체에 속성 추가/제거/수정 이벤트 발생 시 처리
HttpSessionBindingListener valueBound( )
valueUnbound( )
세션에 바인딩/언바인딩된 객체를 알려주는 이벤트 발생 시 처리
HttpSessionAttributeListener attributedAdded( )
attributedRemoved( )
attributeReplaced( )
세션에 속성 추가/제거/수정 이벤트 발생 시 처리
ServletContextListener contextInitialized( )
contextDestroyed( )
컨텍스트 객체의 생성/소멸 이벤트 발생 시 처리
HttpSessionActivationListener sessionDidActivate( )
sessionWillPassivate( )
세션의 활성화/비활성화 이벤트 발생 시 처리

 

 

1) HttpSessionBindingListener 이용해 로그인 접속자수 표시

 

login2.html

<body>
	<form name="frmLogin" method="post" action="login" encType="UTF-8">
		아이디 : <input type="text" name="user_id"><br>
		비밀번호: <input type="password" name="user_pw"><br>
		<input type="submit" value="로그인">
		<input type="reset" value="다시 입력">
	</form>
</body>

 

LoginImpl loginUser=new LoginImpl(user_id, user_pw)를 실행하여 전송된 ID와 비밀번호를 저장한다.

session.setAttribute("loginUser", loginUser)으로 세션에 바인딩 시 미리 HttpSessionBinding Listener를 구현한 LoginImpl의 valueBound( ) 메서드를 호출한다.

 

LoginTest.java

	protected void doPost(HttpServletRequest request, HttpServletResponse response) 
    		throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html; charset=utf-8");
		PrintWriter out = response.getWriter();
		HttpSession session = request.getSession();
		String user_id = request.getParameter("user_id");
		String user_pw = request.getParameter("user_pw");
		LoginImpl loginUser = new LoginImpl(user_id, user_pw);
		if(session.isNew()) {
			session.setAttribute("loginUser", loginUser);
		}
		out.println("<head>");
		out.println("<script type='text/javascript'>");
		out.println("setTimeout('history.go(0);', 5000)");
		out.println("</script>");
		out.println("</head>");
		out.println("<html><body>");
		out.println("아이디는 " + loginUser.user_id + "<br>");
		out.println("총 접속자수는 " + LoginImpl.total_user + "<br>");
		out.println("</body></html>");
	}

 

LoginImpl.java

public class LoginImpl implements HttpSessionBindingListener {
	String user_id;
	String user_pw;
	static int total_user=0;
	public LoginImpl() {
	}
	
	public LoginImpl(String user_id, String user_pw) {
		this.user_id = user_id;
		this.user_pw = user_pw;
	}
	
	public void valueBound(HttpSessionBindingEvent arg0) {
		System.out.println("사용자 접속");
		++total_user;
	}
	
	public void valueUnbound(HttpSessionBindingEvent arg0) {
		System.out.println("사용자 접속 해제");
		total_user--;
	}
}

 

 

크롬 브라우저 login2.html 실행화면

 

엣지 브라우저 login2.html 실행화면

 

 

 

2) HttpSessionListener 이용해 로그인 접속자수 표시

 

setAttribute( )를 이용해 loginUser를 세션에 바인딩하면 LoginImpl 클래스에 구현된 이벤트 핸들러를 이용해 접속자수를 1 증가시키고, user_list에 접속자 ID를 저장한 다음 ServletContext 객체에 바인딩한다.

 

LoginTest3.java

@WebServlet("/login")
public class LoginTest3 extends HttpServlet {
	ServletContext context=null;
	List user_list=new ArrayList(); // 로그인한 접속자 ID를 저장하는 ArrayList
	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) 
    		throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html; charset=utf-8");
		context=getServletContext();
		PrintWriter out = response.getWriter();
		HttpSession session = request.getSession();
		String user_id = request.getParameter("user_id");
		String user_pw = request.getParameter("user_pw");
		LoginImpl loginUser = new LoginImpl(user_id, user_pw); // LoginImpl 객체 생성 후 전송된 ID와 비밀번호 저장
		// 최초 로그인 시 접속자 ID를 ArrayList에 차례로 저장한 후 다시 context 객체에 속성으로 저장
        if(session.isNew()) {
			session.setAttribute("loginUser", loginUser);
			user_list.add(user_id);
			context.setAttribute("user_list", user_list);
		}
		
		out.println("<html><body>");
		out.println("아이디는 " + loginUser.user_id + "<br>");
		out.println("총 접속자수는 " + LoginImpl.total_user + "<br><br>"); // 세션에 바인딩 이벤트 처리 후 총 접속자수를 표시
		out.println("접속 아이디:<br>");
		List list=(ArrayList)context.getAttribute("user_list"); // context 객체에 ArrayList를 가져와 접속자 ID를 차례로 브라우저에 출력
		for(int i=0; i<list.size(); i++) {
			out.println(list.get(i)+"<br>");
		}
		out.println("<a href='logout?user_id="+user_id+"'>로그아웃 </a>"); // 로그아웃 클릭 시 서블릿 logout으로 접속자 ID를 전송해 로그아웃
		out.println("</body></html>");
	}

}

 

LoginImpl.java

public class LoginImpl implements HttpSessionBindingListener {
	String user_id;
	String user_pw;
	static int total_user=0;
	public LoginImpl() {
	}
	
	public LoginImpl(String user_id, String user_pw) {
		this.user_id = user_id;
		this.user_pw = user_pw;
	}
	
	public void valueBound(HttpSessionBindingEvent arg0) {
		System.out.println("사용자 접속");
		++total_user;
	}
	
	public void valueUnbound(HttpSessionBindingEvent arg0) {
		System.out.println("사용자 접속 해제");
		total_user--;
	}
}

 

 

로그아웃 링크를 클릭하면 접속자 수를 1 감소시키고 user_list에서 로그아웃한 접속자 ID를 삭제한 후 다시 user_list를 ServletContext 객체에 바인딩하도록 설정한다.

 

LogoutTest.java

	private void doHandle(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html; charset=utf-8");
		context=getServletContext();
		PrintWriter out = response.getWriter();
		HttpSession session = request.getSession();
		String user_id = request.getParameter("user_id"); // user_list에서 삭제할 ID를 가져옴
		session.invalidate(); // 로그아웃 시 세션을 소멸 시킴
        	// user_list에서 로그아웃한 접속자 ID를 삭제한 후 다시 user_list를 컨텍스트에 저장함
		List user_list = (ArrayList)context.getAttribute("user_id");
		user_list.remove(user_id);
		context.removeAttribute("user_list");
		context.setAttribute("user_list", user_list);
		out.println("<br>로그아웃 했습니다.");
	}

 

LoginImpl 클래스는 HttpSessionListener를 구현해 세션 생성과 소멸 시 이벤트를 처리하는 핸들러이다.

중요한 것은 앞의 LoginImpl에서 구현한 HttpSessionBindingListener와는 다르게 HttpSessionListener는 반드시 리스너를 구현한 이벤트 핸들러를 애너테이션을 이용해서 등록해야 한다는 것이다. 

 

1. 패키지를 선택하고 마우스 오른쪽 버튼을 클릭한 후 New>Listner를 선택

 

2. Class name으로 LoginImpl 입력 후 Next 클릭

 

 

3. HTTP session events의 Lifecycle javax.servlet.http.HttpSessionListener 체크 후 Next 클릭

 

4. Finish 클릭 하고 @WebListener 애너테이션으로 리스너가 등록된 것을 확인

 

리스너를 등록한 이벤트 핸들러를 이용해 세션을 생성할 때는 sessionCreated( ) 메서드로 이벤트를 처리하고, 세션을 삭제할 때는 sessionDestroyed( ) 메서드로 이벤트를 처리한다.

 

LoginImpl.java

//HttpSessionBindingListener를 제외한 Listener를 구현한 모든 이벤트 핸들러는 반드시 애너테이션을 이용해 Listener로 등록해야 한다
@WebListener 
public class LoginImpl implements HttpSessionListener {
	String user_id;
	String user_pw;
	static int total_user=0;

    public LoginImpl() {
    }

    @Override
    // 세션 생성 시 이벤트를 처리함
    public void sessionCreated(HttpSessionEvent se)  { 
    	System.out.println("세션 생성");
    	++total_user;
    }

    @Override
    // 세션 소멸 시 이벤트를 처리함
    public void sessionDestroyed(HttpSessionEvent se)  { 
    	System.out.println("세션 소멸");
    	--total_user;
    }
	
}

 

 


참고 :  ⌜자바 웹을 다루는 기술⌟ 책을 공부하며 요약・정리한 내용입니다.

 

 

728x90