반응형
반응형

내장객체

1. out : 페이지 내용을 담고 있는 출력 스트림 객체

2. request : 파라미터를 포함한 요청정보를 담고 있는 객체

3. response : 요청에 대한 응답을 담고있는 객체

4. session : 세션 정보를 담고 있는 객체

5. application : 어플리케이션 Context의 모든 페이지가 공유할 데이터를 담고 있는 객체

6. pageContext : 페이지 실행에 필요한 Context정보를 담고있는 객체

7. page : JSP페이지의 서블릿 객체

8. config : JSP페이지의 서블릿 설정 데이터 초기화 정보객체

9. exception : JSP페이지의 서블릿 실행시 처리하지 못한(에러발생) 예외 객체

 

★★★ request, session, application, pageContext 내부객체는 임의의 속성값(attribute)을 저장하고 읽을 수 있는 메서드를 제공한다.

 

setAttribute(String key, Object value) : 주어진 key에 속성값을 연결한다.
getAttribute(String key) : 주어진 key에 대한 속성값을 얻는다.
removeAttribute(String key) : 주어진 key에 연결된 속성값을 제거한다.
getAttributeNames() : 모든 속성의 이름을 얻어낸다.

. JSP페이지에 관련된 객체 : page, config
. 페이지 입출력 관련된 객체 : request, response, out
. 컨텍스트에 관련된 객체 : session, application, pageContext
. 에러에 관련된 객체 : exception

 

〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓
★ out 내장 객체 Method
1. isAutoFlush() : 출력 버퍼가 가득찼을 때 자동으로 밀어낼 것인지 여부 지정 (true/fasle)
2. getBufferSize() : 출력 버퍼 전체 size를 구함
3. getRemaining() : 출력 버퍼중 남아있는 size를 구함
4. clearBuffer() : 출력 버퍼를 비운다.
5. println() : String을 출력한다.
6. flush() : 출력 버퍼 내용을 밀어낸다.
7. close() : 출력 버퍼 내용을 밀어 내고, 출력 버퍼를 닫는다.

 

〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓
★ request 내장 객체 메서드
1. getMethod() : 요청 방식 알아내기 (get, post)
2. getRequestRUI() : 요청 파일 경로 알아내기 (예: jsp2/RequestTest.jsp)
3. getRequsetURL() : 요청 경로 알아내기 (예: http://localhost:9000/jsp2/Request.jsp)

4. getRemoteHost() : 클라이언트 호스트 이름 알아내기
5. getRemoteAddr() : 클라이언트 주소 알아내기
6. getRemoteUser() : (인증을 이용한 경우) 이용자 ID 알아내기

7. getProtocol() : 사용중인 프로토콜 알아내기(HTTP1.1)
8. getServerName() : 서버 도메인 이름 알아 내기
9. getServerPort() : 서버 Port 알아내기

10. getHeader(name) : name에 해당하는 요청 헤더 항목 값을 알아내기

11. getParameter(name) : name에 해당하는 파라미터값 얻는다.
12. getParameterValues(name) : name에 해당하는 파라미터값을 모두 얻는다.
13. getParameterNames() : form에 있는 모든 파라미터 이름을 얻는다.

 

〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓
★ response 내장 객체 메서드
1. setContentType(type) : 출력 문서의 contentType 설정
2. getCharacterEncoding() : 문자 인코딩 설정 내용 알아내기
3. setHeader(name, value) : 응당 헤더 설정
   예: response.setHeader("Refresh", "3;URL=http://www.daum.net");//3초후 URL로 이동
4. sendRedirect("url") : 지정 url로 요청을 재전송한다.
   예: response.sendRedirect("로컬URL");
       response.sendRedirect("외부URL");

 

※ response.sendRedirect와 forward 액션태그 차이점
  - sendRedirect()는 웨브라우저가 다른 페이지로 이동하는덷 이때 다른 페이지로 가기의해 웹 브라우저는 웹서버에 새로운 Http요청을 보낸다. 즉, TCP네트워크 연결이 다시 만들어 지는 것이다.

 - 이제 비해 forward액션은 JSP엔진에서 Http요청을 다른 페이지로 보내는 것이다. 즉, Http요청 처음 만들어진 것 하나만 있는 것이다. 이것은 중요한 의미를 갖는다.
    cf) <jsp:forward page="로컬URL"/>
         <jsp:forward page="외부URL"/> --안됨!! 

 - sendRedirect()는 사용하면 웹브라우저에서 처음에 전송한 Http요청과 이 요청에 포함된 데이터들은 새로 이동된 페이지에서 사용할 수 없게 된다. 반면에 forward액션을 사용하면 Http요청은 하나만 사용하기 때문에 새로 이동된 페이지에서도 클라이언트에서 전송된 데이터를 사용할 수 있다.

 

※ forward액션 태그
   방법1 <jsp:forward page="로컬URL"/> = <jsp:forward page="로컬URL"></jsp:forward>
   방법2 <jsp:forward page="로컬URL">
               <jsp:param name="id" value="kim"/>
               <jsp:param name="pwd" value="123"/>
            </jsp:forward>


※ include지시자(디텍티브)

   <%@ include file ="파일명.확장자" %>
                              name.txt
                              aa.html
                              bb.jsp <- 현재 JSP페이지에 포함할 문서
        *include지시자는 단순히 문서를 포함시킨다. 포함시킬 문서는 헤더부분 넣지 말아야한다.

※ include액션
   *include앤셕 실행될 결과물을 현재페이지에 포함시킨다.
   <방법1>
      <jsp:include page="로컬URL" flush="true"/>
   <방법2>
      <jsp:include page="로컬URL" flush="true"/>
          <jsp:param name=" " value=" "/>
          <jsp:param name=" " value=" "/>
          .....

      </jsp:include>

 

〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓
★ application 내장 객체 메서드
 application 내장 객체는 서블릿 또는 어플리케이션 외부환경정보(context)의 내부객체입니다.
 application은 javax.servlet.ServletContext의 객체이다.

<Method>
1. String getServletInfo() : 서버 정보를 구한다.(웹 컨테이너이름과 버전, 즉 JSP컨테이너에 대한 정보)
2. String getMimeType(fileName) : fileName대한 MIME타입을 리턴한다.
  예) String str = request.getParameter("filename");
      String contentType = application.getMimeType(str);
3. String getMajorVersion() : 서버가 지원하는 서블릿규약의 Major version을 리턴한다.(정수부분)
4. String getMinorVersion() : 서버가 지원하는 서블릿규약의 Minor version을 리턴한다.(소수부분)

5. String getRealPath(url) : 지정 URL의 실제 경로를 리턴한다.
6. void log("message") : message내용을 file에 기록한다.

〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓
--myroot\WEB-INF\web.xml--
<context-param>
 <description>로깅여부</description>
 <param-name>logEnabled</param-name> <!-- 이름이 logEnabled이고 값이 true인 초기화 파라미터 추가 -->
 <param-value>true</param-value>
</context-param>
 
<context-param>
 <description>로깅레벨</description>
 <param-name>debugLevel</param-name> <!-- 이름이 debugLevel이고 값이 5인 초기화 파라미터 추가-->
 <param-value>5</param-value>
</context-param>

 

〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓
★ Cookie 내장 객체 생성자 &메서드
생성자
- Cookie(name, value) 이름이 name이고, 값이 value인 쿠키를 생성

메서드
 setter method or setXXX()
- setValue() : 쿠키값 설정
  setDomain() : 쿠키에 전달되는 도메인 설정
  setPath() : 쿠키에 전달되는 경로 설정
  setMaxAge() : 쿠키 나이 설정(쿠키 유효기간 설정<-초>)
  setSecure() : 보안 프로토콜(HTTPS)에서만 쿠키를 전달되도록 설정한다.
  
 getter method or getXXX()
