'Java/Servlet & JSP'에 해당하는 글 26건

클라이언트와 지속적인 연결을 유지하지 못하는 것이 http protocol의 특징이므로, 이전 요청한 클라이언트와의 연결을 유지하기 위해서 Session을 사용한다.
컨테이너(톰캣) 단에서 Session ID를 발행하고, 해당 Session ID와 Cookie를 맵핑 한 다음 해당 쿠키를 클라이언트에서 사용하도록 하면 클라이언트를 구분해서 받을 수 있다.

* 세션 ID는 다음과 같은 방법으로 사용할 수 있다.

HttpSession session = request.getSession();

위와 같이 하게 되면, request로부터 세션 ID를 가지고 올 수 있고, 제일 처음 요청이라면 response 객체에 보낼 쿠키도 생성하게 된다.

* 세션이 이미 있는지, 아니면 처음 요청으로 새롭게 만들게 되었는지를 확인하려면 다음과 같이 하면 된다.

HttpSession session = request.getSession();

if(session.isNew()) {
    out.println("This is a new session");
} else {
    out.println("Welcome back!");
}

* 클라이언트가 쿠키를 사용하지 않을 경우에는 세션 ID를 URL 뒤에 붙여 보내줘서 쿠키 대신에 URL을 파싱해서 클라이언트를 구분하기도 한다.
URL 뒤에 세션 아이디를 붙여 보내기 위해서는 다음과 같이 하면 된다.

HttpSession session = reqeust.getSession();

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

세션을 유지하면서 요청을 다른 서블릿이나 JSP로 보내고 싶은 경우에는 encodeRedirectURL()을 사용하면 된다.

* 오래된 세션은 세션 타임아웃을 web.xml에 설정하여 전체 세션에 적용해서 사용하거나, 메소드를 사용하여 특정 세션에서만 사용할 수 있다.
사용 방법은 다음과 같다.

web.xml에서 사용하는 방법

  <session-config>
      <session-timeout>15</session-timeout>
  </session-config>

특정 세션에서만 사용하는 방법

session.setMaxInactiveInterval(20*60);

web.xml에서는 분 단위로 적을 수 있고, setMaxInactiveInterval의 인자값으로 사용할 경우에는 초 단위로 사용할 수 있다.
위의 경우에는 15분 또는 20분이라는 의미이다.





'Java > Servlet & JSP' 카테고리의 다른 글

HttpSessionBindingListener와 HttpSessionAttributeListener  (0) 2009.02.02
Cookie 사용하기  (0) 2009.02.02
Session 관리  (0) 2009.01.30
스레드 안전한 ServletContext 만들기  (1) 2009.01.29
ServletContext 이용하기  (2) 2009.01.23
ServletConfig 이용하기  (0) 2009.01.22

WRITTEN BY
체리필터
프로그램 그리고 인생...

받은 트랙백이 없고 , 댓글이 없습니다.
secret
스레드 안전이란 말은 어떤 속성에 set을 한 다음 get을 하기 전에 다른 무엇인가가 해당 속성에 set을 해서 내가 set한 속성 값을 그대로 get하지 못하는 경우를 말한다.
ServletContext에서도 스레드 안전이 보장되지 못한다.
즉 다음과 같이 코딩하게 되면 잘못된 결과가 리턴될 수도 있다는 말이다.

    public void doGet(HttpServletRequest request, HttpServletResponse response)
                    throws IOException, ServletException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
       
        out.println("test context attributes<br>");
       
        getServletContext().setAttribute("foo", "22");
        getServletContext().setAttribute("bar", "42");
       
        out.println(getServletContext().getAttribute("foo"));
        out.println(getServletContext().getAttribute("bar"));
    }

