'2009/12'에 해당되는 글 19

  1. 2009/12/28 18. MVC 패턴 구현
  2. 2009/12/27 17. 웹 어플리케이션 이벤트 처리
  3. 2009/12/27 16. 필터(Filter)
  4. 2009/12/27 15. 커스텀 태그 만들기
  5. 2009/12/26 14. 표준 태그 라이브러리(JSTL)
  6. 2009/12/26 13. 표현언어(Expression Language)
  7. 2009/12/26 12. 데이터베이스 프로그래밍 기초
  8. 2009/12/21 11. <jsp:useBean> 액션 태그를 이용한 객체 사용
  9. 2009/12/21 10. 클라이언트오의 대화 2: 세션
  10. 2009/12/20 09. 클라이언트와의 대화1 : 쿠키

18. MVC 패턴 구현

01. 모델 2구조와 MVC 패턴
JSP 기반 웹 어플리케이션의 구조에는 크게 모델1구조와 모델2구조가 있다. JSP 에서 모든 로직과 출력을 처리하느냐 아니면 JSP에서 출력만 처리하느냐에 따라서 모델 1구조와 모델2구조로 구분된다.

1.1 모델1구조
모델1구조는 JSP를 이용한 단순한 모델이다. 지금까지 살펴본 거의 대부분의 JSP 페이지가 모델1구조를 사용하고 있다. 보통 처음 JSP를 배울때 사용하는 구조가 모델1구조인데 웹브라우저의 요청이 곧바로 JSP에 전달된다. 웹 브라우저의 요청을 받은 JSP는 자바빈이나 서비스 클래스를 사용해서 웹 브라우저가 요청한 작업을 처리하고 그 결과를 클리이언트에 출력해 준다.
JSP 페이지에서 웹 브라우저가 요청한 것들을 처리한다는것은 JSP 페이지에 비즈니스로직을 처리하기 위한 코드와 웹 브라우저에 결과를 보여줄출력 관련 코드가 섞인다는 것을 의미한다. 원하는 작업을 수행하고 그 결과를 출력하는 경우가 많은데 이것이 모델 1구조의 전형적인 예이다.

1.2 모델2구조
모델 2구조는 모델1구조와 달리 웹 브라우저의 요청을 하나의 서블릿이 받게 된다. 서블릿은 웹 브라우저의 요청을 알맞게 처리한후 그 결과를 보여줄 JSP 페이지로 포워딩한다. 포워딩을 통해서 요청 흐름을 받은 JSP 페이지는 결과화면을 클라이언트에 전송한다. 즉 서블릿이 비즈니스 로직 부분을 처리하게 되는 것이다.
모델2구조의 특징은 웹 브라우저의 모든 요청이 단일 진입점, 즉 하나의 서블릿에서 처리된다는 점이다. 하나의 서블릿이 우베 브라우저의 모든 요청을 받기 때문에 서블릿은 웹 브라우저의 요청을 구분할수 있는 방법을 필요로 하며, 서블릿은 웹 브라우저의 요청을 처리한 후 웹 브러우저에 보여줄 JSP를 선택하게 된다. 모델2구조의 이런한 특징 때문에 MVC패턴에 기반을 두어 웹 어플리케이션을 구현할때는 모델 2구조를 주로 사용한다.
 
1.3 MVC 패턴
스몰토크라는 프로그래밍 언어에서 사용되는 패턴이었는데 스윙과 같은 UI 컴포넌트로 그활용범위가 확정되었으며 JSP에서 모델2구조가 나오면서 웹 어플리케이션 개발 영역에서도 보편적으로 사용하기 시작했다.

MVC 패턴은 크게 모델, 뷰, 컨트롤러의 세부분으로 구성되면 역할은 다음과 같다.

모델 : 비즈니스 영역의 상태 정보를 처리한다.
뷰 : 비즈니스 영역에 대한 프리젠테이션 뷰를 담당한다.
컨트롤러 : 사용자의 입력 및 흐름제어를 담당한다.

사용자는 원하는 기능을 처리하기 위한 모든 요청을 단일 컨트롤러에 보낸다. 모델은 비느지스와 관련된 상태 정보 및 관련 기능을 제공하는데 컨트롤러는 이 모델을 통해서 사용자의 요청을 처리한다. 모델을 사용하여 알맞은 비즈니스 로직을 수행한후 컨트롤러는 사용자에게 보여줄 뷰를 서낵하며 선택된 뷰는 사용자에게 알맞은 결과 화면을 보여준다. 뷰가 사용자에게 결과화면을 보여줄때에는 결과 정보가 필요한데 컨트롤러가 이 정보를 뷰에 전달해 준다.

MVC 핵심 패턴
ㅇ 비즈니스로직을 처리하는 모델과 결과 화면을 보여주는 뷰가 분리되어 있다.
ㅇ 어플리케이션의 흐름제어나 사용자의 처리 요청은 컨트롤러에 집중된다.

즉 모델은 오직 비즈니스와 관련된 부분을 처리하면 될 뿐 사용자에게 보여줄 화면이나 흐름제어에 대한 처리할 필요가 없다. 반대로 뷰는 사용자에게 알맞은 화면을 보여주는 역할만 수행하면 될 뿐, 비즈니스 로직이나 흐름제어등을 신켱쓸 필요가 없다. 이렇게 모델과 뷰가 분리되어 있기 때문에 모델의 내부 로직이 변경된다 하더라도 뷰는 영향을 받지 않으며, 뷰와 모델이 결합되어 있지 않기 때문에 뷰를 얼벼지 않게 변경할수 있다.

또한 컨트롤러는 사용자의 요청에 대해서 알맞은 모델을 사용하고 사용자에게 보여줄 뷰를 선택하기만 하면 된다. 비즈니스 로직에는 포함되지 않지만 전체 웹 어플리케이션에 일괄적으로 적용되는 기능을 컨트롤러에 집중적으로 처리하게 된다.

웹 어플리케이션의 흐름 제어나 보안 설정의 변경등과 같은 유지 보수 작업이 필요할 경우 컨트롤러만 변경하면 되고, 새로운 타입의 사용자가 새롭게 추가될때에는 컨트롤러나 모델에 상광없이 새로운 뷰를 추가해 주면된다. 즉 MVC 패턴을 사용함으로써 유지 보수 작업이 간단해지고 어플리케이션을 쉽게 확장할수 있게 되는 것이다.

1.4 MVC 패턴과 모델 2구조의 매핑
ㅇ 컨트롤러 = 서블릿
모델 = 비즈니스 로직 처리 클래스, 자바빈
뷰 = JSP
사용자 = 웹 브라우저 내지 휴대폰과 같은 다양한 기기

1.5 MVC의 컨트롤러 : 서블릿
모델2구조에서 서블릿은 MVC 패턴의 컨트롤러 역할을 한다. 서블릿은 웹 브라우저의 요청과 웹 어플리케이션의 전체적인 흐름을 제어하게 된다.
과정1 : 웹 브라우저가 전송한 HTTP 요청을 받는다. 서블릿의doGet() 메서드나 do POST() 메서드가 호출된다.
과정2: 웹 브라우저가 어떤 기능을 요청했는지 분석한다. 예를 들어 게시판 목록을 쵸청했는지, 글 쓰기를 요청했는지 알아낸다.
과정3: 모델을 사용하여 요청한 기능을 수행한다.
과정4: 모델로 부터 전달받은 결과물을 알맞게 가공한후 request 나 session의 setAttribute()메서드를 사용하여 결과값을 속성에 저장한다. 이렇게 저장된 결과값은 뷰인 JSP에서 사용된다.
과정5: 웹브라우저에 보여줄 JSP를 선택한후 해당 JSP로 포워딩 한다. 경우에 따라서 리다이렉트를 하기도 한다.

서블릿은 모델이 내부적으로 어떻게 비즈니스로직을 처리하는지 알 필요 없이, 웹브라우저의 요청에 알맞게 모델을 사용하여 요청한기능을 수행하고 그 결과를 뷰인 JSP에 전달해 주기만 하면 된다. 웹 브라우저의 결과를 보여줄 JSP 페이지는 컨트롤러 서블릿이 선택하게 되며 요청 처리 결과를 request 나 session에 저장해서 뷰 역할을 하게 되는 JSP 페이지에 전달한다.


1.6 MVC의 뷰 : JSP
모델2구조에서 JSP는 뷰의 역할을 담당한다. 비즈니스 로직과 관련된 코드가 없는 점을 제외하면 일반 JSP와 거의 동일한 형태를 취한다. 뷰역할을 하는 JSP는 컨트롤러 부분에서 request 기본 객체나 session 기본 객체에 저장한 데이터를 사용하여 웹 브라우저에 알맞은 겨로가를 출력해 준다는 점이다. 뷰 JSP의 경우는 컨트롤러 서블릿 처럼 일반적인 처리 순서가 정해져 있지는 않다.

뷰 열할을 하는 JSP 는 웹 브라우저가 요청한 겨로가를 보여주는 프리젠 테이션 역할을 할 뿐만아니라 웹 브라우저의 요청을 컨트롤러에 전달해 주는 매개체가 되기도 한다.
예를들어 웹 브라우저가 게시판 글 목록 보기를 요청하여 그 결과가 뷰를 사용하여 출력되었다고 해보자. 글쓰기와 같은 링크가 존재 할것이며 글쓰기 링크는 컨트롤러에 연결되어 있을것이다.
저작자 표시

'BOOK Study > J2EE' 카테고리의 다른 글

01. 먼저 간략히 알아봅시다.  (0) 2010/01/01
두번째 이야기 . HeadFrist Servlet & JSP  (0) 2010/01/01
18. MVC 패턴 구현  (0) 2009/12/28
17. 웹 어플리케이션 이벤트 처리  (0) 2009/12/27
16. 필터(Filter)  (0) 2009/12/27
15. 커스텀 태그 만들기  (0) 2009/12/27
Trackback 0 Comment 0

17. 웹 어플리케이션 이벤트 처리

01. ServletContextListener를 이요한 이벤트 러치
웹 컨테이너는 우베 어플리케이션이 시작되거나 종료되는 시점에 특정 클래스의 메서드를 실행할수 있는 기능을 제공하고 있다. 이 기능을 사용하면 웹 어플리케이션을 실행하는데 필요한 초기화 작업이나 웹 어플리케이션이 종료된 후 사용된 자원을 반환하는등의 작업을 수행할수 있다.

웹 어플리케이션이 시작되고 종료될때 특정한 기능을 실행하려면 다음과 같이 코드를 작성하면 된다.

javax.servlet.ServletContextListener 인터페이스를 구현한 클래스를 작성한다.
web.xml 팡리에 1번에서 작성한 클래스를 등록한다.

ServletContextListener 인터페이스를 구현한 클래스가 웹 어플리케이션이 시작되거나 종료될때 실행하도록 하려면  web.xml 파일에 <listener> 태그와 <listener-class> 태그를 사용해서 오나전한 클래스 이름을 명시해 주면 된다.

<listener>
<listener-class> kame.jdbc.loader.DBCPInitListener</listener-class>
</listener>



저작자 표시

'BOOK Study > J2EE' 카테고리의 다른 글

두번째 이야기 . HeadFrist Servlet & JSP  (0) 2010/01/01
18. MVC 패턴 구현  (0) 2009/12/28
17. 웹 어플리케이션 이벤트 처리  (0) 2009/12/27
16. 필터(Filter)  (0) 2009/12/27
15. 커스텀 태그 만들기  (0) 2009/12/27
14. 표준 태그 라이브러리(JSTL)  (0) 2009/12/26
Trackback 0 Comment 0