- getName() : 쿠키이름 얻기
  getValue() : 쿠키값 얻기
  getDomain() : 쿠키가 전달되는 도메인 알아내기
  getPath() : 쿠키가 전달되는 경로 알아내기
  getMaxAge() : 쿠기 유효기간 알아내기
  getSecure() : 보안 프로토콜(HTTPS)에서만 쿠키가 전달되는지 알아내기

 <<쿠키를 생성해서 클라이언트 심는 방법>>
  Cookie cookie = new Cookie("쿠키이름", URLEncoder.encode("쿠키값"));
  response.addCookie(cookie); //쿠키심기
 
 <<클라이언트가 보내주는 쿠기를 모두 받아서 특정 이름의 쿠키값을 알아내기>>

 Cookie[] cookies = request.getCookies(0;
 if(cookies!=null){
         for(int i=0; i<cookies.length; i++){
                 if(cookies[i].getName().equals("쿠키이름")){
                         visiterName = URLDecoder.decode(cookies.getValue());
                         out.println("쿠키값 : " + visiterName);
                 }
         }
 }

 

〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓
★ session 내장 객체 메서드

- 세션은 쇼핑몰같은 구매 제품을 클릭할때마다 누가 클릭했는지 기억을 해야하는 사이트에서는
웹서버쪽에 사용자별 기록을 남겨야만 합니다.

 웹 서버쪽에 기억 시키는 것을 세션이라고 합니다.
 JSP에서는 session객체를 통하여 이용할 수 있습니다.

<< session객체 method >>
1. String getId() : 해당 세션의 고유한 세션의 ID를 리턴
2. void setMaxInactiveInterval(time) : 세션 유지 시간 설정(초단위)
3. int getMaxInacativeInterval() : 세션 유지 시간을 얻는다(기본 유지시간 30분)

4. isNew() : 새로 생성된 세션이면 true return
5. invalidate() : session를 제거

setAttribute(name, value) : session에 name, value값의 항목을 추가
getAttribute(name) : session에서 name에 해당하는 value값을 얻는다.

* HttpSession getSession() :
  1. getSession(true) : true는 새로운 세션을 create만 하는 것
  2. getSession(false) : false는 현재 세션을 그대로 리턴 하는 것
  3. getSession() : session존재 여부를 확인하여,
                    session이 없다면 새로 session을 create하고
                    session이 있다면 그대로 return
                    위 2개의 장점을 취한 것.

 

〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓
※JSP 액션
<jsp:useBeans> - JSP페이지에서 빈을 초기화 하는데 사용
<jsp:setProperty> - 빈의 property에 값을 넣어 주기 위해 사용
<jsp:getProperty> - 빈의 property의 앖을 가져오기 위해서 사용
<jsp:forward> - 처리를 분기할 때 사용
<jsp:include> - 처리 결과무를 포함 시킬 때 사용

지시자
<%@ page %>
<%@ include file="파일명" %>
<%@ taglib %>

[출처] JSP내장객체|작성자 신지c


반응형

게시판 연습

 

[여기서는 먼저 전 게시물의 JDBC 프로그래밍을 복습한 후에 내용을 보시기 바랍니다.]

 

JDBC 프로그래밍에서 실습한 GetEmp.java 순수 애플리케이션을 서블릿으로 바꾸고 실행해 보세요(servlet API 참고)

[참고] JDBC 드라이버 (ORACLE_HOME/jdbc/lib/classes12.jar, nls_charset12.jar)를 {애플리케이션홈}/WEB-INF/lib 에

복사합니다.

 

문제 1 답:

 

package example;

 

import java.sql.*;

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;


public class GetEmp extends HttpServlet {

         private String DB_URL;

         private String DB_USER;

         private String DB_PASSWORD;

        

         public void init(ServletConfig config) throws ServletException {

                  super.init(config);

                  //설치과정에서 자신이 정한 정보에 맞게 바꾼다.

                  DB_URL="jdbc:oracle:thin:@127.0.0.1:1521:orcl";

                  DB_USER="scott";

                  DB_PASSWORD="tiger";

                 

                  try {

                           //드라이버를 로딩합니다.

                           Class.forName("oracle.jdbc.driver.OracleDriver");

                  }catch(ClassNotFoundException e){

                           e.printStackTrace();

                  }

         }

 

         public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException,ServletException {

                  res.setContentType("text/html;charset=euc-kr");

                  PrintWriter out = res.getWriter();

                  Connection conn = null;

                  Statement stmt = null;

                  ResultSet rs = null;

                  String query="select * from emp";

                  try {

                           //데이터베이스의 연결을 설정합니다.

                           conn=DriverManager.getConnection(DB_URL,DB_USER,DB_PASSWORD);

                           //Statement를 가져온다.

                           stmt=conn.createStatement();

                           //SQL문을 실행합니다.

                           rs=stmt.executeQuery(query);

                           while(rs.next())  {

                                   String empno=rs.getString(1);

                                   String ename=rs.getString(2);

                                   String job=rs.getString(3);

                                   String mgr=rs.getString(4);

                                   String hiredate=rs.getString(5);

                                   String sal=rs.getString(6);

                                   String comm=rs.getString(7);

                                   String depno=rs.getString(8);

                                   //결과를 출력합니다.

                                    out.println(empno+" : "+ename+" : "+job+" : "+mgr+" : "+hiredate+" : "+sal+" : "+comm+" : "+depno+"<br>");

                           }

                  } catch (SQLException e) {

                           e.printStackTrace(out);

                  }

                  finally {

                           try{

                                   rs.close();

                                   stmt.close();

                                   conn.close();

                           }catch(SQLException e){}

                  }

         }

}


7369 : SMITH : CLERK : 7902 : 1980-12-17 00:00:00.0 : 800 : null : 20
7499 : ALLEN : SALESMAN : 7698 : 1981-02-20 00:00:00.0 : 1600 : 300 : 30
7521 : WARD : SALESMAN : 7698 : 1981-02-22 00:00:00.0 : 1250 : 500 : 30
7566 : JONES : MANAGER : 7839 : 1981-04-02 00:00:00.0 : 2975 : null : 20
7654 : MARTIN : SALESMAN : 7698 : 1981-09-28 00:00:00.0 : 1250 : 1400 : 30
7698 : BLAKE : MANAGER : 7839 : 1981-05-01 00:00:00.0 : 2850 : null : 30
7782 : CLARK : MANAGER : 7839 : 1981-06-09 00:00:00.0 : 2450 : null : 10
7788 : SCOTT : ANALYST : 7566 : 1987-04-19 00:00:00.0 : 3000 : null : 20
7839 : KING : PRESIDENT : null : 1981-11-17 00:00:00.0 : 5000 : null : 10
7844 : TURNER : SALESMAN : 7698 : 1981-09-08 00:00:00.0 : 1500 : 0 : 30
7876 : ADAMS : CLERK : 7788 : 1987-05-23 00:00:00.0 : 1100 : null : 20
7900 : JAMES : CLERK : 7698 : 1981-12-03 00:00:00.0 : 950 : null : 30
7902 : FORD : ANALYST : 7566 : 1981-12-03 00:00:00.0 : 3000 : null : 20
7934 : MILLER : CLERK : 7782 : 1982-01-23 00:00:00.0 : 1300 : null : 10

 

위와 같은 결과 화면을 웹 브라우저에서 확인하셨습니까?

GetEmp 서블릿의 57번째 줄에서 에러가 발생한다는 메시지를 보신다면 /bbs/WEB-INF/lib 에 classes12.jar 파일을 복사하지 않으셨거나 오라클이 가동중이 아니거나 리슨너가 가동중이 아니거나 한 경우입니다.

윈도우에서 오라클을 설치하셨다면 나중 2개는 무시하시고 JDBC 드라이버를 올바른 위치에 복사했는지 확인하시기 바랍니다.

 

문제 2 : 위 서블릿을 JSP로 바꾸어 보세요

 

문제 2 답: 파일명 getEmp.jsp

 

<%@ page contentType="text/html;charset=euc-kr" %>

<%@ page import="java.sql.*" %>

<%

         String DB_URL="jdbc:oracle:thin:@127.0.0.1:1521:orcl";

         String DB_USER="scott";

         String DB_PASSWORD="tiger";

         //설치과정에서 자신이 정한 정보에 맞게 바꾼다.

         try {

                  //드라이버를 로딩합니다.

                  Class.forName("oracle.jdbc.driver.OracleDriver");

         } catch(ClassNotFoundException e){

                           e.printStackTrace();

         }

 

         Connection conn = null;

         Statement stmt = null;

         ResultSet rs = null;

         String query="select * from emp";

         try {

                  //데이터베이스의 연결을 설정합니다.

                  conn=DriverManager.getConnection(DB_URL,DB_USER,DB_PASSWORD);

                  //Statement를 가져온다.

                  stmt=conn.createStatement();

                  //SQL문을 실행합니다.

                  rs=stmt.executeQuery(query);

                  while(rs.next()) {

                           String empno=rs.getString(1);

                           String ename=rs.getString(2);

                           String job=rs.getString(3);

                           String mgr=rs.getString(4);

                           String hiredate=rs.getString(5);

                           String sal=rs.getString(6);

                           String comm=rs.getString(7);

                           String depno=rs.getString(8);

                           //결과를 출력합니다.

                           out.println(empno+" : "+ename+" : "+job+" : "+mgr+" : "+hiredate+" : "+sal+" : "+comm+" : "+depno+"<br>");

                  }

         } catch (SQLException e) {

                  out.println("SQLException: " + e.getMessage());

         }

         finally {

                  try {

                           rs.close();

                           stmt.close();

                           conn.close();

                  } catch(SQLException e){}

         }

%>

 

문제 1 에서와 같은 결과를 확인했습니까?

문제1의 서블릿과 지금 JSP는 코드가 조금 다릅니다.

서블릿에서는 init 메소드에서 JDBC 드라이버에 대한 설정을 했습니다.

서블릿의 라이트 사이클에서 살펴 보았듯이 init 메소드안의 내용은 처음 사용자가 요청한 경우를 제외하고는 다음 요청 부터는 JDBC 드라이버 설정을 하지 않으므로 그렇지 않은 코드보다는 성능이 좋습니다.

JSP에서도 서블릿의 init 메소드와 같은 메소드가 있을 것입니다. 이것은 여러분이 찾아서 고치시기 바랍니다.

 

 

ConnectionPool 사용법

 

데이터베이스에 대한 Connection 을 관리하는 것은 매우 바람직한 일입니다.
왜냐하면 매 페이지마다 데이터베이스에 연결을 시도하는 것(= 커넥션 객체를 얻는것)은 시간이 많이 걸리는 작업입니다.
그럼에도 불구하고 위에서 우리는 Connection 을 얻은 후 사용 후 바로 자원을 반납했습니다
.

 

Database Connection Pool 이란 이전에 연결된 Connection 을 종료하지 않고 웹 클라이언트의 요구시 기존의 Connection을

통하여 데이터베이스에 접근할 수 있도록 하는 free Connection list 입니다.

즉, 시간이 오래 걸리는 커넥션 객체를 쓰고 난 다음에 리스트에서 넣고 관리하겠다는 의미입니다.

적절하게 리스트를 관리하면 시간을 절약하는데 크게 기여하게 하는 기법입니다.

 

. 전체 클래스 요약

 

Log.java
에러 메시지를 콘솔화면에 표시하기 위한 클래스입니다.

 

DBConnectionPoolManager.java

각 데이터베이스의 커넥션풀을 관리하기 위한 클래스입니다.

 

DBConnectionPool.java
DBConnectionPoolManager가 관리하는 데이터베이스당 가지는 커넥션 풀
실제로 이 클래스가 이미 생성된 커넥션을 관리
합니다.

 

ConnectionManager.java
DBConnectionPoolManager 클래스에 일을 시키는 클래스인데
여러 데이터베이스를 고려한 추상클래스입니다.
데이터베이스에 따라서 이 클래스를 상속받아 알맞는 클래스
를 만듭니다.

 

OracleConnectionManager.java 
데이터베이스 오라클을 사용하기 위해 ConnectionManager 클래스를 상속한 서브 클래스입니다.

 

oracle.properties
오라클 설정 파일입니다.
최대 커넥션 수, 초기 커넥션 수 등의 셋팅을 담당합니다.

이렇게 설정 내용을 코드가 아닌 파일에 저장하면 관리하기가 쉽습니다.

 

. 커넥션 풀 관련 소스

 

Log.java


package net.java_school.util;

 

import java.io.*;

import java.util.Date;

 

public class Log {

         public String dbgFile = "H:\\debug\\error.dbg"; // 윈도우  계열

         //public String dbgFile = "/debug/error.dbg"; // 유닉스 계열

 

         FileWriter fw = null;

         public Log() {

                  super();

                  try{

                           fw = new FileWriter(dbgFile, true);

                  }catch(IOException e){}

         }

 

         public void close() {

                  try{

                           fw.close();

                  }catch(IOException e){}

         }

 

         public void close(FileWriter fw) {

                  try{

                           fw.close();

                  }catch(IOException e){}

         }

 

         public void debug(String msg) {

                  try{

                           fw.write("-------------------------------------------------\r\n");

                           fw.write(new java.util.Date()+ " : ");

                           fw.write(msg + " \r\n");

                           fw.write("-------------------------------------------------\r\n");

                           fw.flush();

                  }catch(IOException e){

                           System.err.println("IOException.......!!");

                  }

         }

 

         public static void out(String msg) {

                  System.out.println(new Date() + ": "+msg);

         }

 

         public static void err(String msg) {

                  System.out.println(new Date() + ": "+msg);

         }

 

         public static void err(Throwable e,String msg) {

                  System.err.println(new Date() + ": "+msg);

                  e.printStackTrace(System.out);

         }

}


DBConnectionPool.java


package net.java_school.db.dbpool;


import java.util.*;
import java.sql.*;
import java.util.Date;
import net.java_school.util.Log;


// Connection Pool을 관리하는 클래스
class DBConnectionPool {
 
    // 현재 사용 중인 Connection 개수
    private int checkedOut;
 
    // Free Connection List
    private Vector freeConnections = new Vector();

    // Connection 최대 개수
    private int maxConn;

    // Connection 초기 개수
    private int initConn;

    // Waiting time (pool에 connection이 없을때 기다리는 최대시간)
    private int maxWait;

    // Connection Pool Name
    private String name;

    // DB Password
    private String password;

    // DB URL
    private String URL;

    // DB UserID
    private String user;

    // Constructor
    public DBConnectionPool(String name, String URL, String user, String password, int maxConn, int initConn, int waitTime) {
        this.name = name;
        this.URL = URL;
        this.user = user;
        this.password = password;
        this.maxConn = maxConn;
        this.maxWait = waitTime;
 
        for (int i = 0; i < initConn; i++) {
            freeConnections.addElement(newConnection());
        }
    }
 
    // Connection 반납
    // @param con : 반납할 Connection
    public synchronized void freeConnection(Connection con) {
        freeConnections.addElement(con);
        checkedOut--;
        // Connection을 얻기 위해 대기하고 있는 thread에 알림
        notifyAll();
    }
 
    // Connection 을 얻음
    public synchronized Connection getConnection() {
        Connection con = null;

        // Connection이 Free List에 있으면 List의 처음 것을 얻음
        if (freeConnections.size() > 0) {
            con = (Connection) freeConnections.firstElement();
            freeConnections.removeElementAt(0);
            try {
                // DBMS에 의해 Connection이 close 되었으면 다시 요구
                if (con.isClosed()) {
                    Log.err("Removed bad connection from " + name);
                    con = getConnection();
                }
            } // 요상한 Connection 발생하면 다시 요구
            catch (SQLException e) {
                Log.err(e, "Removed bad connection from " + name);
                con = getConnection();
            }
        } // Connection이 Free List에 없으면 새로 생성
        else if (maxConn == 0 || checkedOut < maxConn) {
            con = newConnection();
        }
        if (con != null) {
            checkedOut++;
        }
        return con;
    }
 
    // Connection을 얻음
    // @param timeout : Connection을 얻기 위한 최대 기다림 시간
    public synchronized Connection getConnection(long timeout) {
        long startTime = new Date().getTime();
        Connection con;

        while ((con = getConnection()) == null) {
            try {
                wait(timeout * maxWait);
            } catch (InterruptedException e) {}
            if ((new Date().getTime() - startTime) >= timeout) {
                // 기다림 시간 초과
                return null;
            }
        }
        return con;
    }
 
    // Connection 생성
    private Connection newConnection() {
        Connection con = null;

        try {
            if (user == null) {
                con = DriverManager.getConnection(URL);
            } else {
                con = DriverManager.getConnection(URL, user, password);
            }
            Log.out("Created a new connection in pool " + name);
        } catch (SQLException e) {
            Log.err(e,
                    "Can't create a new connection for " + URL + " user : "
                    + user + " passwd : " + password);
            return null;
        }
        return con;
    }
}



DBConnectionPoolManager.java


package net.java_school.db.dbpool;

 

import java.sql.*;

import java.util.*;

import net.java_school.util.Log;


public class DBConnectionPoolManager {

         // 인스턴스를 하나만 유지하기 위해 static 으로 선언

         static private DBConnectionPoolManager instance=null;

         //JDBC 드라이버 관리

         private Vector drivers = new Vector();

         // DB Connection Pool List

         private Hashtable pools = new Hashtable();

         // DBConnectionPoolManager의 instance를 얻음

         // @return DBConnectionManger

         static synchronized public DBConnectionPoolManager getInstance() {

                  if (instance == null) {

                           instance = new DBConnectionPoolManager();

                  }

                  return instance;

         }

        

         // Default Constructor

         private DBConnectionPoolManager() {}

 

         // 현재 Connection을 Free Connection List로 보냄

         // @param name : Pool Name

         // @param con : Connection

         public void freeConnection(String name, Connection con) {

                  DBConnectionPool pool = (DBConnectionPool) pools.get(name);

                  if (pool != null) {

                           pool.freeConnection(con);

                  }

                  Log.out("One Connection of " + name + " was freed");

         }

 

         // Open Connection을 얻음. 현재 열린 커넥션이 없고 최대 커넥션 개수가

         // 사용 중이 아닐 때는 새로운 커넥션을 생성. 현재 열린 커넥션이 없고

         // 최대 커넥션 개수가 사용 중일 때 기본 대기 시간을 기다림

         // @param name : Pool Name

         // @return Connection : The connection or null

         public Connection getConnection(String name) {

                  DBConnectionPool pool = (DBConnectionPool) pools.get(name);

                  if (pool != null) {

                           return pool.getConnection(10);

                  }

                  return null;

         }

 

         // Connection Pool을 생성

         // @param poolName : 생성할 Pool Name

         // @param url : DB URL

         // @param user : DB UserID

         // @param password : DB Password

         private void createPools(String poolName, String url, String user, String password, int maxConn, int initConn, int maxWait) {

                  DBConnectionPool pool = new DBConnectionPool(poolName, url, user, password, maxConn, initConn, maxWait);

                  pools.put(poolName, pool);

                  Log.out("Initialized pool " + poolName);

         }

 

         // 초기화 작업

         public void init(String poolName, String driver, String url, String user, String passwd, int maxConn, int initConn, int maxWait) {

                  loadDrivers(driver);

                  createPools(poolName, url, user, passwd, maxConn, initConn, maxWait);

         }

 

         // JDBC Driver Loading

         // @param driverClassName : 사용하고자 하는 DB의 JDBC 드라이버

         private void loadDrivers(String driverClassName) {

                  try {

                           Class.forName(driverClassName);

                           drivers.addElement(driverClassName);

                           Log.out("Registered JDBC driver " + driverClassName);

                  } catch (Exception e) {

                           Log.err(e, "Can't register JDBC driver: " + driverClassName);

                  }

         }

        

         public Hashtable getPools() {

                  return pools;

         }

        

         public int getDriverNumber() {

                  return drivers.size();

         }

}



ConnectionManager.java


package net.java_school.db.dbpool;

 

import java.sql.*;

import java.io.*;

import java.util.*;

import net.java_school.util.Log;

 

public abstract class ConnectionManager {

         protected DBConnectionPoolManager connMgr=null;

         protected String poolName, dbServer, dbName, port, userID, passwd;

         int maxConn,initConn, maxWait;

         private Properties dbProperties;

         private String configFile;

 

         public ConnectionManager(String pool) {

                  poolName = pool;

                  // mnd 컨텍스트 베이스에 config디렉토리에 Property파일이 있음을 가정

                  configFile = "F:\\apps\\tomcat\\webapps\\mnd\\config\\"+poolName+".properties";

                  try {

                           dbProperties = readProperties();

                           dbServer = getProperty( "dbServer" );

                           port = getProperty( "port" );

                           dbName = getProperty( "dbName" );

                           userID = getProperty( "userID" );

                           passwd = getProperty( "passwd" );

                           maxConn = Integer.parseInt(getProperty("maxConn"));

                           initConn = Integer.parseInt(getProperty("initConn"));

                           maxWait = Integer.parseInt(getProperty("maxWait"));

                  } catch( IOException ioe ) {

                           Log.err( "Error reading properties of " + configFile);

                  }

         }

 

         public Connection getConnection() {

                  return (connMgr.getConnection(poolName));

         }

 

         public void freeConnection(Connection conn) {

                  connMgr.freeConnection(poolName,conn);

         }

 

         private String getProperty( String prop ) throws IOException {

                  return ( dbProperties.getProperty( prop ) );

         }

 

         protected synchronized Properties readProperties() throws IOException {

                  Properties tempProperties = new Properties();

                  FileInputStream in = new FileInputStream(configFile);

                  tempProperties.load(in);

                  return tempProperties;

         }

        

         public int getDriverNumber() {

                  return connMgr.getDriverNumber();

         }

}


OracleConnectionManager.java


package net.java_school.db.dbpool;

 

public class OracleConnectionManager extends ConnectionManager {

         public OracleConnectionManager() {

                  super("oracle");

                  String JDBCDriver = "oracle.jdbc.driver.OracleDriver";

                  // 오라클용 JDBC thin driver

                  String JDBCDriverType = "jdbc:oracle:thin";

                  String url = JDBCDriverType+":@"+dbServer + ":" + port + ":" + dbName;

                  connMgr = DBConnectionPoolManager.getInstance();

                  connMgr.init(poolName, JDBCDriver, url, userID, passwd, maxConn, initConn, maxWait);

         }

}

 

oracle.properties

 

#########################################
# Database Connection Properties for Oracle 9i
#########################################

# Database Server Name OR IP address
dbServer=127.0.0.1

# The port number your DB server listents to.
port=1521

# Database Name
dbName=ORCL

# Database User
userID=scott

# Database Password
passwd=tiger

# Maximum Connection Number
maxConn=20

# Inital Connection Number
initConn=5

# Maximum Wait Time
maxWait=5

 

문제 1

getEmp.jsp 를 ConnectionPool을 이용하게 고쳐보세요

 

 

getEmpWithPool.jsp

 

<%@ page contentType="text/html;charset=euc-kr" %>

<%@ page import="java.sql.*, net.java_school.db.dbpool.*" %>

<jsp:useBean id="dbmgr" class="net.java_school.db.dbpool.OracleConnectionManager" scope="application" />

<%

Connection conn = null;

Statement stmt = null;

ResultSet rs = null;

String query="select * from emp";

try {

          //데이터베이스의 연결을 설정합니다.커넥션풀 이용

          conn=dbmgr.getConnection();

          //Statement를 가져온다.

          stmt=conn.createStatement();

          //SQL문을 실행합니다.

          rs=stmt.executeQuery(query);

          while(rs.next()) {

                   String empno=rs.getString(1);

                   String ename=rs.getString(2);

                   String job=rs.getString(3);

                   String mgr=rs.getString(4);

                   String hiredate=rs.getString(5);

                   String sal=rs.getString(6);

                   String comm=rs.getString(7);

                   String depno=rs.getString(8);

                   //결과를 출력합니다.

                   out.println(empno+" : "+ename+" : "+job+" : "+mgr+" : "+hiredate+" : "+sal+" : "+comm+" : "+depno+"<br>");

          }

} catch (SQLException e) {

         out.println("SQLException: " + e.getMessage());

} finally {

         try {

                  rs.close();

                  stmt.close();

                  dbmgr.freeConnection(conn);

         } catch(SQLException e){}

}

%>

 

문제 2 : 위 파일을 로그 클래스(Log.java)를 이용해서 SQLException이 일어날때 이를 로그 파일(error.dbg)에 기록하게 고치세요

 

: getEmpWithPooldbg.jsp

 

<%@ page contentType="text/html;charset=euc-kr" %>

<%@ page import="java.sql.*, net.java_school.db.dbpool.*, net.java_school.util.*" %>

<jsp:useBean id="dbmgr" class="net.java_school.db.dbpool.OracleConnectionManager"

scope="application" />

<%

Log log = new Log();

Connection conn = null;

Statement stmt = null;

ResultSet rs = null;

String query="select * from emp";

try {

         //데이터베이스의 연결을 설정합니다.커넥션풀 이용

         conn=dbmgr.getConnection();

         //Statement를 가져온다.

         stmt=conn.createStatement();

         //SQL문을 실행합니다.

         rs=stmt.executeQuery(query);

         while(rs.next()) {

                  String empno=rs.getString(1);

                  String ename=rs.getString(2);

                  String job=rs.getString(3);

                  String mgr=rs.getString(4);

                  String hiredate=rs.getString(5);

                  String sal=rs.getString(6);

                  String comm=rs.getString(7);

                  String depno=rs.getString(8);

                  //결과를 출력합니다.

                  out.println(empno+" : "+ename+" : "+job+" : "+mgr+" : "+hiredate+" : "+sal+" : "+comm+" : "+depno+"<br>");

         }

} catch (SQLException e) {

         log.debug("Error Source:getEmpWithPooldbg.jsp : SQLException");

         log.debug("SQLState : " + e.getSQLState());

         log.debug("Message : " + e.getMessage());

         log.debug("Oracle Error Code : " + e.getErrorCode());

         log.debug("Query : " + query);

} finally {

         try {

                  rs.close();

                  stmt.close();

                  dbmgr.freeConnection(conn);

                  log.close();

         } catch (SQLException e){}

}

%>

 

위 파일에서 select * from emp 란 스트링을 일부러 에러가 나게 select * fromemp 라고 고치고 다시 테스트해봅니다.

 

로그파일은 Log.java 파일에서 정한대로의 위치에 error.dbg 란 파일을 내용없이 만들어 위치시켜야 합니다.

 

그러면 다음과 같이 로그 파일에 기록이 쌓이는 것을 확인할 수 있습니다.

 

Sat Jun 19 14:01:58 KST 2004 : Error Source:getEmpWithPooldbg.jsp : SQLException
Sat Jun 19 14:01:58 KST 2004 : SQLState : 42000
Sat Jun 19 14:01:58 KST 2004 : message : ORA-00923: FROM 키워드가 있어야할 곳에 없습니다
Sat Jun 19 14:01:58 KST 2004 : Oracle Error Code : 923
Sat Jun 19 14:01:58 KST 2004 : Query : select * fromemp

여기까지 오셨다면 게시판을 위한 준비가 다 된 것입니다.

파일에 로그 파일 쌓이지 않은다면 ConnectionManager.java 의 코드에서 명시한 디렉토리에 error.dbg 파일이 없기 때문입니다.


 

 게시판 연습

 

먼저 테이블을 만듭니다. (오라클에 대한 내용은 오라클 카테고리의 글을 참고하세요)

 

-- 게시판 연습 테이블
create table board(
 num number primary key,
 subject varchar2(200) not null,
 sogae varchar2(4000) not null,
 content varchar2(4000),
 wdate date
);

create sequence seq_board_num
start with 1
increment by 1;

 

적당한 디렉토리에 board.sql로 위 내용으로 만들고 scott 계정으로 접속하여 (C:\에 저장했다면)

 

@C:\board.sql

 

하면 테이블과 시퀀스가 생성됩니다.

 

여기서의 게시판은 단순한 기본적인 기능만을 가진 것을 만들어 보겠습니다.

다음은 게시판을 위해 쓸 파일 흐름도 입니다.

(서블릿과 JSP 를 모두 이용하기 위해 애쓴것이지 이와 같이 프로그래밍하지는 않습니다.)

 

list.jsp ---> write_form.jsp

                  |              |--------->BoardWriter.java(서블릿) - DB insert 문 실행

                  |                                         

                  |---> view.jsp : 게시물의 내용을 보여준다.

                             |

                             |

                             |---> modify_form.jsp

                             |            |----------> BoardModifier.java(서블릿) --- DB update 문 실행

                             |

                             |---> delete_confirm.jsp

                                          |-----------> BoardDeleter.java(서블릿) -- DB delete 문 실행

 

list.jsp : 게시물을 모두 보여줍니다.(페이지분할 기능, 페이지 직접 이동 기능, 검색 기능은 후에 붙이도록 합니다.)

write_form.jsp : 새글 입력 폼 화면

BoardWriter.java : 새글 입력을 실제로 DB에 입력하는 서블릿

view.jsp : 해당 게시물의 상세 정보를 출력하는 페이지

modify_form.jsp : 수정 입력 폼 화면

BoardModifier.java : 수정을 위해 실제로 DB 테이블을 수정을 행하는 서블릿

delete_confirm.jsp : 삭제를 사용자가 선택했을 때 삭제를 정말로 할 것인가 확인하는 화면

BoardDeleter.java : 테이블에서 해당 레코드를 삭제하는 서블릿

 

각각의 소스

 

/bbs/bbs01/list.jsp


<%@ page contentType="text/html;charset=euc-kr" %>

<%@ page import="java.sql.*,net.java_school.util.*,net.java_school.db.dbpool.*" %>

<jsp:useBean id="dbmgr" scope="application" class="net.java_school.db.dbpool.OracleConnectionManager" />

<html>

<body>

<%

Log log = new Log();

Connection conn = null;

PreparedStatement prepare = null;

ResultSet rs = null;

String query = null;

try{

         conn = dbmgr.getConnection();

         query = "select num,subject,wdate from board order by num desc";

         prepare = conn.prepareStatement(query);

         rs = prepare.executeQuery();

         while(rs.next()){

         int num = rs.getInt("num");

         String subject = rs.getString("subject");

         Date wdate = rs.getDate("wdate");

%>

<a href="view.jsp?num=<%= num %>"><%= subject%></a>&nbsp;&nbsp;<%= wdate.toString() %><br>

<%

         }

} catch(SQLException e){

         log.debug("Error Source:bbs/list.jsp : SQLException");

         log.debug("SQLState : " + e.getSQLState());

         log.debug("Message : " + e.getMessage());

         log.debug("Oracle Error Code : " + e.getErrorCode());

         log.debug("Query : " + query);

} finally {

         try {

                  rs.close();

                  prepare.close();

                  dbmgr.freeConnection(conn);

                  log.close();

         } catch (SQLException e){}

}

%>

<br>

<br>

<p>

<a href="write_form.jsp">새글 쓰기</a>

</body>

</html>

 

/bbs/bbs01/write_form.jsp

 

<%@ page contentType="text/html;charset=euc-kr" %>
<html>
<body>
<center><h1>새글 쓰기</h1></center>
<hr>
<table cellspacing="0" cellpadding="0" border="0" width="600" align="center">
<form name="frm" method="POST" action="../servlet/bbs01.BoardWriter">
<tr>
 <td width="100" align="center">제목</td><td><input type="text" name="subject" size="45"></td>
</tr>
<tr>
 <td width="100" align="center">소개글</td><td><textarea name="sogae" rows="10"

cols="60"></textarea></td>
</tr>
<tr>
 <td width="100" align="center">본문</td><td><textarea name="content" rows="10"

cols="60"></textarea></td>
</tr>
<tr>
 <td colspan="2" align="center"><input type="submit" value="전송">&nbsp;&nbsp;&nbsp;<input type="reset" value="취소"></td>
</tr>
</form>
</table>
<br>
<center><a href="list.jsp">목록으로</a></center>
</body>
</html>

 

/bbs/WEB-INF/classes/BoardWriter.java

 

package bbs01;

 

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

import java.sql.*;

import net.java_school.db.dbpool.*;

import net.java_school.util.*;

 

public class BoardWriter extends HttpServlet {

         PreparedStatement prepare = null;

         OracleConnectionManager dbmgr = null;

         // 입력 순서 : 시퀀스 , 제목, 소개글, 본문

         String query = "insert into board values (seq_board_num.nextval,?,?,?,sysdate)";

 

         public void init()  throws ServletException {

           ServletContext sc = getServletContext();
           dbmgr = (OracleConnectionManager)sc.getAttribute("dbmgr");
         }
 

         public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

                  req.setCharacterEncoding("euc-kr");

                  Log log = new Log();

                  String subject = req.getParameter("subject");

                  String sogae = req.getParameter("sogae");

                  String content = req.getParameter("content");

                  Connection con = dbmgr.getConnection();

                  try {

                           prepare = con.prepareStatement(query);

                           prepare.setString(1,subject); //제목 부분

                           prepare.setString(2,sogae); // 소개글 부분

                           prepare.setString(3,content); // 본분 부분

                           prepare.executeUpdate();      // 쿼리 실행

                  } catch (SQLException e){

                           log.debug("Error Source:BoardWriter.java : SQLException");

                           log.debug("SQLState : " + e.getSQLState());

                           log.debug("Message : " + e.getMessage());

                           log.debug("Oracle Error Code : " + e.getErrorCode());

                           log.debug("Query : " + query);

                  } finally {

                           try {

                                   prepare.close();

                                   dbmgr.freeConnection(con);

                                   log.close();

                           } catch(SQLException e){}

                           String path = req.getContextPath();

                           res.sendRedirect(path+"/bbs01/list.jsp");

                  }

         }

}

 

