HttpServlet으로 GET요청 다루기 - 회원 목록 화면에 '신규 회원' 링크 추가

src/spms/servlet/MemberAddServlet

@WebServlet("/member/add")
public class MemberAddServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        resp.setContentType("text/html; charset=UTF-8");

        PrintWriter out = resp.getWriter();
        out.println("<html><head><title>회원 등록</title></head>");
        out.println("<body><h1>회원 등록</h1>");
        out.println("<form action='add' method='post'>");
        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='추가'>");
        out.println("<input type='reset' value='취소'>");
        out.println("</form>");
        out.println("</body></html>");
    }
}

HttpServlet 클래스

GenericServlet 클래스 대신 HttpServlet 클래스를 상속받았다. HttpServlet 클래스는 GenericServlet 클래스의 하위 클래스다. 따라서 javax.servlet.Servlet 인터페이스를 구현한 것이 된다.

doGet() 메서드 오버라이딩

HttpServlet 클래스에 정의된 메서드 중에서 doGet() 메서드를 오버라이딩한다. doGet() 메서드 안에 이 클래스가 해야 할 일을 작성한다. 지금까지는 이 역할을 service() 메서드가 했는데 이번에 doGet() 메서드를 사용한 이유는 다음과 같다.

클라이언트 요청이 들어오면, 첫째로 상속받은 HttpServlet의 service() 메서드가 호출되고, 둘째로 service()는 클라이언트 요청 방식에 따라 doGet()이나, doPost(), doPut() 등의 메서드를 호출한다.

따라서 HttpServlet을 상속받을 때 service() 메서드를 직접 구현하기보다는 클라이언트의 요청 방식에 따라 doXXX() 메서드를 오버라이딩한다.

회원 정보 입력폼 실행

Chapter04(2)-1

HttpServlet으로 POST 요청 다루기

doPost() 오버라이딩

src/spms/servlet/MemberAddServlet.java

@Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        Connection conn = null;
        PreparedStatement stmt = null;

        try {
            DriverManager.registerDriver(new com.mysql.jdbc.Driver());
            conn = DriverManager.getConnection(
                    "jdbc:mysql://localhost/practicedb",  //JDBC URL
                    "study",  // DBMS 사용자 아이디
                    "1111");  //DBMS 사용자 암호
            stmt = conn.prepareStatement(
                    "INSERT INTO MEMBERS(EMAIL,PWD,MNAME,CRE_DATE,MOD_DATE)"
                            + " VALUES (?,?,?,NOW(),NOW())");
            stmt.setString(1, req.getParameter("email"));
            stmt.setString(2, req.getParameter("password"));
            stmt.setString(3, req.getParameter("name"));
            stmt.executeUpdate();

           resp.setContentType("text/html; charset=UTF-8");
            PrintWriter out = resp.getWriter();
            out.println("<html><head><title>회원등록결과</title></head>");
            out.println("<body>");
            out.println("<p>등록 성공입니다!</p>");
            out.println("</body></html>");
        }  catch (Exception e) {
            throw new ServletException(e);
        } finally {
            try {if (stmt != null) stmt.close();} catch(Exception e) {}
            try {if (conn != null) conn.close();} catch(Exception e) {}
        }
    }

JDBC 객체를 위한 참조 변수 선언

SQL 문을 실행하는데 Statement 대신 PreparedStatement를 사용했다. PreparedStatement는 반복적인 질의를 하거나, 입력 매개변수가 많은 경우에 유용하다. 특히 이미지와 같은 바이너리 데이터를 저장하거나 변경할 때는 PreparedStatement만이 가능하다.

PreparedStatement의 사용

Now()는 MySQL 서버에서 제공하는 함수로 SQL 문을 실행하는 시점의 날짜와 시간을 반환한다. INSERT 문에서 생성일(CRE_DATE)과 변경일(MOD_DATE)은 현재 시간으로 맞추고, 나머지 값은 입력 매개변수로 지정한다.

입력 매개변수의 값 설정

입력 매개변수는 SQL 문에서 '?' 문자로 표시된 입력 항목을 가리키는 말이다. 입력 항목의 값은 SQL 문을 실행하기 전에 setXXX() 메서드를 호출하여 설정한다.

입력 매개변수 타입이 문자열 -> setString()

입력 매개변수 타입이 정수형 -> setInt()

입력 매개변수 타입이 날짜형 -> setDate()

입력 매개변수의 번호는 배열의 인덱스와 달라 0부터 시작하지 않고 1부터 시작한다. 순서에 상관없이 설정할 수 있지만 순서대로 하는 것이 좋다.

SQL 질의 수행

SQL 문을 준비하고 입력 매개변수에 값을 할당했으면 데이터베이스에 질의하는 일만 남았다. INSERT처럼 결과 레코드를 만들지 않는 DDL이나 DML 종류의 SQL 문을 실행할 때는 executeUpdate()를 호출한다.

회원 등록 테스트

Chapter04(2)-2

Chapter04(2)-3

Chapter04(2)-4