위와 같이 하면 ServletContext에 foo라는 속성에 22라는 값이, bar라는 속성에 42라는 값이 저장되게 되고, 화면 출력도 22, 42가 나오는 것이 정상이다.
하지만, 스레드 안전하지 못하기 때문에 중간에 다른 요청에 의해 위 메소드(doGet)가 실행되게 되거나, 다른 서블릿에 의해 foo 또는 bar의 속성이 변경되게 된다면 우리는 우리가 예상한 값을 보지 못할 수도 있다.
따라서 우리는 해당 Context에 lock을 걸어서 스레드 세이프 하게 만들어야 할 것이다.
해당 Context에 lock을 거는 방법은 아래와 같다.

    public void doGet(HttpServletRequest request, HttpServletResponse response)
                    throws IOException, ServletException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
       
        out.println("test context attributes<br>");
       
        synchronized (getServletContext()) {
            getServletContext().setAttribute("foo", "22");
            getServletContext().setAttribute("bar", "42");
           
            out.println(getServletContext().getAttribute("foo"));
            out.println(getServletContext().getAttribute("bar"));
        }
    }

synchronized block을 통해 해당 context에 접근하는 경우 lock을 건 다음 작업을 할 수 있다.
물론 이 방법도 완전히 안전한 것은 아니다.
해당 메소드 내에서 위와 같이 lock을 걸어서 사용한다 하더라도 synchronized block을 사용하지 않은 다른 메소드로 부터는 안전하지 않다.

'Java > Servlet & JSP' 카테고리의 다른 글

Cookie 사용하기  (0) 2009.02.02
Session 관리  (0) 2009.01.30
스레드 안전한 ServletContext 만들기  (1) 2009.01.29
ServletContext 이용하기  (2) 2009.01.23
ServletConfig 이용하기  (0) 2009.01.22
MVC 식 Servlet 사용  (0) 2009.01.21

WRITTEN BY
체리필터
프로그램 그리고 인생...

받은 트랙백이 없고 , 댓글 하나 달렸습니다.
  1. Servlet 내에서 그런식의 Synchronized 를 쓴다는게 좀 이상하네요 .. 물론 굳이 예제를 보여주기 위해서라면 이해는 갑니다만 ..
    그럼 혹 이런 방식은 어떤지
    현재 쓰레드 ID 를 가져와 [ThreadId].foo 를 넣어서 다시 그이름으로 찾는 다면 좀더 안전 하지 않을까 합니다
    다른 쓰레드 접근 걱정도 문제 없고 동기화 블록으로 생기는 보틀넥도 줄이고 ..
    그럼 ..
secret
ServletConfig는 해당 서블릿에서만 사용할 수 있지만 Web App 내에서 공통적인 내용을 가져다 사용하려면 ServletContext를 사용할 수 있다.
ServletContext는 ServletConfig와 마찬가지로 web.xml을 사용하며, 따라서 바로 사용하려면 String만 사용할 수 있다.
하지만, ServletContextListener를 이용하면 객체 역시 Web App 전역에서 사용할 수 있다.

ServletContextListener는 서블릿이 로딩 되기 전, 컨테이너(ex:톰캣) 차원에서 initialize 하고 destroy 하게 하는 것이다.
따라서 이 속성을 이용해서 컨테이너가 ServletContextListener를 로딩할 때 context-param을 추가한 후, 기타 다른 servlet에서 그 후에 해당 객체를 가져다 쓰는 것이다.
말로 설명하기가 힘든 부분이 있으니 Head First Servlet & JSP에 나와 있는 예제를 살펴보도록 하자.

1. web.xml

  <servlet>
      <servlet-name>ListenerTester</servlet-name>
      <servlet-class>com.example.ListenerTester</servlet-class>
  </servlet>
  <servlet-mapping>
      <servlet-name>ListenerTester</servlet-name>
      <url-pattern>/ListenTest.do</url-pattern>
  </servlet-mapping>

  <context-param>
      <param-name>breed</param-name>
      <param-value>Great Dane</param-value>
  </context-param>
  <listener>
      <listener-class>
          com.example.MyServletContextListener
      </listener-class>
  </listener>

위 내용에서 볼 수 있듯이 브라우져에서 요청할 url은 http://localhost:8080/ListenTest.do 이며 맵핑 된 com.example.ListenerTester 서블릿을 호출하게 된다.
중용한 것은 위 xml 중에서 listener 부분이다.
컨테이너(톰캣)가 처음 로딩 될 때 com.example.MyServletContextListener 클래스를 호출하게 되며 MyServletContextListener 는 ServletContextListener를 implements 하게 된다.
implements 해야 하는 메소드로는 contextInitialized와 contextDestroyed이다.
MyServletContextListener 의 소스는 아래와 같다.