/bbs/bbs01/view.jsp

 

<%@ page contentType="text/html;charset=euc-kr" import="java.sql.*,

net.java_school.util.*,net.java_school.db.dbpool.*" %>

<jsp:useBean id="dbmgr" scope="application"

class="net.java_school.db.dbpool.OracleConnectionManager" />

<html>

<body>

<%

int num = Integer.parseInt(request.getParameter("num"));

Log log = new Log();

Connection conn = null;

PreparedStatement prepare = null;

ResultSet rs = null;

String query = null;

try{

         conn = dbmgr.getConnection();

         query = "select num,subject,sogae,content,wdate from board where num="+num;

         prepare = conn.prepareStatement(query);

         rs = prepare.executeQuery();

         while(rs.next()){

                  String subject = rs.getString("subject");

                  String sogae = rs.getString("sogae");

                  String content = rs.getString("content");

                  Date wdate = rs.getDate("wdate");

%>

<%= subject %></a><br>

<hr>

<%= sogae %><br>

<hr>

<%= content %><br>

<hr>

<%= wdate.toString() %><br>

<%

         }

} catch(SQLException e){

         log.debug("Error Source:bbs/view.jsp : SQLException");

         log.debug("SQLState : " + e.getSQLState());

         log.debug("Message : " + e.getMessage());

         log.debug("Oracle Error Code : " + e.getErrorCode());

         log.debug("Query : " + query);

} finally{

         try {

                  rs.close();

                  prepare.close();

                  dbmgr.freeConnection(conn);

                  log.close();

         } catch(SQLException e){}

}

%>

<form name="modify" method="POST" action="modify_form.jsp">

<input type="submit" value="수정">

<input type="hidden" name="num" value="<%= num %>">

</form>

<form name="delete" method="POST" action="delete_confirm.jsp">

<input type="submit" value="삭제">

<input type="hidden" name="num" value="<%= num %>">

</form>

<br>

<a href="list.jsp">목록으로</a>

</body>

</html>

 

/bbs/bbs01/modify_form.jsp

 

<%@ page contentType="text/html;charset=euc-kr"

import="java.sql.*,net.java_school.util.*,net.java_school.db.dbpool.*" %>

<jsp:useBean id="dbmgr" scope="application"

class="net.java_school.db.dbpool.OracleConnectionManager" />

<%

Log log = new Log();

int num = Integer.parseInt(request.getParameter("num"));

Connection conn = null;

PreparedStatement prepare = null;

ResultSet rs = null;

String subject = null;

String sogae = null;

String content = null;

String query = "select subject,sogae,content from board where num ="+num;

try {

         conn = dbmgr.getConnection();

         prepare = conn.prepareStatement(query);

         rs = prepare.executeQuery();

 

         while(rs.next()){

                  subject = rs.getString("subject");

                  sogae = rs.getString("sogae");

                  content = rs.getString("content");

         }

} catch(SQLException e){

         log.debug("Error Source:modify_form.jsp : SQLException");

         log.debug("SQLState : " + e.getSQLState());

         log.debug("Message : " + e.getMessage());

         log.debug("Oracle Error Code : " + e.getErrorCode());

         log.debug("Query : " + query);

} finally{

         try {

                  rs.close();

                  prepare.close();

                  dbmgr.freeConnection(conn);

                  log.close();

         } catch(SQLException e){}

}

%>

<html>

<body>

<center><h1>글 수정</h1></center>

<hr>

<table cellspacing="0" cellpadding="0" border="0" width="600" align="center">

<form name="frm" method="POST" action="../servlet/bbs01.BoardModifier">

<input type="hidden" name="num" value="<%= num %>">

<tr>

         <td width="100" align="center">제목</td><td><input type="text" name="subject" size="45" value="<%= subject %>"></td>

</tr>

<tr>

         <td width="100" align="center">소개글</td><td><textarea name="sogae" rows="10" cols="60"><%= sogae %></textarea></td>

</tr>

<tr>

         <td width="100" align="center">본분</td><td><textarea name="content" rows="10" cols="60"><%= content %></textarea></td>

</tr>

<tr>

         <td colspan="2" align="center"><input type="submit" value="전송">&nbsp;&nbsp;&nbsp;<input type="reset" value="취소"></td>

</tr>

</form>

</table>

<br>

<center><a href="list.jsp">목록으로</a></center>

</body>

</html>

 

/bbs/WEB-INF/classes/BoardModifier.java

 

package bbs01;

 

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

import java.sql.*;

import net.java_school.db.dbpool.*;

import net.java_school.util.*;

 

public class BoardModifier extends HttpServlet {

         PreparedStatement prepare = null;

         OracleConnectionManager dbmgr = null;

         String query = "update board set subject=?, sogae=?, content=? where num=?";

        

         public void init()  throws ServletException {
           ServletContext sc = getServletContext();
           dbmgr = (OracleConnectionManager)sc.getAttribute("dbmgr");
         }
 

         public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

                  req.setCharacterEncoding("euc-kr");

                  Log log = new Log();

                  int num = Integer.parseInt(req.getParameter("num"));

                  String subject = req.getParameter("subject");

                  String sogae = req.getParameter("sogae");

                  String content = req.getParameter("content");

                  Connection con = dbmgr.getConnection();

                  try{

                           prepare = con.prepareStatement(query);

                           prepare.setString(1,subject);   //제목 부분

                           prepare.setString(2,sogae);    // 소개글 부분

                           prepare.setString(3,content);   // 본분 부분

                           prepare.setInt(4,num);     // 시퀀스 primary key

                           prepare.executeUpdate();    // 쿼리 실행

                  }catch(SQLException e){

                           log.debug("Error Source:BoardModifier.java : SQLException");

                           log.debug("SQLState : " + e.getSQLState());

                           log.debug("Message : " + e.getMessage());

                           log.debug("Oracle Error Code : " + e.getErrorCode());

                           log.debug("Query : " + query);

                  } finally {

                           try {

                                   prepare.close();

                                   dbmgr.freeConnection(con);

                                   log.close();

                           } catch(SQLException e){}

                           String path = req.getContextPath();

                           res.sendRedirect(path+"/bbs01/view.jsp?num="+num);

                  }

         }

}

 

/bbs/bbs01/delete_confirm.jsp

 

<%@ page contentType="text/html;charset=euc-kr"

import="java.sql.*,net.java_school.util.*,net.java_school.db.dbpool.*" %>

<jsp:useBean id="dbmgr" scope="application"

class="net.java_school.db.dbpool.OracleConnectionManager" />

<%

Log log = new Log();

int num = Integer.parseInt(request.getParameter("num"));

Connection conn = null;

PreparedStatement prepare = null;

ResultSet rs = null;

String subject = null;

String sogae = null;

String query = "select subject,sogae from board where num ="+num;

try {

         conn = dbmgr.getConnection();

         prepare = conn.prepareStatement(query);

         rs = prepare.executeQuery();

 

         while(rs.next()){

         subject = rs.getString("subject");

         sogae = rs.getString("sogae");

         }

} catch(SQLException e){

         log.debug("Error Source:delete_confirm.jsp : SQLException");

         log.debug("SQLState : " + e.getSQLState());

         log.debug("Message : " + e.getMessage());

         log.debug("Oracle Error Code : " + e.getErrorCode());

         log.debug("Query : " + query);

} finally{

         try {

                  rs.close();

                  prepare.close();

                  dbmgr.freeConnection(conn);

                  log.close();

         } catch(SQLException e){}

}

%>

<html>

<body>

<center><h1>삭 제 확 인</h1></center>

<hr>

<table cellspacing="0" cellpadding="0" border="0" width="600" align="center">

<form name="frm" method="POST" action="../servlet/bbs01.BoardDeleter">

<input type="hidden" name="num" value="<%= num %>">

<tr>

         <td width="100" align="center">제목</td><td><input type="text" name="subject" size="45" value="<%= subject %>"></td>

</tr>

<tr>

         <td width="100" align="center">소개글</td><td><textarea name="sogae" rows="10" cols="60"><%= sogae %></textarea></td>

</tr>

<tr>

         <td colspan="2" align="center">위 글을 정말로 삭제하겠습니까?</td>

</tr>

<tr>

         <td colspan="2" align="center"><input type="submit" value="삭제">&nbsp;&nbsp;&nbsp;

<input type="button" value="취소" onClick="javascript:history.go(-1)"></td>

</tr>

</form>

</table>

</body>

</html>

 

/bbs/WEB-INF/classes/BoardDeleter.java

 

package bbs01;

 

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

import java.sql.*;

import net.java_school.db.dbpool.*;

import net.java_school.util.*;

 

public class BoardDeleter extends HttpServlet {

         PreparedStatement prepare = null;

         OracleConnectionManager dbmgr = null;

         String query = "delete board where num=?";

 

         public void init()  throws ServletException {
           ServletContext sc = getServletContext();
           dbmgr = (OracleConnectionManager)sc.getAttribute("dbmgr");
         }
 

         public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

                  req.setCharacterEncoding("euc-kr");

                  Log log = new Log();

                  int num = Integer.parseInt(req.getParameter("num"));

                  Connection con = dbmgr.getConnection();

                  try{

                           prepare = con.prepareStatement(query);

                           prepare.setInt(1,num);

                           prepare.executeUpdate();    // 쿼리 실행

                  }catch(SQLException e){

                           log.debug("Error Source:BoardDeleter.java : SQLException");

                           log.debug("SQLState : " + e.getSQLState());

                           log.debug("Message : " + e.getMessage());

                           log.debug("Oracle Error Code : " + e.getErrorCode());

                           log.debug("Query : " + query);

                  } finally {

                           try {

                                   prepare.close();

                                   dbmgr.freeConnection(con);

                                   log.close();

                           } catch(SQLException e){}

                           String path = req.getContextPath();

                           res.sendRedirect(path+"/bbs01/list.jsp");

                  }

         }

}

<출처: http://cafe.naver.com/webprogramguide >

반응형

JSP 예제

 

[예제를 실습하기에 앞서 첨부 파일(example.zip)을 다운로드 한 후 /bbs 디렉토리에 압축을 풉니다.]

 

include 지시자를 이용한 파일 인클루드 예제

 

/bbs/ex1/main.jsp : main.jsp에서 include 지시자를 사용하여 디자인 페이지인 main.html 포함.

main.jsp 내에서 다음과 같이 main.html 페이지를 인클루드 합니다.

 

<%@ include file=”main.html” %>


유지 보수의 편리함 때문에 디자인 페이지를 include 지시자를 이용하여 포함시키는 경우가 많이 발생합니다.

이때 주의해야 할 사항은 인클루드 되는 파일(main.html)내에서의 링크는(<img src=..) 인클루드하는 파일(main.jsp)이 기준으로 해야 합니다는 점입니다.

이 예제에서 만약에 main.jsp 가 /bbs/ex1/ 에 위치하고 main.html 파일이 /bbs/ex1/inc 에 그리고 이미지 파일의 디렉토리가 /bbs/img 라고 가정한다면,

main.html 내에서의 이미지에 대한 링크는 <src img=../img/image.gif > 이어야지 <src img=../../img/image.gif>이면 안됩니다.

물론 main.html 만를 요청하면 main.html 내에서 이미지는 깨집니다. 하지만 깨지는 것이 정상입니다.

우리가 서비스하는 파일은 main.html 파일 단독이 아니기 때문입니다. main.jsp 가 웹 사이트가 방문자가 방문할 페이지이지 main.html 역시 단독으로 방문할 수 있는 페이지라면 디렉토리 구조부터 바꾸어야 합니다.

 

Form 태그의 텍스트필드를 이용해서 파라미터 값 전송 예제

 

main.jsp -> welcome.jsp

 

/bbs/ex2/main.jsp : main.jsp 에서 파라미터 값으로 uid, passwd를 welcome.jsp 에 전달

main.jsp 에서 <input type=”text” name=”uid”> 로 welcome.jsp 로 전송했다면 welcome.jsp에서는 사용자가 웹 브라우저를 통해 보내는 문자열 정보를 받는 코드 조각으로 받을 수 있습니다.


<% request.getParameter(“uid”) %>

 

파라미터 값을 자바빈에 설정하고 값 가져오기(set/get) 예제

 

/bbs/ex3/main.jsp 파일에서 디자인 파일 main.html 과 welcome.jsp 파일을 인클루드 하는데

welcome.jsp는 uid, passwd 값이 넘어 올때만 인클루드 됩니다. (main.jsp 소스를 확인해 보세요)

 

또한 이 예제에는 자바빈을 이용합니다.

이 때 자바빈을 어떻게 셋팅하고 자바빈에 저장된 값을 어떻게 가지고 오는지 확인합니다.


main.jsp 에서 아래와 같이 표준액션을 이용해서 자바빈을 생성합니다.

 

<%@ page import="kr.go.mnd.baby.*" info="Simple JSP" contentType="text/html; charset=euc-kr" %>

<jsp:useBean id="login" scope="page" class="kr.go.mnd.baby.User" />

<jsp:setProperty name="login" property="*"/>


여기서 <jsp:useBean>은 main.jsp 가 요청되면 id가 login이고 scope가 page인 객체를 찾아서 레퍼런스를 리턴하려 합니다.

그런데 찾는 객체가 없으면 객체를 생성합니다.

객체를 생성할 때는 페이지 지시자의 임포트된 팩키지에서 클래스를 찾아서 생성하게 됩니다.

두번째 표준액션인 <jsp:setProperty>는 넘어온 파라미터값으로 자바빈의 set 메소드를 호출하여 값을 저장하는 액션인데 처음 main.jsp를 호출하게 되면 아무런 작용도 하지 않는다.

main.jsp 에서 uid, passwd를 값을 자기 자신인 main.jsp에 넘기게 되면

 

<jsp:setProperty name="login" property="*"/>

 

의해 이미 생성한 User 자바빈의 setUid() 메소드와 setPasswd() 메소드를 호출하게 되어 자바빈을 설정하게 됩니다.

 

main.jsp

main.jsp

User.java

<input type=”text” name=”uid”>

<jsp:setProperty name=”login” property=”uid”>

setUid(String userid)


여기서 자바빈의 setUid 메소드에서 Uid가 대문자인 것에 의구심을 가질 수도 있는데

이는 자바 언어의 메소드 이름 규칙에 의한 것입니다.

자바 언어는 메소드나 변수의 이름을 작성할 때 첫 글자는 소문자로 시작하고 여러 단어가 붙을 때는 단어의 첫글자는 대문자로 함을 권고합니다.

클래스의 작명 규칙은 첫 글자는 대문자인 것만 빼고 메소드 작명 규칙과 같습니다.

실습 : 아래 자바빈은 /bbs/ex3/main.jsp 를 실행하기 위해서 필요한 자바빈입니다. 작성한 후 /bbs/WEB-INF/claases 에 넣고

컴파일하면 /bbs/ex3/main.jsp 가 실행이 됩니다.

 

package kr.go.mnd.baby;

