[필기정리] Day107-1 - filter class, listener class, ContextParam 등

Web/JSP

2020. 11. 24. 12:31

# 필터 클래스(filter class)

웹 프로그램에서 하나의 페이지에서 다른 페이지로 전달되는 데이터가 필터를 지나며 가공되거나 걸러지게 된다.

이런 필터 기능을 구현할 때 사용하는 클래스가 필터 클래스이다.

필터는 데이터를 가로채서 처리를 한다고 생각하면 된다. 

하나의 작업에서 다른 작업으로 넘어갈 때나 어떤 작업이 또 다른 작업으로 넘어갈 때

데이터를 가로채서 처리를 할 수 있다. 

 

요청이나 세션에 담긴 데이터뿐 아니라 헤더에도 필터가 적용될 수 있다. 

기존 작업이 일어나기 직전(전처리)이나 일어난 직후(후처리) 모두 필터가 적용되는 시점이다. 

필터가 웹 프로그램에서 사용되는 경우는 다음과 같다.

 

전달받은 데이터를 인코딩하는 경우

② 세션 데이터를 인증하는 경우

③ 이벤트나 공지 등 팝업을 추가하는 경우

 

웹 관련 클래스가 모두 그러하듯이 필터 클래스의 메서드도 요청 객체와 응답 객체를 매개 변수로 가진다.

여기에 추가적으로 FilterChain 객체를 매개 변수로 갖는데, 필터 기능 자체가 페이지의 분기점에 있기 때문이다. 

따라서 FilterChain 객체는 필터 기능이 완료되고 다음 페이지로 연결하는 기능에 사용된다. 

 

먼저, 서블릿의 일반 클래스처럼 web.xml 파일에 등록해야 한다.

당연하겠지만 일반 클래스가 아니므로 <servlet>태그가 아니라 <filter> 태그를 사용한다.

필터 관련 클래스로는 javax.servlet.Filter, javax.servlet.FilterConfig, javax.servlet.FilterChain 등이 있다.

필터 클래스가 일반 서블릿 클래스와 다른 점은 Filter라는 인터페이스를 상속받는다는 것과

서블릿의 service() doGet(), doPost() 대신에 doFilter() 메소드를 사용한다는 것이다. 

 

두 번째로, 매개 변수에는 Http 계열은 사용할 수 없고 코드에서처럼 HTTP를 지원하는 형으로 변환을 사용해야만 한다. 

 

마지막으로 세 번째 매개 변수인 FilterChain 클래스의 객체인 chain을 이용해서

다른 필터나 서블릿과 연결하는 코드를 반드시 작성해야 한다.

<filter>태그는 <servlet>태그보다 앞에 놓여야 한다. // 톰캣 이외의 프로그램에서 오류 발생 가능성이 있기 때문

 

이렇게 하나의 페이지에서 다른 페이지로 연결되는 사이에 데이터를 가로채서

특정 기능을 수행하는 클래스가 필터 클래스이다.

필터 클래스를 사용하여 페이지를 분기하는 작업이 가능하다.

 

ex)

- test.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="coderbear">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>coderbear</title>
</head>
<body>
이름 : ${param.name} <br>
전화번호 : ${param.tel} <br>
주소 : ${param.addr} <br>
</body>
</html>

- TestForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="coderbear">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>coderbear</title>
</head>
<body>
 		<form name='data_form' method='post' action='test.jsp'>
			이름 : <input type='text' name='name'/><br/>
			전화번호 : <input type='text' name='tel'/><br/>
			주소 : <input type='text' name='addr'/><br/>
			<input type='submit' value='전송'/>
		</form>
</body>
</html>

