본문 바로가기
JAVA/spring

Servlet Programming

by 개폰지밥 2020. 1. 9.
반응형

자바 웹 개발 워크북 읽으면서 정리

 

3장 서블릿 프로그래밍

3.1 CGI 프로그램과 서블릿

3.1.1 CGI의 이해

사용자가 직접 아이콘을 더블 클릭하거나 명령 창(또는 터미널)을 통해 실행시키는 프로그램을 일반적으로 애플리케이션또는 데스크톱 애플리케이션이라고 합니다. 반면에 사용자가 웹 서버를 통해 간접적으로 실행시키는 프로그램이 웹 애플리케이션입니다.

웹 서버와 프로그램 사이의 데이터를 주고받는 규칙을 CGI(Common gateway interface)라고 합니다.

3.1.2 서블릿

서블릿 컨테이너: 서블릿의 생성과 실행, 소멸 등 생명주기를 관리하는 프로그램.

서블릿 개발자는 더 이상 CGI 규칙에 대해 알 필요가 없습니다. 대신 서블릿 컨테이너와 서블릿 사이의 규칙을 알아야 합니다.

3.3.2 웹 프로젝트 폴더 구조

- src: 자바 소스 파일을 두는 폴더입니다. 앞으로 이 폴더에 서블릿 클래스나 필터, 리스너 등 필요한 모든 자바 클래스 파일을 둘 것입니다. 프로퍼티 파일(.properties)도 이 폴더에 둡니다.

- build / classes: 컴파일된 자바 클래스 파일(.class)이 놓이는 폴더입니다. 물론 패키지에 소속된 클래스인 경우 이 폴더에 해당 피키지가 자동으로 만들어집니다.

- WebContent: HTML, CSS, JavaScript, JSP, 이미지 파일 등 웹 콘텐츠를 두는 폴더입니다. 웹 애플리케이션을 서버에 배치할 때 이 폴더의 내용물이 그대로 복사됩니다.

- WebContent / WEB-INF / web.xml 웹 애플리케이션 설정과 관련된 파일을 두는 폴더입니다. 영어 표현을 줄여서 ‘DD 파일이라고도 부릅니다. 서블릿이나 필터, 리스너, 매개변수, 기본 웹 페이지 등 웹 애플리케이션 컴포넌트들의 배치 정보를 이 파일에 작성합니다. 서블릿 컨테이너를 클라이언트의 요청을 처리할 때 이 파일의 정보를 참고하여 서블릿 클래스를 찾거나 필터를 실행하는 등의 작업을 수행합니다.

- WebContent / WEB-INF / lib

자바 아카이브 파일(.jar)을 두는 폴더입니다. 아카이브란 우리말로 기록 보관소라는 뜻입니다. 즉 아카이브 파일은 클래스 파일(.class)과 프로퍼티 파일(.properties)들을 모아 놓은 파일 보관소 파일입니다. 이러한 이유로 Java Archive의 합성어를 확장자 명(.jar)으로 사용하고 있습니다. 참고로 유닉스(또는 리눅스) 계열 운영체제에서 많이 사용하는 .tarTape Archive의 합성어입니다. 유닉스 초창기에 파일을 백업할 때 자기 테이프 드라이브를 주로 사용하였습니다. 백업하기 전에 백업 대상 파일들을 하나의 파일로 담았는데 이 파일의 확장자가 .tar 입니다. 여러 파일을 주고받을 때도 매우 편리합니다.

3.2 서블릿, JSP vs. Java EE vs. WAS

Java EE 기술 중에서 서블릿, JSP는 웹을 기반으로 한 클라이언트/서버 기술을 정의하고 있습니다. 자바로 웹 애플리케이션을 개발한다는 것은 바로 이 서블릿과 JSP 기술을 사용하여 애플리케이션을 개발한다는 것을 말합니다.

3.2.2 WAS의 이해

클라이언트 서버 시스템 구조에서 서버 쪽 애플리케이션의 생성과 실행, 소멸을 관리하는 프로그램을 애플리케이션 서버라고 합니다. 서블릿 컨테이너와 같이 웹 기술을 기반으로 동작되는 애플리케이션 서버를 ‘WAS(Web Application Server)’라 부릅니다.

 

 3.4 서블릿 만들기