public class User {

         String uid;

         String passwd;

         public User(){

                  uid = null;

                  passwd = null;

         }

         public String getUid(){

                  return uid;

         }

         public String getPasswd(){

                  return passwd;

         }

         public void setUid(String uid){

                  this.uid = uid;

         }

         public void setPasswd(String passwd){

                  this.passwd = passwd;

         }

}

 

 

사용자 유틸리티 클래스 사용 예제

 

파일 : /bbs/ex4/main.jsp, welcome.jsp

 

위 예제에서 uid 값에 한글을 넣고 테스트하면 한글이 깨집니다.

이를 보완하기 위해서 사용자 유틸리티 클래스를 만들어 사용해 봅니다.


/bbs/ex4/main.jsp -> welcome.jsp 로 uid 값을 한글로 보낼 때 welcome.jsp 에서 한글이 제대로 보이도록 하는 것이 목적입니다.


JSP 엔진에 따라서 입력된 한글이 깨져 나올 수 있습니다.

한글 처리가 미흡한 경우에는 코드에서 처리해 주어야 합니다.

JSP 내에서 한글을 처리하기 위해서는 입력 받은 한글을 euc-kr 이나 KSC5601 문자 세트로 변환합니다.

(이는 JSP엔진이나 OS에 따라서 달라질 수 있습니다. 여기서는 KSC5601로 변환했습니다)

데이터베이스에 한글을 삽입할 때도 문제가 생기면 같은 방법을 사용합니다.

 

아래 사용자 유틸리티 클래스를 작성하여 예제 실현


*** Hanguel.java ***

 

package kr.go.mnd.util;

 

import java.io.UnsupportedEncodingException;

public class Hanguel {

    public Hanguel() {}   

         public static String toHanguel(String s) {

                  try {

                           if (s != null)

                                   return (new String(s.getBytes("8859_1"),"KSC5601"));

                           return s;

                  } catch (UnsupportedEncodingException e) {

                           return "Encoding Error";

                  }

    }

}

 

welcome.jsp 에서 기존의 코드 request.getParameter("uid"); 다음과 같이 바꿉니다.

 

Hanguel.toHanguel(request.getParameter("uid"));

 

Hanguel 클래스의 toHanguel메소드를 사용하기 위해서는 welcome.jsp 의 페이지 지시자에서 다음과 같은 해당 클래스를 임포트해주어야 합니다.

 

<%@ page import="kr.go.mnd.util.Hanguel" %>


여기서 주의해야 것은 welcome.jsp 내에서 Hanguel 클래스의 객체 생성하지도 않고 바로 toHanguel 메소드를 사용할 있었다는 것입니다.

이는 Hanguel 클래스의 toHanguel 메소드가 static으로 선언된 클래스 메소드이기 때문에 객체 생성 없이 해당 메소드의 호출이 가능하기 때문입니다. (자바에 대한 기초 내용입니다)


welcome.jsp 파일을 아래와 같이 고치고 테스트해 봅니다.


<%@ page import="kr.go.mnd.util.Hanguel" %>
<center>
<h1>Hello,
<%
out.println(Hanguel.toHanguel(request.getParameter("uid")));
%>
</h1>
</center>

한글을 위해서 위와 같이 사용자 유틸리티 클래스를 이용하는 것대신에 request 의 setCharacterEncoding 메소드를 이용해도 됩니다.

Welcome.jsp 내에서 아래와 같이 사용합니다.


<%

request.setCharacterEncoding("euc-kr");

%>


setCharacterEncodeing 메소드는 최근 자바 버전부터 생긴 메소드로 이전의 웹 애플리케이션을 보면 거의다 위와 유사한 한글 컨버터 사용자 유틸리티 클래스를 쓰고 있습니다.

또한 문서에 의하면 setCharacterEncodeing 메소드가 아직 버그가 있어서 함께 혼용하여 사용하는 것이 낫다고 합니다.


이번에 다운로드 한 그대로의 welcome.jsp 파일를 이용하여 한글을 나오도록 해 보겠습니다.


<center>
<h1>Hello,
<jsp:getProperty name="login" property="uid" />
</h1>
</center>


위 파일이 원래의 welcome.jsp 파일입니다.


자바 빈을 이용하는 것이므로 자바 빈의 코드 안에 위에서 만든 Hanguel 사용자 유틸리티 클래스를 이용하도록 코드를 고칩니다.

아래와 같이 User 빈이 Hanguel 사용자 유틸리티 클래스를 이용하도록 고치고 테스트 합니다.


User.java


package kr.go.mnd.baby;


import kr.go.mnd.util.Hanguel;


public class User {
    String uid;
    String passwd;

    public User() {
        uid = null;
        passwd = null;
    }

    public String getUid() {
        return uid;
    }

    public String getPasswd() {
        return passwd;
    }

    public void setUid(String uid) {
        this.uid = Hanguel.toHanguel(uid);
    }

    public void setPasswd(String passwd) {
        this.passwd = Hanguel.toHanguel(passwd);
    }
}

<출처: http://cafe.naver.com/webprogramguide/>

반응형

JSP란?
Java Server Pages, 즉 JSP는 다이나믹 HTML를 생성하기 위한 자바진영의 기술입니다.

JSP는 마이크로소프트의 ASP에 대항하기 위한 자바진영의 기술로, 서블릿의 가지고 있는 디자인과 코드의 분리의 어려움을 개선한 기술입니다.
JSP 문서의 확장자는 반드시 .jsp 이어야 합니다.
다음 코드는 간단한 JSP파일의 예입니다.


<html>
<body>
<% out.println("Hello JSP Reader"); %>
</body>
</html>

보기에는 단순한 HTML 파일 같지만 사실 자바 코드를 포함하고 있습니다.
이제 이 파일을 클라이언트의 웹 브라우저에서 보기 위해 hello.jsp 로 우리가 만든 /bbs 디렉토리에 옮겨 놓으면 됩니다.


클라이언트가 hello.jsp를 요청하면, 서버는 .jsp 확장자를 인식하고 이것이 특별한 핸들링이 필요하다는 것을 판단하여 서블릿 컨테이너에게 이 파일을 보내게 됩니다. (이것은 웹서버와 PHP 파서와의 관계와 마찬가지입니다)


그러면 JSP엔진은 .jsp 파일을 받아서 이를 서블릿으로 변환합니다.
변환된 서블릿은 톰캣의 경우 <TOMCAT_HOME>/work 에서 확인할 수 있습니다.

 

위의 간단한 예제도 결국은 서블릿으로 변환됩니다.
hello.jsp 가 처음으로 불리워진다면 이 파일은 서블릿으로 변환되고 컴파일된 후에 상주 메모리에 로딩됩니다.


그런 후에 해당하는 출력내용을 요청한 클라이언트에게 보내게 됩니다.


이후 똑같은 요청이 들어오면, 서블릿 엔진은 원본 .jsp 소스가 변경되었는지를 체크합니다.

그리고 객체가 이미 로딩되었는지 확인합니다. 로딩이 되었다면 로딩된 객체가 서비스하고 로딩되지 않았다면 메모리에 로딩시킵니다.

소스가 변경되었다면 JSP엔진은 JSP소스를 다시 파싱하여 서블릿으로 변환합니다.


다음 그림은 JSP 소스의 파싱 과정을 나타낸다.

최초의 클라이어트가 접속하여 서비스를 요청할 때 컨테이너는 JSP 페이지가 서블릿으로 변환하고 서블릿을 컴파일하여 요청에 응답합니다.

일단 서블릿이 요청에 응답하면 메모리에 로딩되어 있는 상태로 다음 클라이언트의 요청을 기다리게 됩니다.

사용자 삽입 이미지

※ JSP도 서블릿 기반의 기술입니다.
따라서 JSP는 서블릿의 자원과 기능을 가집니다.

JSP Directives

이것은 JSP페이지의 전반적인 정보를 서블릿 엔진에게 제공합니다.
JSP 스펙에 의해 현재에 가능한 지시어는
page, include, taglib 입니다.

page Directive

용법 : <%@ page {attribute="value"} %>

 

페이지 지시어의 속성 설명

language="scriptLanguage"

페이지를 컴파일할 서버측 언어가 무엇인지 기술

extend="className"

페이지가 상속한 부모클래스를 정의

import="importList"

페이지가 import하는 자바팩키지 리스트 기술 (,로 구분)

session="true|false"

페이지에 session 데이터가 이용되는지의 여부를 결정

(디폴트값:true)

buffer="none|size in kb"

출력 스트림의 버퍼크기를 결정(디폴트값:8kb)

autoFlush="true|false"

출력버퍼가 자동적으로 비워지는가 또는 버퍼가 차면 익셉션을 발생할것인가 여부를 결정 (디폴트값:true)

isThreadSafe="true|false"

JSP엔진에게 이 페이지가 일시에 다중으로 서비스할 수 있는가의 여부를 알림

(디폴트값은 true, 만약 이 값이 false로 셋팅되었다면

SingleThreadModel 로 페이지가 작동합니다.)

info="text"

JSP페이지에 관한 정보를 나타낸다.

Servlet.getServletInfo()메소드를 이용해 접근가능

errorPage="error_uri"

JSP 익셉션을 다루는 에러 페이지의 상대경로를 나타냄

isErrorPage="true|false"

페이지가 에러핸들링하는 페이지인가를 기술(디폴트값:false)

contentType="ctinfo"        

클라이언트로 보내질 response의 MIME타입과 캐릭터셋


※ 디폴트 값이 적용되므로 개발자는 이 속성을 모두를 정의해 줄 필요가 없습니다.

java.util팩키지를 import하는 페이지 지시어 예


<%@ page import="java.util.*" %>

include Directive


inlcude 지시어는 JSP 변환때에 텍스트나 소스를 삽입하기 위해 사용합니다.


용법 : <%@ include file="relativeURLspec" %>

삽입되는 문서의 포맷을 html이거나 jsp이거나 상관없지만 웹 애플리케이션내에 존재해야 합니다.

예) <%@ include file="header.jsp" %> 상대경로 사용

※ include 지시어는 변환때 한번만 사용됩니다.
따라서 삽입되는 소스파일이 변경될때는 JSP/Servlet엔진이 재시작되기 전까지는 반영되지 않습니다.

taglib Directive


taglib 지시어는 JSP페이지가 커스텀 태그 라이브러리를 이용함을 기술합니다.
커스텀 태그 라이브러리는 각각의 커스텀 태그 집합을 구별하는 prefix와 uri로 유일하게 구별됩니다.

용법 : <%@ taglib uri="tagLibraryURI" prefix="tagPrefix" %>

태그라이브러리 지시어 속성


uri               커스텀태그 라이브러리를 고유하게 이름짓는 URI 참조
prefix            커스텀 태그 라이브러리를 구별하는데 쓰이는 Prefix 정의


 


Scripting


Scripting은 HTML페이지에 자바코드 조각을 바로 삽입하기 위해 사용합니다.
Scripting에는 Declarations, Exceptions, Scriplets 3가지가 있습니다.
이들 각각은 서블릿의 적절한 위치에서 변화되어 놓이게 됩니다.

Declarations


Declarations는 자바 변수와 메소드를 JSP페이지내에서 선언하기 위해선 사용됩니다.

JSP Declarations는 JSP페이지가 첫번째로 로딩될때 초기화되고 그 후에 같은 페이지내의
다른 Declarations, expressions, scriptlets에게 이용되어 진다.

용법 :
<%! declaration %>

변수 선언 예   : <%! String name = new String("BOB") %>
메소드 선언 예 : <%! public String getName() { return name; } %>

Declarations는 서블릿으로 변환될때 서블릿 클래스의 선언부분에 위치하게 됩니다.

 

Expressions


JSP Expressions는 컨테이너에 의해 결과값(문자열)으로 바뀌는 JSP 컴포넌트입니다.
JSP Expressions는 request타임에 .jsp 파일내에서 컨테이너에 의해 변환되어 삽입됩니다.
만약 결과값이 문자열로 변환되지 않는다면 번역시 에러가 발생합니다.
번역시 문자열이 검출되지 않는다면 ClassCastException 익셉션이 request타임에 발생합니다.
용법 :
<%=expression %>
) Hello <%= getName() %>

Scriptlets


Scriptlets는 모든 JSP 요소를 가져올 수 있는 JSP컴포넌트입니다.
이들은 request타임에 실행됩니다.

용법 :
<% scriptlets source %>

Scriptlets를 가지고 있는 페이지를 처음 요청하면 JSP는 서블릿코드로 변환되고 컴파일되고 상주메모리에 로딩됩니다.
<%...%>로 표현되는 Scriptlets는 서블릿의 service() 메소드내에 위치하게 됩니다.

JSP Error 핸들링

JSP 아키텍처는 오로지 에러만을 다룰 수 있는 JSP페이지로서 에러 핸들링의 해법을 제시합니다.
에러는 주로 런타임 에러가 대부분인데 이것은 JSP 바디안 이거나 또는 JSP 바디안 에서 호출하는 어떤 다른 객체에서 발생합니다.


request타임 에러는 호출한 JSP의 몸체에서 잡을 수 있고 또한 다룰 수 있는 에러가 던져졌을 때 발생합니다.

호출한 JSP의 몸체에서 다룰 수 없는 익셉션의 경우는 잡혀지지 않은 익셉션과 함께 클라이언트 request를 에러 페이지로 전송합니다.

JSP Error 페이지 만들기

JSP Error 페이지를 만드는 것은 간단하다.
기본적인 JSP페이지를 만들고 컨테이너에게 이 페이지가 에러 페이지임을 알리면 됩니다.
이것은 앞서 언급한 page Directives의 isErrorPage를 셋팅하면 됩니다.
다음은 에러페이지의 예입니다.

*** errorpage.jsp ***


<html>
<body>
<%@ page isErrorPage="true" %>
Bob there has been an error : <%= exception.getMessage() %> has been reported.
</body>
</html>

<설명>
<%@ page isErrorPage="true" %>
위 지시자는 이 페이지가 에러 페이지라는 것을 컨테이너에게 알리는 역활을 합니다.

<%= exception.getMessage() %>


는 에러페이지로 전달되어 온 익셉션의 에러 메시지를 출력하기 위한 부분입니다.
이때 exception이라는 내장객체를 사용합니다.

JSP Error 페이지 사용법


에러 페이지가 어떻게 작동하는지 알아보기 위해 잡히지 않는 익셉션을 발생시키는 간단한
JSP페이지를 만들어봅시다.

*** testerror.jsp ***

<%@ page errorPage="errorpage.jsp" %>
<%
   if(true){
      //Just throw an exception
      throw new Exception("An uncaght Exception");
   }
%>

에러페이지를 errorpage.jsp로 셋팅했다.

이렇듯 JSP페이지에게 에러페이지를 알리는 방법은 JSP페이지의 page directive에서
errorPage속성값을 정해주는 것입니다.
속성값에서 에러페이지의 위치는 페이지의 상대경로입니다.

이 예제을 실행해보기 위해서는 testerror.jsp 와 errorpage.jsp을
<TOMCAT_HOME>/webapps/bbs/에 위치시키고 testerror.jsp를 방문합니다.

Implicit Objects ( 내장 객체 )

내장 객체는 JSP문서내에서 이용되는 객체인데 특별히 레퍼런스를 얻기 위한 작업 없이 바로 사용할 수 있는 객체를 말합니다.

out

 

javax.servlet.jsp.JspWriter클래스의 인스턴스를 나타냅니다.
데이터를 응답 스트림으로 작성하는데 사용합니다.
이 객체의 일반적인 메소드는 out.println()입니다.
 사용예


*** out.jsp ***


<%@ page errorPage="errorpage.jsp" %>
<html><head><title>Use Out</title></head>
<body>
<%
   //Print a simple message using the implicit out object.
   out.println("<b> Hello Bob! </b>");
%>

</body></html>

request

 

javax.servlet.http.HttpServletRequest 인터페이스의 인스턴스
요청 파라미터나 헤더와 같은 사용자가 요청한 유용한 정보에 대해 접근할 수 있습니다.
request 객체는 모든 HTTP요청과 관련되어 있습니다.
이 객체는 request의 파라미터를 구하는데 일반적으로 사용되는데
getParamter()메소드를 사용함으로써 파라미터의 값을

리턴받습니다.

예)

*** request.jsp ***

<%@ page errorPage="errorpage.jsp" %>
<html>
<head>
   <title>UseRequest</title>
</head>
<body>
<%
   out.println("<b>Welcome: " + request.getParameter("user") + "</b>");
%>
</body>
</html>


실행하려면 다음 URL을 방문합니다. http://localhost/bbs/request.jsp?user=kim



response


javax.servlet.http.HttpServletResponse 인터페이스의 인스턴스입니다.

사용자에게 리턴할 현재 응답을 나타낸다.
하지만 대부분의 HTML 출력은 out객체를 이용합니다.


pageContext

 

jsp범위 내에서 이용 가능한 모든 자원 및 현재의 요청, 응답, ServletContext,

HttpSession, ServletConfig 같은 페이지 속성들에 접근할 수 있는 방법을 제공합니다.

pageContext 객체는 내장 객체를 접근할 수 있는 방법을 제공합니다.

session

session 객체는 javax.servlet.http.HttpSession 객체를 나타냅니다.
세션 데이타를 읽고 저장하는 데 사용됩니다.
 
session 객체의 사용예
*** session.jsp ***


<html> <lhead> <title>Session Example </title> </head>
<body>
<%
   //get a referece to the current count from the session
   Integer count = (Integer)session.getAttribute("COUNT");

   if(count==null){
      //If the count was not found, create one
      count = new Integer(1);
      //and add it to the HttpSession
      session.setAttribute("COUNT",count);
   } else {
      //Otherwise increment the value
      count = new Integer(count.intValue() +1);
      session.setAttribute("COUNT",count);
   }
   out.println("<b>This page has been accessed: " + count + " times.</b>");
%>
</body> </html>

이 예제를 사용하기 위해서는 session.jsp 파일을
<TOMCAT_HOME>/webapps/mnd에 복사하고 http://localhost/bbs/session.jsp 를 방문합니다.
리로드 버튼을 눌러 결과를 확인합니다.

application


application 객체는 javax.servlet.ServletContext 나타낸다.

이 객체는 주로 웹 컴포넌트가 공유할 수 있도록 ServletContext에 저장되어 있는 객체를 접근하기 위해 사용됩니다.


config


이 객체는 ServletConfig의 레퍼런스를 가지고 있습니다.
ServletConfig는 JSP/Servlet엔진의 관한 설정 정보를 담고 있습니다.
초기화 파라미터들에 접근하기위해 사용합니다.


page


이 객체는 현재 JSP페이지의 레퍼런스를 가지고 있습니다.
jsp페이지의 페이지 구현 클래스 인스턴스를 참조하며 Object형으로 선언되어 있습니다.
page변수는 스크립팅 엘리먼트들 안에서 가끔 사용되며, 단순히 jsp페이지와 구현 서블릿 사이의
연결 역할을 합니다.
 
