2010/07/28 10:23

tomcat 6 에서 GET 방식으로 파라메터 값을 읽어올 때 사용하는 캐릭터 셋의 기본 값은 ISO-8859-1 이다. 톰캣 6 에서는 두 가지 방법을 이용해서 GET 방식으로 전달된 파라미터를 읽을 때 사용할 캐릭터 셋을 지정할 수 있다.


- server.xml 파일에서 <Connector> 의 URIEncoding 속성의 값으로 원하는 캐릭터셋을 지정하는 방법


- server.xml 파일에서 <Connector> 의 useBodyEncodingForURI 의 속성 값을 true 로 지정하는 방법. 이 때는 request.serCharacterEncoding() 메소드로 지정한 캐릭터셋이 적용됨.



이 두개를 같이 사용할 수 도 있다

Posted by 개발자 용이~
2009/04/07 18:50
Filter

클라이언트가 요청을하고 난 후 서블릿이 요청을 받기전~ 필터를 거칠수 있습니다(Request Filter). 또는 반대로 서블릿이 브라우저로 응답을 하기전 클라이언트가 응답을 받기전에도 필터를 거칠 수 있습니다. 
예를 들어 request에 한글인코딩을 적용할 때 매번 페이지나 서블릿에서 작업을 하지 않고 Request 필터에 등록을 하기만 하면 서블릿에서는 이 인코딩 작업이 필요가 없다는 것이죠.

용도

Request 필터
- 보안 관련 체크
- 요청정보를 로그파일로 작성
- 인코딩 작업
Response 필터
- 응답결과를 압축
- 응답결과에 내용추가/수정
- 총 서비스 시간 측정

사용방법
- java.servlet.Filter구현합니다.
- destroy(), doFilter(), init() 메소드를 반드시 구현합니다. (Filter가 인터페이스입니다.)
- DD에 등록을 해줍니다.

예제 - Request필터로 UTF-8f 로 인코딩을 합니다.
Filter의 구현

import java.io.*;

import java.util.*;

import javax.servlet.*;

import javax.servlet.http.*;


public class CharsetFilter implements Filter {

  private String encoding;


  public void init(FilterConfig config) throws ServletException {

    encoding = config.getInitParameter("requestEncoding");


    if (encoding == null)

      encoding = "UTF-8";

  }


  public void doFilter(ServletRequest request, ServletResponse response,

      FilterChain chain) throws IOException, ServletException {

    // Respect the client-specified character encoding

    // (see HTTP specification section 3.4.1)

    if (null == request.getCharacterEncoding())

      request.setCharacterEncoding(encoding);


    chain.doFilter(request, response);

  }


  public void destroy() {

  }


DD에 등록

...
...
  <!--CharsetFilter start--> 

  <filter>

    <filter-name>Charset Filter</filter-name>

    <filter-class>filter.CharsetFilter</filter-class>

      <init-param>

        <param-name>requestEncoding</param-name>

        <param-value>UTF-8</param-value>

      </init-param>

  </filter>


  <filter-mapping>

    <filter-name>Charset Filter</filter-name>

