기본적인 암호화 처리를 해주는 메소드를 살짝 변경하였습니다.  암호화키를 저장해주지 못하기 때문에 별도의 페이지에서는 사용이 어려웠음.

 

필요하시면, 가져다 쓰셔도 됩니다. ^^ 암호화된 코드에다가 자기만의 암호화 처리 방법을 넣어서 해주시면 좋습니다. +_+)b

returnEncryptCode(String str)  메소드는 입력받은 문자열을 암호화 한 다음, 암호화에 사용한 암호키와 암호화된 문자열을 합쳐서 반환합니다.
public String returnDecryptCode(String str)  메소드는 returnEncryptCode(String str) 메소드에서 처리한 암호화된 코드를 받으면, 특정 부분에서 잘라서 암호키를 키로 생성하고, 암호화된 코드를 넣어서 해독하여 해독된 문자열을 반환합니다.

 

JSP에서 처리할 경우에는 returnEncryptCode(String str)에서 반환된 문자열을 저장하는 문자열 혹은 객체를 저장하는 방법만 고려하면 되겠다.

 

  1. package encrypt;

    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.security.InvalidKeyException;
    import java.security.Key;

    import javax.crypto.BadPaddingException;
    import javax.crypto.Cipher;
    import javax.crypto.IllegalBlockSizeException;
    import javax.crypto.KeyGenerator;

    import sun.misc.BASE64Decoder;
    import sun.misc.BASE64Encoder;
     
    public class LocalEncrypter{
        //DESede 는 암호화시 사용되는 최대 키 사이즈를 지정하는 키워드임 : 관련페이지 내용 링크
  2.     private static String algorithm = "DESede";
        private static Key    key       = null;
        private static Cipher cipher    = null;
     
       
        // 암호화 키를 발생시키는 메소드입니다.
        // com.sun.crypto.provider.DESedeKey@ + 16진수 8자리
        public LocalEncrypter() throws Exception {
            key = KeyGenerator.getInstance( algorithm ).generateKey();
           
    //        private static String keystr = String.valueOf(key);
    //        System.out.println(key);
    //        System.out.println("암호화 키의 형태 :"+ keystr);
    //        System.out.println(keystr.length());
           
            cipher = Cipher.getInstance( algorithm );   
        }
       
       
        //1. str 을 입력 받아서 이를 암호한다.    //2. 암호화 하는데 사용한 암호키를 encKey 로 문자열화 한다.
        //3. encKey + str 값을 반환한다. 크기는 408 byte
        public  static String returnEncryptCode(String str) throws Exception {
            byte [] encryptionBytes = null;
     

            // 입력받은 문자열을 암호화 하는 부분
            encryptionBytes = encrypt( str );
            BASE64Encoder encoder = new BASE64Encoder();

            //encoder.encode(encryptionBytes) 으로 encrypt 된 값 출력
            String encodeString = encoder.encode(encryptionBytes);
           
            // 키를 문자열로 바꿔주는 곳.
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(key);
            oos.close();
            BASE64Encoder b64enc = new BASE64Encoder();
            byte[] keyArr = bos.toByteArray();
            String encKey = b64enc.encode(keyArr);   
           
    //        System.out.println("문자열이 되어 저장된 키 : " + encKey);
    //        System.out.println("저장된 키의 길이 : " + encKey.length());
    //        System.out.println("암호화된 비밀번호 : " + encodeString);


    /*                // 암호화에 사용된 키값을 뽑아낸 수
             String keycode = keystr.substring(34,42);
             System.out.println("암호화에 사용된 키 : " + keycode);
             String randomcode = returnRandomCode();
             System.out.println("암호화된 코드 : " + encodeString);*/
            
            return encKey + encodeString;
        }

       
        //1. DB에 저장되어 있는 408 byte 길이의 str을 받는다.
        //2. 그중 0~384 까지의 암호화키(encKey)부분을 keycode로 뽑아낸다.
        //3. keycode를 Key에 대입한다.
        //4. 384~408 까지의 암호화된 문자열을 code로 뽑아낸다.
        //5. code를 해독한다.
        //6. 해독된 값을 반환한다.
        public String returnDecryptCode(String str) throws Exception {
            //복호화 하기 위해서는 암호화 키가 필요하다. ㅡㅅ-);;
            // 그래서 생각해낸 것이, DB에 저장될 때, 암호화키를 한번에 집어넣고....
            //substring 으로 잘라서 쓰는 것.
            int strLength = str.length();
           
            //암호화된 비밀번호에 저장되어 있는 암호화키를 추출.
               String keycode = str.substring(0,384);
              
              
               // 추출한 암호키를 KEY 형태로 다시 복구
               BASE64Decoder b64dec = new BASE64Decoder();
               byte[] b = b64dec.decodeBuffer(keycode);
               ByteArrayInputStream bis = new ByteArrayInputStream(b);
               ObjectInputStream ois = new ObjectInputStream(bis);
               key = (Key) ois.readObject();
               ois.close();
              
            String code = str.substring(384, strLength);
           
              
    //        System.out.println("저장된 코드 길이 : " + strLength);
    //           System.out.println("암호화 사용키 : " + keycode);
    //        System.out.println("암호화된 코드: " + code);
           
            BASE64Decoder decoder = new BASE64Decoder();
            String decode = decrypt( decoder.decodeBuffer(code));
           
    //        System.out.println("Ecrypt 에서 해독한 것 : " + decode);
            return decode;
        }
       
     
       
        // encryptionBytes = encrypt( input ), input을 변조하여 encryptionBytes에 대입함.
        private static byte [] encrypt(String input) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException  {
            cipher.init( Cipher.ENCRYPT_MODE, key );
            byte [] inputBytes = input.getBytes();
            return cipher.doFinal( inputBytes );
        }
     
       
       
        //decrypt( decoder.decodeBuffer(encodeString) ) 처리부분.
        private static String decrypt(byte [] encryptionBytes) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException{
            cipher.init( Cipher.DECRYPT_MODE, key);
            byte [] recoveredBytes = cipher.doFinal( encryptionBytes );
            String recovered = new String( recoveredBytes );
            return recovered;
        }
     
    }