3.4.2 javax.servlet.Servlet 인터페이스

서블릿 클래스는 반드시 javax.servlet.Servlet 인터페이스를 구현해야 합니다. 서블릿 컨테이너가 서블릿에 대해 호출할 메서드를 정의한 것이 Servlet 인터페이스 입니다.

Servlet 인터페이스

-       init()

-       service()

-       destroy()

-       getServletInfo()

-       getServletConfig()

 

서블릿의 생명주기와 관련된 메서드: init(), service(), destroy()

Init()는 서블릿 컨테이너가 서블릿을 생성한 후 초기화 작업을 수행하기 위해 호출하는 메서드

예를 들어 이 메서드가 호출될 때 데이터베이스에 연결하거나 외부 스토리지 서버와의 연결, 프로퍼티 로딩 등 클라이언트 요청을 처리하는데 필요한 자원을 미리 준비할 수 있습니다.

Service()는 클라이언트가 요청할 때 마다 호출되는 메서드입니다. 이 메서드에 서블릿이 해야 할 일을 작성하면 됩니다.

Destroy()는 서블릿 컨테이너가 종료되거나 웹 애플리케이션이 멈출 때, 또는 해당 서블릿을 비활성화 시킬 때 호출됩니다. 따라서 이 메서드에는 서비스 수행을 위해 확보했던 자원을 해제한다거나 데이터를 저장하는 등의 마무리 작업을 작성하면 됩니다.

 

Servlet 인터페이스 기타 메서드:getServletConfig(), getServletInfo()

getServletConfig()는 서블릿 설정 정보를 다루는 servletConfig 객체를 반환합니다. 이 객체를 통해 서블릿 이름과 서블릿 초기 매개변수 값, 서블릿 환경정보를 얻을 수 있습니다.

getServletInfo()는 서블릿을 작성한 사람에 대한 정보라든가 서블릿 버전, 권리 등을 담은 문자열을 반환합니다.

 

3.4.3 서블릿 배치 정보 작성

Web.xml 파일을 배치 기술서(Deployment Descriptor) 또는 약자로 ‘DD’파일이라고 부릅니다. 웹 애플리케이션의 배치 정보를 담고 있는 파일입니다. 따라서 서블릿을 만들었으면 DD 파일에 배치 정보를 등록해야 합니다. 그래야만 클라이언트에서 해당 서블릿의 실행을 요청할 수 있습니다. DD 파일에 등록되지 않은 서블릿은 서블릿 컨테이너가 찾을 수 없습니다.

서블릿에 URL 부여

클라이언트에서 서블릿의 실행을 요청할 때 url을 사용합니다. 따라서 서블릿에 url을 부여해야 클라이언트에서 요청할 수 있습니다. <servlet-mapping>태그는 서블릿과 url을 매핑할 때 사용합니다.

<!-- 서블릿 선언 -->

  <servlet>

  <servlet-name>Hello</servlet-name> <!-- 서블릿 별명 -->

  <servlet-class>lesson03.servlets.HelloWorld</servlet-class> <!-- 패키지 이름을 포함한 서블릿 클래스명 -->

  </servlet>

 

  <!-- 서블릿을 URL 연결 -->

  <servlet-mapping>

  <servlet-name>Hello</servlet-name><!-- 서블릿 별명 -->

  <url-pattern>/Hello</url-pattern><!-- 서블릿을 요청할 클라이언트가 사용할 URL -->

  </servlet-mapping>

 

*패키지명 + 클래스명 = Fully qualified name = QName

3.4.5 URL과 서블릿 매핑

 

Sysout() 메서드는 클라이언트로 출력하는 것이 아니라 서버 콘솔창으로 출력하는 것이다.

 

3.4.6서블릿 구동 절차

1) 클라이언트의 요청이 들어오면 서블릿 컨테이너는 서블릿을 찾습니다.

2) 만약 서블릿이 없다면 서블릿 클래스를 로딩하고 인스턴스를 준비한 후 생성자를 호출합니다. 그리고 서블릿 초기화 메서드인 init()를 호출합니다.

3) 클라이언트 요청을 처리하는 service() 메서드를 호출합니다.

