HTTP 프로토콜 정리

2009. 6. 26. 14:01

출처 : http://r00tdj.tistory.com/1?srchid=BR1http%3A%2F%2Fr00tdj.tistory.com%2F1

첫인사

이 글은 정보보안을 공부하고 있는 새내기가 기술하였기 때문에 잘못된 정보가 있을 수도 있습니다.

HTTP 프로토콜

HyperText Transfer Protocl은 www(World Wide Web)으로 접속하는 통신 수단이고 오늘날의 웹에 적용해서 사용되고 있습니다. 정적인 페이지에서 동적인 페이지로 만들기위해 발전되었고 복잡하고 웹 애플리케이션을 지원하기 위하여 만들어진 프로토콜입니다. HTTP는 고객이 Request를 보낸 메시지에 근거한 모델을 사용합니다. 그리고 서버는 Response를 돌려줍니다. 덧붙여 HTTP 필터가 가끔 사용자들에게 돌아가는 경우도 있다. 예를 들어 서버에서 발생한 오류 코드들을 브라우저로 보여줄 때가 있다.

HTTP Request

다음은 전형적인 HTTP request 내용이다.

GET /books/search.asp HTTP/1.1

Accept: image/gif, image/xxbitmap, image/jpeg, image/pjpeg,

application/xshockwaveflash, application/vnd.msexcel,

