콘트롤 서블릿클래스와 DAO 클래스에서 매번 database 연동 Connection 객체나 DAO 객체를 생성하면 많은 가비지(garbage)가 생성되서 반응시간이 길어지는 단점이 있습니다.


그래서 DAO 처럼 여러 서블릿에서 사용하는 객체는 서로 공유하게 하는것이 좋습니다.

그래서  웹 어플리케이션이 시작될때 이러한 객체들을 미리 준비하고 공유할 수 있게 하는것을 설명하겠습니다. 





1

서블릿 컨테이너는 웹 애플리케이션에서 사건(웹 애플리케이션 시작or 종료)이 발생하면

웹 애플리케이션에 등록된 이벤트 리스너에서 아래와 같은 관련된 메소드를 호출합니다.


웹 애플리케이션이

시작되면 contextInitialized() 함수가 실행되고

종료되면 contextDestroyed() 함수가 실행됩니다.

이런 호출되는 함수의 규칙을 정의한게 ServletContextListener 인터페이스 입니다.

그래서 아래와 같이 








3번

ContextLoaderListener 클래스를 만들고 ServletContextListener 인터페이스를 구현합니다.


그럼 애플리케이션이 시작(사건발생)될때 처리해주고 싶은 부분을

ContextLoaderListener 클래스에서 contextInitialized() 함수가 실행될거고

그 함수 안에서 원하는 처리를 해주면 애플리케이션이 실행될때마다 원하는 처리가 실행되겠죠

원하는 처리는Dao 객체와 같은 서블릿들이 공유하는 객체를 준비해 할겁니다.


리스너를 컨테이너에 배치 해야 하는데 방법은 

아래 이미지처럼 


<listener>

 <listener-class>페키지명.클래스명</listener-class>

<listener>

처럼 선언해 주거나


ContextLoaderListener 클래스에서 애노테이션 @WebListener 를 사용해도 됩니다.




우선 ContextLoaderListener 클래스를 만들고 servletContextListener 인터페이스를 구현합니다.


------------------------------------------

 @Override

  public void contextInitialized(ServletContextEvent event) {

    try {

      ServletContext sc = event.getServletContext();


      Class.forName(sc.getInitParameter("driver"));

      conn = DriverManager.getConnection(

          sc.getInitParameter("url"),

          sc.getInitParameter("username"),

          sc.getInitParameter("password"));


      MemberDao memberDao = new MemberDao();

      memberDao.setConnection(conn);


      sc.setAttribute("memberDao", memberDao);


    } catch(Throwable e) {

      e.printStackTrace();

    }

  }

--------------------------------
오버라이드 받은 contextInitialized() 함수안에 위 코드처럼 데이터베이스 연동과 DAO 객체를 준비합니다. 
servletContext 저장소인 sc 객체에 저장을 하면 서블릿 클래스에서 사용할 수 있습니다.

그럼 사용할 서블릿 클래스에서

ServletContext sc = this.getServletContext();

MemberDao memberDao = (MemberDao)sc.getAttribute("memberDao");


를 사용하여 리스너에서 Connection 객체를 Dao(MemberDao)에 담은 Dao 객체를

꺼내 쓸 수 있습니다.


하지만 리스너에서 만든 공유객체는 하나의 Connection 객체에서 롤백해줘야 하기 때문에
한곳에서 롤백이 일어나면 다른 모든 작업도 롤백이 되는 문제가 있습니다.

이런 문제를 해결하기 위한것이 DB 커넥션풀입니다.















MVC 모델패턴에서 Model 부분 만들기


Model : 컨트롤러(서블릿)에서 database(mysql) 와 관련된 입출력 처리기능을 분리한 개념이다.


우선 MVC 구조를 보자



Model, View, Controller 형태인 MVC 패턴을


 서블릿, DAO, JSP 페이지로 매핑을 하면 아래와 같다.



  다시 책 예제와 매핑을 하면 아래와 같다.


      




흐름에 대한 설명은 책 378 page 참고




DAO 클래스를 만들고 데이터베이스 연동코드를 옮겨둡니다.

[예시) 회원목록 열람기능]

 public List selectList() throws Exception {
    Statement stmt = null;
    ResultSet rs = null;

    try {
      stmt = connection.createStatement();
      rs = stmt.executeQuery(
          "SELECT MNO,MNAME,EMAIL,CRE_DATE" + 
              " FROM MEMBERS" +
          " ORDER BY MNO ASC");

      ArrayList members = new ArrayList();

      while(rs.next()) {
        members.add(new Member()
        .setNo(rs.getInt("MNO"))
        .setName(rs.getString("MNAME"))
        .setEmail(rs.getString("EMAIL"))
        .setCreatedDate(rs.getDate("CRE_DATE"))	);
      }
      return members;
    } 
  }