2. MyServletContextListener 의 소스

package com.example;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class MyServletContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent event) {
        // TODO Auto-generated method stub
        ServletContext sc = event.getServletContext();
        String dogBreed = sc.getInitParameter("breed");
        Dog d = new Dog(dogBreed);
        sc.setAttribute("dog", d);
    }
   
    @Override
    public void contextDestroyed(ServletContextEvent event) {
        // TODO Auto-generated method stub
    }
}

contextInitialized 부분에서 setAttribute 메소드를 이용해서 dog라는 param-name에 dog라는 객체를 param-value로 할당하고 있다.
contextInitialized에서 사용된 Dog 클래스의 소스는 다음과 같다.

3. Dog 의 소스

package com.example;

public class Dog {
    private String breed;
   
    public Dog(String breed) {
        this.breed = breed;
    }
   
    public String getBreed() {
        return breed;
    }
}

이제 브라우져가 호출할 서블릿인 com.example.ListenerTester 클래스 소스를 살펴보자.

4. ListenerTester 소스

package com.example;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ListenerTester extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
                    throws IOException, ServletException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
       
        out.println("test context attribute set by listener<br>");
        out.println("<br>");
       
        Dog dog = (Dog) getServletContext().getAttribute("dog");
        out.println("Dog's bread is : " + dog.getBreed());
    }
}

위 내용에서 볼 수 있듯이 getServletContext().getAttribute("dog")로 param-name이 dog인 객체 d를 불러와서 형변환을 한 다음 사용하고 있다.



'Java > Servlet & JSP' 카테고리의 다른 글

Session 관리  (0) 2009.01.30
스레드 안전한 ServletContext 만들기  (1) 2009.01.29
ServletContext 이용하기  (2) 2009.01.23
ServletConfig 이용하기  (0) 2009.01.22
MVC 식 Servlet 사용  (0) 2009.01.21
Servlet의 작성  (3) 2009.01.21

WRITTEN BY
체리필터
프로그램 그리고 인생...

받은 트랙백이 없고 , 댓글  2개가 달렸습니다.
  1. 잘 보고 갑니다~ 문득 궁금한게 생겨서 구글링 하다보면 체리필터님의 글이 자주 눈에 띄고
    내용도 좋아서 댓글 남기게 되었어요 ㅎㅎ
secret
web.xml에 config 정보를 정의하고 해당 내용을 servlet에서 불러와 사용할 수 있다.
사용 방법은 다음과 같다.

1. web.xml 작성

  <!-- ServletConfig Test Start... -->
  <servlet>
      <servlet-name>BeerParamTests</servlet-name>
      <servlet-class>com.example.TestInitParams</servlet-class>
      <init-param>
          <param-name>adminEmail</param-name>
          <param-value>likewecare@wickedlysmart.com</param-value>
      </init-param>
      <init-param>
          <param-name>mainEmail</param-name>
          <param-value>blooper@wickedlysmart.com</param-value>
      </init-param>
  </servlet>
  <servlet-mapping>
      <servlet-name>BeerParamTests</servlet-name>
      <url-pattern>/Tester.do</url-pattern>
  </servlet-mapping>
  <!-- ServletConfig Test End... //-->

init-param을 통해서 param-name(변수명)을 정하고 param-value에 값을 넣은 후 사용할 수 있다.

2. com.example.TestInitParams.java 작성

package com.example;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TestInitParams extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
                    throws IOException, ServletException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("test init parameters<br>");
       
        Enumeration e = getServletConfig().getInitParameterNames();
        while(e.hasMoreElements()) {
            out.println("<br>param name = " + e.nextElement() + "<br>");
        }
        out.println("main email is " + getServletConfig().getInitParameter("mainEmail"));
        out.println("<br>");
        out.println("admin email is " + getServletConfig().getInitParameter("adminEmail"));
    }
}

getServletConfig()를 사용하여서 web.xml 파일에서 정의한 mainEmail, adminEmail 변수를 가져와 사용할 수 있다.

3. 결과물