이 글은 스프링노트에서 작성되었습니다.

미투데이 따라집기!!!

me2daytest(1).JPG

 

테이블 생성 SQL

  1. create table me2daytest(
        pid number primary key,
        pname varchar2(20),
        particle varchar2(150),
        pwdate date );

 

index2.jsp

  1. <%@ page language="java" contentType="text/html; charset=EUC-KR" pageEncoding="EUC-KR"%>
    <html>
    <head>
    <script language="javascript" src="jslb_ajax.js" >
    </script> 
    <script language="javascript">
    <!--
        //콜백함수(수신시에 실행된다)
        function on_loaded(oj){
            //응답을 취득
            var res = oj.responseText

            //응답된 문자열을 DIV로 출력
            document.getElementById("list").innerHTML = res
        }

        function result(oj){
            //응답을 취득
            var res = oj.responseText
       
            //응답된 문자열을 DIV로 출력
            document.getElementById("result").innerHTML = res
    }

        //입력한 내용을 바로 업데이트 시킴.
        function input(oj){
            if (oj.form.article.value.length === 0) return
            sendRequest(result, '&name='+oj.form.name.value+'&article='+oj.form.article.value, 'POST', 'input.jsp', true, true)
            sendRequest(on_loaded, '', 'POST', 'list.jsp', true, true)
            oj.form.article.value='';
        }

        function on_formLoad(oj){
            sendRequest(on_loaded, '', 'POST', 'list.jsp', true, true)
        }


    //-->
    </script>
    <meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
    <title>허니몬의 me2day 떼쳇 따라잡기</title>
    </head>
        <body>
        <h3>사용법 : 이름 입력하고 내용 입력하고 Enter 혹은 글올리기 클릭하면 됨!!</h3>
        <h3>여러분은 낙장불입의 세계에 한발 들어섰습니다.</h3>
        <hr>
        <form>
        <table>
        <tr>
        <th>이름</th><th>내용</th><th><!-- 스크립트 값이 들어가야하려나? document.write(var); -->
        <div id='result'></div>
        </th>
        </tr>
        <tr>
       
        <td><input type='text' name='name' /></td><td><input type='text' name='article' size='50' maxlength='50' onkeyup='on_formLoad(this)'/></td><td><input type='button' value='글 올리기' onclick='input(this)' /></td>
       
        </tr>
        </table>
        </form>
        화면출력!!
        <div id='list'></div>
        </body>
    </html>

 

input.jsp

  1. <%@ page language="java" contentType="text/html; charset=EUC-KR" pageEncoding="EUC-KR"%>
    <jsp:useBean id="data" class="data.DataProc" scope="page"/>
    <%
        String name = request.getParameter("name");
        String article = request.getParameter("article");
       
        data.insertData(name,article);
        out.println("처리완료");
    %>

 

