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

JAVA 62일차 (2023-08-21) 자바 프로그래밍_Servlet 정리_ex05

by prometedor 2023. 8. 21.
- 서블릿 프로그래밍
  - HttpServlet 클래스의 역할 이해

 

ㄴ eomcs.servlet.ex05 패키지 생성

=>

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

=>

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

=>

HTTP 프로토콜 다루기 - HttpServletRequest와 GET/POST

     HTTP 프로토콜로 통신을 하는 서블릿 컨테이너는
     service() 메서드를 호출할 때
     ServletRequest의 파라미터 값으로 HttpServletRequest를 만들어 전달한다.
     ServletResponse의 파라미터 값으로 HttpServletResponse를 만들어 전달한다.
     따라서 service() 메서드의 파라미터 값은 원래
     HttpServletRequest와 HttpServletResponse이다.
     이들 객체에는 HTTP 프로토콜을 다루는 메서드가 추가되어 있다.
     따라서 HTTP 프로토콜을 다루고 싶다면 파라미터 값을
     원래의 타입으로 변환하라!

Servlet01.java (ex05)

// HTTP 프로토콜 다루기 - HttpServletRequest와 GET/POST
package eomcs.servlet.ex05;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex05/s1")
public class Servlet01 extends GenericServlet {

  private static final long serialVersionUID = 1L;

  @Override
  public void service(ServletRequest req, ServletResponse res)
      throws ServletException, IOException {

    // 테스트
    // - http://localhost:8080/web/ex05/test01.html 실행
    //

    HttpServletRequest httpReq = (HttpServletRequest) req;
    HttpServletResponse httpRes = (HttpServletResponse) res;

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

    // HttpServletRequest에는 HTTP 프로토콜의 요청 방식을 리턴하는 메서드가 있다.
    // => HttpServletRequest.getMethod()
    //
    if (httpReq.getMethod().equals("GET")) {
      out.println("GET 요청입니다.");

    } else if (httpReq.getMethod().equals("POST")) {
      out.println("POST 요청입니다.");

    } else {
      out.println("이 서블릿이 다루지 못하는 요청 방식입니다.");
    }

  }
}

=>

=>

Postman 이용하기

ㄴ servlet-app 더보기 아이콘 > App request 선택하여 새로운 request 생성하기

=>

ㄴ ex05/s1 이라는 이름으로 변경해주기

=>

ㄴ localhost:8888/ex05/s1 이라는 url 설정해주기 > [Send] 선택

=>

ㄴ GET 요청임을 확인

=>

ㄴ servlet-app 더보기 아이콘 > App request 선택하여 새로운 request 생성하기

=>

ㄴ ex05/s1 이라는 이름으로 설정해주기

=>

ㄴ POST 방식으로 설정해주기

ㄴ localhost:8888/ex05/s1 이라는 url 설정해주기 > [Send] 선택

=>

ㄴ POST 요청임을 확인

=>

ㄴ servlet-app 더보기 아이콘 > App request 선택하여 새로운 request 생성하기

=>

ㄴ localhost:8888/ex05/s1 이라는 url 설정해주기 > [Send] 선택

ㄴ PUT 방식으로 설정 해주기

=>

ㄴ ex05/Servlet01.java 에 정의되어있지 않은 요청 방식이므로 해당 문구 출력됨

=>

Servlet01.java (ex05)

=>

Servlet01.java (ex05)

ㄴ getMethod 메서드를 이용하여 요청 방식을 알아냄

 

 

MyHttpServlet.java

package eomcs.servlet.ex05;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

// 서블릿 클래스를 만들 때 HTTP 프로토콜을 쉽게 다룰 수 있도록
// service(HttpServletRequest,HttpServletResponse) 메서드를 추가하였다.
// 따라서 GenericServlet을 상속 받아 서블릿을 만들기 보다
// 이 클래스를 상속 받아 서블릿을 만든다면,
// 훨씬 편하게 service()를 구현할 수 있다.
//
@SuppressWarnings("serial")
public abstract class MyHttpServlet extends GenericServlet {

  @Override
  public void service(ServletRequest req, ServletResponse res)
      throws ServletException, IOException {
    // 서블릿 컨테이너가 이 메서드를 호출하면

    // => 파라미터 값을 원래의 타입으로 변환한다.
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    // => 오버로딩한 service()를 호출한다.
    this.service(request, response);
  }

  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // 웹브라우저가 요청하면
    // => 서블릿 컨테이너가 service(ServletRequest,ServletResponse)를 호출한다.
    // => service(ServletRequest,ServletResponse)는
    //    다시 오버로딩한 이 메서드를 호출한다.
    //    현재 이 메서드는 아무런 일을 하지 않는다.
    //    이 클래스를 상속 받는 서브 클래스 쪽에서 이 메서드를 오버라이딩 하면 된다.
  }

}

 

 

