본문 바로가기
네이버클라우드/JAVA 웹 프로그래밍

JAVA 63일차 (2023-08-22) 자바 프로그래밍_Servlet 정리 ex06~ex08

by prometedor 2023. 8. 22.
- 서블릿 프로그래밍
  - Init Parameter 다루는 방법
  - Context Parameter 다루는 방법
  - 필터, 서블릿 배치 방법(복습)
  - 포워드/인클루드, 리프래시/리다이렉트 다루는 방법
  - 절대 경로와 상대 경로의 이해

 

Servlet 정리

servlet-app 프로젝트

ㄴ eomcs.servlet.ex06 패키지 생성

=>

ㄴ /Users/사용자명/git/eomcs-java/eomcs-servlet/app/src/main/java/com/eomcs/web/ex05 에 존재하는 파일 모두 복사하기

=>

ㄴ 인텔리제이에서 생성한 패키지 eomcs.servlet.ex06 에 복사한 파일 모두 붙여넣기 > [OK] 선택

 

 

load on startup - 서블릿 객체 자동 생성하기(애노테이션으로 설정하기)

 클라이언트가 실행을 요청하지 않아도 서블릿을 미리 생성하고 싶다면,
 loadOnStartup 프로퍼티 값을 지정하라.
     loadOnStartup=실행순서
 미리 생성할 서블릿이 여러 개 있다면, loadOnStartup에 지정한 순서대로 생성한다.
 서블릿을 미리 생성하는 경우?
 => 서블릿이 작업할 때 사용할 자원을 준비하는데 시간이 오래 걸리는 경우
    웹 애플리케이션을 시작시킬 때 미리 서블릿 객체를 준비하는 것이 좋다.
    예) DB 연결, 소켓 연결, 필요한 환경 변수 로딩, 스프링 IoC 컨테이너 준비 등

Servlet01.java (ex06)

// load on startup - 서블릿 객체 자동 생성하기(애노테이션으로 설정하기)
package eomcs.servlet.ex06;

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

// 클라이언트가 실행을 요청하지 않아도 서블릿을 미리 생성하고 싶다면,
// loadOnStartup 프로퍼티 값을 지정하기.
//@WebServlet(value="/ex06/s1", loadOnStartup=1)
@SuppressWarnings("serial")
public class Servlet01 extends HttpServlet {

  @Override
  public void init() throws ServletException {
    // 클라이언트가 서블릿의 실행을 요청할 때 서블릿 객체가 없으면 생성된다.
    // 서블릿 객체가 생성될 때 이 메서드가 호출된다.
    System.out.println("/ex06/s1 => init()");
  }

  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    System.out.println("/ex06/s1 => service()");
  }
}

 

WEB-INF > web.xml

ㄴ 해당 코드 복사

=>

WEB-INF > web.xml

ㄴ 복사한 코드 붙여넣기

ㄴ 해당 코드 복사하기

=>

WEB-INF > web.xml

ㄴ 복사한 코드 붙여넣기

=>

WEB-INF > web.xml

ㄴ 경로 알맞게 적어주기

=>

ㄴ App 실행

=>

ㄴ localhost:8888/ex06/s1 요청

=>

ㄴ 클라이언트가 서블릿의 실행을 요청할 때 서블릿 객체가 없으면 생성되고, 서블릿 객체가 생성될 때 init 메서드가 호출되므로 콘솔 창에서 "/ex06/s1 => init()" 이 출력됨을 확인할 수 있음 (init() 메서드가 실행됐다는 뜻)

=>

ㄴ 페이지 새로고침 해주기

=>

ㄴ 페이지 새로고침 해줄 경우 service() 메서드가 호출됨을 확인

ㄴ init() 메서드는 서버 실행하고 처음 한 번만 호출됨을 확인

=>

WEB-INF > web.xml

ㄴ <load-on-startup>1</load-on-startup> 이용하여 자동 로딩 되도록 해줌

    ㄴ <load-on-startup> 요소의 값으로는 양의 정수가 사용되며, 값이 작을수록 초기화 순서가 빠름

    ㄴ 값이 작은 Servlet부터 초기화됨

    ㄴ 값이 0인 경우는 웹 컨테이너가 초기화 순서를 결정하게 됨

=>

ㄴ 서버 실행 시 /ex06/Servlet01 의 init() 이 자동 로딩 됨을 확인

ㄴ loaclhost:8888/ex06/s1 호출하기

=>

ㄴ loaclhost:8888/ex06/s1 호출 시 /ex06/Servlet01 의 service() 메서드 호출됨을 확인

 

 

load on startup - 서블릿 객체 자동 생성하기(web.xml에 설정하기)

Servlet02.java (ex06)

// load on startup - 서블릿 객체 자동 생성하기(web.xml에 설정하기)
package eomcs.servlet.ex06;

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

// 클라이언트가 실행을 요청하지 않아도 서블릿을 미리 생성하고 싶다면,
// loadOnStartup 프로퍼티 값을 지정하라.
// <servlet>
//   ...
//   <load-on-startup>1</load-on-startup>
// </servlet>
// 미리 생성할 서블릿이 여러 개 있다면, loadOnStartup에 지정한 순서대로 생성한다.
// 언제 서블릿을 미리 생성하는가?
// => 서블릿이 작업할 때 사용할 자원을 준비하는데 시간이 오래 걸리는 경우
//    웹 애플리케이션을 시작시킬 때 미리 서블릿 객체를 준비한다.
//    예) DB 연결, 소켓 연결, 필요한 환경 변수 로딩, 스프링 IoC 컨테이너 준비 등
//
@SuppressWarnings("serial")
public class Servlet02 extends HttpServlet {