- web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
  <display-name>FilterClassTest1</display-name>
  
    <filter>
		<filter-name>MyCharacterFilter</filter-name>
		<filter-class>com.tistory.coderbear.filter.MyCharacterFilter</filter-class>
	</filter>
	<filter-mapping>
	<filter-name>MyCharacterFilter</filter-name>
		<!--	<url-pattern>/TestServlet</url-pattern> -->
	 	<url-pattern>/*</url-pattern> 
	</filter-mapping>
  
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

- MyCharacterMyCharacterFilter.java

package com.tistory.coderbear.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

public class MyCharacterFilter implements Filter { // 필터는 Filter 인터페이스를 구현해야 한다.

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest h_request = (HttpServletRequest)request;
		String method = h_request.getMethod();
		if(method.equalsIgnoreCase("POST")) {		// POST 방식의 요청인지 확인하고서 요청 객체로 넘어오는 데이터에 한글 인코딩을 설정한다.
			request.setCharacterEncoding("UTF-8");
		}
		chain.doFilter(request, response);
	}

}

 

필터 메서드 내용 부의 마지막 코드는 현재까지 작업한 내용을 적용하고 연결된 페이지로 이동하도록 만들어 준다.
이런 역할을 하는 메서드가 chain 객체의 doFilter()이다.
 

ex)

- TestForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="coderbear">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
 		<form name='data_form' method='post' action='FilterTestServlet'> // 서블릿 사용!
			이름 : <input type='text' name='name'/><br/>
			전화번호 : <input type='text' name='tel'/><br/>
			주소 : <input type='text' name='addr'/><br/>
			<input type='submit' value='전송'/>
		</form>
</body>
</html>

- web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
  <display-name>FilterClassTest2</display-name>
  
    <filter>
		<filter-name>MyCharacterFilter</filter-name>
		<filter-class>com.tistory.coderbear.filter.MyCharacterFilter</filter-class>
	</filter>
	<filter-mapping>
	<filter-name>MyCharacterFilter</filter-name>
		<!--	<url-pattern>/TestServlet</url-pattern> -->
	 	<url-pattern>/*</url-pattern> 
	</filter-mapping>
  
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

- FilterTestServlet.java

package com.tistory.coderbear;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/FilterTestServlet")
public class FilterTestServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public FilterTestServlet() {
        super();
    }

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String name = request.getParameter("name");
		String tel = request.getParameter("tel");
		String addr = request.getParameter("addr");
		
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		out.println("<html><head>");
		out.println("<style type='text/css'>");
		out.println(".n_border { border:none }");
		out.println("</style></head><body>");
		out.println("전송된 이름 = ");
		out.println("<input type='text' class='n_border' value='" + name + "'/><br/>");
		out.println("전송된 전번 = ");
		out.println("<input type='text' class='n_border' value='" + tel + "'/><br/>");
		out.println("전송된 주소 = ");
		out.println("<input type='text' class='n_border' value='" + addr + "'/><br/>");
		out.println("</body></html>");
	}
}

- MyCharacterMyCharacterFilter.java (filter 폴더 내)

package com.tistory.coderbear.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

public class MyCharacterFilter implements Filter { // 필터는 Filter 인터페이스를 구현해야 한다.

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest h_request = (HttpServletRequest)request;
		String method = h_request.getMethod();
		if(method.equalsIgnoreCase("POST")) {		// POST 방식의 요청인지 확인하고서 요청 객체로 넘어오는 데이터에 한글 인코딩을 설정한다.
			request.setCharacterEncoding("UTF-8");
		}
		chain.doFilter(request, response);
		/*
		 * 필터 메서드 내용부의 마지막 코드는 현재까지 작업한 내용을 적용하고 연결된 페이지로 이동하도록 만들어 준다.
		 * 이런 역할을 하는 메서드가 chain 객체의 doFilter() 메서드이다.
		 */
	}

}

 

ex) 세션이 없을 때 접근하지 못하도록 하는 예시

- filterTest.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="session.jsp">세션 설정</a><br/>
<a href="sessionRemove.jsp">세션 지우기</a><br/>
<a href="test/page1.jsp">페이지1</a><br/>
<a href="test/page2.jsp">페이지2</a><br/>
<a href="page3.jsp">페이지3</a>
</body>
</html>