브라우져에서 호출하면 아래와 같은 결과물을 볼 수 있다.

test init parameters

param name = mainEmail

param name = adminEmail
main email is blooper@wickedlysmart.com
admin email is likewecare@wickedlysmart.com




'Java > Servlet & JSP' 카테고리의 다른 글

Session 관리  (0) 2009.01.30
스레드 안전한 ServletContext 만들기  (1) 2009.01.29
ServletContext 이용하기  (2) 2009.01.23
ServletConfig 이용하기  (0) 2009.01.22
MVC 식 Servlet 사용  (0) 2009.01.21
Servlet의 작성  (3) 2009.01.21

WRITTEN BY
체리필터
프로그램 그리고 인생...

받은 트랙백이 없고 , 댓글이 없습니다.
secret
Head First Servlet & JSP 책을 통해 알게 된 MVC 식 Servlet 예제를 통해 기본적인 Servlet & JSP가 어떻게 돌아가는지 확인해 본다.
기본적인 디렉토리는 아래와 같다는 가정하에 작업을 한다.


1. 디렉토리 구성

src밑에 com.example.web 패키지와 com.example.model 패키지를 만든다.(패키지는 디렉토리와 같은 개념이다.)
web 디렉토리 밑에는 일반적인 servlet이 들어가며, model 밑에는 Pojo Java가 들어간다.
기본적인 html 파일인 form.html과 결과값을 처리할 jsp 파일인 result.jsp 파일은 WebContent 밑에 들어간다.

2. web.xml 작성

WebContent/WEB-INF/web.xml에 다음과 같이 작성한다.

  <servlet>
      <servlet-name>Ch3 Beer</servlet-name>
      <servlet-class>com.example.web.BeerSelect</servlet-class>
  </servlet>
  <servlet-mapping>
      <servlet-name>Ch3 Beer</servlet-name>
      <url-pattern>/SelectBeer.do</url-pattern>
  </servlet-mapping>

3. form.html은 다음과 같이 작성한다.

<html>
<body>
<h1 align="center">Beer Selection Page</h1>
<form method="post" action="SelectBeer.do">
Select beer characteristics<p>
Color:
<select name="color" size="1">
    <option>light</option>
    <option>amber</option>
    <option>brown</option>
    <option>dark</option>
</select>
<br><br>
<center>
    <input type="submit">
</center>
</form>
</body>
</html>

form.html파일에서 호출하는 파일은 SelectBeer.do파일이며 DocumentRoot 디렉토리 바로 아래서 호출하게 되므로 http://localhost:8080/SelectBeer.do 파일을 호출하게 될 것이다.
호출하는 방식은 post 형식이다.
web.xml 파일에 설정한 대로 SelectBeer.do url pattern은 Ch3 Beer라고 이름이 정해진 서블릿을 찾아 호출하게 된다. 즉 com.example.web 패키지 밑에 있는 BeerSelect.class 파일을 호출하게 되는 것이다.

4. BeerSelect.java(Servlet)

package com.example.web;

import com.example.model.*;

import java.awt.List;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class BeerSelect extends HttpServlet {
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {       
        String c = request.getParameter("color");
       
        BeerExpert be = new BeerExpert();
        ArrayList result = be.getBrands(c);
       
        request.setAttribute("styles", result);
       
        RequestDispatcher view = request.getRequestDispatcher("result.jsp");
        view.forward(request, response);
    }
}

5. BeerExpert.java(Pojo Java)

package com.example.model;

import java.util.ArrayList;

public class BeerExpert {
    public ArrayList getBrands(String color) {
        ArrayList brands = new ArrayList();
        if(color.equals("amber")) {
            brands.add("Jack Amber");
            brands.add("Red Moose");
        } else {
            brands.add("Jail Pale Ale");
            brands.add("Gout Stout");
        }
       
        return(brands);
    }
}

form.html에서 select list의 이름으로 지어진 color란 값을 BeerSelect에서 request객체의 getParameter메소드로 받아 c란 변수에 담아둔다.
model에 있는 BeerExpert에서 경우에 따라 값을 선택한 후 리턴한다.
BeerSelect Servlet에서는 리턴된 값을 result에 받아서 request 객체에 담아 result.jsp로 forward 한다.