exception


JSP페이지에서 발생한 잡히지 않은 익셉션에 접근을 제공하는 객체입니다.
이 객체는 page 지시어 중 isErrorPage가 true로 설정한 페이지내에서만 사용이 가능합니다.

, 페이지디렉티브를 이용해서 에러 페이지로 지정한 jsp에서만 유용한 객체입니다.


표준 액션

표준 액션이란 미리 제공된 커스텀 태그라 생각하면 됩니다.
6가지 표준액션이 제공됩니다.

<jsp:useBean>

이 표준액션은 자바빈을 생성하거나 생성된 자바빈을 찾기 위한 액션입니다.
<jsp:useBean>은 매우 유연합니다.


JSP문서내에서 <jsp:useBean>부분에 이르면 우선 같은 scope와 ID를 사용하는 객체를 찾습니다.
만약 찾는것에 실패하면 scope와 ID와 관련이 있는 객체를 생성하기 위해 시도합니다.

신택스


<jsp:useBean id="name" scope="page|request|session|application" typeSpec>
body
</jsp:useBean>

typeSpec :: =class="className" |
       class="className" type="typeName" |
       type="typeName" class="className" |
       beanName="beanName" type="typeName" |
       type="typeName" beanName="beanName" |
       type="typeName"

<jsp:useBean>의 속성 설명
id : 특정 scope 내에서 객체의 인스턴스와 관련되어 있는 키
scope : 참조되는 객체의 라이프 page | request | session | application

class : 객체의 구현을 정의하는 클래스
beanName : 자바빈의 레퍼런스
type : 정의된 변수의 타입(정의되지 않으면 class의 속성값과 같습니다)

<jsp:setProperty>

이 액션은 자바빈의 속성값을 셋팅하는 데 쓰입니다.

신택스 : <jsp:setProperty name="beanName" propexpr />
name 속성은 빈의 이름을 나타낸다.

propexpr

property="*" |
property="propertyName" |
property="propertyName" param="parameterName" |
property="propertyName" value="propertyValue"

<jsp:setProperty> 액션의 속성 설명

name  

<jsp:useBean>에서나 다른 액션에서 정의된 인스턴스의 이름


property  

셋팅을 원하는 곳의 속성
만약 propertyName에다가 * 라고 셋팅하면 ServletRequest로부터 차례대로 전달받은 파라미터로 모든 속성값을 세팅하게
됩니다.
만일 해당 파라미터가 비어있습니다면 수정되지 않는다.


param    

셋팅하기를 원하는 파라미터의 이름

value      

빈의 속성에 대응하는 값

<jsp:getProperty>

빈의 속성값을 가져와서 스트림으로 변환하고 이것을 output 스트림에 두는 액션
신택스    <jsp:getProperty name="name" property="propertyName" />

<jsp:getProperty> : 표준 액션 속성 설명
name   : 빈 인스턴스의 이름
property  : 얻고자 하는 빈 인스턴스의 속성값

<jsp:param>

이 액션은 표준 액션, <jsp:include>,<jsp:forward>,<jsp:plugin>에 파람값을 전달할때 이용합니다.

신택스 : <jsp:param name="name" value="value" />

<jsp:param> 의 속성 설명
name : 파리미터의 이름
value : 파리미터의 값

<jsp:include>


이 액션은 JSP페이지에 정적 또는 다이나믹 웹 컴포넌트를 추가할때 사용합니다.

신택스
<jsp:include page="urlSpec" flush="true">
   <jsp:param ... />
</jsp:include>

<jsp:include> 의 속성 설명
page :  인클루드 되는 소스의 상대경로
flush :  버퍼가 비워지는 여부

※ include 지시어와 include 표준 액션과의 차이점
지시어는 한번만 번역타임에 해석되지만 표준액션의 경우는 매 request타임마다 해석됩니다.
따라서 지시어를 사용한 인클루드는 인클루드되는 파일의 변화는 톰캣이 재시동되지 않으면 반영되지 않습니다.


<jsp:forward>

이 액션은 JSP엔진이 실행중에 request를 다른 자원(정적 문서,서블릿, JSP)에게 넘기는 것을 가능하게 합니다.
이 액션에서도 <jsp:param>가 쓰일 수 있는데 이는 포워딩할 대상자원에게 전달할 파라미터를 지정하기 위해 쓰입니다.

신택스   
<jsp:forward page="relativeURL">
   <jsp:param .../>
</jsp:forward>

단일 속성 page는 포워딩할 대상자원을 상대주소로 나타낸 값입니다.

<jsp:plugin>

이 액션은 다운로드나 애플릿,자바빈의 실행을 일으키는 HTML 코드를 생성하는데 사용됩니다.
이 액션은 한번 해석되어 <object> 나 <embed>로 바뀝니다.
속성은 바뀌는 코드에 표현을 위한 설정데이터로 제공됩니다.

신택스
<jsp:plugin type="pluginType" code="classFile" codebase="relativeURLpath">
   <jsp:params>
   </jsp:params>
</jsp:plugin>

<jsp:plugin>의 속성 설명
type : 인클루드할 플러그인 타입 예를 들면 applet
code : 플러그인이 실행할 클래스의 이름
codebase : 클래스의 절대 또는 상대경로



서블릿컨텍스트와 웹 애플리케이션의 관계

 

서블릿컨텍스트와 웹 애플리케이션과의 관계에 대해 알기 전에 먼저 서블릿컨텍스트가 무엇인지 부터 알아야 합니다.
서블릿컨텍스트(ServletContext)는 javax.servlet 팩키지에 속하는 객체입니다.

이것은 웹 애플리케이션의 서브 사이드 컴포넌트와 서블릿 컨테이너와의 통신을 담당하는 메소드 집합을 정의합니다.

서블릿컨텍스트의 가장 일반적인 사용중 하나는, 웹 애플리케이션의 서버 사이드 컴포넌트들 모두에게 이용될 수 있는 객체를 위한 저장소로 이용되는 것입니다.
서블릿컨텍스트에 저장된 객체는 웹 애플리케이션의 일생동안 존재합니다.
4개의 서블릿컨텍스트의 메소드는 공유메모리기능를 제공하기 위해 쓰입니다.

다음은 각각의 메소드에 관한 설명입니다.

setAttribute(java.lang.String name,java.lang.Object object)


첫번째 파라미터값인 이름으로 객체를 바인딩하고 객체를 서블릿컨텍스트에 저장합니다.
만약 특정 이름이 이미 사용중이라면 기존의 이름으로 바인딩된 속성을 지우고 새로운 객체를 이 이름으로 바인딩합니다.

getAttribute(java.lang.String name)


첫번째 파라미터값을 이름으로 참조하는 객체를 반환합니다.
만약 주어진 이름으로 바인된 속성이 없다면 널을 반환합니다.

getAttributeNames()
서블릿컨텍스트에 저장된 속성이름을 Enumeration 타입으로 반환합니다.

웹 애플리케이션과 서블릿컨텍스트의 관계


우리는 이미 <TOMCAT_HOME>/conf/server.xml 파일에 새로운 Context를 추가했습니다. (톰캣 admin 툴을 이용해서).
이 작업을 하면 웹 애플리케이션을 생성한 것입니다.
웹 애플리케이션을 추가함과 동시에 새로운 서블릿컨텍스트를 또한 만든 것입니다.
이것이 웹 애플리케이션과 서블릿컨텍스트의 관계입니다.
모든 웹 애플리케이션마다 단 하나의 서블릿컨텍스트가 있습니다.
이는 서블릿 스펙에 의해 요구되어지고 모든 서블릿엔진에 의해 수행됩니다.

웹 애플리케이션이 웹 애플리케이션 컴포넌트에 어떻게 영향을 미치는지의 예

실제로 서블릿컨텍스트와 웹 애플리케이션과의 관계를 이해하기 위해,
우리는 이미 만든 /bbs 웹 애플리케이션을 외에 /bbs2 라는 웹 애플리케이션을 추가합니다.(톰캣 admin 툴 이용)
그리고 각각의 웹 애플리케이션에 아래와 같은 2개의 웹컴포넌트를 각각 배치합니다.


첫번째 웹 컴포넌트 서블릿

*** ContextText.java ***

 

package example;

import javax.servlet.*;

import javax.servlet.http.*;

import java.io.*;

import java.util.*;

 

public class ContextTest extends HttpServlet{

             private static final String CONTENT_TYPE="text/html;charset=euc-kr";

             public void init() throws ServletException {

             }

             public void doGet(HttpServletRequest request,HttpServletResponse response)

                           throws ServletException,IOException{

 

                           doPost(request,response);

             }

             public void doPost(HttpServletRequest request,HttpServletResponse response)

                           throws ServletException,IOException{

 

                           // ServletContext 레퍼런스를 얻는다.

                           ServletContext context=getServletContext();

                           // ServletContext로부터 count 속성값을 얻기를 시도합니다.

                           Integer count=(Integer)context.getAttribute("count");

                           // 만약 count 속성이 없다면 만든다.

                           // count 속성 초기값은 0 입니다.

                           if(count==null){

                                        count=new Integer(0);

                                        context.setAttribute("count",new Integer(0));

                           }

 

                           response.setContentType(CONTENT_TYPE);

                           PrintWriter out=response.getWriter();

                           out.println("<html>");

                           out.println("<head><title>ContextTest</title></head>");

                           out.println("<body>");

                           // count 속성값의 현재값을 출력합니다.

                           out.println("<p>현재 COUNT 는 : "+count+".</p>");

                           out.println("</body></html>");

                           // doPost메소드가 불릴때마다 count 속성값을 1씩 증가시킨다.

                           count=new Integer(count.intValue()+1);

                           // ServletContext에 증가한 count 속성을 저장합니다.

                           context.setAttribute("count",count);

             }

             public void destory(){

             }

}

 


코드 설명


1. getServletContext()메소드를 이용해서 ServletContext의 레퍼런스를 얻습니다.


ServletContext context = getServletContext();

2. 서블릿컨텍스트의 레퍼런스를 얻었다면 서블릿컨텍스트로부터 count 속성값을 얻고자 시도합니다.

이때 getAttribute()메소드를 사용합니다.

Integer count = (Integer)context.getAttribute("count");

3. 서블릿컨텍스트에 count라는 속성이 있는지 조사하고 만일 그런 속성이 존재하지 않는다면 만들고 서블릿컨텍스트에 추가합니다.

이때 setAttribute()메소드를 사용합니다.

if( count == null) {
   count = new Integer(0);
   
context.setAttribute("count",new Integer(0));
}

4. 속성이 발견되었다면 이 값을 출력스트림에 씁니다.


out.println("<p>The current COUNT is : " + count + ".</p>");

5. 서블릿컨텍스트의 속성값을 증가시키고 이 값을 서블릿컨텍스트에 추가합니다.

count = new Integer(count.intValue() + 1);

context.setAttribute("count", count);

서블릿을 2개의 웹 애플리케이션에 배치합니다.
위 서블릿 코드를 bbs/WEB-INF/classes와 bbs2/WEB-INF/classes 에 위치시킨후

javac -d . ContextTest.java


라는 명령어로 컴파일하고


http://localhost/bbs/servlet/example.ContextTest

http://localhost/bbs2/servlet/example.ContextTest


를 방문해 확인합니다.

2번째 웹컴포넌트 JSP페이지


파일위치 : /bbs/example/ , /bbs2/example/


***
ContextTest.jsp ***


<%@ page contentType="text/html;charset=euc-kr" %>

<HTML><head><title>ContextTest</title></head><body>

<h1>

<%

             // count 속성을 얻기를 시도합니다.

             Integer count=(Integer)application.getAttribute("count");

             // 만약 count 속성이 null이면 하나 만들어서 서블릿컨텍스트에 저장합니다.

             if(count==null){

                           count=new Integer(0);

                           application.setAttribute("count",count);

             }

%>

 

현재 COUNT 는 : <%=count%>

<%

             // count 속성을 1 증가시켜 서블릿컨텍스트에 새로 저장합니다.

             count=new Integer(count.intValue()+1);

             application.setAttribute("count",count);

%>

</h1>

</body></html>


이 파일을 bbs/example 와 bbs2/example 에 복사합니다.
각각의 분리된 웹 애플리케이션이 어떻게 이들 컴포넌트에 영향을 미치는지 확인합니다.
실험을 시작하기 위해 다음 URL를 방문합니다.

http://localhost/bbs/example/ContextTest.jsp

http://localhost/bbs2/example/ContextTest.jsp



Refresh 버튼을 여러번 누르고 count가 증가되는지 확인합니다.
새로운 브라우저를 열고 서블릿을 방문합니다.

http://localhost/bbs/servlet/example.ContextTest

http://localhost/bbs2/servlet/example.ContextTest



출력결과는 ContextTest.jsp 와 같을 것입니다.
count의 값에 주목합니다.


ContextTest.jsp에서보다 1만큼 증가된 값입니다.
이것은 서블릿과 JSP가 같은 서블릿컨텍스트를 공유하고 있습니다는 의미입니다.
서블릿 컨텍스트의 공유메모리 기능입니다. (공동 저장소 기능)
각각 JSP와 서블릿을 방문함으로써 count 객체가 어떻게 공유되는지 알 수 있습니다.

이제 /bbs2/ContextTest.jsp JSP페이지를 새로운 창으로 방문합니다.
http://localhost/bbs2/example/ContextTest.jsp count의 값이 0인 결과화면을 볼 수 있습니다.
이것이 의미하는 것은 /bbs 웹 애플리케이션이 사용하는 count와 지금의 count는 다르다는 것입니다.
이것이 웹 애플리케이션과 서블릿컨텍스트의 관계입니다.
/bbs2 와 관련이 있는 서블릿 컨텍스트는 이 웹 애플리케이션에 유일합니다.
그리고 다른 웹 애플리케이션 /bbs 안에 있는 웹 컨포넌트에 의해 영향을 받지 않는다는 것입니다.


다시 확인을 위해 /bbs2 의 서블릿을 방문합니다.
http://localhost/bbs2/servlet/example.ContextTest
/bbs2 에 배치된 JSP와 같은 count 레퍼런스를 사용함을 알 수 있습니다

 

JSP 문법에서 꼭 확인해야 할 사항들


1. <%@ page session=true>


Q. page 지시자에서 session 속성은 구체적으로 무엇을 의미하는가?

page 지시자에 session 속성이 false로 되어 있으면 웹 컨테이너에서는 해당 페이지가 session 객체를 생성하지도 못하고 또한 기존의 session 객체에 대한 레퍼런스도 얻을 수도 없습니다.

false로 되어 있는 상태에서 session 객체에 접근하고자 하면 에러가 발생하게 됩니다.

 

2.<jsp:useBean id="name" scope="page|request|session|application"  class=ClassName />


Q. 표준액션의 <jsp:useBean>에서 scope 속성은 무엇을 의미하는가?

scope 속성은 jsp:useBean 속성 중에서 가장 중요한 부분입니다.

일단 이 속성은 자바 빈즈를 객체화시킨 후 어느 범위까지 사용을 할 것인지를 결정하는 것입니다.

Scope 속성으로 지정한 영역의 수명에 따라서 빈 객체는 하나의 페이지가 아니라 여러 페이지에서 소멸하지 않고 참조되기고 합니다.

(예를 들어 scope 속성이 session 으로 설정되었다면 빈 객체는 세션이 종료할 때까지 소멸되지 않고 유지됩니다.)

빈 객체가 생성된 이후 어떤 페이지에서도 참조될 수 없을 때 자동으로 소멸됩니다.

Scope 속성은 기본 값은 page입니다.

scope 속성에는 4개의 값을 지정해 줄 수 있는데 각각의 값에 대해서 정리하면 다음과 같습니다.

 

page : 자바 빈즈가 현재의 JSP 페이지 내에서만 사용 가능하도록 설정할 때

기본 값이므로 특별히 지정하지 않으면 이 옵션이 적용됩니다.

빈 객체의 수명은 한 페이지 내에서만 유지됩니다.

Page 영역으로 생성된 객체는 요청된 페이지 내에서만 유효합니다.

같은 페이지를 요청해도 새로운 빈 객체가 생성됩니다.

페이지의 실행 종료와 함께 빈 객체는 소멸됩니다.

매 페이지마다 새로 생성되므로 객체가 생성자의 초기화 부분을 항상 실행합니다.

Page영역은 한 페이지에서만 유효하므로 <jsp:include> 태그나 <jsp:forward> 태그로 포함된 페이지에서

<jsp:useBean> 태그는 이미 만들어진 빈 객체를 참조하는 것이 아니라 같은 id 속성값을 가진 새로운 객체를 생성하게 됩니다.

또한 <jsp:include> 태그에서 생성한 빈 객체는 원 페이지에서 참조될 수 없습니다.

Page 영역의 빈 객체는 jsp 페이지가 불릴 때마다 먼저 생성된 빈 객체의 상태가 필요하지 않고 새로 생성되어도 되는 경우에 적합하다.

 

request : JSP 페이지는 jsp:forward, jsp:include 태그를 이용해서 다른 JSP 페이지와 함께 사용할 수 있는데 이 값으로 범위를 지정하면 현재의 JSP 페이지와 연결되어 있는 모든 JSP 페이지까지 영향을 미칩니다.

이럴 경우 이 자바 빈즈의 id는 다른 페이지에 동일한 이름의 id가 존재해서는 안됩니다.

반대로 page 속성으로 지정되어 있을 경우에는 현재 페이지에 jsp:forward와 jsp:include가 있을 지라도 해당 페이지까지 영향을 미치지는 않습니다. 즉, 해당 페이지가 원 페이지에서 참조하는 자바 빈즈를 참조하지 못합니다.

또한 request 영역으로 생성된 빈 객체를 request 객체에 저장하여 request 객체에서 찾아서 참조가 가능합니다.

<jsp:include> 태그와 <jsp:forward>태그를 사용하는 경우 같은 request 객체를 사용하게 됩니다.

 

session : 이 값으로 범위를 지정해 놓으면 세션에 유효할 때까지 자바 빈즈의 객체가 유효합니다.

세션이 유지되는 동안 같은 세션에서 호출되는 모든 페이지에서 빈 객체는 소멸되지 않고 유지됩니다.

Session 영역으로 생성된 빈은 session 객체에 저장됩니다.

각 사용자에 대하여 독립적으로 생성되는 session 객체는 세션이 종료될 때까지 호출되는 모든 페이지에서 id 속성으로 구분되는 객체들을 유지하고 사용할 수 있게 해준다.

한가지 주의할 점은 page 지시자에서 session 속성을 false로 해 놓았을 경우에는 이 자바 빈즈 객체는 사용할 수 없게 됩니다.