- page1.jsp (test 폴더 내)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
page1
</body>
</html>

- page2.jsp (test 폴더 내)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
page2
</body>
</html>

- session.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
	session.setAttribute("id", "cool");
	response.sendRedirect("filterTest.jsp");
%>
</body>
</html>

- sessionRemove.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
	session.invalidate();
	response.sendRedirect("filterTest.jsp");
%>
</body>
</html>

- error.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
Session Error가 발생했습니다
</body>
</html>

- MySessionFilter.java

package com.tistory.coderbear;
import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class MySessionFilter implements Filter {

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest hRequest = (HttpServletRequest)request;
		HttpSession hSession = hRequest.getSession();
		String id = (String)hSession.getAttribute("id");
		
		if(id == null || id.trim().length() == 0) { // trim = 공백제거			
			HttpServletResponse h_response = (HttpServletResponse)response;
			h_response.sendRedirect("../error.htm"); // 세션이 없을 때 error 페이지로 이동			
		}
		chain.doFilter(request, response);
	}
}

 

# Listener Class(리스너 클래스) : 특정한 행위를 해주고 싶을 때 사용

ex)

- web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>ListenerClass</display-name>
   	<listener>
		<display-name>Context Listener</display-name>
		<listener-class>com.tistory.coderbear.listener.Listener1</listener-class>
	</listener>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

- Listener1.java (listener 폴더 내)

package com.tistory.coderbear.listener;

import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class Listener1 implements ServletContextAttributeListener, ServletContextListener {
	
	// 톰캣이 구동될 때 실행된다.
	public void contextInitialized(ServletContextEvent e) {
		System.out.println("ServletContext 가 초기화 되었습니다.");
		System.out.println("init context = " + e.getServletContext());
	}
	
	// 톰캣이 종료될 때 실행된다.
	public void contextDestroyed(ServletContextEvent e) {		
		System.out.println("ServletContext 가 소멸 되었습니다.");
		System.out.println("dest context = " + e.getServletContext());
	}
	
	// ServletContext 객체에 속성이 새로 추가될 때 실행된다. 
	public void attributeAdded(ServletContextAttributeEvent e) { // 해당 내용 실행됨
		System.out.println("Context 영역에 값이 추가 되었습니다.");
		System.out.println("added = " + e.getName() + " : " + e.getValue());
	}

	// ServletContext 객체의 속성이 삭제될 때 실행 된다.
	public void attributeRemoved(ServletContextAttributeEvent e) {
		System.out.println("Context 영역에 값이 삭제 되었습니다.");
		System.out.println("removed = " + e.getName() + " : " + e.getValue());
	}

	// ServletContext 객체의 속성이 수정될 때 수정 직전에 실행된다.
	public void attributeReplaced(ServletContextAttributeEvent e) {
		System.out.println("Context 영역에 값이 변경 되었습니다.");
		System.out.println("replaced = " + e.getName() + " : " + e.getValue());		
	}
}

- ServletListener1.java

package com.tistory.coderbear;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/ServletListener1")
public class ServletListener1 extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public ServletListener1() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=euc-kr");
		PrintWriter out = response.getWriter();
		out.println("<html><body><center>");
		out.println("<form method='post'>");
		out.println("<input type='submit' value='Context 값 할당 하기'/>");
		out.println("</form></center></body></html>");
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ServletContext context = this.getServletContext();
		context.setAttribute("my_name", "홍길동");
		context.setAttribute("my_name", "길동");
		context.removeAttribute("my_name");
		
		response.setContentType("text/html;charset=euc-kr");
		PrintWriter out = response.getWriter();
		out.println("<html><body><center>");
		out.println("Context 값 추가, 삭제, 변경 성공!");
		out.println("</center></body></html>");
	}
}

 

 

