안녕하세요

프로그램 과정에서 막혔던 문제들에 대한 해결책 정리


페이지 목록

레이블이 Servlet인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Servlet인 게시물을 표시합니다. 모든 게시물 표시

2011년 8월 14일 일요일

서버와 클라이언트

 서버 - 클라이언트로부터 요청을 받아, 요청한 것을 넘겨 줌, 사용자가 웹 브라우져를 통해 서버에 자원을 요청하면 그 요청에 맞는 자료를 넘겨주는 역할
 클라이언트 - 서버에 자료를 요청하고 요청한 자료가 도착하면 사용자에게 그 내용을 보여주는 역할
 둘 사이의 의사소통을 위해 HTML과 HTTP가 필요하다.
 HTML => 브라우져가 서버의 전달사항을 어떤 식으로 보여줘야 하는 지 알려주는 Language
 HTTP => 클라이언트와 서버간에 대화하기 위해 만들어진 규약
 보통 클라이언트가 요청하면 서버에서 응답을 보내주는 형식으로 짜여 있다.

 클라이언트에서 HTTP를 이용해 자원을 요청하면 서버는 그 요청에 맞는 자료를 HTTP에 HTML을 실어 전송한다. 그러면 Browser는 HTML을 해독하여 사용자에게 보여준다.
 HTTP 요청에는 HTTP Method가 들어 있다.
 HTTP Method 중 가장 중요하고 자주 사용 되는 것은 Get 과 Post 이다.
 Get의 경우 자료를 요청할 때 자주 쓰인다. 단순하게 자료를 받아 오는 것이기에 멱등 - 즉 같은 동작을 여러번 반복해도 문제가 생기지 않는다.
 Post의 경우 서버에 자료를 요청할 때 사용자가 몇 가지 정보를 함께 제출하여 그 정보에 따라 응답을 받을 수 있다.
 사실 Get으로도 정보를 보낼 수 있지만 그 정보가 URL 뒤에 붙어서 나오기에 보낼 수 있는 양이 한계가 있고 URL 창에 정보가 노출되어 보안상 중요한 내용을 보내기에 적합하지 못하다. 그리고 Get으로 보내는 요청은 URL 뒤에 붙어 나오기에 즐겨찾기에 추가 할 수 있다.

 HTTP 응답은 Header와 Body로 구성되어 있다.
 Header => 사용된 프로토콜, 보내준 요청이 성공했는지, 몸체에 포함 된 컨텐츠 종류가 무엇인지 등...
Body => HTML과 같은 컨텐츠

 사실 웹서버는 정적인 정보만을 제공할 수 있다. 그렇기에 웹 서버에 동적인 서비스를 제공하기 위해서는 같은 컴퓨터에 있는 다른 App들의 도움이 필요하다. 이러한 App들을 CGI라 한다.

 그리고 이러한 서블릿을 원할하게 돌아가기 위해서는 많은 도움이 필요하다. 서블릿 클래스 생성과 로드 그리고 스레드 관리 등 많은 일들을 해야 한다. 이와 같은 일을 하기 위해서 컨테이너가 생겼다. Tomcat도 이러한 컨테이너의 일종이다.

2011년 8월 3일 수요일

Servlet EL 함수

 1. 정적인 공용 메소드를 제공하는 클래스를 먼저 작성
 일반적인 자바 클래스 but Method는 반드시 public static 으로
 인자는 있어도 무방 but 리턴 타입이 void면 곤란
 작성 후 /WEB-INF/classes 디렉토리에 .class 파일을 옮길 것
 2. 태그 라이브러리 서술자 파일
  TLD( Tag Library Descriptor) 란 파일로 함수를 정의한 자바 클래스와 이를 호출할 JSP 매핑
 3. JSP에 taglib 지시자를 코딩
  지금 JSP에서 이 TLD를 쓸 건데 다른 것하고 헛갈릴 수 있으니 앞첨자 (prefix)를 붙이고 싶네
 4. 함수를 호출하는 EL 작성
 ${prefix:name()}

 EL 연산자들
 더하기: + // 뺴기 : - // 곱하기 * // 나누기 / 와 div // 나머지 % 와 mod
 논리 연산자 :
 AND : && 와 and // OR || 와 or // NOT : ! 와 not
 관계 연산자 :
 등호 == 와 eq // 부등호 != 와 ne // ~보다 작다 < 와 lt // ~보다 크다 > 와 gt // ~ 보다 작거나 같다 : <= 와 le // ~보다 크거나 같다 >= 와 ge

 EL은 널(null)을 아주 자연스럽게 처리
 산술 연산에서 EL은 널을 "0"으로
 논리연산에서 EL은 널을 "거짓 (false)"로 처리