4) service() 메서드에서 만든 결과를 http 프로토콜에 맞추어 클라이언트에 응답하는 것으로 요청처리를 완료합니다.

5) 만약 시스템 운영자가 서블릿 컨테이너를 종료하거나, 웹 애플리케이션을 종료 한다면,

6) 서블릿 컨테이너는 종료되기 전에 서블릿이 마무리 작업을 수행할 수 있도록 생성된 모든 서블릿에 대해 destroy() 메서드를 호출합니다.

 

웹 페이지를 새로 고침하면 서버에 HelloWorld의 실행을 다시 요청하지만 이전 요청과 다르게 init()는 호출되지 않고 service()만 호출됩니다.

 

Destroy()가 호출되는 경우를 확인하는 방법은 톰캣 서버를 종료하는 것입니다.

 

3.4.7 웰컴 파일들

웹 서버에게 요청할 때 서블릿 이름을 생략하고 디렉터리 위치까지만 지정한다면, 웹 서버는 해당 디렉터리에서 웰컴 파일을 찾아서 보내 줍니다.

웰컴 파일이란? 디렉토리의 기본 웹 페이지 입니다.

웰컴 파일의 이름은 web.xml<welcome-file-list> 태그를 사용하여 설정할 수 있습니다. 이 태그의 하위 태그로 <welcome-file>이 있는데, 바로 이 하위 태그에 웰컴 파일의 이름을 적어 넣으면 됩니다.

위에서부터 아래로 순차적으로 조회하고 먼저 찾은 것을 클라이언트로 보내게 됩니다.

 

웰컴 파일 테스트

web03까지만 입력하고 엔터

찾을 수 없다고 뜨는 이유는 앞에서 설정한 웰컴 파일이 한 개도 없기 때문이다.

앞에서 설정한 웰컴 파일중 default.html파일을 WebContent 폴더에 작성해보자

 

만약 index.html을 만들면 default.html 보다 먼저 선언되었기 때문에 index.html의 결과가 출력된다.

 

3.5 웹 애플리케이션 배치

3.5.2 톰캣 실행 환경의 임시 배치 폴더

Tmp0은 플러그인이 관리하는 임시 폴더이다.

 

3.5.3 운영 서버에 배치하기

실제 운영하는 서버에 배치할 때는 배치할 파일들을 하나의 웹 아카이브 파일(.war)로 만들어서 배치 폴더에 복사합니다.

웹 아카이브 파일 생성

File -> export -> war 검색

 

운영 서버에 .war 파일 배치

1)     war 파일을 복사하여 $TOMCAT_HOME/webapps 폴더에 붙여 넣기.

2)     이클립스 통하지 않고 톰캣 서버를 직접 실행

 

3.6 GenericServlet의 사용

예를 들어 destroy()는 웹 애플리케이션을 종료될 때 호출되는데, 서블릿에 대해 마무리할 작업이 없다면 구현할 필요가 없습니다. 그럼에도 인터페이스를 구현하는 클래스는 반드시 인터페이스에 선언된 모든 메서드를 구현해야 합니다. 이런 불편한 점을 해소하기 위해 등장한 것이 GenericServlet 추상 클래스입니다.

 

3.6.2 GenericServlet의 용도

서블릿을 만들 때 GenericServlet을 상속받는다면 Servlet 인터페이스 메서드 중에서 service()만 구현하면 된다.

 

3.6.3 계산기 서블릿 작성(귀찮으니까 계산기만 작성)

package lesson03.servlets;

 

import java.io.IOException;

import java.io.PrintWriter;

 

import javax.servlet.GenericServlet;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

 

public class CalculatorServlet extends GenericServlet {

 

       @Override

       public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {

             // TODO Auto-generated method stub

            

             int a = Integer.parseInt(request.getParameter("a"));

             int b = Integer.parseInt(request.getParameter("b"));

            

             response.setContentType("text/plain");

             response.setCharacterEncoding("UTF-8");

            

             PrintWriter writer = response.getWriter();

             writer.println(a+b);

             }

}

 

3.6.4 ServletRequest

Service()의 매개변수 중에서 ServletRequest 객체는 클라이언트의 요청 정보를 다룰 때 사용합니다.