위 코딩과 같이 DAO클래스 selectList() 함수 호출을 함으로써

데이터베이스 입출력 기능을 구현합니다.


12번째 줄에서 ArrayList 저장공간 [members] 에 


14번~9번 코드에서 값을 저장한후

21번 코드에서 쿼리 결과가 담긴 members 객체를 return 합니다.



그럼 서블릿에서는

request.setAttribute("members", memberDao.selectList());
RequestDispatcher rd = request.getRequestDispatcher("/member/MemberList.jsp");
rd.include(request, response);



1번 라인에서 2번째 파라미터 결과값이

DAO에서 처리결과물이다. 이 결과물을

members 이름으로 request 에 다시 저장합니다.

(view 에서 이 결과값을 사용하기 위해)


그후 페이지 출력을 위해 2,3번 라인에서

include를 request와 response를 인자로 보내고

페이지 결과값을 브라우저에게 보냅니다.
















GET과 POST 방식이 조금 달라요ㅎ

(방식이 다른이유는  GET방식의 경우 파라미터값을 URL 주소와 함께 오기 때문에 조금 달라요) 


POST 방식 인코딩 처리


POST방식은 URL 뒷부분이 아닌 몸통(데이터 영역)에서 파라미터값이 전달 되기 때문에 

setCharacterEncoding 함수로 처리해 주면 됩니다ㅎ

request.setCharacterEncoding("utf-8");
String name = request.getParameter("name");




GET 방식 인코딩처리  


우선  GET방식에서 속성(파라미터)값이 전달 될때는 URL 과 함께 전달 되기 때문에


POST 방식처럼 바로 인코딩 함수로 처리가 힘들어요ㅎ 

GET 방식은 2가지 방법으로 인코딩 처리를 할 수 있어요.


1방법

톰캣설치디렉터리/conf/seraver.xml 파일 또는 아래 화면과 같이 개발도구에서 [빨간네모] 부분인

server.xml 에서 

 
<Connector port="8080" protocol="HTTP/1.1"
  				ConnectionTimeout="20000"
  				redirectPort="8443"/>






<Connector>태그에서 useBodyEncodingForURI 속성값을  true 로 추가해주세요.



<Connector port="8080" protocol="HTTP/1.1"
  				ConnectionTimeout="20000"
  				redirectPort="8443"
      useBodyEncodingForURI="true" />



useBodyEncodingForURI 속성값이 true 가 되면 GET방식으로 값을 가져올때 request.setCaharacterEncoding() 메서드로 케릭터 셋이 적용할 수 있어요ㅎ



그후 GET방식으로 파라미터값을 가져올때

request.setCharacterEncoding("utf-8");

String name = request.getParameter("name");   


이런식으로 읽어올 수 있어요 ㅎ


2번째 방식

server.xml 파일에서  useBodyEncodingForURI 속성 대신

URIEncoding 속성을 사용 할 수 있어요

<Connector port="8080" protocol="HTTP/1.1"
  				ConnectionTimeout="20000"
  				redirectPort="8443"
      URIEncoding="true" />



 

URIEncoding 속성을 사용할 경우 GET방식으로 파라미터 값을 읽을때 항상 이 속성에서 지정한

값으로 처리를 해주죠 대신 2번째 방법을 하시면 setCharacterEncoding 은 적용되지 않아요

  String name = request.getParameter("name");


바로 이런식으로 사용하시면 되는거죠









JSP 자바 코딩에서 다양한 url 주소 가져오는 함수를정리할게요 ㅎ

 

프로젝트 Path만 가져옵니다.

request.getContextPath() 

예)  http://localhost:8080/project/list.jsp

[return]/project 

 

프로젝트 + 파일경로까지 가져옵니다.

request.getRequestURI() 

예)  http://localhost:8080/project/list.jsp

[return]        /project/list.jsp  

String url = request.getRequestURI.split("/");

String Name = url[url.length -1];       // list.jsp

 

전체 경로를 가져옵니다. 

request.getRequestURL()

예) http://localhost:8080/project/list.jsp

[return]   http://localhost:8080/project/list.jsp

 

파일명만 가져옵니다.

request.ServletPath() 

예) http://localhost:8080/project/list.jsp

[return] /list.jsp

 

서버 or 로컬 웹 애플리케이션 절대결로 가져옵니다. 

request.getRealPath() 

예) http://localhost:8080/projectname/list.jsp

[return]         c:\project\webapps\projectname\

 
 

 

 
 

'프로그래밍 > JSP' 카테고리의 다른 글

servletContextListener 만들기  (0) 2015.05.21
DAO 만들기  (0) 2015.05.21
GET방식 POST방식 인코딩 처리하기  (2) 2015.04.05

+ Recent posts