Programmer's Progress

ServletContext, ServletConfig 를 활용하여 DB 데이터 요청하기 본문

Servlet + JSP/Self Learning

ServletContext, ServletConfig 를 활용하여 DB 데이터 요청하기

Blanc et Noir 2021. 7. 2. 21:32

  ServletContext 클래스는 톰캣 컨테이너 실행 시에 각 콘텍스트마다 하나의 객체가 생성된다.

톰캣 컨테이너가 종료되면 이 객체가 소멸되는데, 이 객체를 통해 웹 애플리케이션의 모든 서블릿들이

자원이나 정보를 미리 바인딩해서 공유하여 사용할 수 있도록 한다.

쉽게 말해서 전역변수를 선언하는 것과 비슷한 효과를 얻을 수 있다.

 

  반면 ServletConfig 클래스는 각 서블릿 객체들마다 생성되는 클래스다. 즉, 각 서블릿은 고유한 ServletConfig

객체를 가지며, 지역변수처럼 데이터를 읽어 들일 수 있게끔 한다. 이 클래스는 데이터를 초기화할 때 주로 사용한다.

이렇게 글로만 나열해둔 정보로는 도대체 어떻게 동작하는지 잘 알수가 없었다. 직접 사용해 필요성을 느끼기로 했다.

 

LoginServlet 클래스

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
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({ "/LoginServlet", "/login" })
public class LoginServlet extends HttpServlet {
	ServletConfig config;
	ServletContext context;
	UserDAO dao = new UserDAO();
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		this.config = config;
		context = config.getServletContext();
	}

	public void destroy() {
		// TODO Auto-generated method stub
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doHandle(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doHandle(request, response);
	}
	protected void doHandle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();

		ArrayList<UserVO> list = dao.getList(context.getInitParameter("col1"), context.getInitParameter("col2"));
		
		for(int i=0; i<list.size(); i++) {
			System.out.println(list.get(i).user_id+" : "+list.get(i).getUser_pw());
		}
		out.close();
	}
}

LoginServlet 클래스는 UserDAO클래스를 통해 DB에 기록된 로그인 정보들을 얻어온다.

 

이때 중요한 것은, 초기화를 위해서 web.xml 파일에는 아래와 같이 구성되어 있는데

<param-name>태그의 내용에 유의하도록 하자. key값은 col1, col2이며 각각 value값이 user_id, user_pw이다.

이는 DB의 컬럼이름과 동일하다.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
	<context-param>
		<param-name>col1</param-name>
		<param-value>user_id</param-value>
	</context-param>
		<context-param>
		<param-name>col2</param-name>
		<param-value>user_pw</param-value>
	</context-param>
</web-app>

 

실제 DB의 컬럼을 확인하면 user_id, user_pw로 지정되어있다.

 

저런 식으로 web.xml파일에 초기화와 관련된 선언을 하거나, 어노테이션을 이용하는 경우에는

getInitParameter(String string) 메소드를 통해 그 value값을 얻을 수 있다.

앞서 LoginServlet에서는 col1, col2라는 key값을 통해 user_id, user_pw라는 문자열 값을 얻었으며

이를 UserDAOgetList( ) 메서드의 인자로 전달하였다.

 

 

UserDAO 클래스

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.sql.DataSource;

public class UserDAO {
	ArrayList<UserVO> list = new ArrayList<>();
	DataSource ds;
	UserDAO(){
		try {
			Context con = new InitialContext();
			Context env = (Context) con.lookup("java:/comp/env");
			ds = (DataSource) env.lookup("jdbc/oracle");			
		} catch (NamingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public ArrayList<UserVO> getList(String col1, String col2){
		try {
			Connection con = ds.getConnection();
			PreparedStatement pstmt = con.prepareStatement("select "+col1+", "+col2+" from t_user");
			ResultSet rs = pstmt.executeQuery();
			while(rs.next()) {
				UserVO user = new UserVO(rs.getString(col1),rs.getString(col2));
				list.add(user);
			}
			con.close();
			pstmt.close();
			rs.close();
			return list;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return list;
	}
}

 

DataSource, ConnectionPool 등을 이용해 DB와 연동한 후에, 로그인 정보를 요청하고 있다.

이때 수행하고자 하는 쿼리문을 보면 다음과 같다.

 

PreparedStatement pstmt = con.prepareStatement("select "+col1+", "+col2+" from t_user");

얻어오고자 하는 칼럼의 값이 col1, col2 String참조 변수로 지정되어 있다.

 

이렇게 복잡하게 구성하면 도대체 어떤 이점이 있는 걸까?

 

바로 DB에서 칼럼명이 바뀌더라도, web.xml 파일에서 그 칼럼명만 수정하면 전체 소스코드를 수정할 필요가

줄어들게 된다. 즉, 유지보수 면에서 뛰어나다는 것이다.

 

생각해보자, 만약 지금과 같이 구현하지 않고, 일일이 "user_id", "user_pw"같이 getList( ) 메서드의 내용을

채워 넣었더라면, 지금이야 간단한 소스코드지만, 소스코드가 복잡하거나, 수십 개의 칼럼명이 바뀌고

수백 개의 서블릿이 존재한다면... 이 소스코드를 일일이 수정하는 것은 고된 노동일 것이다...

 

어노테이션이나 web.xml파일에 미리 선언하지 않고, 동적으로 설정하는 경우도 존재한다.

이때는 서블릿 간 데이터를 포워딩할 때 사용하던 바인딩 방식처럼 setAttribute( ) 메서드와 getAttribute( ) 메서드를

활용하면 된다.

Comments