티스토리 뷰
1. ServletContextListener
- Servlet이 Life Cycle을 가지고 있는 것처럼, 웹 어플리케이션도 Life Cycle을 가진다.
- 이때 ServletContextListener을 통해, 언제 웹 어플리케이션이 초기화되고 제거되었는지를 알 수 있다.
2. Filter
- 서블릿이 요청 받기 전과 결과를 웹 브라우저에게 응답을 하기 전에 특정 작업을 수행할 수 있도록 Filter을 사용할 수 있다.
- 즉, 웹 컴포넌트가 실행되기 전의 선처리(요청 필터) 작업과 응답되기 전의 후처리(응답 필터) 작업을 수행하는 API다.
- Filter는 체인처럼 묶어서 적용시킬 수 있다.
- Filter도 service처럼 요청필터와 응답필터를 가진다.
- Request 요청이 요청 필터를 걸쳐서 서블릿으로 전송된다. 이때, 서블릿이 처리하기 전에 실행되어야 하는 선처리 작업을 수행할 수 있다.
- Response 응답은 응답 필터를 걸쳐서 전송된다. 요청과 마찬가지로 웹 브라우저로 응답되기 전에 실행되어야 하는 후처리 작업을 할 수 있다.
- 필터도 리스너와 같이 인터페이스이다.
- 필터도 URL Mapping을 해야 한다.
[ 1. webapp 폴더 밑의 파일을 ServletContext 객체로 읽어 내기 ] (***)
package org.zerock.myapp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
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;
import lombok.Cleanup;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
@Log4j2
@NoArgsConstructor
@WebServlet("/ContextFile")
public class ContextFileServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
log.trace("service(req, res) invoked.");
// =============================================
req.setCharacterEncoding("UTF-8");
// webapp파일 밑에 있는 텍스트 파일 읽기
String readFile = "/WEB-INF/testFile.txt"; // 텍스트 파일의 위치 지정
ServletContext sc = this.getServletContext();
@Cleanup
InputStream is = sc.getResourceAsStream(readFile);
@Cleanup
BufferedReader br = new BufferedReader(new InputStreamReader(is)); // 버퍼 + 바이트기반을 문자기반으로
// =============================================
res.setContentType("text/html; charset=utf8");
@Cleanup
PrintWriter out = res.getWriter();
out.println("<html>");
out.println("<head></head>");
out.println("<body>");
out.println("<p>");
// =============================================
String line = null;
while ( ( line = br.readLine() ) != null ) {
out.println(line);
} // while : line의 값을 br.readline에서 가져오기 때문에 빈문장이 들어오기 전까지 무한반복을 실행한다.
// =============================================
out.println("</p>");
out.println("</body>");
out.println("</html>");
out.flush();
} // service
} // end class
[ 2. 공유 데이터 주고 받기 ] (******)
[ 2 - 1. 공유데이터 올리기 ]
package org.zerock.myapp;
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;
import lombok.Cleanup;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
@Log4j2
@NoArgsConstructor
@WebServlet("/ContextSet")
public class ContextSetServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
log.trace("service(req, res) invoked.");
// =============================================
ServletContext sc = this.getServletContext();
// sc.setAttribute("속성 name", 속성값);
sc.setAttribute("name", "HongGilDong");
sc.setAttribute("age", 29); // Auto-Boxing : int -> Integer
// =============================================
res.setContentType("text/html; charset=utf8");
@Cleanup
PrintWriter out = res.getWriter();
out.println("<h1> Setting a new shared attributes into application scope success : Application Scope에 새로운 속성 추가 성공 </h1>");
out.flush();
// =============================================
} // service
} // end class
[ 2 - 2. 공유데이터 가지고 오기 및 삭제 ]
package org.zerock.myapp;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
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;
import lombok.Cleanup;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
@Log4j2
@NoArgsConstructor
@WebServlet("/ContextGet")
public class ContextGetServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
log.trace("service(req, res) invoked.");
// =============================================
ServletContext sc = this.getServletContext();
ServletConfig config = this.getServletConfig();
log.info("\t + sc : {}, config : {}", sc, config);
// =============================================
// ServletClass의 FQCN이 나온다. ( 클래스의 이름이 출력 -> 사용X )
String servletName = this.getServletName();
String servletInfo = this.getServletInfo();
// Application Scope에 공유된 2개의 속성값을 획득 (*****)
String name = (String) sc.getAttribute("name");
int age = (int) sc.getAttribute("age");
// =============================================
// Application Scope에 공유된 2개의 속성값을 삭제 (*****)
sc.removeAttribute("name");
sc.removeAttribute("age");
// =============================================
res.setContentType("text/html; charset=utf8");
@Cleanup
PrintWriter out = res.getWriter();
out.println("<h3> servletName : " + servletName + "</h3>");
out.println("<h3> servletInfo : " + servletInfo + "</h3>");
out.println("<h3> name : " + name + "</h3>");
out.println("<h3> age : " + age + "</h3>");
out.flush();
} // service
} // end class
[ 3. 라이프사이클 리스너 생성 ]
package org.zerock.myapp.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
@Log4j2
//@NoArgsConstructor
@WebListener
public class ContextListenerImpl implements ServletContextListener {
// =========================================================
public ContextListenerImpl () {
log.trace("Default Constructor invoked.");
} // ContextListenerImpl
// =========================================================
@Override
public void contextDestroyed(ServletContextEvent sce) {
log.trace("contextDestroyed({}) invoked.", sce);
} // contextDestroyed ( sce ) : WAS가 내려가기 직전에 수행
// =========================================================
@Override
public void contextInitialized(ServletContextEvent sce) {
log.trace("contextInitialized({}) invoked.", sce);
} // contextInitialized ( sce ) : 서비스하기 직전에 수행
// =========================================================
} // end class
[ 4. @webListener이 아닌, 수동으로 web.xml 파일에 리스너 등록하는 방법 ]
<listener>
<listener-class>org.zerock.myapp.listener.ContextListenerImpl</listener-class>
</listener>
package org.zerock.myapp.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
@Log4j2
//@NoArgsConstructor
//@WebListener // @WebListener가 없으면 web.xml에 직접 등록해줘야 한다.(***)
public class ContextListenerImpl implements ServletContextListener {
// =========================================================
public ContextListenerImpl () {
log.trace("Default Constructor invoked.");
} // ContextListenerImpl
// =========================================================
@Override
public void contextDestroyed(ServletContextEvent sce) {
log.trace("contextDestroyed({}) invoked.", sce);
} // contextDestroyed ( sce ) : WAS가 내려가기 직전에 수행
// =========================================================
@Override
public void contextInitialized(ServletContextEvent sce) {
log.trace("contextInitialized({}) invoked.", sce);
} // contextInitialized ( sce ) : 서비스하기 직전에 수행
// =========================================================
} // end class
[ 5. 필터 생성 ]
package org.zerock.myapp.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpFilter;
import lombok.extern.log4j.Log4j2;
@Log4j2
//@NoArgsConstructor
@WebFilter("/*") // *는 All의 의미로 모든 요청에 수행하겠다는 의미이다.
public class MyFilter extends HttpFilter implements Filter {
private static final long serialVersionUID = 1L;
// =========================================================
public MyFilter() {
super();
log.trace("Default Constructor invoked.");
} // default ConStructor
// =========================================================
@Override
public void destroy() {
log.trace("destroy() invoked.");
} // destroy
// =========================================================
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
log.trace("doFilter(req, res, chain) invoked.");
// 1. place your Pre-processing code here
log.info("1. Pre-processing ......"); // 사전 처리
req.setCharacterEncoding("UTF-8");
// pass the request along the filter chain
chain.doFilter(req, res);
// 2. place your Post-processing code here
log.info("2. Post-processing ......"); // 사후 처리
// res.setContentType("text/html; charset=utf8");
// 한글이 깨지지 않도록, 필터에서 사전 사후 처리에 등록해 더 이상 반복코딩이 없도록 하였다.
} // doFilter(req, res, chain) : service와 같은 기능
// =========================================================
public void init(FilterConfig fConfig) throws ServletException {
log.trace("init(fConfig) invoked.");
} // init(fConfig)
// =========================================================
} // end class
[ 6. 필터 생성 2 - 체인 ]
package org.zerock.myapp.filter;
import java.io.IOException;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpFilter;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
@Log4j2
@NoArgsConstructor
@WebFilter(dispatcherTypes = {DispatcherType.REQUEST }
, servletNames = { "HelloServlet" }) // 특정한 서블릿에서만 작동
public class MyFilter2 extends HttpFilter implements Filter {
private static final long serialVersionUID = 1L;
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
log.trace("doFilter(req, res, chain) invoked.");
// 1. place your Pre-processing code here
log.info("1. Pre-processing ......"); // 사전 처리
// pass the request along the filter chain
chain.doFilter(req, res);
// 2. place your Post-processing code here
log.info("2. Post-processing ......"); // 사후 처리
} // doFilter(req, res, chain) : service와 같은 기능
// MyFilter과 MyFilter2이 HelloServlet을 호출할때, 체인으로 실행되고 있다.
// 다른 서블릿의 경우에는 MyFilter만 적용된다.
} // end class
[ 7. web.xml에 필터 수동으로 등록하기 ]
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>org.zerock.myapp.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/*</url-pattern>
<!-- <servlet-name>REQUEST</servlet-name> -->
<!-- REQUEST는 정상적으로 실행되는 것에만 적용한다는 의미이다. -->
</filter-mapping>
<!-- ============================================ -->
<filter>
<filter-name>MyFilter2</filter-name>
<filter-class>org.zerock.myapp.filter.MyFilter2</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>HelloServlet</url-pattern>
<!-- <servlet-name>REQUEST</servlet-name> -->
<!-- REQUEST는 정상적으로 실행되는 것에만 적용한다는 의미이다. -->
</filter-mapping>
'KH 정보교육원 [ Java ]' 카테고리의 다른 글
KH 90일차 - Servlet ( JDBC와 커넥션풀로 연결 ) / 패턴 (****) (0) | 2022.07.06 |
---|---|
KH 89일차 - Servlet / 커넥션 풀 (****) (0) | 2022.07.05 |
KH 87일차 - ServletContext (*****) (0) | 2022.07.01 |
KH 86일차 - Servlet 3 ( 파라미터 값 가지고 오기,초기화 파라미터 ) (***) (0) | 2022.06.30 |
KH 85일차 - Servlet 2 (****) (0) | 2022.06.29 |