Servlet Action(서블릿 액션)

 표준 액션  <jsp:include page = "wickedFooter.jsp"/>
 기타 액션: <c:set var = "rate" value "32" />

 스크립트가 없는 JSP
 빈 관련 표준 액션
 <jsp:useBean> 실제 객체를 선언하고 초기화하는 태크
 <jsp:useBean id="person" class = "foo.Person" scope = "request"/>
 id = 빈 객체 식별자 선언
 class = 클래스 타입 선언
 scope = 빈 객체 속성 생존 범위
 <jsp:getProperty name = "person" property = "name" />
 name = 빈객체 이름
 property = 프로퍼티 이름을 적음

 <jsp:useBean>은 객체 생성도 함
 <jsp:setProperty name = "person" property = "name" value = "Fred"/>
 <jsp:useBean id = "person" type = "foo.Person" class = "foo.Employee" scope = "page">
 class 없이 type만 쓸 경우, 빈이 먼저 존재해야 함
 type 이 있든 없든 관계없이 class가 있을 경우 이 클래스는 추상 객체여서는 안되며 반드시 인자가 없는 public 생성자가 있어야 함
 scope 속성의 default 값은 "page"

 서블릿을 거치지 않고 JSP로 바로 요청을 날리면,
 <%person.setName(request.getParaeter("userName"));%>
 표준 액션 안에 스크립팅
 <jsp:setProperty name = "person" property = "name" value = "<%= request.getParameter("userName") %>%>
 param 속성으로 요청 파라미터 값을 빈 프로퍼티에 곧바로 설정가능

 여기서 value 대신 param = "userName" 을 쓸 수도 있다.

 이 보다 더 나은 방식으로는 폼 입력 필드 이름이 빈 프로퍼티 이름과 같으면 param 속성이 없어도 동작한다.

 빈의 모든 프로퍼티 이름과 요청 파라미터 이름이 같을 때
 예) Param 빈에 두개의 프로퍼티 (name, empID) 가 있을때
 <jsp:setProperty name = "person" property = "*" />
 빈 태그는 기본 타입 프로퍼티를 자동으로 변환
 프로퍼티가 String 기본형도 아닌 경우
 EL을 사용
 ${person.dog.name}
 [] 연산자는 도트 연산자 보다 막강
 ${person["name"]} = ${param.name}

 []연산자는 맵, 빈, 리스트, 배열 사용가능
 오른쪽에 있는 값이 인덱스 값 즉 숫자가 될 수 있으며, 자바 명명 규칙을 따르지 않는 것도 올 수 있음
 예) 문자열과 도트를 가지는 다음과 같은 값 "coo.foo.trouble" 도 맵의 키가 될 수 있다.
 [] 연산자 안의 값이 문자열(따옴표로 묶여 있다면) 이라면, 이것은 맵키가 될 수 있고, 빈 프로퍼티 또는 리스트나 배열 인덱스가 될 수 있다.

 배열에 [] 연산자 사용하기
EL의 [] 연산자는 그냥 [] 연산자일 뿐 자바와 상관관계가 없다.
 문자열(String)이아니면, 이게 뭘까 하고 실행(평가)
 맵 키 값이면 맵의 값을 가져 옴
 request.setAttribute("Genre", "Ambient");
 Music is ${musicMap[Genre]} => Music is ${musicMap["Ambient"]}
 
 [] 안에 내장 표현식을 쓸 수 있다.
 ${musicMap[MusicType[0]]}
 ${musicMap["Ambient"]}

 EL에서 요청 파라미터
 ${param.name}
 ${param.empID}
 ${paramValues.food[0]}