HTTP 프로토콜 다루기 - MyHttpServlet 클래스를 활용하기

Servlet02.java (ex05)

// HTTP 프로토콜 다루기 - MyHttpServlet 클래스를 활용하기
package eomcs.servlet.ex05;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex05/s2")
public class Servlet02 extends MyHttpServlet {

  private static final long serialVersionUID = 1L;

  @Override
  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // 테스트
    // - http://localhost:8080/web/ex05/test02.html 실행
    //
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();

    if (request.getMethod().equals("GET")) {
      out.println("GET 요청입니다.");

    } else if (request.getMethod().equals("POST")) {
      out.println("POST 요청입니다.");

    } else {
      out.println("이 서블릿이 다루지 못하는 요청 방식입니다.");
    }

  }
}

=>

ㄴ Get 요청임을 확인

=>

ㄴ Post 요청임을 확인

=>

ㄴ ex05/Servlet02.java 에서는 처리할 수 없는 요청임을 확인

 

 

HTTP 프로토콜 다루기 - MyHttpServlet2 클래스를 활용하기

MyHttpServlet2.java (ex05)

package eomcs.servlet.ex05;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

// MyHttpServlet 클래스를 사용하여 서블릿을 만드는 것도 편하지만,
// 여기에다가 HTTP 요청 방식에 따라 메서드를 구분해 놓는다면
// 서브 클래스를 만들기가 더 편리할 것이다.
//
@SuppressWarnings("serial")
public abstract class MyHttpServlet2 extends GenericServlet {

  @Override
  public void service(ServletRequest req, ServletResponse res)
      throws ServletException, IOException {
    // 서블릿 컨테이너가 이 메서드를 호출하면

    // => 파라미터 값을 원래의 타입으로 변환한다.
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    // => 오버로딩한 service()를 호출한다.
    this.service(request, response);
  }

  protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // HTTP 요청 방식에 따라 메서드를 분리하여 호출한다.
    String httpMethod = request.getMethod();

    switch (httpMethod) {
      case "GET":
        doGet(request, response);
        return;
      case "POST":
        doPost(request, response);
        return;
      case "PUT":
        doPut(request, response);
        return;
      case "HEAD":
        doHead(request, response);
        return;
      default:
        error(request, response);
    }
  }


  // 서브 클래스에서 오버라이딩 할 메서드라면 private으로 선언하지 말라.
  // => 서브 클래스에서 이 메서드를 오버라이딩 하지 않으면 오류를 출력하도록 한다.
  // => 즉 클라이언트의 이런 요청을 처리하라면 서브 클래스에서 그 요청 방식에 해당하는 메서드를
  // 오버라이딩 하면 된다.
  // => 클라이언트 요청이 들어오면
  // 서블릿 컨테이너
  // ==> service(ServletRequest,ServletResponse) 호출
  //     ==> service(HttpServletRequest,HttpServletResponse) 호출
  //         ==> doXxx(HttpServletRequest,HttpServletResponse) 호출
  //
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    error(request, response);
  }

  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    error(request, response);
  }

  protected void doPut(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    error(request, response);
  }

  protected void doHead(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    error(request, response);
  }

  private void error(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    request.setCharacterEncoding("UTF-8");
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("해당 HTTP 요청을 처리할 수 없습니다.");
  }



}

 

Servlet03.java (ex05)

// HTTP 프로토콜 다루기 - MyHttpServlet2 클래스를 활용하기
package eomcs.servlet.ex05;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/ex05/s3")
public class Servlet03 extends MyHttpServlet2 {

  private static final long serialVersionUID = 1L;


  // HTTP GET 요청에 응답하고 싶다면
  // 상속 받은 메서드 중에서 doGet()을 오버라이딩 한다.
  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // 테스트
    // - http://localhost:8080/web/ex05/test03.html 실행
    //
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("doGet() => GET 요청입니다.");
  }

  // HTTP POST 요청에 응답하고 싶다면
  // 상속 받은 메서드 중에서 doPost()을 오버라이딩 한다.
  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // 테스트
    // - http://localhost:8080/java-web/ex05/test03.html 실행
    //
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("doPost() => POST 요청입니다.");
  }
}

=>

ㄴ doGet() 일 경우 "GET 요청입니다." 출력됨

=>

ㄴ doPost() 일 경우 "POST 요청입니다." 출력됨

=>

MyHttpServlet2.java (ex05)

ㄴ 해당 코드 주석 처리 할 경우 아래와 같이 출력됨

=>

ㄴ ContentType 을 UTF-8 로 설정하는 코드를 주석처리 했으므로 ? 가 출력됨

=>

MyHttpServlet2.java (ex05)

ㄴ 주석 풀어줘야 함

=>

ㄴ ex05/Servlet03.java 서블릿에서는 처리할 수 없는 요청이므로 "해당 HTTP 요청을 처리할 수 없습니다." 문구가 정상적으로 출력됨을 확인