application/vnd.mspowerpoint, application/msword, */*

Referer: http://wahh-app.com/books/default.asp

Accept-Language: en-gb,en-us;q=0.5

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)

Host: wahh-app.com

Cookie: lang=en; JSESSIONID=0000tI8rk7joMx44S2Uu85nSWc_:vsnlc502

( 공백행 )

GET /books/search.asp HTTP/1.1

- GET메소드를 이용하여 search.asp라는 문서를 요청하며, 이 때 HTTP1.1버전을 사용한다.

User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)

Accept: image/gif, image/xxbitmap, image/jpeg, image/pjpeg,

- 클라이언트는 서버에게 옵션헤더 정보를 보내 자신이 설정한 내용과 받아들일 문서의 형식을 알린다. 모든 헤더 정보는 각 헤더 이름과 값을 가즌 행별로 주어진다. 그리고 사용자는 헤더의 끝을 알리기 위해 공백행을 보낸다.

- 요청과 헤더를 보낸 후에, 클라이언트는 추가로 다른 데이터를 보낼수있다. 이 때 POST메소드를 사용하는 CGI프로그램을 이용한다.

Request에는 크게 세가지 부분으로 이루어져있다.

첫번째 라인에는 HTTP명령어와 사용자가 질의한 파일이나 자원을 표시하는 URL, 그리고 HTTP 버전 번호로 이루어진다. 두번째 부분은 사용자와 서버에서 보내는 데이터ENTITY에 대한 정보를 제공하는 헤더 정보가 포함되고, 세번째 부분은 사용자 요청으로 서버에게 보내는 데이터인 ENTITY의 몸체이다.

메소드

메소드는 사용자 요구 사항의 첫째 라인에서 시작한다. 서버에게 사용자의 목적을 알리는 역할을 하는데, HTTP에서는 미리 정의 된 GET, HEAD, POST가 있다. 물론 다른 메소드도 지원하지만 현재 서버에서 폭넓게 지원하지는 않는다. 참고로 메소드는 대소문자를 구분한다.

GET 메소드

GET 메소드는 서버에서 명시된 URI에 위치 정보에 대한 요청으로 웹 브라우저가 문서를 받아 보는데 사용되는 일반적인 방법이다. GET 요청의 결과는 서버에서 접근할 수있는 파일, 프로그램이나 CGI등의 결과 값, 하드웨어 장치로부터의 출력등의 여러방식으로 생성될 수 있다.

사용자가 GET 메소드를 사용하여 요청할 때, 서버는 상태 표시줄, 헤더, 요청된 데이터로 응답한다. 서버에서 오류가 발생하거나 권한이 아닌 상태로 인해 요청을 진행시킬수 없다면 서버는 적절한 오류 메세지를 보낸다.

GET이 요청하는 실제 데이터 부분은 항상 비어있다. GET메소드는 근본적으로 파일을 달라는 요청상태로 이용된다. 사용자가 요청하는 파일이나 프로그램은 일반적으로 서버에서 전체 경로명에 의해 식별된다. 또한 GET 메소드는 폼 태그를 통해 CGI같은 프로그램으로 입력된 데이터를 보내는데 사용되기도 한다. 위에서도 언급했듯이 비어있는 ENTITY몸체를 가지고 있으므로 입력된 자료는 요청의 GET행에 있는 URL에 덧붙혀진다.

GET /books/search.asp?q=wahh HTTP/1.1

위의 예는 서버에서 클라이언트가 입력한 q의 값 wahh를 나타낸다.

q와 wahh는 <form>태그의 키와 값을 나타내며 2개 이상의 키와 값을 전송할때는 &기호에 의해 추가 할수있다.

HEAD 메소드

HEAD 메소드는 서버가 응답해야 할 데이터를 보내지 않는다는 것을 제외하면 GET 메소드와 같다. HEAD 메소드는 파일이나 자원에 대한 헤더 정보만을 요구한다.

클라이언트는 다음과 같은 예의 정보를 원한다.

- 캐시 관련 질의에 유용한 문서의 수정 시간

- 도착 시간을 측정하거나 문서의 더 작은 버전을 요청을 결정하는 페이지

레이아웃에 유용한 문서의 크기

- 클라이언트가 특정 문서만 검색할 수 있도록 해주는 문서의 유형

- 주문형 서버 질의를 가능하게 하는 서버의 유형

서버가 제공하는 헤더 정보의 대부분은 선택적이며 모든 서버들이 제공하는 것은 아니다. 또한 클라이언트에게 유익한 설계는 요구하는 헤더 정보를 서버가 전달하지 못할 경우, 서버가 융통성 있게 응답하고 기본적인 조치를 취하도록 하는것이다.

POST 메소드

POST 메소드는 클라이언트가 요청한 데이터를 서버에게 보내게 한다. 데이터는 서버에서 접근할 수 있는 데이터를 다룰 수 있는 프로그램(CGI등)에 전달된다.

POST 메소드는 다음과 같은 애플리케이션에서 사용될 수 있다.

- 글을 올릴수 있는 네트워크 서비스

- 명령행에서 실행되는 프로그램

- 서버에 있는 문서의 주석

- 데이터베이스 조작

서버는 POST 메소드와 각종 헤더들을 처리한 후, ENTITY 몸체를 URI에 지정된 프로그램에 전달한다. POST 메소드에서 가장 일반적으로 사용되는 인코딩 방법은 URL인코딩이다. 폼으로부터 전달된 데이터가 CGI처리를 위한 변수와 값으로 변환되게 한다.

기타 메소드들에는 LINK, UNLINK, PUT, DELETE, OPTIONS, TRACE, CONNECT 등이 있다.(자세한 정보는 구글신에게 기도를 드리자!)

HTTP Response

다음은 전형적인 HTTP Respose 내용이다.

HTTP/1.1 200 OK

Date: Sat, 19 May 2007 13:49:37 GMT

Server: IBM_HTTP_SERVER/1.3.26.2 Apache/1.3.26 (Unix)

Set-Cookie: tracking=tI8rk7joMx44S2Uu85nSWc

Pragma: no-cache

Expires: Thu, 01 Jan 1970 00:00:00 GMT

Content-Type: text/html;charset=ISO-8859-1

Content-Language: en-US

Content-Length: 24246

( 공백행 )

HTTP/1.1 200 OK

서버는 HTTP버젼, 상태코드, 설명으로 응답을 한다. HTTP버전은 서버가 응답하기 위해 사용하는 HTTP의 버전을 나타내며, 상태코드는 사용자가 요청한 서버의 결과를 나타내는 세자리 숫자이다. 설명은 우리들이 이해할 수 있는 텍스트로 되어있다.

위의 내용의 서버가 사용자의 요청에 HTTP 1.1버전을 사용했다는 것을 나타내고 200이란 상태 코드는 사용자의 요청이 성공적으로 됐다는 것을 의미한다. OK는 200에 대한 우리들이 이해할 수 있는 텍스트이다.

공백행은 헤더의 끝을 나타낸다.

HTTP Header

HTTP 헤더는 클라이언트와 서버 사이에서 모든 종류의 정보를 전송하는데 이용되며 크게 4가지로 분류할 수 있다.

General - 클라이언트, 서버 또는 HTTP와 관계된 정보

Request - 문서 양식과 서버의 매개 변수들

Response - 응답을 보내는 서버에 대한 정보

Entitiy - 클라이언트와 서버 사이에 전송되는 데이터에 대한 정보

HTTP메시지에 있는 모든 헤더는 헤더 이름을 포함하여 콜론, 공백, 헤더의 값 순으로 구성된다. 헤더 이름은 대소문자를 구별하지 않는다. 또한 헤더의 값은 적어도 하나의 공백이나 탭 문자를 각행에 붙임으로써 여러 줄로 확장하여 쓸 수 있다.

일반 헤더와 ENTITY헤더는 서버와 클라이언트 모두 동일하다.

General Header

일반 헤더는 클라이언트의 요청과 서버의 응답 양쪽에서 사용될 수있다.

일반 헤더는 다음과 같은 내용을 가지고 있다.

- Cache-Control

Cache-control: directives

쉼표로 구분된 목록에 캐싱 지시문을 지정

캐시 요청 지시문

ㄱ. no-cache 캐시 하지 않는다.

ㄴ. no-store 신속히 넘긴 후에 정보를 제거한다.

ㄷ. max-age = seconds seconds에 지정한 것보다 오래된 응답은 보내지 않는다.

ㄹ. max-stale [=seconds] 만료된 데이터를 보낸다. 만약 seconds가 지정되어

있다면 지정한 숫자보다 적은 만료된 데이터를 보

낸다.

ㅁ. min-fresh = seconds 명시된 seconds의 수 이후의 변경된 새 데이터만 보낸다.

ㅂ. only-if-cached 새로운 데이터를 검색하지 않고 캐시에 있는 데이터만 반환한다.

캐시 응답 지시문

ㄱ. public 어떠한 캐시라도 캐시할수 있다.

ㄴ. private 공유된 캐시는 캐시하지 않는다.

ㄷ. no-cache 캐시하지 않는다.

ㄹ. no-transform 데이터를 변환하지 않는다.

ㅁ. must-revalidate 클라이언트는 데이터를 재확인 해야 한다.

ㅂ. proxy-revalidate 개인적인 클라이언트 캐시를 제외하고 데이터를 재확인 해야한다.

ㅅ. max-age=seconds 문서는 지정된 seconds만큼만 변화가 없는 상태라고 생각

Connection

Connection: options

options에서는 연결을 위해 지정하는데 프록시 서버에 의한 연결은 포함하지 않는다. close연결 옵션은 클라이언트나 서버 둘 중 하나가 연결을 해제하기를 원한다는 것을 알린다.

Date

Date: dateformat

현재의 날짜와 시간을 표시한다.

예) Mon, 11 May 2000 07:45:00 GMT

때로는 이전과 호환을 위해 RFC-850과 ANSI C asctime() 도 사용할 수 있다.

Monday, 11-May-98 07:45:00 GMT

Mon May 11 07:45:00 2000

단 년도 항목에 2자리를 사용으로 인한 문제가 발생할 수 있다.

MIME-Version

MIME-Version: version

HTTP 트랜젝션에서 사용되는 MIME(RFC-2045[7])의 버전을 말한다.

메시지의 ENTITY몸체가 MIME를 따르지 않으면 이 헤더는 생략될 수 있다. 만약 틀랜잭션에서 MIME-encoded데이터를 호출하지만 이 헤더가 삭제되었다면 디폴트로 1.0을 사용한다.

Progma

Pragma: no-cache

프록시 시스템에 대한 지시문을 말한다. 이 헤더는 목표가 되는 서버에서는 무시된다.

HTTP는 이 헤더를 위해 no-cache라는 지시어만 정의 한다. HTTP 1.0에서, 이 것은 그 로컬 캐시 대신 서버로부터의 문서를 요구하도록 프록시 서버에 명령한다.

단, HTTP1.1은 Cache Control:no-cache를 주로 사용한다.

Transfer-Encoding

Transfer-Encoding: encoding_type

안전한 전송을 위해 메시지 본체에 어떤 종류의 변환이 적용이 됐는지 나태낸다.

Upgrade

Upgrade: protocol/version

우선하는 프로토콜을 명시한다. 응답 코드 101 Switching Protocols과 연결하여 사용된다.

예) Upgrade: HTTP/1.2

Via

Via: protocol host [comment]…

게이트웨이와 프록시에 의해 사용되어 클라이언트와 서버 간의 트랜잭션을 처리하는 프로토콜과 호스트를 표시한다.

클라이언트 요청 헤더

Accept

Accept: type/subtype [; q=qvalue]

클라이언트가 우선적으로 받아들이는 미디어 형을 명시한다. 여러 개의 미디어 형을 쉼표로 구분해서 나열할 수있다. 옵션인 qbalue는 받는 형태의 수준 순서로써 0 에서 1까지 나타낸다.

Accept-Charaset

Accept-Charset: character_set [;q=qvalue]

클라이언트가 우선하는 문자 세트를 지정한다. 여러 개의 문자 세트는 쉼표로 구분하여 나열한다. 옵션인 qvalue는 우선하지 않는 문자 세트의 수준 순서로 0 에서 1까지 나타낸다.

Accept-Encoding

Accept-Encoding: endoding_types

compress 또는 gzip과 같은 클라이언트가 받아들일 수 있는 인코딩 방식을 지정한다. 여러 개의 인코딩 방식을 쉼표로 구분하여 나열한다. 만약 인코딩 형태를 지정하지 않으면 어떤 형태도 클라이언트에게 받아들여지지 않는다.

Accept-Language

Accept-Language: language [; q=qvalue]

클라이언트가 우선적으로 지원하는 언어를 지정한다. 쉼표로 구분해서 여러 개의 언어를 지정할 수 있다. 옵션인 qvalue는 우선하지 않는 언어 순서로 0에서 1까지로 나타낸다. 언어는 두문자로 축약해서 쓴다.(예)en, fr, kr 등

Authorization

Authorization: scheme credentials

URI에 클라이언트가 데이터에 접근할 수 있는 권한을 제공한다. 요청된 문서가 권한을 요구하면 서버는 요구된 권한의 유형을 설명하는 WWW-Authenticate헤더를 반환한다. 그리고 나서 클라이언트는 적당한 권한 정보를 요청할 때마다 이것을 반복한다.

HTTP에 일반적으로 사용된 권한 계획은 BASIC이며, BASIC방식에서는 권한을 인증하기 위해 base64로 인코딩된 username:password 형태를 따른다. 예를 들면, 사용 자명이 ‘webmaster’ 이고 패스워드가‘zrma4v’라면 authorization 헤더는 이것을 다음과 같이 보이게 한다.

Authorization: BASIC d2VibWFzdGVyOnpycW1hNHY=

이것의 디코딩 값은 webmaster : zrma4v이다

Cookie

Cookie: name=value

URL을 위해 저장된 정보의 이름=값을 포함한다. 여러 개의 쿠키는 세미콜론으로 구분하여 나열된다. 넷스키이프도 쿠키를 지원한다. HTTP표준에는 포함되어 있지 않다.

From

From: email_address

현재 사용하고 있는 클라이언트의 전자 우편 주소를 반환한다.

Host

Host: hostname[:port]

호스트의 이름과 URI의 port번호를 지정한다. 클라이언트는 HTTP1.1에 반드시 이정보를 공급해야 하는데 이것은 여러 개의 호스트명이 갖는 애매한 URL을 쉽게 구별하는 데 도움이 된다.

If-Modified-Since

If-Modified-Since: date

헤더의 값으로 주어진 날짜 이후 수정이 되었다면 URI데이터를 보낸다는 것을 명시한다. 이것은 클라이언트 측 캐시에 대해 유용하다. 만약 문서가 수정되지 않았다면 서버는 304코드를 반환하여 클라이언트에게 로컬에 있는 사본을 보여준다. 단 지정한 날짜는 Date헤더 아래에 설명된 형식을 따라야 한다.

If-Match

If-Match: entity_tag

조건적으로 요청하는 것으로 주어진 ENTITY태그와 매치된다. *기호는 어떠한 ENTITY와도 매치되며, ENTITY가 존재해야만 트랜잭션이 계속된다.

If-None-Match

If-None-Match: entity_tag

조건적으로 요청하는 것으로 주어진 엔티티 태그와 어떠한 것도 매치되지 않는다.

*기호는 어떠한 엔티티와도 매치되며 엔티티가 존재하지 않아야만 트랜잭션이 계속된다.

If-Range

If-Range: entity_tag | date

조건적으로 요청하는 것으로 실체의 일부가 변하지 않았는데 찾을 수 없고, 그것이 실체의 전부를 나타낸다. Range헤더와 함께 사용되어야 한다. ENTITY 태그나 날짜 둘 중 하나는 이미 주어진 실체의 일부분을 식별할 수 있다.

If-Unmodified-Since

If-Unmodified-Since: date

주어진 날짜 이후로 수정되지 않았다면 URI데이터를 보내도록 지정한다. 지정한 날짜는 Date헤더 아래에 설명된 형식을 따라야 한다.

Max-Forwards

Max-Forwards: n

요청을 전달한 프록시나 게이트 웨이의 개수를 제한한다. TRACE 메소드와 함께 사용하여 디버깅에 유용하며, 무한 루프를 피할 수 있다.

Proxy-Authorization

Proxy-Authorization: credentials

클라이언트가 권한을 요구하는 프록시에 대해 자신을 식별하기 위해 사용한다.

Range

Range: bytes= n-m

문서가 요구하는 부분적인 범위를 명시한다. 여러 개의 범위는 세미콜론으로 구분하여 나열한다. 만약 쉼표로 구별된 바이트 범위인 첫번째 숫자가 없다면 범위는 문서의 끝에서부터 없어진다고 가정한다. 만일 두번째 숫자가 없다면 범위는 끝에서 n바이트까지이다. 첫번째 바이트는 0바이트이다.

Referer

Referer: url

요청된 URI를 참조하는 문서의 URI에 전달한다.

User-Agent

User-Agent: string

클라이언트 프로그램에 대한 식별 가능한 정보를 준다.

서버 응답 헤더

Accept-Ranges

Accept-Ranges: bytes|none

URI를 위한 요청 범위의 승인을 나타내며 또는 받아들인 요청의 범위가 없을 경우 none을 지정한다. 범위의 단위는 byte이다.

Age

Age: seconds

seconds에 문서의 나이를 지시한다.

Proxy-Authenticate

Proxy-Authenticate: scheme realm

확인 계획과 이URI와 그 현재의 연결에 대해 프록시에 대한 적용할 수 있는 매개변수를 나타낸다. 응답으로 407을 사용한다.

Retry-After

Retry-After: dateseconds

응답코드 5 0 3(Service Uncavailable)과 함께 사용된다. 정수나GMT 날짜와 시간(D a t e헤더 형태를 설명)둘 중 하나를 포함한다. 만일 값이 정수이면 seconds의 숫자로 해석하여 요청이 발생한 후 지정한 seconds만큼 기다린다.

예) Retry-After: 3500

Retry-After: Fri, 17 May 1999 12:24:17 GMT

Server

Server: string

서버의 이름과 버전 번호를 포함한다.

예) Server: NCSA/1.3

Set-Cookie

Set-Cookie: name=value [; option ]

U R L을 위해 보유한 정보의 이름/값 쌍을 포함한다. 넷스케이프 쿠키를 지원하기 위

한 것으로 HTTP 표준에는 포함되어 있지 않다.

옵션의 예)

expires=date

지정된 날짜가 지나면 쿠키가 유효하지 않게 된다.

path=pathname

쿠키가 유효한URL 범위

domain=domain_name

쿠키가 유효한 도메인명의 범위

secure

보안이 적용된 연결에서만 쿠키를 반환한다.

Vary

Vary: *| headers

엔티티가 다중 자원을 가지고 있으므로 요청한 헤더를 지정한 목록이 상황에 따라 변할 수 있다는 것을 지정한다. 여러 개의 헤더는 세미콜론으로 구분하여 나열한다.

*기호는 요청한 헤더가 반환되는 문서에 영향을 미칠 수도 있는 다른 요인을 의미 한다.

Warning

Warning: code host [ :port] string

프록시 캐싱에서 사용하기 위한 상태 코드의 추가 정보를 나타낸다. host필드는 이름 또는 서버 호스트의 익명을 포함하며, 선택적으로 포트 번호를 포함한다. 두 자리 경고 코드와 그것을 설명하는 문자열은 다음과 같다.

10 Response is stale

응답 데이터는 오래된 것으로 알려져 있다.

11 Revalidation failed

응답 데이터는 오래된 것으로 알려져 있으며 그 이유는 프록시가 데이터를 재검증하는 데 실패했기 때문이다.

12 Disconnected operation

캐시가 네트워크로부터 연결되지 않았다.

13 Heuristic expiration

데이터는2 4시간 이상 된 것이며, 캐시는2 4시간 보다 더 이전에 만들어진 것을 사용한다.

14 Transformation applied

프록시는Content-Encoding이나 Content-Type 헤더에 명시한 대로 인코딩이나 문서의 미디어 형을 변경시켰다.

99 Miscellaneous warning

임의의 정보가 클라이언트에게 접속되거나 나타났다.

WWW-Authenticate

WWW-Authenticate: scheme realm

401(Unauthorized) 응답 코드와 함께 사용된다. 요청된 URI에서 클라이언트로부터 요청된 권한의 범위와 권한의 계획을 명시한다. 많은 다른 권한 범위는 서버에 존재한다. 일반적인 권한 계획은 BASIC이며 사용자명과 패스워드를 요구한다.

예) WWW-Authenticate: BASIC realm="admin"

ENTITY Header

Allow

Allow: methods

지정한 URI에서 허락하는 메소드를 쉼표로 구분된 목록을 포함한다. 요청된 정보에 유용한 메소드들을 클라이언트에게 알리는 코드 405(Method Not Allow)를 서버 응답에 사용한다.

Content-Encoding

Content-Encoding: encoding_schemes

엔티티 몸체를 전송할 때 사용할 인코딩 체계(scheme)를 지정한다. 값으로는gzip(또는 x-gzip)과 compress(또는 x-compress)를 사용할 수 있다. 만약 여러 개의 인코딩 체계(쉼표로 구별한 목록 안에)가 지정되어 있다면 소스 데이터에 적용한 명령을 나열해야 한다.

Content-Language

Content-Language: languages

전송될 엔티티 몸체에서 의도하는 언어를 지정한다. 언어는 두 자리 숫자 코드로 나타낸다.(예, en, kr 등)

Content-Length

Content-Length: n

이 헤더는 전송된 엔티티 몸체가 가진 데이터의 길이(byte 단위로)를 지정한다. 어떤요청은 동적인 성질을 가질 수 있기 때문에 컨텐츠의 길이를 알 수 없을 경우도 있고, 이 경우에는 이 헤더를 제거한다.

Content-Location

Content-Location: uri

엔티티에 대한 URI를 제공한다. 이 경우 문서가 독립적으로 접근 가능한 위치에 다중 엔티티를 갖고 있을 수 있다. U R I는 절대 혹은 상대 경로로 지정할 수 있다.

Content-MD5

Content-MD5: digest

인수한 메시지의 완전성을 검사하기 위해 엔티티의 MD5 다이제스트를 제공한다.

Content-Range

Content-Range: bytes n-m/length

수반하는 엔티티 몸체 일부에 삽입되며, 전체 엔티티 몸체의 크기를 지정한다.

예)Content-Range: bytes 6143-7166/15339

Content-Transfer-Encoding

Content-Transfer-Encoding: scheme

네트워크에 전달되는 엔티티 몸체에 적용되는 어떤 변화를 지정한다. 일반적인 값으로는 7bit, 8bit, binary, base64, 그리고 quoted-printable이 있다.

Content-Type

Content-Type: type/subtype

엔티티 몸체의 미디어 형과 부미디어 형을 설명한다. 이는 같은 값을 클라이언트의Accept 헤더로 사용하며, 서버는 그 클라이언트가 우선적으로 지원하는 포맷 양식에 따르는 미디어 형을 반환해야 한다.

ETag

ETag: entity_tag

If-Match와 If-None-Match 요청 헤더를 위한 태그를 정의한다.

Expires

Expires: date

문서가 변경될 수도 있을 때의 시간 또는 그것의 정보가 유효하지 않을 때의 시간을명시한다. 그 시간 이후, 문서는 변경 또는 삭제되거나 그렇지 않을 수 있다. 값은 Date 헤더에서 설명한 것과 같은 유효한 형태의 날짜와 시간이다.

Last-Modified

Last-Modified: date

지정한 URI가 마지막으로 변경된 때를 명시한다. 값은Date 헤더에 설명한 것과 같은 유효한 형태의 날짜와 시간이다.

Location

Location: uri

문서의 새로운 위치를 지정한다. 일반적으로 응답 코드 201(Created), 301(MovedPerm anently), 또는302(Moved Temporarily)와 함께 사용된다. 주어진URI는 절대 주소로 지정해야 한다.

쿠키

항구적인 상태에 있는 클라이언트측 쿠키는 넷스케이프 네비게이터에서 소개한 것으로, 서버가 클라이언트의 장치에서 클라이언트가 지정한 정보를 저장할 수 있게 하기 위한 것이다. 서버는 클라이언트에 의해 다시 특정한 페이지나 서버에 접근할 때 그 정보를 이용할 수 있다. 쿠키 작동 형태는 서버가 각 클라이언트에 보내는 페이지를 개별화할 수 있도록 해주거나 사이트의 다양한 페이지들을 브라우징할 때 클라이언트가 선택했던 것들을 기억할 수 있게 해준다. 따라서 서버측에서 복잡한 CGI나 데이터베이스 시스템을 사용하지 않아도 된다.

쿠키는 다음과 같은 방법으로 작동한다. CGI 프로그램은 새로운 사용자를 식별할 때,서버가 클라이언트의 입력에서 조금씩 모아둔 정보와 그 사용자에 대한 식별자를 포함에 부가 헤더를 추가한다. 이 헤더는 클라이언트의 쿠키 파일에 사용자의 쿠키정보를 추가하라고 쿠키를 사용할 수 있는 브라우저에 알린다. 그러면, 웹 브라우저 URL의 모든 요청은 기타 헤더의 요청에 그 쿠키 정보를 포함시킬 것이며, CGI 프로그램은 특정한 사용자에게 맞추어진 문서를 보여줄 때 이 정보를 사용한다.

쿠키는 클라이언트의 하드 드라이브에 저장되므로 정보는 웹 브라우저가 닫히고 다시 열어도 남아 있다.

Set-Cookie 응답 헤더

사용자가 처음으로 사이트나 페이지를 방문하면 쿠키가 생성된다. CGI 프로그램은 사용자 요청을 받으면 이전의 쿠키 정보를 검색한다. 만약 쿠키가 없다면 Set-Cookie 헤더를 포함하는 응답을 보낸다. 이 헤더에는 클라이언트에 대해 유지하고자 하는 정보를 담고 있는 이름/값 으로 포함되어 있다. 헤더에 다른 선택 필드들도 포함시킬 수 있다.

Set-Cookie 헤더는 다음과 같은 구문을 사용한다.

Set-Cookie: name=value; expires=date;

path=pathname; domain=domain-name; secure

여러 개의 Set-Cookie 헤더는 서버 응답에 포함될 수 있다. ‘이름=값’으로 이루어진쌍은 이 헤더에 요구되는 유일한 속성이며, 처음에 와야 한다. 그 다음 속성들은 순서 없이 사용할 수 있고 다음과 같이 정의한다.

name=value

이름과 값 모두에 세미콜론, 공백(space), 또는 탭(tab)을 포함하지 않는 문자열을 지정한다. 스크립트를 다룰 준비가 되는 한, 실체가 그 이름이나 값에서URL 인코딩과 같은 인코딩을 요구한다면 사용할 수 있다.

expires=date

이 속성으로 쿠키의 유효 기간이 끝나는 날짜를 설정한다. 날짜의 형식은 표준적인 방법을 따르지 않고 다음과 같이 지정한다.

Wednesday, 01-Sep-96 00:00:00 GMT

이 날짜가 지나면 쿠키의 유효성이 만료하여 웹 브라우저가 더 이상 쿠키를 보내지 않는다. 만료일 표시에는 G M T(Greenwich Mean Time)만 사용된다. 만료일을 지정하지 않으면 쿠키는 현재 세션에서만 사용된다.

path=pathname

path 속성은 쿠키가 유효한 URL의 범위를 제공한다. 예를 들어, 경로명을/ pub라고 설정하면 /pub에 있는 /pub/docs나 /pub/images와 같은 하위 수준의 URL에도 쿠키를 보낸다. ‘/’의 pathname을 나타낸다면 쿠키가 지원하는 사이트의 모든 URL에 쿠키를 사용할 것이라는 뜻이다. path 속성이 없다면 쿠키는 URL에 지원하는 곳에서만 유효하다는 것을 뜻한다.

domain=domain-name

이 속성은 쿠키가 반환되는 범위의 도메인 이름을 지정한 것이다. domain-name에는 적어도 두 개의 점(.)이 포함되어 있어야 한다. 예를 들면, .naver.com이라는 값은 www.naver.com와 cafe.naver.com, 그리고 기타 다른 naver.com 도메인을 갖는 서버 전체를 포괄한다.

secure

이 속성은 보안이 되는 연결(SHTTP와 SSL을 통한)에서만 쿠키를 반환한다는 것을 뜻한다. 이 속성이 없으면 쿠키는 연결에 상관없이 항상 반환된다.

쿠키 요청 헤더

웹 브라우저는 매번 웹 페이지로 가서 U R L을 위해 저장된 쿠키에 대한 쿠키 파일이있는지 검사한다. 파일이 있으면 웹 브라우저는 요청에 쿠키의‘이름=값’쌍을 포함하는 Cookie 헤더를 포함시킨다.

Cookie: name1=value1;name2=value2;…

쿠키 파일 안에 반환된 쿠키가 여러 개의 항목으로 구성되어 있다면, 경로명 범위와도메인의 범위로 구성한다. 다음 헤더에 같은 사이트에 대해 두 개의 쿠키가 설정되어 있는 예이다.

Set-Cookie: AbcBook=book; path=/

Set-Cookie: AbcBook=Bitems; path=/books

브라우저가 /books 경로에 있는 사이트의 한 페이지를 요청하면, 그것을 반환한다.

Cookie: AbcBook=Bitems; AbcBook=Bitems

양쪽 항목이 같은 이름을 공유하지만, 그것은 별개의 쿠키이며, 양쪽 다 /books 같은 특정한 URL에 적용된다. 쿠키가 반환될 때, 웹 브라우저는 매치 여부를 따져 가장 정확한 경로명이나 도메인을 먼저 반환한다.

Cookie 헤더를 만나면 많은 서버들은 HTTP_COOKIE 환경 변수를 사용하는CGI 프로

그램으로 헤더의 값을 전달한다.

또한 쿠키들의 개수와 크기에 대한 제약이 있다.

- 클라이언트는 합쳐서 적어도 3 0 0개의 쿠키를 지원할 수 있어야 한다. 서버는 사

용자가 더 이상 저장하는 것을 기대해서는 안 된다.

- 각 쿠키(이름과 값을 조합해서)의 크기는4 K B를 넘어서는 안 된다.

- 각각의 서버 또는 도메인은 최대 2 0개의 쿠키를 지원한다. 이 제약 사항은 각기 지정한 서버 또는 도메인에 적용되므로 www.naver.com에서 20개를 저장할 수 있고 cafe.naver.com에서도 20개가 가능하며, 쿠키들의 이름 전체를 각기 명시 할 수 있다.

하지만 문제는 헤더와 관련된 프록시 서버에서 일어난다. 페이지가 캐시되거나 수정되지 않았을지라도, Set-Cookie와 Cookie 헤더 모두는 프록시를 통해 전파되어야 한다(If-Modified-Since 조건에 따라서). 또한 Set-Cookie 헤더는 프록시에 의해 결코 캐시 되어서는 안 된다.

상태 코드

위에서 언급한 서버의 응답에서 요청한 상태를 표시하는 세자리 숫자와 상태를 설명하는 짧은 문구를 포함하는 것을 다음과 같이 나눌 수 있다.

코드 범위

응답의 의미

100 ~ 199

200 ~ 299

300 ~ 399

400 ~ 499

500 ~ 599

정보

클라이언트의 요청이 성공적이다.

다른 동작이 더 필요해 클라이언트의 요청을 리다이렉트 했다.

클라이언트의 요청이 불완전하다.

서버오류

100 ~199 정보 응답

100 Continue

요청된 초기 부분은 접수되었고 클라이언트는 계속해서 요청할 수 있다.

101 Switching Protocols

서버는 Upgrade 헤더 필드에 명시된 프로토콜로 교환하기 위한 클라이언트 요청

에 따르고 있다.

200~299 클라이언트 요청의 성공 응답

200-299의 범위에 있는 응답은 클라이언트의 요청이 성공적이었다는 것을 의미한다.

200 OK

클라이언트의요청이성공적이였으며, 서버는요청한데이터를포함하여응답한다.

201 Created

이 상태 코드는 새로운 URI가 만들어질 때마다 사용된다. 결과 코드와 함께 새로

운 데이터가 위치한 곳을 지정하기 위해 Location 헤더가 서버에 의해 주어진다.

202 Accepted

요청은 받아들여 졌지만 즉시 실행되지는 않는다. 트랜잭션에 대한 심층 정보가 서버 응답의 엔티티 몸체에서 주어지기도 한다. 주의할 점은 요청이 정당한 것처럼 보였을 수도 있지만 서버가 요청을 실제로 승인하리라는 보장은 없다는 것이다.

203 Non-Authoritative Information

엔티티 헤더에 있는 정보는 원래 서버가 아니라 로컬이나 다른 서버로부터 온다.

204 No Content

이 코드는 응답할 때 주어지는 헤더이다. 그러나 응답된 실제 내용은 없다는 뜻이다. 이런 응답을 받는 이유는 웹 브라우저가 문서를 보기 위해 갱신을 하지 않았기 때문이다. 이미지맵에서 클라이언트가 이미지의 영역 중 사용하지 않거나 공백인 부분을 클릭했을 때를 처리할 때 유용하다.

205 Reset Content

웹 브라우저가 추가적인 입력을 위해 사용된 트랜잭션을 지우는 것이다. CGI 애플리케이션에서 데이터를 입력받을 때 적합하다.

206 Partial Content

서버가 요청된 크기의 부분 데이터를 반환하고 있다. Range 헤더 지정 요청에 응답하는 데 이용된다. 서버는 반드시 Content-Range 헤더와 응답에 포함된 범위를 지정해야 한다.

300~399 리다이렉션

300~399 범위에 있는 응답 코드는 요청이 수행되지 않았다는 것을 나타내며, 클라이언트는 요청을 성공시키기 위해 다른 행위가 필요하다는 것을 나타낸다.

300 Multiple Choices

요청된 URI는 하나 이상의 리소스를 참조한다. 예를 들면, URI는 여러 개의 언어로 변환된 문서를 참조할 수 있다. 서버에 의해 반환된 엔티티 몸체는 올바른 리소스를선택하는 방법에 대한좀 더 특정한 데이터의 목록을 가지고 있을수 있다.

301 Moved Permanently

요청된 URI는 더 이상 사용되지 않으며 요청에서 지정한 연산은 수행되지 않았다. 요청된 문서를 위한 새로운 위치는 Location 헤더에 명시한다. 앞으로 요청될 모든 문서는 새로운 URI를 사용할 것이다.

302 Found

요청된 URI는 일시적으로 새로운 URI를 가진다. Location 헤더는 새로운 장소를 가리킨다. 만일 이것이 GET이나 HEAD 메소드에 대한 응답이라면 클라이언트는 응답을 받자마자 요청을 해결하기 위해 새로운 URI를 사용해야 한다.

303 See Other

요청된 URI는 다른 URI(Location 헤더에 명시한)에서 찾을 수 있으며, 리소스는 GET 메소드로 구할 수 있다.

304 Not Modified

이것은 If-Modified-Since 헤더에 대한 응답 코드로써 지정한 날짜 이래로 수정되지 않았다. 엔티티 몸체는 보내지 않으며, 클라이언트는 자신의 로컬 사본을 사용해야 한다.

305 Use Proxy

요청된 URI는 Location 헤더에 있는 프록시를 통해서만 접근할 수 있다.

307 Temporary Redirect

요청된 URI가 일시적으로 옮겨졌다. Location 헤더가 새로운 장소를 가리킨다. 이 상태 코드를 받는 즉시, 클라이언트는 요청을 해결하기 위해 새로운 URI를 사용해야 하지만, 앞으로 모든 요청들은 이전의 URI를 사용할 것이다.

400~499 클라이언트 요청의 불안전 응답

400~499 범위에 있는 응답 코드는 클라이언트의 요청이 불안전하며, 클라이언트가 요

청을 성공시키려면 다른 정보가 필요하다는 것을 나타낸다.

400 Bad Request

이 응답 코드는 클라이언트의 요청에 문법적인 오류가 있는 것을 서버가 알아냈다는 것을 의미한다.

401 Unauthorized

이 결과 코드는 WWW-Authenticate 헤더와 함께 그 요청에 적당한 권한이 부족했다는 것을 나타내기 위해 주어지며, 이 URI를 다시 요구하면 클라이언트는 적당한 권한으로 접속해야 한다.

402 Payment Required

이 코드는 아직 HTTP로 구현되지 않았다. 하지만 언젠가는 서버의 문서를 받아 보기 위해 지불이 필요하다는 것을 나타낸다.

403 Forbidden

이 요청은 서버가 클라이언트를 가리키고 싶어하지 않아(또는 아무 이유 없이) 거부되었다.

404 Not Found

지정한 URI에 문서가 존재하지 않는다.

405 Method Not Allowed

이 코드는 Allow 헤더와 함께 클라이언트가 사용한 메소드가 이 URI에 대해 지원되지 않는다는 의미이다.

406 Not Acceptable

클라이언트가 지정한 URI는 존재하지만 클라이언트가 원하는 형식이 아니다. 이 코드와 함께 서버는 Content-Language, Content-Encoding, 그리고 Content-Type 헤더를 제공한다.

407 Proxy Authentication Required

프록시 서버는 요청된 문서를 보여주기 전에 권한을 필요로 한다. Proxy-Authenticate헤더와 함께 사용한다.

408 Request Time-out

이 응답 코드는 클라이언트의 모든 요청이 지정한 시간(일반적으로 서버의 구성할때 명시한다) 동안 처리되지 않았음을 뜻하며, 서버는 네트워크 연결을 끊는다.

409 Conflict

이 코드는 다른 요청이나 서버의 구성과 충돌이 있음을 나타낸다. 충돌에대한 정보는 응답되는 데이터의 일부로 반환된다.

410 Gone

이 코드는 요청된 URI가 더 이상 존재하지 않고, 서버에서 완전히 사라졌음을 나타낸다.

411 Length Required

서버는Content-Length 헤더가 없는 요청을 받아들이지 않는다.

412 Precondition Failed

하나 이상의 If…헤더에 의해 명시된 조건에 의해 요청을 평가하여 false 값을 가지는 경우이다.

413 Request Entity Too Large

서버는 실제 본문이 너무 커서 요청을 처리할 수 없다.

414 Request-URI Too Long

서버는 요청된 URI가 너무 커서 요청을 처리할 수 없다.

415 Unsupported Media Type

서버는 실제 본문이 지원되는 않는 형식이라 처리할 수 없다.

416 Requested Range Not Satisfiable

서버는 목표에 대해 어떤 유효한 값도 포함하지 않은 Range 헤더를 찾아냈다. 추

가로 If-Range 헤더는 없어졌다.

417 Expectation Failed

Expect 헤더에서 명시된 조건은 만족될 수 없다.

500~599서버 오류

500~599 범위에 있는 응답 코드는 서버가 오류를 만나거나, 클라이언트의 요청을 수행할 수 없음을 나타낸다.

500 Internal Server Error

이 코드는 서버의 일부(예를 들면, CGI 프로그램)가 멈추었거나 설정에서 오류가 났음을 나타낸다.

501 Not Implemented

이 코드는 클라이언트의 요청된 행위가 서버에서 수행할 수 없음을 나타낸다.

502 Bad Gateway

이 코드는 서버(또는 프록시)가 다른 서버(또는 프록시)로부터의 응답이 적절하지 않음을 나타낸다.

503 Service Unavailable

이 코드는 서비스를 일시적으로 제공할 수 없으나, 앞으로 복구된다는 의미이다.만일 서버가 복구될 때를 알기 위해서는 Retry-After 헤더도 함께 제공해야 한다.

504 Gateway Time-out

이 응답은 게이트웨이나 프록시의 시간이 경과했다는 것만 빼고는 408(Request Time-out)과 같다.

505 HTTP Version not supported

서버가 요청에 사용된HTTP 프로토콜 버전을 지원하지 않는다.

Posted by 나비:D
:

사내 웹사이트 구축 번거롭고 힘드셨죠?
이제 Visio 2007의 웹사이트 관리 기능을 이용해 보세요.
시간낭비와 고민하실 필요 없이 효율적으로 웹사이트를 계획하고 관리하실 수 있습니다.
어떤 프로그램을 이용했을지 궁금해 하실 것 같아 알려드립니다~ ^^


사내 웹사이트 구축에 참여해 본 분들이시라면 다음의 이야기에 공감하실 겁니다.

웹사이트 구축을 의뢰한 사측 관리자는 보통은 복잡한 문서를 넘겨주고 웹사이트에 들어갈 자료이니 알아서 분류해서 메뉴를 만들어 달라고 요구를 합니다. 웹사이트 개발을 맡은 개발자는 혼자서 아이디어를 구상하고 열심히 웹사이트를 만들고 나면, 왠지 구조가 맘에 안 들거나 구성이 짜임새가 없어 보인다고 핀잔을 듣기 일쑤입니다. 서로의 의견이 조율될 때까지 개발자는 스트레스와 업무에 시달리게 되고, 관리자는 늦어지는 사이트 오픈에 조바심과 불안함을 가지고 지켜보게 됩니다. 결국, 적당한 합의를 보고 사이트를 오픈 하지만 100% 맘에 들 수는 없다는 말로 위안을 삼죠.. 여러분 언제까지 이런 일들을 반복하실 건가요?
또 이렇게 어렵게 구축한 웹사이트 제대로 운영되고 있는지 확인은 해보시나요? Visio 2007의 웹사이트 관리 기능을 이용하여 가장 효율적으로 웹사이트를 계획하고 관리하는 방법을 알려드리겠습니다.
이번 팁을 통해서 익히게 되는 기능을 정리하면 다음과 같습니다. 1. 웹사이트 개념도 작성
2. 웹사이트 맵 작성


웹사이트 구축과 관리를 위한 템플릿 Visio 2007는 웹사이트를 구축하고 관리하기 위한 템플릿을 제공하고 있습니다. 1. [파일]-[새로 만들기]-[시작] 메뉴를 이용하면 다양한 템플릿을 선택할 수 있습니다.
그 중 [네트워크] 또는 [소프트웨어 및 데이터 베이스] 범주에서 웹사이트 템플릿을 찾을 수 있습니다.



2. 아래 이미지는 Visioplus.com 사이트 기획 당시 [웹 사이트 개념도]를 이용하여 사이트를 기획한 결과물입니다. [웹 사이트 개념도]는 아래와 같이 웹 사이트의 콘텐츠, 메뉴 구분, 디렉터리 구분 등 관리자와 개발자 사이에 커뮤니케이션을 편리하게 하기 위해 사용합니다.


3. [웹 사이트 개념도]를 이용하는 방법은 순서도, 조직도 그리는 방법과 유사합니다.
웹사이트 개념도에서 제공하는 [웹 사이트 개념도 셰이프]를 이용하여 적절히 관계를 연결하면 됩니다. 이전 팁들을 통해 셰이프를 연결하고 활용하는 방법을 알아봤으므로, 이번 팁은 [웹사이트 맵]을 위주로 진행하겠습니다.


4. Visio 2007을 실행시키고 [템플릿 범주]에서 [소프트웨어 및 데이터베이스]를 선택하고 [웹 사이트 맵]을 클릭합니다.


5. 웹사이트 맵을 시작하면 다음과 같이 웹 주소를 넣을 수 있는 창이 나타납니다.
자주 들어오는 오피스튜터 사이트는 어떻게 관리되고 있는지 한번 확인해볼까요?
[주소] 입력란에 http://www.officetutor.co.kr 을 입력합니다.


6. 만일 사이트를 읽어올 때, 읽혀지는 사이트의 설정을 조정하고 싶다면, [설정] 메뉴를 클릭합니다.

1)[웹사이트 맵 설정]의 [레이아웃]탭에서 읽어오려는 링크의 최대 수와 링크 수준 (depth) 등을 조절할 수 있습니다.
[기본 셰이프 텍스트]는 사이트를 읽어서 그 사이트를 표시할 때 주소를 표시하도록 하거나 HTML 제목을 표시하면, 확인하기에 편리합니다.
지금은 기본 설정인 [상대 URL]을 선택합니다.



2)[확장명],[프로토콜],[특성] 탭에서는 인식할 수 있는 웹 사이트의 형식, 종류를 구분하여 선택할 수 있습니다. ① [프로토콜] 탭
Visio 2007의 경우 HTTP, HTTPS, File, FTP, GOPHER, MailTo, NEWS, NNTP, PROSPERO, TELNET, WAIS 등의 프로토콜을 지원합니다. ② [특성] 탭
웹 사이트 맵은 HTML내의 하이퍼링크 값을 읽어서 표현하게 된다. 상황에 따라서 아래와 같은 HTML 태그 내부에 정의된 속성의 링크 값들은 표시하지 않도록 조절할 수 있다.


3)[고급] 탭에는 사이트 맵을 그리기 위한 영역을 설정합니다.


① 검색조건
다음 3가지 다른 방법 중 한 가지 검색 방법을 선택합니다. I. 검색한 모든 파일 분석 : 조건 없이 모든 링크된 사이트를 검색합니다.
II. 지정한 도메인에 있는 파일 분석 : 입력 주소의 도메인 내부에 포함된 사이트를 검색합니다.
III. 지정한 디렉터리에 있는 파일 분석 : 입력 주소와 같은 폴더 내의 사이트를 검색합니다. ② HTTP 인증
만일, 웹 서버에 접근할 때에 암호 인증이 필요하다면, HTTP 인증란에 아이디와 패스워드를 입력합니다.


7. [설정] 메뉴의 모든 옵션을 기본 상태로 유지하기 위해 [웹 사이트 맵 설정] 창의 [취소] 버튼을 누르고 빠져나옵니다. 8. 마지막 단계로 웹 사이트 맵을 그리기 위해 [사이트 맵 생성] 창에서 [확인]을 클릭합니다.



9. 드디어 입력한 사이트의 웹사이트 맵이 그려졌습니다.


10. 각 아이콘이 무엇을 나타내는지는 [웹 사이트 맵 셰이프]의 셰이프를 확인하면 알 수 있습니다.


11. 대부분의 맵 셰이프 옆에는 아래와 같이 군인 마크와 같은 모양이 덧붙여져 있습니다.
이 표시는 이 사이트를 확장할 수 있다는 표시입니다.


12. 마우스 오른쪽 버튼을 클릭한 후 바로 가기 메뉴 중 [하이퍼링크 확장]을 선택하여 사이트의 링크 정보를 트리 구조로 확인할 수 있습니다.


13. [하이퍼링크 확장]메뉴를 클릭하면 모든 트리의 마지막에 선택한 셰이프의 복사본과 그와 링크된 사이트들이 추가로 표시됩니다.


14. 사이트 맵 중간에 아래와 같이 X 표시가 빨갛게 되어 있는 사이트도 있습니다.
이미지의 X 표시는 읽어온 콘텐츠에 연결된 하이퍼링크 주소가 정확하지 않을 경우 나타납니다. 웹 사이트에 잘못된 주소가 없는지 확인하는 것도 웹 사이트 맵을 그리는 가장 큰 이유 중 하나입니다.


15. 사이트 맵으로 그려진 구조가 너무 복잡하거나 콘텐츠가 너무 많을 경우, 그 종류에 따라 구분하여 볼 수 있도록 [필터 창]과 [목록 창]을 제공하고 있습니다.
각 창의 리스트 앞에 있는 체크박스의 선택을 해제하면 해당되는 페이지와 그와 연결된 하이퍼링크, 또는 해제된 종류의 콘텐츠는 사이트 맵에서 지워지게 됩니다.


16. 마지막으로 웹사이트 맵이 제공하는 또 하나의 멋진 기능인 [보고서]를 이용해 보도록 하겠습니다. [웹 사이트 맵]-[보고서]를 클릭합니다.
사이트 맵을 이용하여 깨진 링크, 등록된 콘텐츠, 사이트의 구조 등을 시각화하여 파악하기도 이 사이트 맵을 텍스트로 표시하여 엑셀 파일로 변환하여 모든 링크 정보를 표시하거나, 오류를 가진 링크 정보를 보고서로 출력할 수 있습니다.


17. [보고서] 리스트에서 웹 사이트 맵 링크(오류 포함)을 선택하여 보고서를 작성해 보겠습니다. [보고서] 창의 보고서 목록 중 [웹 사이트 맵 링크(오류 포함)]을 선택하고 [실행]을 클릭합니다.


18. [보고서 실행] 창의 [보고서 형식 선택] 목록 중에서 [Excel]을 선택하고 [확인]을 클릭합니다.


19. 오피스튜터 사이트는 1개의 링크가 깨져있고, 이 링크는 비트맵 파일과 연결된 링크입니다.


실전 응용
관리자님을 대신하여 제가 깨진 링크를 확장하여 어떤 비트맵 파일인지 확인해보겠습니다.
위에서 다룬 방법 중 사이트를 선택하여 마우스 오른쪽 메뉴를 보면 [하이퍼링크 확장]이 있었죠. 이 기능을 이용하여 깨진 사이트를 확장하였더니 아래와 같은 트리가 생성이 되었습니다.



자 이제 어떤 경로에 있는 그림인지 파악이 되시죠?
링크가 정상인 사이트는 하이퍼링크를 이용하여 그 콘텐츠를 확인할 수 있습니다.


출처 :
Posted by 나비:D
:
현재 착수하고 있는 새로운 ASP.NET MVC프레임웍을 커버하는 블로그 시리즈의 1번째를 포스팅했다. 이 시리즈의 1번째글에서는 간단하게 전자거래의 제품 목록표시나 검색사이트를 구축했다. 그곳에서는 MVC뒤에 있는 고급레벨 개념을 커버하고 있어, ASP.NET MVC프로젝트를 아무것도 없는 상태에서 만들어 제품목록표시기능을 만들고 테스트하는 방법을 소개했다.

오늘 블로그에서는 ASP.NET MVC 프레임웍의 URL 라우팅 아키텍쳐에 대해서 깊히 알아볼 것이고 응용프로그램으로 보다 고급 시나리오로 사용하는 방법을 몇가지 이야기하겠다.

파트1의 간단한 리뷰
이 시리즈의 파트1에서는 3개의 타입 URL을 공개하는 전자거래 사이트를 만들었다.

 URL 포멧  동작  URL 예
 /Products/Categories  모든 Product Categories를 검색  /Products/Categories
 /Products/List/Category  Category내 Products을 목록화  /Products/List/Beverages
 /Products/Detail/ProductID  특정 Product의 상세표시  /Products/Detail/34

이런 URL을 아래와 같이 :ProductsController"클래스를 만들어 처리했다.

step11.jpg

위 클래스가 응용프로그램에 추가되면 ASP.NET MVC프레임웍은 컨트롤러에서 처리를 하는데 적절한 액션 메소드에 자동적으로 들어온 URL을 라우팅처리한다.

오늘 블로그 글은 확실하게 이 URL 매핑이 어떻게 하는지 알아보는 것과 동시에 ASP.NET MVC프레임웍으로 활용할 수 있는 고급 시나리오를 알아보자. 또한, URL라우팅의 시나리오를 간단하게 테스트하는 방법도 소개하겠다.

ASP.NET MVC URL 라우팅 시스템은 무엇을 실행하는가?
ASP.NET MVC 프레임웍에서는 유연한 URL 라우팅 시스템이 있어 응용프로그램으로 URL매핑 규칙을 정의할 수 있다. 이 라우팅 시스템에는 주로 2가지 목적이 있다.

1. 들어오는 URL을 응용프로그램에 맵 및 그런 루트의 결정에 의해 알맞은 컨트롤러와 액션메소드가 처리를 실행한다.
2. 컨트롤러/액션(예로 폼의 포스트 <a href="">링크 AJAX  호출)의 콜백에 사용되는 외부로 향한 URL을 구축

내부/외부로 향한 URL시나리오의 양쪽 모두를 처리하는 URL매핑규칙을 사용할 수 있게 되면, 응용프로그램 코드에 큰 유연성을 줄 수 있다. 응용프로그램의 URL구조를 다음에 변경하고 싶은 경우, 응용프로그램 레벨로 매핑규칙의 1식을 수정하는 것으로 처리할 수 있어, 컨트롤러 또는 뷰의 템플릿내에서 코드를 변경할 필요가 없다.

기본 ASP.NET MVC URL 라우팅 규칙
기본적으로 Visual Studio로 "ASP.NET MVC 웹응용프로그램" 템플릿을 사용하여 새 프로젝트를 만들 때, ASP.NET 응용프로그램 클래스를 프로젝트에 추가한다. 이것은 Global.asax의 코드비하인드에 포함된다.

step1.jpg

ASP.NET 응용프로그램 클래스에 의해 개발자는 응용프로그램 시작/종료, 및 글로벌 오류처리를 할 수 있게 된다.
기본적으로 ASP.NET MVC 프로젝트의 템플릿은 자동적으로 Application_Start메소드를 클래스에 추가하여 2개의 URL 라우팅 규칙을 함께 등록한다.

step2.jpg

위 최초 라우팅 규칙은 어느 컨트롤러 클래스를 초기화하여 어느 액션 메소드를 실행시킬지를 결정할 때, ASP.NET MVC 프레임웍은 "[controller]/[action]/[id]"의 포멧을 사용하고 기본적으로 URL을 컨트롤러에 매핑해야하는 것인지를 나타낸다.

이 기본 라우팅 규칙에 의해 파트1에 있던 전자거래 검색 예제 /Products/Detail/3에 대한 URL의 요청이 자동적으로 ProductsController클래스내에 Detail메소드를 호출시켜 ID메소드의 인수값으로서 3이 넘어온다.

step10.jpg

위 2번째 라이팅 규칙은 응용프로그램으로 특별한 경우인 루트의 Default.aspx(이것은 응용프로그램의 루트URL에 대한 요청을 처리할 때 "/"대신에 웹서버로부터 가끔보내진다) URL에 추가된다. 이 규칙에서는 응용프로그램의 루트 "/Default.aspx" 또는 "/"의 어느 쪽에 대한 요청도 "HomeController"클래스(Visual Studio가 자동적으로 새 응용프로그램을 "ASP.NET MVC 웹응용프로그램"템플릿을 사용하면 자동 추가된다) 위 "Index()" 엑션에 의해 처리도록 한다.

루트 인스턴스 이해하기
라우팅 규칙은 루트 인스턴스를 System.Web.Mvc.RouteTable의 Routes콜렉션에 추가하면 등록된다.
Route클래스에서 맵핑규칙의 구성에 사용하는 수많은 속성이 정의되어 있고 속성은 "일반적인" .NET 2.0속성설정을 사용하여 설정할 수 있다.

step4.jpg

또한, 새로운 객체 초기화(object  initializer) 기능을 VS2008의 C# 및 VB컴파일러로 활용하여 보다 간결하게 속성을 설정할 수도 있다.

step3.jpg

Route클래스의 "Url"속성은 URl의 매칭 규칙을 정의한다. 이것은 루트 규칙이 특정 내부 요청에 적용할지를 평가하기 위해서 사용되는 것이다. 이것은 또한 인수에 대한 URL의 토큰화 메소드도 정의한다. URL로 변경하여 넣은 인수는 [ParamName]문장구조법을 사용하여 정의된다. 다음을 보면 "well known(잘알려진)"인수명에만 한전되는 일이 없이, URL로 사용하고 싶은 임의의 인수를 임의 수만큼 가질 수 있다. 예를 들어, 블로그 글에 대해서 들어온 URL을 토큰화하기 위해 "/Blogs/[Username]/Archive/[Year]/[Month]/[Day]/[Title]"의 Url규칙을 사용하여 자동적으로 MVC프레임웍에 UserName, Year, Month, Day, Title인수를 컨트롤러의 액션 메소드에 넘겨 처리되도록 한다.

Route클래스의 "Defaults"속성에는 들어오는 URL에 특정 인수값이 1개도 포함되지 않았던 경우에 사용하는 기본값의 사전을 정의한다. 예를 들면, 위 URL매핑예로 2개의 기본 URL인수값, "[action]"과 "[id]"에 대해서 정의한다. 즉, /Products/에 대한 URL가 응용프로그램에 수신되었을 경우, 라우팅시스템은 ProductsController상에서 실행되는 기본 액션명으로 "Index"를 사용한다. 같은 /Products/List/"가 특정되었을 경우 "ID"인수에 대한 Null문자열값이 사용된다.

Route클래스의 "RouterHandler"속성에서는 URL이 토큰화되어 사용되는 알맞은 라우팅 규칙이 결정된 후에 요청을 처리하기 위해 사용하는 IRouteHandler인스턴스를 정의한다, 이 여분의 스텝이 있는 이유는 URL 라우팅 시스템이 MVC와 MVC가 아닌 요청 모두에 대해서 확실하게 사용할 수 있도록 하기 위해서이다. 이 IRouteHandler인터페이스를 갖는다라고 하는 것은 MVC가 아닌 요청(예로 표준 웹폼, Astoria REST 지원등)에 대해서도 깔끔하게 사용할 수 있는 것이다.

또한, Route 클래스에는 "Validation"속성이 있는데 이것은 나중에 따로 본다. 이 속성에는 미리 만든 프리컨디션 제품에 특정할 수 있다. 특정한 라우팅 규칙에 합치키기 위해 필요하게 된다. 예를 들면, 특정 HTTP verb(REST명령어에 의해 간단하게 매핑할 수 있음)에 대해서만 적용하는 라우팅 규칙을 나타내거나 라우팅 규칙에 대해서 필더를 하기 위해 인수에 정규식을 사용하거나 할 수 있다.

주: 최초 공개 MVC 프리뷰에서는 Route클래스는 확장이 가능하지 않다. (데이터 클래스가 됨), 다음 프리뷰 릴리즈에서 이것을 확장가능하게 하고 개발자가 한층 더 시멘틱스한 기능을 깔끔하게 추가하기 위해 시나리오의 특정 루트클래스(예로 RestRoute하위클래스)를 추가할 수 있도록 하고 싶다.

루트 규칙 평가
들어오는 URL을 ASP.NET MVC 웹응용프로그램이 수신했을 때, MVC 프레임웍은 RouteTable.Routes컬렉션으로 라우팅규칙을 평가하여 그 요청을 처리하는 알맞은 컨트롤러를 결정한다.

MVC 프레임웍은 등록된 순서로 RouteTable규칙을 평가하는 것으로 사용하는 컨트롤러를 선택한다. 들어오는 URL은 각 루트 규칙에 합치고 있는지 확인한다. 만약, 루트 규칙이 합쳐지는 경우, 그 규직(관련된 RouteHandler)가 요청을 처리하는데 사용된다. 즉, 일반적인 경우, "상세"순서로 라우팅 규칙을 구조화해 두면 좋다고 생각한다.

라우팅 시나리오: 사용자지정 검색 URL
몇개인지 사용자지정의 라우팅 규칙을 실제 시나리오로 사용해보자. 이것은 전자거래 사이트의 검색 기능이다.
우선 새 SearchController클래스를 프로젝트에 추가한다.

step5.jpg

이후, SearchController클래스에서 2개의 액션메소드를 정의한다. Index()액션메소드는 사용자가 입력하여 검색대상을 송신하는데 사용하는 TextBox가 있는 검색페이지를 표시하기 위해 사용된다. Result()액션은 그곳으로부터 폼송신을 처리하여 데이터베이스에서 검색한 다음 그 결과를ㄹ 표시하기 위해 사용된다.

step6.jpg

기본적으로 /[controller]/[action]/[id] URL루트 매핑 규칙을 사용하여 아래와 같이 "설정이 끝난 상태"의 URL을 SearchController 액션 실해엥 사용할 수 있다. actions:

 시나리오  URL  액션 메소드
 검색폼  /Search/  Index
 검색결과  /Search/Results?query=Beverages  결과
   /Search/Results?query=ASP.NET  결과

Index()액션 메소드에 대해 기본적으로 루트의 /Search URL이 맵핑되고 있는 이유는 Visual Studio가 새 프로젝트를 만들 떄("Defaults"속성을 통해) 컨트롤러에서 기본 액션으로서 "Index"를 설정했을 때 기본적으로 /[countroller]/[action]/[id] 루트 정의가 추가되었기 때문이다.

step3.jpg

URL이 /Search/Results?query=Beverages등의 경우 완벽하게 가능하지만, 조금 깔끔한 URL을 검색결과에 보여주고 싶다. 특히 Results액션명을 URL로부터 삭제하고 QueryString인수를 사용하는 대신에 URL일부로서 검색 쿼리를 보내고 싶은 경우 있을 것이라고 생각한다. 예를 들면,

 시나리오  URL  액션 메소드
 검색폼  /Search/  Index
 검색결과  /Search/Beverages  Results
   /Search/ASP.NET  Results

아래와 같이, 기본 /[controller]/[action]/[id]규칙 전에 2개의 사용자지정 URL루트매핑 규칙을 추가하여 깔끔한 검색결과를 보일 수 있다.

step7.jpg

처음 2개의 규칙에서는 /Search/ URL에 대해서 컨트롤러나 액션인수를 현재 명시적으로 지정하고 있다. "/Search"는 항상 SearchController에서 "Index"액션으로 처리되는 것이 당연한 것으로 나타내고 있다. 현재 하위 URL 계층을 가지는 URL은 모두(/Serach/Foo나 /Serach/Bar 등), 항상 SearchController상에서 "Results"액션으로 처리되고 있다.

위 2번째 라우팅 규칙은 /Search/프리픽스를 넘는 것은 모두 "[query]"로 불리는 인수로서 처리되어 SearchController의 Results액션에 메소드 인수로서 보내지는 것을 나타낸다.

step8.jpg

대부분의 경우(검색결과가 10이상 표시되는 경우), 검색결과를 페이지 번호를 나타내고 싶어한다고 생각한다. 이것은 쿼리 스트링 인수를 통해 할지 또는 옵션으로서 URL일부에 페이지번호(/Search/Beverages/2)를 처리한다. 이것은 다음 옵션으로서 지원하기 위해 추가 인수를 2번째 라우팅 규칙에 추가해둔다. :

step9.jpg

위에서 확인할 수 있는 것으로 새 URL 규칙을 합쳐 현재 "Search/[query]/[page]"가 되어 잇다. 또한, 기본페이지번호는 URL에 포함되지 않도록 하는 경우를 위해 1로 설정한다. (이것은 "Defaults"속성으로서 처리된 익명형을 통해서)
이후, SearchController.Results액션 메소드를 업데이트하고 이 페이지 인수를 메소드 인수로서 받는다.

step10.jpg

이렇게 하여 사이트에 대해서 깔끔한 URL로 검색할 수 있다.

라우팅 규칙에 대한 전체컨디션 평가
이 글에 대해서는 앞에서도 말했지만, Route클래스는 "Validation"속성을 가지고 있어 루트규칙이 합쳐지면 True가 되지 않으면 안되는 전제조건 규칙을 검증할 수 있도록 추가되었다. ASP.NET MVC 프레임웍은 정규식을 사용하여 URL의 각 인수를 평가할 수 있어 HTTP헤더 평가리를 하는 일도 할 수 있다.

이하는 사용자지정 평가규칙으로 "/Products/Detail/43"등과 같은 URL에 대한 유효화를 할 수 있다. 이는 ID인수가 수치로 1-8문자가 아니면 안되는 설정이다.

step11.jpg

응용프로그램에 /Products/Detail/12와 같은 URL로 처리할 경우, 위 라우팅 규칙은 유효하게 되지만, /Products/Detail/abc 또는 /Products/Detail/2323232323과 합치지 않는다.

라우팅 시스켐으로부터 밖으로 향한 URL구축
이 글의 앞에서 말했지만, ASP.NET MVC 프레임웍의 URL 라우팅 시스템은 2개를 가지고 있다.

1. 처리하기 위해 들어온 URL을 Controllers/Actrions에 매핑
2. Controllers/Actions에 다음 콜백에 사용가능성이 외부로 향한 URL구축을 지원(예를 들면, 폼, <a href="">링크, AJAX호출)

URL의 라우팅시스템에는 많은 헬퍼 메소드나 클래스가 있어 이를 간단하게 실행시 URL을 동적으로 검색 및 구축할 수 있다.(RouteTable Route컬렉션을 집적조작하는 것으로 URL을 검색할 수 있다)

Html.ActionLink
이 시리즈의 파트1에서 간단하게 Html.ActionLink() 뷰 헬퍼 메소드에 대해서 말했지만, 그것은 뷰내에서 사용할 수 있어 동적으로 <a href="">하이퍼링크를 생성할 수 있다. 장점은 MVC라우팅 시스템으로 정의된 URL매핑 규칙을 사용하여 이런 URL을 생성한다. 예를 들면 아래  2개의 Html.ActionLink를 호출한:

step12.jpg

자동적으로 이 글 앞쪽에서 구성한 특정 Search결과의 루트 규칙과 이것을 반양하여 자동적으로 생성한 "href"속성을 선택한다.

step13.jpg

특히, 어떻게 Html.ActionLink에 대한 2번째 호출이 자동적ㅇ로 "page"인수를 URL일부로서 매핑되어 있지 않을 까 확인하세요. (또한, 서버사이트에서 기본값이 제공되는 것을 알았기 때문에, 1번째 호출로 페이지 인수값이 생략되는 모습을 확인한다)

Url.Action
Html.ActionLink의 사용을 추가형 ASP.NET MVC에는 Url.Action()뷰 헬퍼 메소드도 있다. 이것은 문자열 URL을 생성한다. 이것을 사용하고 싶다면 아래와 같이 코드 스닙펫:

step14.jpg

URL 라우팅 시스템을 사용하고 아래의 URL을 리턴한다.(<a href="">요소에는 랩핑되어 있지 않다)

step15.jpg

Controller.RedirectToAction
ASP.NET MVC는 Controller.RedirectToAction() 헬퍼 메소드를 지원하고 있어, 그것은 컨트롤러에서 사용하고 (URL이 URL 라우팅 시스템을 사용하여 계산되었을 경우) 리다이렉트를 실행할 수 있다.
예를 들면, 아래 코드가 컨트롤러내에서 실행되었을 때,

step16.jpg

내부에서 Response.Redirect("/Search/Beverages") 호출을 생성한다.

DRY
위 모든 헬퍼메소드는 컨트롤러나 뷰의 논리내에서 URL경로에 하드코드할 필요가 없는 일이다. 만약, 다음에 "/Search/[query]/[page]"로부터 "/Search/Results/[query]/[page]" 또는 /Search/Results?query=[query]&page=[page]"에 검색 URL의 루트 매핑 규칙을 변경하려고 결정하면, 1개의 장소(루트 등록코드)에서 편집하는 것으로 간단하게 할 수 있다. 새로운 URL(이것은 "DRY principle"을 보관유지한다)를 선택하기 위해 뷰 또는 컨트롤러에서 코드를 변경할 필요가 없다.

라우팅 시스템으로부터 외부로 나가는 URL을 구축(Lambda식 사용)
전에 URL헬퍼 예는 VS2008으로 지원되고 있는 VB와 C#에 있는 새로운 익명형을 활용하고 있다. 위 에에서는 익명형을 사용하여 효과적으로 일련의 이름과 값이 맞추어 URL의 매핑을 보조하고 있다. (이것을 사전으로 깔끔하게 생성하는 방법이라고 생각할 수 있다)

익명형을 사용한 동적인 방법으로 인수를 보내는 것을 추가하여 ASP.NET MVC 프레임웍은 강력한 메커니즘을 사용하여 액션루트를 만드는 기능도 지원하고 있어 이를 컴파일시 체크와 URL헬더에 대한 인텔리센스가 제공된다. Generic형과 Lambda식에 대한 새로운 VB와 C#이 지원하고 있어 이를 사용한다.

예를 들면 아래의 익명형을 ActionLink 호출:

step17.jpg

또는 다음과 같이 쓸 수 있다.

step18.jpg

조금 간결하게 쓸 수 있는 것을 추가형 2번째 옵션을 형 세이프인 장점을 가진다. 즉, 식의 컴파일시 체크와 Visual Studio 코드 인텔리 센스(리펙토링도 사용할 수 있다)를 사용할 수 있다.

step19.jpg

위에서 SearchController에서 액션 메소드를 선택하기 위해서 인텔리센스를 어떻게 사용하는지 인수가 어떻게 강한 형이 되는지 확인한다. 생성된 URL은 모두 ASP.NET MVC URL라이팅 시스템으로부터 없앤다.

이것은 어떻게 실행되는지? 생각할지도 모른다. 8개월전 Lambda식에 대한 글을 포스팅했지만,  거기서는 코드 Delegate 및 Lambda식을 분석하기 위한 실행시 사용가능한 expression tree object의 어딘가에 Lambda식을 컴파일할 수 있는 것에 대해 이야기햇다. Html.ActionLink<T> 헬퍼 메소드로 이 expression tree object을 사용하여 실행시 Lambda식을 분석하여 실행시키는 액션 메소드와  식안에 특정 인수형태, 이름, 값을 검색한다. 이것들을 MVC url라우팅 시스템으로 사용하여 적절한 URL과 관련된 HTML을 리턴할 수 있다.

중요: 이 Lambda식을 사용할 때, 컨트롤러 액션은 전혀 실행하지 않는다. 예를 들면 아래 코드는 SearchController에서 "Results"액션 메소드를 실행하지 않는다.

step18.jpg

이 HTML의 하이퍼링크를 리턴하는 대신에

step20.jpg

최종 사용자가 이 하이퍼링크를 클릭했을 때, HTTP요청이 서버에 보내져 SearchController의 Results액션메소드를 실행시킨다.

루트의 전체 테스트
ASP.NET MVC 프레임웍의 코어 설계의 원칙하나가 테스트를 많이 지원할 수 있도록 하는 것이다. 나머지 MVC프레임웍과 같이 쉽게 루트나 루트를 합치는 규칙의 전체 테스트를 할 수 있다. MVC의 라우팅 시스템은 ASP.NET으로부터 도립하여 초기화하여 실행할 수 있다. 즉, 어떤 전체 테스트 라이브러리(웹서버를 시작할 필요가 없다) 안에서도 어떤 전체 테스트 프레임웍(NUint, MBUnit, MSTest등)을 사용해도 루트패턴을 읽어 전체테스트할 수 있다.

여러개의 전체 테스트 중에서 직접 ASP.NET MVC응용프로그램의 글로벌 RouteTable매핑 콜렉션을 전체 테스트할 수 있지만, 일반적으로 전체 테스트를 변경하거나 글로벌 상황에 의지하는 것은 좋은 생각은 아니다. 좋은 패턴은 아래와 같이 RegisterRoutes() 헬퍼 메소드에 루트 등록 놀리를 구조화하는 것이다. 이것은 인수로서 보내지는 RouteCollection에 대해서 실행된다. (주: 아마 이것을 다음 프리뷰 업데이트에서 기본 VS템플릿패턴으로 할 것으로 생각된다)

step21.jpg

고유의 RouteCollection인스턴스를 만들어 루트 규칙을 응용프로그램안에서 등록하기 위해 응용프로그램의 RegisterRoutes()헬퍼를 호출하는 전체 테스트를 쓸 수 있다. 그러면, 응용프로그램에 대한 요청을 레이트하고 그것들에 대한 올바른 컨트롤러나 액션이 등록되어 있는지 어떤 문제가 있을지 걱정하는 일없이 확인할 수 있다.

step22.jpg

정리
이번 글에 의해 ASP.NET MVC 라우팅 아키텍쳐의 동작과 이를 사용하여 ASP.NET MVC응용프로그램내 발생하는 URL구조나 레이아웃을 사용자지정으로하는 방법에 대해서 상세히 다루어서 다행이다.

기본적인 새 ASP.NET MVC 웹응용프로그램을 만들 때, 기본적으로 /[constroller]/[action]/[id] 라우팅 규칙이 정의된다. 이것에 의해 스스로 고유의 사용자지정으로 라우팅 규칙을 등록할 필요없이 많은 응용프로그램을 구축할 수 있게 되지만, 앞에서 소개한 것에 의해 URL포멧을 사용자지정으로 하고 싶은 경우 간단하게 만들수 있어 이것을 실행할 때 MVC프레임웍이 큰 파워와 유연성을 줄 수 있어 기쁘게 생각한다.

Hope this helps.
Scott
Posted by 나비:D
:

[SOAP 모니터링 사용]


TCP Monitor(윈도APP)

D:/work>java org.apache.axis.utils.tcpmon

위와 같이 하면 자바 위도APP가 실행되는데, 여기서 로컬포트를 지정하는 곳이 있다.

일종의 터널링이라 할 수 있는데, 클라이언트가 이 포트를 통해 요청하면 프락시 역활을 하여 서버에 요청하고 그 결과를 다시 클라이언트에 전송한다.

이 과정에서 TCP Monitor는 클라이언트/서버간 주고 받는 메시지를 파악하게 되는 것이다.

사용자가 할 일은 기존 클라이언트가 서비스를 제공받기 위해 접속하던 주소를 변경해주면 된다.

즉, 아래와 같이 해주면 된다.


//public final static String ENDPOINT = http://127.0.0.1:8080/FOO/services/MyService;

:원래 접속할 서버

public final static String ENDPONT = "http://127.0.0.1:1234/FOO/services/MyService;

:TCP Monitor용 연결


처음 실행 화면, 여기서 리스터 포트는 1234로 설정하고 추가 버튼을 클릭한다.

사용자 삽입 이미지
 

로컬의 1234포트로 클라이언트의 연결을 기다리고 있다.

사용자 삽입 이미지


클라이언트가 접속한 예.

사용자 삽입 이미지


[SOAP Monitor(애플릿)]

http://localhost:8080/axis/SOAPMonitor


[SOAP Monitor 활성화하기]

활성화하리 위해 2과정이 필요하다


1. SOAPMonitorApplet.java 애플릿 컴파일

2. deploy-monitor.wsdd를 통한 SOAP Monitor deploy


1.SOAPMonitorApplet.java 애플릿 컴파일

E:/>type d:/util/axis.bat

@echo off

set AXIS_HOME=D:util.axis-1_4

set AXIS_LIB=%AXIS_HOME%/lib

set AXISCLASSPATH=%AXIS_LIB%/axis.jar;%AXIS_LIB%/jaxrpc.jar;%AXIS_LIB%/saaj.jar;

%AXIS_LIB%/log4j-1.2.8.jar;%AXIS_LIB%/commons=discovery-0.2.jar;%AXIS_LIB%/commons-logging-1.0.4.jar;%AXIS_LIB%/wsdl4j-1.5.1.jar

set CLASSPATH=%CLASSPATH%;%AXISCLASSPATH%

E:/>axis.bat

E:/>cd "%CATALINA_HOME%/webapps/axis"

E:/>Program Files/Apache Software Foundation/Tomcat 5.5/webapps/axis>javac SOAPMonitorApplet.java

Note : SOAPMonitorApplet.java.uses or overrides a deprecated API.

Note : Recompile with -Xlint : deprecation for details.

Note : SOAPMonitorApplet.java uses unchecked or unsafe operations.

Note : Recompile with -Xlint : unchecked for details.


2. deploy-monitor.wsdd를 통한 SOAP Monitor deploy

D:/work>java org.apache.axis.client.AdminClient deploy-monitor.wsdd

log4j:WARN No appenders coulde be found for logger(org.apache.axis.i18n.ProjectResourceBundle).

log4j:WARN Please initialize the log4j system property.

Processing file deploy-monitor.wsdd

<Admin>Done processing</Admin>


[deploy-monitor.wsdd]

<deployment xmlns=http://xml.apache.org/axis/wsdd/

                   xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">

    <handler name="soapmonitor"

                 type="java:org.apache.axis.handlers.SOAPMonitorHandler">

        <parameter name="wsdlURL"

                         value="/aixs/SOAPMonitorService-impl.wsdl" />

        <parameter name="namespace"

                         value=http://tempuri.org/wsdl/2001/12/SOAPMonitorService-impl.wsdl />

        <parameter name="serviceName" value="SOAPMonitorService" />

        <parameter name="portName" value="Demo" />

    </handler>

    <service name="SOAPMonitorService" provider="java:RPC">

        <parameter name="allowedMethods" value="publishMessage" />

        <parameter name="className" value="org.apache.axis.monitor.SOAPMonitorService" />

        <parameter name="scope" value="Application" />

    </service>

</deployment>


[브라우저에서 SOAP 모니터를 실행]

사용자 삽입 이미지


[SOAP Monitor 사용예]

deploy.wsdd작성시 requestFlow, responseFlow를 추가해주면 해당 웹서비스가 주고받는 SOAP메시지를 실시간으로 볼 수 있다.

개발과정에서 아주 요긴하게 사용될 수 있다.

2회때 사용한 예제에서 deploy.wsdd파일에 다음을 추가해주기만 하면된다.

[deploy,wsdd]

<deployment xmlns=http://xml.apache.org.axis.wsdd/ xmlns:java="http://xml.apache.org.axis/wsdd/providers/java">

    <service name="MyService" provider="java:RPC">

        <parameter name="className" value="MyService" />

        <parameter name="allowMethods" value="*">

        <requestFlow><handler type="soapmonitor" /></requestFlow>

        <responseFlow><handler type="soapmonitor" /></responseFlow>

    </service>

</deployment>


D:/work>java Client "안녕, 세상아!"

log4j:WARN No appenders coulde be found for logger(org.apache.axis.i18n.ProjectResourceBundle).

log4j:WARN Please initialize the log4j system property.

You typed : 안녕, 세상아!

D:work>


브라우저에 모니터링된 SOAP,메시지는 그림과 같다.

 

사용자 삽입 이미지
Posted by 나비:D
:

[메시지 스타일 서비스]

자바코드로의 매핑을 빼고 XML데이터 자체를 주고받는 서비스다.


D:/work>type MessageService.java

import org.w3c.dom.Element;

import javax.xml.soap.*;

public class MessageService{

    public Element[] echoElements(Element[] elems){

        return elems;

    }

    public void Process(SOAPEnvelope req, SOAPEnvelope res) throws javax.xml.soap.SOAPException{

        SOAPBody body = res.getBody();

        Name ns0 = res.createName("TestNS0", "ns0", http://aa.com);

        Name ns1 = res.createName("TestNS1", "ns1", http://aa.com);

        SOAPElement bodyElement = body.addBodyElement(ns0);

        SOAPElement el = bodyElement.addChildElement(ns1);

        el.addTextNode("TEST RESPONSE");

    }

}

D:/work>javac MessageService.java

D:/work>copy MessageService.class "%CATALINA_HOME%/webapps/axis/WEB-INF/classes"

1개 파일이 복사되었습니다.

D:/work>type deploy.wsdd

<deployment name="test" xmlns=http://xml.apache.org/axis/wsdd/

                   xmlns:java=http://xml.apache.org/axis/wsdd/providers/java

                   xmlns:xsi="http://www.w3c.org/2000/10/XMLSchema-instance">

//주석 : note that either style="message" OR provider="java:MSG" both work

    <service name="MessageService" style="message">

        <parameter name="className" value="MessageService" />

        <parameter name="allowedMethods" value="echoElements" />

    </service>

    <service name="MessageService2" style="message">

        <parameter name="className" value="MessageService" />

        <parameter name="allowedMethods" value="process" />

    </service>

</deployment>

D:/work>type undeploy.wsdd

<undeploytment name="test" xmlns="http://xml.apache.org/axis/wsdd/">

    <service name="MessageService" />

</undeployment>

D:/work>java org.apache.axis.client.AdminClient deploy.wsdd

log4j : WARN No appenders could be found for logger(org.apache.axis.i18n.ProjectResourceBundle).

log4j : WARN Please initialize the log4j system property.

Processing file deploy.wsdd

<Admin>Done processing</Admin>

D:/work>java org.apache.axis.client.AdminClient list

D:/work>jaba org.apache.axis.client.AdminClient list

log4j : WARN No appenders could be found for logger(org.apache.axis.i18n.ProjectResourceBundle).

log4j : WARN Please initialize the log4j system property.

<ns1:deployment xmlns=http://xml.apache.org/axis/wsdd/

                         xmlns:java=http://xml.apache.org/axis/wsdd/providers/java

                         xmlns:ns1="http://xml.apache.org/axis/wsdd/">

    <ns1:globalConfiguration>

        <ns1:parameter name="sendMultiRefs" value="true" />

        <ns1:parameter name="disablePrettyXML" value="true" />

        <ns1:parameter name="adminPassword" value="admin" />

        <ns1:parameter name="attachments.Directory" value="E:/Program Files/Apache Software Foundation.Tomcat5.5/webapps/axis/WEB-INF/arrachments" />

        <ns1:parameter name="dotNetSoapEncFix" value="true" />

        <ns1:parameter name="enableNamespacePrefixOptimization" value="false" />

        <ns1:parameter name="sendXsiTypes" value="true" />

        <ns1:parameter name="attachments.implementation" value="org.apache.axis.attachments.AttachmentsImpl" />

        <ns1:requestFlow>

            <ns1:handler type="java:org.apache.axis.handlers.JWSHandler">

                <ns1:parameter name="scope" value="session" />

            </ns1:handler>

            <ns1:handler type="java:org.apache.axis.handlers.JWSHandler">

                <ns1:parameter name="scope" value="request" />

                <ns1:parameter name="extension" value=".jwr" />

            </ns1:handler>

        </ns1:requestFlow>

    </ns1:globalConfiguration>

    <ns1:handler name="LocalResponder" type="java:org.apache.axis.transport.local.LocalResponder" />

    <ns1:handler name="URLMapper" type="java:org.apache.axis.handlers.http.URLMapper" />

    <ns1:handler name="Authenticate" type"java:org.apache.axis.handlers.SimpleAuthenticationHAndler" />

    <ns1:service name="MessageService2" provider="java:MSG" style="message" use="literal">

        <ns1:parameter name="allowedMethods" value="process" />

        <ns1:parameter name="className" value="MessageService" />

        <ns1:parameter name="sendXsiTypes" value="false" />

        <ns1:parameter name="sendMultiRefs" value="false" />

    </ns1:service>

    <ns1:service name="MessageService" provider="java:MSG" style="message" use="literal">

        <ns1:parameter name="allowedMethods" value="echoElements" />

        <ns1:parameter name="className" value="MessageService" />

        <ns1:parameter name="sendXsiTypes" value="false" />

        <ns1:parameter name="sendMultiRefs" value="false" />

    </ns1:service>

    <ns1:service name="AdminService" provider="java:MSG">

        <ns1:parameter name="allowedMethods" value="AdminService" />

        <ns1:parameter name="enableRemoteAdmin" value="false" />

        <ns1:parameter name="className" value="org.apache.axis.utils.Admin" />

        <ns1:namespace>http://xml.apache.org/axis/wsdd/</ns1:namespace>

    </ns1:service>

    <ns1:service name="Version" provider="java:RPC">

        <ns1:parameter name="allowedMethods" value="getVersion" />

        <ns1:parameter name="className" value="org.apache.axis.Version" />

    </ns1:service>

    <ns1:transport name="http">

        <ns1:requestFlow>

            <ns1:handler type="URLMapper" />

            <ns1:handler type="java:org.apache.axis.handlers.http.HTTPAuthHandler" />

        </ns1:requestFlow>

        <ns1:parameter name="qs:list" value="org.apache.axis.transport.http.QSListHandler" />

        <ns1:parameter name="qs:wsdl" value="org.apache.axis.transport.http.QSWSDLHandler" />

        <ns1:parameter name="qs:list" value="org.apache.axis.transport.http.QSListHandler" />

        <ns1:parameter name="qs:method" value="org.apache.axis.transport.http.QSMethodHandler" />

        <ns1:parameter name="qs:method" value="org.apache.axis.transport.http.QSMethodHandler" />

        <ns1:parameter name="qs:wsdl" value="org.apache.axis.transport.http.QSWSDLHandler" />

    </ns1:transport>

    <ns1:transport name="local">

        <ns1:responseFlow>

            <ns1:handler type="LocalResponder" />

        </ns1:responseFlow>

    </ns1:transport>

</ns1:deployment>


[클라이언트로 서비스 테스트]

D:/work>javac TestMsg.java

D:/work>java TestMsg

log4j : WARN No appenders could be found for logger(org.apache.axis.i18n.ProjectResourceBundle).

log4j : WARN Please initialize the log4j system property.

D:/work>type TestMsg.java


import org.apache.axis.client.Call;

import org.apache.axis.client.Service;

import org.apache.axis.message.SOAPBodyElement;

import org.apache.axis.utils.Options;

import org.apache.axis.Utils.XMLUtils;

import org.w3c.dom.CDATASection;

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.soap.MessageFactory;

import javax.xml.soap.MimeHeaders;

import javax.xml.soap.SOAPConnection;

import javax.xml.soap.SOAPConnectionFactory;

import javax.xml.soap.SOAPEnvelope;

import javax.xml.soap.SOAPMessage;

import javax.xml.soap.SOAPPart;

import java.io.ByteArrayInputStream;

import java.net.URL;

import java.util.Vector;


//주석 : Simple test driver for our message service.


public class TestMsg{

    public String doit(String[] args) throws Exception{

        Optionsopts = new Options(args);

        opts.setDefaultURL(http://localhost:8080/axis/service/MessageService);

        Service service = new Service();

        Call call = (Call) service.createCall();

        call.setTargetEndpointAddress(new URL(opts.getURL()));

        SOAPBodyElement[] input = new SOAPBodyElement[3];

        input[0] = new SOAPBodyElement(XMLUtils.,StringToElement("urn:foo", "e1", "Hello"));

        input[1] = new SOAPBodyElement(XMLUtils.,StringToElement("urn:foo", "e1", "World"));

        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocunebtBuilder();

        Document doc = builder.newDocument();

        Element cdataElem = doc.createElementNS("urn:foo", "e3");

        CDATASection cdata = doc.createCDATASection("Text with/n/t Important <b> witespace</b> and tags!");

        cdataElem.appendChild(cdata);

        input[2] = new SOAPBodyElement(cdataElem);

        Vector elems = (Cevtor)call.invoke(input);

        SOAPBodyElement elem = null;

        Element e = null;

        elem = (SOAPBodyElement) elems.get(0);

        e = elem.getAsDOM();

        String srt = "Reselem[0]=" + XMLUtils.ElementToString(e);

        elem = (SOAPBodyElement) elems.get(1);

        e = elem.getAsDOM();

        str = str + "Reselem[1]=" + XMLUtils.ElementToString(e);

        elem = (SOAPBodyElement) elems.get(2);

        e = elem.getAsDOM();

        str = str + "Reselem[2]=" + XMLUtils.ElementToString(e);

        return(str);

    }

    public void testEnvelope(String[] args) throws Exception{

        String xmlString =

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

         "<soapenv:Envelope xmlns:soapenv=/"http://schemas.xmlsoap.org/soap/envelope//"/n+

         "xmlns:xsd=/"http://www.w3.org/2001/XMLSchema/"/n"+

         "xmlns:xsi=/"http://www.w3.org/2001/XMLSchema-instance/">/n"+

         "<soapenv:Header>/n"+

         "<shw:Hello xmlns:shw=/"http://localhost:8080/axis/services/MessageService/">/n"+

         "<shw:Myname>Tony</shw:Myname>/n"+

         "</shw:Hello>/n"+

         "</soapenv:Header>/n"+

         "<soapenv:Body>/n"+

         "<shw:process xmlns:shw=/"http://message.samples/">/n"+
         "<shw:City>GENT</shw:City>/n"+
         "</shw:process>/n" +
         "</soapenv:Body>/n"+
         "</soapenv:Envelope>/n"+
         MessageFactory mf = MessageFactory.newInstance();
         SOAPMessage smsg =
mf.createMessage(new MimeHeaders(), new ByteArrayInputStream(xmlString.getBytes()));
         SOAPPart sp = smsg.getSOAPPart();
         SOAPEnvelope se = (SOAPEnvelope)sp.getEnvelope();
         SOAPConnection conn = SOAPConnectionFactory.newInstance().createConnection();        
         SOAPMessage response = conn.call(smsg, http://localhost:8080/axis/services/MessageService2);
    }
    public static void main(String[] args) throws Exception{
        TestMsg testMsg = new TestMsg();
        testMsg.doit(args);
        testMsg.testEnvelope(args);
    }
}

Posted by 나비:D
:

[WSDD를 이용한 웹서비스 개발]

D:work>type MyService.java

public class MyService{

    public String serviceMEthod(String arg){

        return arg;

    }

}

D:/work>type deploy.wsdd

<deplyment xmlns=http://xml.apache.org/axis/wsdd/ xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">

    <service name="MyService" provider="java:RPC">

        <parameter name="className" value="MyService"/>

        <parameter name="allowMethods" value="*"/>

    </service>

</deployment>


D:work>type undeploy.wsdd

<undeployment xmlns="htt://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">

    <service name="MyService" />

</undeployment>


[톰캣 시동후, 자것ㅇ한 웹서비스를 deploy]

D:/work>set AXIS_HOME=D:util/axis-1_4

D:/work>set AXIS_LIB=%AXIS_HOME%/lib

D:/work>setAXISCLASSPATH=%AXIS_LIB%/axis.jar;%AXIS_LIB%/jaxrpc.jar;%AXIS_LIB%/saaj.jar;%AXIS_LIB%/log4j-1.2.8.jar;%AXIS_LIB%/commons-discovery-0.2.jar;%AXIS_LIB%/commons-logging-1.0.4.jar;%AXIS_LIB%/wsdl4j-1.5.1.jar

D:/work>set CLASSPATH=%CLASSPATH%;%AXISCLASSPATH%

D:/work>javac MyService.java

D:/work>copy MyService.class "%CATALINA_HOME%/webapps/axis/WEB-INF.classes"

1개 파일이 복사되었습니다.


AdminClient를 이용해 웹서비스를 deploy

D:/work>java org.apache.axis.client.AdminClient deploy.wsdd

log4j:WARN No appenders could ve found for logger(org.apache.axis.i18n.ProjectResourceBundle).

log4j:WARN Please initialize the log4j system property.

Processing file deploy.wsdd

<Admin>Done processing</Admin>

D:/wrok>


*undeploy하려면 다음과 같다.

D:/work>java org.apache.axis.client.AdminClient undeploy.wsdd

log4j:WARN No appenders could be found for logger(org.apache.axis.i18n.ProjectResourceBundle).

log4j:WARN please initialize the log4j system property.

Processing file undeploy.wsdd

<Admin>Done processing<Admin>


[클라이언트 접속 테스트]

D:/work>type Client.java

import org.apache.axis.client.Call;

import org.apache.axis.client.Service;

import org.apache.axis.encoding.XMLType;

import org.apache.axis.utile.Options;

import javax.xml.namespace.QName;

import javax.xml.rpc.ParameterMode;

public class Client{

    public static void main(String[] args){

        try{

            Options options = new Options(args);

            String endpointURL = http://localhost:8080/axis/services/MyService;

            String textToSend;

            args = options.getRemainingArgs();

            if((args == null) || (args.length < 1)){

                textToSend = "<nothing>";

            }else{

                textToSend = args[0];

            }

            Service service = new Service();

            Call call = (Call) service.createCall();

            call.setTargetEndpointAddress(new java.net.URL(endpointURL));

            call.setOperationName(new QName("ServiceMethod"));

            call.addParameter("arg1", XMLType.XSD_STRING, ParameterMode.IN);

            call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);

            String ret = (String) call.invoke(new Object[] {textTosend} );

            System.out.println("You typed : " +ret);

        } catch(Exception e){

            System.err.println(e.toString());

        }

    }

}


D:/wrok>javac Client.java

D:/work>java Client "안녕, 세상아!"

log4j:WARN No appenders could be found for logger(org.apache.axis.i18n.projectResourceBundle).

log4j:WARN Please initialize the log4j system property.

You typed : 안녕, 세상아!



* 웹서비스 deploy되었는지 확인하려면 AdminClient의 list 명령을 사용하면 된다.

이 명령으로 출력된 결과는 AXIS의 설정파일인 WEB-INF/server-config.xml의 내용이다.

이 파일은 명시적으로 생성하지 않으면 axis가 시작할 때 자동으로 만들게 된다.


D:/work>java org.apache.axis.client.AdminClient list

D:/work>java org.apache.axis.client.AdminClient deploy.wsdd

log4j:WARN No appenders could be found for logger(org.apache.axis.i18n.ProjectResourceBundle).

log4j:WARN Please initialize the log4j system property.

Processing file deploy.wsdd

<Admin>Done processing</Admin>


D:/work>java org.apache.axis.client.AdminClient list

log4j:WARN No appenders could ve found for logger(org.apache.axis.i18n.ProjectResourceBundle).

log4j:WARN Please initialize the log4j system property.


<ns1:deployment xmlns="http://xml.apache.org/axis.wsdd/" xmlns:java="htt://xml.apache.org/axis/wsdd/providers/java" xmlns:ns1="http://xml.apache.org/axis/wsdd/">

    <ns1:globalConfiguration>

        <ns1:parameter name="sendMultiRefs" value="true" />

        <ns1:parameter name="disablePrettyXML" value="true" />

        <ns1:parameter name="adminPassword" value="admin" />

        <ns1:parameter name="attachements.Directory" value="E:/Program Files/Apache Software Foundation.Tomcat 5.5/webapps/axis/WEB-INF/attachements" />

        <ns1:parameter name="dotNetSoapEncFix" value="true" />

        <ns1:parameter name="enableNamespacePrefixOptimization" value="false" />

        <ns1:parameter name="sendXMLDeclaration" value="true" />

        <ns1:parameter name="sendMultiRefs" value="true" />

        <ns1:parameter name="disablePrettyXML" value="true" />

        <ns1:parameter name="arrachments.implementation" value="org.apache.axis.attachments.ArrachmentsImpl" />

        <ns1:parameter name="sendXsiTypes" value="true" />

        <ns1:requestFlow>

            <ns1:handler type="java:org.apache.axis.handlers.JWSHandler">

                <ns1:parameter name="scope" value="session" />

            </ns1:handler>

            <ns1:handler type="java:org.apache.axis.handlers.JWSHandler">

                <ns1:parameter name="scope" value="request" />

                <ns1:parameter name="extension" value=".jwr" />

            </ns1:handler>

        </ns1:requestFlow>

    </ns1:globalConfiguration>

    <ns1:handler name="LocalResponder" type="java:org.apache.axis.transport.local.LocalResponder" />

    <ns1:handler name="URLMapper" type="java:org.apache.axis.handlers.http.URLMapper" />

    <ns1:handler name="Authenticate" type="java:org.apache.axis.handlers.SimploAuthenticationHandler" />

    <ns1:service name="AdminService" provider="java:MSG">

        <ns1:parameter name="allowedMethods" value="AdminService" />

        <ns1:parameter name="enableRemoteAdmin value="false" />

        <ns1:parameter name="className" value="org.apache.axis.utiles.Admin"/>

        <ns1:namesapce>http://xml.apache.org/axis/wsdd/</ns1:namespace>

    </ns1:service>

    <ns1:service name="Version" provider="java:RPC">

        <ns1:parameter name="allowedMEthods" value="getVersion" />

        <ns1:parameter name="className" value="org.apache.axis.Version" />

    </ns1:service>

    <ns1:service name="MyService" provider="java:RPC">

        <ns1:parameter name="className" value="MyService" />

        <ns1:parameter name="allowMethods" value="*"/>

    </ns1:service>

    <ns1:transport name="http">

        <ns1:requestFlow>

            <ns1:handler type="URLMapper" />

            <ns1:handler type="java:org.apache.axis.handlers.http.HTTPAuthHandler" />

        </ns1:requestFlow>

        <ns1:parameter name="qs:list" value="org.apache.axis.transport.http.QSListHandler" />

        <ns1:parameter name="qs:wsdl" value="org.apache.axis.transport.http.SQWSDLHandler" />

        <ns1:parameter name="qs:list" value="org.apache.axis.transport.http.QSListHandler" />

        <ns1:parameter name="qs:method" value="org.apache.axis.transport.http.QSMethodHandler" />

        <ns1:parameter name="qs:method" value="org.apache.axis.transport.http.QSMethodHandler" />

        <ns1:parameter name="qs:wsdl" value="org.apache.axis.transport.http.SQWSDLHandler" />

    </ns1:transport>

    <ns1:transport name="local">

        <ns1:responseFlow>

            <ns1:handler type="LocalREsponder" />

        </ns1:responseFlow>

    </ns1:reansport>

</ns1:deployment>


D:/work>


D:/work>java org.apache.axis.client.AdminClient undeploy.wsdd

log4j:WARN No appenders could be found for logger(org.apache.axis.i18n.ProjectResourceBundle).

log4j:WARN Please initialize the log4j system property.

Processing file undeployt.wsdd

<Admin>Done processing</Admin>

D:/work>java Client "안녕, 세상아!"

log4j:WARN No appenders could be found for logger(org.apache.axis.i18n.ProjectResourceBundle).

log4j:WARN Please initialize the log4j system.property.

The AXIS engine could not find a target service to invoke! targetService is MyService

D:/work>

Posted by 나비:D
:

AXIS 설치

1. Axis압축파일(axis-bin-1_4.zip)를 다운받아 압축파일내에 있는 webapps/axis 폴더를 %CATALINA_HOME%/webapps에 푼다

2. 톰캣을 실행하고 브라우저에서 http://localhost:8080/axis/주소로 연결되면 성공


[Trouble Shooting]

위의 주소로 연결후 CAll이라고 되어 있는 링크를 클릭하면 아래와 같은 에러가 발생할 수 있다.

Call -Call a local endpoint that list's the caller's http headers

에러 : java.lang.RuntimeException: No compiler found in your classpath!(you may need to add 'tools.jar')


이는 톰캣 설치시 사용할 런타임 JRE 위치를 JDK가 아닌 JRE로 했기 때문입니다.

이럴 경우 톰캣을 다시 설치하여 JDK쪽의 경로로 변경해주면 된다. 그럴 수 없다면 JDK의 tool.jar를 %CATALINA_HOME%/common/lib로 복사해주면 된다.


JAVA_HOME은 E:/Program Files/Java/jdk1.5.0_09/lib/tool.jar

D:/work>copy "%JAVA_HOME%/lib/tools.jar" "%CATALINA_HOME%/common/lib"

1개 파일이 복사되었습니다.


Administer Axis, SOAPMonitor는 디폴트로 사용할 수 없게 되어 있으므로 지금은 무시한다.

Administer Axis는 web.xml에서 해당 부분을 주석해제하면 사용할 수 있고, SOAPMonitor는 4부에서 설명하겠다.


 [부가기능 설치]

3. JavaMail(javamail-1_4.zip)을 다운받아 압축파일내 mail.jar를 CLASSPATH에 등록

http://java.sun.com/products/javamail/downloads/index.html

4. ㅓㅁㅍ므먀ㅣsms ㅓㅁㄹ vozlwl(jaf-1_1-fr.zip)를 필요로 하므로 이 또한 설치(activation.jar)

http://java.sun.com/beans/glasgow/jaf.html

* 즉, mail.jar와 activation.jar를 %CATALINA_HOME%/common.lib에 넣어주면 된다.


[웹서비스 작성과 테스트(서버측)]

소스파일의 확장자를 jws로 변경하여 올리면 알아서 웹서비스를 수행한다.

jws확장자를 가지면 AXIS는 이 파일이 SOAP기능을 수행할 수 있게 자동으로 모든 과정을 처리해준다.

간편하게 테스트용으로 사용할 수 있겠으나 내부적으로 어떻게 돌아가는지 파악이 되지 않으므로 이런자동구성보다는 수동으로 제어(WSDD파일을 이용)하는 것이 바람직할 것이다.


D:work>type Calculator.java

public class Calculator{

    public int add(int a, int b){

        return a+b;

    }

    public int subtract(int a, int b){

        return a-b;

    }

}


D:work>copy Calculator.java "%CATALINA_HOME%webappsaxisCalculator.jws"

1개 파일이 복사되었습니다.


* .jws 확장자를 가지면 웹서비스로 인식하게끔 web.xml에 설정되어 있다.

위처럼 작업한 뒤, 브라우저에서 http://localhost:8080/axis/Calculator.jws로 접속하면 아래와 같다.


[브라우저 접속화면]

위처럼 확장자를 jws로 만들어 deploy하며느 AXIS는 자동으로 웹서비스가 제공될 수 있도록 처리해준다.

사용자 삽입 이미지


WSDL도 자동으로 만들어 주므로 편하다.


사용자 삽입 이미지


[콘솔에서 테스트 클라이언트(클라이언트측)]

D:work> type CalcClient.java


import org.apache.axis.client.Call;

import org.apache.axis.client.Service;

import org.apache.axis.encording.XMLType;

import org.apache.axis.utils.Options;

import javax.xml.rpc.ParameterMode;

public class CalcClient{

    public static void main(String[] args) throws Exception{

        Options options = new Options(args);

        String endpoint = http://localhost: + options.getPort() + "/axis/Calculator.jws";

        args = options.getRemainingArgs();

        if ( args == null || args.length != 3){

            System.err.println("Usage: CalcClient <add|subtract> arg1 arg2");

            return;

        }

        String method = args[0];

        if ( !(method.equals("add") || method.equals("subtract"))){

            System.err.println("Usage: CalcClient <add|subtract> arg1 arg2");

            return;

        }

        Integer i1 = new Integer(args[1]);

        Integer i2 = new Integer(args[2]);

        Service service = new Service();

        Call Call = (Call) service.createCall();

        call.setTargetEndpointAddress( new java.net.URL(endpoint));

        call.setOperationName(method);

        call.addParameter("op1", XMLType.XSD_INT, ParameterMode.IN);

        call.addParameter("op2", XMLType.XSD_INT, ParameterMode.IN);

        call.setReturnType(XMLType.XSD_INT);

        Integer ret = (Integer) call.invoke(new Object [] {i1, i2});

        System.out.println("Got result : " + ret);

    }

}


D:/work>set AXIS_HOME=D:/util/axis-1_4

D:/work>set AXIS_LIB=%AXIS_HOME%/lib

D:/work>set AXISCLASSPATH=%AXIS_LIB%/axis.jar;%AXIS_LIB%/jaxrpc.jar;%AXIS_LIB%/saaj.jar;%AXIS_LIB%/log4j-1.2.8.jar;%AXIS_LIB%/common-discovery-0.2.jar;%AXIS_LIB%/commons-logging-1.0.4.jar;%AXIS_LIB%/wsdl4j-1.5.1.jar

D:/work>set CLASSPATH=%CLASSPATH%;%AXISCLASSPATH%

D:/work>javac CalcClient.java

D:/work>java CalcClient add 1 2

log4j:WARN No appenders could be found for logger (org.apache.axis.i18n.ProjectResourceBundle).

log4k:WARN please initialize the log4j system. properly.

Got result : 3

D:work>java CalcClient subtract 3 1

log4j:WARN No appenders could be found for logger(org.apache.axis.i18n.ProjectResourceBundle).

log4j:WARN Please initialize the log4j system property.

Got result : 2


D:/work>

Posted by 나비:D
:
Posted by 나비:D
:
- 방법 1
<jsp:useBean id="year" scope="request" type="java.lang.String"/>
<jsp:useBean id="month" scope="request" type="java.lang.String"/>
<jsp:useBean id="last" scope="request" type="java.lang.Integer"/>
<jsp:useBean id="map" scope="request" type="java.util.Map<?,?>"/>
<jsp:useBean id="list" scope="request" type="java.util.List<com.acroem.undine.bean.Sensor>"/>

- 방법 2
String year = (String)request.getAttribute("year");
String month = (String)request.getAttribute("month");
Integer last = (Integer)request.getAttribute("last");
java.util.Map<?,?> map = (java.util.Map<?,?>)request.getAttribute("map");
java.util.List<?> list = (java.util.List<?>)request.getAttribute("list");

아직 어느방법이 좋다고 할순 없지만

방법 1의 경우에는 request 받을때 null이 들어 올 경우 오류가 발생함
방법 2의 경우에는 null이 와도 if문을 이용하여 null체크가 가능

아직 머가 좋다고 말 못하겠음 ㅋ
Posted by 나비:D
:

jsp :: Commons-DbUtils

2008. 3. 6. 11:07
 
출처 Min Gun | 민군
원문 http://blog.naver.com/levin01/100011050694

Commons-DbUtils

 

I. 어디서 다운을 받나요?


http://jakarta.apache.org/site/downloads/downloads_commons-dbutils.cgi


II. 설치는 어떻게 하나요?

다운 받은 commons-beanutils.jar는 자신의 /WEB-INF/lib/ 에 복사합니다


III. DbUtils란 무엇인가요?

DbUtils는 JDBC 작업을 좀더 쉽게 할수있도록 해주는 작은 클래스 집합입니다.


IV. 왜 DbUtils를 사용해야 하는가요?

① resource 누출에 대한 어떠한 가능성도 없습니다
  JDBC코딩을 하는데 있어서 쉽지않고 양도 만만치 않으며 지루해 지기 쉽습니다
  이러다 보면 자기도 모르게 Connection 누수를 발생시킬수 있는데 이러한 가능성을 배재해 줍니다


② 코드의 가독성이 높아집니다
  데이터베이스 처리하는데 필요한 코드의 양을 절대적으로 줄여야 합니다.
  남아있는 코드로 당신의 의도를 정확하게 나타내어야 합니다.


③ ResultSet으로 부터 JavaBean property로 세팅을 해줍니다!
  더이상 setter메소드를 이용하여 ResultSet으로부터 컬럼값을 가져오는 코딩을 하지 않아도 됩니다
  ResultSet 각각의 row는 bean instance의 에 완벽하게 전달해 줍니다


V. 어떻게 사용하나요?

  Connection, Statement, ResultSet 의 close를 간단하게!

    이럴때는 org.apache.commons.dbutils.DbUtils 클래스를 이용하자!

    이 클래스는 모두 static 메소드들로 구성되어있습니다

   

    사용예)

    DbUtils.close(conn);  
    DbUtils.close(stmt);
    DbUtils.close(rs);
    DbUtils.closeQuietly(conn);
    DbUtils.closeQuietly(stmt);
    DbUtils.closeQuietly(rs);
    DbUtils.closeQuietly(conn, stmt, rs);
    DbUtils.commitAndClose(conn);

    DbUtils.commitAndCloseQuietly(conn);
    DbUtils.loadDriver("com.mysql.jdbc.Driver");
    DbUtils.rollback(conn);


    closeQuietly 메소드처럼 뒤에 Quietly라고 붙어 있는 메소드는 익셉션 처리는 자체적으로 처리합니다,

    즉 자신을 call한곳으로 throw 하지 않습니다

    commitAndCloses는 connection을 commit 후 close 하며 rollback는 connection을 rollback 합니다

    loadDriver 는 JDBC 드라이버를 로딩 합니다


 파일로 저장된 SQL을 사용하자!

    이럴 때는 org.apache.commons.dbutils.QueryLoader 클래스를 이용합니다

    이 클래스는 SingleTone 패턴의 클래스입니다

    즉 파일로 저장된 SQL을 읽어 HashMap으로 로드하는 클래스 입니다

   

    사용예)

    QueryLoader queryloader = QueryLoader.getInstance();   //싱글톤
    HashMap hashmap = queryloader.load("sql");      

    queryloader.upload("sql");


    queryloader는 싱클톤이므로 위와같이 객체를 얻어옵니다

    load 함수는 Properties 클래스를 이용하여 sql.properties 파일을 읽어

    HashMap으로 저장하여 리턴하여 줍니다

    unload는 load시 따로 메모리에 저장해 놓았던 sql 정보를 해제합니다


  Setter함수로 더이상 머리 아프지 말자!

   이럴때는 org.apache.commons.dbutils.QueryRunner 클래스를 이용합니다


   사용예)

    ...  

    BoardVO boardVO = null;

    ArrayList arraylist = new ArrayList();

 

    resultset = statement.executeQuery("SELECT * FROM board_t");

    while (resultset.next()) {

        boardVO = new BoardVO();

        boardVO.setTitle("title");

        boardVO.setContent("content");

        boardVO.setWriter("writer");

        arraylist.add(boardVO);       

    }

    ..

   와 같은 코드는 다음과 같이 간략화 됩니다


   ResultSetHandler rsh= new BeanListHandler(BoardVO.class);
   QueryRunner queryRunner = new QueryRunner();

   List list = (List)queryRunner.query(conn, "SELECT * FROM board_t", rsh);


   정말 간단해 집니다 만약 테이블에 컬럼이 30~40개가 된다면..

   select 한문장 할려면 코드수가 몇십줄 입니다. 더이상 노가다 하지 맙시다~


   QueryRunner는 다음과 같은 함수를 지원합니다

   사용예)

  QueryRunner queryrunner = new QueryRunner();
   QueryRunner queryrunner = new QueryRunner(DataSource ds);
//datasource를 바로 이용할 수 있다

  queryRunner.query(Connection conn, String sql, ResultSetHandler rsh)
   queryRunner.query(Connection conn, String sql, Object param, ResultSetHandler rsh)
   queryRunner.query(Connection conn, String sql, Object[] params, ResultSetHandler rsh)


   여기서 말하는 Object param은 파라미터 전달시 사용됩니다

   ArrayList params = new ArrayList();
   params.add("100");

   params.add("200");

   ResultSetHandler rsh = new BeanListHandler(BoardVO.class);
   QueryRunner queryRunner = new QueryRunner();

   List list = (List)queryRunner.query(conn, "SELECT * FROM board_t WHERE boardNo > ? and boardNo < ?", params.toArray(), rsh);


   select 뿐만 아니라 update, delete역시 가능합니다

   사용예)

   QueryRunner queryRunner = new QueryRunner();

   queryRunner.update(Connection conn, String sql)
   queryRunner.update(Connection conn, String sql, Object param)
   queryRunner.update(Connection conn, String sql, Object params[])

  

   ArrayList params = new ArrayList();
   params.add(boardId);
   queryRunner.update(connection, "UPDATE board_t SET read = read + 1 WHERE boardNo = ?", params.toArray());

   와 같이 사용할 수 있습니다



VI. 샘플코드

public class DbUtilsExample() {

   public static void main(String[] args) {

       HashMap map = QueryLoader.getInstance().load("sql");  // (주의) load함수는 실행할때마다 파일을 읽습니다


       Connection conn = null;

       try {

           DbUtils.loadDriver("com.mysql.jdbc.Driver");

           conn = DriverManager.getConnection("jdbc:mysql://localhost/mysql", "root", "");


           ArrayList params = new ArrayList();
           params.add(args[0]);


           ResultSetHandler rsh = new BeanListHandler(BoardVO.class);

           QueryRunner qr = new QueryRunner();

           List list = qr.query(conn, (String)map.get("select"), params.toArray(), rsh);


           for (int i = 0; i < list.size(); i++) {

               BoardVO board = (BoardV)list.get(i);

               System.out.println(board.getTitle());

               System.out.println(board.getContent());

               System.out.println(board.getWriter());

          )

       } catch (Exception e) {

           System.out.println(e);

       } finally {

           DbUtils.closeQuitely(conn);

       }

   }

}



Posted by 나비:D
:

BLOG main image
by 나비:D

공지사항

카테고리

분류 전체보기 (278)
Programming? (0)
---------------------------.. (0)
나비의삽질 (5)
Application (177)
SQL (51)
Web (27)
etc. (14)
Omnia (0)
---------------------------.. (0)

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

달력

«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Total :
Today : Yesterday :