HttpServlet 클래스를 사용하여 서블릿을 만드는 방법을 알아본다. 지금까지 서블릿 클래스를 만들 때 service() 메소드를 정의하였지만 HttpServlet 클래스를 상속받으면 service() 대신 doGet()이나 doPost()를 정의한다. 먼저 doGet()의 사용법을 알아본다.
기존의 작업한 회원 목록 서블릿을 실행한 화면에 신규 회원 링크를 추가한다.
...
//HTML 태그 출력
PrintWriter out = response.getWriter();
out.println("<html><head><title>회원목록</title></head>");
out.println("<body><h1>회원목록</h1>");
//신규 회원 링크 - a태그의 링크 URL은 add다.
out.println("<p><a href='add'>신규 회원</a></p>");
//a태그의 href에서 URL이 '/'로 시작하면 절대 경로, '/'로 시작하지 않으면 상대 경로.
...
- 절대 경로 URL
절대 경로는 웹 서버 루트를 기준으로 계산한다. 만약 링크 URL이 'web04/member/add'라면 실제 URL을 계산해보면 그림 1과 같다(그림 1).
절대 경로 작성 시 현재 웹 애플리케이션의 경로(/web04)를 빠뜨려선 안 되는데, 절대 경로로 URL을 계산 시 현재 컨텍스트 루트(웹 애플리케이션)의 경로가 자동 계산되지 않기 때문이다. 절대 경로를 사용할 때 문제가 되는 것은 컨텍스트 루트의 이름을 바꾸면 절대 경로를 사용한 모든 웹 페이지의 링크를 바꿔야 하기 때문에 실무에서는 절대 경로를 사용하지 않고 상대 경로를 사용하여 URL 요청을 작성한다.
- 상대 경로 URL
상대 경로는 현재 경로를 기준으로 계산한다. 현재 경로(/member/list)를 기준으로 <a> 링크의 상대 경로를 계산하면 그림 2와 같다(그림 2).
MemberListServlet 클래스를 실행하기 위해 톰캣 서버를 시작하여 http://localhost:9999/web04/member/list 링크를 실행한다.
아직 /member/add 요청에 대한 서블릿을 만들지 않았지만 상대 경로의 계산 결과를 확인하기 위해 신규 회원 링크를 클릭한다.
URL을 확인해보면 <a> 태그 링크 'add'의 최종 URL을 알 수 있다(그림 4).
spms.servlets 패키지에 MemberAddServlet 클래스를 작성 후 HttpServlet 추상 클래스를 상속받는다.
package spms.servlets;
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("/member/add")
public class MemberAddServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
//신규 회원 링크 클릭시 GET 요청(a태그로 만들어진 링크 클릭)이 발생하기에 doGet() 메소드를 오버라이딩
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html; charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<html><head><title>회원 등록</title></head>");
out.println("<body><h1>회원 등록</h1>");
out.println("<form action='add' method='post'>"); //action : 실행할 서블릿 URL 주소, method : 서버에 요청하는 방식 지정
//a태그의 href와 마찬가지로 action에서도 URL이 '/'로 시작하면 절대 경로, '/'로 시작하지 않으면 상대 경로.
out.println("이름: <input type='text' name='name'><br>");
out.println("이메일: <input type='text' name='email'><br>");
out.println("암호: <input type='password' name='password'><br>");
out.println("<input type='submit' value='추가'>"); //submit : 서버에 요청을 보내는 버튼
out.println("<input type='reset' value='취소'>"); //reset : 입력폼을 초기화시키는 버튼
out.println("</form>");
out.println("</body></html>");
}
}
HttpServlet 클래스는 GenericServlet 클래스의 하위 클래스다. 따라서 HttpServlet 클래스를 상속받으면 GenericServlet 클래스를 상속받는 것과 마찬가지로 javax.servlet.Servlet 인터페이스를 구현한 것이 된다(그림 5).
서블릿 컨테이너는 Servlet 규칙에 정의된 메소드를 호출하기 때문에, 서블릿 객체는 반드시 Servlet 인터페이스를 구현해야 한다.
HttpServlet 클래스를 상속받을 때 service()를 직접 구현하기 보다는 클라이언트 요청 방식에 따라 doXXX()를 오버라이딩 한다. 즉, 클라이언트 요청이 들어오면 상속받은 HttpServlet의 service()가 호출되고 service()는 클라이언트 요청 방식에 따라 doGet(), doPost(), doPut() 등의 메소드를 호출한다.
회원 목록 서블릿을 실행한 결과 화면에서 신규 회원 링크 클릭 시 GET 요청이 발생하기 때문에 MemberAddServlet 클래스에서 doGet()을 오버라이딩 하였다.
- 웹 브라우저에서 GET 요청이 발생하는 경우
1. 웹 브라우저 주소창에 URL을 입력한 후 엔터를 누를 때
2. a태그로 만들어진 링크를 누를 때
3. form태그의 method 속성 값이 get이거나 method 속성 값이 생략된 경우(method 속성 기본값은 get이다)
톰캣 서버 재시작 후 http://localhost:9999/web04/member/add 링크를 실행한다(그림 6).
입력폼에 임의의 값을 넣고 '추가'버튼을 클릭하면 오류가 발생한다(그림 7).
form 태그의 method 속성을 보면 post인 것을 확인할 수 있다. 즉, POST 요청이 발생하였다. 톰캣 서버가 클라이언트로부터 /member/add 요청을 받으면, MemberAddServlet 클래스의 service()를 호출한다. service()에서는 요청 방식에 따라 GET 요청이면 doGet(), POST 요청이면 doPost()를 호출하지만, 현재 doGet()만 존재하고 doPost()는 존재하지 않으므로 오류가 발생한 것이다.
HttpServlet 클래스를 상속받아 서블릿을 만들 때 클라이언트의 요청에 따라 적절한 doXXX()를 정의해야 한다. 그렇지 않으면 위와 같은 오류가 발생한다.
참고도서 : https://freelec.co.kr/book/1674/
[열혈강의] 자바 웹 개발 워크북
[열혈강의] 자바 웹 개발 워크북
freelec.co.kr
'교재 실습 > 자바 웹 개발 워크북' 카테고리의 다른 글
26. 요청 매개변수의 한글 깨짐 처리 (0) | 2022.01.22 |
---|---|
25. HttpServlet으로 POST 요청 다루기 (0) | 2022.01.20 |
23. 데이터베이스에서 데이터 가져오기 (2) (0) | 2022.01.18 |
22. 데이터베이스에서 데이터 가져오기 (1) (0) | 2022.01.17 |
21. JDBC와 데이터베이스 (0) | 2022.01.15 |
댓글