ex)

- web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>ListenerClass2</display-name>
  	<listener>
		<display-name>Session And Request Listener</display-name>
		<listener-class>com.tistory.coderbear.listener.Listener2</listener-class>
	</listener>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 

- Listener2.java (listener 폴더 내)

package com.tistory.coderbear.listener;

import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class Listener2 implements ServletRequestListener, ServletRequestAttributeListener,
HttpSessionListener, HttpSessionAttributeListener
{
	// ServletRequest 객체가 초기화 될 때 발생한다.
	public void requestInitialized(ServletRequestEvent e) {
		System.out.println("ServletRequest 객체가 초기화 되었습니다.");
		System.out.println("request = " + e.getServletRequest());
	}
	// ServletRequest 객체가 소멸 될 때 발생한다.
	public void requestDestroyed(ServletRequestEvent e) {		
		System.out.println("ServletRequest 객체가 소멸 되었습니다.");
		System.out.println("request = " + e.getServletRequest());
	}	
	// ServletRequest 영역에 속성이 새로 추가될 때 발생한다.
	public void attributeAdded(ServletRequestAttributeEvent e) {
		System.out.println("ServletRequest 영역에 속성이 새로 추가되었습니다.");
		System.out.println("added = " + e.getName() + " : " + e.getValue());
	}
	// ServletRequest 영역의 속성이 삭제 될 때 발생한다.
	public void attributeRemoved(ServletRequestAttributeEvent e) {
		System.out.println("ServletRequest 영역의 속성이 삭제되었습니다.");
		System.out.println("removed = " + e.getName() + " : " + e.getValue());
	}
	// ServletRequest 영역의 속성 값이 변경될 때 발생한다.
	public void attributeReplaced(ServletRequestAttributeEvent e) {
		System.out.println("ServletRequest 영역에 속성의 값이 변경되었습니다.");
		System.out.println("replaced = " + e.getName() + " : " + e.getValue());
	}
	// HttpSession 객체가 생성될 때 발생한다.
	public void sessionCreated(HttpSessionEvent e) {
		System.out.println("HttpSession 객체가 생성 되었습니다.");
		System.out.println("session = " + e.getSession());
	}
	// HttpSession 객체가 소멸될 때 발생한다.
	public void sessionDestroyed(HttpSessionEvent e) {
		System.out.println("HttpSession 객체가 소멸 되었습니다.");
		System.out.println("session = " + e.getSession());
	}
	// HttpSession에 새로 속성이 추가될 때 발생한다.
	public void attributeAdded(HttpSessionBindingEvent e) {
		System.out.println("HttpSession 영역에 속성이 새로 추가되었습니다.");
		System.out.println("added = " + e.getName() + " : " + e.getValue());
	}
	// HttpSession 영역의 속성이 삭제 될 때 발생한다.
	public void attributeRemoved(HttpSessionBindingEvent e) {
		System.out.println("HttpSession 영역의 속성이 삭제되었습니다.");
		System.out.println("removed = " + e.getName() + " : " + e.getValue());
	}
	// HttpSession 영역의 속성 값이 변경될 때 발생한다.
	public void attributeReplaced(HttpSessionBindingEvent e) {
		System.out.println("HttpSession 영역의 속성 값이 변경되었습니다.");
		System.out.println("replaced = " + e.getName() + " : " + e.getValue());
	}
}

- ServletListener2.java