list.jsp

  1. <%@ page language="java" contentType="text/html; charset=EUC-KR" pageEncoding="EUC-KR"%>
    <%@ page import='java.util.*, data.*' %>
    <jsp:useBean id='data' class='data.DataProc' scope='page' />
    <%
        Vector result = data.list();

        if( result.isEmpty() == true) {
            out.println("입력된 데이터가 없습니다.");
        } else {
    %>
        <table border='1'>
    <%
            //vector는 0부터 시작하는 거였구나... 그걸 몰랐다!!
            for( int i = 0; i < result.size(); i++){
                DataBean b = (DataBean)result.elementAt(i);
                String name = b.getPname();
                String article = b.getParticle();
                String wdate = b.getPwdate();
    %>
            <tr>
            <td><%= name %></td><td><%= article %></td><td><%= wdate %></td>
            </tr>
    <%
            }
    %>
        </table>
    <%
           
        }
    %>

 

DataBean.jsp

  1. package data;

    public class DataBean {
        private String pname="";
        private String particle="";
        private String pwdate="";
       
        public DataBean(){}
       
        public DataBean(String pname, String particle, String pwdate){
            this.pname = pname;
            this.particle = particle;
            this.pwdate = pwdate;
        }

        public String getPname() {
            return pname;
        }

        public void setPname(String pname) {
            this.pname = pname;
        }

        public String getParticle() {
            return particle;
        }

        public void setParticle(String particle) {
            this.particle = particle;
        }

        public String getPwdate() {
            return pwdate;
        }

        public void setPwdate(String pwdate) {
            this.pwdate = pwdate;
        }
       
    }

 