예제 소스에서 사용한 getParameter()GET이나 POST 요청으로 들어온 매개변수 값을 꺼낼 때 사용합니다.

3.6.5 ServletResponse

ServletResponse 객체는 응답과 관련된 기능을 제공합니다. 클라이언트에게 출력하는 데이터의 인코딩 타입을 설정하고, 문자집합을 지정하며, 출력 데이터를 임시 보관하는 버퍼의 크기를 조정하거나, 데이터를 출력하기 위해 출력 스트림을 준비할 때 이 객체를 사용합니다.

 

setContentType()

클라이언트에게 출력할 데이터의 정보를 알려줘야함.

예를 들어 HTML 형식일 수도 XML 형식일 수도 있다. 아래는 순수한 텍스트임을 지정하고 있다.

response.setContentType(“text/plain”);

 

setCharacterEncoding() -> 출력할 데이터의 문자 집합 지정

 

출력 데이터의 문자 집합은 다음과 같이 setContentType()을 사용하여 설정할 수 있다.

response.setContentType(“text/plain;chartest=UTF-8”);

 

getWriter()

클라이언트로 출력할 수 있도록 출력 스트림 객체를 반환합니다. 이미지나 동영상과 같은 바이너리 데이터를 출력하고 싶을 때는 getOutputStream()을 사용하세요.

PrintWriter writer = response.getWriter();

             writer.println(a+b);

 

3.6.6 CalculatorServlet 배치 및 테스트

Web.xmlCalculatorServlet의 배치 정보 추가

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">

  <display-name>web03</display-name>

 

  <!-- HelloWorld 서블릿 선언 -->

  <servlet>

  <servlet-name>Hello</servlet-name> <!-- 서블릿 별명 -->

  <servlet-class>lesson03.servlets.HelloWorld</servlet-class> <!-- 패키지 이름을 포함한 서블릿 클래스명 -->

  </servlet>

 

  <!-- 계산기 서블릿 선언 -->

  <servlet>

  <servlet-name>Calculator</servlet-name> <!-- 서블릿 별명 -->

  <servlet-class>lesson03.servlets.CalculatorServlet</servlet-class> <!-- 패키지 이름을 포함한 서블릿 클래스명 -->

  </servlet>

 

  <!-- HelloWorld 서블릿을 URL 연결 -->

  <servlet-mapping>

  <servlet-name>Hello</servlet-name><!-- 서블릿 별명 -->

  <url-pattern>/Hello</url-pattern><!-- 서블릿을 요청할 클라이언트가 사용할 URL -->

  </servlet-mapping>

 

  <!-- 계산기 서블릿을 URL 연결 -->

  <servlet-mapping>

  <servlet-name>Calculator</servlet-name><!-- 서블릿 별명 -->

  <url-pattern>/calc</url-pattern><!-- 서블릿을 요청할 클라이언트가 사용할 URL -->

  </servlet-mapping>

 

  <welcome-file-list>

    <welcome-file>index.html</welcome-file>

    <welcome-file>index.htm</welcome-file>

    <welcome-file>index.jsp</welcome-file>

    <welcome-file>default.html</welcome-file>

    <welcome-file>default.htm</welcome-file>

    <welcome-file>default.jsp</welcome-file>

  </welcome-file-list>

</web-app>

 

웹 브라우저를 띄워 CalculatorServlet의 실행을 요청합니다. 서블릿을 요청할 때 다음과 같이 URLab의 매개변수 값을 붙입니다.

 

3.6.7 GET 요청으로 넘어온 매개변수 값의 인코딩 설정

GET 요청은 매개변수 값이 URI에 포함되어 있기 때문에 setCharacterEncoding()으로는 문자 집합을 설정할 수 없습니다. 서블릿 컨테이너에서 권고하는 지침에 따라 URI의 인코딩 형식을 설정해야 합니다.

Servers 프로젝트의 톰캣 실행 환경 폴더에서 server.xml 파일을 엽니다.

 

<Connector connectionTimeout="20000" port="9999" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>

 

3.6.8 @WebServlet 애노테이션을 이용한 서블릿 배치 정보 설정