  @Override
  public void init() throws ServletException {
    // 클라이언트가 서블릿의 실행을 요청할 때 서블릿 객체가 없으면 생성된다.
    // 서블릿 객체가 생성될 때 이 메서드가 호출된다.
    System.out.println("/ex06/s2 => init()");
  }

  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    System.out.println("/ex06/s2 => service()");
  }
}

 

WEB-INF > web.xml

ㄴ /ex06/Servlet01 관련 설정 주석 처리 해준 후 /ex06/Servlet02 관련 설정 추가 해주기

=>

ㄴ App 실행

=>

ㄴ 브라우저에서 localhost:8888/ex06/s2 호출

=>

ㄴ /ex06/Servlet02 의 service() 메서드가 호출됨을 확인

 

 

Servlet01.java

ㄴ 애노테이션 주석 풀어주기

=>

ㄴ 서버 실행 시 /ex06/s1 과 /ex06/s2 의 init() 메서드 모두 자동 로딩 됨을 확인

 

 

서블릿 초기화 파라미터 - web.xml에서 설정하기

Servlet04.java (ex06)

// 서블릿 초기화 파라미터 - web.xml에서 설정하기
package eomcs.servlet.ex06;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

// 서블릿이 사용할 값을 DD 설정으로 지정할 수 있다.
// => web.xml 에 지정하였다.
@SuppressWarnings("serial")
public class Servlet04 extends HttpServlet {

  @Override
  public void init() throws ServletException {
    System.out.println("ex06/s4 => init()");

    ServletConfig config = this.getServletConfig();

    System.out.printf("driver=%s\n", config.getInitParameter("jdbc.driver"));
    System.out.printf("url=%s\n", config.getInitParameter("jdbc.url"));
    System.out.printf("username=%s\n", config.getInitParameter("jdbc.username"));
    System.out.printf("password=%s\n", config.getInitParameter("jdbc.password"));
  }
}

 

WEB-INF > web.xml

ㄴ /ex06/Servlet02 설정 복사하여 /ex06/Servlet04 설정 추가해주기

=>

WEB-INF > web.xml

ㄴ <init-param> 태그를 이용하여 설정 추가해주기

=>

Servlet04.java (ex06)

ㄴ ServletConfig 의 getInitParameter() 메서드를 이용하도록 함

=>

ㄴ 서블릿 초기화 파라미터 값 설정됨을 확인

 

 

서블릿 초기화 파라미터 - 애노테이션으로 설정하기

Servlet03.java (ex06)

// 서블릿 초기화 파라미터 - 애노테이션으로 설정하기
package eomcs.servlet.ex06;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

// 서블릿이 사용할 값을 DD 설정으로 지정할 수 있다.
//
//@WebServlet(
//    value = "/ex06/s3",
//    loadOnStartup = 1,
//    initParams = {
//        @WebInitParam(name = "jdbc.driver", value = "org.mariadb.jdbc.Driver"),
//        @WebInitParam(name = "jdbc.url", value = "jdbc:mariadb://localhost/studydb"),
//        @WebInitParam(name = "jdbc.username", value = "study"),
//        @WebInitParam(name = "jdbc.password", value = "******")})
@SuppressWarnings("serial")
public class Servlet03 extends HttpServlet {

  //  ServletConfig config;
  //
  //  @Override
  //  public void init(ServletConfig config) throws ServletException {
  //    // 서블릿 객체가 생성될 때 뭔가 준비하는 작업을 해야 한다면,
  //    // 보통 이 메서드를 오버라이딩 할 것이다.
  //    //
  //    // 이 메서드가 호출될 때 넘어오는 값(config)은 나중에 사용할 수 있도록
  //    // 보통 인스턴스 필드에 보관해 둔다.
  //    // 즉 getServletConfig()가 호출될 때 리턴하도록 다음과 같이 코드를 작성한다.
  //    this.config = config;
  //
  //    // 그런데 init()를 오버라이딩 할 때 마다 이렇게
  //    // config 객체를 인스턴스 필드에 저장하도록 코딩하는 것은 매우 번거롭다.
  //    //
  //    // 이런 불편함을 없애기 위해서 GenericServlet은
  //    // 미리 이 메서드에 해당 코드를 작성해 두었다.
  //    // 그리고 추가적으로 파라미터 값을 받지 않는 init()를 호출하도록
  //    // 구현하였다.
  //    //
  //    // 결론?
  //    // => 그러니 개발자는 서블릿 객체가 생성될 때 뭔가 작업을 수행하고 싶다면,
  //    //    이 메서드를 직접 오버라이딩 하지 말고,
  //    //    이 메서드가 호출하는 다른 init()를 오버라이딩 하라!
  //    //
  //    //
  //
  //  }