6. result.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.*" %>
<!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>Beer Recommendation JSP</title>
</head>
<body>
<h1 align="center">Beer Recommendation JSP</h1>
<%
    ArrayList styles = (ArrayList)request.getAttribute("styles");
    Iterator it = styles.iterator();
    while(it.hasNext()) {
        out.println("<br>try : " + it.next());
    }
%>
</body>
</html>

request 객체에서 styles란 변수에 담긴 내용을 가져와서 루프를 돌면서 보여준다.

==================================================================================================

위와 같이 작업을 하게 되면, BeerSelect가 controller, BeerExpert가 model, result.jsp가 view가 되는 것이다.
기존 php 개발과 비교해 보면 상당히 난잡(?) 한 느낌이 든다.
객체 지향이라는 기본적인 개념은 상당히 좋은 개념인 듯 한데, 실제 적용에는 상당히 복잡해 보인다.
앞으로 이런 삽질을 계속 해 대야 하다니 ^^;;

덧. 되도 않는 UML을 그려 봤습니다. 사실 사용법을 몰라 대충 그린 건데, 글로 설명하는 것보다 이미지 설명이 그나마 좋을 듯 해서 첨부합니다. ^^



'Java > Servlet & JSP' 카테고리의 다른 글

Session 관리  (0) 2009.01.30
스레드 안전한 ServletContext 만들기  (1) 2009.01.29
ServletContext 이용하기  (2) 2009.01.23
ServletConfig 이용하기  (0) 2009.01.22
MVC 식 Servlet 사용  (0) 2009.01.21
Servlet의 작성  (3) 2009.01.21

WRITTEN BY
체리필터
프로그램 그리고 인생...

받은 트랙백이 없고 , 댓글이 없습니다.
secret
php에서는 DocumentRoot 아래에 있는 물리적인 디렉토리와 물리적인 파일을 호출하게 된다. 반면에 Java(Servlet)에서는
   

web.xml을 통해 url과 물리적인 servlet class를 맵핑 시켜서 호출하게 된다.
맵핑 시키는 방법은 아래와 같다.


위와 같은 디렉토리가 있다면, "WebContent/WEB-INF/web.xml" 파일을 열어 맵핑 정보를 등록할 수 있다.
web.xml 파일은 기본으로 생성되어 있으며, 다음과 같이 작성할 수 있다.

  <servlet>
      <servlet-name>Chapter1 Servlet</servlet-name>
      <servlet-class>Ch1Servlet</servlet-class>
  </servlet>
  <servlet-mapping>
      <servlet-name>Chapter1 Servlet</servlet-name>
      <url-pattern>/Serv1</url-pattern>
  </servlet-mapping>

위와 같이 작성을 하게 되면 물리적인 servlet 파일을 찾아가는 flow는 다음과 같다.

1. http://localhost:8080/Serv1을 브라우져 주소창에 넣는다.
2. 톰캣에서는 url-pattern 을 통해서 servlet-name이 Chapter1 Servlet이란 것을 알게 된다.
3. Chapter1 Servlet 이름을 가진 servlet-class의 이름이 Ch1Servlet이란 것을 알게 된다.
4. WEB-INF 아래 classes란 디렉토리에 배포된 Ch1Servlet.class 파일을 호출하게 된다.

============================================================================================================

기존에 php만 개발하던 개발자에게는 다소 생소한 개념이므로 위 내용을 알아두면 좋다.

'Java > Servlet & JSP' 카테고리의 다른 글

Session 관리  (0) 2009.01.30
스레드 안전한 ServletContext 만들기  (1) 2009.01.29
ServletContext 이용하기  (2) 2009.01.23
ServletConfig 이용하기  (0) 2009.01.22
MVC 식 Servlet 사용  (0) 2009.01.21
Servlet의 작성  (3) 2009.01.21

WRITTEN BY
체리필터
프로그램 그리고 인생...

받은 트랙백이 없고 , 댓글  3개가 달렸습니다.
  1. 정말 간단하지만 명쾌한 차이점이군요.. 설명 감사합니다. ㅎㅎㅎㅎ
  2. 깔끔한 정리 감사합니다.
secret