16. 필터(Filter)

01. 필터란 무엇인가 ?
HTTP 요청과 응듭을 변경할수 있는 재 사용가능한 코드 이다. 필터는 객체의 형태로 존재하며 클라이언트로 부터 오는 요청과 최정자원 사이에 위치하여 클라이언트의 요청 정보를 알맞게 변경할수 있으며, 또한 필터는 최종 자원과 클라이언트 가능 응답 사이에 위치하여 최종자원의 요청결과를 알맞게 변경할수 있다.

자원이 받게 되는 요청 정보는 클라이언트와 자원 사이에 존재하는 필어에 의해 변경된 요청 정보가 되며, 도한 클라이언트가 보게 되는 응답 정보는 클라이언트와 자원사이에 존재하는 필터에 의해 변경된 응답 정보가 된다.
클라이언트와 자원사이에 한개의 필터만 존재할수 있는 것은 아니며, 여러개의 필터가 모여 하나의 필터 체인을 형성하게 된다.

여러개의 필터가 모여서 하나의 체인을 형성할떄 첫번째 필터가 변경하는 요청 정보는 클라이언트의 요청 정보가 되지만, 체인의 두번째 필터가 변경하는 요청정보는 첫번째 필터를 통해 변경된 요청정보가 된다. 즉, 요청 정보는 변경에 변경을 거듭하게 되는 것이다.

02. 필터의 구현
2.1 필터 인터페이스

Fileter 인터페이스는 다음과 같은 메서드를 선언하고 있으며, 필터 기능을 제공할 클래스느 ㄴ필터 인터페이스를 알맞게 구현해 주어야 한다.
public void init(FilterConfig filterConfig) throwxception : 필터를 초기화 할때 호출 된다.
public void doFilter(ServletRequest request, ServletResponse response, Filter Chain chain) throws java.io.IOException, ServletException : 체인을 따라 다음에 존재하는 필터로 이동한다. 체인의 가장 마지막에는 클라이언트가 요청한 최종 자원이 위차한다.
public void destory() : 필터가 웹 컨테이너에서 삭제될 때 호출된다.

public class FilrstFilter implements Filter{
public void init(FiltercONfig filterConfig) throws ServletException{
//필터 초기화 작업
}

public void doFilter(ServletRequest request, ServletResponse response, FilterChain Chain) throws IOException, SevletExceptiion{
//1. request 파ㄹ미터를 이용하여 오청의 필터 작업 수행
//2. 체인의 다음 필터 처리
chain.doFilter(request, response)
//3. response를 이용하여 응답의 필터링 작업 수행
}
public void destory(){
//주로 필터가 사용한 자원을 반납
}
}

위 코드에서 filter 인터페이스의 doFilter()메소드는 요청이 있을때 마나 매번 실행된다. 예를들어, 클라이언트가 요청한 자원이 필터를 거치는 경우 클라이언트의 요청이 있을때마나 doFilter()메서드가 호출되며, doFilter() 메소드는 JSP/서블릿과 마찬가지로 요청에 대해서 알맞은 작업을 처리하게 된다.

1. request 파라미터를 이용하여 클라이언트의 요청 필터링 : 1단계에서는 RequestWWrapper클래스를 사용하여 클라이언트의 요청을 변경한다.
2. chain.doFilte() apthem ghcnf : 2단계에서는 요청의 필터링 결과를 다음 필터에 전달한다.
3. response 파라미터를 사용하여 클라이언트로 가능 응답필터링 : 3단계에서는 체인을 통해서 전달되 ㄴ응답데이터를 변경하여 그 결과를 클라이언트에 전송한다.

2.2 필터 설정하기
필터를 사용하기 위해서는 어떤 필터가 어떤 자원에 대해서 적도용된다는 것을 웹 컨테이너에 알려주어야 한다. 지금까지 웹 어플리케이션과 관련된 설정 정보를 web.xml 파일에 명시했듯이 필터에 관한 정보도 web.xml 파일을 통해서 설정하게 되어있다.

<filter>
<filter-name>FilterName</filter-name>
<filter-class>javacan.filter.FileClass</filter-class>
<init-param>
<param-name>paramName</param-name>
</init-param>
</filter>

<filter-mapping>
<filter-name>FilterName<filter-name>
<url-pattern>*.jsp</url-pattern>
<//filter-mapping>

<filter>태그는 웹 어플리케이션에서 사용될 필터를 지정하는 역할이며, <filter-mapping> 태그는 특정 자원에 대해 어떤 필터를 사용할지 지정한다.
<init-param>태그는 필터가 초기화될떄, 즉 필터의 init() 메소드가 호출될때 전달되는 파라미터값이다. 이는 서블릿의 초기화 파라미터와 비슷한 역할을 하며, 주로 필터를 사용하기전에 초기화 해야 하는 객체나 자원을 할당할때 필요한 정보를 제공하기 위해 사용된다.

<url-pattern> 태그는 클라리언트가 요청한 특정 URI에 대해서 필터링할때 사용된다.

필터 매핑정보
<filter-mapping>
<filter-name>AuthCheckFilter</filter-name>
<url-pattern>/pds/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>

