'Servlet'에 해당되는 글 34건
- 2008.09.08 servlet api 일본어판 다운로드
- 2008.09.08 JSTL 기초 자료 링크
- 2008.09.08 JSP코드작성표준양식-한글판
- 2008.09.08 Servlet API 사이트
- 2008.09.08 Servlet 구조
- 2008.09.08 [CONTAINER] 톰캣5 관리자 아이디 설정 등 사용자,권한 설정
- 2008.09.08 jsp 운영환경 구축 - 톰캣 어드민
- 2008.09.08 jdk와 tomcat 버전
- 2008.09.08 이클립스 설치 및 톰캣과 오라클 연동 정리
- 2008.09.08 자바빈과 세션을 이용한 회원가입
'My work space > JSP/Servlet' 카테고리의 다른 글
HttpSessionBindingListener로 구현한 중복로그인체크(2) (0) | 2008.09.08 |
---|---|
HttpSessionBindingListener로 구현한 중복로그인체크(1) (0) | 2008.09.08 |
JSTL 기초 자료 링크 (0) | 2008.09.08 |
JSP코드작성표준양식-한글판 (0) | 2008.09.08 |
Servlet API 사이트 (0) | 2008.09.08 |
JSTL 기초, Part 1: Expression Language (한글)
http://www.ibm.com/developerworks/kr/library/j-jstl0211.html
JSTL 기초, Part 2: core 분석 (한글)
http://www.ibm.com/developerworks/kr/library/j-jstl0318/index.html
JSTL 기초, Part 3: 보여지는 것도 중요하다! (한글)
http://www.ibm.com/developerworks/kr/library/j-jstl0415/index.html
JSTL 기초, Part 4: SQL과 XML 콘텐트에 액세스 하기 (한글)
http://www.ibm.com/developerworks/kr/library/j-jstl0520/index.html
'My work space > JSP/Servlet' 카테고리의 다른 글
HttpSessionBindingListener로 구현한 중복로그인체크(1) (0) | 2008.09.08 |
---|---|
servlet api 일본어판 다운로드 (0) | 2008.09.08 |
JSP코드작성표준양식-한글판 (0) | 2008.09.08 |
Servlet API 사이트 (0) | 2008.09.08 |
Servlet 구조 (0) | 2008.09.08 |
JavaServer PagesTM (JSPTM)가 점점 널리 웹기반 어플리케이션으로 자리잡아가면서, 개발과 유지보수에 종사하는 많은 JSP 프로그래머들과 웹 개발자들은, 예전에 자바프로그래머들이 겪었던 것과 같은 딜레마에 직면했다. "어떻게 JSP 코드를 짜면 읽기, 쓰기, 유지보수하기를 일관적으로 쉽게 할 수 있을까?"
이 글은, 웹 컴포넌트를 사용하는 전형적인 소프트웨어 프로젝트에서 준수해야 할 JSP(1.1 과 1.2버전) 표준 작성요령을 제안한다. 이 문서의 모체는 자바 언어 코드 작성요령이다. (JSP 와 관련된) 코드 작성 방법 스펙에 소개된 다양하고 중요한 요소들을 확인할 수 있는 템플릿으로 삼았다. 특히, 파일명, 구성, 들여쓰기, 주석, 지시자, 선언문, 스크립틀릿, 표현식, 공백, 명명법(이름 짓는 법), 프로그래밍 습관 등을 소개한다. 처음으로 시도되는 JSP 코드 작성요령이기 때문에, 이 권고 문서에 대한 여러분들의 관심과 피드백을 기다린다. 연락처는 jsp-codeconv-comments@sun.com이다.
JSP 2.0 스펙에서는 1.2 버전을 모두 포용하지만, 스크립트가 없는 프로그래밍 스타일(선언문, 스크립틀릿, 표현식이 없는)을 지향하고, 수많은 새 특징들을 갖고 있어서, 이 작성요령을 더 진보시켜야 될 필요가 있다. 가능한 한, 이 문서는 새로운 JSP 2.0 특징에 도움을 주는 작성방식을 선택했다.
마지막으로, 이 글을 읽는 수준은 JSP, Java, 자바 코드 작성요령에 익숙해야 하고, 이미 프로젝트를 수행하는 팀에 적용이 되어 있어야 된다. 그렇지 않다면, 이 링크를 읽어 보기를 추천한다. Java 링크 JSP 링크.
왜 코드 작성요령이 필요한가? Why Have Code Conventions?
코드 작성요령은 프로그래머와 웹 컨텐츠 개발자에게 여러 가지 이유로 중요하다:
- 소프트웨어 산출물의 가독성을 향상시킨다.
- 견습 관리와 노력을 경감한다.
- 표준화에 대한 조직적 참여도를 배가시킨다.
파일 이름과 위치 File Names and Locations
파일 이름짓기는 툴 벤더와 웹 컨테이너로 하여금 파일 타입을 인식하고, 각각에 맞게 해석할 수 있는 방법을 제공한다. 다음 테이블은 추천하는 방식의 파일 확장자와 위치 목록이다.
File Type | File 확장자 | 추천 위치 |
JSP | .jsp |
<context root>/<subsystem path>/ |
JSP fragment | .jsp |
<context root>/<subsystem path>/ |
.jspf |
<context root>/WEB-INF/jspf/ <subsystem path>/ | |
cascading style sheet | .css |
<context root>/css/ |
javascript | .js |
<context root>/js/ |
HTML page | .html |
<context root>/<subsystem path>/ |
web resource | .gif, .jpg , etc. |
<context root>/images/ |
tag library descriptor | .tld |
<context root>/WEB-INF/tld/ |
위 테이블을 볼 때 몇 가지 유념할 것이 있다. 우선, <context root> 는 웹 어플리케이션(.war
파일 내의 루트 디렉토리) 컨텍스트의 루트이다. 둘째로, <subsystem path> 는 동적, 정적 웹페이지 컨텐츠의 논리적인 그룹으로 나누도록 한다. 작은 웹 어플리케이션일 경우, 이게 필요하지 않을 수도 있다. (한 곳에 모두 놓아도 된다.)
세째로, 다른 JSP 파일에 포함되는 JSP 를 언급할 때 JSP fragment (JSP 프래그먼트 조각)라는 용어를 사용한다. 주의할 것은 JSP 2.0 에서는 "JSP fragment" 용어가 겹치기 때문에 "JSP 세그먼트(JSP segment)" 용어가 대신 사용된다. JSP fragment 는 확장자로 .jsp
또는 .jspf
를 사용하고, /WEB-INF/jspf
나 다른 정적인 컨텐츠와 함께 각각 위치하면 된다. 불완전한 JSP fragment는 언제나 .jspf
확장자를 사용하고, /WEB-INF/jspf
에 위치해야 된다. 네째로, JSP 스펙에서는 JSP fragment 확장자로 .jspf
와 .jsp
양쪽 모두를 권장하지만, 추천하는 것은 .jspf
인데, .jsf
는 JavaServer Faces™ 스펙에서 사용될 것이기 때문이다.
끝으로, 태그 라이브러리 디스크립터 파일이나 다른 비공개적인 컨텐츠는 WEB-INF/
또는 이 하위 디렉토리에 놓아두는 것은 보편적으로 좋은 습관이다. 웹 컨테이너는 WEB-INF/
아래 있는 어떤 파일도 송출하지 않기 때문에, 이 방법을 사용하면, 클라이언트가 접근하거나 볼 수 없게 된다.
배치 설명자(web.xml
)의 welcome-file
엘리먼트에 선언되어 있는 웰컴 파일의 이름은 동적인 컨텐츠를 생성하려면, index.jsp
가 되어야 되고, 정적인 웰컴 페이지라면 index.html
로 해야 한다.
JSP 파일을 다국어로 작성할 때, 로케일에 따라 디렉토리를 나누어 그룹 짓기를 추천한다. 예를 들어서 index.jsp
의 US English 버전은 /en_US/index.jsp
에, 같은 파일의 일본어판은 /ja_JP/index.jsp
에 있게 한다. 일반적으로 자바 코드의 국제화에 관한 추가적인 정보는 Java Tutorial 에 있고, 웹 어플리케이션의 국제화에 대한 정보는 Designing Enterprise Applications with the J2EETM Platform 책에 나와있다.
파일 구조 File Organization
구조가 잘 갖춰진 소스 코드 파일은 읽기 쉽고, 파일 사이에 정보를 더 빨리 놓아둘 수 있다. 이 섹션에서, JSP와 태그 라이브러리 디스크립터 파일 모두를 위한 구조를 소개하려한다.
JSP 파일 / JSP Fragment 파일
JSP 파일은 다음의 섹션들이 나열한 순서대로 구성된다:
- 도입 주석
- JSP 페이지 지시자(directive)
- 선택적 태그 라이브러리 지시자
- 선택적 JSP 선언문
- HTML 과 JSP 코드
도입 주석 Opening Comments
JSP 파일 또는 프래그먼트 파일은 서버측 주석으로 시작한다:
<%-- - 작성자: - 일자: - 저작권 표시: - @(#) - 설명: --%>
이 주석은 서버측에서만 볼 수 있다. JSP 변환 과정에서 제거되기 때문이다. 여기에는 웹 개발자를 위한 JSP에 대한 작성자, 일자, 개정판의 저작권, 증명과 설명이 포함된다. "@(#)
" 문자 조합은 증명의 시작을 지시하는 것으로 어떤 프로그램에서 인식된다. 이런 표식을 사용하는 프로그램들은 많이 사용되지 않지만, 있어도 해가 될 것은 없다. 추가로, 이 조합은 때때로 "$Id$
" 를 덧붙여서, 어떤 종류의 버전 관리 프로그램에서는 자동으로 증명 정보를 JSP에 기록하도록 한다. 설명
부분은 JSP의 목적에 관한 축약된 정보를 제공한다. 한 문단 이상 넘어가지 않도록 한다.
어떤 상황에서는, 도입 주석이 JSP 변환과정을 지나서 출처가 확실하다는 뜻과 법적인 목적으로 클라이언트의 브라우저에 보여질 필요가 있다. 이럴 경우 주석 부분을 두개로 나눠서 우선 클라이언트측 스타일의 주석을 단다:
<!-- - Author(s): - Date: - Copyright Notice: --%>
그리고 나서 짧아진 나머지 서버측 스타일의 주석을 단다:
<%-- - @(#) - Description: --%>
JSP 페이지 지시자 JSP Page Directive(s)
JSP 페이지 지시자는 JSP 변환 시점에 관련된 속성을 정의한다. JSP 스펙은 같은 페이지에 JSP 페이지 지시자의 수량을 제한하지 않는다. 그래서 다음 두 개의 코드 예제는 똑같다.(다른 점이 있는데, 첫 예제는 출력시에 맨 위에 두 개의 빈 줄이 포함된다):
코드 예제 1:
<%@ page session="false" %><%@ page import="java.util.*" %><%@ page errorPage="/common/errorPage.jsp" %>
페이지 지시자 같이 지시자의 길이가 일반적인 JSP 폭(80 문자)을 넘어갈 경우 여러 줄로 나눠진다:
코드 예제 2:
<%@ page session="false" import="java.util.*" errorPage="/common/errorPage.jsp"%>
일반적으로, 코드 예제 2는 코드 예제 1보다 즐겨 사용된다. 예외가 있는데, 매우 긴 import
속성을 쓰게 되는, 여러 개의 자바 패키지가 JSP페이지에서 필요할 경우이다:
<%@ page session="false" import="java.util.*,java.text.*, com.mycorp.myapp.taglib.*, com.mycorp.myapp.sql.*, ..."...%>
이런 경우, 페이지 지시자를 다음과 같이 나누는 것이 즐겨사용된다:
<%-- import를 제외한 모든 속성 --%><%@ page...%><%-- import 속성들은 여기부터 시작 --%><%@ page import="java.util.*" %><%@ page import="java.text.*" %>...
주의할 점은, 일반적으로 import
문은 자바의 지역 코드 작성요령을 준수한다. 예를 들어, 같은 패키지에서 세 개의 클래스까지만 사용되면, import
는 패키지를 선언하기 보다는, 클래스를 일일이 선언한다. 세 개를 넘어가면, 클래스를 일일이 지정할 것인지 아니면, ".*" 표시를 사용할 것인지는 웹 개발자 마음이다. 전자의 경우, 외부 클래스가 무엇이 사용되는지를 쉽게 알수 있다. 특히 버그가 많은 클래스를 위치시키려고 하거나, JSP 가 자바 코드와 어떻게 상호작용하는지를 이해하려할 경우에 유용하다. 예를 들어서, 아래처럼 임포트한 자바 패키지들에 관해 알지 못하면, 웹 개발자는 Customer
클래스를 찾기 위해서 이 모든 패키지들을 검색해봐야 된다:
<%@ page import="com.mycorp.bank.savings.*" %><%@ page import="com.thirdpartycorp.cashmanagement.*" %><%@ page import="com.mycorp.bank.foreignexchange.*" %>...
후자의 경우, 작성된 JSP 가 깔끔하지만, 사용한 클래스가 무엇인지 아는 것은 어려워진다. 일반적으로, JSP 에 임포트 지시자가 너무 많으면, 자바 코드가 너무 많이 들어가 있기 쉽다. 보다 나은 선택은 JSP 태그를 더 사용하는 것이다.(후에 언급하겠다).
선택적 태그 라이브러리 지시자 Optional Tag Library Directive(s)
태그 라이브러리 지시자는 JSP 에서 사용하는 커스텀 태그 라이브러리를 선언한다. 짧은 지시자는 하나의 줄에 선언할 수 있다. 여러 개의 태그 라이브러리 지시자들은 JSP 의 한 곳에 같이 모아둔다:
<%@ taglib uri="URI1" prefix="tagPrefix1" %><%@ taglib uri="URI2" prefix="tagPrefix2" %>...
페이지 지시자처럼, 태그 라이브러리 지시자의 길이가 일반적인 JSP 폭(80 문자)을 넘어갈 경우 여러 줄로 나눠진다:
<%@ taglib uri="URI2" prefix="tagPrefix2"%>
오직 페이지에서 사용하는 태그 라이브러리만 임포트되어야 한다.
JSP 1.2 부터, 웹 어플리케이션의 JSP에 JSTL;JSP 표준 태그 라이브러리사용하기를 적극 권장한다. 페이지에서 JSP 스크립틀릿 사용할 필요를 줄여주기 때문이다. 일반적으로, JSTL을 사용하는 페이지는 소스읽기와 유지보수가 보다 편하다.
선택적 JSP 선언문 Optional JSP Declaration(s)
JSP 선언문은 JSP에서 소속된 메소드와 변수를 선언한다. 이들 메소드와 변수는 자바 프로그램에서의 선언문과 다를바 없다. 그래서 적절한 코드 작성요령을 따르기만 하면 된다. 선언문은 <%! ... %
> JSP 선언문 블록 하나에 모두 몰아서 한 곳에 집중해 놓는 것이 좋다. 예를 들면:
다른 선언문 블록들 | 바람직한 선언문 블록 |
<%! private int hitCount; %> <%! private Date today; %> ... <%! public int getHitCount() { return hitCount; } %> |
<%! private int hitCount; private Date today; public int getHitCount() { return hitCount; } %> |
HTML 과 JSP 코드 HTML and JSP Code
이 섹션은 JSP 코드와 HTML 이 섞여있는 페이지에 대해 설명한다. JSP 표현식, 스크립틀릿, 자바빈즈 지시자 등이 해당된다.
태그 라이브러리 설명서 Tag Library Descriptor
태그 라이브러리 설명서(TLD)는 적당한 XML선언과 올바른 DTD 문으로 시작한다. 예를 들어서, JSP 1.2 TLD 는 다음과 같이 시작해야 된다:
<?xml version="1.0" encoding="ISO-8859-1" ?><!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
바로 뒤이어 서버측 주석과 같은 스타일의 주석을 기입한다. 작성자, 일자, 저작권, 증명 정보, 라이브러리에 대한 짧은 설명이다:
<!-- - 작성자: - 일자: - 저작권 표시: - @(#) - 설명: -->
여기에 관한 규칙과 가이드라인은 JSP 파일/프래그먼트 파일에서 정의된 것과 동일하다.
태그 라이브러리 파일의 나머지는 다음에 나오는 순서대로 이루어져 있다:
- 태그 라이브러리 검증기 하나의 선택적 선언문
- 이벤트 리스너들의 선택적 선언문
- 하나 이상의 가능한 태그들의 선언
TLD 에서 엘리먼트 마지막에 선택적 서브 엘리먼트를 항상 덧붙이기를 추천한다. 이 선택적 서브 엘리먼트는 태그 디자이너가 TLD의 습성과 추가적인 정보를 문서화할 장소를 제공한다. 이것은 웹 컴포넌트 개발자들에게는 보이지 않게 된다.
TLD Element | JSP 1.2 Recommended Sub-element |
JSP 1.1 Recommended Sub-element |
attribute (JSP 1.2) | description | |
init-param (JSP 1.2) | description | |
tag | display-name, description, example | name, info |
taglib | uri, display-name, description | uri, info |
validator (JSP 1.2) | description | |
variable (JSP 1.2) | description |
들여쓰기 Indentation
들여쓰기는 반드시 공백문자로 채워야한다. 탭은 사용하는 에디터마다 표시하는 공백의 수가 다르기 때문에 JSP 내에서 들여쓰기로 사용하기에는 적합하지 않다. 특별히 통합개발환경(IDE) 툴에서 제한되지 않았다면, 기본 들여쓰기 단위는 4개의 공백문자로 한다. 다음은 그 사용예이다:
<myTagLib:forEach var="client" items="${clients}"> <myTagLib:mail value="${client}" /></myTagLib:forEach>
연속 들여쓰기는 이전 줄의 적당한 지점에서 시작한다. 연속 들여쓰기의 공백은 기본 들여쓰기 공백의 배수이다. (4개의 공백문자의 배수):
<%@ page attribute1="value1" attribute2="value2" ... attributeN="valueN"%>
스크립트 엘리먼트의 들여쓰기 Indentation of Scripting Elements
JSP 스크립트 엘리먼트(선언문, 스크립틀릿, 표현식과 같은)가 한 줄에 맞지 않는 경우, 스크립트 언어의 들여쓰기 작성요령이 엘리먼트 내에 적용된다. 몸체는 엘리먼트의 여는 기호 <%=
와 같은 줄에서 시작한다. 다음줄의 기준도 여는 기호 <%=
가 된다. 몸체의 끝은 다른 줄에 있는 엘리먼트의 닫는 기호(%>
)로 마무리된다. 예제이다:
<%= (Calendar.getInstance().get(Calendar.DAY_OF_WEEK)
= Calendar.SUNDAY) ?
"Sleep in" :
"Go to work"
%>
첫줄과 마지막 줄을 제외한 몸체의 가운데 줄들은 단위 들여쓰기 공백(앞 예제에서
로 보인다)이 앞에 있기 때문에 나머지 JSP 보다 확연히 드러나게 된다.
JSP, HTML, JAVA의 복합 들여쓰기 Compound Indentation with JSP, HTML and Java
자바의 스크립트 코드와 템플릿 텍스트(HTML)가 섞여있는 JSP 엘리먼트를 위해서 복합 들여쓰기가 필요한 이유는 JSP 소스를 이해하기 위해 드는 노력을 덜어주기 위해서이다. 기존의 들여쓰기 요령은 JSP 소스파일을 더 알아보기 어렵게 할 수 있기 때문이다. 보편적인 규칙에 따라서, 다른 소스 사이에 끼어 있을 경우마다 보통 들여쓰기에 특별한 단위를 할당한다. 클라이언트에 보여지는 들여쓰기에 영향을 준다. 추가적인 들여쓰기는 (브라우저에 의해) 보통 무시되고, 브라우저에 나타나는 결과는 차이가 없다. 예를 들어, <TABLE>
태그 앞에 공백이 몇 개 더 추가된다고 해서, 브라우저에서 보여지는 테이블의 위치가 달라지는 것은 아니다. 그래서 이러한 작성요령을 사용하는 것이 더 좋아 보인다:
<table> <% if { tableHeaderRequired ) { %> <tr> <th>Last Name</th> <th>First Name</th> </tr> <% } %> <c:forEach var="customer" items="${customers}"> <tr> <td><c:out value="${customer.lastName}"/></td> <td><c:out value="${customer.firstName}"/></td> </tr> </c:forEach> </table>
위 방식보다는 아래 방식이 낫다:
<table> <% if { tableHeaderRequired ) { %> <tr> <th>Last Name</th> <th>First Name</th> </tr> <% } %> <c:forEach var="customer" items="${customers}"> <tr> <td><c:out value="${customer.lastName}"/></td> <td><c:out value="${customer.firstName}"/></td> </tr> </c:forEach> </table>
주석 Comments
주석은 추가 정보 전달이나 코드를 둘러쌀 목적으로 사용한다. 여기서는 JSP에서 사용하는 두가지 형태의 주석을 볼 것이다: JSP 측과 클라이언트 측 주석이다.
JSP 주석 JSP Comments
JSP 주석(또는 서버 측 주석)은 서버에서만 볼 수 있다(즉, 클라이언트로 전파되지 않는다). 순수 JSP 주석을 스크립팅 언어와 섞여있는 JSP 주석보다 즐겨 사용한다. 전자가 기반 스크립트 언어에 덜 종속적이기 때문이고, JSP 2.0 으로 진화하기 더 쉽기 때문이다. 다음 도표는 이것을 설명한다:
Line | JSP 스크립틀릿과 스크립트 언어 주석 | 순수 JSP 주석 |
한 줄 | <% /** ... */ %> <% /* ... */ %> <% // ... %> |
<%-- ... --%> |
여러 줄 | <% /* * ... * */ %> |
<%-- - ... - -- %> |
<% // // ... // %> |
클라이언트 측 주석 Client Side Comments
클라이언트 측 주석(<!-- ... -->
)은 응답에 대해서 부가적인 정보를 클라이언트로 보내기 위해 응답에 주석을 다는 것이다. 서버 어플리케이션의 행동이나 내부적인 구조에 대한 것과 응답 내용을 생성하는 코드가 포함되어서는 안된다.
클라이언트/사용자의 입장에서 서버에서 보내온 응답을 해석하기 위해서 이런 종류의 주석을 직접 볼 필요가 없기 때문에, 클라이언트 측 주석은 보편적으로 사용되지 않는다. 앞서 얘기한대로 증명이나, 저작권 정보 등의 법적인 목적의 증명에 사용될 경우는 예외가 되겠다. 다른 예외적인 경우는 HTML 저작도구들이 HTML 문서 구조의 틀을 잡아주기 위해 작은 양의 HTML 주석들을 사용하는 경우가 되겠다. 예를 들면 다음과 같다:
<!-- 툴바 섹션 --> ...<!-- 왼쪽 네비게이션 메뉴 --> ...<!-- main body --> ...<!-- footer --> ...
여러 줄의 주석 Multiline Comment Block
JSP 또는 클라이언트 측 모두, 여러 줄의 주석은 대시 문자 "-" 로 꾸며진다. XML 스펙에서, 더블-대시 문자열 "--"은 XML 주석 문 내에 허용되지 않는다. 그러므로, 이 스펙에 호환성과 일관성을 갖기 위해서, 더블-대시 문자열은 여러줄의 주석문 내에 사용되면 안된다. 다음 도표는 클라이언트 측 여러 줄 주석 사용법을 보여준다:
권장 | XML과 맞지 않는 법 |
<!-- - line 1 - line 2 ... --> |
<!-- -- line 1 -- line 2 ... --> |
JSP 선언문 JSP Declarations
자바 코드 작성요령에 따라서, 같은 타입의 변수 선언문은 다른 줄에서 이루어져야 된다:
비 추천 | 추천 |
<%! private int x, y; %> |
<%! private int x; %> <%! private int y; %> |
자바빈즈는 <jsp:useBean>
액션 태그를 사용하는 대신, JSP 선언문을 통해서 선언되고 인스턴스화되면 안된다.
일반적으로, 변수를 위한 JSP 선언문은 그 자체가 스크립트 언어의 사용을 부추기기 때문에 사용하지 않는 것이 좋다. JSP 는 프리젠테이션 목적으로 설계되었는데, 여기에 비지니스 로직과 자바코드를 섞어놓기 때문이다. 그리고, 변수의 스코프 관리에 따른 부담도 생기게 된다.
JSP 스크립틀릿 JSP Scriptlets
가급적, 태그라이브러리로 동일한 기능을 구현할 수 있으면, JSP 스클립틀릿은 피하기 바란다. 이렇게 하면 페이지 가독성도 높이고, 유지보수도 쉬워진다. 비지니스 로직을 프리진테이션 로직에서 분리하는데 일조하며, JSP 2.0 스타일의 페이지로 쉽게 옮겨갈 수 있다(JSP 2.0 도 스크립틀릿을 지원하지만 덜 강조한다). 다음 예제는 customers 표시 방법이 데이터 형에 따라서 다른 스크립틀릿을 사용하는 것을 보여준다:
customers
는 Customers의 배열
<table> <% for ( int i=0; i<customers.length; i++ ) { %> <tr> <td><%= customers[i].getLastName() %></td> <td><%= customers[i].getFirstName() %></td> </tr> <% } %> </table>
customers 는 Enumeration
형
<table> <% for ( Enumeration e = customers.elements(); e.hasMoreElements(); ) { Customer customer = (Customer)e.nextElement(); %> <tr> <td><%= customer.getLastName() %></td> <td><%= customer.getFirstName() %></td> </tr> <% } %> </table>
그러나, 공통 태그라이브러리를 사용하면, customers 의 데이터 형이 달라도 보다 높은 유연성이 생긴다. 예를 들어서, JSTL 에서는customers 를 나타내기 위해서 배열과 Enumeration
양쪽 모두 지원하는 다음과 같은 코드로 표시할 수 있다:
<table> <c:forEach var="customer" items="${customers}"> <tr> <td><c:out value="${customer.lastName}"/></td> <td><c:out value="${customer.firstName}"/></td> </tr> </c:forEach> </table>
비지니스 로직과 프리젠테이션 층과의 결합도을 줄이기 위한 모델-뷰-컨트롤러(MVC) 디자인 패턴을 적용하려고 한다면, JSP 스크립틀릿은 비지니스 로직을 구현하기 위해서 사용되어서는 안된다. 오히려, JSP 스크립틀릿은 클라이언트의 요청을 처리한 뒤에 나오는 데이터("가치 객체 value objects"로 불리는)를 적절한 클라이언트의 준비된 형식에 전송하기 위해 필요하다면 사용된다. 심지어 그럴 경우에도, 프론트 컨트롤러 서블릿이나 커스텀 태그로 하는 게 더 낫다. 예를 들면, 다음의 코드는 데이터베이스에서 직접 customers 의 이름을 가져와 클라이언트에 보여준다:
<% // 스크립틀릿을 이용하는 것은 추천하지 않음! Connection conn = null; try { // Get connection InitialContext ctx = new InitialContext(); DataSource ds = (DataSource)ctx.lookup("customerDS"); conn = ds.getConnection(); // Get customer names Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT name FROM customer"); // Display names while ( rs.next() ) { out.println( rs.getString("name") + "<br>"); } } catch (SQLException e) { out.println("Could not retrieve customer names:" + e); } finally { if ( conn != null ) conn.close(); }%>
다음의 JSP 코드는 데이터베이스 처리부분을 내부적으로 데이터베이스 코드의 의존성을 숨기고 캡슐화한 커스텀태그myTags:dataSource
에 위임하고 있기 때문에 더 보기 좋다:
<myTags:dataSource name="customerDS" table="customer" columns="name" var="result" /><c:forEach var="row" items="${result.rows}"> <c:out value="${row.name}" /> <br /></c:forEach>
result
는 커스텀 태그 myTags:dataSource
가 customer 데이터베이스에서 customer의 이름들 뽑아낸 결과를 담으려고 만들어 낸 스크립팅 변수이다. JSP 코드는 클라이언트의 요구에 따라 동적으로 다른 종류의 출력(HTML, XML, WML)을 생성하기 위해 확장할 수 있다. 그것도 백엔드 코드(dataSource
태그를 위한)를 변경하지 않고도 가능하다. 더 나은 선택은 이것을 프론트 컨트롤러 서블릿에 위임하는 것이다. 이 서블릿은 데이터를 불러와서 그 결과를 request 스코프의 속성을 통해서 JSP에 제공한다. 예제는 자바 BluePrint의 엔터프라이즈 섹션을 참고하기 바란다.
요약하면 :
- 이상적으로, 스크립트 언어로부터 독립하기 위해서 JSP 스크립틀릿은 JSP 내에서 사라져야 되고, JSP 내의 비지니스 로직 구현은 피해야 된다.
- 그것이 불가하면, 서버 측에서 정보를 전달하는데 값 객체(자바빈즈)를 사용하고, JSP 스크립틀릿은 클라이언트 출력에 이 값 객체를 전달하는 데 사용한다.
- 가능하면 커스텀 태그(태그 핸들러)를 사용해서 서버측에서 정보를 처리하도록 한다.
JSP 표현식 JSP Expressions
JSP 표현식은 JSP 스크립틀릿처럼 가능하면 삼가는 것이 좋다. 동일한 작업을 수행하는 다음 3가지 예제가 잘 설명해준다:
Example 1 (자바 코드 사용):
<%= myBean.getName() %>
Example 2 (JSP 태그 사용):
<jsp:getProperty name="myBean" property="name" />
Example 3 (JSTL 태그 사용):
<c:out value="${myBean.name}" />
Example 1 은 myBean
이라는 스크립트 변수가 선언된 것이라고 가정한다. 다른 두 예제에서 myBean
은 어떤 스코프의 속성으로 PageContext.findAttribute()
을 통해서 접근할 수 있다고 가정한다. 두 번째 예제는 또한 <jsp:useBean>
에 의해서 페이지에 소개된 myBean
이라고 가정한다.
셋 중에서 JSTL 태그 예제가 낫다. JSP 표현식 만큼 짧고, 가독성도 좋고, 유지보수하기도 보다 편하다. 그리고, 자바 스크립틀릿에 의존하지 않는다(스크립틀릿은 자바 언어와 API 함수들에 익숙해야 다룰 수 있다.) 더우기, JSP 2.0 스타일 프로그램으로 쉽게 이동할 수 있는 장점이 있다. 어떤 선택이 채택되든, 모든 개발자들의 동의를 얻어서, 같은 프로젝트에 있는 JSP 결과물들은 전체적으로 일관된 방식을 사용해야 된다. 주의할 점은, JSTL 예제는 로컬 자바 스크립트 변수로부터가 아닌, page 컨텍스트로부터 myBean
의 값을 가져온다는 것이 실질적으로 조금 다른 점이다.
마지막으로, JSP 표현식은 기반 스크립팅 언어의 문법에 의존하는, 같은 기능의 JSP 스크립틀릿보다 낫다. 예를 들어,
<%= x %>
로 하는 게 아래 방법보다 좋다.
<% out.print( x ); %>
공백 White Space
코드의 이해와 유지보수에 드는 노력을 줄이기 위해서 JSP 코드를 보기 좋게 들여쓰기하는데 공백을 사용한다. 특히, 빈 줄과 공백은 필요한 곳에서 JSP 의 여러 곳에 삽입되어야 한다.
빈 줄 Blank Lines
빈 줄은 출력에 원하지 않는 영향만 주지 않는다면 JSP의 가독성을 높이기 위해서 가끔 사용된다. 아래 예제에서, HTML <PRE>
블록 내에 두 개의 JSP 표현식 사이에 있는 빈 줄은 클라이언트의 브라우저에 HTML 출력 결과에서 한줄 더 생기게 만든다. 그러나 빈 줄이 <PRE>
블록 사이에 있지 않다면, 브라우저의 출력에 나타나지 않는다.
JSP 구문 | 클라이언트의 HTML 출력 |
<pre> <%= customer.getFirstName() %> <%= customer.getLastName() %> </pre> |
Joe Block |
<pre> <%= customer.getFirstName() %> <%= customer.getLastName() %> </pre> |
Joe Block |
<%= customer.getFirstName() %> <%= customer.getLastName() %> |
Joe Block |
빈 문자열 Blank Spaces
공백 문자(
; 역자주:공백은 길이가 1, 빈 문자열은 ""처럼 길이가 0)는 JSP 태그와 몸체 사이에 쓰여져야 된다. 예를 들어 다음
<%= customer.getName() %>
코드는 아래 것보다 좋다.
<%=customer.getName()%>
JSP 주석 태그와 주석을 분리하는 공백 문자들이 있어야 된다:
<%-- - 여러 줄의 주석이 나뉘어지면, 각각의 줄은 - 한 줄씩 차지한다. --%><%-- 짧은 주석 --%>
이름짓는 요령 Naming Conventions
이름짓는 요령을 적용하면, 프로젝트 내의 웹 컴포넌트 엘리먼트들을 쉽게 확인, 분류, 통합할 수 있다. 이 섹션에서, JSP에 적합한 요령을 살펴보자.
JSP 이름 JSP Names
JSP (파일) 이름은 언제나 소문자로 시작해야 한다. 여러 개의 단어로 구성될 수 있고, 이러한 경우 단어들은 모두 붙여쓰고, 이어지는 단어의 첫글자는 대문자로 쓴다. JSP 이름은 간단한 명사나 짧은 문장이 될 수 있다. 동사뿐인 JSP 명은 개발자에게 충분한 의미를 전달하지 못하기 때문에, 피하도록 한다. 예를 들면:
perform.jsp
파일은 다음 파일보다 명확하지 않다.
performLogin.jsp
JSP 이름에 동사가 들어가는 경우, 은연 중에 뒷쪽에서 처리하고 있다는 표시로 현재형을 쓴다:
showAccountDetails.jsp
로 쓰는 게 아래 파일명 보다 좋다
showingAccountDetails.jsp
태그 이름 Tag Names
태그 핸들러와 관련된 클래스에 대한 이름짓는 요령은 다음과 같다:
설명 | 클래스 명 |
XXX tag extra info (javax.servlet.jsp.tagext.TagExtraInfo 를 상속함) |
XXXTEI |
XXX tag library validator (javax.servlet.jsp.tagext.TagLibraryValidator 를 상속함) |
XXXTLV |
XXX tag handler interface (javax.servlet.jsp.tagext.Tag/IterationTag/BodyTag 를 상속함) |
XXXTag |
XXX tag handler implementation | XXXTag |
덧붙여, 태그 이름은 자바에 관련된 코드작성법에서 정한 클래스와 인터페이스 이름 짓는 요령을 따라서 정해야 된다.
태그 관련된 클래스와 다른 클래스와 더 분명하게 구분하기 위해서, 패키지 접미사(tags 또는 taglib)를 클래스의 패키지명에 적용한다. 예를 들면:
com.mycorp.myapp.tags.XXXTag
태그 prefix 이름 Tag Prefix Names
태그 prefix 는 짧지만 의미가 담긴 명사를 사용해야 하고, 첫문자는 소문자로 해야한다. 태그 prefix 는 알파벳 문자만 포함해야 된다. 몇 가지 예를 들면 다음과 같다:
예 | OK? |
mytaglib |
no |
myTagLib |
yes |
MyTagLib |
no |
MyTagLib1 |
no |
My_Tag_Lib |
no |
My$Tag$Lib |
no |
XML 문법의 JSP 페이지 JSP Pages in XML Syntax
JSP 는 두가지 다른 문법을 제공한다: JSP 페이지를 작성하는 '표준 문법'과 JSP를 XML문서로 작성하는 'XML 문법'이 있다. 표준 문법을 사용하는 JSP 페이지들이 'JSP 페이지'로 많이 쓰인다. XML 문법으로 작성된 JSP는 'JSP 문서'라고 일컫는다. 이 기사는 우선적으로 JSP 페이지를 소개하지만, 많은 부분의 개념들이 JSP 문서에도 역시 적용될 수 있다. XML이 좀 더 유행하면 JSP 문서 사용도 많아질 것이라고 기대된다. JSP 2.0 스펙에서는 더 많은 XML 문법 친화적인 것들이 소개될 것이다.
주의할 것은 XML 문법을 이용해서 JSP를 만드는 것과 JSP로 XML 결과(view)를 만들어 내는 것과 혼동해서는 안된다. 페이지 제작도구는 JSP를 만들기 위해 표준 또는 XML 문법을 사용한다. 그리고 나서 컨테이너는 JSP를 XML 결과로 변환하고, 이것은 태그 라이브러리 밸리데이터(유효성 검증기)에서 확인한다.
JSP 문서 구조 JSP Document Structure
JSP 문서는 다음과 같은 기본 구조를 갖는다:
<? xml version="1.0" ?> <!-- - Author(s): - Date: - Copyright Notice: - @(#) - Description: --> <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:prefix1="URI-for-taglib1" xmlns:prefix2="URI-for-taglib2" version="1.2"> JSP Document ... </jsp:root>
첫 줄은, 이 페이지가 XML 문서라고 정의하는 선택적 XML 프롤로그이다. 다음으로 오는 것은 문서에 대한 주석이다. <jsp:root>
엘리먼트는 이것이 JSP 문서임을 정의하고, 반드시 이 엘리먼트가 루트 엘리먼트로 나타나야 된다. jsp
이름공간은 반드시 가져와야 되고, 모든 태그 라이브러리는 이 루트 엘리먼트를 사용해서 가져와야 된다. 버전 속성이 필요하고, 어떤 버전을 사용할 지를 정해준다. JSP 문서의 실제 내용은 <jsp:root>
엘리먼트의 서브엘리먼트에 나타난다. 표준 XML 들여쓰기 룰에 따라서 문서 전체적으로 일관되게 적용하는 들여쓰기 단위는 4개의 공백문자이다.
JSP 문서는 형식이 잘 갖춰진 XML 문서이기 때문에, <% %>
와 같은 엘리먼트는 <jsp:scriptlet />
같이 XML로 바꿔서 표기해야 된다. 자세한 것은 JSP 스펙을 보기 바란다.
XML 주석 XML Comments
JSP 스펙은 XML 스타일의 주석을 어떻게 처리할 지에 대해 불분명하기 때문에, 주석이 클라이언트로 안전하게 전달되기 위해서는, <jsp:text>
로 다음과 같이 감싸주어야 된다:
... <jsp:text><![CDATA[ <!-- - Multiline comment - to be sent to client. --> ]]></jsp:text> ...
JSP 문서 내의 자바 코드 Java Code in JSP Documents
선언문, 스크립틀릿, 표현식에서 자바 코드를 쓰려고 할 때, 코드가 문서의 구조를 망가뜨리지 않는다면, CDATA엘리먼트를 사용한다.
... <jsp:scriptlet> for( int level = 0; level < 3; level++ ) { </jsp:scriptlet> <tr> <td> <jsp:expression><![CDATA[ "<h" + level + ">Text</h" + level + ">" ]]></jsp:expression> </td> </tr> <jsp:scriptlet> } </jsp:scriptlet> ...
표준 문법에서와 다르게, XML 들여쓰기 법칙은 엘리먼트의 내용과 상관없이 준수되어야 한다.
프로그래밍 습관 Programming Practices
일반적으로, 다음과 같은 이유로 JSP 페이지에 자바 코드(선언문, 스크립틀릿, 표현식) 쓰기를 피한다:
- JSP 페이지의 자바 코드 문법 에러는 페이지가 배치되기 전까지 발견되지 않는다. 반면에, 태그 라이브러리와 서블릿에 있는 문법 에러는 배치 이전에 발견된다.
- JSP 페이지 내의 자바 코드는 디버깅하기 힘들다.
- JSP 페이지 내의 자바 코드는 유지보수하기 힘들다. 특히 자바 전문가가 아니라면 더욱 더 그렇다.
- 보통 복잡한 비즈니스 로직과 프리젠테이션 로직을 섞어놓지 않는 것이 납득이 가는 습관이다. JSP는 우선적으로 프리젠테이션 로직을 목적으로 한다.
- 자바 코드가 포함된 코드와 HTML과 다른 스크립트 명령어가 섞여있다면 더 읽기 어려워진다.
- JSP 2.0 은 더 단순한 표현 언어를 덕분에 스크립틀릿의 중요도를 낮추었다. JSP 에서 JSP 2.0 스타일로 쉽게 옮기기 위해서는 페이지에서 자바 코드를 사용하지 않는 것이 좋다.
자바 BluePrints의 엔터프라이즈 섹션에 있는 더 자세한 정보와 가이드라인을 참고하기 바란다.
자바빈즈 초기화 JavaBeans Initialization
JSP는 JavaBeanTM의 프로퍼티로 증명되는 모든 PropertyDescriptor
를 초기화하기 위해 편리한 엘리먼트를 제공한다. 예를 들면:
<jsp:setProperty name="bankClient" property="*"/>
그러나, 주의해서 사용해야 한다. 첫째로, 빈이 프로퍼티를 갖고 있다, 즉 amount
프로퍼티가 있다고 하고, 현재 ServletRequest
객체에 파라미터(amount)가 없거나 파라미터 값이 ""라고 한다면, 아무것도 하지 않는다: JSP는 빈의 특정 프로퍼티에 null
를 할당하지도 않는다. bankClient
빈에 amount
의 기존 값이 무엇이든지 간에 영향을 받지 않는다. 둘째로, PropertyEditors
를 선언하지 않은 비-요소적인 프로퍼티는 ServletRequest
객체의 스트링 값에서 암묵적으로 초기화 되지 않기 때문에, 명시적인 변환이 필요하다. 세째로, 만일 어플리케이션이 주의 깊게 설계되지 않았다면, 악의를 가진 사용자는 추가적으로 요청 파라미터를 덧붙여서 빈의 사용하지 말아야할 프로퍼티 값을 설정할 수 있다.
깔끔한 코드를 위해서 jsp:setProperty
태그에 property="*"
를 사용한다면, jsp:setProperty
태그 이전에 ServletRequest 객체를 통해서 받아와야 할, 빈을 초기화하기 위한 파라미터들에 대해 주석을 달기를 권한다. 다음 예제에서는 bankClient
빈을 초기화하기 위해서 firstName
와 lastName
파라미터가 필요하다는 것을 주석에서 읽을 수 있다:
<%-- - ServletRequest에서 firstName와 lastName를 요구 --%><jsp:setProperty name="bankClient" property="*" />
JSP 내장 객체 JSP Implicit Objects
API 호출을 통해서 객체를 참조하기 보다는 JSP 내장 객체를 직접 사용하는 것이 좋다. 그래서 ServletContext
인스턴스에 의해 제공되는 초기 파라미터에 접근하기 위해 다음을 쓰는 대신에
getServletConfig().getServletContext().getInitParameter("param")
기존 내장 객체를 사용하는 게 낫다:
application.getInitParameter("param")
초기 파라미터 값이 출력이 되어야 하는 경우에는, JSTL로 접근해서 출력하는 것이 더 좋다:
<c:out value="${initParam['param']}" />
인용부호 Quoting
일정한 인용부호의 사용을 채택한다. 인용부호는 작은따옴표 ' 대신 큰따옴표 " 를 사용한다.
불규칙한 인용부호 | 좋은 인용부호 사용 |
<%@ page import='javabeans.*'%> |
<%@ page import="javabeans.*" %> |
예외적인 경우는 작은따옴표가 필요할 때이다. 예를 들어서 스크립트 언어에서 큰따옴표를 사용하는 경우를 들 수 있다:
<jsp:include page='<%= getFoodMenuBar("Monday") %>' />
커스텀 태그 사용하기 Using Custom Tags
만일 커스텀태그가 몸체가 없다면, 컨텐트는 (생략해서 "JSP" 기본값으로 하지 말고) empty라고 명확하게 선언되어야 한다. 태그 라이브러리 설명서에서 다음과 같이 정해준다:
<tag> <name>hello</name> <tag-class>com.mycorp.util.taglib.HelloTagSupport</tag-class> <body-content>empty</body-content> ...</tag>
이렇게 하면 JSP 컨테이너는 태그 몸체가 무조건 비어야 되며 파싱할 어떤 JSP 문법도 포함하지 않아야 된다고 인식한다. 효과는 빈 몸체를 파싱하기 위해서 불필요하게 자원의 할당이 이뤄지는 것을 제거한다.
빈 태그는, 가독성향상을 위해 열고 닫는 XML 엘리먼트 쌍으로 표시하기보다는, 짧은 XML 엘리먼트로 표시한다. 그래서
<myTag:hello />
라고 표기하는 것이 아래보다 낫다.
<myTag:hello></myTag:hello>
TagExtraInfo와 TagLibraryValidator 사용 Use of TagExtraInfo and TagLibraryValidator
때때로, 태그 라이브러리를 사용하는데 TLD 하나로 유효성을 검증할 수 없는 경우가 있다. 그 때는 TLD에 등록된 TagExtraInfo
클래스나 TagLibraryValidator
클래스를 사용해서, 변환할 때 태그 라이브러리에 있는 에러를 잡아낼 수 있다.
자바스크립트 사용 Use of JavaScriptTM
스크립트가 제대로 돌아가기 위해서는 자바스크립트는 브라우저 타입의 특성과 관계없어야 된다.
동작을 한다면, JSP에서 자바스크립트 코드를 독립적인 파일로 분리하고, 다음과 같이 JSP에서 자바스크립트를 불러쓰는 방식은 좋은 생각이다:
<script language=javascript src="/js/main.js">
이렇게 하면 자바스크립트의 재사용성도 향상되고, 여러 JSP 사이에 일관된 습성의 자바스크립트를 유지할 수 있고, JSP페이지의 복잡성을 줄여준다.
캐스케이딩 스타일 시트 CSS Cascading Style Sheets
CSS를 사용해서 헤딩, 테이블 등의 공통적인 특성을 중앙에서 제어하도록 한다. 이 방법은 사용자들에게 프리젠테이션의 일관성을 향상시키고, 유지보수 노력과 JSP 페이지의 코드 사이즈를 줄여준다. 그래서, 다음과 같이 HTML 태그에서 스타일 정보를 끼어쓰지 말고:
<H1><FONT color="blue">Chapter 1</FONT></H1>...<H1><FONT color="blue">Chapter 2</FONT></H1>...
하나의 스타일 시트 파일myJspStyle.css
에 다음과 같은 스타일 정보를 정의한다:
H1 { color: blue }
그리고 JSP 페이지에 스타일 시트를 적용한다:
<link rel="stylesheet" href="css/myJspStyle.css" type="text/css">...<H1>Chapter 1</H1>...<H1>Chapter 2</H1>...
컴포짓 뷰 패턴 사용 Use of Composite View Patterns
여러 JSP 페이지에서 반복되는 고정되고 복잡한 구조가 요구될 때, 이것을 다루는 방법으로 컴포짓 뷰 패턴(Composite View pattern;자바 Blueprints 의 패턴 섹션 참고)을 사용해서, 조각조각으로 나눠서 처리하는 법이 있다. 예를 들어, 프리젠테이션 구조에서 JSP 는 때때로 다음과 같은 로직 레이아웃을 갖고 있다:
header | |
menu bar | main body |
footnote | |
footer |
이런 방식으로, 컴포짓 JSP 는 각각 분리된 JSP로 구현되는 다른 모듈로 나뉠 수 있다. 구성성분이 되는 JSP는 서블릿으로 변환할 때나 요청시에 include JSP 태그를 사용해서 컴포짓 JSP 의 적당한 위치에 놓이게 된다. 보편적으로, 독립적으로 요청되지 않는 페이지를 불러쓰는, 정적인 include 지시자를 사용할 때는 .jspf
확장자를 사용하고, 웹 어플리케이션 (war)에서 /WEB-INF/jspf/
디렉토리에 놓아둘 것을 기억하기 바란다. 예를 들면 다음과 같다:
<%@ include file="/WEB-INF/jspf/header.jspf" %>...<%@ include file="/WEB-INF/jspf/menuBar.jspf" %>...<jsp:include page="<%= currentBody %>" />...<%@ include file="/WEB-INF/jspf/footnote.jspf" %>...<%@ include file="/WEB-INF/jspf/footer.jspf" %>...
다른 추천사항 Other Recommendations
이 문서에서, JSP 코드와 웹 컴포넌트를 작성하는데 보다 유지보수하기 쉽고, 일관된 추천 코드 작성법 한 세트를 제시했다. 이 주제에 보다 더 관심있다면, 더 많은 최고의 작성법이 존재한다. 예를 들어, JSP 1.2 스펙에서는 다음을 추천한다:
- 새로운 내장 객체 선언하기
- 벤더 고유의 안내서 읽기
- 커스텀 태그 라이브러리 사용하기
덧붙여서, 자바 BluePrints 는 더 큰 스케일에서 최고의 작성법을 제공한다. (패턴 섹션에서 보여지는) 모델-뷰-컨트롤러 패턴과 같은 것을 예로 들 수 있다.
우리는 이 문서에서 제시한 작성요령에 대한 여러분의 의견에 관심이 있습니다. JSP 코드 작성요령에 대해서 여러분의 다른 의견이 있다면 나누면 좋겠습니다. 피드백은 여기로 보내기 바랍니다. jsp-codeconv-comments@sun.com.
아래에, 위에서 설명한 코드 작성요령을 적용해 놓은 완전한 웹 어플리케이션의 소스를 소개한다. 이 어플리케이션의 WAR 파일을 여기 에서 다운로드 받을 수 있다.
코드 예제 Code Examples
여기에 있는 웹 어플리케이션 예제는 이 문서에 있는 내용이 어떻게 적용되는지 보여주기 위한 것이다. .war 파일에는 다음의 소스코드 파일과 디렉토리 구조로 되어 있다:
/index.jsp/WEB-INF/classes/codeconv/GetResultsTag.class/WEB-INF/jspf/footer.jspf/WEB-INF/lib/jstl.jar/WEB-INF/lib/standard.jar/WEB-INF/tld/lotterylib.tld/WEB-INF/web.xml
index.jsp 페이지에서는 오늘까지 포함된 이번 달의 모의 복권 추첨결과를 보여주는 커스텀 태그 라이브러리( lotterylib.tld
)를 사용한다. 그리고, HTML 에 보여질 결과를 형식화하고, 반복하기 위해서 JSTL을 사용한다.
예제는 JSP 1.2 과 JSTL 1.0 을 사용한다.
/index.jsp 파일 소스
<%-- - Author: Mark Roth - Date: January 17, 2003 - - Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. - - This software is the proprietary information of - Sun Microsystems, Inc. - Use is subject to license terms. - - @(#) - Description: Renders fake lottery results for the current month. --%><%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %><%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %><%@ taglib prefix="lottery" uri="http://codeconv/lotterylib" %><html> <head> <title>Fake Lottery Results for this Month </title> </head> <body> <jsp:useBean id="now" class="java.util.Date" /> <h1> Fake Lottery Results for <fmt:formatDate value="${now}" pattern="MMMM yyyy" /> </h1> <hr /> <table border="1" cellpadding="5"> <%-- Store current month and year --%> <c:set var="currentMonth"> <fmt:formatDate value="${now}" pattern="M" /> </c:set> <c:set var="currentYear"> <fmt:formatDate value="${now}" pattern="yyyy" /> </c:set> <%-- Determine last day to report results for --%> <c:set var="endDay"> <fmt:formatDate value="${now}" pattern="d" /> </c:set> <%-- Display one row for each day --%> <c:forEach var="day" begin="1" end="${endDay}"> <%-- Construct date --%> <c:set var="dateString"> <c:out value="${currentMonth}/${day}/${ currentYear}" /> </c:set> <fmt:parseDate var="date" value="${dateString}" pattern="M/d/yyyy" /> <jsp:useBean id="date" class="java.util.Date" /> <tr> <td> <c:out value="${dateString}" /> </td> <%-- Retrieve and display fake results for this day --%> <lottery:getResults var="numbers" date="<%= date %>" /> <c:forEach var="number" items="${numbers}"> <td> <c:out value="${number}" /> </td> </c:forEach> </tr> </c:forEach> </table> <%@ include file="/WEB-INF/jspf/footer.jspf" %> </body></html>
/WEB-INF/classes/codeconv/GetResultsTag.java 소스
/* * codeconv.GetResultsTag * * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. * * This software is the proprietary information of * Sun Microsystems, Inc. * Use is subject to license terms. * * Version: @(#) * * Date: January 13, 2003 * */package codeconv;import java.util.Date;import java.util.Random;import javax.servlet.jsp.JspException;import javax.servlet.jsp.PageContext;import javax.servlet.jsp.tagext.TagSupport;/** * Retrieves fake lottery results for the given date and * returns the result in the given attribute * * @version @(#) * @author Mark Roth */public class GetResultsTag extends TagSupport { /** The maximum number that can be drawn */ private static final int MAX_NUMBER = 58; /** The number of numbers that are drawn */ private static final int NUMBER_COUNT = 6; /** The variable to store results to */ private String var; /** The date on which the numbers were drawn */ private Date date; /** The PageContext, used to return the result */ private PageContext pageContext; /** * Remember the PageContext so it can be used later * to return the result. * * @param pageContext The page context of the calling page */ public void setPageContext( PageContext pageContext ) { this.pageContext = pageContext; } /** * Returns fake lottery results for the given date. * * @return EVAL_PAGE so the rest of the page is evaluated. */ public int doEndTag() throws JspException { // Generate the (fake) results. Random random = new Random( this.date.getTime() ); int[] result = new int[NUMBER_COUNT]; for( int i = 0; i < NUMBER_COUNT; i++ ) { result[i] = random.nextInt( MAX_NUMBER ) + 1; } // Place the result in the scoped attribute named by 'var'. pageContext.setAttribute( this.var, result ); return EVAL_PAGE; } /** * Setter for date * * @param date The fake date on which the lottery numbers * were drawn */ public void setDate( Date date ) { this.date = date; } /** * Getter for date * * @return The fake date on which the lottery numbers * were drawn */ public Date getDate() { return this.date; } /** * Setter for var * * @param var The name of the variable to store the result in */ public void setVar( String var ) { this.var = var; } /** * Getter for var * * @return The name of the variable to restore the result in */ public String getVar() { return this.var; }}
/WEB-INF/jspf/footer.jspf 소스
<%-- - Author: Mark Roth - Date: January 17, 2003 - - Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. - - This software is the proprietary information of - Sun Microsystems, Inc. - Use is subject to license terms. - - @(#) - Description: Sample Footer that can be included on pages. - Assumes JSTL fmt taglib is imported. --%><!-- common footer --><hr /><jsp:useBean id="footerNow" class="java.util.Date" /><i> Last Updated: <fmt:formatDate type="both" value="${footerNow}" dateStyle="full" timeStyle="full" /></i>
/WEB-INF/tld/lotterylib.tld 파일 소스
<?xml version="1.0" encoding="ISO-8859-1" ?><!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/j2ee/dtd/web-jsptaglibrary_1_2.dtd"><!-- - Author: Mark Roth - Date: January 17, 2003 - - Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. - - This software is the proprietary information of - Sun Microsystems, Inc. - Use is subject to license terms. - - @(#) - Description: Tag Library for fake lottery results. --><taglib> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>lottery</short-name> <uri>http://codeconv/lotterylib</uri> <display-name>FakeLotteryTaglib</display-name> <description> Tag Library for fake lottery results. </description> <tag> <name>getResults</name> <tag-class>codeconv.GetResultsTag</tag-class> <body-content>empty</body-content> <display-name>getResults</display-name> <description> Retrieve an array of fake lottery results for the given date and store them in the given scoped attribute. </description> <variable> <name-from-attribute>var </name-from-attribute> <declare>true</declare> <description> The fake lottery results for the given date. </description> </variable> <attribute> <name>var</name> <required>true</required> <description> The name of the variable to store the results in. </description> </attribute> <attribute> <name>date</name> <required>true</required> <rtexprvalue>true</rtexprvalue> <type>java.util.Date</type> <description> The date on which the fake lottery numbers were drawn. </description> </attribute> <example><![CDATA[ <lottery:getResults var="numbers" date="${date}" /> ]]></example> </tag></taglib>
/WEB-INF/web.xml 소스
<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"><!-- - Author: Mark Roth - Date: January 17, 2003 - - Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. - - This software is the proprietary information of - Sun Microsystems, Inc. - Use is subject to license terms. - - @(#) - Description: Web Deployment Descriptor for JSP 1.2 fake - lottery example --><web-app> <display-name>FakeLotteryExample</display-name> <description> JSP 1.2 example application that illustrates correct JSP coding style. </description> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <taglib> <taglib-uri>http://codeconv/lotterylib</taglib-uri> <taglib-location>/WEB-INF/tld/lotterylib.tld </taglib-location> </taglib></web-app>
감사의 말 Acknowledgments
이 문서의 이전 드래프트에 소중한 조언을 제공해 주신 Gregory Murray (Java BluePrints Team), Damian Fauth (Sun Java Center), Kate Morris (Sun Java Center) 님들께 감사드립니다.
References
- Code Conventions for the Java Programming Language.
- JSP best practices.
- Hans's Top Ten JSP Tips.
- JavaServer Pages Specification version 1.2.
- Alur D., Crupi J., Malks D., Core J2EE Patterns: Best Practices and Design Strategies, Sun Microsystems Press, Prentice Hall Inc., 2001.
- Naming Conventions for Enterprise Applications.
- JavaServer Pages Standard Tag Library.
- Gamma E., Helm R., Johnson R., Vlissides J., Design Patterns: Elements of Reusable Software, Addison-Wesley, 1995.
- JavaServerTM Faces Technology.
- Java BluePrints.
- Designing Enterprise Applications with the J2EETM Platform, 2nd ed..
출처 :
'My work space > JSP/Servlet' 카테고리의 다른 글
servlet api 일본어판 다운로드 (0) | 2008.09.08 |
---|---|
JSTL 기초 자료 링크 (0) | 2008.09.08 |
Servlet API 사이트 (0) | 2008.09.08 |
Servlet 구조 (0) | 2008.09.08 |
[CONTAINER] 톰캣5 관리자 아이디 설정 등 사용자,권한 설정 (0) | 2008.09.08 |
서블릿 프로그램을 작성하다 보면, 서블릿 API를 참고해야 할 때가 있다.
아래 사이트 참조
1. tomcat 4.1 : http://tomcat.apache.org/tomcat-4.1-doc/servletapi/index.html
2. tomcat 5.0 : http://tomcat.apache.org/tomcat-5.0-doc/jspapi/index.html
3. tomcat 5.5 : http://tomcat.apache.org/tomcat-5.5-doc/jspapi/index.html
4. tomcat 6.x : http://tomcat.apache.org/tomcat-6.0-doc/api/index.html
'My work space > JSP/Servlet' 카테고리의 다른 글
JSTL 기초 자료 링크 (0) | 2008.09.08 |
---|---|
JSP코드작성표준양식-한글판 (0) | 2008.09.08 |
Servlet 구조 (0) | 2008.09.08 |
[CONTAINER] 톰캣5 관리자 아이디 설정 등 사용자,권한 설정 (0) | 2008.09.08 |
jsp 운영환경 구축 - 톰캣 어드민 (0) | 2008.09.08 |
javax.servlet.http
javax.servlet.Servlet
- init() : 서블릿을 초기화
- service() : 클라이언트 요청에 대한 서비스
- destory() : 자원반납
이들 메소드는 서블릿 라이프사이클(생명주기) 메소드이다. 모든 서블릿은 상속을 통해서든 아니면 직접적인 구현을 통해서든 반드시 Servlet 인터페이스를 구현해야 한다.
서블릿의 기본 골격인 인터페이스와 클래스
이 메소드는 서블릿이 인스턴스가 된 후 바로 호출되고, 단 한번만 호출.
init() 메소드는 request 를 다룰 때 사용하는 자원을 만들고 이 자원을 초기화할때 사용.
init() 메소드는 또한 ServletException 을 던질 수 있도록 선언되어 있음.
만약 서블릿이 request 를 핸들링할 수 있는 자원을 초기화할 수 없게 되었을 때 init() 메소드는 ServletException 을 해당 에러 메시지와 함께 전달.
ServletRequest 는 클라이언트가 제공한 정보.
ServletResponse 는 클라이언트에 보내는 정보.
service() 메소드를 가장 일반적인 구현은 HttpServlet 클래스에서.
HttpServlet 클래스는 GenericSevlet 를 상속하므로서 Servlet을 구현.
웹 애플리케이션이 shutdown 될때, 서블릿의 destory() 메소드가 호출.
그러면 init() 메소드에 의해 만들어진 모든 자원이 반납.
HttpServlet 클래스는 GenericServlet 클래스를 상속.
HttpServlet 과 GenericServlet는 서블릿을 개발할 때 이들 중 하나를 사용.
GenericServlet 클래스를 상속하면 service()메소드를 구현해야 함.
GenericServlet.service() 메소드는 상속하는 클래스가 구현해야 함.
service()메소드로 전달되는 2개의 파라미터는 ServletRequest 와 ServletResponse 객체.
ServletRequest 는 서블릿으로 전달되어진 모든 정보.
ServletResponse 는 클라이언트에게 보내고자 하는 데이터.
HttpServlet 클래스를 상속했을때는, service()메소드를 일반적으로 구현할 필요가 없음.
HTTPServlet 클래스는 이미 service()메소드를 구현하고 있기 때문.
구현한 메소드는 public void service() 메소드이고 이 메소드는 protected void service() 메소드.
그런데 실질적인 서비스는 protected void service() 메소드.
왜냐하면 HttpServlet 의 public service는 단지 protected service 메소드에게 제어권을 넘기는 역할.
(※Serlvets API 문서를 참고하세요)
이 doGet(), doPost() 가 우리가 오버라이딩 해야 하는 메소드.
메소드 타입이 GET 이면 우리가 오버라이딩 할 메소드는 doGet(), POST 이면 doPost() .
HttpServlet 클래스에 전달되는 파라미터, HttpServletRequest 와 HttpServletResponse 는 GenericServlet 클래스에 전달되는 파라미터였던 ServletRequest, ServletResponse 각각을 상속한 인터페이스.
그럼 HttpServletRequest 와 HttpServletResponse 를 구현한 클래스는 어디에?
'My work space > JSP/Servlet' 카테고리의 다른 글
JSP코드작성표준양식-한글판 (0) | 2008.09.08 |
---|---|
Servlet API 사이트 (0) | 2008.09.08 |
[CONTAINER] 톰캣5 관리자 아이디 설정 등 사용자,권한 설정 (0) | 2008.09.08 |
jsp 운영환경 구축 - 톰캣 어드민 (0) | 2008.09.08 |
jdk와 tomcat 버전 (0) | 2008.09.08 |
[CONTAINER] 톰캣5 관리자 아이디 설정 등 사용자,권한 설정

[CONTAINER] 톰캣5 관리자 아이디 설정 등 사용자,권한 설정 | |||||||
theY
|
|||||||
|
'My work space > JSP/Servlet' 카테고리의 다른 글
Servlet API 사이트 (0) | 2008.09.08 |
---|---|
Servlet 구조 (0) | 2008.09.08 |
jsp 운영환경 구축 - 톰캣 어드민 (0) | 2008.09.08 |
jdk와 tomcat 버전 (0) | 2008.09.08 |
이클립스 설치 및 톰캣과 오라클 연동 정리 (0) | 2008.09.08 |
7. jsp 운영환경 구축 - 톰캣 어드민
![]()
|
JSP #1 JSP 운영 환경 구축- 톰캣 어드민으로 디렉토리 설정하기
안녕하세요? 이지성입니다.
근사모에서 제공되는 apmsetup(php)를 설치하면 환경설정이 있습니다.
jsp의 톰캣에도 admin으로 접속하여 환경설정을 할 수 있습니다.
앞으로 jsp 공부를 할 때 필요한 jsp 파일을 저장할 디렉토리를 톰캣 어드민의 환경설정에서 할것이며
jsp 파일을 저장할 디렉토리를 만들고, 컨텍스트를 등록하는 과정을 공부합니다.
1. 톰캣 어드민에 대해서..
톰캣 어드민은 apmsetup과 비교하자면 apmsetup의 환결설정과 비슷하다고 생각하면 됩니다.
또한 톰캣 4.1부터 추가된 기능이 톰캣 어드민입니다. (Tomcat Admin)
톰캣 어드민은 웹 브라우저에서 쉽게 톰캣을 설정 할 수 있습니다.
톰캣 어드민이 나오기 전에는 개발자가 직접 server.xml 파일(각종..환경설정)을 수정하였습니다.
톰캣 어드민 도구를 사용하면 쉽게 관리 할 수 있습니다.
앞으로 jsp 실습할 예제를 위해 컨텍스트(Context)를 등록하는 과정을 다루겠습니다.
2. 톰캣 어드민 접속하기
톰캣 어드민을 접속하기 위해서는 첫 번째로, 아파치 톰캣(자카르타)이 실행되고 있는 상태이어야 합니다.
근사모에서 제공되는 Tomcat for Windows가 run(실행) 상태이면 됩니다.
웹 브라우저를 실행 시키고 http://localhost:8080/admin을 주소창에 입력하여 실행합니다.
admin의 아이디와 비밀번호를 입력하여 [로그인]을 합니다.
톰캣의 포트와 관리자의 아이디, 비밀번호를 설정하는 것은 Tomcat for Windows 설치과정 강의를 참고하세요.
3. 디렉토리 만들기
앞으로 우리가 실습할 jsp 파일을 위치할 디렉토리를 만듭니다.
모든 예제와 실습파일은 /jsp_study이라는 디렉토리와 URL로 접속할 것이며 관리하기 쉽게 jsp_study 폴더를 만듭니다.
일단 C:\TforWindows 폴더안에 jsp_study 이라는 폴더를 만듭니다. 아래의 그림을 참고하세요.
4. 톰캣 어드민에 로그인 되면..
톰캣 어드민에 로그인 되면 아래의 화면과 같이 관리 화면이 나옵니다.
관리화면은 왼쪽 프레임에 메뉴를 트리 형태로 구성하며, 오른쪽 프레임에는 관리 내용이 나옵니다.
각 화면에서 오른쪽 상단을 보면 작업 가능한 메뉴가 있는 것을 볼 수 있습니다.
(앞으로 강의를 만들때 포토샵으로 이미지를 편집하겠습니다.)
5. 컨텍스트 등록-1
어드민 화면의 왼쪽 트리중에서 'Service (Catalina)' 메뉴를 확장한 다음 'Host(localhost)'를 선택합니다.
그리고 오른쪽의 상단 팝업 메뉴()에서 'Create New Context'를 선택합니다.
아래의 화면과 같이 해주시면 됩니다.
5. 컨텍스트 등록-2
이번에는 새로운 컨텍스트를 입력하는 것을 해보겠습니다. 아래의 화면은 컨텍스트를 입력할 수 있는 화면입니다
여러 항목의 섹션으로 나누어져 있습니다. 현재는 'Context Properties'만 설정하면 됩니다.
아래의 화면과 100% 똑같이 입력해 주세요.
각 항목에 대한 설명은 다음 표와 같습니다.
[표] Context 속성-참고문헌 한빛미디어의 자바 웹 프로그래밍 저자 황희정(P.60)
속성 |
기본값 |
설명 |
---|---|---|
Cookies | True | 쿠키를 사용할지 지정한다. True로 한다. |
Cross Context | False |
ServletContext.getContext()에 대해 request dispatcher를 넘겨준다. 이 경우 다른 application에서 현재 application에 접근 할 수 있으으로 보안 문제 등 여러 문제가 발생할 수 있다. 보통 False로 설정한다. |
Document Base |
C:\TforWindows\jsp_study |
소스(파일)가 위치할 디렉토리를 지정한다. |
Path | /jsp_study |
Web Application에 접속할 URL 상태 이름이다. |
Reloadable | True |
WEB-INF/classes, WEB-INF/lib 클래스나 jar 파일이 변경되면 자동으로 변경된 내용을 읽어들인다. 새로운 Web Application을 개발하는 과정에서는 True로 해서 작업 편의성을 가질 수 있지만 실제로 서비스를 운영할 때에는 성능문제로 인해 False로 둔다. |
swallowOutPut | False |
True로 설정하면 Web Application에서 발생하는 System.out이나 System.err 출력이 곧바로 로그 파일로 전달된다. |
useNaming | True | JNDI를 지원할 것인지 설정한다. |
6. 컨텍스트 등록-3
컨텍스트 등록-2에서 설정을 다했다면 버튼과 버튼을 꼭 눌러주시고
설정을 저장한 다음, 톰캣을 종료(Tomcat for Windows)하고 다시 실행합니다.
(만약 Path에서 Error가 나오면 /(슬러시)와 \(역슬러시)를 구분해주세요.)
Save에 성공하면 아래와 같은 화면이 나옵니다.
그런다음 웹 브라우저를 실행하여 http://localhost:8080/jsp_study에 접속해 봅니다.
만약 http://localhost:8080/jsp_study을 해도 되지 않는 경우 톰캣을 종료 한 후 컴퓨터를 재부팅을 하여 시도합니다.
만일 404 오류가 발생하면 컨텍스트를 지우고 다시 만들어야 합니다. jsp_study 폴더에 아무런 파일이나 폴더를 넣고
다시 http://localhost:8080/jsp_study에 접속을 하면 만들었던 파일이나 폴더가 나타날 것입니다.
아래의 화면은 제가 tomcat_admin_config라는 폴더를 만들어 http://localhost:8080/jsp_study에 접속한 화면입니다.
아래와 같이 화면이 나온다면 정상적으로 설정되었으며 웹 어플리 케이션에 접속된 것입니다.
7. server.xml
예전에는 server.xml 파일에 환경설정을 하였다고 합니다. (%CATALINA_HOME%\conf\server.xml파일에 저장하였다고..)
지금은 http://localhost:8080/admin을 적극적으로 사용하시고 server.xml 파일을 자세히 알아보려면 톰캣 문서를 참고!
8. 웹 어플리케이션과 컨텍스트-참고문헌 한빛미디어의 자바 웹 프로그래밍 저자 황희정(P.62)
컨텍스트는 웹 어플리 케이션을 어플리케이션 서버가 관리하는 이름이라고 할 수 있다.
일반적으로 웹 어플리 케이션 하나가 등록된다.
일부 서적에서 앨리어스(별칭, 가상 디렉토리)라는 용어를 사용하는데, 이는 엄격하게 컨텍스트와는다른 개념.
경우에 따라 웹 어플리케이션 하나에 앨리어스 여러개를 가질 수 있기 때문이다.
톰캣에서는 여러분이 직접 관리 도구를 이용해서 컨텍스트(웹 어플리케이션과 같은 의미로 생각하면 된다)를
등록할 수 있다. 만일 '%CATALINA_HOME%\webapps' 폴더에 WAR 파일이나 웹 어플리케이션 형태의
디렉토리를 만든다면 톰캣이 자동으로 컨텍스트를 등록하게 된다.
9. 톰캣의 환경변수
앞으로 종종 %CATALINA_HOME이 언급되는데 이는 톰캣이 설치된 디렉토리를 의미하며 환경설치 형태로 관리된다.
(Tomcat for Windows에서는 C:\TforWindows\Tomcat5\ 폴더가 됩니다.)
톰캣을 시동하면 설치된 디렉토리를 자동으로 %CATALINA_HOME으로 인식됩니다.
톰캣3엣는 %CATALINA_HOME이라는 환경변수를 이름을 사용했고, 카탈리나는 톰캣의 핵심 엔진이름이고, 톰캣3의
전혀 다른 내부 구조며, 혁신적인 서버의 성능을 향상시킨 엔진이랍니다.
10. 포트(Port)
일반적으로 아파치는 80포트를 사용합니다. 물론 톰캣도 아파치 톰캣이고 자카르타라고도 부릅니다.
실제로 localhost는 나의 컴퓨터 ip인 127.0.0.1을 말하며 실제 컴퓨터의 IP를 입력해도 됩니다.
자기 자신의 IP를 보는 방법은 시작→실행→cmd입력→ipconfig (NT/2000/XP/2003 기준)을 입력하면 됩니다.
톰캣에서는 8080이 포트 번호인데 기본 포트는 변경이 가능합니다. http://www.e-station.com 에서도 톰캣을
사용하며 포트를 8001, 8002를 사용하더군요~~ 또한 웹 브라우저의 주소창에 localhost:8080을 해도 안될경우,
http://localhost:8080 Or, http://127.0.0.1:8080 Or http://나의IP:8080을 입력하면 됩니다.
부탁의 말씀 :
학교에서 배운 교재를 복습하여 잊지 않기 위해 강의를 담아보았습니다.
저작권이 어쩌고 저쩌고 말을 안했으면 합니다. 배우는 입장에서 정보를 공유하여 습득했으면 합니다.
책은 "한빛미디어의 자바 웹 프로그래밍 저자 황희정"을 추천합니다.
출처
'My work space > JSP/Servlet' 카테고리의 다른 글
Servlet 구조 (0) | 2008.09.08 |
---|---|
[CONTAINER] 톰캣5 관리자 아이디 설정 등 사용자,권한 설정 (0) | 2008.09.08 |
jdk와 tomcat 버전 (0) | 2008.09.08 |
이클립스 설치 및 톰캣과 오라클 연동 정리 (0) | 2008.09.08 |
주민등록번호, 그 속에 숨은 비밀을 아시나요? (0) | 2008.09.08 |
1. tomcat55는 jdk1.5버전을 필요로 합니다.
꼭 1.4로 쓰셔야 한다면, 아파치 싸이트에서 jdk1.4호환모듈을 받아야 합니다.
2. 5.5 버전과 4.1 버전의 차이중 하나가 서블릿 스팩차이인데요,
Servlet/JSP Spec | Apache Tomcat version |
2.5/2.1 | 6.0.13 |
2.4/2.0 | 5.5.23 |
2.3/1.2 | 4.1.36 |
2.2/1.1 | 3.3.2 |
컨텍스트의 web.xml에 특별한 내용이 없다면, 괜찬겠지만,
스펙을 타는 내용들이 있다면, 체크하셔야 합니다.
3. 만약 자바를 1.5로 업하신다면, 코드중에
Enumeration enum;
으로 선언한 부분이 있다면, enum을 다른 이름으로 바꾸어야 합니다. 1.5버전부터는
enum이 예약어로 바뀐듯합니다.
그리고 업무때문이라면 어쩔수 없지만 공부때문이라면 tomcat5.0은 비추입니다.
차라리 tomcat5.5.x를 상요하세요 정 안되면 4.1.를 사용하시길
자바버젼벌 톰켓지원상황
jdk1.4.x = Tomcat 4.1.x = servlet2.3 = jsp1.0
jdk5 = Tomcat5.5.x = servlet2.4 = jsp2.0
근대 Tomcat5.0은 저 두가지 스펙의 중간에 걸칩니다. 애매합니다. 비츄~
'My work space > JSP/Servlet' 카테고리의 다른 글
Servlet 구조 (0) | 2008.09.08 |
---|---|
[CONTAINER] 톰캣5 관리자 아이디 설정 등 사용자,권한 설정 (0) | 2008.09.08 |
jsp 운영환경 구축 - 톰캣 어드민 (0) | 2008.09.08 |
이클립스 설치 및 톰캣과 오라클 연동 정리 (0) | 2008.09.08 |
주민등록번호, 그 속에 숨은 비밀을 아시나요? (0) | 2008.09.08 |
|
'My work space > JSP/Servlet' 카테고리의 다른 글
Servlet 구조 (0) | 2008.09.08 |
---|---|
[CONTAINER] 톰캣5 관리자 아이디 설정 등 사용자,권한 설정 (0) | 2008.09.08 |
jsp 운영환경 구축 - 톰캣 어드민 (0) | 2008.09.08 |
jdk와 tomcat 버전 (0) | 2008.09.08 |
주민등록번호, 그 속에 숨은 비밀을 아시나요? (0) | 2008.09.08 |
JavaBean 경로: registerBean2/WEB-INF/src/reg
Jsp파일 경로: registerBean2/join
파일 설명: 우선 memberList.jsp는 게시판 형태로 로그인한 사람들의 정보를 보여준다.
로그인과 회원가입 버튼으로 각 기능을 수행할수 있다.
로그인시 게시판 상단에 로그인한 아이디와 로그아웃 버튼이 보인다.
* 위) 로그인하기 전 , 아래) 로그인후 memberList.jsp파일

memberList.jsp --> 리스트 보여주기
loginin.jsp --> 로그인
loginout.jsp --> 로그아웃
loginin_ok.jsp --> 로그인 ok
login_err.jsp --> 로그인이 안될 경우 표시
Register.jsp , Register_ok.jsp --> 회원가입정보 입력
Zipcheck.jsp , ZipcodeBean --> 회원가입정보에서 우편번호 검색및 입력 파일
idCheck.jsp --> ID 중복검사
script.js --> 자바스크립트 모음
RegisterBean.java --> 회원가입 정보 임시 저장 파일
Methodinsert.jsp --> 값을 빈에 넣어주는 지시 파일
MemberMgr.java --> 모든 처리가 담긴 빈 파일
* 본 파일을 모두 올릴 경우 스크롤이 상당히 길어지므로 중요한 memberList.jsp (게시판파일)
값을 저장하는 RegisterBean.java , MemberMgr.java 파일만 소스를 보여주며,
전체파일은 압축하여 올린다.
* 본 작업은 이클립스와 오라클을 기준으로 하며, workspace자체를 올렸으므로 사용할 경우 파일들을
프로젝트 폴더에 수동으로 옮겨 작업 하기를 권한다.
1) 데이터베이스 구성
create table mem(
id varchar(12) not null primary key,
passwd varchar(12) not null,
name varchar(10) not null,
jumin_num1 varchar(6) not null,
jumin_num2 varchar(7) not null,
email varchar(30),
phone varchar(13) not null
);
2) memberList.jsp
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR" import="reg.*,java.util.*"%>
//id 세션값이 있으면
<% String mem_id = (String)session.getAttribute("idKey"); %>
<% if(mem_id!= null){ %>
지금 <font color=red><b><%=mem_id %></b></font>로 로그인하셨습니다.
<%}else{} %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>로그인 목록</title>
</head>
<body>
<table border=1>
<tr>
<td>Id</td>
<td>name</td>
<td>mem_num1</td>
<td>mem_num2</td>
<td>e_mail</td>
<td>phone</td>
<td>zipcode</td>
<td>address</td>
<td>job</td>
</tr>
<jsp:useBean id="memMgr" class="reg.MemberMgr" />
<%
Vector vlist = memMgr.getMemberList(); //getMemberList()메소드는 벡터로 반환
int counter = vlist.size(); //벡터의 사이즈 크기는 레코드의 개수를 얘기한다.
for(int i=0;i<vlist.size();i++)
{
// elementAt()메소드는 값 반환을 Object형으로 반환
RegisterBean regBean = (RegisterBean)vlist.elementAt(i);
// elementAt() 메소드는 벡터에 있는 요소에 접근하기 위한 메소드이다.
%>
<tr>
<td><%=regBean.getMem_id() %></td>
<td><%=regBean.getMem_name() %></td>
<td><%=regBean.getMem_num1() %></td>
<td><%=regBean.getMem_num2() %></td>
<td><%=regBean.getMem_email() %></td>
<td><%=regBean.getMem_phone() %></td>
<td><%=regBean.getMem_zipcode() %></td>
<td><%=regBean.getMem_address() %></td>
<td><%=regBean.getMem_job() %></td>
</tr>
<%
}
%>
<tr>
<td colspan=9 align=right>
<input type=button value=로그인 onclick="javascript:location.href('loginin.jsp')">
<%if(mem_id!=null){ %>
<input type=button value=로그아웃 onclick="javascript:location.href('logout.jsp')">
<%}else{}%>
<input type=button value=회원가입 onclick="javascript:location.href('Register.jsp')"></td>
</tr>
</body>
</html>
3) RegisterBean.java
package reg;
public class RegisterBean {
private String mem_id;
private String mem_passwd;
private String mem_name;
private String mem_num1;
private String mem_num2;
private String mem_email;
private String mem_phone;
private String mem_zipcode;
private String mem_address;
private String mem_job;
//get메소드와 set메소드 설정을 외워두세요...
public String getMem_id(){
return mem_id;
}
public void setMem_id(String mem_id){
this.mem_id = mem_id;
}
public String getMem_passwd(){
return mem_passwd;
}
public void setMem_passwd(String mem_passwd){
this.mem_passwd = mem_passwd;
}
public String getMem_name(){
return mem_name;
}
public void setMem_name(String mem_name){
this.mem_name = mem_name;
}
public String getMem_num1(){
return mem_num1;
}
public void setMem_num1(String mem_num1){
this.mem_num1 = mem_num1;
}
public String getMem_num2(){
return mem_num2;
}
public void setMem_num2(String mem_num2){
this.mem_num2 = mem_num2;
}
public String getMem_email(){
return mem_email;
}
public void setMem_email(String mem_email){
this.mem_email = mem_email;
}
public String getMem_phone(){
return mem_phone;
}
public void setMem_phone(String mem_phone){
this.mem_phone = mem_phone;
}
public String getMem_zipcode(){
return mem_zipcode;
}
public void setMem_zipcode(String mem_zipcode){
this.mem_zipcode = mem_zipcode;
}
public String getMem_address(){
return mem_address;
}
public void setMem_address(String mem_address){
this.mem_address = mem_address;
}
public String getMem_job() {
return mem_job;
}
public void setMem_job(String mem_job) {
this.mem_job = mem_job;
}
}
4) MemberMgr.java --> 중요~~~
달달달 외워두시면 쓸모 많을겁니다.
각 메소드가 기능에 따라 어떤 메소드를 받고 어떤 쿼리문을 쓰는지 파악하면 반이상은 이해한것입니다.
package reg;
import java.util.*; //vector클래스는 java.util패키지에 속해있다.
import reg.RegisterBean;
import java.sql.*;
public class MemberMgr {
private final String JDBC_DRIVER = "oracle.jdbc.driver.OracleDriver";
private final String JDBC_URL = "jdbc:oracle:thin:@localhost:1521:orcl";
private final String USER = "system";
private final String PASS = "oracle";
public MemberMgr(){ //드라이버 셋팅
try{
Class.forName(JDBC_DRIVER);
}catch(Exception e){
System.out.println("Error:JDBC드라이버 로딩 실패");
}
}//MemberMgr종료
/* id중복체크 메소드 */
public boolean checkId(String id){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
boolean Check = false;
try{
conn=DriverManager.getConnection(JDBC_URL,USER,PASS);
String sql="select id from mem where id=?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1,id);
rs = pstmt.executeQuery();
Check = rs.next();
}catch(Exception ex){
System.out.println("Exception" + ex);
}finally{
if(rs != null)try{rs.close();}catch(SQLException sqle){}
if(pstmt != null)try{pstmt.close();}catch(SQLException sqle){}
if(conn != null)try{conn.close();}catch(SQLException sqle){}
}//finally 끝
return Check;
}//checkID메소드 끝
/* login하는 메소드 */
public boolean loginok(String id,String pw){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
boolean Check = false;
//int Check = 0;
try{
conn=DriverManager.getConnection(JDBC_URL,USER,PASS);
String sql = "select id,passwd from mem where id=? and passwd=?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1,id);
pstmt.setString(2,pw);
rs = pstmt.executeQuery();
Check = rs.next();
/*if(rs.next()){
if(id==""){
Check=1;
}else if(pw==""){
Check=2;
}else if(id=="" && pw==""){
Check=3;
}else{
Check=4;
}
}*/
}catch(Exception ex){
System.out.println("Exception" + ex);
}finally{
if(rs != null)try{rs.close();}catch(SQLException sqle){}
if(pstmt!=null)try{pstmt.close();}catch(SQLException sqle){}
if(conn != null)try{conn.close();}catch(SQLException sqle){}
}
return Check;
}
/* 우편번호 검색 메소드 */
public Vector zipcodeRead(String dong){
Connection conn = null;
PreparedStatement pstmt = null;
//Statement stmt = null;
ResultSet rs = null;
Vector ziplist = new Vector();
try{
conn = DriverManager.getConnection(JDBC_URL,USER,PASS);
//String sql = "select * from ZIPCODE where DONG like '%" + dong +"%'";
String sql = "select * from zipcode where dong like '%' || ? || '%'";
//stmt = conn.createStatement();
//rs = stmt.executeQuery(sql);
pstmt = conn.prepareStatement(sql);
pstmt.setString(1,dong);
rs = pstmt.executeQuery();
while(rs.next()){
ZipcodeBean zipBean = new ZipcodeBean();
zipBean.setZipcode(rs.getString("zipcode"));
zipBean.setSido(rs.getString("sido"));
zipBean.setGugun(rs.getString("gugun"));
zipBean.setDong(rs.getString("dong"));
zipBean.setBunji(rs.getString("bunji"));
ziplist.addElement(zipBean); // 받아온 값을 벡터에 넣는다.
}
}catch(Exception ex){
System.out.println("Exception"+ex);
}finally{
if(rs != null)try{rs.close();}catch(SQLException e){}
if(pstmt != null)try{pstmt.close();}catch(SQLException e){}
//if(stmt != null)try{stmt.close();}catch(SQLException e){}
if(conn != null)try{conn.close();}catch(SQLException e){}
}
return ziplist; // 반환값을 받기 위해서.
}
/*일시적으로 RegisterBean값을 memberInsert를 통해 db에 insert한다. */
public boolean memberInsert(RegisterBean regBean){
Connection conn = null;
PreparedStatement pstmt = null;
boolean flag = false;
try{
conn=DriverManager.getConnection(JDBC_URL,USER,PASS);
String sql = "insert into mem values (?,?,?,?,?,?,?,?,?,?)";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1,regBean.getMem_id());
pstmt.setString(2,regBean.getMem_passwd());
pstmt.setString(3,regBean.getMem_name());
pstmt.setString(4,regBean.getMem_num1());
pstmt.setString(5,regBean.getMem_num2());
pstmt.setString(6,regBean.getMem_email());
pstmt.setString(7,regBean.getMem_phone());
pstmt.setString(8,regBean.getMem_zipcode());
pstmt.setString(9,regBean.getMem_address());
pstmt.setString(10,regBean.getMem_job());
int counte = pstmt.executeUpdate();
if (counte > 0){
flag =true;
}
}catch(Exception ex){
System.out.println("Exception" + ex);
}finally{
if(pstmt!= null)try{pstmt.close();}catch(SQLException ex){}
if(conn != null)try{conn.close();}catch(SQLException ex){}
}
return flag;
}
/* Vector로 리스트 보이는 메소드 */
public Vector getMemberList(){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
Vector vecList = new Vector();
try{
conn=DriverManager.getConnection(JDBC_URL,USER,PASS);
String sql = "select * from mem";
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
while(rs.next())
{
//while문을 통해 가지고 오는 값을 생성된 빈에 셋팅
RegisterBean regBean = new RegisterBean();
regBean.setMem_id(rs.getString("id"));
regBean.setMem_passwd(rs.getString("passwd"));
regBean.setMem_name(rs.getString("name"));
regBean.setMem_num1(rs.getString("jumin_num1"));
regBean.setMem_num2(rs.getString("jumin_num2"));
regBean.setMem_email(rs.getString("email"));
regBean.setMem_phone(rs.getString("phone"));
regBean.setMem_zipcode(rs.getString("zipcode"));
regBean.setMem_address(rs.getString("address"));
regBean.setMem_job(rs.getString("job"));
vecList.add(regBean);
}
}catch(Exception ex){
System.out.println("Exception"+ex);
}finally{
if(rs != null)try{rs.close();}catch(SQLException e){}
if(pstmt != null)try{pstmt.close();}catch(SQLException e){}
if(conn != null)try{conn.close();}catch(SQLException e){}
}
return vecList;
}
}