DataProc.java

  1. package data;

    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.Statement;
    import java.util.Vector;

    import javax.naming.InitialContext;
    import javax.sql.DataSource;

    public class DataProc {
        DataSource ds;
       
        public DataProc(){
            try {
                InitialContext context = new InitialContext();
                ds = (DataSource)context.lookup("java:comp/env/jdbc/oracle");
            } catch(Exception e){
                e.printStackTrace();
            }
        }
       
        public void insertData(String name, String article){
            Statement stat;
            Connection con;
            int pid = checkpid();
           
            String sql = "INSERT INTO me2daytest values(" + pid + ",'" + name + "', '"+ article +"', sysdate)";
            try{
                con = ds.getConnection();
                stat = con.createStatement();
                stat.executeUpdate(sql);
                stat.close();
                con.close();
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
       
        public Vector list(){
            Connection con;
            Statement stat;
            Vector result = new Vector();
           
            String sql = "SELECT pname, particle, pwdate FROM me2daytest ORDER BY pwdate desc";
            try {
                con = ds.getConnection();
                stat = con.createStatement();
                ResultSet rs = stat.executeQuery(sql);
                while( rs.next() ){
                    String name = rs.getString(1);
                    String article = rs.getString(2);
                    String wdate = rs.getString(3);
                    DataBean bean = new DataBean(name, article, wdate);
                    result.add(bean);
                }
                rs.close();
                stat.close();
                con.close();
            } catch(Exception e){
                e.printStackTrace();
            }
            return result;   
        }
       
        public int checkpid(){
            Connection con;
            Statement stat;
            int pid=0;
           
            String sql = "SELECT max(pid) FROM me2daytest";
            try {
                con = ds.getConnection();
                stat = con.createStatement();
                ResultSet rs = stat.executeQuery(sql);
                while( rs.next() ){
                    pid = rs.getInt(1);
                }
                rs.close();
                stat.close();
                con.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return pid+1;
        }
    }

 

문제점 :

  • 다른 사람이 입력한 뒤에 Reload가 되지 않는다. 이건 어떻게 해야하지? ㅡㅅ-)? 원격인터페이스를 써줘야할까? EJB 무상태 세션빈?
  • 본문 입력시 입력하지 않고 입력했을 때 javascript로 거절하도록 한다.
  • 페이지 나누기 기능이 필요할 듯 하다.
  • 미관상 이쁘지 않다.

이 글은 스프링노트에서 작성되었습니다.

과제풀이

내용 정리


 

자바 서버 페이지(JSP)

위키백과 ― 우리 모두의 백과사전.

자바 서버 페이지(JavaServer Pages, JSP)는 HTML내에 자바 코드를 삽입하여 웹 서버에서 동적으로 웹 페이지를 생성하여 웹 브라우저에 돌려주는 언어이다. Java EE 스펙 중 일부로 웹 애플리케이션 서버에서 동작한다.

자바 서버 페이지는 실행시에는 자바 서블릿으로 변환된 후 실행되므로 서블릿과 거의 유사하다고 볼 수 있다. 하지만, 서블릿과는 HTML 표준에 따라 작성되므로 웹 디자인하기에 편리하다. 이와 비슷한 구조인 것인 PHP, ASP, ASP.NET 등도 있다.

아파치 스트럿츠자카르타 프로젝트JSTL 등의 JSP 태그 라이브러리를 사용하는 경우에는 자바 코딩없이 태그만으로 간략히 기술이 가능하므로 생산성을 높일 수 있다.

● JSP - 위키백과 : http://ko.wikipedia.org/wiki/자바_서버_페이지

● OKJSP(JSP 전문 사이트) : http://okjsp.pe.kr

● JSP development (API and implementation) : https://jsp.dev.java.net/

● JAVA EE 5 API DOCS : http://java.sun.com/javaee/5/docs/api/

● JSP에 대한 설명 : http://en.wikipedia.org/wiki/JavaServer_Pages

● JavaServer Pages Technology pages of SUN : http://java.sun.com/products/jsp/

 

자바 서블릿

위키백과 ― 우리 모두의 백과사전.

 

자바 서블릿(Java Servlet)은 자바를 사용하여 웹페이지를 동적으로 생성하는 서버측 프로그램 혹은 그 사양을 말하며, 흔히 "서블릿"이라 불린다.

자바 서블릿은 Java EE사양의 일부분으로, 주로 이 기능을 이용하여 쇼핑몰이나 온라인 뱅킹 등의 다양한 웹 시스템이 구현되고 있다.비슷한 기술로는 등을 이용한 CGI, PHP를 아파치 웹 서버 프로세스에서 동작하게 하는 mod_php, 마이크로소프트사의 IIS에서 동작하는 ASP 등이 있다. CGI는 요청이 있을 때마다 새로운 프로세스가 생성되어 응답하는 데 비해, 자바 서블릿은 외부 요청마다 프로세스보다 가벼운 쓰레드로써 응답하므로 보다 가볍다. 또한, 자바 서블릿은 자바로 구현되므로 다양한 플랫폼에서 동작한다.

서블릿은 동적인 콘텐츠를 생성하기 위해 자바로 작성한 웹 컴포넌트이다. 서블릿은 자바 클래스 형태로 작성할 수 있으며, 웹 컨테이너에 의해서 관리된다. 서블릿은 자바 언어를 이용해서 작성하지만, 기존의 C 혹은 C++ 언어를 사용하는 CGI 프로그램에 비해 성능이 뛰어나다. 이것은 CGI가 프로세스(Process) 기반으로 동작하는 것에 비해, 서블릿은 스레드(Thread) 기반으로 동작하기 때문이다. 스레드에 비해서 프로세스는 생성 속도가 느리며, 시스템 자원을 많이 소모한다.

 

서블릿의 장점

● 플랫폼 독립성

서블릿은 자바를 이용해서 작성하기 때문에 플랫폼에 독립적이다. 따라서 작성한 서블릿 프로그램은 변경하지 않더라도 UNIX, 윈도우 등의 컴퓨터 플랫폼에 상관없이 실행할 수 있다.

● 서버 독립성

서블릿은 거의 모든 웹 서버에서 지원하기 때문에 웹 서버와 무관하게 실행될 수 있다.

● 확장성

서블릿은 자바로 작성하기 때문에 다른 업체에서 지원하는 다양한 클래스들을 바로 사용할 수 있다

● 개발 용이성

CGI 프로그램을 개발하려는 경우 적당한 통합 개발 환경(IDE)이 없지만, 자바의 경우는 다수의 통합 개발환경들이 있다. 프로그램 디버깅 층면에서도 Perl 이나 C로 작성된 CGI 프로그램은 예외처리가 되지 않아서 에러가 발생한 곳이 어딘지를 찾기가 어렵다. 이에 반해 자바는 예외 처리 기능과 통합 개발 환경을 이용해서 쉽게 에러를 발견할 수 있다. 이런 여러가지 측면에서 크고 복잡한 프로그램 개발에는 서블릿이 CGI 프로그램보다 적합하다.

 

● 자바 서블릿 관련 API : j2eeri-1_4-Servlet-doc-api.zip

● 참조 : http://java.sun.com/products/servlet/docs.html

[1]. JSP는 .JSP로 저장한다.

[2]. JAVA 파일이 아니기 때문에 컴파일(Compile)을 필요로 하지 않는다.

● JSP -> 자바 서블릿 으로 변환되어 실행

 

웹 응용프로그램(Web Application)

웹 서버의 기능을 확장함으로써 비즈니스 로직(Bussiness Logic)을 서버 측에 배포(설치, Deploy)하고, 클라이언트로 웹 브라우저를 사용하는 클라이언트/버서 형태의 프로그램이다.

 

팻클라이언트(Fat Client) - 클라이언트에 대용량의 실행파일을 설치해야하는 경우를 의미

팻서버(Fat Server) - 팻클라이언트 못지 않게 서버도 실행파일을 설치해둬야한다.

 

클라이언트 티어(Client Tier)

이에 해당하는 웹 브라우저는 사용자와 상호 작용하는 인터페이스 역할을 수행하며, 웹 사용자에게 HTML, CSS, 플래시, 자바 스크립트, 그림 파일 등으로 작성된 내용들을 보여준다. 웹 브라우저는 Thin Client(Fat Client의 반대의미)이기 때문에 비즈니스 로직을 가지고 있지 않으며, 사용자를 위한 GUI와 유효성 검사(Validity Check) 기능만을 가지고 있다.

 

미들 티어(Middle Tier)

비즈니스 로직을 수행하고 동적인 콘텐츠를 제공한다. 웹 응용프로그램 중에서 미들 티어는 가장 핵심적인 역할을 수행하는 부분으로서 주로 CGI, ASP, PHP, JSP, 서블릿 등의 기술을 이용해서 프로그램을 작성한다. 우리는 JSP와 서블릿을 이용해서 미들 티어 부분의 프로그램을 작성할 것이다.

 

서버 티어(Server Tier)

데이터를 저장하고 관리하는 역할을 수행하는 부분으로, 데이터를 저장하기 위해 대부분 오라클, MS SQL, MySQL과 같은 DBMS를 이용한다. 미들 티어가 서버 티어에 있는 데이터베이스에 접근하려면, JDBC, ODBC 등과 같은 표준화된 API와 DBMS에서 제공하는 고유의 API를 사용해야 한다.

 

웹 응용프로그램을 작성하기 위해서는 클라이언트에서 사용하는 HTML, 플래시, 자바 스크립트와 같은 기술과 미들 티어에서 사용하는 CGI, PHP, ASP, JSP, 서블릿과 같은 기술을 함께 사용할 수 있어야 한다.

 

컨테이너(Container)

서버(Server)라고 생각하면 된다. JSP와 서블릿을 실행시킬수 있는 소프트웨어를 웹 컨테이너(Web Container) 혹은 서블릿 컨테이너(Servlet Container)라고 한다. 엔진 이라고도 한다. 대표적인 웹 컨테이너로는 자카르타 톰캣, Resin, 웹로직 등이 있다.

 

[1]. editplus + Resin

[2]. Eclipse + Tomcat

[3]. WebLogic

 



Resin 설치하기

http://caucho.com/ 에서 Resine 을 다운 받는다.

현재 업계에서 사용되는 것은 2.1.17 버전( resin-2.1.17.zip )이라고 한다.

압축파일을 풀고 /BIN 폴더로 들어가면 httpd.exe를 실행하면 아래화면을 볼 수 있다. 브라우저에서 http://localhost:8080 을 입력하면 Resine 서버가 작동되고 있는 것을 확인할 수도 있다.

ResinRun.JPG


 이 부분이 서블릿에서 가장 핵심이지 싶다. ㅡㅅ-);

● 서블릿을 만들어서 C:\Program Files\resin-2.1.17\doc\WEB-INF\classes 폴더에 저장해주어야 한다.
..\doc\WEB-INF\classes      (서블릿)JAVA 인 것을 저장.

 

● C:\Program Files\resin-2.1.17\doc 에는 html, jsp, txt, jpg 등을 에 넣어두어야 한다.
..\doc

 

http://java.sun.com/j2ee/1.4/docs/tutorial/doc/index.html 참조바람.

 



서블릿 프로그램 작성

서블릿은 두 개의 패키지로 구성되어 있다. 이 패키지들은 웹 컨테이너에 포함되어 있다.

javax.servlet         : 일반 서비스를 위한 서블릿 패키지

javax.servlet.http   : HTTP 서비스를 위한 패키지

 

아래 그림에 있는 jsdk23.jar 파일을 복사해서

  lib_jsdk23.JPG

아래 폴더의 위치에 붙여넣기 해준다.

copyTOextJSDK23.JPG

다시 resin 폴더로 이동해서 resin.conf (resin 설정(Configure) 파일)을 열어본다. 특별히 수정할 필요는 없다.

resineConf.JPG

 



HelloServlet.java 작성

  1. 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=KSC5601");
            // setContentType 를 잘못 입력할 경우, 컴파일 시 다운로드 하시겠습니까? 라고 나온다.
            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]. HelloServlet.java 프로그램을 컴파일하고, HelloServlet.class 파일을 <Resin>\doc\WEB-INF\classes 에 복사한다. 만약, class 디렉토리가 없는 경우에는 새로 만들도록 한다(본인의 경우에는 귀찮아서.... classes 폴더에서 자바(.java)를 작성하기로 결심했다).