package com.tistory.coderbear;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@WebServlet("/ServletListener2")
public class ServletListener2 extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=euc-kr");
		PrintWriter out = response.getWriter();
		out.println("<html><body><center>");
		out.println("<form method='post'>");
		out.println("<input type='submit' value='Session 및 Request 속성 처리 하기'/>");
		out.println("</form></center></body></html>");
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		request.setAttribute("my_name", "홍길동"); 	// request 속성 새로 추가
		request.setAttribute("my_name", "길동"); 		// request 속성 값 변경
		request.removeAttribute("my_name"); 		// request 속성 삭제
		
		HttpSession session = request.getSession(true); // session 객체 생성
		session.setAttribute("my_name", "홍길동"); 		// session 속성 새로 추가
		session.setAttribute("my_name", "길동"); 			// session 속성 값 변경
		session.removeAttribute("my_name"); 			// session 속성 삭제		
		
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		out.println("<html><body><center>");
		out.println("Session 및 Request 속성 추가, 삭제, 변경 성공!");
		out.println("</center></body></html>");
	}
}

 

# ContextParam : 모든 서블릿이 ContextParam의 내용을 공유

ex)

- web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>ContextParamTest</display-name>
  <context-param>
    <param-name>companyName</param-name>
    <param-value>좋은회사</param-value>
  </context-param>
  <context-param>
    <param-name>companyTel</param-name>
    <param-value>012-3456-7890</param-value>
  </context-param>
  <context-param>
    <param-name>companyEmail</param-name>
    <param-value>goodCompany@good.com</param-value>
  </context-param>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

- ContextParamTest.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="coderbear">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
<%
	String companyName = application.getInitParameter("companyName");
%>
<%= companyName %> // 결과 : 좋은회사
</body>
</html>

- ContextParamTest2.java

package com.tistory.coderbear;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/ContextParamTest2")
public class ContextParamTest2 extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public ContextParamTest2() {
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setCharacterEncoding("UTF-8");
		ServletContext context = getServletContext();
		String companyName = context.getInitParameter("companyName");
		String companyTel = context.getInitParameter("companyTel");
		String companyEmail = context.getInitParameter("companyEmail");
		
		PrintWriter out = response.getWriter();
		out.println("<!DOCTYPE html>");
		out.println("<html>");
		out.println("<head>");
		out.println("<meta charset='UTF-8'>");
		out.println("</head>");
		out.println("<body>");
		out.println("<h2>" + companyName + "</h2>");
		out.println("<h2>" + companyTel + "</h2>");
		out.println("<h2>" + companyEmail + "</h2>");
		out.println("</body>");
		out.println("</html>");
	}

}

 

서블릿은 웹에서 실행되는 프로그램이기 때문에 네트워크 통신의 사이사이에서 특별한 동작을 만들어 낼 수 있다.

홈페이지에 접속하기 직전에 이벤트 창을 띄운다든지

데이터 입력 후 실제 저장하는 페이지로 넘어가기 전에 넘겨지는 데이터들에 대하여

한글 처리를 한다든지 등의 작업을 할 수 있다.

 

또한, 세션이 만들어지거나 삭제될 때 이를 감지하는 작업도 할 수 있다.

이렇게 여러 가지 동작에 있어서 사이사이에 끼워져서 실행되는 서블릿의 클래스를

필터(Filter)라 부르고 동작이 발생할 때 감지하는 것을 이벤트(Event)라 부른다.

 

// 서블릿 이벤트

이벤트가 웹 프로그램에서 사용되는 경우는 다음과 같다.

컨텍스트가 초기화되는 경우

세션이 생기거나 소멸되는 경우

속성이 바뀌는 경우

 

이런 이벤트에 대해서 미리 web.xml 파일에 등록해 두면

웹 서버는 자동으로 이벤트를 감지하고 우리가 지정한 클래스 내의 메서드를 실행해 준다.

이벤트는 외부의 변화보다는 내부의 변화를 처리하는 경우가 많다.

 

서블릿에서 이벤트 클래스가 실행되게 하려면 무엇보다 web.xml 파일의 설정이 중요하다.

초기에 웹 서버가 구동하면서 해당 이벤트를 대기 상태로 두기 때문이다.

 

web.xml 파일에서 사용하는 태그로는 <listener> <context-param>이 있다.

<listener> 태그는 서블릿의 이벤트를 대기 상태로 두고