    <url-pattern>/*</url-pattern>

  </filter-mapping>

  <!--CharsetFilter end-->

...

...


위와같이 해주면 모든 request에  UTF-8 인코딩이 적용됩니다.
Posted by 개발자 용이~
2009/04/07 18:00

속성


속성은 3개의 서블릿 API객체 즉, ServletContext, HttpServletRequest(또는 ServletRequest), HttpSession 객체중 하나에 설정해 놓는(바인당한(binding)) 객체를 말합니다.


setAttribute(String name, Object value)로 바인딩하고

getAttribute(String name)으로 속성을 얻습니다.



속성의 생존범위 (Scope)


 Scope API  속성의 Scope 
 Application Scope ServletContext  속성은 컨테이너와  동일한 Scope를 갖는다.
 Session Scope HttpSession  속성은 브라우저(동일)와 동일한 Scope를 갖는다. 
 Request Scope HttpServletRequest  속성은 요청/응답 싸이클과 동일한 Scope를 갖는다. 


Thread-safe문제


synchronized 로 동기화를 하지맙시다.

단지 Request속성지역변수만이 쓰레드 안전합니다.

Posted by 개발자 용이~
2009/04/07 14:05
Session Tracking이란?

서블릿이나 JSP로 작성된 웹 페이지들간의 클라이언트 상태유지를 위해 사용되는 기술을 의미하며 서로 관련이 없던 페이지들 간에 연관성을 설정하는 방법입니다.

 HTTP프로토콜은 클라이언트와 서버간 요청과 응답이 실행되면 연결이 종료됩니다. 전페이지에서 수행했던 작업을 다른 페이지에서 인식할 수 없는데 이를 해결하기위한 방법이 Session Tracking입니다.



Session Tracking 방법


- HTML hidden태그 사용하기

- get방식을 이용한 URL파라미터 이용

- 쿠키 이용

- 세션 이용


위의 방법중에 쿠키와 세션에 대해서 알아보겠습니다. 쿠키와 세션의 가장큰 차이점으로는 쿠키는 클라이언트에 저장, 세션은 서버에 저장되는 것입니다.


쿠키

HTTP한계를 극복할 수 있도록 웹사이트의 방문기록을 클라이언트에 저장하여 사용자와 웹사이트를 매개해주는 정보.

특징

- 정보가 클라이언트에 저장됨.

- 용량에 제한이 있음 (도메인당 20개씩 총 300개, 파일 용량은 4kb)

- 보안이 취약함

- 클라이언트에 의해서 사용유무가 결정됨

- 도메인당 쿠키가 생성됨


용도

- 사이트의 고객 맞춤 정보제공(타깃 마케팅)

- 로그인시 'ID저장' 기능

- 팝업창에서 '오늘은 더 이상 창 열지 않기' 구현 등



java.servlet.http.Cookie를 이용합니다.


예제소스 (주요 메소드는 굵게 표시됨. 설명은 주석 보기)
<cookieform.jsp>

<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>Insert title here</title>

</head>

<body>

<form method="post" action="cookieTest.do">

<input name="username" type="text"/>

<input type="submit" value="클릭하삼"/>

</form>


</body>

</html>


<CookieTest.java>

import javax.servlet.*;

import javax.servlet.http.*;

import java.io.*;

import java.net.URLEncoder;


public class CookieTest extends HttpServlet {

  @Override

  public void doPost(HttpServletRequest request, HttpServletResponse response)

      throws IOException, ServletException {

    response.setContentType("text/html");

    String name = request.getParameter("username");


    Cookie cookie = new Cookie("username", name); // 생성자는 "이름/값" 쌍을 인자로 받습니다.

    // 이건 한글 쿠키 입력시

    // Cookie cookie = new Cookie("username", URLEncoder.encode(name, "utf-8"));


    cookie.setMaxAge(30 * 60); // 30분 동안 살아있게 함

    response.addCookie(cookie);


    RequestDispatcher view = request.getRequestDispatcher("cookieresult.jsp");

    view.forward(request, response);

  }

}


<cookieresult.jsp>

<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>Insert title here</title>

</head>

<body>

  <a href="cookieCookie.do">click here</a>

</body>

</html>


<CheckCookie.java>

import java.io.IOException;

import java.io.PrintWriter;

import java.net.URLDecoder;

import java.util.Enumeration;


import javax.servlet.*;

import javax.servlet.http.*;


public class CheckCookie extends HttpServlet {

  @Override

  public void doGet(HttpServletRequest request, HttpServletResponse response)

      throws IOException, ServletException {

    response.setContentType("text/html;charset=utf-8");

    PrintWriter out = response.getWriter();


    // 헤더 정보 찍어보기

    Enumeration enu = request.getHeaderNames();

    while (enu.hasMoreElements()) {

      String key = (String) enu.nextElement();

      System.out.println(key + " " + request.getHeader(key));

    }


    Cookie[] cookies = request.getCookies(); // Reqeust에서 쿠키들을 읽기


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

      Cookie cookie = cookies[i];

      if (cookie.getName().equals("username")) {

        String userName = cookie.getValue();

        // 이건 한글 쿠키 입력시

        //String userName = URLDecoder.decode(cookie.getValue(), "utf-8");

        out.println("Hello " + userName);

        break;

      }

    }

  }

}


<web.xml>

...
  <servlet>

    <servlet-name>CookieTest</servlet-name>

    <servlet-class>ch06.CookieTest</servlet-class>

  </servlet>

  

  <servlet-mapping>

    <servlet-name>CookieTest</servlet-name>

    <url-pattern>/ch06/cookieTest.do</url-pattern>    

  </servlet-mapping>

  

    <servlet>

    <servlet-name>CheckCookie</servlet-name>

    <servlet-class>ch06.CheckCookie</servlet-class>

  </servlet>

  

  <servlet-mapping>

    <servlet-name>CheckCookie</servlet-name>

    <url-pattern>/ch06/cookieCookie.do</url-pattern>    

  </servlet-mapping>

...


setMaxAge메소드

- 인자값으로 음수를 지정하거나 setMaxAge 메소드를 사용하지 않으면 Session쿠키로 저장.

- 양수값을 지정하면 Persistence쿠키로 저장되며 지정값 만큼만 쿠키가 유효.


※ Persistence쿠키 - 파일로 저장됨.



세션

HTTP한계를 극복할 수 있도록 웹사이트의 방문기록을 서버에 저장하여 사용자와 웹사이트를 매개해 주는 정보


특징

- 정보가 서버에 저장된다.

- 세션구현은 쿠키를 이용한다.

- 쿠키보다 보안에 유리하다.

- 서버에 부담이 될수 있다.

- 브라우저당 유일한 세션(세션id)이 하나씩 생긴다.

- 서버에 저장된 정보는 유효시간을 갖는다. 기본적으로 30분(1800초)동안 유효하다.


용도

- 로그인 기능 구현

- 쇼핑몰의 장바구니 구현



java.servlet.http.HttpSession을 이용합니다.


생성과 사용


- 세션생성과 생성된 세션을 사용하는 메소드가 동일합니다.

- getSession메소드를 이용합니다.

getSession() : 세션이 있으면 리턴하고 없으면 새로 생성해서 리턴한다.

getSession(true) : 세션이 있으면 리턴하고 없으면 새로 생성해서 리턴한다.

getSession(flase) : 세션이 있으면 리턴하고 없으면 null을 리턴한다.


세션생성 메소드의 예

  @Override

  public void doGet(HttpServletRequest request, HttpServletResponse response)

      throws IOException {


    response.setContentType("text/html;charset=UTF-8");

    PrintWriter out = response.getWriter();

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

    String id = request.getParameter("id");

    String pass = request.getParameter("pass");

    HttpSession session = request.getSession();


    if (session.isNew()) {

      session.setAttribute("login.name", name);

      session.setAttribute("login.id", id);

      session.setAttribute("login.pass", pass);

    }

  }


세션 사용의 예

  @Override

  public void doGet(HttpServletRequest request, HttpServletResponse response)

      throws IOException {


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

    PrintWriter out = response.getWriter();


    String name = "";

    String id = "";

    String pass = "";


    HttpSession session = request.getSession(false);

    if (session != null) {

      name = (String) session.getAttribute("login.name");

      id = (String) session.getAttribute("login.id");

      pass = (String) session.getAttribute("login.pass");

    } else { // 세션이 없으면 리다이렉트한다. 로그인에 쓰이면 좋은..

      response.sendRedirect("loginSession.html"); 

    }

  }



클라이언트에서 쿠키를 제한한다면~ 


세션처리도 쿠키를 이용하기 때문에 브라우저에서 쿠키사용을 제한하면 세션처리가 불가능합니다. 이럴 때

URL재작성(URL Rewriting)을 하면됩니다. 

- response.encodeURL()메소드 이용.
위의 메소드는 인위적으로 jsessionid 값을 생성하여 서버에 전달 됨.
예)

out.println("<a href=\"" + response.encodeURL("/BeerTest.do") + " >");



사용자로부터 들어온 요청을 다른 서블릿이나 JSP로 보내고(redirect)싶을 때는 밑의 메소드를 사용합니다.

response.encodeRedirectURL("/BeerTest.do");




세션종료


로그아웃 같은 기능으로 세션을 종료할 경우에는 invalidate() 메소드를 사용합니다.

Posted by 개발자 용이~
2009/04/02 07:10

Forword


정의 

- 특정 서블릿에 대한 요청을 다른 서블릿이나 jsp로 요청을 넘겨주는 작업을 의미함.


용도

- 요청에 대한 처리작업을 분산시킬 목적으로 사용되며 이 경우 하나의 요청을 여러 서블릿(또는 jsp)이 공유할 수 있습니다.

- MVC모델의 Controller에서 View로 요청을 넘길 때 사용됩니다.


방법 

- redirect와 dispatche로 나눌수 있습니다.



redirect

response.sendRedirect("list.jsp");

- 특정 서블릿이 포워드 할때 클라이언트(이용자의 브라우저죠.)에서 재요청이 됩니다. 따라서 URL이 포워드 될 곳으로 재설정 됩니다.

- 추가적인 재요청으로 인해 dispatche 방법보다 성능이 떨어집니다.

- 요청시 바인딩된 데이터가 지속되지 못합니다.


dispatche

RequestDispatcher dis = request.getRequestDispatcher("list.jsp");

dis.forward(request, response);

- 특정 서블릿이 포워드 할 때 컨테이너에서 재요청이 됩니다. 따라서 URL이 재설정 되지 않습니다.

- 클라이언트에서는 포워드 발생 여부를 인지 할 수 없습니다.

- 요청시 바인딩된 데이터가 지속됩니다.

- Struts 프레임워크에서는 기본적으로 dispatche방법으로 구현.



바인딩(Binding)

실행시 필요한 자원을 컨테이너가 인식할 수 있도록 등록하는 작업을 말하며 등록된 자원은 서블릿이나 JSP에서 사용할 수 있습니다.


용도

- 모듈화된 컴포넌트간의 자원공유가 필요로 할 때 사용이 됩니다.

- MVC모델에서 Model과 View컴포넌트간에 자원 공유시 사용됩니다.


메소드~

- setAttribute(String name, Object obj)

- getAttribute(String name)

- removeAttribute(String name)


request.setAttribute("styles", brands);

RequestDispatcher view = request.getRequestDispatcher("result.jsp");

view.forward(request, response);


Posted by 개발자 용이~
2009/04/02 06:50
이번에는 클라이언트의 요청을 얻어서 응답하는 법을 알아보겠습니다.
크게 get, post로 요청을 받게되는데 이는 html에서 <form>태그 내의 속성에서 정해줄수있습니다.

일단 form태그의 속성에 대해서 알아보면
 속성 설명 
 name 폼태그의 이름을 명시. 여러개의 폼이 존재 할 때 name으로 구분한다.
 method 폼데이터를 처리할 동작방식, GET 또는 POST를 입력한다. (기본은 GET) 
 action 폼데이터를 처리할 서블릿(또는 jsp)을 지정한다.
 encType 폼데이터의 인코딩 타입을 지정한다.
파일 업로드의 경우 multipart/form-data 이다.

서블릿에서 폼 데이터 처리방법
javax.servlet.http.HttpServletRequest 를 이용하여 요청을 받을수 있습니다.
doGet()메소드나 doPost()메소드를 오버라이드하여 사용하면 됩니다.

주요 메소드
- getParameter(String name)
- getParameterValues(String name)
- getParameterNames()


출력하기

PrintWriter와 OutputStream을 이용하여 출력을 해 줄 수가 있습니다.

PrintWriter의 예

PrintWriter out = response.getWriter();

out.println("test init parameters<br>");


OutputStream의 예

ServletOutputStream out = response.getOutputStream();

out.write(aByteArray);


Posted by 개발자 용이~
2009/03/31 02:31

getServletConfig().getInitParameter("mainEmail");

getServletContext().getInitParameter("mainEmail");


위의 예에서 첫번째  getServletConfig()가 서블릿 초기화 파라미터를 사용한 것이며
두번째줄의 getServletContext()가 컨텍스트 초기화 파라미터를 사용한 것입니다.


서블릿 초기화 파라미터(굵은 글씨로 표시된 부분) - DD의 내용

...

  

  <servlet>

    <servlet-name>BeerParamTests</servlet-name>

    <servlet-class>com.example.TestInitParams</servlet-class>

    <init-param>

      <param-name>mainEmail</param-name>

      <param-value>likewecare@wickedlysmart.com</param-value>

    </init-param>

    <init-param>

      <param-name>adminEmail</param-name>

      <param-value>blooper@wickedlysmart.com</param-value>

    </init-param>

  </servlet>



...


서블릿 초기화가 된 다음에야 서블릿 초기화 파라미터를 사용할 수 있습니다. 컨테이너가 서블릿의 init()을 호출하고 난  다음에야, 서블릿은 서블릿의 정체성을 갖기 때문이라네요. 그리고 컨테이너가 서블릿을 초기화할 때 단 한번만 서블릿 초기화 파라미터를 읽습니다. 
또한 이름에서 알수 있듯이 특정 하나의 서블릿만 사용할수 있습니다.(서블릿당 하나)
위에서 볼수 있듯 <servlet> 항목 안에 작성해야 합니다.


컨텍스트 초기화 파라미터(굵은 글씨로 표시된 부분) - DD의 내용

...


  </servlet>


  <context-param>

    <param-name>breed</param-name>

    <param-value>Greate Dane</param-value>

  </context-param>


...

서블릿 초기화 파라미터와 달리 모든 웹 애플리케이션에서 이용할 수 있습니다.(웹 어플리케이션당 하나) 위에서 볼 수 있듯 <web-app>항목 내에 작성해야 합니다.



초기화 파라미터에 객체 넣기!!

ServletContextListener 인터페이스를 구현한 클래스를 만들어야 합니다!!

package com.example;


import javax.servlet.ServletContext;

import javax.servlet.ServletContextEvent;

import javax.servlet.ServletContextListener;


public class MyServletContextListener implements ServletContextListener {


  public void contextInitialized(ServletContextEvent event) {

    ServletContext sc = event.getServletContext();


    String dogBreed = sc.getInitParameter("breed");

    Dog d = new Dog(dogBreed);

    sc.setAttribute("dog", d);

    System.out.println("초기화 했슈!!");

  }


  public void contextDestroyed(ServletContextEvent event) {

    System.out.println("소멸됨~!!");

  }


}



DD에 추가 할 내용

<web-app ...>

...

...
 

  <listener>

    <listener-class>com.example.MyServletContextListener</listener-class>

  </listener>

...

...
</web-app>

이렇게 바꿔놓은 후에 컨테이너를 다시 실행 시켜주면 초기화, 소멸 메시지를 볼수 있습니다.


나중에 dog의 값을 받아서 쓰고 싶으면 밑의 코드처럼 쓰면 됩니다.

Dog dog = (Dog) getServletContext().getAttribute("dog");



※ 위에서 본 것 처럼 ServletContext 이벤트를 리스닝하기 위해서는 ServletContextListener 인터페이스를 구현해야합니다. 그 후에 DD에 <listener> 항목을 추가하여줍니다~

Posted by 개발자 용이~
2009/03/30 22:19
Life Cycle 관련 메소드

1. init() 메소드
- 서블릿 요청시 맨 처음 단 한번 수행된다.
- 서블릿의 초기화 작업을 수행한다.

2. 서비스 메소드
- doGet(), doPost()메소드
- 서블릿 요청시 매번 수행된다.
- 실제로 클라이언트의 요청을 수행하는 비즈니스 작업을 수행함.

3. destroy() 메소드
 - 서블릿이 컨테이너에서 소멸될 때 단 한번 수행됨.
- 서블릿의 마무리 작업을 수행한다.

예제소스
- HelloServlet.java

import javax.servlet.http.*;


public class HelloServlet extends HttpServlet {

  @Override

  public void init() {

    System.out.println("init 메소드 호출");

  }


  @Override

  public void doGet(HttpServletRequest request, HttpServletResponse response) {

    System.out.println("doGet 메소드 호출");

  }


  @Override

  public void destroy() {

    System.out.println("destroy 메소드 호출");

  }


- web.xml 수정하기~

<web-app ....>

  

  <servlet>

    <servlet-name>LifeCycleViewer</servlet-name>

    <servlet-class>com.example.HelloServlet</servlet-class>

  </servlet>

  

  <servlet-mapping>

    <servlet-name>LifeCycleViewer</servlet-name>

    <url-pattern>/LifeCycleView.do</url-pattern>

  </servlet-mapping>


</web-app>


LifeCycleView.do를 브라우저에서 열어보면~~ 로그가 쌓이게 됩니다.
확인을 해보면 처음에 init()메소드가 호출이 된 후!! 페이지를 새로 요청 할 때 마다 doGet()메소드가 호출되는 것을 볼수가 있습니다. 그리고 클래스파일이 다시 컴타일 되어 컨테이너가 리로드 할때~ 그리고 컨테이너를 종료 시킬때 destroy()메소드가 호출되는 것을 볼수가 있습니다. 직접 해보세요~


Posted by 개발자 용이~
2009/03/30 21:13
JSP, Servlet 환경에서의 웹 애플리케이션 구조, context 에 대해서 알아보겠습니다.
웹 에플리케이션 정의 : html, JSP, Servlet, 일반 클래스들이 다수의 컨테이너에서 동작할 수 있고 묶여질 수 있는 자원들의 모음.


구조~



위의 그림처럼 웹 어플리케이션의 구조가 있어야 합니다.

웹 애플리케이션의 루트를 /webTest 라고 한다면 디렉토리별 하는 일은 밑의 표과 같습니다.

 디렉토리  설명
 /webTest  웹 애플리케이션의 루트 디렉토리, 모든 jsp 및 html파일이 저장된다.
 /webTest/WEB-INF  웹 애플리케이션의 web.xml이 있는 위치이다. 이 디렉토리는 공개 문서가 아니기 때문에 어떤 파일도 클라이언트에서 접근이 불가능 하다.
 /webTest/WEB-INF/classes  서블릿과 일반 유틸리티 클래스가 있는 위치이다.
 /webTest/WEB-INF/lib  웹 애플리케이션에서 사용하는 자바압축파일(jar)파일이 위치한다. 

※ web.xml
- 배치지시자(Deployment Descriptor)로서 일종의 환경설정 파일.
- 현재 웹 앷플리케에션에 대한 각종 설정사항을 갖고 있음.



Context

Context는 웹 애플리케이션을 container가 관리하는 이름을 이미합니다.

특징
- 애플리케이션당 하나의 context가 등록된다.
- 브라우저에서 요청시 context이름으로 요청한다.
- context 이름은 중복되지 않는다.
- 의미있는 명사형으로 context 이름을 지정한다.
- 대소문자 구별이 엄격하다.
Posted by 개발자 용이~
2008/12/28 22:39
MVC의 핵심은 비즈니스 로직과 프리젠테이션 로직의 분리입니다.

1. Model(자바 클래스)
비즈니스 로직이 여기에 들어갑니다. 모델의 state, getter, setter가 여기에 같아 들어가게 됩니다. 모델은 데이터베이스와 통신하는 유일한 곳입니다.(DB통신만을 전달하는 객체를 따로 빼내지 않을 경우.)

2. View(JSP)
프리젠테이션에 대한 책임을 집니다. 뷰는 컨트롤러로부터 모델정보를 읽어옵니다. 뷰는 또한 사용자가 입력한 정보를 컨트롤러에게 넘겨주어야 합니다.

3. Controller(Servlet)
Request객체에서 사용자가 입력한 정보를 뽑아내며, 모델에대하여 어떤 작업을 해야 하는지 알아냅니다. 모델 정보를 수정한다든지, 뷰에게 넘겨줄 새로운 모델을 만드는 작업을 합니다.

위키 참고링크에요!
Posted by 개발자 용이~