classInResin_classes.JPG

[2]. http://localhost:8080/servlet/MessageServlet  라고 입력하면 HelloServlet.JPG

Hello Servlet 이라고 나오는 걸 볼 수 있을 것이다.

 

HelloServlet 과 MessageServlet을 서로 찾게 만드는 코드.

MessageServlet.java

  1. import java.io.*;
    import javax.servlet.*;
    import javax.servlet.http.*;

    public class MessageServlet extends HttpServlet {
        public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

            res.setContentType("text/html;charset=KSC5601");
            // setContentType 를 잘못 입력할 경우, 컴파일 시 다운로드 하시겠습니까? 라고 나온다.
            PrintWriter out = res.getWriter();

            //태그<tag> 사용할 때는 보다시피 .println() 메소드 안에 사용해주면 된다.
            out.println("<html>");
            out.println("<head><title>Hello Servlet</title></head>");
            out.println("<body>");
            out.println("Message Servlet : ");
            out.println("<a href='HelloServlet'>HelloServlet Link</a>");
            out.println("</body>");
            out.println("</html>");
            out.close();

        }
    }

HelloServlet.java

  1. 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=KSC5601");
            // setContentType 를 잘못 입력할 경우, 컴파일 시 다운로드 하시겠습니까? 라고 나온다.
            PrintWriter out = res.getWriter();

            //태그<tag> 사용할 때는 보다시피 .println() 메소드 안에 사용해주면 된다.
            out.println("<html>");
            out.println("<head><title>Hello Servlet</title></head>");
            out.println("<body>");
            out.println("Hello Servlet : ");
            out.println("<a href='MessageServlet'>MessageServlet Link</a>");
            out.println("</body>");
            out.println("</html>");
            out.close();

        }
    }

 