page,request  scope 속성으로 생성된 빈은 브라우저의 요청에 대하여 결과를 생성하여 돌려준 다음에는 소멸됩니다.

 

application : 이 값은 가장 광범위한 범위를 갖는 값입니다. 이 값으로 범위를 지정하면 모든 JSP 페이지에서 사용할 수 있으며 자바 빈즈 객체는 JSP 엔진을 정지시키거나 다시 시작시킬 때까지 계속 살아 있게 됩니다.

즉, JSP엔진에 의해 소멸되지 않고 유지됩니다.

application scope 속성으로 생성된 빈은 application 내장객체에 저장되어 같은 웹 애플리케이션을 사용하는 모든 사용자에게 사용되어 질 수 있게 됩니다. 이 옵션은 거의 사용되지 않습니다.

 

3. <%@ include file=”상대경로파일명” %> 과 <jsp:include page=”상대경로파일명” /> 의 정확한 차이는?

 

Include 디렉티브의 경우 포함되는 페이지와 현재 jsp 페이지가 합쳐져서 하나의 jsp 페이지(이는 곧 합쳐진 jsp페이지가 서블릿으로 변환됨을 의미)가 되는 반면에 <jsp:include>액션 태그로 포함되는 페이지와 포함하는 페이지가 합쳐지지 않고 그대로 존재하게 됩니다.

<출처:
http://cafe.naver.com/webprogramguide>

반응형

바로 JSP로 만든 게시판으로 들어가지는 않겠습니다.


왜냐하면 JSP는 서블릿 기반 기술이기 때문입니다. 서블릿에 대한 기본적인 이해를 한 다음  JSP를 하는 것이 낫다고  생각하기

때문입니다.


JSP가 서블릿 기반 기술이라는 것은 확장자가 jsp인 파일은 톰캣과 같은 서블릿 엔진에 의해 결국은 서블릿으로 변환된 다음에

서비스되기 때문입니다.


서블릿은 CGI 프로그래밍에 대한 자바측 기술로 등장하게 됩니다.

JSP는 마이크로소프트 진영의 ASP가 인기를 끌자 ASP에 대응하기 위한 자바측 기술로 나타납니다.


서블릿 문법


서블릿 아키텍처는
javax.servletjavax.servlet.http 두개의 팩키지로 구성됩니다.

javax.servlet 팩키지는
모든 서블릿이 상속하거나 구현하는 일반적인 인터페이스와 클래스로 구성되어 있습니다.

javax.servlet.http 팩키지는 HTTP 프로토콜에 맞춘 서블릿 클래스로 구성됩니나.

javax.servlet.Servlet 인터페이스는 서블릿 아키텍처의 핵심으로 모든 서블릿의 기초 클래스인 Servlet 인터페이스는

5개의 메소드를 정의합니다.


그 중 가장 중요한 3개의 메소드는 다음과 같다.

init() : 서블릿을 초기화
service() : 클라이언트 요청에 대한 서비스
destory() : 자원반납
이들 메소드는 서블릿 라이프사이클 메소드를 구성합니다.

상속을 통해서든 아니면 직접적인 구현을 통해서 모든 서블릿은 반드시 Servlet 인터페이스를 구현해야 합니다.

서블릿 프레임워크

사용자 삽입 이미지

GenericServlet 과 HttpServlet 클래스서블릿 아키텍처에서 보이는 2개의 중요한 클래스는 GenericServletHttpServlet 클래스입니다.

HttpServlet 클래스는 GenericServlet 클래스를 상속합니다.

GenericServletServlet를 구현한 클래스입니다.

HttpServletGenericServlet는 서블릿을 개발할때 이들 중 하나를 사용합니다.

GenericServlet클래스를 상속하면 service()메소드를 구현해야 합니다.
GenericServlet.service()메소드는 프레임워크를 따르기 위해서 반드시 구현하도록 추상 메소드로 정의됩니다.

GenericServlet.service() 프로토타입

public abstract void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;

 

추상 메소드이므로 프로그래머가 반드시 구현해야 합니다.

service()메소드로 전달되는 2개의 파라미터는 ServletRequest ServletResponse 객체입니다.

ServletRequest 는 서블릿으로 전달되어진 모든 정보를 가지고 있습니다.
ServletResponse 는 클라이언트에게 보내고자 하는 데이터가 위치하는 곳입이다.

HttpServlet 클래스를 확장했을때는, service()메소드를 일반적으로 구현할 필요가 없습니다.
HTTPServlet 클래스는 이미 service()메소드를 구현하고 있기 때문입니다.

HttpServlet.service() 프로토타입


Protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException,IOException;

HttpServlet.service()메소드가 호출되면
이 메소드는 request 안에서 메소드 타입값을 읽어내고 이 값에 따라서 호출할 메소드를 결정합니다.

이 메소드는 우리가 오버라이딩 해야하는 메소드입니다.

메소드 타입이 GET 이면 우리가 오버라이팅 할 메소드는
doGet(),  POST 이면 doPost() 입니다.

service()메소드는 5가지 메소드타입을 가지고 있지만 doGet()과 doPost()만 관심을 가지면 됩니다.

HttpServlet 클래스에 전달되는 파라미터, HttpServletRequest와 HttpServletResponse는
Servlet 클래스에 전달되는 파라미터였던 ServletRequest, ServletResponse 각각을 상속한 클래스입니다.

서블릿의 라이프 사이클
자바서블릿의 라이프사이클은 매우 논리적인 순서를 따르고 있습니다.
라이프사이클 메소드를 선언하고 있는 인터페이스가 javax.servlet.Servlet 인터페이스 입니다.

서블릿 라이프사이클 메소드는 init(), service(), destory() 입니다.

1. init() 메소드를 이용하여 서블릿이 로딩되고 초기화 됩니다.

2. 서블릿이 로딩되면 클라이언트이 요청에 응답을 하는 서비스를 시작하는데 이때 servie() 메소드가 이용됩니다.

3. 서블릿이 shutdown 될때 이용되는 메소드가 destory() 메소드입니다

init()


init() 메소드는 서블릿이 그 일생을 시작하게 하는 메소드입니다.
이 메소드는 서블릿이 인스턴스가 된 후 바로 호출되고, 단 한번만 호출됩니다.
init() 메소드는 request 를 다룰 때 사용하는 자원을 만들고 이 자원을 초기화할때 사용합니다.
init() 메소드의 모습은 다음과 같습니다.

public void init(ServletConfig config) throw ServletException;

init() 메소드는 파라미터로 ServletConfig 객체를 전달받습니다.
init() 메소드는 또한 ServletException을 던질 수 있도록 선언되어 있습니다.

만약 서블릿이 request를 핸들링할 수 있는 자원을 초기화할 수 없게 되었을 때 init() 메소드는 ServletException 을 해당 에러 메시지와 함께 던집니다.

service()


service()메소드는 request/response 패턴을 사용하는 클라이언트로부터 받은 모든 request에 대해 서비스합니다.

service()메소드의 모습은 다음과 같습니다.
public void service( ServletRequest req, ServletResponse res) throws ServletException, IOException;

service()메소드는 2개의 파라미터를 가집니다.
하나는 ServletRequest 객체인데, 클라이언트가 제공한 정보를 담고 있습니다.
다른 하나는 ServletResponse 객체인데, 클라이언트에 보내는 정보를 담고 있습니다.

service() 메소드를 가장 일반적인 구현은 HttpServlet 클래스에서 이루어진다.
HttpServlet 클래스는 GenericSevlet를 상속하므로서 Servlet을 구현합니다.
 
destory()


이 메소드는 서블릿 라이프의 끝을 의미합니다.
웹 애플리케이션이 shutdown 될때, 서블릿의 destory() 메소드가 호출됩니다.
그러면 init() 메소드에 의해 만들어진 모든 자원이 반납됩니다.

destory() 메소드의 모습은 다음과 같습니다.

public void destroy(); 

간단한 서블릿 예제와 설명이제 서블릿이 무엇이고 어떻게 작동하는에 관한 기본적인 이해를 가지게 되었습니다.
간단한 서블릿에 예제를 만들어 보겠습니다.

***
SimpleServlet.java ***


package example;

 

import javax.servlet.*;

import javax.servlet.http.*;

import java.io.*;

import java.util.*;

 

public class SimpleServlet extends HttpServlet{

             public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

                           doPost(req,res);

             }

             public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

 

                           res.setContentType("text/html;charset=euc-kr");

                           PrintWriter out=res.getWriter();

 

                           out.println("<html>");

                           out.println("<head><title>Simple Servlet</title></head>");

                           out.println("<body>");

 

                           //요청한 클라이언트의 IP를 출력합니다.

                           out.println("Your address is " + req.getRemoteAddr() + "\n");

                           out.println("</body></html>");

                           out.close();

             }

}

 

※ 여기서 주의하여 볼 것은 SimpleServlet가 init() 과 destory()메소드를 구현하고 있지 않는다는 것입니다.
이들 메소드는 GenericServlet 이 기본적으로 두개의 메소드를 구현하고 있기에 구현하지 않아도 되는 것이죠

SimpleServlet을 컴파일, 실행

0. http://www.okjsp.pe.kr 에서 Frequently Asked Question 의 서블릿 접근이 안되는 경우에서 web.xml 파일을

{TOMCAT_HOME}/conf 에 복사합니다. (그전에 기존의 web.xml 파일은 백업을 하는 것이 좋겠습니다)
1. servlet.jar를 CLASSPATH에 추가시킵니다.
2. SimpleServlet 컴파일합니다. 
javac –d . SimpleServlet.java
3. http://localhost:8080/bbs/servlet/example.SimpleServlet 를 방문해서 결과를 확인합니다.

<결과 화면>

사용자 삽입 이미지

※ 전 글에서 아파치와 연동을 위한 작업을 했기 때문에 localhost 다음에 포트 번호가 빠져도 실행이 됩니다.

SimpleServlet에 접근하기 위한 URL에 /servlet 이 포함되어 있어야 합니다.
이렇게 하므로써 컨테이너에게 서블릿을 찾고 있음을 알리게 됩니다.

SimpleServlet 코드 설명


SimpleServlet 에서 doGet()과 doPost()
이 두 메소드는 SimpleServlet 에서 오버라이드한 메소드입니다.
모든 비즈니스 로직이 이곳에 존재합니다.
예제에서 doGet() 메소드는 단순히 doPost() 메소드를 호출합니다.

doPost() 의 첫번째 실행라인

res.setContentType("text/html;charset=euc-kr");

이는 response에 대한 컨텐츠타입을 셋팅하는 작업입니다.
이것은 단 한번만 사용이 가능합니다.
또한 OutputStream으로서 PrintWriter를 코딩하기에 앞서 위 코딩 작업이 이루어져야 합니다.

다음은 PrintWriter 을 획득해야 합니다.

왜냐하면 클라이언트의 웹 브라우저에 IP를 나타내기 위해서 입니다.
PrintWriter 의 획득은 ServletResponse 의 getWriter() 을 호출함으로써 이루어집니다.

PrintWriter out = res.getWriter();

PrintWrtier는 클라이언트 응답에 보내지는 스트림에 글을 쓸 수 있게 합니다.
그러면 클라이언트의 브라우저에서 이 글을 볼 수 있게 됩니다.

클라이언트에 텍스트를 보낼 수 있는 객체에 대한 레퍼런스(out)를 얻었으므로,
이 객체를 사용하여 클라이언트에게 메시지를 전달할 수 있는 것입니다.

이 메시지는 HTML를 포함하고 있습니다.
이는 메시지가 클라이언트의 웹브라우저에 보이게 하기 위함입니다.
다음 몇 라인은 이것이 어떻게 행해지는지 보여준다.

out.println("<html>");
out.println("<head><title>Simple Servlet</title></head>");
out.println("<body>");

//요청한 클라이언트의 IP를 출력합니다.
out.println("Your address is " + req.getRemoteAddr() + "\n");

위에서 보듯이 SimpleServlet는 클라이언트에게 HTML을 보내기 위해 PrintWriter의 println()메소드를 사용하고 있습니다.

//요청한 클라이언트의 IP를 출력합니다.

out.println("Your address is " + req.getRemoteAddr() + "\n");


req.getRemoteAddr() 부분은 클라이언트에서 보내온 정보를 이용합니다.
즉, HttpServletRequest 의 getRemoteAddr() 메소드를 호출하여 클라이언트의 주소를 반환받고 있습니다.
이렇게, HttpServeltRequest 는 클라이언트가 보내거나, 클라이언트에 관한 정보를 담고 있습니다.

HttpServletRequest와 HttpServletResponse 객체에 관한 자세한 정보는 썬의 웹사이트에서 찾을 수 있습니다.


http://java.sun.com/products/servlet/

다음은 기본적으로 한번은 읽어 봐야 할 서블릿 클래스와 그의 메소드를 정리해 놓은 것입니다.

하나 하나 다 설명은 없지만 서블릿 API를 통해서 한번쯤은 읽고 넘어간다면 웬만한 JSP에 관한 책은 모두 이 범위 안에 있기에 이해가 쉬울 것입니다.

 

서블릿 클래스 요약

 

Servlet

init()

service()

destroy()

getServletConfig()

getServletInfo()

 

ServletConfig

getInitParameter()

getInitParameterNames()

getServletContext()

 

GenericServlet

log()

 

HttpServlet

doGet()

doPost()

 

ServletContext

setAttribute()

getAttribute()

getRequestDispatcher()

getRealPath()

getResource()

 

RequestDispatcher

forward()

include()

 

ServletRequest

getInputStream()

getParameter()

getParameterValues()

 

HttpServletRequest

getCookie()

getSession()

getSession(boolean created)

 

ServletResponse

getOutputStream()

getWriter()

 

HttpServletResponse

addCookie()

sendRedirect()

 

Servlet API Spec 은 다음 사이트에서 다운로드 받을 수 있습니다.

http://java.sun.com/products/servlet

 

서블릿 연습하기

 

Hello Servlet ! : HelloServlet.java

 

package example;

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

 

public class HelloServlet extends HttpServlet {

             public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException,IOException{

                           res.setContentType("text/html;charset=euc-kr");

                           PrintWriter out=res.getWriter();

                           out.println("<HTML>");

                           out.println("<HEAD><TITLE>Hello Servlet</TITLE></HEAD>");

                           out.println("<BODY>");

                           out.println("Hello Servlet!");

                           out.println("</BODY>");

                           out.println("</HTML>");

                           out.close();

             }

}

 

<설명>

1.HttpServlet 클래스를 상속받은 서블릿 클래스는 public class 로 선언해야 합니다.

 

2.HTTP 의 GET 방식으로 웹 브라우저가 요청해오면 doGet() 메소드를 작성합니다.

(일반적으로 웹서버의 자원을 요청하는 것은 GET 방식의 요청입니다.)

 

3.doGet() 메소드는 HttpServletRequest 와 HttpServletResponse 타입의 아규먼트를 가집니다.

이 메소드는 예외가 발생할 수 있으므로 다음 문장으로 예외를 처리합니다.

throws ServletException, IOExcepiton

 

4. res.setContentType(“text/html;charset=euc-kr”);

은 웹브라우저에 응답으로 출력될 문서의 MIME 타입을 기술합니다.

;charset=euc-kr을 쓰지 않으면 한글이 깨지는 경우가 발생합니다.

setContentType()메소드는 HttpServletResponse 의 메소드입니다.

 

5. PrintWriter out = res.getWriter();

웹브라우저에 대한 출력 스트림을 얻습니다.

out의 plintln() 메소드안에 문자열을 넣으면 그대로 흘러 흘러서 클라이언트의 웹브라우저에 출력된다고 생각하시면 됩니다.

 

6. 주소창에서 /bbs/servlet/ 는 /bbs/WEB-INF/classes 로 접근하기 위한 일종의 약속입니다.

 

7. HelloServlet 서블릿이 어떻게 작동하는가?

클라이언트, 즉 웹브라우저가 서버의 HelloSerlvet 서블릿 자원을 요청합니다.

서블릿엔진인 톰캣은 클라이언트의 요청을 캡슐화한 HttpSerlvetRequest 인터페이스를 구현한 객체와

요청에 대한 응답을 캡슐화한 HttpSerlvetResponse 인터페이스를 구현한 객체를 service(,) 메소드의 아규먼트로 넘깁니다.

HttpServlet은 GenericServlet 의 추상 sevice(,)메소드를 구현한 클래스입니다.

구현내용은 단지 웹브라우저가 헤더로 보낸 HTTP 메소드(GET,POST)에 따라 자동적으로 doGet(,) 또는 doPost(,)메소드를 호출하도록 하는 것이 전부입니다.

(따라서 doGet(,)이나 doPost(,)를 생각하지 않으려면 service(,)메소드를 오버라이딩하면 됩니다.)

객체로 된 HelloServlet 서블릿은 클라이언트의 각각의 요청을 개발자가 구현한 doGet(,), doPost(,) 혹은 service(,) 메소드가 병행적으로 처리하므로써 클라이언트의 요청에 응답하게 됩니다.

 

"Hello Servlet" 을 출력하는 기본적인 예제를 실행해 봤습니다.

이제는 웹브라우저, 즉 클라이언트가 보내는 정보를 어떻게 서블릿에서 다룰 수 있는지 알아봅니다.

정확하게 클라이언트가 보내는 문자열 정보를 서블릿에서 catch하는 코드를 설명합니다.

 

웹 브라우저가 서버에 문자열을 전송하는 방법

HTML FORM 태그를 이용하여 웹브라우저가 서버로 문자열 데이터를 전달하는 방법과 서블릿에서 그 정보를 받는 코드조각은

다음과 같습니다.

                                               è

HTML

서블릿

<input type=text name=addr>

req.getParameter(“addr”);

<input type=radio name=os value=win98>

<input type=radio name=os value=win2000>

req.getParameter(“os”);

<input type=hidden name=cur_page value=1>

req.getParameter(“cur_page”);

<input type=password name=passwd>

req.getParamter(“passwd”);

<input type=checkbox name=hw value=intel>

<input type=checkbox name=hw value=amd>

….

req.getParameterValues(“hw”);

<select name=os multiple>

<option value=”windows”>windows</option>

<option value=”linux”>linux</option>

<option value=”solaris”>solaris</option>

</select>

req.getParameterValues(“os”);

(참고: multiple 속성이 없다면

req.getParameter(“os”)도 가능)

 

위의 내용을 하나 하나 예로 들어 설명합니다.

 

GetData.html / GetData.java

 

HTML FORM 태그의 텍스트필드를 이용한 문자열 전송

 

파일 위치 : /bbs/example/GetData.html , /bbs/WEB-INF/classes/GetData.java

*** GetData.html ***

 

<html><body>

<center><h1>GET 테스트</h1></center>

<form method=POST action=../servlet/example.GetData>

이름 : <input type=text name=name size=20><br>