Request에서 파라미터 이상의 정보를 원할 때
 "host" 헤더 정보 읽기
 Host is : ${header["host"]} = ${header.host}

 requestScope은 request 정보 (property)가 아닌 request 속성을 가져 오기 위해 사용. request 정보 pageContext를 통해서 접근
 ${pageContext.request.method}
 생존 범위 관련 내장 객체가 도움이 될 때

 한 군데 이상 똑같은 이름으로 몰려 있을지도 모르는 경우
${requestScope.person.name}
 속성 이름이 문자열인 경우
 request.setAttribute("foo.person",p);
 -> ${requestScope["foo.person"].name}

2011년 8월 2일 화요일

PageContext로 속성 접근하기

 pageContext는 자신이 설정되어 있는 page 범위 속성 뿐만 아니라 어떤 다른 생존 범위 속성도 접근할 수 있을 정도로 매우 막강
 pageContext를 이용하여 속성을 읽고, 설정하는 예제

  •  page 생존 범위의 속성 세팅하기

 <%Float one = new Float(42.5);%>
 <% pageContext.setAttribute("foo",one);%>

  •  page 생존 범위의 속성 읽기

 <%= pageContext.getAttribute("foo")%>

  •  pageContext를 이용하여 session 생존 범위 속성 세팅하기

 <%Float two = new Float(22.4);%>
 <%pageContext.setAttribute("foo",two, PageContext.SESSION_SCOPE);%>

  • pageContext를 이용하여 session 생존 범위 속성 읽기

 <%=pageContext.getAttribute("foo", PageContext.SESSION_SCOPE)%>

  •  pageContext를 이용하여 application 생존 범위 속성 읽기

 <%= pageContext.getAttribute("mail",PageContext.APPLICATION_SCOPE)%>
 = <%= application.getAttribute("mail")%>


  •  pageContext를 이용하여 어떤 생존범위인지 모르는 속성 찾기 

<%= pageContext.findAttribute("foo")%>

 3가지 지시자
 1. page 지시자
 <%@page import = "foo.*" session = "false" %>
 2. taglib 지시자
 <%@taglib tagdir = "/WEB-INF/tags/cool" prefix = "cool"%>
 3. include 지시자
<%@ include file = "wickedHeader.html" %>

JSP 사용

 JSP 도 Servlet으로 변환된다.
 JSP 안에서 자바 코드를 <%.... %> 태그 안에 스크립틀릿으로 작성
 <%@ page import = "foo.*" %>

JSP 초기화 하기
 서블릿 초기화 파라미터 설정하기
 jspInit() 재정의하기
jspInit() 메소드를 JSP 파일에 코딩 => 컨테이너가 서블릿 인생 시작 시에 이 메소드를 호출

Servlet 세션 관리

 대화 상태 유지 하기
 Session에 정보 저장 => 클라이언트 구별을 위해 유일한 세션 ID가 필요
 세션 ID 쿠키 사용 => 컨테이너가 알아서 관리
 쿠키 사용을 못할 시 => URL 재작성
 response의 URL 인코딩 => response.encodeURL("/BeerTest.do");
 사용자로부터 들어 온 요청을 다른 서블릿이나 JSP로 보내고 싶은데 세션은 계속해서 유지하고 싶을 떄
 response.encodeRedirectURL("/BeerTest.do")
 세션 제거 하기
HttpSession 메소드
세션 타임 아웃 설정하기

  •   시간이 다 되어서
  •   개발자가 세션 객체에 invalidate() 메소드 실행
  •   App 다운
 쿠키 사용의 또 다른 방법 => 쿠키는 서버와 클라이언트 간에 교환하는 조그마한 데이터 
 서블릿 API로 쿠키 사용하기
 
 세션 이동
 오직 HttpSession 객체와 그 속성 만이 하나의 VM에서 다른 VM으로 옮겨 감
 HttpSession은 웹 애플리캐이션 당 하나의 세션 ID당 하나 밖에 없음 얼마나 많은 VM이 분산환경에서 돌아가든지 상관 없음