그림 파일을 넣는 방법

HelloWorld.java

  1. import java.io.*;
    import javax.servlet.*;
    import javax.servlet.http.*;

    public class HelloWorld extends HttpServlet {
        public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

            res.setContentType("text/html;charset=KSC5601");
            // setContentType 를 잘못 입력할 경우, 컴파일 시 다운로드 하시겠습니까? 라고 나온다.
            PrintWriter out = res.getWriter();

            //태그<tag> 사용할 때는 보다시피 .println() 메소드 안에 사용해주면 된다.
            out.println("<html>");
            out.println("<head><title>Hello Servlet</title></head>");
            out.println("<body>");
            out.println("Hello Servlet : ");
            out.println("<a href='MessageServlet'>MessageServlet Link</a>");
            out.println("<img src = '/images/comics.gif>");
            out.println("</body>");
            out.println("</html>");
            out.close();

        }
    }

docImages.JPG

 

HTTP 관련 오류코드

오류 1) http://localhost:8080/servlet/HelloWorld 8  라고 할 경우.

500 Servlet Exception

javax.servlet.ServletException: Class `HelloWorld 8' was not found in classpath.

Classes normally belong in /WEB-INF/classes.

at com.caucho.server.http.Application.instantiateServlet(Application.java:3198)

at com.caucho.server.http.Application.createServlet(Application.java:3104)

at com.caucho.server.http.Application.loadServlet(Application.java:3065)

at com.caucho.server.http.QServletConfig.loadServlet(QServletConfig.java:435)

at com.caucho.server.http.Application.getFilterChainServlet(Application.java:2809)

at com.caucho.server.http.Application.buildFilterChain(Application.java:2765)

at com.caucho.server.http.Invocation.service(Invocation.java:313)

at com.caucho.server.http.CacheInvocation.service(CacheInvocation.java:135)

at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:253)

at com.caucho.server.http.HttpRequest.handleConnection(HttpRequest.java:171)

at com.caucho.server.TcpConnection.run(TcpConnection.java:139)

at java.lang.Thread.run(Thread.java:619)

Resin 2.1.17 (built Tue Jul 11 09:01:03 PDT 2006)

 



오류 2) http://localhost:8080/test.html 라고 할 경우(404 에러)  파일이 존재하지 않을 때

404 Not Found

/test.html was not found on this server.


Resin 2.1.17 (built Tue Jul 11 09:01:03 PDT 2006)

 

 



오류 3) http://localhost:8080/servlet/HelloWorld 하고 발생할 경우(405 에러) Get 메소드가 쓰여야할 곳에 doPost()를 사용했을 때 발생.

  1. import java.io.*;
    import javax.servlet.*;
    import javax.servlet.http.*;

    public class HelloWorld extends HttpServlet {
        public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

            res.setContentType("text/html;charset=EUC-KR");
            // setContentType 를 잘못 입력할 경우, 컴파일 시 다운로드 하시겠습니까? 라고 나온다.
            PrintWriter out = res.getWriter();

            //태그<tag> 사용할 때는 보다시피 .println() 메소드 안에 사용해주면 된다.
            out.println("<html>");
            out.println("<head><title>Hello Servlet</title></head>");
            out.println("<body>");
            out.println("Hello Servlet : ");
            out.println("<a href='MessageServlet'>MessageServlet Link</a>");
            out.println("<img src = '/images/comics.gif>");
            out.println("</body>");
            out.println("</html>");
            out.close();

        }
    }

405 GET not supported

 


Resin 2.1.17 (built Tue Jul 11 09:01:03 PDT 2006)

 

 

서블릿 라이프 사이클

서블릿은 init(), service(), destroy() 메소드를 호출하는 라이프 사이클을 가진다.

 

init()

처음에 서블릿이 메모리에 로드(Load)되면 init() 메소드가 수행된다. init() 메소드는 서블릿이 서비스 하기 위해 필요한 초기화 작업을 수행한다. 따라서 init()메소드는 서블릿이 실행되기 위해서 필요한 각종 환경을 설정하기 위한 목적으로 사용한다. 예를 들어, 필요한 파일을 열고, 데이터베이스에 연결하는 등의 작업을 수행한다(자바로 치면 생성자 정도 되려나?).

 

service()

초기화된 서블릿은 클라이언트의 요청이 있을 때마다 스레드가 생성되어서 병행적으로 service() 함수를 수행한다. 따라서 서블릿을 개발할 때 병행성 문제를 고려해야 한다. 클라이언트의 요청이 있을 때마다 service() 메소드가 호출되고, service() 메소드가 HTTP의 method 타입에 따라 GET 방식이면 doGet() 메소드를, POST 방식이면 doPost() 메소드를 호출한다.

 

destroy()

서블릿이 더 이상 서비스를 하지 않거나 메모리가 부족하면 웹 컨테이너에 의해 서블릿은 메모리에서 언로드(Unload)된다. 이때 메모리에서 언로드 되기 전에 destroy() 함수가 수행된다.

 

서블릿 작업 중단

클라이언트의 요청을 처리하는 서블릿의 작업을 더 이상 진행시키지 않고, 중단시키기 위해서는 doPost(), doGet(), service() 등의 함수에서 return 문을 사용해야 한다. 서블릿 작업을 중둔시키기 위해 System.exit()을 호출해서는 안된다. System.exit()을 호출하면 서블릿 컨테이너가 종료된다.

 

 

● doGet() 메소드는 브라우저에서 호출될 경우 작동함.

● doPost() 메소드는 Form 태그 안에서 method = POST 일 때에 호출됨

  1.  <BODY>
      <FORM METHOD=POST ACTION="">
       
      </FORM>
     </BODY>

 

서블릿을 이용한 폼 데이터 처리

  1. contact.html(경로 : <Resin>\doc\contact.html>
  2. 실행 : 웹브라우저 상에서 주소창에 http://localhost:8080/contact.html 호출

  3. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
     <HEAD>
      <TITLE> New Document </TITLE>
      <META NAME="Generator" CONTENT="EditPlus">
      <META NAME="Author" CONTENT="">
      <META NAME="Keywords" CONTENT="">
      <META NAME="Description" CONTENT="">
     </HEAD>

     <BODY>
      <FORM METHOD=POST ACTION=/servlet/Contact>
      <!-- 서블릿 에서는 doPost() 메소드를 사용해줘야 한다.-->
        로그인<br><hr>
        번호 : <INPUT TYPE="text" NAME="number"><br>
        이름 : <INPUT TYPE="text" NAME="name"><br>
        주소 : <INPUT TYPE="text" NAME="address"><br><hr>
        <INPUT type="submit">
        <!-- Form 태그에 ACTION 안에 입력된 곳으로 이동 -->
      </FORM>
     </BODY>
    </HTML>

 

  1. Contact.java (클래스 파일 위치는 <Resin>\doc\WEB-INF\classes\Contact.class)

  2. import java.io.*;
    import javax.servlet.*;
    import javax.servlet.http.*;

    public class Contact extends HttpServlet {

        public void doPost(HttpServletRequest req, HttpServletResponse res){
            try {
                res.setContentType("text/html; charset=KSC5601");
                PrintWriter out  = res.getWriter();
                req.setCharacterEncoding("KSC5601");
                String number = req.getParameter("number"); // html 에서 name ="number"인 입력상자의 파라메터 받아와서 number에 넣음
                String name = req.getParameter("name"); //name="name"인 파라메터 받아와서 name에 넣음
                String address = req.getParameter("address"); //name="address"인 파라메터 받아와서 address에 넣음
                out.println("<html>");
                out.println("<head><title>Contact 서블릿 실행하기</title></head>");
                out.println("<body><h3> " +number + " 번 당신!!<h3><br>");
                out.println("이름은 " + name + " 이고!!!");
                out.println("사는 곳은 " + address + " 가 맞지!?");
                out.println("조사하면 다나와~~ ㅡㅅ-)ㅋ");
                out.println("</body>");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

contact.html 실행화면(브라우저에서 실행해야 한다 ㅡㅅ-)b

HTMLRequestPost.JPG

contact.html 내에서 Form 의 action 에 의해 Contact 서블릿이 호출되는 상황

ServletPostResponse.JPG

 

● 폼 데이터 처리

HTML의 폼에서 태그에 사용된 이름이 유일한 경우에는 getParameter9)로 값을 알아볼 수 있었다. 하지만, 동일한 이름이 여러 번 사용된 경우에는 어떻게 될까? 이러한 경우에는 전달되는 값도 여러 개이다. 따라서 값을 얻을 때 여러 개의 값을 저장할 수 있는 배열 형태를 사용해야 한다. HttpServletRequest는 이러한 용도로 getParameterValues() 메소드를 제공한다. 이 메소드는 다음 예와 같은 방법으로 사용할 수 있다. 이 메소드를 사용할 때 주의할 점은 해당 이름으로 값이 전달되지 않는 경우에 리턴 값이 "null"이 올 수도 있기 때문에 "null"인지 여부를 반드시 확인하여야 한다.

 

예 : 값이 여러 개 전달되는 경우

  1. String values[] = res.getParameterValues("name");
    if ( values != null) {
       ...
    }

※ 전달되는 값

HTML의 폼(Form)에서 Input 타입이 text인 경우에는 사용자가 입력한 문자열이 서블릿에 전달된다. 그런데 입력 타입이 checkbox나 radio인 경우에는 어떤 값들이 전달될까? HML 폼에서 체크박스를 사용하면 선택된 체크 박스의 value 속성으로 기술된 값만 서블릿에 전달된다. 만약 HTML 폼의 체크 박스에 value 속성을 기술하지 않으면 'on' 값이 서블릿에 전달되기 때문에 주의해야 한다.

 

예 : 파라미터 이름을 모를 경우

  1. import java.util.Enumeration; //필요

    Enumeration e = req.getParameterNames();
    while( e.hasMoreElements() ) {
       String name = (String) e.nextElement();
       String value = req.getParameter(name);
       if (values != null){
          for(int i = 0; i < values.length; i++ ) {
             out.println("<li>" + name + " : " + values[i]);
          }
       }
    }

 

이 글은 스프링노트에서 작성되었습니다.

+ Recent posts