주소 : <input type=text name=addr size=20><br>

<input type=submit value="전송"><input type=reset value="취소">

</form>

</body></html>

 

*** GetData.java ***

 

package example;

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

 

public class GetData extends HttpServlet {

         public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException,ServletException {

                  res.setContentType("text/html;charset=euc-kr");

                  PrintWriter out = res.getWriter();

                  req.setCharacterEncoding("euc-kr");

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

                  String addr = req.getParameter("addr");

                  out.println("<html><body>");

                  out.println("<center><h2>GET TEST</h2></center>");

                  out.println("<li>이름 : "+name);

                  out.println("<li>주소 : "+addr+"<br>");

                  String path = req.getContextPath();

                  out.println("<a href="+path+"/example/GetData.html>뒤로</a>");

                  out.println("</body></html>");

                  out.close();

         }

}

 

<설명>

 

1. HTML문서와 서블릿간의 상대경로에 주의합니다.

HTML이나 JSP에서 서블릿을 링크할때는 /servlet/을 컨텍스트 루트처럼 생각하고 상대경로를 걸면 해결됩니다.

하지만 서블릿 코드에서 HTML문서나 JSP문서에 링크를 걸때는 req.getContextPath() 메소드를 통해 풀패스를 얻어서 경로를 걸어야 확실합니다.

 

2. 서블릿 소스에 package 가 선언되어 있다면 그 서블릿은 팩키지명.서블릿클래스명 으로 접근합니다.

 

3. HttpServletRequest 의 setCharacterEncoding(“euc-kr”)은 웹브라우저,즉 클라이언트가 보내는 한글 데이터를 한글 인코딩으로 받기 위한 것입니다.

이 코드조각이 없다면 클라이언트가 보낸 한글 데이터는 깨질 것입니다.

반면 HttpServletResponse.setContentType() 메소드는 서블릿이 만드는 HTML문서의 타입과 문자셋을 지정하는 것입니다.

혼동하지 말기 바랍니다.

 

4. HttpServletRequest 의 getParameter() 메소드는 가장 보편적으로 웹브라우저에서 사용자가 보내는 데이터를 받기 위한 메소드입니다.

 

6. 상대경로 문제

JSP 나 HTML 문서에서 서블릿을 링크시킬때는 /bbs/servlet/까지를 Context Base 라고 생각하고 일반적인 상대경로 개념으로 접근합니다.

서블릿에서 JSP 나 HTML문서를 링크시킬때는

req.getContextPath() 로 일단 Context base 경로를 구한후에 이를 이용해 경로를 링크시키면 됩니다.

 

톰캣4.1.30 버전에서 테스트 할 때는 GET 방식으로 클라이언트가 보낸 한글 이름과 주소가 정상적으로 출력이 되었으나 5.0.28 에서 테스트 할 때에는 한글이 깨져서 나옵니다.

근본적인 해결책은 아직 못찾아보았고, 대신 GET방식이 아닌 POST 방식으로만 서버에 정보를 보내도록 프로그래밍하면 되겠습니다.

GET 방식으로도 html form 에 입력한 한글을 정상적으로 출력하도록 하는 근본적인 해결책은 찾으시면 제게도 알려주시면 감사하겠습니다.

 

MultiCheck.html / MultiCheck.java

 

HTML FORM 태그의 체크박스를 이용한 문자열 전송

 

파일 위치 : /bbs/example/MultiCheck.html , /bbs/WEB-INF/classes/MultiCheck.java

 

*** MultiCheck.html ***

 

<html><body>

<center><h2>체크박스 다중 선택 테스트</h2></center>

<form method=POST action="../servlet/example.MultiCheck"><br>

다음중 사용중인 소프트웨어를 선택해 주세요<br>

<input type=checkbox name=sw value="jdk1.4">jdk1.4<br>

<input type=checkbox name=sw value="한글">한글<br>

<input type=checkbox name=sw value="MS오피스">MS오피스<br>

<input type=submit value="전송">

<input type=reset value="취소">

</form>

</body></html>

 

*** MultiCheck.java ***

 

package example;

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

 

public class MultiCheck extends HttpServlet {

         public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {

                  res.setContentType("text/html;charset=euc-kr");

                  PrintWriter out = res.getWriter();

                  req.setCharacterEncoding("euc-kr");

                  String[] values = req.getParameterValues("sw");

                  out.println("<html><body>");

                  out.println("선택한 사용중의 소프트웨어는 아래와 같습니다.");

                  if(values!=null){

                           for(int i=0;i<values.length;i++){

                                   out.print("<li>");

                                   out.print(values[i]);

                                   out.println("<br>");

                           }

                  }

         }

}

 

<설명>

 

1. 웹브라우저를 통해 사용자가 다중선택을 하여 전송하는 데이터의 경우는 HttpServletRequet 의

getParamter() 메소드가 아닌 getParamterValues() 메소드가 쓰입니다.

이 메소드의 리턴값은 사용자가 선택한 값들만으로 구성된 String 배열입니다.

 

SelectItems.html / SelectItems.java

 

HTML FORM 태그의 Select 태그를 이용한 문자열 전송

 

파일 위치 : /bbs/chapter3/SelectItems.html , /bbs/WEB-INF/classes/SelectItems.java

 

*** SelectItems.html ***

 

<HTML><BODY>

<center><h2>SELECT 테스트</h2></center>

<form method=POST action=../servlet/example.SelectItems>

개발환경 운영 체제는?<br>

<select name=os size=3 multiple>

         <option value="윈도우">윈도우</option>

         <option value="리눅스">리눅스</option>

         <option value="솔라리스">솔라리스</option>

         <option value="기타">기타</option>

</select>

<br><br>

사용중인 초고속통신망은?<br>

<select name="초고속통신서비스" multiple>

         <option value="매가패스">매가패스</option>

         <option value="하나포스">하나포스</option>

         <option value="두루넷">두루넷</option>

         <option value="기타">기타</option>

</select>

<input type=submit value="전송">

<input type=reset value="취소">

</form></BODY></HTML>

 

*** SelectItems.java ***

 

package example;

import java.io.*;

import java.util.*;

import javax.servlet.*;

import javax.servlet.http.*;

public class SelectItems extends HttpServlet {

         public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException,ServletException {

                  res.setContentType("text/html;charset=euc-kr");

                  PrintWriter out = res.getWriter();

                  req.setCharacterEncoding("euc-kr");

                  Enumeration e = req.getParameterNames();

                  while(e.hasMoreElements()){

                           String name = (String)e.nextElement();

                           String values[] = req.getParameterValues(name);

                           if(values!=null){

                                   out.println("<li>");

                                   out.println(name + "중 아래 항목을 선택하셨습니다.<br>");

                                   for(int i=0;i<values.length;i++){

                                            out.println(values[i]);

                                            out.println("|");

                                   }

                           }

                           out.println("<br>");

                  }

                  String path = req.getContextPath();

                  out.println("<a href=" + path + "/example/SelectItems.html>뒤로</a>");

         }

}

 

<설명>

 

만약 사용자가 어떤 파라미터명으로 데이터를 보내는지 알수 없다고 가정을 합니다(그럴 경우는 거의 없지만)

이때 사용자가 보내는 파라미터명을 알 수 있는 메소드가 HttpServletRequest getParamterNames()입니다.

getParameterNames() 메소드는 리턴값으로 Enumeration 타입을 반환합니다.

(Enumeration 은 hasMoreElements() , nextElement() 2개의 메소드를 이용할 줄 알면 됩니다.)

 

MultiItems.html / MultiItems.java

 

HTML FORM 태그의 라디오버튼을  이용한 문자열 전송

 

파일 위치 : /bbs/chapter3/MultiItems.html, /bbs/WEB-INF/classes/MultiItems.java

 

*** MultiItems.html ***

 

<HTML><BODY>

<center><h2>라디오 버튼 테스트</h2></center>

<form method=POST action=../servlet/example.MultiItems>

다음 사항을 선택해 주세요<br>

사용중인 운영체제는?<br>

<input type=radio name=os value="windowsXP">windowsXP<br>

<input type=radio name=os value="windowsMe">windowMe<br>

<input type=radio name=os value="window98">windows98<br>

<input type=radio name=os value="redhat90">redhat90<br>

사용중인 컴퓨터 하드웨어는?<br>

<input type=radio name=hw value="intel">intel<br>

<input type=radio name=hw value="amd">amd<br>

<input type=radio name=hw value="기타">기타<br>

사용중인 초고속통신회사는?<br>

<input type=radio name="telecom" value="매가패스">매가패스<br>

<input type=radio name="telecom" value="하나포스">하나포스<br>

<input type=radio name="telecom" value="두루넷">두루넷<br>

<input type=submit value="전송">

<input type=reset value="취소">

</form></BODY></HTML>

 

*** MultiItems.java ***

 

package example;

import java.io.*;

import java.util.*;

import javax.servlet.*;

import javax.servlet.http.*;

 

public class MultiItems extends HttpServlet{

         public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException,ServletException{

                  res.setContentType("text/html;charset=euc-kr");

                  PrintWriter out = res.getWriter();

                  req.setCharacterEncoding("euc-kr");

                  Enumeration e = req.getParameterNames();

                  while(e.hasMoreElements()){

                           String name=(String)e.nextElement();

                           String value=req.getParameter(name);

                           out.println("<li>");

                           out.println(name + "|");

                           out.println(value);

                           out.println("<br>");

                  }

         }

}

 

 

RequestDispatcher 사용 예제

 

파일 위치 : /bbs/WEB-INF/classes/IncludingServlet.java , /bbs/WEB-INF/classes/In.java

 

*** IncludingServlet.java ***

 

package example;

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

public class IncludingServlet extends HttpServlet {

             public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException ,ServletException{

                           res.setContentType("text/html;charset=euc-kr");

                           PrintWriter out = res.getWriter();

                           out.println("<html><body>");

                           out.println("<center><h2>Including Servlet</h2></center>");

                           out.println("다음 내용은 다른 서블릿의 내용을 inlcude한 것입니다<hr>");

                           ServletContext sc = getServletContext();

                           RequestDispatcher rd= sc.getRequestDispatcher("/servlet/example.In");

                           rd.include(req,res);

                           out.println("<hr>이곳은 다시 IncludingServlet 입니다.");

                           out.println("</body></html>");

             }

}

 

*** In.java ***

 

package example;

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

public class In extends HttpServlet {

             public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

                           res.setContentType("text/html;charset=euc-kr");

                           PrintWriter out = res.getWriter();

                           out.println("안녕하세요");

                           out.println("IN 서블릿입니다.");

             }

}

 

ServletConfig 의 getInitParameter() 사용 예제

 

파일 위치 : /bbs/WEB-INF/classes/InitParam.java

 

*** InitParam.java ***

 

package example;

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

 

public class InitParam extends HttpServlet {

             String file;

             long  counter;

             public void init() throws ServletException {

                           ServletContext cxt = getServletContext();

                           file = getInitParameter("file");

                           if(file != null) {

                                        try {

                                                     file = cxt.getRealPath(file);

                                                     DataInputStream in = new

                                                                  DataInputStream(new FileInputStream(file));

                                                     counter = in.readLong();

                                                     in.close();

                                        } catch (Exception e) { }

                           }

             }

             public void service(HttpServletRequest req,

             HttpServletResponse res) throws IOException, ServletException {

                           res.setContentType("text/html;charset=euc-kr");

                           PrintWriter out = res.getWriter();

                           out.println("<html><head><title>방문자 수</title></head>");

                           out.println("<body> <center><h2>방문자 수</h2>");

                           out.println("</center><hr>");

                           out.print("file = " + file + "<br>");

                           counter++;

                           out.print(counter);

                           out.println(" 번째 손님입니다.");

             }

public void destroy() {

                           if(file != null) {

                                        try {

                                                     DataOutputStream out = new

                                                                  DataOutputStream(new FileOutputStream(file));

                                                     out.writeLong(counter);

                                                     out.close();

                                        } catch(Exception e) {

                                                     System.out.println(e);

                                        }

                           }           

             }

}

 

위 파일을 실행하기에 앞서 /bbs/WEB-INF/web.xml 파일을 아래를 추가합니다.

<servlet>

        <servlet-name>example.InitParam</servlet-name>

        <servlet-class>example.InitParam</servlet-class>

        <init-param>

               <param-name>file</param-name>

               <param-value>counter.dat</param-value>

        </init-param>

</servlet>

 

(전체 내용에 대해서는 제가 여기까지 설정한 /bbs/WEB-INF/web.xml 파일을 올립니다 첨부파일을 참고하세요)

 

그런 다음 counter.dat 란 파일을 /bbs 에 생성합니다.

다음으로 톰캣을 재시동합니다.

어느정도 InitParam 서블릿을 실행한 다음 InitParam 서블릿을 강제로 내리기 위해서 톰캣을 재시동합니다.

그런 다음 다시 InitParam 서블릿을 요청하여 방문횟수가 저장되었는지 확인합니다.

 

http://localhost/bbs/servlet/InitParam

 

 

서버에서 클라이언트로 이미지 전송시키는데 이용하는 메소드 소개

res.setContentType(“image/gif”); // jpg 이미지는 (“image/jpeg”)

ServletOutputStream out = res.getOutputStream(); // 바이너리 데이터 전송이므로

 

서버에서 클라이언트로 MS오피스 타입의 자료 전송하는데 이용하는 메소드 소개

엑셀의 경우 : res.setContentType(“application/vnd.ms-excel;charset=euc-kr”);

워드의 경우 : res.setContentType(“application/vnd.msword;charset=euc-kr”);

 

파일 업로드을 위한 MultipartRequest 팩키지 사용 방법

MultipartRequest 팩키지는 썬에서 만든 표준 라이브러리가 아니지만 현재 파일 업로드에 널리 이용되고 있는 팩키지입니다.

(파일로 첨부합니다)

 

MultipartRequest 클래스의 생성자 소개

MultipartRequest(HttpServletRequest req, String dir)

dir 디렉토리에 파일을 업로드할 MultipartRequest 객체 생성

MultipartRequest(HttpServletRequest req, String dir, int max)

아규먼트의 max는 업로드 가능한 파일의 최대크기를 나타낸다.

MultipartRequest(HttpServletRequest req, String dir, int max, boolean overwrite, boolean save)

아규먼트의 overwrite는 파일시스템에 동일한 파일이 있으면 덮어쓰는가 여부를 나타낸다.

아규먼트의 save는 파일시스템에 저장하는지 여부를 나타낸다.

 

MultipartRequest 메소드 소개

<input type=file name=pic01> ç 파일찾기로 images.gif 를 업로드했다고 가정하면,

서버에서 MultipartRequest를 사용했다면 아래 메소드를 이용할 수 있습니다.

 

getContentType(“pic01”) : 업로드된 파일의 MIME 타입 리턴 (image/gif)

getFile(“pic01”) : 업로드되어 서버에 저장된 File 객체 리턴

getFileNames() : 업로드된 모든 파일들의 이름을 리턴 (여기서는 Enumeration 에 pic01 저장)

getFilesystemName(“pic01”) : 파일의 파일시스템 이름을 리턴 (images.gif)

 

HttpServletRequest 와 같은 인터페이스 제공하기 위한 메소드를 제공합니다.

getParameter()

getParameterNames()

getParameterValues()

 

MultipartRequest 를 이용한 파일 업로드 예제

파일위치 : /bbs/example/upload.html , /bbs/WEB-INF/classes/UploadTest.java

 

*** upload.html ***

 

<HTML><BODY>

<center><h2>파일 업로드</h2></center>

<form action=../servlet/example.UploadTest method=POST ENCTYPE=multipart/form-data>

이름 : <input type=text name=submitter><br>

업로드할 파일 : <input type=file name=file1><br>

업로드할 파일 : <input type=file name=file2><br>

<input type=submit value="전송">

</form>

</BODY></HTML>

 

*** UploadTest.java ***

 

package example;

import java.io.*;

import java.util.*;

import javax.servlet.*;

import javax.servlet.http.*;

import com.oreilly.servlet.MultipartRequest;

public class UploadTest extends HttpServlet {

         public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {

                  res.setContentType("text/html;charset=euc-kr");

                  PrintWriter out = res.getWriter();

                  req.setCharacterEncoding("euc-kr");

                  ServletContext cxt = getServletContext();

                  String dir = cxt.getRealPath("tmp");

                  try{

                           MultipartRequest multi = new MultipartRequest(req,dir,5*1024*1024);

                           out.println("<html>");

                           out.println("<head><title>파일 업로드</title></head>");

                           out.println("<body>");

                           out.println("<h2>파일 업로드</h2>");

                           out.println("<h3>Params</h3>");

                           out.println("<pre>");

                           Enumeration params = multi.getParameterNames();

                           while(params.hasMoreElements()){

                                   String name=(String)params.nextElement();

                                   String value=multi.getParameter(name);

                                   out.println(name+"="+value);

                           }

                           out.println("</pre>");

                           out.println("<h3>업로드된 파일</h3>");

                           out.println("</pre>");

                           Enumeration files=multi.getFileNames();

                           while(files.hasMoreElements()){

                                   String name=(String)files.nextElement();

                                   String filename=multi.getFilesystemName(name);

                                   String type=multi.getContentType(name);

                                   File f=multi.getFile(name);

                                   out.println("파라메터 이름 : "  + name + "<br>");

                                   out.println("파일 이름 : " + filename + "<br>");

                                   out.println("파일 타입 : " + type + "<br>");

                                   if(f!=null){

                                            out.println("크기: " + f.length() + "<br>");

                                            out.println("<br>");

                                   }

                           }

                           out.println("</pre>");

                  }catch(Exception e){

                           out.println("<pre>");

                           e.printStackTrace(out);

                           out.println("</pre>");

                  }

                  out.println("</body></html>");

         }

}

 

<설명>

 

1. 테스트는 /bbs/tmp 라는 디렉토리를 만듭니다.

2. 컴파일을 위해 cos.jar 파일을 CLASSPATH에 추가하고 컴파일합니다.

3. cos.jar 파일을 /bbs/WEB-INF/lib 아래 복사 후 톰캣 재가동합니다.

 

2 단계에서 컴파일이 안된다고요?

cos.jar 파일안의 MultiparFormRequest 팩키지에 대한 클래스 패스가 잡히지 않아서입니다.

cos.jar 파일의 클래스 패스를 잡아줍니다.

클래스 패스를 잡기 위해서는 cos.jar 파일을 적당한 위치에 복사한다음 그 경로를 CLASSPATH 에 추가하면 됩니다.

jar 파일이므로 cos.jar 라는 이름까지 추가하셔야 합니다.

제 경우는 F:\javaschool_lib 라는 폴더를 만들고 그 아래에 cos.jar 파일을 복사했습니다.

그리고 F:\javaschool_lib\cos.jar 라는 경로를 CLASSPATH에 추가한다음 컴파일을 했습니다.

 