  @Override
  public void init() throws ServletException {
    System.out.println("/ex06/s3 ==> init()");
    // 이 객체가 생성될 때 DB에 연결한다고 가정하자!
    // DB에 연결하려면 JDBC Driver 이름과 JDBC URL, 사용자 아이디, 암호를
    // 알아야 한다.
    //
    // 그런데 다음과 같이 자바 소스 코드에 그 값을 직접 작성하면,
    // 나중에 DB 연결 정보가 바뀌었을 때
    // 이 소스를 변경하고 다시 컴파일 해야 하는 번거로움이 있다.
    // => 소스에 변할 수 있는 값을 작성하는 것은 바람직하지 않다.
    // => 보통 이렇게 값을 직접 작성하는 것을 "하드(hard) 코딩"이라 부른다.
    // String jdbcDriver = "org.mariadb.jdbc.Driver";
    // String jdbcUrl = "jdbc:mariadb://localhost:3306/studydb";
    // String username = "study";
    // String password = "******";

    // 위의 코드처럼 언제든 변경될 수 있는 값을
    // 소스코드에 직접 작성하는 방식은 좋지 않다.
    // 해결책?
    // => 이런 변경 값들은 외부에 두는 것이 관리에 편하다.
    // => 값이 바뀌더라도 소스를 변경할 필요가 없다.
    // => 보통 DD 파일(web.xml)에 둔다.
    // => 다만 이 예제에서는 애노테이션으로도 설정할 수 있다는 것을
    //    보여주기 위해 서블릿 상단에 애노테이션으로 설정하였다.
    // => 예)
    //    @WebInitParam(name = "jdbc.driver", value = "org.mariadb.jdbc.Driver")
    // => 애노테이션에 설정된 값을 꺼내기 위해서는 ServletConfig 객체가 필요하다.
    //
    ServletConfig config = this.getServletConfig();

    // 이렇게 @WebInitParam()으로 설정된 값을
    // "서블릿 초기화 파라미터"라 부른다.
    String jdbcDriver = config.getInitParameter("jdbc.driver");
    String jdbcUrl = config.getInitParameter("jdbc.url");
    String username = config.getInitParameter("jdbc.username");
    String password = config.getInitParameter("jdbc.password");

    System.out.println(jdbcDriver);
    System.out.println(jdbcUrl);
    System.out.println(username);
    System.out.println(password);

  }
}

=>

ㄴ 해당 코드 주석 풀어주기

=>

 

 

WEB-INF > web.xml

ㄴ 필터 객체 등록하기

=>

ㄴ ex06.Filter01.init() 실행됨을 확인

=>

=>

ㄴ /ex06/Filter01 가 호출된 후 /ex06/s2 의 service() 메서드 호출됨

=>

WEB-INF > web.xml

ㄴ 초기화 값 설정

=>

ㄴ 서버 실행만 했을 경우의 초기화 확인

=>

=>

ㄴ web.xml 파일의 Filter01 에서 설정한 값이 출력됨을 확인

ㄴ /ex06/Servlet02 의 service() 메서드 호출됨

 

 

필터 초기화 파라미터 : web.xml에서 설정한 값 가져오기

Filter01.java

// 필터 초기화 파라미터 : web.xml에서 설정한 값 가져오기
package eomcs.servlet.ex06;

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

public class Filter01 implements Filter {

  FilterConfig filterConfig;

  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
    this.filterConfig = filterConfig;
    System.out.println("ex06.Filter01.init()");
  }

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {

    // 필터의 DD 설정으로 지정한 파라미터 값 가져오기
    System.out.printf("ex06.Filter01 : encoding=%s\n",
        filterConfig.getInitParameter("encoding"));

    System.out.printf("ex06.Filter01 : aaa=%s\n",
        filterConfig.getInitParameter("aaa"));

    chain.doFilter(request, response);
  }

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

// 필터 객체가 사용할 값을 외부 파일인 web.xml 에 둘 수 있다.
// web.xml 예)
// <filter>
//   <filter-name>f1</filter-name>
//   <filter-class>com.eomcs.web.ex06.Filter01</filter-class>
//   <init-param>
//     <param-name>encoding</param-name>   <== 이렇게 파라미터 이름과
//     <param-value>UTF-8</param-value>    <== 파라미터 값을 설정할 수 있다.
//   </init-param>
//   <init-param>  <== 여러 개 설정하고 싶다면 이렇게 반복하라!
//     <param-name>aaa</param-name>
//     <param-value>okok</param-value>
//   </init-param>
// </filter>
// <filter-mapping>
//   <filter-name>f1</filter-name>
//   <url-pattern>/ex05/*</url-pattern>
//  </filter-mapping>
//
// 필터에서 web.xml 에 설정된 파라미터 값을 꺼내고 싶다면,
// => FilterConfig.getInitParameter(파라미터명) 메서드를 사용하라.
//
//

=>

Filter01.java

ㄴ web.xml 의 DD 설정대로 파라미터 값 가져오기

=>

WEB-INF > web.xml

ㄴ 해당 코드 모두 주석 처리 해주기

=>

필터 초기화 파라미터 : 애노테이션으로 설정한 값 가져오기

Filter02.java

// 필터 초기화 파라미터 : 애노테이션으로 설정한 값 가져오기
package eomcs.servlet.ex06;

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

//@WebFilter(
//    value="/ex06/*",
//    initParams={
//        @WebInitParam(name="encoding", value="UTF-8"),
//        @WebInitParam(name="aaa", value="nono")
//    })
public class Filter02 implements Filter {

  FilterConfig filterConfig;

  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
    this.filterConfig = filterConfig;
  }

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {

    // 필터의 DD 설정으로 지정한 파라미터 값 가져오기
    System.out.printf("ex06.Filter02 : encoding=%s\n",
        filterConfig.getInitParameter("encoding"));

    System.out.printf("ex06.Filter02 : aaa=%s\n",
        filterConfig.getInitParameter("aaa"));

    chain.doFilter(request, response);
  }
}

=>

Filter02.java

ㄴ 해당 코드 주석 해제해주기

=>

ㄴ App 실행 시 /ex06/s1, /ex06/s3 의 init() 메서드가 실행됨을 확인