<context-param> 태그는 초기화 매개 변수가 된다.

<filter>태그보다 앞에 <content-param>태그를 적는다.

ServletContext 객체를 가지고 web.xml 파일에 등록된 초기화 매개 변수들을 가져와서 사용할 수 있다.

 

ServletContext 객체의 변화에 대해 반응하는 메서드들은

ServletContextListener ServletContextAttributeListener 인터페이스에 정의되어 있기 때문에 이를 구현해주어야 한다.

 

web.xml 파일에 이벤트 클래스를 등록하자.

이 때 <listener>태그를 <context-param>태그보다 앞에 적는다.

 

web.xml 파일 작성 방법

01 : <web-app>
02 :                  <display-name>프로젝트명</display-name>
03 :     
04 :                  <filter>

05 :                             <filter-name>필터 닉네임</filter-name>
06 :                             <filter-class>필터 클래스 풀네임(패키지 명까지)</filter-class>

07 :                             <init-param>

08 :                                        <param-name>매개변수명</param-name>

09 :                                        <param-value></param-value>

10 :                             </init-param>

11 :                  </filter>

12 :                  <filter-mapping>

13 :                             <filter-name>필터 닉네임</filter-name>

14 :                             <url-pattern>필터 클래스가 실행 될 위치</url-pattern>

15 :                  </filter-mapping>

16 :     

17 :                  <servlet>

18 :                             <servlet-name>서블릿 닉네임</servlet-name>

19 :                             <servlet-class>서블릿 클래스 풀네임(패키지 명까지)</servlet-class>

20 :                             <init-param>

21 :                                        <param-name>매개변수명</param-name>

22 :                                        <param-value></param-value>

23 :                            </init-param>

24 :                             <load-on-startup>실행 순서 값(0값은 서버임의실행)</load-on-startup>

25 :                  </servlet>

26 :                  <servlet-mapping>

27 :                             <servlet-name>서블릿 닉네임</servlet-name>

28 :                             <url-pattern>/url패턴</url-pattern>

29 :                  </servlet-mapping>

30 :     

31 :                  <welcome-file-list>

32 :                             <welcome-file>기본 연결파일</welcome-file>

33 :                  </welcome-file-list>

34 :      <web-app>

line2 : <display-name>프로젝트명</display-name>  
         web.xml 파일이 속한 프로젝트의 이름을 적는다.

line4-11 : 프로젝트에서 사용할 필터 클래스를 등록한다.

line5<filter-name>필터 닉네임</filter-name>

          필터 클래스의 닉네임을 적는다. (임의로 정해도 됨)


line6 : <filter-class>
필터 클래스 풀네임(패키지 명까지)</filter-class>

         해당 필터 클래스에 대해 패키지의 이름까지 전체를 등록한다.
         패키지가 아니면 클래스 이름만 등록한다.


line7-10 :
해당 필터 클래스가 실행되면서 기본적으로 갖는 초기화 매개 변수를 적는다.(여러 개 등록해도 됨)

           void main(String[] args) 메서드의 args[0] args[1] 등과 같은 개념이라고 보면 된다.
           void main() 
메서드에서는 args 이라는 이름으로 사용하지만 여기서는 변수의 이름과 값을 모두 등록해야 한다.

 

line12-15 : 해당 필터 클래스가 실행되는 시점을 등록한다.

 

line13 : <filter-name>필터 닉네임</filter-name>

          실행될 필터 클래스의 닉네임을 적는다.
          5
행에서 적은 이름과 대소문자까지 같아야 한다.

 

line14 : <url-pattern>필터 클래스가 실행 될 위치</url-pattern>

           실행될 시점을 지정한다.

 

line17-25 : 서블릿 등록 (여러 개 등록해도 됨)

 

