서블릿 초기화 매개변수과 컨텍스트 초기화 매개변수

서블릿 초기화 매개변수란 서블릿을 생성하고 초기화할 때, 즉 init()을 호출할 때 서블릿 컨테이너가 전달하는 데이터이다. 보통 데이터베이스 연결 정보와 같은 정적인 데이터를 서블릿에 전달할 때 사용한다.

서블릿 초기화 매개변수는 DD파일(web.xml)의 서블릿 배치 정보에 설정할 수 있고, 애노테이션을 사용하여 서블릿 소스 코드에 설정할 수 있다.

서블릿 초기화 매개변수는 그 매개변수가 선언된 서블릿에서만 사용될 수 있으므로 다른 서블릿은 참조할 수 없다. 따라서 JDBC 드라이버와 데이터베이스 연결 정보에 대한 초기화 매개변수를 각 서블릿마다 별도로 설정해 주어야 한다. 이 작업은 매우 번거롭고 낭비적이므로 컨텍스트 초기화 매개변수를 사용하면 된다. 컨텍스트 초기화 매개변수는 같은 웹 어플리케이션에 소속된 서블릿들이 공유하는 매개변수이다.

여기에서는 컨텍스트 초기화 매개변수를 활용해 보겠다.

회원 목록 페이지에 상세 정보 링크 추가

src/spms/servlet/MemberListServlet.java

while(rs.next()) {
        out.println(
        rs.getInt("MNO") + "," +
        "<a href='update?no=" + rs.getInt("MNO") + "'>" +
        rs.getString("MNAME") + "</a>," +
        rs.getString("EMAIL") + "," + 
        rs.getDate("CRE_DATE") + "<br>"
    );
}

회원 상세 정보 링크의 URL은 'update'이다.

DD파일에 컨텍스트 초기화 매개변수 설정

   <!-- 컨텍스트 초기화 파라미터 -->
    <context-param>
        <param-name>driver</param-name>
        <param-value>com.mysql.jdbc.Driver</param-value>
    </context-param>
    <context-param>
        <param-name>url</param-name>
        <param-value>jdbc:mysql://localhost/practicedb</param-value>
    </context-param>
    <context-param>
        <param-name>username</param-name>
        <param-value>study</param-value>
    </context-param>
    <context-param>
        <param-name>password</param-name>
        <param-value>1111</param-value>
    </context-param>

위처럼 소스 파일 밖에 DB 정보를 두면 나중에 DB정보가 바뀌더라도 web.xml만 편집하면 되므로 유지보수가 쉬워진다.

회원 상세 정보를 출력하는 서블릿 작성

src/spms/servlet/MemberUpdateServlet.java

@SuppressWarnings("serial")
@WebServlet("/member/update")
public class MemberUpdateServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;

        try {
            ServletContext sc = this.getServletContext();
            Class.forName(sc.getInitParameter("driver"));
            conn = DriverManager.getConnection(
                    sc.getInitParameter("url"),
                    sc.getInitParameter("username"),
                    sc.getInitParameter("password"));

            stmt = conn.createStatement();
            rs = stmt.executeQuery(
                    "SELECT MNO,EMAIL,MNAME,CRE_DATE FROM MEMBERS" +
                            " WHERE MNO=" + req.getParameter("no"));
            rs.next();

            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='update' method='post'>");
            out.println("번호: <input type='text' name='no' value='" +
                    req.getParameter("no") + "' readonly><br>");
            out.println("이름: <input type='text' name='name'" +
                    " value='" + rs.getString("MNAME")  + "'><br>");
            out.println("이메일: <input type='text' name='email'" +
                    " value='" + rs.getString("EMAIL")  + "'><br>");
            out.println("가입일: " + rs.getDate("CRE_DATE") + "<br>");
            out.println("<input type='submit' value='저장'>");
            out.println("<input type='button' value='삭제' "
                    + "onclick='location.href=\"delete?no=" +
                    req.getParameter("no") + "\";'>");
            out.println("<input type='button' value='취소'" +
                    " onclick='location.href=\"list\"'>");
            out.println("</form>");
            out.println("</body></html>");

        } catch (Exception e) {
            throw new ServletException(e);
        } finally {
            try {if (rs != null) rs.close();} catch(Exception e) {}
            try {if (stmt != null) stmt.close();} catch(Exception e) {}
            try {if (conn != null) conn.close();} catch(Exception e) {}
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        Connection conn = null;
        PreparedStatement stmt = null;
        try {
            ServletContext sc = this.getServletContext();
            Class.forName(sc.getInitParameter("driver"));
            conn = DriverManager.getConnection(
                    sc.getInitParameter("url"),
                    sc.getInitParameter("username"),
                    sc.getInitParameter("password"));
            stmt = conn.prepareStatement(
                    "UPDATE MEMBERS SET EMAIL=?,MNAME=?,MOD_DATE=now()"
                            + " WHERE MNO=?");
            stmt.setString(1, req.getParameter("email"));
            stmt.setString(2, req.getParameter("name"));
            stmt.setInt(3, Integer.parseInt(req.getParameter("no")));
            stmt.executeUpdate();

            resp.sendRedirect("list");

        } 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) {}
        }
    }

ServletContext

컨텍스트 초기화 매개변수의 값을 얻으려면 ServletContext 객체가 필요하다. HttpServlet으로부터 상속받은 getServletContext()를 호출하여 ServletContext 객체를 준비한다.

ServletContext sc = this.getServletContext();

이 객체를 통해 getInitParameter()를 호출하면 web.xml에 선언된 컨텍스트 초기화 매개변수 값을 얻을 수 있다.

초기화 매개변수를 이용하여 JDBC 드라이버 로딩

이전 방식

이전 예제에서는 다음과 같이 직접 드라이버 클래스의 인스턴스를 생성하여 JDBC 드라이버를 등록했다.

DriverManager.registerDriver(new com.mysql.jdbc.Driver());

클래스 로딩

Class.forName()을 사용하여 JDBC 드라이버 클래스, 즉 java.sql.Driver를 구현한 클래스를 로딩한다.

Class.forName(/* JDBC 드라이버 클래스의 이름 */)

Class.forName()은 인자값으로 클래스 이름을 넘기면 해당 클래스를 찾아 로딩한다. 클래스 이름은 반드시 패키지 이름을 포함해야 한다. 보통 영어로 'fully qualified name' 또는 'QName' 이라고 표현한다.

컨텍스트 초기화 매개변수의 값 꺼내기

sc.getInitParameter(/* 매개변수 이름 */)

getInitParameter()는 배치 정보가 있는 web.xml로부터 컨텍스트 초기화 매개변수의 값을 꺼내 준다.

getInitParameter -> com.mysql.jdbc.Driver

("driver") -> driver

이렇게 초기화 매개변수를 이용하면 유지 보수가 쉽고 드라이버를 바꾸고 싶을 때 간단히 web.xml만 변경하면 된다.