ㄴ web.xml 에서 DD 설정한 컨텍스트 초기화 파라미터 값 출력됨을 확인

=>

ㄴ 브라우저 리프레시

=>

ㄴ /ex06/Filter02 에 설정된 웹 초기화 파라미터 값 출력됨을 확인

=>

WEB-INF > web.xml

ㄴ 필터와 서블릿에서 공유하는 파라미터 등록하는 부분

 

컨텍스트 파라미터 가져오기

Filter03.java

// 컨텍스트 파라미터 가져오기
package eomcs.servlet.ex06;

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

//@WebFilter("/ex06/*")
public class Filter03 implements Filter {

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {

    // 필터의 DD 설정으로 지정한 파라미터 값 가져오기
    System.out.printf("ex06.Filter03 : encoding=%s\n",
        request.getServletContext().getInitParameter("encoding"));

    System.out.printf("ex06.Filter03 : aaa=%s\n",
        request.getServletContext().getInitParameter("aaa"));

    chain.doFilter(request, response);
  }
}

=>

Filter03.java

ㄴ 해당 코드 주석 해제 해주기

ㄴ Filter03 은 ex06 패키지에 있는 모든 파일과 공유하는 필터임

=>

Filter03.java

ㄴ ServletReqeust 의 getServletContext().getInitParameter 를 이용하여 필터의 DD 설정으로 지정한 파라미터 값 가져오기

=>

ㄴ App 실행

=>

ㄴ localhost:8888/ex06/s2 요청(에러 무시)

=>

ㄴ localhost:8888/ex06/s2 요청 시 Filter03, Filter02 가 호출됨을 확인

ㄴ web.xml 에 설정하는 방법과 애노테이션으로 설정하는 방법 확인

 

 

컨텍스트 초기화 파라미터 - web.xml에서 설정하기

Servlet05.java

// 컨텍스트 초기화 파라미터 - web.xml에서 설정하기
package eomcs.servlet.ex06;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;

// 서블릿의 DD 설정으로 지정한 초기화 파라미터 값은 그 서블릿에서만 사용할 수 있다.
// 모든 서블릿에서 사용할 값을 설정하려면 컨텍스트 파라미터로 설정해야 한다.
// => web.xml 에 지정하였다.
//
//@WebServlet(value="/ex06/s5", loadOnStartup=1)
@SuppressWarnings("serial")
public class Servlet05 extends HttpServlet {

  @Override
  public void init() {

    // 컨텍스트 초기화 파라미터 값을 꺼내려면 ServletContext 객체가 있어야 한다.
    // => 웹 애플리케이션 당 ServletContext 객체는 한 개이다.
    // => 따라서 다음 코드 모두 같은 객체를 리턴한다.
    ServletContext sc = this.getServletContext();
    ServletContext sc2 = this.getServletConfig().getServletContext();
    System.out.println(sc == sc2);

    System.out.printf("driver=%s\n", sc.getInitParameter("jdbc2.driver"));
    System.out.printf("url=%s\n", sc.getInitParameter("jdbc2.url"));
    System.out.printf("username=%s\n", sc.getInitParameter("jdbc2.username"));
    System.out.printf("password=%s\n", sc.getInitParameter("jdbc2.password"));
  }
}

=>

Servlet05.java

ㄴ 애노테이션을 이용하여 설정

=>

WEB-INF > web.xml

ㄴ 컨텍스트 초기화 파라미터 값 설정 코드 복사

=>

WEB-INF > web.xml

ㄴ 복사한 코드 붙여 넣은 후 2로 변경해줌

=>