모두 잘 한것 같은데 파일 업로드를 시도하니 HTTP Status 500 - 에러가 나온다고요?

에러 메시지를 잘 보시면

 

java.lang.NoClassDefFoundError: javax/activation/DataSource

 

위와 같은 메시지가 있습니다. 여기서 힌트를 얻어서 해결책을 찾아보면 ...

JavaBeans(TM) Activation Framework 라는 팩키지가 필요한데 이것에 대한 팩키지는 j2sdk에 들어있지 않습니다.

따라서 http://java.sun.com 에 방문해서 jaf라는 이름으로 검색해서 팩키지를 다운로드 받아야 합니다.

그리고 이 파일을 {JAVA_HOME}/jre/lib/ext 폴더에 복사합니다.

그런 다음 톰캣을 재가동한 후 다운로드를 다시 시도합니다.

꼭 필요한 것 같으나 j2sdk에 포함되지 않은 팩키지가 이것 말고 javamail 팩키지 입니다.

메일과 관련된 프로그램을 위해서도 이 팩키지를 다운로드 받고 압축을 풀고 mai.jar 파일을

{JAVA_HOME}/jre/lib/ext 폴더에 복사하도록 합니다.

 

에러가 없다면 /bbs/tmp 폴더로 가서 확인합니다.

파일명이 바뀌었습니다.

이 팩키지는 MultipartRequest 원본이 아니고 최종명씨가 저자인 "웹 프로그래머를 위한 서블릿/JSP" 란 책에 첨부된 팩키지입니다.

아마도 파일명이 절대로 같게 하지 않게 소스를 변경해서 컴파일한 후 배포한 것으로 생각합니다.

(파일명 뒤에 시스템의 시간이 붙는 것 같습니다)

cos.jar 팩키지에는 소스가 없습니다.

따라서 이것이 마음에 들지 않다면 MultipartRequest 팩키지를 이용하기 위해서는 다른 곳에서 구해야 합니다.

(저는 개인적으로 이게 더 좋습니다.)

 

쿠키

 

HTTP 전송방식의 특징상 각각의 웹 브라우저가 서버와 통신에서 세션을 유지하지 못하는 것을 보완하기 위한 기술입니다.

서버가 쿠키를 전송하면 웹 브라우저는 그 다음 요청마다 쿠키 값이 서버로 전달하여 사용자 정보를 유지할 수 있게 됩니다.

(쇼핑몰의 장바구니, 회원로그인이 필요한 웹 사이트에 쓰임)

 

서버 à 웹 브라우저 (쿠키를 굽는다고 표현되는데 아래와 같은 정보가 클라이언트의 웹 브라우저로 날아가서 셋팅합니다)

 

Set-Cookie : name = value ; expires = date ; path = path ; domain = domain ; secure

 

웹 브라우저 à 서버 (쿠키가 웹브라우저에 셋팅되면 그 다음부터의 요청시마다 웹 브라우저는 아래와 같은 문자열을 쿠키를 준 서버로 보내게 됩니다. 단 쿠키를 구어준 서버가 아니면 이런 정보를 보내지 않습니다)

 

Cookie ; name = value1 ; name2 = value2 ; …

 

쿠키값이 이름과 값으로 얼마든지 만들 수 있는 것은 아닙니다.

 

쿠키 설정 절차

 

1. Cookie 객체를 만든다. Cookie(String name, String value) 이때 value에 해당하는 값을 인코딩

2. 쿠키에 속성을 부여 : setValue(),setDomain(),setMaxAge(),setPath(),setSecure()

3. 쿠키를 전송 : res.addCookie(cookie);

 

서블릿에서 쿠키 이용

...

Cookie[] cookie = req.getCookie();

String name = cookie[i].getName();

If(name.equals(“id”){

        

}

...

 

String value = cookie[I].getValue();

 

서블릿에서 쿠키 삭제

 

삭제하고자 하는 쿠키와 같은 이름의 쿠키를 생성하고 setMaxAge(0) 을 호출합니다.

...

Cookie name = new Cookie(“name”,””);

name.setMaxAge(0);

res.addCookie(name);

...

 

세션

 

세션은 쿠키 기반 기술로 쿠키의 보안상 약점을 극복하기 위한 기술입니다.

쿠키와 다른 점(즉, 보안상 개선된 점) : 웹브라우저는 서버가 정해준 세션ID만을 쿠키값으로 저장합니다.

세션이 생성되면(즉, 세션ID 쿠키가 구워지면) 세션ID 쿠키만을 서버로 전송하게 되고,

서버에서는 세션ID로 해당 HttpSession 객체를 호출하게 되어(이 작업을 서블릿 컨테이너가 해야 함)

웹브라우저와 세션과의 통신이 이루지게 됩니다.

 

HttpSession 의 메소드 소개

 

setAttribute(String name , Object value)

getAttribute(String name)

removeAttribute(String name)

invalidate();

 

사용법

세션 생성 : HttpSession session = req.getSession(true); //true 일때 세션이 없으면  생성합니다.

HttpSession session = req.getSession(false); // false 일때 세션이 없다면 null 을 리턴

세션에 정보 저장 : session.setAttribue(“data”,value); //data 이름으로 value 객체 저장

 

File 클래스

 

자바에서는 파일을 표현하기 위해 File 클래스를 사용합니다.

디렉토리도 File 클래스로 표현됩니다.

주의할 것은 File 클래스는 파일을 읽거나 쓰는 메소드는 가지고 있지 않습니다.

파일을 읽거나 쓰기 위해서는 입출력 클래스를 사용합니다.

 

File 클래스로 할 수 있는 작업

 

디렉토리 내용을 알아본다.

파일의 속성을 알아보거나 설정합니다.

파일의 이름을 변경하거나 삭제합니다.

 

File 클래스 생성

객체 생성 : File dir = new File(path);

주의) 여기서 path 에 해당하는 파일이나 디렉토리는 시스템의 풀패스가 되어야 한다는 것입니다.

 

File 클래스 중요 메소드 소개와 사용법

 

isDirectory()  : dir.isDirectory(); // dir 이 디렉토리이면 true 리턴

isFile() : dir.isFile(); // dir 이 파일이면 true 리턴

list() : dir.list() : // dir 이 디렉토리일 때 디렉토리에 있는 파일명이 String[] 값으로 리턴

listFiles() : dir.listFiles(); // 디렉토리에 있는 파일의 파일 객체 배열 리턴

mkdir() : dir.mkdir(); //  File객체의 이름을 가진 디렉토리를 만든다

getName() : 파일명을 리턴

getPath() : 경로를 리턴

delete() : 파일을 지운다.

exists() : 파일이 존재하는지 여부를 알려준다.

 

이것으로 아주 간단하게 서블릿 문법을 살펴보았습니다.

서블릿에 대한 이해가 있어야 JSP 할때에 이해가 쉽습니다.

그리고 성능향상을 위해서 JSP 프로젝트에서 서블릿이 종종 쓰입니다.

 

그럼 다음은 JSP 문법으로 넘어갑니다.

<출처: http://cafe.naver.com/webprogramguide/88 >

반응형

Tomcat 설치와 JDBC 연동이 확인됐다면 JSP 프로그래밍을 위한 준비가 되었다고 생각합니다.


다음으로는 톰캣과 웹 애플리케이션에 대해서 간단히 설명을 하겠습니다.

톰캣은 순수 자바로 만든 자바 웹 애플리케이션의 컨테이너라고 표현합니다.

컨테이너란 그릇이란 뜻인데 담는 내용물이 자바 웹 애플리케이션입니다.


자바 웹 애플리케이션을 담는 것뿐만 아니라 웹상에서 클라이언트의 요구에 따라 자바 웹 애플리케이션이 서블릿, JSP 스펙에 따라서

동작하도록 하는 것을 자바 웹 애플리케이션 컨테이너가 하는 일입니다.


JSP 서블릿을 서비스하기 위해서는 컨테이너를 선택하여 서버상에 동작하도록 해야 합니다.

우리는 Tomcat 을 선택했고 지난 글에서 설치를 하였습니다.


자바 웹 애플리케이션에 대해서 좀더 자세하게 살펴봅시다


자바 웹 애플리케이션란?


"자바 웹 애플리케이션은 서블릿, html 페이지, 클래스, 그리고 그 외 자원의 집합인데
이들 자원은 번들화될 수 있고, 이 번들은 다양한 벤더의 다양한 컨테이너에서 작동할 수 있다."

간단하게 정리하면, 웹 애플리케이션은 다음 리스트의 어떠한 결합도 유지할 수 있는 것을 자바 웹 애플리케이션이라고 할 수 있습니다.

* Servlets
* Java Server Pages (JSPs)
* utility classes, JavaBeans
* 정적 엘리먼트 HTML, images 등
* 클라이언트 사이드 classes
* 자바 웹 애플리케이션을 설명하는 메타 정보

또 한가지 중요한 것은, 웹 애플리케이션의 주요 특징 중 하나가 ServletContext 과 웹 애플리케이션과의 관계라는 것입니다.
각각의 웹 애플리케이션은 오직 하나의 ServletContext를 가집니다.
이 관계는 서블릿 컨테이너에 의해 유지되고, ServletContext 안의 객체에 두개의 웹 애플리케이션
이 접근할때 충돌이 일어나지 않게 하는 것을 보장합니다.
참고로 ServletContext는 웹 애플리케이션의 컴포넌트간 공동 저장소로서 주로 이용됩니다.
공동 저장소로서 사용되는 예제는 뒤에서 살보겠습니다.


자바 웹 애플리케이션은 위와 같은 파일들의 모임인데 이 파일들이 위치하는 디렉토리도 일정하게 정해져 있으므로 알맞은 위치에서

두어야 서비스 할 수 있습니다.


자바 웹 애플리케이션의 디렉토리 구조

%% 이클립스에 설정하요 사용시 디렉토리 구조가 다를수 있다. %% 

만약 {Tomcat}/webapps 디렉토리에 웹 애플케이션을 새로 설치한다면 {Tomcat}/webapps 아래에 다음과 같은 디렉토리 구조를 가지게 됩니다.

(우리가 새로 작업할 디렉토리명을 mnd라고 정했다면..)


/mnd
웹 애플리케이션 root 디렉토리입니다 , 모든 JSP, HTML 파일을 여기에 저장합니다.

서브 디렉토리 역시 만들 수 있습니다.


/mnd/WEB-INF
root 디렉토리에 있지 않은 모든 자원을 여기에 위치시킵니다.
여기에는 웹 애플리케이션 배치 정의자 (web.xml)가 위치합니다.
클리이언트가 직접적으로 접근할 수 있는 파일은 이곳에 없습니다.

/mnd/WEB-INF/classes
Servlets 과 사용자 유틸리티 클래스, 자바빈을 이곳에 저장합니다.

/mnd/WEB-INF/lib
웹 애플리케이션이 사용하는 자바 아카이브 파일을 이곳에 저장합니다.
예를들면 JDBC 드라이버나 태그 라이브러리를 구성하는 jar 파일을 이곳에 저장합니다.

웹 애플리케이션 디렉토리에서 주목해야 할 것은
컴파일된 클래스 파일이 위치하는 곳이 두 군데 라는 것입니다.
하나는 /mnd/WEB-INF/classes 이고 다른 하나는 /mnd/WEB-INF/lib 입니다.
만일 똑같은 객체가 이들 두곳에 위치합니다면 어떻게 될까요?
클래스 로더는 먼저 /mnd/WEB-INF/classes 에서 로딩하고 그 다음에 /mnd/WEB-INF/lib 를 로딩하게 됩니다.
따라서 /mnd/WEB-INF/classes 에 있는 클래스가 우선권을 가지고 로딩되고 /lib 에 있는 클래스는 무시된다고 합니다.

하지만 중복되지 않게 하는 것이 더 중요하겠지요.


다음은 /mnd/WEB-INF/ 내에 있는 파일인 web.xml 파일을 좀 더 정리합니다.


Deployment Descriptor (배치자) 설명


웹 애플리케이션의 심장은 Deployment Descriptor (배치자)라고 불리는 web.xml 이라는 이름의 XML파일입니다.
Deployment Descriptor 는 /mnd/WEB-INF/ 디렉토리안에 둡니다.

배치자는 웹 애플리케이션의 모든 설정 정보를 정의합니다.
배치자 파일이 가지고 있는 정보는 다음과 같습니다


* servlet 정의
* servlet 초기 파라미터
* session 설정 파라미터
* servlet/JSP 매핑
* MIME 타입 매핑
* 보안 설정 파라미터
* welcome 파일 리스트
* 에러 페이지 리스트
* 자원과 환경 변수 정의

web.xml 의 예

<web-app>
   <display-name>The Mnd App</display-name>
   <session-timeout>30</session-timeout>
   <servlet>
      <servlet-name>TestServlet</servlet-name>
      <servlet-class>kr.go.mnd.TestServlet</servlet-class>
      <load-on-startup>1</load-on-startup>
      <init-param>
         <param-name>name</param-name>
         <param-name>value</param-name>
      </init-param>
   </servlet>
</web-app>


<display-name>은 단순히 웹 애플리케이션의 이름을 나타냅니다.
이것은 아무런 기능도 하지 않습니다.

<session-timeout> 은 애플리케이션의 HttpSession 객체의 라이프타임을 컨트롤합니다.
위의 <session-timeout> 값은 JSP/servlet 컨테이너에게 HttpSession 객체가 30분 동안 아무런
움직임이 없다면 소멸될 것이라는 것을 알려줍니다.

<servlet>은 servlet과 해당 servlet 의 프로퍼티를 나타냅니다.


web.xml 파일은 간단한 웹 애플리케이션의 경우 생략이 가능합니다.


팩킹 (Packing)

위 디렉토리 구조로 개발이 완료되었다면 웹 애플리케이션을 번들화 하여 다른 웹 애플리케이션 컨테이너에 배포를 할 수 있습니다.


배포를 하기 위해서는 웹 애플리케이션의 루트 디렉토리에서 다음과 같은 명령을 내려 war 확장자를 가진 war 파일을 만듭니다.


jar cvf mnd.war .


그러면 mnd.war 파일이 만들어지는데 이 파일을 다른 톰캣 컨테이너에 배포를 하는 방법은 다른 톰캣 컨테이너의 webapps 디렉토리에 두면 자동으로 서비스를 할 수 있게 톰캣이 알아서 자동으로 우리의 mnd 애플리케이션을 배치합니다.


다른 방법으로는 톰캣의 manager 툴을 이용하는 방법이 있습니다.


이 툴은 톰캣을 설치하면 같이 설치가 되는 툴이며 이것 역시 웹 애플리케이션입니다.

<출처: http://cafe.naver.com/webprogramguide/88 >

반응형

목차

가. JDBC 프로그래밍 환경 셋업
나. JDBC 프로그래밍 방법

가. JDBC 프로그래밍 환경 셋업

(1) 데이터베이스에 맞는 JDBC 드라이버를 구합니다.
Oracle용 JDBC Thin 드라이버는 오라클을 설치하면 [ORACLE_HOME]/jdbc 디렉토리에 자동으로 설치가 됩니다.

보통은 이 파일을 그대로 쓰시면 됩니다.

더 자세한 사항은 http://www.oracle.com/technology/global/kr/index.html 에서 찾으시기 바랍니다.

(2)[ORACLE_HOME]/jdbc 디렉토리에 있는 다음 파일을 CLASSPATH에 추가합니다.

classes12.jar , nls_charset12.jar 파일의 경로를 CLASSPATH에 추가합니다(현재는 . 만 되어 있습니다.)

예).;C:\oracle\product\10.1.0\db_1\jdbc\lib\classes12.jar;C:\oracle\product\10.1.0\db_1\jdbc\lib\nls_charset12.jar

다음에 명령 프롬프트를 새로 띄우고 set classpath 입력합니다.

CLASSPATH가 제대로 잡혔는지 확인합니다.


(3) GetEmp.java 파일로 JDBC 연동 테스트

파일명: GetEmp.java

import java.sql.*;


public class GetEmp {
    public static void main(String[] args) {
        // 위 부분은 설치과정에서 자신이 정한 정보에 맞게 바꾼다.
        String DB_URL = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
        String DB_USER = "scott";
        String DB_PASSWORD = "tiger";
        Connection conn;
        Statement stmt;
        ResultSet rs;
        String query = "select * from emp";

        try {
            // 드라이버를 로딩한다.
            Class.forName("oracle.jdbc.driver.OracleDriver");
            // 데이터베이스의 연결을 설정한다.
            conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
            // Statement를 가져온다.
            stmt = conn.createStatement();
            // SQL문을 실행한다.
            rs = stmt.executeQuery(query);
            while (rs.next()) {
                String empno = rs.getString(1);
                String ename = rs.getString(2);
                String job = rs.getString(3);
                String mgr = rs.getString(4);
                String hiredate = rs.getString(5);
                String sal = rs.getString(6);
                String comm = rs.getString(7);
                String depno = rs.getString(8);

                // 결과를 출력한다.
                System.out.println(
                        empno + " : " + ename + " : " + job + " : " + mgr
                        + " : " + hiredate + " : " + sal + " : " + comm + " : "
                        + depno);
            }
            // ResultSet를 닫는다.
            rs.close();
            // Statement를 닫는다.
            stmt.close();
            // Connection를 닫는다.
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }// main()의 끝
}// 클래스의 끝

 


컴파일하고 실행시킨 결과 다음의 결과가 나오면 JDBC 프로그래밍 준비 완료가 된 겁니다.

주의할 것은 String DB_URL="jdbc:oracle:thin:@127.0.0.1:1521:orcl";  이 부분입니다.

여기서 orcl 은 SID 명인데 설치시에 입력한 것으로 지정합니다.

> javac GetEmp.java 엔터

> java Getemp 엔터


------------- 실행 결과 -------------
7369 : SMITH : CLERK : 7902 : 1980-12-17 00:00:00.0 : 800 : null : 20
7499 : ALLEN : SALESMAN : 7698 : 1981-02-20 00:00:00.0 : 1600 : 300 : 30
7521 : WARD : SALESMAN : 7698 : 1981-02-22 00:00:00.0 : 1250 : 500 : 30
7934 : MILLER : CLERK : 7782 : 1982-01-23 00:00:00.0 : 1300 : null : 10
..


나. JDBC 프로그래밍 방법

(1) JDBC 드라이버 로딩 :

Class.forName("oracle.jdbc.driver.OracleDriver");


(2) Connection 맺기 :

String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
Connection con = DriverManager.getConnection(url,"scott", "tiger");


(3) SQL 실행


(4) [SQL문이 select문이었다면 ResultSet을 이용한 실행결과 처리]


(5) 자원 반환

위 순서가 JDBC 프로그래밍 방법입니다.

<출처 : http://cafe.naver.com/webprogramguide/86 >

+ Recent posts