실제 세션 이동 HttpSession만 이동한다
 HttpSessionActivationListener 는 속성을 옮김

Servlet 속성(Attribute)란?

 ServletContext, HttpServletRequest, HttpSession 객체 중 하나에 설정해 놓는 객체
 Context, Request, Session
 Context 생존 범위는 스레드-안전 하지 못하다
 세션 속성 역시 스레드 - 안전 하지 못하다.

 가능한 방법은 ServletContext나 httpSession 등에 Synchronized를 거는 방법이 있다.

Servlet Listener( 서블렛 리스너)

 ServletContextListener => ServletContext 초기화와 소멸에 귀를 기울임
 Context 초기화(App 배포)를 알아차림
 ServletContext로부터 Context 초기화 파라미터를 읽음
 데이터 베이스 연결을 위해 초기화 파라미터 검색명 사용
 데이터베이스 Connection 객체를 속성에 저장

 HttpSessionBindingListener -> 속성 자신이 세션에 속성으로 추가, 제거 되는 지
 HttpSessionAttributeListener -> 세션에 어떤 속성이라도 속성이 추가, 제거, 수정 되는 이벤트가 발생하는지

ServletConfig() Method

 컨테이너가 서블릿을 초기화 할 때, 서블릿 마다 하나씩 ServletConfig 생성
 Container는 DD에서 서블릿 초기화 파라미터를 읽어, 이 정보를 ServletConfig로 넘겨줌. 그 다음 ServletConfig를 서블릿의 init() method에 제공 컨테이너가 서블릿을 만들 때 DD를 읽어 이름/값의 쌍으로 ServletConfig를 생성

 ServletConfig -> init-param
 JSP에서 서블릿 초기화 파라미터 접근 하는 법은?
 <context-param>
 ServletContext로 할 수 있는 일은?
 컨텍스트 파라미터에는 String 밖에 저장이 안 됨
 초기화 파라미터로 데이터베이스 dataSource 객체를 저장하고 싶을 경우 => Data source 검색명(look up name)을 저장 => 그 후 String 검색명을 실제 DataSource 객체로 바꾸면 됨

Servlet Request & Response (서블릿 요청 응답)

 service()의 인자이자 가장 중요한 것
 Request => 쿠키, 헤더, 세션 등 HTTP에 관련된 것들을 서비스, HTTP 프로토콜에 관련 된 Method 추가, 서블릿이 클라이언트, 브라우져와 대화하기 위한 것
 Response => HTTP에 관련 된 오류, 쿠키, 헤더 정보에 대한 메소드
 HttpServlet Request와 HttpServletResponse는 Container가 구축

 Http 요청 메소드는 doGet() or doPost() 결정

Servlet 로딩과 초기화 (Servlet loading & initailize)

 컨테이너가 서블릿 파일을 찾아서 로딩 시 시작 => 컨테이너 시작 시(톰캣) 이루어 진다.
 생성자의 실행 성성자 : '존재하지 않음' -> '초기화 됨'
 객체를 만드는 것이지 서블릿을 만드는 것이 아니다.

 1. ServletConfig 객체
 서블릿 당 하나
 서블릿 배포시 설정 된 정보를 서블릿으로 넘겨주기 위해
 ServletContext 접근
 파라미터값은 배포서술자에서 설정 가능

 2. ServletContext
 Application 당 하나
 웹 App의 파라미터 정보를 읽음 (DD 안에 설정 된 정보들)
 App용 게시판
 서버 정보 파악
 Servlet 의 임무 => 요청 핸들링

JSP Fragment

 JSP Code를 나타내는 객체, 스크립팅 사용 불가
 객체 => 다른 도우미 객체로 넘길수 있고 JSpFragment의 메소드 (getJspContent()) 를 호출해서 필요한 정보를 읽을 수 있음 => 이를 통해 속성 정보 및 다른 객체 정보에 접근 가능
 JSP Fragment가 하는 작업 => 응답에 태그 몸체 내용 출력
 getContents()나 getBody() 같은 메소드는 없다.

 몸체
 invoke() method는 인자로 java.io.write를 받는다.