<filter-mapping>
<filter-name>IPCheckFilter</filter-name>
<url-pattern>/pds/data/*</url-pattern>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>

ㅇ웹 브라우저 /pds/data/download.jsp를 요청헀다고 해보자. 이경우 두개의 필터 매핑 모두 <url-pattern>에 따라서 이 URL을 처리할수 있게 된다. 그런데 두번째 필터 매핑은<dispatcher>의 값이 INCLUDE 이기 떄문에 웹 브라우저의 요청에 대해서는 필터가 적용되지 않는다.
<jsp:include page="/pds/data/util.jsp" flush="false"/>

2.3 요청 및 응답 래퍼 클래스
필터가 필터로서의 젝 기능을 하기 위해서는 클라이언트의 요청을변경하고, 또한 클라이언트로 가는 응답을 변경할수 있어야 할 것이다. 이러한 변경을 할수 있도록 해주는 것이 바로 servletRequsetWrapper와 ServletResponseWrapper이다. 서블릿 요청/응답 래퍼클래스를 이용함으로써 클라이언트의 요청 정보를 변경하여 최종자원인 서블릿 /기타자원에 전달할수 있고 또한 최종 자원으로부터의 응답결과를 변경하여 새로운 응답 정보를 클라이언트에 보낼수 있게 된다.


03 필터의 응용
필터를 사용하는 방버에는 제한이 없으며, 얼마나 필터의 특징을 잘 활용하느냐에 따라서 필터의 응용범위가 달라질수 있다. 서블릿 규약에서는 다음과 같은 응용 분야를 제시하고 있다.

ㅇ 데이터변환
ㅇ xsl/t를 이용한 xml문서 변경
ㅇ 사용자 인증
ㅇ 캐싱 필터
ㅇ 자원 접근에 대한 로깅
저작자 표시

'BOOK Study > J2EE' 카테고리의 다른 글

18. MVC 패턴 구현  (0) 2009/12/28
17. 웹 어플리케이션 이벤트 처리  (0) 2009/12/27
16. 필터(Filter)  (0) 2009/12/27
15. 커스텀 태그 만들기  (0) 2009/12/27
14. 표준 태그 라이브러리(JSTL)  (0) 2009/12/26
13. 표현언어(Expression Language)  (0) 2009/12/26
Trackback 0 Comment 0

15. 커스텀 태그 만들기

때에 따라서 JSP 액션 태그나 JSTL 태그만으로는 뭔가 아쉬울 때가 있다. 예를 들어 로그인에 성공헀을때 세션의 member 속성에 Member 자바빈 객체를 저장한다고 해보자 이때 로그인 여부를 판단할때에는 다음과 같은 JSTL 태그를 사용할수 있다.
<c:if test="${! empty sessionScope.member}">
로그인한상태
</c:if>
<c:if test="${empty sessionScope.member}">
로그인 하지 않은 상태
</c:if>

하지만 다음과 같이 원하는 기능에 알맞은 태그를 사용할수 있다면 어떨가?
<ct:login>
로그인한 상태
</ct:login>

<ct:login value="false">
로그인하지 않은 상태
</ct:login>

위와 같은 특정한 상황에 알맞은 태그가 존재한다면 코드를 더욱 간결하게 작성할수 있을 것이다. 또한 더 중요한 것은 코드의 의미가 명확해 진다는 것이다.
JSP는 이처럼 JSTL이나 기본적인 JSP 액션 태그로 표현할수 없는 경우 스크립트 코드와 EL 코드를 혼합해서 사용하는 대신 또 다른 태그를 만들어서 사용할수 있도록 지원하고 있는데 이렇게 원하는 목적에 맞게 작성된 태그를 커스텀 태그라고 부른다. 그리고 커스텀 태그를 모아 놓은 것이 커스텀 태그 라이브러리라 한다.

1.1 커스텀 태그의 장점
ㅇ 재사용성 향상 : 한번 작성한 커스텀 태그는 어떤 JSP 컨테이너에서든지 사용이 가능하다.
ㅇ 쉽고 단순한 JSP 제작 : 자바 코드에 익슥하지 않은 개발자들도 커스텀 태그를 통해 쉽게 JSP 페이지를 작성할수 있게 된다. 예를 들어 JSTL과 EL을 사용하는 경우 스크립트 코드만을 사용하는 경우보다 훨씬 쉽다.
ㅇ 코드의 가독성 향상 : 앞에서 설명했듯이 커스텀 태그는 뚜렷한 목적을 갖고 있고 커스텀 태그를 사용함으로써 스크릅트 코드를 줄일수 있기 때문에 JSP 코드의 가독성을 높일수 있다.

02. 태그 파일을 이용한 커스텀 태그 구현
태그 파일이 출현하기 전까지 커스텀 태그를 구현하려면 정해진 규책대로 자바 코드를 작성하고, 컴파일해서 클래스파일을 만들고 TLD 파일을 작성하고 web.xml 파일에 TLD관련 정보를 기술해 주어야 했다. 이런 어려움을 없애기 위해 추가된것이 태그 팡리이다. 마치 서블릿의 복잡한 구현과정을 JSP가 쉽게 처리하듯이 커스텀태그클래스를 만들기 위한 복잡한 과정을 커스텀태그파일이 쉽게 처리할수 있도록 하였다.

2.1 태그파일의 기본
태그파일은 JSP 페이지와 동일한 문법을 사용한다. JSP페이지를 작성하듯이 태그파일을 작성할수있다. 또한 웹 컨테이너가 JSP소스코드를 서블릿클래스로 변환해 주듯이 태그파일도 커스텀 태그 클래스로 변환해 준다.

tag : JSP페이지의 page 디렉티브와 동일하다. page 디렉티브가 JSP 페이제에 대한 설정 정보등을 명시하는 것처럼 tag 디렉티브는 태그 파일의 정보를 명시한다.
taglib : JSP 페이지와 마찬가지로 태그 파일에 사용할 태그 라이브러리를 명시할때 사용한다.
include: JSP페이지와 마찬가지로 태그 파일에 특정한 파일을 포함시킬때 사용한다.
attribute : 태그 파일이 커스텀 태그로 사용될때 입력 받을 속성을 명시한다.
variable : EL 변수로 사용될 변수에 대한 정보를 지정한다.

태그 파일의 ㅇ튀치 및 태그 파일 참조
태그 파일은 \WEB-INF\tags 디렉터리 또는 그 하위 디렉터리에 위치한다. 이 디렉터리에 위치한 파일중에서 .tag 확장자나 .tagx 확장자를 갖는 파일만 태그 파일로 인식된다. 태그 파일의 이름은 커스텀 태그 이름이 된다. 예를 들어 \WEB-INF\tags\util 디렉터리에 removeHtml.tag 태그파일이 위치했다고 가정해 보자 이경우 JSP 페이지에서는 다음과 같이 이 태그 파일을 커스텀 태그로 사용할수 있다.
<%@ taglib prefix ="tf" tagdir="\WEB-INF\tags\util" %>
<tf:removeHtml...>..</tf:removeHtml>
taglib 디렉티브의 uri 속성 대신 tagdir 속성을 사용해서 태그 파일이 위치한 디렉터리의 경로를 입력하고, 해당 디렉터리에 있는 태그 파일의 이름은 각각 하나의 커스텀 태그 이름이 된다.

2.2 내용을 출력하는 단순 태그 파일 구현
<%@ taglib prefix="tf" tagdir="\WEB-INF\tags" %>

2.3 태그 파일의 속성 설정 방법
'JSTL의 <c:if> 태그나 <c:forEach> 태그를 보면 test, var, items등의 속성을 이용해서 태그를 실행하는데 필요한 값을 전달 받았다. 태그파일도 속성을 이용해서 태그 파일을 실행하는데 필요한 값을 전달받게 된다.

attribute 디렉티브의 속성
description : 속성에 대한 설명
name : 속성의 이름, 태그 파일내에서 스크립트 변수나 EL 변수의 이름으로 사용된다.
required : 속성의 필수 여부를 지정한다.
rtexprvalue : 속성값으로 표현식을 사용할수 있는지의 여부를 지정한다.
type : 속성값의 타입을 명시한다.
fragment : <jsp:attribute> 액션 태그로 속성값을 전달할때 이 값을 true 로 지정한다.

(1) 속성값을 전달하는 기본 방식
<%@ attribute name = "title" required="ture" %>
<%= title %> 또는 ${title}


<%@ attribute name title required="ture" %>
<%@ attribute name = "levle" type="java.lang.Integer"%>

<%
String headStartTag = null;
String headEndtTag = null;
if(level == null){
headStartTag = "<h1>";
headEndTag="<h1>";
}else if(level == 1){
headStartTag = "<h1>";
headEndTag="<h1>";
}else if(level == 2){
headStartTag = "<h2>";
headEndTag="<h2>";
}else if(level == 3){
headStartTag = "<h3>";
headEndTag="<h3>";
}
<%= headStartTag%>
${title}
<%=headEndTag%>

-----------------------------------<tf:header>--------------------

<%@ taglib prefix="tf" tagdir="\WEB-INF\tags" %>
<html>
<body>
<tf:header title ="텍스트 제목" level="2"/>
<tf:header title ="EL 제목" level="3"/>
<tf:header title ="표현식 제목" />
</body>
</html>

(2)<jsp:attribute> 액션 태그를 이용한 속성값 전달
attribute 디렉티브의 fragment 속성값이 true 일 경우, JSP에서는 속성에 값을 전달할때 <jsp:attribute> 액션 태그를 사용해야 한다.

<%-- header.tag--%>
<%@ attribute name = "title" fragment="true" %>

<%-- JSP --%>
<%@ taglib prefix="tf" tagdir ="\WEB-INF\tags"%>
<tf:header>
<jsp:attribute name="title">${article.title}</jsp:attribute>
</tf:header>

<jsp:attribute> 태그는 두개의 속성을 갖는데 두 속성은 다음과 같다.
ㅇ name : 속성의 이름
ㅇ trim : 속성의 값 좌우의 공백들 문자들을 제거할지의 여부, 기본값은 true이다.
<jsp:attribute> 의 몸체에서는 일반 템플릿 텍스트, EL 그리고 <jsp:include> 액션 태그를 사용할수있으며 스크립트 코드는 사용할수 없다.

<jsp:attribute> 액션 태그를 이요해서 커스텀그의 속성값을 지정한 경우, 태그 파일에서는 <jsp:invoke>액션태그를 이용해서 설정한 속성값을 사용할수 있다. <jsp:invoke> 액션 태그의 사용방법은 두기지가 있다.

<%@ attribute name="title" fragment="true"%>

//첫번째 <jsp:attribute>의 몸체 내용을 그대로 처리하여 출력
<jsp:invoke fragment="title"/>
//두번째 <jsp:attribute>의 몸체 내용을 처리한 결과를 지정 영역의 속성에 저장
<jsp:invoke fragment="title" var="rs" scope="page"/>
${pageScope.rs}

<jsp:invoke> 액션 태그의 fragment 속성값은 attribute 디렉티브의 anme 속성과 같은 값을 갖는다. 첫번째 경우처럼 <jsp:invoke>의 fragment 속성값만 사용한 경우에는 <jsp:attrivute>액션 태그의 몸체 내용을 처리한 결과가 그대로 출력된다.

var 속성과 scope 속성을 사용한 경우 <jsp:attribute> 액션 태그의 몸체 내용을 처리한 결과를 scope 속성에서 지정한 영역의 속성으로 저장한다. 이때 var 속성을 이용해서 영역에 저장될때 사용될 이름을 지정한다. 위 예제코드는 apge 영역의 rs 라는 속성에 <jsp:attribute> 액션 태그의 몸체 처리 결과를 저장한다. 이ㅏ후 EL을 이용해서 저장된 객체의 값을 사용할수있게 된다.

(3) 동적 속성 전달
미리 속성 이름을 정의 할수는 없지만 상황에 따라서 동적으로 속성을 추가하고 싶은 경우에는, 커스터 ㅁ태그의 동적 속성기능을 사용하면 된다. 동적 속성을 사용할떄에는 다음과 같이 태그 파일의 tag 디렉티브에서 dynamic-attributes의 속성에 동적 속성을 저장할 변수 명을 입력해 주면 된다.

<%@ tag dynamic-attribute="dynamicMap" %>
${dynamicMap.attrName}..

--예제소스--
<WEB-INF\tags\select.tag>파일
<%@ tag dynamic-attributes="optionMap" %>
<%@attribute name = "name" required="ture" %>
<%@ taglib prefix="c" url="httpL..java.sun.com/jsp/jstl/core" %>
<select name="${name}">
<c:forEach items="${optionMap}" var="option">
<option value="${option.key}">${option.value}</option>
</c:forEach>
</select>
-----------------------------
use_select.jsp

<%@ taglib prefix="tf" tagdir="\WEB-IONF\tags" %>
<html>
<body>
<tf:select name="code" rgb="RGB 모드" wb="흑백모드"/>
<tf:select name="genre" rock="락" ballad="발라드" metal="메탈" />
</body>
</html>

2.4 몸체 내용의 처리
<c:if> 태그는 test 속성의 값이 true일 겨웅 몸체 내용을 출력 하였다.
<c:if test="${someCondition}">
someCondition이 경우 몸체 내용을 출력
</c:tf>

태그 파일로 부터 구현된 태그 몸체를 전달하는 첫번째 방법은 JSTL 태그와 동일하게 시작 태그와 끝 내그 사이에 몸체 내용을 삽입하는 것이다.
<tf:someTagFile atr1="속성값">
여기에 몸체 내용을 입력 한다.
</tf:someTagFIle>

몸체 내용을 전달하는 두번째 방법은 <jsp:body> 태그를 이요해서 몸체 내용을 전달하는 것이다. 태그 파일이 <jsp:attribute>태그를 이용해서 속성값을 전달받는 경우에 <JSP:body>를 사용하여 몸체 내용을 전달 할수 있다.

<tf:someTagFile attr1="속성값">
<jsp:attribute name="attr2">value</jsp:attribute>
<jsp:body>
여기에 몸체 내용을 입력한다.
</jsp:body>
</tf:someTagFIle>

(1)EL 및 태그가 처리된 몸체 내용 사용하기
ㅇ tag 디렉티브의 body-content 속성의 값을 scriptless로 지정한다.
ㅇ <jsp:doBody> 액션 태그를 이용해서 몸체내용을 출력하거나 EL 변수로저장한다.

<%@ tag body-content="scriptless"%>
<jsp:doBody/>

(2) 몸체 내용을 반복적으로 사용하기
<%@ attribute name="count" required="ture" type="java.lang.Integer"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:forEach begin="${1}" end="${count}">
<jsp:doBody />
</c:forEach>
-------------------------------------

<%@ taglib prefix="tf" tagdir="\WEB-INF\tags"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body>
<c:set var="num value="${1}" />
<tf:multiple count ="10">
${num}<br/>
<c:set var="num" value="${num+1}" / >
</tf:multiple>
</body>
</html>

2.5 변수의 생성
JSTL 태그의 <c:forEach> 태그는 var 속성을 이용해서 태그 몸체 내부에서 사용될 EL 변수를 정의할 수있는 기능을 제공하고 있다. <c:set> 태그는 태그를 사용하년 페이지에 새로운 EL 변수를 추가해 준다.
<c:forEach var="prod" items="${prodList}">
${prod.name}
</c:forEach>

<-- 태그 실행 이후 사용 가능한 EL 변수 (name)  추가-->
<c:set var="name" value="bk"/>
${name}


저작자 표시
Trackback 0 Comment 0

14. 표준 태그 라이브러리(JSTL)

JSP는 개발자가 직접 <jsp:include>와 같은 태그를 작성할수있는 기능을 제공하는데 이를 태그라고 한다.
이것들을 모아서 JSTL이라는 규약을 만들었다.
1. JSTL이란
1.1 JSTL이 제공하는 태그의 종류
코어 : 변수지원, 흐름제어, URL처리 --> c
xml : XML 코어, 흐름제어, XML 변호나 --> x
국제화 : 지역, 메시지 형식, 숫자 및 날짜 형식 --> fmt
데이터베이스 : SQL --> sql
함수 : 컬렉션 처리, String 커리 --> fn


02. 코어 태그
변수지원
set : JSP에서 사용될 변수를 설정한다.
remove : 설정한 변수를 제거한다.
흐름제어
if : 조건에 따라 내부 코드를 수행한다.
choose : 다중 조건을 처리할때 사용된다.
forEach : 컬렉션이나 Map의 각 항목을 처리할때 사용된다.
forTokens: 구분자로 분리된 각각의 토큰을 처리할때 사용된다.
URL처리
import : URL을 사용하여 다른 자원의 결과를 삽입힌다.
redirect : 지정한 경로로 리다이렉트 한다.
url : URL을 사용하여 다른 자원의 결과를 삽입힌다.
기타 태그
catch : 예외처리에 사용된다.
out : JspWriter에 내용을 알맞게 처리한 후 출력한다.

2.1 변수지원태그
(1) <c:set>태그
<c:set var = "varName" value="varvalue" [scpoe="영역"]/>
<c:set var = "varName"  [scpoe="영역"]>varvalue</c:set>

var : 값을 지정할 EL변수의 이름
value : 변수의 값을 지정ㅎ나다. 표현식, EL, 정적인 텍스트를사용하여 값을 지정할수 있다.
Scope : 변수를 지정할 영역을 지정한다. 값은 page, request, session, application 중 하나가 온다. 지정하지 않을 경우 기본값은 apge 이다.

<c:set var = "name" value="${m.lastName} ${m.firstName}" />

<c:set target="대상" property = "프로퍼티 이름" value="값"/>
<c:set target="대상" property = "프로퍼티 이름" /> 값</c:set>

target : 프로퍼티 ㄱ밧을 설정할 대상 객체. 표현식이나 EL변수를 지정한다. 대상 객체는 자바빈 객체나 Map이어야 한다.
property: 설정할 프로퍼티의 이름. target이 자바빈 객체인 경우 프로퍼티 이름에 대항다흔 set메서드를 제공해 주어야 한다.
value : 설정할 프로퍼티 값

<c:set var="member" value="<%=member %>"/>
target대상이 EL변수인 경우 target속성의 값을 ${member}와 같이 EL을 이용해서 설정해 주어야 한다.
<c:set var="이름" value=#{expr}"/>

var : EL변수 이름
value : 변수에 할당할 값
scope : 변수를 생성할 영역
target : 프로퍼티 값을 설정할 객체 지정
property : 프로퍼티 이름

(2)<c:remove> xorm

<c:remove>태그는 <c:set>태그로 지정하 ㄴ변수를 삭제 할때 사용된다.
<c:remove var="varName" [scope="영역"]/>

2.2 흐름제어 태그
(1) <c:if>
<c:if test="true">..</:if>

<c:if test="<%=some condition %>" var="testResult">

(2) <c:choose><c:wen><c:otherwise>

<c:choose>
<c:when test="${member.lever=='trial'}">
</c:when>
<c:when test="${member.lever=='abc'}">
</c:when>
<c:otherwise>
</c:otherwise>
</c:choose>

(3)<c:forEach> 태그
<c:forEach>태그는 배열, Collection 또는 Map에 저장되어 있는 값들을 순차적으로 처리할때 사용할수 있느 ㄴ태그로서, 자바의 for, do-while 등을 대신해서 사용할수 있다. 
<c:forEach var="i" begin="1" end="10" setp="2">
${i}사용
</:forEach>

<c:forEach var="i" items="${intArray}" begin="1" end="10" >
${i}사용
</:forEach>

<c:forEach var="i" items="${intArray}" varStatus="status">
${status.index+1}사용
</:forEach>

var : 몸체에서 사용할 EL 변수 이름
items : 반복처리할 데이터
varStatus : 루프상태를 저장할 EL 변수이름
begin : 시작 인덱스 값
end : 끝 인덱스값
step : 인텍스 증분 값

2.3 URL 처리 태그
URL관련 태그는 내부/외부 자원 삽입, URL 생성, 리다이텍트처리의 세가지 기능을 제공한다. 이태그를 이요하면, 스크립트릿이나 표현식을 사용하지 않고 간결한 코드로 URL관련 기능을 수행 할수 있다. 
(1)<c::import> 태그
<jsp:include>는 동일한 웹 어플리케이션내에 위치한 자원을 포함해 주는 기능이라면 <c:import>태그는 동일한 웹 어플리케이션뿐만아니라 외부의 다름 자원을 읽어와 포함시킬수 있도록 해준다. 

요청 파라미터를 추가하는 방식은 다음 두가지 방식이 있다.
ㅇ URL에 직접입력
   1. <c:import url="http://flickr.com/search/?q=design"/>
ㅇ <c:param>태그를 이용해서 입력
   1. <c:import url="http://search.daum.net/search">
         <c:param name="nil_suggest" value="btn" /> 
         <c:param name="1" value="보라매공원" />
        </c:import>

url : 읽어올 URL
var : 읽어온 결과를 저장할 변수 이름
scope : 변수를 저장할 영역
charEncoding : 결과를 읽어올때 사용할 캐릭터 인코딩

(2)<c:url> 태그
URL을 생성해주는 기능을 제공한다. 
<c:url value ="URL" [var="varName"][scope="영역"]>
   <c:param name="이름" value="값" />
</c:url>

<c:url value="/view/list.jsp"/>
---생성하는 URL은 /view/list.jsp를 생성한다. 
value : 읽어올 URL
var : 읽어온 결과를 저장할 변수 이름
scope : 변수를 저장할 영역

(3) <c:redirect> 태그
<c:redirect> 태그는 respone.sendRedirect() 처럼 지정한 페이졸 리다이렉트 해주는 기능을 제공한다. 
<c:redirect url="URL">
<c:param name="이름" value="값"/>
</c:redirect>

<c:redirect url="/viewToday.jsp context="/chap1"/>

04. 함수 
length(obj) : obj가 list와 같은 Collection 인 경우 저장된 항목의 개수를 리턴하고, obj가 문자열일 경우 문자열의 길이를 리턴한다.
toUpperCase(str) : str을 대문자로 변환한다.
toLowerCase(str) : str을 소문자로 변환한다.
substring(str, idx1, idx2) : idx2가 -1일경우str.substring(idx1)과 동일하다
substringAfter(str1, str2) : str1에서 str1에 포함되어 있는 str2이후의 문자열을 구한다.
substringBefore(str1, str2) : str1에서 str1에 포함되어 있는 str2이전의 문자열을 구한다.
trim(str) : str좌우의 공백 문자를 제거한다.
replace(str, src, dest) : str에 있는 src를 dest로 변환한다.
indexOf(str2, str2) : str1에서 str2가 위치한 인덱스를 구한다.
startsWith(str1, str2) : str1이 str2로 시작할 경우 true를 그렇지 않을 경우 false를 리턴한다.
endsWith(str1, str2): str1이 str2로 끝나는 경우 true를 그렇지 않을 경우 false를 리턴한다.
contains(str1, str2) : str1이 str2를 포함하고 있을 경우 true를 리턴한다.
containslgnoreCase(str1, str2) : 대소문자 구분 없이 str1이 str2를 포함하고 있을경우  true를 리턴한다.
split(str1, str2) : str2로 명시한 글자를 기준으로 str1을 분리해서 배열을 리턴한다.
join(array, str2) : array에 저장된 문자열을 합친다. 이때 각문자열 사이에는 str2이 붙는다.
escapeXml(str) : XML의 객체 참조에 해당하는 특수문자를 처리한다. 예를 들어 '&'는 '&amp;'로 변환한다.

  

저작자 표시
Trackback 0 Comment 0

13. 표현언어(Expression Language)

표현언어는 이름에서 알수 있듯이 값을 표현하는데 사용되는 새로운 스크립트 언어로서 JSP의 기본 문법을 보오나하는 역할을 한다.
1. JSP의 네가지 기본 객체가 제공하는 영역의 속성을 사용한다.
2. 집합 객체에 대한 접근 방법 제공
3. 수치 연산, 관계연산, 논리 연산자 제공
4. 자바 클래스 메서드 호출 기능 제공
5. 표현언어만의 기본 객체 제공

1.1 표현언어의 기본 문법
${expr}

<jsp:include page="/module/${skin.id}/header.jsp" flush="ture" />

<b>${sessionScope.member.id}</b>님 환영합니다.

#{expr} 형식의 EL은 실제로 값이 필요할때 계산을 수행하기 때문에 Deferred Expression 이라고 부른다.

02. 표현언어의 기본 객체
EL도 이와 마찬기지로 11개의 기본 객체를 제공함으로써 요청 파라마터나 세션 속성값등을 표현식에서 쉽게 사용할수 있도록 하고 있다. 

pageContext : JSP의 page 기본 객체와 동일한다.
pageScope : pageContext 기본 객체에 저장된 속성의<속성, 값> 매핑을 저장한 Map 객체
requestScope : request 기본 객체에 저장된 속성의 <속성, 값> 매핑을 저장한 MAP 객체
sessionScope : session기본 객체에 저장된 속성의 <속성, 값> 매핑을 저장한 MAP 객체
applicationScope : application 기본 객체에 저장된 속성의 <속성, 값> 매핑을 저장한 MAP 객체
param : 요청 파라미터의 <파라미터이름, 값> 매핑을 저장한 Map 객체, 파라미터 값의 타입은 String으로서 request.getParameter의 결과와 동일하다
paramValues : 요청 파라미터의<파라미터이름, 값배열> 매핑을 저장한 map 객체. 값의 타입은 String[]으로서, request.getParametervalues의 결과와 동일하다
header : 요청정보의<헤더이름, 값> 매핑을 저장한 map 객체
headervalues : 요청정보의<헤더이름, 값 배열> 매핑을 저장한 Map 객체
cookie : <쿠키이름, Cookie> 매핑을 저장한 Map 객체
initParam  : 초기화 파라미터의 <이름, 값> 매핑을 저장한 map 객체

EL언으의 특징으로서 EL언어는 값이 존재하지 않을 경우 아무것도 출력하지 않는다.
${cookie.ID.value}
EL의 cookie 기본 객체는<이름, Cookie 객체>의 맵을 저장하고 있기 때문에 cookie.ID는 이름이 ID인 Cookie 객체를 리턴하다. 따라서 Cookie.ID.value 가 출력값은 이름이 ID인 Cookie 객체의 getValue() 메서드의 리턴 값이 된다. 이름이 "ID"인 쿠키가 존재 하지 않는다면 아무 값도 출력되지 않는다.

03. 표현언어의 기본

3.1 EL의 데이터 타입
블리언 : true, false
정수 타입 : 0~9로 이루어진 정수값 음수의 경우 -가 붙음
실수타입 : 0~9로 이루어져 있으며, 소수점을 사용할수 있고 3.24e3과 같이 지수형 표현가능
문자열타입 : 따옴표(',")로 둘러싼 문자열.
널타입 : null

3.2 객체에 접근하기
<표현1>.<표현2> 또는 <표현1>[<표현2>]

1. 표현1을 값1로 변환한다.
2. 값1이 null 이면 null을 리턴한다.
3. 값1이 null이 아닐경우 표현2를 값2로 변환한다. 
 ㅇ 값2가 null 이면 null을 리턴한다.
4. 값1이 map,list 배열인 경우
 ㅇ 값1이 map이면
    1. 값1.containsKey(값2)가 false이면 null을 리턴한다.
    2. 그렇지 않으면 값1.get(값2)를 리런한다.
  ㅇ 값1이 list 이면
    1. 값2가 정수인 값인지 검사한다(정수값이 아닐경우 에러발생)
    2. 값1.get(값2)또는 Array.get(값1, 값2)를 리턴한다.
    3. 위코드가 예외를 발생하면 에러를 발생한다.
5. 값1이 다른객체이면
  ㅇ 값2를 문자열로 변호낳ㄴ다.
  ㅇ 값1이 이름이 값2이고 읽기 가능한 프로퍼티를 포함하고 있다면 프로퍼티의 값을 리턴한다.
  ㅇ 그렇지 않을경우 에러를 발생한다.

------------------------${cookie.ID.value} EL 표현식을 분석 --------------------
cookie는 EL이 제공하는 기본 객체로서 타입은 Map이다 따라서 위 처리과정중에서 4-A에 해당한다. cookie.ID를 분석할때에는 cookie.containsKey("ID")의 존재 여부를 확인한후, 존재할 경우 cookie.get("ID")를 리턴한다. cookie.get("ID")가 리턴하는 객체는 Cookie 객체이므로 cookie.ID.value는 위의 과정중 5에 해당한다. value를 문자열로 변혼한후, cookie.ID 객체가 읽기 가능한  value 프로퍼티가 있는지 조사한다. cookie.ID는 Cookie 클래스의 객체이고 Cookie 클래스는m getValue() 메서드를 제공하므로 읽기 가능한 value 프로퍼티가 존재한다. 따라서 결과적으로 Cookie.ID.value는 이름이 ID인 쿠키 값을 리턴하게 된다.

3.3 객체의 탐색
Page, Request, Session, Application 영역에 저장된 속성에 접근 할때에는 pageScope, requestScope, sessionScope,applicationScope 기본 객체를 사용한다고 했다. 예를들어 다음 코드는 apge 영역에 저장되어 있는 name이라는 속성값을 참고하게 된다. ${pageScope.NAME}

영역을 나타내는 EL 기본 객체를 사용하지 않고 이름만 지정할 경우 EL은 4개의 영역을 차례대로 검색해서 속성이 존재하는지 확인한다.
${NAME}
3.4 수치 연산자
+ : 덧셈
- : 뺄샘
* : 곱셈
/ : 나눗셈
% : 나머지

숫자가 아닌 객체와 수치 연산자를 사용할 경우 객체를 숫자 값으로 변환한 후 연산자를 수행한다.
${"10"+1} = 에러 발생
${"일"+1} = 에러발생
${null +1} = 1 null은 0으로 처리
${3/2} = 1.5 EL에서 나눗셈 연산자는 정수가 아님

3.5 비교 연산자
--, !=, <, >, <=, >=

문자열 비교 : String.compareTo()
${someValue == "2004"}
---> (someValue.compareTo("2004")==0)과 같은 의미

3.6 논리연산자
&&,||,!

3.7 empty 연산자
empty연산자는 검사할 객체가 텅 빈 객체인지를 검사하기 위해 사용하낟. empty 연산자는 다음과 같이 사용한다. empty <값>
여기서 <값>에 따라 리턴되는 값은 다음과 같이 결정된다.
1. <값>이 null이면 true를 리턴한다.
2. <값>이 빈문자열이면  true를 리턴한다.
3. <값>이 길이가 0인 배열이면 true를 리턴한다.
4. <값>이 빈 Map이면 true를 리턴한다.
5. <값>이 빈 Collection이면 true를 리턴한다.
6. 이외의 경우에는  false를 리턴한다.

3.8 비교 선택 연산자
<수식>? 값1: 값2

3.9 특수문자 처리하기
\${expr} 또는 \#{expr}을 입력 할 경우 있는 그대로를 출력한다.

* EL에서 클래스의 메소드를 사용하기 위해서는 클래스의 메소드를 static으로 정의해야 하며, static 이 아닌 메소드는 사용할수 없다.

4.1 함수를 정의한 TLD 파일 작성
클래스 파일을 작성했다면 TLD 파일을 작성해 주어야 한다. TLD 파일은 태그 라이브러리에 대한 설정 정보를 담고 있다.
TLD파일은 WEB-INF\tlds디렉터리나 WEB-INF\jsp 디렉터리와 같은곳에 위치시킨다.

el-function.tld
<?xml version ="1.0" encoding="euc-kr"?>
<taglib xmlns="................">
<description>EL에서 함수 실행</description>
<tlib-version>1.0</tlib-version>
<short-name>ELfunctions</short-name>

<function>
<descpritoion> date 객체 포맷팅 </description>
<name dateFormat</name>
<function-class>kame.dateUtil</function-clas>
<function-signature>java.lang.String format(java.util.Date)</fucntion-signature>
</function>

4.3 web.xml 파일에 TLD 내용 추가 하기
TLD 파일을 작성한 다음에는 web.xml 팡리에 TLD 파일에 대한 내용을 추가 해 주어야 한다.

<jsp-config>
<taglib>
<taglib-uri>
/WEB-INF/tlds/elfunction.tld
</taglib-uri>
<taglib-location>
/WEB-INF/tlds/el-functions.tld
</taglib-location>
</taglib>
</jsp-config>

4.4 EL에서 함수 사용하기
EL에서 함수를 사용하기 위해서는 다음과 같은 형태의 코드를 사용한다.
<%@ taglib prefix="pre" uri=".." %>
${pre:functionName(arg1,arg2,..)}

<%@ taglib prefix="elfunc" uri="/WEB-INF/tlds/el-function.tld" %>
${elfunc:dateFormat(today)}

5. 표현언어 비활성화 방법
ㅇ web.xml 파일에 비활성화 옵션 지정하기

<jsp-config>
<jsp-property-group>
<url-pattern>/oldversion/*</url-pattern>
<el-ignored>true</el-ignored>
</jsp-property-group>
</jsp-config>

또는

<jsp-config>
<jsp-property-group>
<url-pattern>/oldversion2_4/*<url-pattern>
<deferren-syntax-allowed-as-literal>true </deferren-syntax-allowed-as-literal>
</jsp-property-group>
</jsp-config>

ㅇ JSP 페이지에 비활성화 옵션 지정하기
JSP 페이지의 page 디렉티브를 이용하여 EL을 활성화 시키거나 비활성화 시킬수 있다.
isELlogored :  이값이 true 일경우 EL을 일반 문자열로 처리한다.
defrredSyntaxAllowedAsLiteral : 이 값이 true일 경우 #{expr} 형식의 EL을 문자열로 처리 한다.
<%@ page isELIgnored="true" %>
<%@ page deferredSyntaxAllowedAsLiteral="true"%>

web.xml 파일을 서블릿 2.3 또는 2.4 버젼에 맞게 작성하기





저작자 표시
Trackback 0 Comment 0

12. 데이터베이스 프로그래밍 기초

01. JSP에서 JDBC 프로그래밍 하기
 1.1 JDBC의 구조
   자바 웹 어플리케이션 => JDBC API => JDBC 드라이버
 1.2 JDBC 프로그래밍의 코딩 스타일
  1. JDBC 드라이버 로딩
  2. 데이터베이스 커넥션 구함
  3. 쿼리 실행을 위한 statement 객체 생성
  4. 쿼리 실행
  5. 쿼리 실행 결과 사용
  6. statement 종료
  7. 데이터베이스 커넥션 사용
1.3 
<%@ page  import  = "java.sql.DriverManager"%>
<%@ page  import  = "java.sql.Connection"%>
<%@ page  import  = "java.sql.Statement"%>
<%@ page  import  = "java.sql.ResultSet"%>
<%@ page  import  = "java.sql.SQLException"%>

<%
Class.forName("com.mysql.jdbc.Driver");
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;

try{
String jdbcDriver = "jdbc:mysql://localhost:3306/chap12?" +
  useUnicode=true&characterEncoding=euckr";
String dbUser = "sa";
String dbpass = "sa";

String query = "select * from MEMBER order by MEMBERID";

conn = DriverManager.getConnection(jdbcDriver, dbuser, dbPass);

stmt = conn.create.Statement();

rs=stmt.executeQuery(query);

while(rs.next()){
%>
<%= rs.getString("NAME")%>
<%
}
} catch(SQLException ex){
  out.println(ex.getMessage());
 ex.printStackTrace();
}
finally{
if(rs != null) try {rs.close();} catch(SQLException ex){}
if(stmt != null) try{ stmt.close();} catch(SQLException ex){}
if(conn != null) try{ conn.close();} catch(SQLException ex){}
}
%>

1.4 DBMS와 통신을 위한 JDBC 드라이버

MySQL : com.mysql.jdbc.Driver
오라클 : oracle.jdbc.driver.OracleDriver
MS SQL 서버 : com.microsoft.sqlserver.jdbc.SQLServerDriver

1.5 ResultSet에서 값 읽어 오기
rs.next : ture
  - > 1행 -> 2행 -> 3행 으로 커서는 이동한다.
ResultSet 클래스의 주요 데이터 읽기 매소드
getString(String name) : 지정한 컬럼의 값을 String  으로 읽어 온다.
getString(int index)

getCharacterStream(String name) : 지정한 컬람의 값을 스틸힘으로 읽어 온다. Long Varchar 타입을 읽어올 떄 사용
getCharacterString(int index)

getInt(String name) : 지정한 컬럼의 값을 int 타입으로 읽어온다.
getInt(int index)

getLong(String name) : 지정한 컬럼의 값을 long 타입으로 읽어온다.
getLong(int index)

getDouble(String name) : 지정한 컬럼의 값을 double타입으로 읽어온다.
getDouble(int index)

getFloat(String name) : 지정한 컬럼의 값을 float타입으로 읽어온다.
getFloat(int index)

getTimestamp(String name) : 지정한 컬럼의 값을 timestamp 타입으로 읽어온다.
getTimestamp(int index)

getDate(String name) : 지정한 컬럼의 값을 date 타입으로 읽어온다
getDate(int index)

getTime(String name) : 지정한 컬럼의 값을 time 타입으로 읽어온다.
getTime(int index)

1.6 ResultSet에서 LONG VARCHAR 타입 값 읽어오기
대량의 덱스트 데이터를 저장할때 사용되며, Resultset에서 LONG VARCHAR 타입의 데이터를 읽어 오기 위해서는 getCharacterStream() 메서드를 사용해야 한다. ResultSet.getCharacterStream(메서드의 리턴 타입이 java.io.Reader 타입이다

- 코드:
String data = null;
java.io.Reader reader = null;
try{
reader = rs.getCharacterStream("FIELD");
if(reader != null){
StringBuffer buff = new StringBuffer();
char[] ch = new char[512];
int len = -1;

while((len=reader.read(ch))!= -1){
buff.append(ch, -, len);
}

data = buff.toStirng();
}
chatch(IOException ex){
}finally{
if(reader != null) try{reader.close();} chatch(IOException ex){}
}

1.7 PreparedStatement를 사용한 쿼리 실행
java.sql.PreparedStatement는 java.sql.Statement와 동일한 기능을 제공 , 차이가 있다면 SQL 쿼리의 틀을 미리 생성해 놓고 값을 나중에 지정한느것
순서 :
1. Connectin.prepareStatement() 메서드를 사용하여 preparedStatement 생성
2. PreparedStatement의 set 메서드를 사용하여 필요한 값 지정
3. PreparedStatement의 executeQuery() 또는 executeUpdate() 메서드를 사용하여 쿼리를 실행
4. finally 블록에서 사용한 PreparedStatement를 닫는다. (close() 메서드 사용)

PreparedStatement를 생설할때 실행할 쿼리를 입력해야 하는데 다음과 같이 사용한다.
PreparedStatement pstmt = null;
pstmt = conn.prepareStatement( "insert into member(memberid, name, email) values(?,?,?)");
pstmt.setString(1,"starstroy");
pstmt.setString(2,"홍길동");
pstmt.setString(3,a@a.com);
pstmt.executeUpdate();

ResultSet의 메서드들
setString(int index, String x) : 지정한 인덱스의 파라미터 값을 x로 지정한다.
setCharacterStream(int index, Reader reader, int length) : 지정한 인덱스의 값이 long varchar 타입의 값으로 지정할때 사용한다.
setInt(int index, int x) : 지정한 인덱스의 타파라미터 값을 int 값 x 로 지정한다.
setLong(int index, long x) : 지정한 인덱스의 타파라미터 값을 long 값 x 로 지정한다.
setDouble(int index, double x) : 지정한 인덱스의 타파라미터 값을 double값 x 로 지정한다.
setFloat(int index, float x) : 지정한 인덱스의 타파라미터 값을 float 값 x 로 지정한다.
setTimestamp(int index, Timesetamp x) : 지정한 인덱스의 값을 SQL  TIMESTAMP 타입을 나타내는 java.sql.TimeStamp 타입으로 지정한다.
setDate(int index Date x) : 지정한 인덱스의 값을 SQL DATE 타입을 나타내는 java.sql.date 타입으로 지정한다.
setTime(int index, Time x) : 지정한 인덱스의 값을 SQL TIME 타입을 나타내는 java.sql.time 타입으로 지정한다.
1.8 PreparedStatementdpjt LONG VARCHAR 타입 값 지정하기
setCharacterStream(int index, Reader reader, int length)

Reader로 부터 length 클자 수만큼 데이터를 읽어와 저장ㅎ나다. Reader에는 String으로 부터 데이터를 읽어 오는 Reader와 파일로 부터 읽어 오는 Reader등 다양한 Reader 가 존재한다.
코드 :
PreapredStatement pstmt = null;
try{
String value = "....";
pstmt = conn.prepareStatement(...);
java.io.StirngReader reader = new java.io.StringReader(value);
pstmt.setCharacterStream(1, reader, value.length());
..
} catch(SQLException ex){
}finally{
if(pstmt != null) try{pstmt.close(); } catch(SQLException ex){}

1.9 PreparedStatement 쿼리를 사용하는 이유
1. 반복해서 실행되는 동일 쿼리의 속도를 증가시키기 위해
2. 값 변환을 자동으로 하기 위해
3. 간결한 코드를 위해

1.10 웹 어플리케이션 구동시 JDBC 드라이버 로딩하기
Class.forName(JDBCDriverClass);
웹 어플리케이션이 시작될때 자동으로 JDBC 드라이버를 로딩하도록 만드려면 서블릿 클래스를 사용해야 한다.

package kame.jdbc.loader;

import javax.servlet.http.HttpServlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import java.util.StringTokenizer;

public class Loader extends HttpServlet{
public void init(ServletConfig config) throws ServletException {
try{
String dervers = config.getInitParameter("jdbcdriver");
String Tokenizer st = new StringTokenizer(drivers,",");
while(st.hasMoreTokens()){
String jdbcDriver = st.nextToken();
Class.forName(jdbcDriver);
}
}catch(Exception ex){
throw new ServletException(ex);
}
}
}

Loader.java 를 컴파일 한 다음에는 웹 어플리케이션이 시작될때 자동으로 Loader 서블릿 클래스가 실행되도록 설정해 주어야 한다. web.xml파일에 <servlet> 태그를 추가해주면 된다.
<servlet>
<servlet-name> JDBCDriverLoader</servlet-name>
<servlet-class>kame.jdbc.loader.Loader</servlet-class>
<init-param>
<param-name>jdbcdriver</param-name>
<param-value>com.mysql.jdbc.Driver</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

2. JDBC에서 트랜잭션 처리
트랜잭션 시작 : 트랜잭션 시작 이후 실행되는 쿼리를 하나의 작업으로 처리
..
..
..
트랜잭션 커밋 : 트랜잭션 시작 이후 에러가 발생하지 않으면 쿼리 결과를 DB에 반영

트랜잭션 롤백 : 에러가 발생하면 실행된 쿼리 결과를 DB에 반영하지 않고 취소함

try{
conn=DriverManager.getConnection(...);
conn.setAutoCommit(false);
conn.commit();
}
catch(SQLException ex){
if(conn != null){
conn.rollback();
}
}
finally{
if(conn != null){
try{conn.colse();}catch(SQLException ex){}}}

3. 커넥션 풀
 : 커넥션 풀 기법에서는 풀속에 데이터베이스와 연결된 커넥션을 미리 생성해 놓는다. 데이터베이스 커넥션이 필요할 경우, 커넥션을 새로 생성하는 것이 아니라 풀속에 미리 생성되어 있는 커넥션을 가져다가 사용하고, 사용이 끝나면 커넥션을 풀에 반환한다. 풀에 반호나된 커넥션은 다음에 다시 사용된다.
 풀속에 미리 커넥션이 생성되어 있기 때문에 커넥션을 생성하는데 드는 연결시간이 소비 되지 않는다.
 커넥션을 계속 해서 재사용하기 때문에 생성되는 커넥션 수가 많지 않다.
 3.1 DBCP를 이용해서 커넥션 풀 사용하기
 - DBCP 관련 jar 파일 및 JDBC 드라이버 jar 파일 설치하기
 - 커넥션 풀 관련 설정 파일 초기화 하기
  : DBMS에 연결할때 사용될 JDBC 드라이버
  : org.apache.commons.dbcp.PoolingDriver : DBCP API의 JDBC 드라이버

 web.xml 파일을 사용한  DB초기화
<servlet>
  <servlet-name> DBCPInit</servlet-name>
  <servlet-class>madvires.jdbcdriver.DBCPInit</servlet-class>
 <init-param>
   <param-name>jdbcdriver</param-name>
   <param-value>com.mysql.jdbc.Driver</param-value>
 </init-param>
 <load-on-startup>1</load-on-startup>
</servlet>
---- 웹 어플리케이션이 시작할때 DBCPInit 서블릿 클래스가 자동으로 시작되고 init() 메서드가 호출된다.
 - 커넥션 풀 관련 드라이버 로딩하기
 - 커넥션 풀로 부터 커넥션 사용하기
Connection conn = null;
try{
Stirng jdbcDriver = "jdbc:apache:commons:dbcp:/pool";
conn = DriverManager.getConnection(jdbcDriver);
}finally{
if(conn != null) try{conn.close(); } catch(SQLException ex) {}
}



저작자 표시
Trackback 0 Comment 0

11. <jsp:useBean> 액션 태그를 이용한 객체 사용

01. 자바빈
자바빈은 데이터를 표현한는 것을 목적으로 하는 자바 클래스로서, 다음과 같은 형태로 구성된다.

public class BeanClassName implements java.io.Serializable{
private String value;
// BeanClassName의 기본 생성자
public BeanClassName(){
}
// 필드의 값을 읽어오는 값
public String getvalue(){
return value;
}

//필드의 값을 변경하는 값
public void setValue(String value){
this.value = value;
}
}

자바빈 규약에 따르는 클래스를 자바빈이라고 부르며, JSP 프로그래밍에서 사용되는 자바빈클래스는 위 예시코드와 같이 데이터를 저장하는 필드, 데이터를 읽어올때 사용되는 메서드, 값을 저장할때 사용되는 메서드로 구성된다.
1.1 자바빈 프로퍼티
public void setMaxAge(int value);
public int getMaxAge();

ㅇ 읽기 전용 프로퍼티 : get 또는 is메소드만 존재하는 프로퍼티
ㅇ 읽기/쓰기 프로퍼티 : get/set 또는 is/set 메소드가 존재하는 프로퍼티

ㅇ자바빈 프로퍼티의 타입은 다음과 같이 배열로도 정의 할수 있다.
public int[] getMark()
public void setMark(int[] values)
02. <jsp:useBean> 태그를 이용한 자바 객체 사용
<%
  MembeInfo mi = new MemberInfo();
mi.setId("starstory");
mi.setName("홍길동");
%>
이름 - <%= mi.getName() %>, 아이디 - <%=mi.getId() %>

2.1 <jsp:useBean> 액션 태그를 사용하여 객체 생성하기
<jsp:useBean id = "빈이름" class="자바빈클래스이름" scope"범위"/>
id : JSP 페이지에서 자비빈 객체에 접근할때 사용할 이름을 명시한다.
class : 패키지 이름을 포함한 자바빈 클래스의 오나전한 이름을 입력한다.
scope : 자바빈 객체가 저장될 영역을 지정한다. page, request, session, application 중 하나의 값을 갇는다.
<jsp:useBean id = "info" class ="chap11.member.MemberInfo" scope="request"/>
<%
member.setId("starstory");
Member.setName("홍길동");
%>
<jsp:forward page = "/useObject.jsp"/>

2.2 <jsp:getProperty> 액션태그와 <jsp:setProperty> 액션 태그
<jsp:setProperty name="자바빈" property"이름" value="rkqt" />
ㅇ name : 프로퍼티의 값을 변경할 자바빈 객체의이름 <jsp:useBean> 액션 태그의 id 속성에서 지정한 값을 사용한다.
ㅇ property : 값을 지정할 프로퍼티의 이름
ㅇ value : 포르퍼티의 값, 표현식을 사용할수 있다. 

<jsp:useBean id = "member" class="chap11.member.MemberInfo"/>
<jsp:setProperty name ="member" property ="name" value="홍길동">

value 속성 대신에 param 속성을 사용할수 도 있다. param 속성은 파리미터의 값을 프로퍼티의 값으로 지정할대 사용된다. 예를 들어 memberId 파라미터의 값을 자바빈 객체의 id프로퍼티의 값으로 지정하고 싶다면 다음같이 지정하면 된다. 

<jsp:setProperty name ="member" property="id" param="memberId" />

-------------------------getProperty
<jsp:getProperty name = "자바빈이름 property="프로퍼티 이름" />

<jsp:getProperty name = "member" property="name"/>

예제 -------------------------------------
<% 
request.setCharacteEncoding("euc-kr");
%>
<jsp:useBean id = "memberInfo" class = "chap11.member.MemberInfo" />
<jsp:setProperty name = "memberInfo" property="*" />
<jsp:setProperty name = "memberInfo" property="password" value=<%= memberInfo.getId() %>" /> 

아이디 : <jsp:getProperty name "memberInfo" property="id"/>
패스워드 : <jsp:getProperty name "memberInfo" property="password"/>

저작자 표시
Trackback 0 Comment 0

10. 클라이언트오의 대화 2: 세션


세션을 사용하면 서버는 클라이언트의 상태 값을 유지 할수 있기 때문에, 인증도니 사용자 정보를 유지하기 위한 목적으로 세션을 많이 사용한다.
01. 세션사용하기
세션은 웹 컨테이너에서 정보를 보관 할때 사용된다. 세션은 오직 서버에서만 사용된다.
웹컨테이너는 기본적으로 하나의 웹 브라우저에 하나의 새션을 생섢나다.
1.1 세션 생성하기
JSP에서 세션을 생성하기 위해서는 page 디렉티브의 session 속성을 true로 지정해 주면 된다.

<%@ page session = "true"%>
: page의 ssion 속성의 기본값은 true 이므로 session 속성의 값을 false로 지정하지만 않으면 세션이 생성된다. 일단 새션이 생성되면 session 기본 객체를 통해서 새션을 사용할수 있게 된다.
1.2 session 기본 객체
getID() : 새션의 고유 ID를 구한다.
getCreationTime() : 새션의 생성된 시간을 구한다. 단위는 1/1000초이다.
getLastAccessedTime() : 웹브라우저가 가장 마지막에 새션에 접근한 시간을 구한다. 단위는 1/1000초이다.

<@ page session = "true"%>
새션ID : <%= session.getID() %>
<%
time.setTime(session.getCreationTime());
%>
새션 생성 시간 : <%=formatter:format(time) %>
<%
time.setTime(Session.getLastAccessedTime());
%>
최근 접근 시간 : <%=formatter:format(time) %>

1.3 session 기본 객체의 속성 사용
생성된 세션은 지정된 유효시간 동안 유지된다. 따라서 request 객체가 하나의 요청을 처리하는데 사용되는 JSP페이지 사이에서 공유된다면, session 기본 객체는 웹 브라우저의 여러 요청을 처리하는 JSP페이지 사이에서 공유 된다. 따라서 로기은 한 회원정보등 웹 브라우저와 1:1 매핑이 되는 값을 저장할때에는 쿠키 대신 새션을 사용할수도 있다.

새션값을 저장할때는 속성을 사용한다. 속성에 값을 저장할때는 request  객체와 마찬가지로 setAtribute()메소드를 사용하며, 속성값을 사용할때는 getAttribute() 메소드를 사용한다.
<%
session.setAttribute("MemberID","starstory");
session.setAttribute("NAME","홍길동");
%>


------------새션가져오기
<%
String name = (String)session.getAttribute("NAME");
%>
회원명 : <%=name %>

1.4 세션 종료
<%
session.invalidate();
%>
* 세션이 한번 종료 되면, 다음에는 새로운 세션이 생성된다. 

1.5 새션의 유효시간
 - session.getLastAccessedTime()

web.xml파일에 <session-config>태그를 사용하여 세션 유효시간을 지정할수 있다. 
<session-config>
<session-timeout>50</session-timeout>
</session-config>

<session-timeout>의 값을 0이나 음수로 설정하면 세션은 유효시간을 갖지 않는다.
명시적으로 session.invalidate() 메서드를 호출하지 않으면 생성된 세션 객체가 서버에서 제거되지 않고 유지된다.
세션 객체로 인해 메모리가 부족해지는 현상을 방지하려면, 반드시 세션 타임아웃 시간을 지정해 주어야 한다.
-------------------setMaxInactiveInterval();
 <%
setMaxInactiveInterval(60*60);
%>

1.6 request.getSession()을 이용한 새션 생성
<%
HttpSession httpSession = request.getSession();
List list = (List)httpSession.getAttribute("list");
list.add(productId);
%>
request.getSession() 메서드는 session이 생성되어 있는 경우 생선된 sessionㅇ르 리턴하고 생성되어 있지 않은 경우 새롭게 session을 생성해서 리턴한다.
request.getSession(false)를 실행하면 session 객체가 생성된 경우에는 session 객체를 리턴하고 session 객체가 생성되어 있지 않은 경우에는 null을 리턶ㄴ다.

<%
HttpSession httpSession = request.getSession(false);
List list = null;
if(httpSession != (List)httpSession.getAttribute("list");
}
else{
list = Collections.emptyList();
}

02.세션을 사용한 인증 저보 유지
1. 로그인인에 성공하면 session 객체의 특정 속성에 데이터를 기록한다.
2. 이후로 session 객체의 특정 속성이 존재하면 로그인한 것으로 간줗ㄴ다.
3. 로그아웃 할 경우 session.invalidate() 메서드를 호출하여 세션을 종료한다.

<%
String id = request.getParameter("id");
String password = request.getParameter("password");

if(id.equals(password)){
session.setAttribute("MEMBERID", id);
%>
----------
<%
String memberId = (String)session.getAttribute("MEMBERID");
boolean login = memberId == null ? false : true;
%>

2.3 로그아웃 처리
<%
session.invalidate();
%>
또는
<%
session.removeAttribute("MEMBERID");
%>
:::세션정보:::
<%@ page contentType = "text/html; charset=euc-kr" %>
<%@ page session = "true" %>
<%@ page import! = "java.util.Date" %>
<%@ page import! = "java.text.SimpleDateFormat" %>
<%
    Date time = new Date();
    SimpleDateFormat formatter =
       new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
%>
<html>
<head><title>세션정보</title></head>
<body>
세션ID: <%= session.getId() %> <br>
<%
    time.setTime(session.getCreationTime());
%>
세션생성시간: <%= formatter.format(time) %> <br>
<%
    time.setTime(session.getLastAccessedTime());
%>
최근접근시간: <%= formatter.format(time) %>
</body>
</html>
 

:::세션생성:::
<%@ page contentType = "text/html; charset=euc-kr" %>
<%
    session.setAttribute("MEMBERID", "madvirus");
    session.setAttribute("NAME", "최범균");
    session.setMaxInactiveInterval(60*60); //시간설정
%>
<html>
<head><title>세션에 정보 저장</title></head>
<body>
세션에 정보를 저장하였습니다.
<% String name=(String)session.getAttribute("NAME"); %>
회원명: <%= name %>
</body>
</html>
 

:::세션종료:::
<%@ page contentType = "text/html; charset=euc-kr" %>
<%
    session.invalidate();
%>
<html>
<head><title>세션 종료</title></head>
<body>
세션을 종료하였습니다.
</body>
</html>
 

:::세션시간xml:::
<?xml version="1.0" encoding="euc-kr"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">
  <display-name>9장 예제</display-name>
  <description>
     9장의 예제 소스 코드 및 실행 코드
  </description>
 
  <session-config>
    <session-timeout>1</session-timeout>
  </session-config>
</web-app>
 

:::세션로그인:::
<%@ page contentType = "text/html; charset=euc-kr" %>
<%@ page import! = "jsp.util.Cookie!Box" %>
<%
    String id = request.getParameter("id");
    String password = request.getParameter("password");
   
    if (id.equals(password)) {
        session.setAttribute("MEMBERID", id);
%>
<html>
<head><title>로그인성공</title></head>
<body>
로그인에 성공했습니다.
</body>
</html>
<%
    } else { // 로그인 실패시
%>
<script>
alert!("로그인에 실패하였습니다.");
history.go(-1);
</script>
<%
    }
%>
 

:::세션로그인폼:::
<%@ page contentType = "text/html; charset=euc-kr" %>
<html>
<head><title>로그인폼</title></head>
<body>
<form action="<%= request.getContextPath() %>/member/sessionLogin.jsp"
      method="post">
아이디 <input type="text" name="id" size="10">
암호 <input type="password" name="password" size="10">
<input type="submit" value="로그인">
</form>
</body>
</html>
 
:::세션로그인여부검사:::
<%@ page contentType = "text/html; charset=euc-kr" %>
<%
    String memberId = (String)session.getAttribute("MEMBERID");
    boolean login = memberId == null ? false : true;
%>
<html>
<head><title>로그인여부 검사</title></head>
<body>
<%
    if (login) {
%>
아이디 "<%= memberId %>"로 로그인 한 상태
<%
    } else {
%>
로그인하지 않은 상태
<%
    }
%>
</body>
</html>
 
:::세션로그아웃:::
<%@ page contentType = "text/html; charset=euc-kr" %>
<%
    session.invalidate();
%>
<html>
<head><title>로그아웃</title></head>
<body>
로그아웃하였습니다.
</body>
</html>
저작자 표시
Trackback 0 Comment 0

09. 클라이언트와의 대화1 : 쿠키

ㅇ 웹서버가 우 브라우저에 정보를 전달하는 방법
01. 쿠키 사용
쿠키란 : 웹 브라우저가 보관하고 있는 데이터로서 웹 서버에 요청을 보낼때 함꼐 전송된다. 웹서버와 웹 브라우저 양쪽에서 생성 할수 있으며, 웹 서버는 웹 브라우저가 전송한 쿠키를 사용하여 필요한 데이터를 읽어 올수 있다.
ㅇ 쿠키생성 단계 : 쿠키를 사용하기 위해서는 쿠키를 생성해야 한다.
ㅇ 쿠키저장단계 : 웹 브라우저는 응답데이터에 포하된 쿠키를 쿠키저장소에 보고나한다. 쿠키의 종류에 따라 메모리나 파일로 저장된다.
ㅇ 쿠키전송단계 : 웹 브라우저는 한번 저장된 쿠키를 매번 요청이 있을때 웹 서버에 전송한다. 웹서버는 웹 브라우저가 전송한 쿠키를 사용해서 핋요한 작업을 수행 할수있다.

- 웹브라우저는 쿠키가 삭제 되기 전까지 웹 서버에 쿠키를 전송한다. 지속적으로 유지해야 하는 정보는 쿠키를 사용해서 저장할수 있다.
1.1 쿠키의 구성
이름 : 각각의 쿠키 를 구별하는데 사용되는 이름
값 : 쿠키의 이름과 관련된 값
유효시간 : 쿠키의 유지 시간
도메인 : 쿠키를 전송할 도메인
경로 : 쿠키를 전송할 요청 경로

- 쿠키의 이름은 아스키 코드의 알파벳과 숫자만을 포함할수 있다.
- 콤마, 세미콜론, 공백등의 문자는 포함할수 없다.
- $ 로 시작할수 없다.

1.2 쿠키 생성하기
<%
Cookie cookie = new Cookie("cookieName", "cookieValue");
response.addCookie(cookie);
%>

<% cookie.getName() %> 쿠키의 값 = "<%=cookie.getValue() %>

-----결과물------
cookieName 쿠키의 값 = cookievalue

cookie클래스가 제공하는 메소드

getName() : 쿠키의 이름을 구한다.
getValue() : 쿠키의 값을 구한다.
setValue(String value) : 쿠키의 값을 지정한다.
setDoimain(String pattern): 이 쿠키가 전송될 서버의 도메인을 지정한다.
getDomain() : 쿠키의 도메인을 구한다.
setPath(String uri) : 쿠키를 전송할 경로를 지정한다.
getPath() : 쿠키의 전송 경로를 궇ㄴ다.
setMaxAge(int expiry) : 쿠키의 유효시간을 초단위로 지정한다. 음수를 입력할경우 웹 브라우저를 닫을때 쿠키가 함께 삭제된다.
getMaxAge() : 쿠키의 유효시간을 구한다.

1.3 쿠키 값 읽어오기
Cookie[] cookies = request.getCookies();

1.4 쿠키 값 변경 및 쿠키 삭제하기
Cookie cookie = new Cookie("name", URLEncoder.encode("새로운 값", "euc-kr"));
response.addCookie(cookie);


쿠키 삭제 -------------
Cookie cookie = newCookie(name, value);
cookie.setMaxAge(0);
response.addCookie(cookie);

1.5 쿠키의 도메인
Cookie cookie1 = newCookie("id", "starstory");
cookie1.setDomain(".starstory");
response.addCookie(cookie1);

1.6 쿠키의 경로
쿠키는 도메인 뿐만아니라 경로를 지정할 수도 있다.
Cookie cookie1 = newCookie("path1",URLEncoder.encode("경로:/enter", "euc-kr"));
cookie1.setPath("/enter");
respnse.addCookie(cookie1);
 
1.7 쿠키의 유효시간
쿠키는 유효시간을 갖고 이씅며 유효시간을 지정하지 않은 경우 웹 브라우저를 닫으면 쿠키는 자옫으로 삭제되며, 이후 웹 브라우저를 실행할때에 지워진 쿠키를 사용할수 없게 된다.
Cookie cookie = newCookie(name, value);
cookie.setMaxAge(60 *60); = 60초 * 60 = 1시간
response.addCookie(cookie);

1.8 쿠키와 헤더
쿠키는 응답 헤더 형태로 웹 브라우저에 전달되기 때문에 쿠키 역시 출력 버퍼가 플러시 된 이후에는 새롭게 추가 할수 없다. 따라서 쿠키의 추가 및 변경 작업은 반드시 출력버퍼가 플러시 되기 전에 처리해 주어야 한다.

02. 쿠리 처리를 위한 유틸리티 클래스
* 쿠키생성
 - Cookie클래스의 생성자를 사용하는 대신 CookieBox.createCookie()메서드를 사용하면 된다.
Cookie cookie1 = Cookiebox.createCookie("name","홍길동");
Cookie cookie2 = Cookiebox.createCookie("name","홍길동","path1",-1);
Cookie cookie3 = Cookiebox.createCookie("id","jsp",".starstory.net","/",60);

--------------------------------------CookieBox클래스를 사용하게 되면
Cookie cookie= new Cookie("id", URLEncoder.encode(value));
Cookie.setDomain(".starstory.net");
cookie.setPath("/");
cookie.setMaxAge(60);
---------------------------------------다음과 같은 코드를 사용하면 더 간결하게 쿠키를 추가 할수 있다.
response.addCookie(CookieUtil.createCookie(name, value));
response.addCookie(CookieUtil.createCookie("id","starstory","/chap09",-1));
---------------------- 한줄로 끝
2.2 CookieBox 클래스를 이용한 쿠키 읽기
//쿠키가 존재하는지 확인
if(cookieBox.exists("name")){
//Cookie 클래스로 사용할 경우 getCookie() 메서드 사ㅛㅇ
Cookie cookie = cookieBox.getCookie("name");
}
if(cookieBox.exists("id")){
//값만 사용할 경우 getValue() 메서드 사용
String value = cookieBox.getValue("name");
}

03. 쿠키를 사용한 로그인 유지
1. 로그인을 하면 관련 쿠키를 생성한다.
2. 관련쿠키가 존재하면 로그인한 상태라고 판단한다.
3. 로그아웃을 하면 고나련 쿠키를 삭제한다.

3.1 로그인 처리
------------login.jsp
<%
String id = request.getparameter("id");
String password = request.getParameter("password");

response.addcookie( CookieBox.createCookie("LOGIN","SUCCESS", "/", -1));
response.addCookie(CookieBox.createCookie("ID",id,"/",-1));
%>
3.2 로그인 판단여부
<%
boolean login = cookieBox.exists("LOGIN") && cookieBox.getvalue("LOGIN").equals("SUCCESS");
%>

<%= cookieBox.getValue("ID") %>"로 로그인 한 상태
3.3 로그아웃 처리
<% response.addCookie(CookieBox.createCookie("LOGIN","'""/",0));
<% response.addCookie(CookieBox.createCookie("ID","'""/",0));


:::쿠키생성:::
<%@ page contentType = "text/html; charset=euc-kr" %>
<%@ page import! = "java.net.URLEncoder" %>
<%
    Cookie cookie = new Cookie("name", URLEncoder.encode("최범균"));
    response.addCookie(cookie);
%>
<html>
<head><title>쿠키생성</title></head>
<body>

<%= cookie.getName() %> 쿠키의 값 = "<%= cookie.getValue() %>"

</body>
</html>

 

:::쿠키 뷰:::
<%@ page contentType = "text/html; charset=euc-kr" %>
<%@ page import! = "java.net.URLDecoder" %>
<html>
<head><title>쿠키목록</title></head>
<body>
쿠키 목록<br>
<%
    Cookie[] cookies = request.getCookies();
    if (cookies != null && cookies.length > 0) {
        for (int i = 0 ; i < cookies.length ; i++) {
%>
    <%= cookies[i].getName() %> =
    <%= URLDecoder.decode(cookies[i].getValue()) %><br>
<%
        }
    } else {
%>
쿠키가 존재하지 않습니다.
<%
    }
%>
</body>
</html>

 


:::쿠키값 변경:::
<%@ page contentType = "text/html; charset=euc-kr" %>
<%@ page import! = "java.net.URLEncoder" %>
<%
    Cookie[] cookies = request.getCookies();
    if (cookies != null && cookies.length > 0) {
        for (int i = 0 ; i < cookies.length ; i++) {
            if (cookies[i].getName().equals("name")) {
                Cookie cookie = new Cookie("name",
                         URLEncoder.encode("JSP프로그래밍"));
                response.addCookie(cookie);
                //cookies[i].setValue(URLEncoder.encode("자바와 JSP"));
                //response.addCookie(cookies[i]);
            }
        }
    }
%>
<html>
<head><title>값 변경</title></head>
<body>
name 쿠키의 값을 변경합니다.
</body>
</html>

 


:::쿠키 삭제:::
<%@ page contentType = "text/html; charset=euc-kr" %>
<%@ page import! = "java.net.URLEncoder" %>
<%
    Cookie[] cookies = request.getCookies();
    if (cookies != null && cookies.length > 0) {
        for (int i = 0 ; i < cookies.length ; i++) {
            if (cookies[i].getName().equals("name")) {
                Cookie cookie = new Cookie("name", "");
                cookie.setMaxAge(0);
                response.addCookie(cookie);
            }
        }
    }
%>
<html>
<head><title>쿠키 삭제</title></head>
<body>
name 쿠키를 삭제합니다.
</body>
</html>

 


:::쿠키의 도메인:::
<%@ page contentType = "text/html; charset=euc-kr" %>
<%@ page import! = "java.net.URLEncoder" %>
<%
    Cookie cookie1 = new Cookie("id", "madvirus");
    cookie1.setDomain(".madvirus.net");
    response.addCookie(cookie1);
   
    Cookie cookie2 = new Cookie("only", "onlycookie");
    response.addCookie(cookie2);

    Cookie cookie3 = new Cookie("invalid", "invalidcookie");
    cookie3.setDomain("javateam.korea.ac.kr");
    response.addCookie(cookie3);
%>
<html>
<head><title>쿠키생성</title></head>
<body>

다음과 같이 쿠키를 생성했습니다.<br>
<%= cookie1.getName() %>=<%= cookie1.getValue() %>
[<%= cookie1.getDomain() %>]
<br>
<%= cookie2.getName() %>=<%= cookie2.getValue() %>
[<%= cookie2.getDomain() %>]
<br>
<%= cookie3.getName() %>=<%= cookie3.getValue() %>
[<%= cookie3.getDomain() %>]

</body>
</html>

 

:::쿠키의 경로:::
<%@ page contentType = "text/html; charset=euc-kr" %>
<%@ page import! = "java.net.URLEncoder" %>
<%
    Cookie cookie1 = new Cookie("path1",
                     URLEncoder.encode("경로:/chap09/path1"));
    cookie1.setPath("/chap09/path1");
    response.addCookie(cookie1);
   
    Cookie cookie2 = new Cookie("path2",
                     URLEncoder.encode("경로:"));
    response.addCookie(cookie2);
   
    Cookie cookie3 = new Cookie("path3",
                     URLEncoder.encode("경로:/"));
    cookie3.setPath("/");
    response.addCookie(cookie3);

    Cookie cookie4 = new Cookie("path4",
                     URLEncoder.encode("경로:/chap09/path2"));
    cookie4.setPath("/chap09/path2");
    response.addCookie(cookie4);
%>

<html>
<head><title>쿠키 경로 지정</title></head>
<body>

다음과 같이 쿠키를 생성했습니다.<br>
<%= cookie1.getName() %>=<%= cookie1.getValue() %>
[<%= cookie1.getPath() %>]
<br>
<%= cookie2.getName() %>=<%= cookie2.getValue() %>
[<%= cookie2.getPath() %>]
<br>
<%= cookie3.getName() %>=<%= cookie3.getValue() %>
[<%= cookie3.getPath() %>]
<br>
<%= cookie4.getName() %>=<%= cookie4.getValue() %>
[<%= cookie4.getPath() %>]

</body>
</html>

 

:::쿠키의 유효시간 설정:::
<%@ page contentType = "text/html; charset=euc-kr" %>
<%
    Cookie cookie = new Cookie("oneh", "1time");
    cookie.setMaxAge(60 * 60); // 60초(1분) * 60 = 1시간
    response.addCookie(cookie);
%>
<html>
<head><title>쿠키유효시간설정</title></head>
<body>

유효시간이 1시간인 oneh 쿠키 생성.

</body>
</html>

 

 


:::쿠키생성클래스:::(.java)
//package jsp.util;

import! javax.servlet.http.HttpServletRequest;
import! javax.servlet.http.Cookie!
import! java.util.Map;
import! java.net.URLEncoder;
import! java.net.URLDecoder;
import! java.io.IOException;

public class CookieBox {
   
    private Map cookieMap = new java.util.HashMap();
   
    public CookieBox(HttpServletRequest request) {
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (int i = 0 ; i < cookies.length ; i++) {
                cookieMap.put(cookies[i].getName(), cookies[i]);
            }
        }
    }
   
    public static Cookie createCookie(String name, String value)
    throws IOException {
        return new Cookie(name, URLEncoder.encode(value, "euc-kr"));
    }

    public static Cookie createCookie(
            String name, String value, String path, int maxAge)
    throws IOException {
        Cookie cookie = new Cookie(name,
                                URLEncoder.encode(value, "euc-kr"));
        cookie.setPath(path);
        cookie.setMaxAge(maxAge);
        return cookie;
    }
   
    public static Cookie createCookie(
            String name, String value, 
            String domain, String path, int maxAge)
    throws IOException {
        Cookie cookie = new Cookie(name,
                                URLEncoder.encode(value, "euc-kr"));
        cookie.setDomain(domain);
        cookie.setPath(path);
        cookie.setMaxAge(maxAge);
        return cookie;
    }
   
    public Cookie getCookie(String name) {
        return (Cookie)cookieMap.get(name);
    }
   
    public String getValue(String name) throws IOException {
        Cookie cookie = (Cookie)cookieMap.get(name);
        if (cookie == null) return null;
        return URLDecoder.decode(cookie.getValue(), "euc-kr");
    }
   
    public boolean exists(String name) {
        return cookieMap.get(name) != null;
    }
}

 

 

:::클래스를 이용한 쿠키생성:::
<%@ page contentType = "text/html; charset=euc-kr" %>
<%@ page import! = "jsp.util.Cookie!Box" %>
<%
    response.addCookie(CookieBox.createCookie("name", "최범균"));
    response.addCookie(
        CookieBox.createCookie("id", "madvirus", "/chap09", -1));
%>
<html>
<head><title>CookieBox사용예</title></head>
<body>

CookieBox를 사용하여 쿠키 생성

</body>
</html>

 


:::클래스를 이용한 쿠키읽기:::
<%@ page contentType = "text/html; charset=euc-kr" %>
<%@ page import! = "jsp.util.Cookie!Box" %>
<%
    CookieBox cookieBox = new CookieBox(request);
%>
<html>
<head><title>Cookie 사용</title></head>
<body>

name 쿠키 = <%= cookieBox.getValue("name") %> <br>
<%  if (cookieBox.exists("id")) { %>
id 쿠키 = <%= cookieBox.getValue("id") %> <br>
<%  }  %>
</body>
</html>

 


:::로그인폼:::
<%@ page contentType = "text/html; charset=euc-kr" %>
<html>
<head><title>로그인폼</title></head>
<body>

<form action="<%= request.getContextPath() %>/member/login.jsp"
      method="post">
아이디 <input type="text" name="id" size="10">
암호 <input type="password" name="password" size="10">
<input type="submit" value="로그인">
</form>

</body>
</html>

 

:::로그인:::
<%@ page contentType = "text/html; charset=euc-kr" %>
<%@ page import! = "jsp.util.Cookie!Box" %>
<%
    String id = request.getParameter("id");
    String password = request.getParameter("password");
   
    if (id.equals(password)) {
        // ID와 암호가 같으면 로그인에 성공한 것으로 판단.
        response.addCookie(
            CookieBox.createCookie("LOGIN", "SUCCESS", "/", -1)
        );
        response.addCookie(
            CookieBox.createCookie("ID", id, "/", -1)
        );
%>
<html>
<head><title>로그인성공</title></head>
<body>

로그인에 성공했습니다.

</body>
</html>
<%
    } else { // 로그인 실패시
%>
<script>
alert!("로그인에 실패하였습니다.");
history.go(-1);
</script>
<%
    }
%>

 


:::로그아웃:::
<%@ page contentType = "text/html; charset=euc-kr" %>
<%@ page import! = "jsp.util.Cookie!Box" %>
<%
    response.addCookie(
        CookieBox.createCookie("LOGIN", "", "/", 0)
    );
    response.addCookie(
        CookieBox.createCookie("ID", "", "/", 0)
    );
%>
<html>
<head><title>로그아웃</title></head>
<body>

로그아웃하였습니다.

</body>
</html>

저작자 표시
Trackback 0 Comment 0