WEB-INF > 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"
  version="4.0"
  metadata-complete="false">

  <!-- 컨텍스트 초기화 파라미터 등록 -->
  <context-param>
    <param-name>encoding</param-name>
    <param-value>UTF-8</param-value>
  </context-param>
  <context-param>
    <param-name>aaa</param-name>
    <param-value>오호라!</param-value>
  </context-param>

  <context-param>
    <param-name>jdbc2.driver</param-name>
    <param-value>aaa</param-value>
  </context-param>
  <context-param>
    <param-name>jdbc2.url</param-name>
    <param-value>bbb</param-value>
  </context-param>
  <context-param>
    <param-name>jdbc2.username</param-name>
    <param-value>ccc</param-value>
  </context-param>
  <context-param>
    <param-name>jdbc2.password</param-name>
    <param-value>ddd</param-value>
  </context-param>

  <!-- 필터 객체 등록 -->
  <!--
  <filter>
    <filter-name>ex06.f1</filter-name>
    <filter-class>eomcs.servlet.ex06.Filter01</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
      <param-name>aaa</param-name>
      <param-value>오호라...</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>ex06.f1</filter-name>
    <url-pattern>/ex06/*</url-pattern>
  </filter-mapping>
  -->
  
  <!-- 서블릿 객체 등록 -->
  <!-- 
  <servlet>
    <servlet-name>s1</servlet-name>
    <servlet-class>eomcs.servlet.ex01.Servlet01</servlet-class>
  </servlet>
   -->
  
  <!-- 서블릿에 경로 설정 -->
  <!-- 
  <servlet-mapping>
    <servlet-name>s1</servlet-name>
    <url-pattern>/ex01/first</url-pattern>
  </servlet-mapping>
   -->

  <!--
  <servlet>
    <servlet-name>ex06.s2</servlet-name>
    <servlet-class>eomcs.servlet.ex06.Servlet02</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>ex06.s2</servlet-name>
    <url-pattern>/ex06/s2</url-pattern>
  </servlet-mapping>

  <servlet>
    <servlet-name>ex06.s4</servlet-name>
    <servlet-class>eomcs.servlet.ex06.Servlet04</servlet-class>
    <init-param>
      <param-name>jdbc.driver</param-name>
      <param-value>aaa</param-value>
    </init-param>
    <init-param>
      <param-name>jdbc.url</param-name>
      <param-value>bbb</param-value>
    </init-param>
    <init-param>
      <param-name>jdbc.username</param-name>
      <param-value>ccc</param-value>
    </init-param>
    <init-param>
      <param-name>jdbc.password</param-name>
      <param-value>ddd</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>ex06.s4</servlet-name>
    <url-pattern>/ex06/s4</url-pattern>
  </servlet-mapping>
  -->

</web-app>

=>

Servlet05.java (ex06)

ㄴ ServletContext 의 getServletContext() 메서드를 이용하거나 getServletConfig().getServletContext() 메서드를 이용하여 컨텍스 파라미터 값을 꺼내도록 함

=>

ㄴ true 가 출력됨을 확인할 수 있음

 

 

=>

ㄴ ex07 패키지 생성 후 ex06 과 동일하게 파일 가져오기

=>

ㄴ App 실행

=>

포워딩(forwarding) - 서블릿 실행을 위임하기

 주의!
     => + 연산을 수행하지 못한다.
     왜? 서버에 '+' 문자를 전송하면 URL 디코딩 할 때 '+' 문자가 공백(' ')문자로 변환되기 때문이다.
     => + 연산자를 파라미터 값으로 보내고 싶다면 직접 URL 인코딩 해야 한다.
     => 왜? + 문자는 URL에서 한 칸의 공백을 의미한다.
        즉 getParamter("op")의 리턴 값이 공백(" ") 이다.
     => + 문자의 URL 인코딩 값은?
     %2b
     
     
명심!
     => 서블릿의 PrintWriter 객체를 통해 값을 출력하면
        클라이언트로 바로 출력되는 것이 아니라,
        내부에 마련된 버퍼로 출력된다.
     => 그럼 출력 결과는 언제?
        - service() 메서드 호출이 끝났을 때 버퍼의 내용이 클라이언트로 출력된다.
     => 만약 버퍼가 꽉 차면, service() 메서드 호출이 끝나기 전에 자동으로 출력된다.

Servlet01.java (ex07)

// 포워딩(forwarding) - 서블릿 실행을 위임하기
package eomcs.servlet.ex07;

import javax.servlet.RequestDispatcher;
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 java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex07/s1")
@SuppressWarnings("serial")
public class Servlet01 extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 테스트 방법:
    // => http://localhost:8080/java-web/ex07/s1?a=100&b=200&op=+
    // => http://localhost:8080/java-web/ex07/s1?a=100&b=200&op=-
    // => http://localhost:8080/java-web/ex07/s1?a=100&b=200&op=*
    //

    // => + 연산을 파라미터 값으로 보내려면
    // http://localhost:8080/java-web/ex07/s1?a=100&b=200&op=%2b
    //
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();

    // 다음 출력코드는 버퍼로 값을 출력한 것이다.
    // 아직 클라이언트로 보낸 상태가 아니다.
    out.println("더하기 계산 결과:");

    String op = request.getParameter("op");
    if (!op.equals("+")) {
      // 자신의 일이 아니라면 다른 서블릿으로 위임할 수 있다.
      // => 요청을 다른 서블릿으로 전달할 수 있다.
      // 요청배달자 = request.getRequestDispatcher(다른 서블릿 URL);
      RequestDispatcher 요청배달자 = request.getRequestDispatcher("/ex07/s2");

      // 이 서블릿이 지금까지 출력한 것은 모두 취소된다.
      // => PrintWriter 객체를 통해 출력하는 내용은 즉시 웹 브라우저로 전달되는 것이 아니다.
      //    내부 출력 버퍼(보통 8KB 크기)에 보관된다.
      // => 서블릿의 service() 메서드 호출이 종료될 때 비로서 버퍼의 내용이
      //    웹 브라우저로 전송된다.
      // => 물론 그 전에 버퍼가 꽉 차면 자동으로 출력된다.
      // => 그래서 다른 서블릿으로 실행을 위임하기 전에
      //    이 서블릿이 출력한 내용을 취소할 수 있는 것이다.
      요청배달자.forward(request, response);

      // 포워딩 한 후 리턴되는지 확인해보자!
      // 다음 출력이 서버 콘솔창에 보인다면 포워딩 후에 리턴됨을 알 수 있다.
      System.out.println("ex07/Servlet01!!!");

      // 그러면 포워딩 서블릿에서 다시 원래 서블릿으로 돌아온 후에
      // 클라이언트로 출력한다면?
      out.println("어떻게 될까?");

      // 리턴된 후에 출력하는 것은 모두 무시된다.
      // 따라서 포워딩 후에 리턴되면 하위의 코드를 실행하지 않고
      // 바로 종료하도록 다음과 같이 return 명령을 삽입하라!
      return;
    }

    int a = Integer.parseInt(request.getParameter("a"));
    int b = Integer.parseInt(request.getParameter("b"));

    out.printf("%d + %d = %d\n", a, b, a + b);
  }
}

 

Servlet02.java (ex07)

// 포워딩(forwarding) - 서블릿 실행을 위임하기
package eomcs.servlet.ex07;

import javax.servlet.RequestDispatcher;
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 java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex07/s2")
@SuppressWarnings("serial")
public class Servlet02 extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();

    out.println("빼기 계산 결과:");

    String op = request.getParameter("op");
    if (!op.equals("-")) {
      // 자신의 일이 아니라면 다른 서블릿으로 위임할 수 있다.
      // => 요청을 다른 서블릿으로 전달할 수 있다.
      // 요청배달자 = request.getRequestDispatcher(다른 서블릿 URL);
      RequestDispatcher 요청배달자 = request.getRequestDispatcher("/ex07/s3");

      // 이 서블릿이 지금까지 버퍼로 출력한 것은 모두 취소된다.
      // => 엥! 출력된 것이 최소될 수 있나요?
      요청배달자.forward(request, response);

      System.out.println("ex07/Servlet02!!!");
      // 포워딩 한 서블릿을 실행한 후 리턴된다.
      // 단 리턴된 후에 출력하는 것은 모두 무시된다.
      // 따라서 포워딩 후에 리턴되면 하위의 코드를 실행하지 않고
      // 바로 종료하도록 다음과 같이 return 명령을 삽입하라!
      return;
    }

    int a = Integer.parseInt(request.getParameter("a"));
    int b = Integer.parseInt(request.getParameter("b"));

    out.printf("%d - %d = %d\n", a, b, a - b);
  }
}

 

Servlet03.java (ex07)

// 포워딩(forwarding) - 서블릿 실행을 위임하기
package eomcs.servlet.ex07;

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 java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex07/s3")
@SuppressWarnings("serial")
public class Servlet03 extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("해당 연산을 수행할 수 없습니다.");

    System.out.println("ex07/Servlet03!!!");
  }
}

=>

ㄴ + 연산은 + 라고 적으면 연산 불가능함

=>

=>

ㄴ + 연산은 %2b 로 적어줘야 함

=>

Servlet01.java (ex07)

ㄴ getReqeustDispatcher 라는 요청 배달자에 의해 /ex07/s2 로 요청을 전달

ㄴ 요청배달자에 대해 forward 를 실행

=>

Servlet01.java (ex07)

=>

ㄴ - 연산은 정상적으로 실행됨을 확인

=>

 "어떻게 될까?" 문구는 포워딩 후에 출력하는 것이므로 출력되지 않고 무시됨

ㄴ 서버 콘솔창에 보이는 출력을 통해 포워딩 후에 리턴됨을 알 수 있음

 

=>

 

인클루딩(including) - 다른 서블릿의 작업을 포함시키기

Servlet11.java

// 인클루딩(including) - 다른 서블릿의 작업을 포함시키기
package eomcs.servlet.ex07;

import javax.servlet.RequestDispatcher;
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 java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex07/s11")
@SuppressWarnings("serial")
public class Servlet11 extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 테스트 방법:
    // => http://localhost:8080/java-web/ex07/s11?a=100&b=200&op=%2b
    // => http://localhost:8080/java-web/ex07/s11?a=100&b=200&op=-
    // => http://localhost:8080/java-web/ex07/s11?a=100&b=200&op=*
    //
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();

    out.println("계산 결과:");
    out.println("---------------------------------------");
    String op = request.getParameter("op");

    RequestDispatcher 요청배달자 = null;

    if (op.equals("+")) {
      요청배달자 = request.getRequestDispatcher("/ex07/s11_plus");
    } else if (op.contentEquals("-")) {
      요청배달자 = request.getRequestDispatcher("/ex07/s11_minus");
    } else {
      요청배달자 = request.getRequestDispatcher("/ex07/s11_error");
    }

    // 다른 서블릿을 실행시킨다.
    // => forward()는 다른 서블릿으로 위임할 때 현재 서블릿의 출력을 취소한다.
    // => include()는 다른 서블릿으로 실행을 위임하더라도
    //    현재 서블릿의 실행 결과를 유지한다.
    // => 인클루드의 경우 현재 서블릿에서 setContentType()을 설정해야 한다.
    // => 포워드는 현재 서블릿에서 설정한 setContentType()이 무시된다.
    요청배달자.include(request, response);

    // including 서블릿을 실행한 후에 리턴되면
    // 현재 서블릿은 계속해서 출력할 수 있다.
    // => forwarding 서블릿을 실행한 후에서 리턴되어도
    //    현재 서블릿이 출력할 수 없었다.
    //    정확히 하면 출력한 것이 모두 무시되었다.

    out.println("---------------------------------------");
  }
}

 

Servlet11_plus.java

// 인클루딩(forwarding) - 다른 서블릿의 실행을 포함시키기
package eomcs.servlet.ex07;

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 java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex07/s11_plus")
@SuppressWarnings("serial")
public class Servlet11_plus extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 이미 이전 서블릿에서 setContentType()을 호출했기 때문에
    // 이 서블릿에서는 할 필요가 없다.
    // => forwarding으로 서블릿을 실행할 때는 여기에서 따로 setContentType()을 호출해야 한다.
    PrintWriter out = response.getWriter();

    int a = Integer.parseInt(request.getParameter("a"));
    int b = Integer.parseInt(request.getParameter("b"));

    out.printf("%d + %d = %d\n", a, b, a + b);

    // 이 메서드의 호출이 완료되면 이전 서블릿으로 되돌아 간다.
  }
}

 

Servlet11_minus.java

// 인클루딩(forwarding) - 다른 서블릿의 실행을 포함시키기
package eomcs.servlet.ex07;

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 java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex07/s11_minus")
@SuppressWarnings("serial")
public class Servlet11_minus extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 이미 이전 서블릿에서 setContentType()을 호출했기 때문에
    // 이 서블릿에서는 할 필요가 없다.
    // => forwarding으로 서블릿을 실행할 때는 여기에서 따로 setContentType()을 호출해야 한다.
    PrintWriter out = response.getWriter();

    int a = Integer.parseInt(request.getParameter("a"));
    int b = Integer.parseInt(request.getParameter("b"));

    out.printf("%d - %d = %d\n", a, b, a - b);

    // 이 메서드의 호출이 완료되면 이전 서블릿으로 되돌아 간다.
  }
}

 

Servlet11_error.java

// 인클루딩(forwarding) - 다른 서블릿의 실행을 포함시키기
package eomcs.servlet.ex07;

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 java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex07/s11_error")
@SuppressWarnings("serial")
public class Servlet11_error extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 이미 이전 서블릿에서 setContentType()을 호출했기 때문에
    // 이 서블릿에서는 할 필요가 없다.
    // => forwarding으로 서블릿을 실행할 때는 여기에서 따로 setContentType()을 호출해야 한다.
    PrintWriter out = response.getWriter();
    out.println("해당 연산자를 지원하지 않습니다.");

    // 이 메서드의 호출이 완료되면 이전 서블릿으로 되돌아 간다.
  }
}

=>

 

 

ㄴ ex08 패키지 생성 후 ex06, ex07 과 동일하게 파일 가져오기


들여쓰기 값 설정

ㄴ Editor > Code Style > Java > Tabs and Indents > Indent : 2 로 설정

 

줄바꿈 설정

ㄴ Editor > Code Style > General > Hard wrap at : 100 으로 설정


리프래시 - 클라이언트에게 다른 URL을 요청하라는 명령

     리프래시
     => 서버로부터 응답을 받고 "내용을 출력"한 후
        지정된 시간이 경과되면 특정 URL을 자동으로 요청하도록 만들 수 있다.
     => 보통 웹 페이지를 자동으로 이동시키고 싶을 때 사용한다.
     => 예
        예1: 로그인 후 메인페이지로 자동 이동
        예2: 메일을 전송한 후 메일 목록 페이지로 자동 이동
        예3: 게시글 등록한 후 게시글 목록으로 자동 이동
        예4: 결제 완료 후 결제 상태 페이지로 자동 이동

Servlet01.java (ex08)

// 리프래시 - 클라이언트에게 다른 URL을 요청하라는 명령
package eomcs.servlet.ex08;

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 java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex08/s1")
@SuppressWarnings("serial")
public class Servlet01 extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 테스트 방법:
    // => http://localhost:8080/java-web/ex08/s1
    //

    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();

    out.println("안녕하세요! - /ex08/s1");

    // 응답 헤더에 Refresh 정보를 추가한다.
    //
    // 위에서 벌써 클라이언트에게 응답을 했는데 어떻게 응답 헤더를 출력할 수 있나요?
    // => 잊지 말자! out.println()이 출력한 것은 출력스트림 버퍼에 보관되어 있다.
    //    따라서 아직 클라이언트에게 응답한 상태가 아니다.
    //    그래서 다음과 같이 출력을 한 후에 응답 헤더 값을 추가하거나 변경할 수 있는 것이다.
    //    메서드 호출이 완료될 때 비로소 클라이언트로 응답헤더와
    //    버퍼에 저장된 message-body가 출력된다.
    //
    // 만약 out.println()/out.printf()/out.print() 등에서 출력한 내용이
    // 버퍼를 꽉 채웠다면 어떻게 되나요?
    // => 그러면 자동으로 클라이언트에게 응답한다.
    //    따라서 일단 클라이언트에게 응답을 하면
    //    헤더를 추가하거나 변경하는 코드는 적용되지 않는다.
    //    즉 응답을 완료한 후에 헤더 값을 변경하거나 바꿀 수 없기 때문이다.
    //    소용이 없다.
    //

    // 다음은 일부러 버퍼를 채우는 코드이다.
    // 버퍼가 꽉차면 자동으로 출력하는 것을 확인해보자!
    for (int i = 0; i < 150; i++) {
      // 약 40 바이트씩 100번 출력하면 아직 버퍼에 차지 않았기 때문에
      // 클라이언트로 출력되지 않는다.
      // 따라서 반복문 아래에 있는 응답 헤더 설정이 유효하다.
      // 그러나 200번 출력하면 헤더 값과 이전에 출력한 값,
      // 그리고 반복문에서 출력한 데이터가 8KB 버퍼를 꽉 채우기 때문에
      // 즉시 클라이언트로 응답한다.
      // 즉 반복문 다음에 헤더를 설정하기 전에 이미 버퍼 내용이 출력된다.
      // 응답이 완료된 후에 응답 헤더의 값을 변경하거나 추가해봐야 소용없다.
      //
      //      out.println(i + " ===> 1234567890123456789012345678901234567890");
    }

    response.setHeader("Refresh", "3;url=s100");

    // 이 service() 메서드의 호출이 끝나면
    // 비로서 응답 프로토콜에 맞춰
    // 클라이언트로 헤더와 내용을 전송한다.
  }
}

=>

ㄴ 해당 코드 주석 처리

=>

ㄴ 현재 페이지가 로딩된 후 3초 뒤에 자동으로 리프레시하고, 그 후에는 s100 페이지로 이동하도록 함

ㄴ 상대 경로 => 3;url=s100

ㄴ 절대 경로 => 3;url=/ex08/s100

=>

ㄴ App 실행

=>

ㄴ localhost:8888/ex08/s1 요청

=>

ㄴ 3초 뒤 리프레시 되며 s100 으로 이동됨을 확인

=>

리프래시 II - 클라이언트에게 다른 URL을 요청하라는 명령

 

Servlet02.java (ex08)

// 리프래시 II - 클라이언트에게 다른 URL을 요청하라는 명령
package eomcs.servlet.ex08;

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 java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex08/s2")
@SuppressWarnings("serial")
public class Servlet02 extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 테스트 방법:
    // => http://localhost:8080/java-web/ex08/s2
    //

    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();

    out.println("<html><head>");

    // HTML을 출력하는 경우
    // 응답 헤더가 아니라 HTML 헤더에 리프래시 명령을 설정할 수 있다.
    out.println("<meta http-equiv='Refresh' content='3;url=s100'>");

    out.println("</head><body>");
    out.println("<h1>안녕하세요! - /ex08/s2</h1>");
    out.println("</body></html>");
  }
}

// HTTP 응답 프로토콜 예:
//
//HTTP/1.1 200 
//Content-Type: text/html;charset=UTF-8 
//Content-Length: 119 
//Date: Mon, 16 Sep 2019 03:36:11 GMT
//
//<html><head> 
//<meta http-equiv='Refresh' content='3;url=s100'> 
//</head><body>
//<h1>안녕하세요! - /ex08/s2</h1>
//</body></html>

=>

ㄴ HTML 의 meta 태그를 이용하여 HTML 헤더에 리프레시 명령을 설정

=>

ㄴ localhost:8888/ex08/s2 요청

=>

ㄴ 3초 뒤 리프레시 되며 s100 으로 이동됨을 확인

=>

 

 

리다이렉트 - 응답할 때 콘텐트를 보내지 않는다. 바로 다른 페이지를 요청하라고 명령한다.

 리다이렉트
     => 클라이언트의 요청을 받은 후 콘텐트를 보내는 대신
        다른 페이지의 URL을 알려줄 때 사용한다.
     => 웹 브라우저는 응답 받는 즉시 해당 페이지를 요청한다.
        웹 서버로부터 콘텐트를 받지 않았기 때문에 어떤 것도 출력하지 않는다.
        바로 다른 페이지로 이동한다.
     => 리프래시와 달리 서버는 콘텐트(message-body)를 보내지 않는다.
     => 사용 예:
        - 로그인 후 로그인 결과를 출력하지 않고 즉시 메인 화면으로 보내고 싶을 때
        - 결제완료 후 결과를 출력하지 않고 즉시 결제 상태 페이지로 보내고 싶을 때
     => 리다이렉트 HTTP 응답 프로토콜

        HTTP/1.1 302 <----- 리다이렉트 응답 상태 코드 (요청한 자원이 다른 URL에 있음을 표시)
        Location: s100 <----- 리다이렉트 URL (다른 URL의 주소를 알려줌)
        Content-Type: text/html;charset=UTF-8
        Content-Length: 0
        Date: Tue, 02 Apr 2019 03:38:45 GMT
        빈 줄
             <---- 콘텐트를 보내지 않는다. 즉 message-body가 없다.

Servlet03.java (ex08)

// 리다이렉트 - 응답할 때 콘텐트를 보내지 않는다. 바로 다른 페이지를 요청하라고 명령한다.
package eomcs.servlet.ex08;

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 java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex08/s3")
@SuppressWarnings("serial")
public class Servlet03 extends HttpServlet {

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    // 테스트 방법:
    // => http://localhost:8080/java-web/ex08/s2
    //
    System.out.println("/ex08/s3");
    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();

    out.println("<html><head>");
    out.println("<title>리다이렉트</title>");
    out.println("</head><body>");

    // 버퍼가 꽉차서 클라이언트로 자동 출력되면
    // 리다이렉트가 안먹힌다.
    // 왜? 리다이렉트 명령을 응답헤더로 보내기 때문이다.
    // 이미 클라이언트로 출력을 완료했는데 어떻게 응답헤더를 보내는가?
    // 다음 반복문 주석을 풀라!
    for (int i = 0; i < 1000; i++) {
//      out.println("안녕하세요! - /ex08/s3<br>");
    }
    out.println("</body></html>");

    // 클라이언트에게 URL을 알려줄 때 상대 경로를 지정할 수 있다.
    // forward/include 와 달리 '/'는 컨텍스트 루트(웹 애플리케이션 루트)가 아닌
    // 웹 서버 루트를 의미한다.
    response.sendRedirect("s100");

    // 리다이렉트를 하는 순간 이전까지 버퍼로 출력된 내용은 모두 버려진다.
    // 왜? 리다이렉트는 클라이언트로 콘텐트를 보내지 않는다.
    //
    // 만약 출력한 내용이 버퍼를 꽉 채워서 자동으로 응답을 했다면 어떻게 되나요?
    // => 이미 응답했기 때문에 리다이렉트는 동작되지 않는다.
  }
}

=>

Servlet03.java (ex08)

ㄴ 해당 코드 주석 처리 해주기

=>

ㄴ 응답 헤더에 콘텐트를 보내지 않고 페이지를 바로 요청함

 

Postman 이용하기

=>

ㄴ servlet-app 에 Add request 선택하여 ex08/sx 라는 이름의 새로운 request 생성

ㄴ localhost:8888/ex08/s1 를 입력하고 [Send] 선택하여 GET 방식으로 요청

=>

=>

ㄴ Header 확인