Servlet 애플리케이션 개발

웹 MVC 시작하기

처음 프로젝트 시작을 maven-archetype-webapp 으로 시작

Pom.xml에 servlet-api 디펜던시 추가

<dependency>
    <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>4.0.1</version>
  <scope>provided</scope>
</dependency>

provided 는 개발할때만 사용되고, 빌드 될때는 빠진다. 이유는 tomcat 에서 구현이 될것이다.

Servlet 생성

web.xml 파일

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>me.morris.HelloServlet</servlet-class>
  </servlet>


  <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>

</web-app>

me.morris 패키지 HelloServlet.java

package me.morris;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class HelloServlet extends HttpServlet {

    @Override
    public void init() throws ServletException {
        System.out.println("init");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet");
        resp.getWriter().println("" +
                "<html>\n" +
                "<body>\n" +
                "<h2>Hello Servlet!</h2>\n" +
                "</body>\n" +
                "</html>\n");

    }

    @Override
    public void destroy() {
        System.out.println("Destroy");
    }
}

톰캣을 사용하여 실행 하면 처리가 됨

Init 메소드는 처음에 요청시에만 출력

Destroy는 tomcat servlet콘테이너가 종료 될때 실행

Servlet Listener와 Filter

Servlet Listener :

  • 웹 어플리케이션에서 발생하는 주요 이벤트를 감지하고, 각 이벤트에 특별한 작업이 필요한 경우에 사용 할 수 있다.
    • 서블릿 컨택스트 수준의 이벤트
      • 컨텍스트 라이프사이클 이벤트
      • 컨텍스트 애트리뷰트 변경 이벤트
    • 세션 수준의 이벤트
      • 세션 라이프 사이클 이벤트
      • 세션 애트리뷰트 변경 이벤트

Servlet Container가 시작될때, DatabaseConnection을 미리 만들어놓고, 다양한 servlet에서 생성할 수 있다.

Servlet attribute에 DatabaseConnection을 미리 만들어 놓을 수 있다.

구현

아래는 Servlet Context의 라이프사이클 변경에 대한 이벤트 를 감지 한것

MyListener.java 추가 하기

public class MyListener implements ServletContextListener {
    //Servlet Container의 라이프 사이클의 이벤트를 감지
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("contextInitialized ");
        sce.getServletContext().setAttribute("name","morriskim");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("contextDestroyed");
    }
}

web.xml 에 listener 태그 추가

<listener>
  <listener-class>me.morris.MyListener</listener-class>
</listener>

결과 :

[2020-03-01 06:39:52,389] Artifact SpringWebMVC:war exploded: Artifact is being deployed, please wait...
contextInitialized <-- 여기 추가된것을 알수 있다.
[2020-03-01 06:39:52,781] Artifact SpringWebMVC:war exploded: Artifact is deployed successfully
[2020-03-01 06:39:52,782] Artifact SpringWebMVC:war exploded: Deploy took 393 milliseconds
01-Mar-2020 18:40:02.244 정보 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/Users/daeyunkim/Documents/03.util/apache-tomcat-8.5.42/webapps/manager]
01-Mar-2020 18:40:02.281 정보 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/Users/daeyunkim/Documents/03.util/apache-tomcat-8.5.42/webapps/manager] has finished in [37] ms
init
doGet

Servlet Filter :

  • 들어온 요청을 서블릿으로 보내고, 또 서블릿이 작성한 응답을 클라이언트로 보내기 전에 특별한 처리가 필요한 경우에 사용 할 수 있다.
  • 체인 형태의 구조

어떠한 요청이 들어왔을때, 요청, 응답에 있어서 전에 처리를 하고 싶은 경우, 여러개의 서블릿에 추가적으로 할 수 있다.

구현

MyFilter.java 추가

  • 주의 해야할점 : javax.servlet의 Filter를 implements 해야됨
    doFilter의 파라미터 들의 값을 보면 ServletRequest request, ServletResponse response, FilterChain chain 을 들어간것을 볼수 있다.
    여기에서는 Filterchain이 request,response를 연결 해줘야한다.

    package me.morris;

    import javax.servlet.*;
    import java.io.IOException;

    public class MyFilter implements Filter {

      @Override
      public void init(FilterConfig filterConfig) throws ServletException {
          System.out.println("Filter init");
      }
    
      @Override
      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
          System.out.println("Filter ");
          chain.doFilter(request,response);
      }
    
      @Override
      public void destroy() {
          System.out.println("Filter destroy");
      }

    }

web.xml 에 Filter 설정 추가

,

의 안의 속성에는 servlet-name과 url-pattern이 있는데,

하나의 주소 이외에 다양한 곳에 필터를 사용할때 url-pattern을 사용한다.

  <filter>
    <filter-name>myfilter</filter-name>
    <filter-class>me.morris.MyFilter</filter-class>
  </filter>

  <filter-mapping>
    <filter-name>myfilter</filter-name>
    <servlet-name>hello</servlet-name>
  </filter-mapping>

Filter를 추가한 실행 동작 순서

[2020-03-01 06:49:03,499] Artifact SpringWebMVC:war exploded: Artifact is being deployed, please wait...
contextInitialized 
Filter init
[2020-03-01 06:49:03,887] Artifact SpringWebMVC:war exploded: Artifact is deployed successfully
[2020-03-01 06:49:03,887] Artifact SpringWebMVC:war exploded: Deploy took 388 milliseconds
init
Filter 
doGet
01-Mar-2020 18:
  1. contextInitialized : 서블릿 리스너에서 contextInitinalize가 실행
  2. Filter init : Filter 를 구현한 클래스에서 init 메서드 실행
  3. FilterMapping된 Servlet 클래스 호출
  4. init : Servlet클래스 init 메서드 실행
  5. Filter : Filter 클래스에서의 doFilter 메서드 실행
  6. doGet : Servlet 메서드의 doGet 메서드 실행

으로 적용된다.

Servlet Container ->(request)-> Filter -> Servlet ->(response)-> Servlet Container

+ Recent posts