태그 파일

 include 처럼 행동하지만 좀 더 개선된 방식
 <myTags: Header/> => 태그 이름이 바로 파일 이름
 태그 파일에서는 요청 파라미터를 사용하지 않고 태그 속성으로 정보를 넘김
 속성으로 넘겨야 할 값이 많을 경우
 한문장 정도 크기 일 때
 태그 파일에 쓸 body-content 정의 =-> tag 지시자 사용
 <body-content>=> TLD 파일 <tag>의 하위 항목 필수
태그 파일 => 정의하지 않으면 디폴트인 scriptless가 설정

 태그 파일에서는 스크립팅이 가능하지만 태그 파일을 호출하는 JSP에서 태그 몸체에 스크립팅 사용 불가
 커스텀 태그 핸들러 : classic, simple

 자바 코드를 출력하기 위해

 몸체가 있는 심플 태그
 body를 사용하기 위해 => getJspBody().invoke(null);

Servlet 오류 페이지

<%@ page isErrorPage = "true"%>
<%@ page errorPage = "errorPage.jsp"%>

DD <error-page> tag
 <exception-type> 이나 또는 HTTP 상태 <error-page>

 defalut error page
 <error-page>
 <exception-type>java.lang.Throwable</exception-type>
 <location> /errorPage.jsp</location>
 </error-pgage>

 특정 예외 사항에 대한 오류 페이지
 <error-page>
 <exception-type> java.lang.ArithmeticException</exception-type>
 <location>/arithmeticError.jsp</location>
 </error-page>

 <c:catch>

 예외 사항이 실제 발생시 Exception 객체에 접근하는 방법은?
 실제 오류 페이지도 아니고 일반 JSP 라서 내장 객체인 exception을 쓸 수도 없다.

 Exception을 속성으로 만든다.

 <c:catch> 문 뒤에 Exception 객체를 다루고 싶으면 옵션 속성인 var를 사용

 <c:catch var = "myException">

 <c:catch> 자바의 catch 문이 아닌 try 문처럼 행동

2011년 7월 22일 금요일

세션 제거하기

 시간을 체크한다.

 세션 종료의 세가지 이유
 1) 시간이 다 되어서 (타임 아웃)
 2) 개발자가 세션 객체에 Invalidate() 메소드를 실행
 3) App이 다운되는 경우( 문제가 생겨 다운되거나, 언디플로이(undeploy) 되는 경우)

쿠키(Cookie)

 쿠키는 Header 중 하나이다.
 Container에서 거의 모든 Cookie 관련 작업을 수행한다.

 Response 객체에 세션 Cookie 보내는 방법
 HttpSession session = request.getSession();

 Request 객체로부터 세션 ID 가져오기
 HttpSession session = request.getSession();

session.isNew() - 세션이 새로 만들어졌는지 아닌지 확인

 URL 재작성 => response.encodeURL( " blur blur ");

 쿠키 => URL 재작성

 정적인 페이지는 URL 재작성이 불가 하다.

컨테이너에서 클라이언트를 구분 하는 방법

 Client는 유일한 Session ID가 필요하다. 그리고 쿠키를 사용해서 Client와 Container는 이 Session ID를 공유한다.

속성(Attribute)란?

 3개의 Servlet API 객체 (ServletContext, HttpServletRequest 또는
ServletRequest),HttpSession 객체 중 하나에 설정해 놓는 객체(Binding)

ServletContext를 리턴 받는 두 가지 방법

 1) getServletConfig().getServletContext().getInitParameter();
 2) this.getServletContext().getInitParamete()
 1) 번의 경우 HTTPServlet 이나 GenericServlet을 상속 받지 않는다.

ServletConfig

 ServletConfig의 역할 => 초기화 Parameter에 접금
 ServletContext 리턴하는 메소드 제공 -> Context 정보 (Servlet 설
정 정보)를 가짐
 웹 App의 다른 Component 와 공유할 경우 => Request 객체를 통
해 보냄. -> 그리 좋은 방법은 아니다.