line18 : <servlet-name>서블릿 닉네임(패키지 명까지)</servlet-name>

           서블릿의 닉네임을 등록하고 있다.
           닉네임은 클래스의 이름이 너무 길 때 편의상 사용한다. 
           클래스 이름이 짧으면 클래스 이름과 동일하게 등록해도 무방하다.

 

line19 : <servlet-class>서블릿 클래스 풀네임</servlet-class>

           서블릿 클래스의 전체 이름을 등록하고 있다.
           패키지면 패키지의 이름까지 모두 적어야 한다.

line20-23 : 필터 클래스처럼 서블릿이 실행될 때 초깃값으로 전달될 매개 변수를 적고 있다.
              여러 개를 등록해도 무방하다.


line24 : <load-on-startup>
실행 순서 값(0값은 서버임의 실행)</load-on-startup>

           웹 서버가 구동될 때 서블릿의 Init() 메서드를 미리 실행할지 지정하고 있다.

line31-33 : 클라이언트의 사용자가 웹 브라우저로 웹 서버에 접속할 때
               기본적으로 보여주는 메인 페이지를 등록하고 있다.

 

web.xml 파일은 웹 컨테이너와 웹 프로그램의 파일을 서로 연결하고 관리하는 설정 파일이다.

 

서블릿은 최초 요청이 들어올때 초기화 된다.

클래스 로딩 인스턴스화 초기화설정을 해야하는데

이렇게 되면 서버가 올라가고 맨 처음 호출한 유저는 보통 시간보다 시간이 오래걸린다.

그것을 방지하기 위해 load-on-startup이라는 것이 있다.

(서블릿 최초 실행 시 init 메소드가 실행되는데,

 두 번째에 서비스 메소드 실행된다.

 아파치 서버가 실행이 될 때 init 메소드가 바로 빠르게 실행되도록 해주는 것)

 

24행에서 값을 0으로 지정하면 웹 서버가 임의로 init() 메서드를 실행하고,

0 이외의 정수를 값으로 지정하면 웹 서버가 구동될 때

이 순서대로 해당 서블릿의 init() 메소드가 차례대로 실행된다.

 

예를 들어 A, B, C라는 서블릿이 있을 때 B Init() 메서드를 먼저 실행하고 다음으로 A,

마지막으로 C 서블릿의 init() 메서드를 실행해야 한다면 B서블릿을 등록할 때 load-on-startup 값을 1로 하고,

A 서블릿의 load-on-startup 2, C 서블릿의 load-on-startup 값을 3으로 하면

웹 서버가 구동될 때 해당 순서대로 init() 메서드를 실행하게 된다는 의미이다.

 

메인 페이지 등록과 관련해서 추가적으로 설명하면

Daum 사이트에 접속할 때 http://www.daum.net/index.html 이라고 적어야 정상적으로 메인 페이지를 볼 수 있다.

그러나 우리는 대게 http://www.daum.net 이라고만 적는다.

당연하게도 이렇게 적어도 정상적으로 보여진다.

 

이유는 바로 앞서 welcome 파일을 등록했기 때문이다.

해당 프로젝트의 이름까지만 적을 때 실행될 파일을 welcome 파일로 지정할 수 있다.

 

<welcome-file-list>
           <welcome-file>Servelt01</welcome-file>
</welcome-file-list>

이와 같은 경우 http://localhost:8080/Round12 라고만 적어도

http://localhost:8080/Round12/Servlet01이라고 적은 것과 동일한 효과를 보인다.

 

그런데 Servlet01파일이 없으면 어떻게 될까?

이럴 때를 대비해서 welcome 파일을 여러 개 등록할 수 있다.

적은 순서대로 찾은 파일을 실행한다.

<welcome-file-list>
           <welcome-file>index.html</welcome-file>
           <welcome-file>Servlet01</welcome-file>
           <welcome-file>home.jsp</welecome-file>
</welcome-file-list>

이와 같이 되어 있으면 첫 번째 index.html 파일이 없기 때문에 건너뛰고

두 번째 Servlet01파일은 있기 때문에 실행된다.