Servlet 3.0 사양부터는 애노테이션으로 서블릿 배치 정보 설정 가능.

CalculatorServlet 클래스를 web.xml 대신 애노테이션을 이용해 배치 정보를 작성

 

DD 파일인 web.xml에서 서블릿 정의와 URL 매핑을 주석처리

실행해도 결과는 동일하게 나옴.

 

결론: DD파일인 web.xml에서 서블릿 정의와 URL 매핑을 통해 서블릿 정보를 읽혀줬는데 Servlet 3.0부터는 이것을 @WebServlet 애노테이션을 통해 서블릿을 배치할 수 있다.

 

3.6.9 @WebServlet 애노테이션의 주요 속성

name

서블릿의 이름을 설정하는 속성입니다. 기본값은 빈 문자열(“”) 입니다.

 

urlPatterns

서블릿의 URL 목록을 설정하는 속성입니다. 속성값으로 String 배열이 옵니다. 기본값은 빈 배열({}) 입니다.

// 서블릿에 대해 한 개의 URL을 설정하는 경우

@WebServlet(urlPatterns=”/calc”)  //일반적인 문자열로 표기 가능

@WebServlet(urlPatterns={“/calc”}) //중괄호를 사용하여 배열 표기

 

// 서블릿에 대해 여러 개의 URL을 설정하는 강의

@WebServlet(urlPatterns={“/calc”, “calc.do”, “calculator.action”}

 

value

urlPatterns와 같은 용도입니다. 애노테이션의 문법에서는 속성 이름이 ‘value’인 경우는 속성 이름 없이 값만 설정할 수 있습니다.

@WebServlet(value=”/calc”)

@WebServlet(“calc”) //속성명 ‘value’ 생략 가능

 

Value 속성 외에 다른 속성의 값도 함께 설정한다면 value 속성의 이름을 생략할 수 없습니다.

@WebServlet(value=”/calc”, name=”Calcualtor”)

 

3.7 정리

서블릿 명칭은 ServerApplet의 합성어 입니다. 클라이언트에게 서비스를 제공하는 작은 단위의 서버 프로그램이라는 뜻입니다.

*애플릿: 플러그인 하나로서 전용 위젯 엔진이나 더 큰 프로그램 범위 내에서 실행되는 특정한 작업을 수행하는 조그마한 응용 프로그램을 말한다. 웹 브라우저, 제어판과 같은 다른 프로그램에서 실행되는 소프트웨어 구성 요소로 볼 수 있다.

 

서블릿 컨테이너는 서블릿의 생성에서 실행, 소멸까지 서블릿의 생명주기를 관리하는 프로그램입니다. 클라이언트로부터 요청이 들어오면, 서블릿 컨테이너는 호출 규칙에 따라 서블릿의 메서드를 호출합니다. 서블릿 호출 규칙은 javax.servlet.Servlet 인터페이스에 정의되어 있습니다. 따라서 서블릿을 만들 때는 반드시 Servlet 인터페이스를 구현해야만 합니다.

 

서블릿 라이브러리는 서블릿을 좀 더 편리하게 개발할 수 있도록 javax.servlet.GenericServlet이 라는 추상 클래스를 제공한다. Service()를 제외한 나머지 메서드가 구현되어 있다.

 

 

남들보다 더 잘하려고 고민하지 마라.

'지금의 나'보다 잘하려고 애쓰는 게 더 중요하다. -윌리엄 포크너 -

책에 적혀있었는데 좋은 말 인것 같아서 적었어요. 언제나 남들과 비교하면서 좀 더 빠르게, 좀 더 열심히, 좀 더 잘 하려고 발만 동동 굴렀는데

남들과의 비교 보다는 어제의 나 그리고 지금의 나보다 더 잘하려고 애쓰는 것이 더 중요하지 않을까요?

멈추지 않고 꾸준히 천천히 걸어가는 것이 중요한 것 같습니다. 

 

 

반응형

'JAVA > spring' 카테고리의 다른 글

MVC Architecture  (0) 2020.02.24
Servlet JDBC  (1) 2020.01.20
Web programming  (0) 2020.01.03
Web Applications  (0) 2020.01.02
spring war Deployment  (0) 2019.09.18

댓글