마지막 home.jsp 파일은 찾아보지도 않는다.

 

더 자세한 내용은 http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd

 

// Tip : 필터 클래스는 여러 개를 등록할 수 있다.

          이 때 필터 태그를 사용하면서 필터 맵핑 태그와 중첩되면 안된다.

<filter>...</filter>
<filter-mapping>...<filter-mapping>
<filter>...</filter>
<filter-mapping>...</filter-mapping>

이와 같이 중첩해서 사용하면 정상적으로 인식되지 않는다.

필터 클래스 여러 개를 등록할 때는 다음과 같이 동일한 태그를 연속해서 작성하기 바란다.

<filter>...</filter>
<filter>...</filter>
<filter-mapping>...</filter-mapping>
<filter-mapping>...</filter-mapping>

이 원칙은 서블릿 태그와 서블릿 매핑 태그에서도 동일하게 적용된다.

 

Q.

1. 텍스트 박스에 이름, 전화번호, 주소를 입력받고 이것을 Servlet01로 전송하도록 하자.

   필터클래스를 통해 Servlet01로 넘어가는 것들을 한글로 인코딩을 하자.

 

2. 필터 클래스를 이용하여 아이디가 없이 접근했을 때는 에러 페이지로 가도록 하고

   아이디가 있을 때는 "아이디님 환영합니다."라고 출력하도록 하자.

 

3. <context-param> 태그를 가지고 초기화 매개 변수를 설정하고 사용해 보자.

   웹 서버가 구동하면서 web.xml 파일에서 회사 이름과 전화번호, 관리자 이메일 등을 가져오는 서블릿을

   src 폴더에 ConTextParamServletTest.java 파일로 만들자.

 

4. ServletContext 객체와 관련된 이벤트를 처리해 보도록 하자.

   서블릿 이벤트 클래스를 src 폴더에 ServletListenerTest1.java 파일로 만들고서 다음과 같이 코드를 작성하자.               ServletContext 객체의 변화에 반응하는 메서드들은

   ServletContextListener ServletContextAttributeListener 인터페이스에 정의되어 있기 때문에

   이를 구현해 주어야 한다.

   그리고 이벤트가 발생했을 때 각각 다음과 같이 출력해 주도록 한다.

   그리고 그 이벤트를 발생시키게끔 적절한 서블릿을 구현하도록 하자.

"ServletContext가 초기화 되었습니다."
"ServletContext가 소멸 되었습니다."
"Context 영역에 값이 추가 되었습니다."
"Context 영역에 값이 삭제 되었습니다."
"Context 영역에 값이 변경 되었습니다."

 

5. 세션과 요청에 대한 이벤트를 관리할 서블릿을 src 폴더에 ServletListenerTest2.java파일로 만들자.

   세션과 요청 객체의 변화에 대해 반응하는 메서드들은 각각 HttpSessionListener,

   HttpSessionAttributeListener, ServletRequestListener, ServletRequestAttributeListener

   인터페이스에 정의되어 있기 때문에 이를 구현해야 한다.

   그리고 이벤트가 발생했을 때 각각 다음과 같이 출력해 주도록 한다.

   그리고 그 이벤트를 발생시키게끔 적절한 서블릿을 구현하도록 하자.

"ServletRequest 객체가 초기화 되었습니다."
"ServletRequest 객체가 소멸 되었습니다."
"ServletRequest 영역에 속성이 새로 추가되었습니다."
"ServletRequest 영역의 속성이 삭제되었습니다."
"ServletRequest 영역에 속성의 값이 변경되었습니다."
"HttpSession 객체가 생성 되었습니다."
"HttpSession 객체가 소멸 되었습니다."
"HttpSession 영역에 속성이 새로 추가되었습니다."
"HttpSession 영역의 속성이 삭제되었습니다."
"HttpSession 영역의 속성 값이 변경되었습니다."

 

728x90