태그를 사용하여 POST 방식으로 요청을 전송합니다.
????Note: 쿼리스트링은 URL 뒤에 “?키=값&키=값” 형태로 덧붙여진 부분을 말합니다.
❸ 역시 태그를 통해 POST 방식으로 요청합니다. 다만 이번에는 다양한 태그를 사용했습니다. type 속성에 따라 매개변수를 읽어오는 방식이 조금 다른데, 다음 절에서 설명합니다.
❹ 에서는 HTTP 요청 헤더를 읽기 위한 링크를 생성했습니다. 2.3에서 링크를 통해 이동했을 때와 직접 실행했을 때 출력되는 정보의 차이를 확인해보겠습니다.
다음은 RequestMain.jsp 실행 화면 중 ‘1. 클라이언트와 서버의 환경정보 읽기’ 부분입니다.
그리고 다음 예제 코드는 이 페이지에서 ‘GET 방식 전송’ 링크나 [POST 방식 전송] 버튼을 클릭했을 때 나타나는 페이지의 소스입니다. 보다시피 request 내장 객체로부터 클라이언트와 서버의 환경정보를 읽어와 화면에 표시해줍니다.
▼ 환경정보 읽기
Use a different Browser
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
내장 객체 - request 1. 클라이언트와 서버의 환경정보 읽기 데이터 전송 방식 : <%= request.getMethod() %> ❶ URL : <%= request.getRequestURL() %> ❷ URI : <%= request.getRequestURI() %> ❸ 프로토콜 : <%= request.getProtocol() %> 서버명 : <%= request.getServerName() %> 서버 포트 : <%= request.getServerPort() %> 클라이언트 IP 주소 : <%= request.getRemoteAddr() %> ❹ 쿼리스트링 : <%= request.getQueryString() %> ❺ 전송된 값 1 : <%= request.getParameter("eng") %> ❻ 전송된 값 2 : <%= request.getParameter("han") %>
❶ 의 getMethod( ) 메서드는 GET과 POST 같은 전송 방식을 반환합니다. 앞서 ‘GET 방식 전송’ 링크를 클릭했다면 “GET”을, [POST 방식 전송] 버튼을 클릭했다면 “POST”를 반환할 것입니다.
❷ 의 getRequestURL( )과 ❸ 의 getRequestURI( ) 메서드는 요청 주소를 반환합니다. 여기서 URL과 URI의 차이는 호스트host를 포함하느냐 여부입니다. URL은 호스트를 포함한 전체 주소를 뜻하며, URI는 호스트를 제외한 컨텍스트 루트부터의 주소를 뜻합니다.
????Note: 컨텍스트 루트는 호스트명 다음에 나오는 프로젝트명 정도로 생각하면 됩니다.
❹ 의 getRemoteAddr( ) 메서드는 클라이언트의 IP 주소를 반환합니다. localhost로 접속했을 때는 0:0:0:0:0:0:0:1과 같이 출력됩니다. 윈도우 10에서는 IPv6를 반환하는 게 기본이기 때문인데, WAS 설정을 IPv4로 변경하면 127.0.0.1로 출력됩니다.
❺의 getQueryString( ) 메서드는 요청 주소 뒷부분의 매개변수 전달을 위한 쿼리스트링 전체를 반환합니다. 쿼리스트링 중 특정 키값을 얻어오려면 ❻ 처럼 getParameter( ) 메서드에 키값을 인수로 넣어주면 됩니다.
RequestMain.jsp 실행 화면에서 ‘GET 방식 전송’ 링크를 클릭했을 때의 결과는 다음과 같습니다. 주소표시줄을 보면 쿼리스트링으로 매개변수가 2개 전달되었고, 출력도 정상적으로 되었습니다.
[POST 방식 전송] 버튼을 클릭했을 때의 결과는 다음과 같습니다.
❶ POST 방식이므로 주소표시줄에는 경로 외에는 아무것도 표시되지 않습니다. ❷ 그러므로 쿼리스트링은 null이 출력됩니다.
2.2 클라이언트의 요청 매개변수 읽기
태그 하위 요소를 통해 입력한 값들도 서버로 전송됩니다. 전송된 값은 서버에서 읽은 후 변수에 저장하고, 적절한 처리를 위해 컨트롤러(Controller)나 모델(Model)로 전달됩니다. 대표적으로 회원가입이나 로그인 등을 예로 들 수 있습니다.
다음은 RequestMain.jsp 실행 화면 중 ‘2. 클라이언트의 요청 매개변수 읽기’ 부분입니다.
값을 적당히 입력하고 [전송하기] 버튼을 클릭하면 POST 방식으로 RequestParameter.jsp에 전송됩니다.
▼ 요청 매개변수 읽기
Use a different Browser
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
내장 객체 - request <%request.setCharacterEncoding("UTF-8"); ❶String id = request.getParameter("id"); ❷String sex = request.getParameter("sex");String[] favo = request.getParameterValues("favo"); ❸String favoStr = "";if (favo != null) { ❹ for (int i = 0; i < favo.length; i++) { favoStr += favo[i] + " "; }}String intro = request.getParameter("intro").replace("\r\n", " "); ❺%> 아이디 : <%= id %> 성별 : <%= sex %> 관심사항 : <%= favoStr %> 자기소개 : <%= intro %>
톰켓의 버전에 따라 POST 방식으로 전송된 값이 한글인 경우 깨짐 현상이 발생할 수 있습니다. 이럴 때는 ❶ 처럼 다국어를 지원하는 UTF-8로 인코딩해주면 해결됩니다.
❷ 전송되는 값이 하나라면 getParameter( ) 메서드로 받을 수 있습니다. 주로 type 속성이 text, radio, password인 경우 사용되고, checkbox인 경우라도 선택값이 하나라면 getParameter( )로 값을 받을 수 있습니다.
하지만 type 속성이 checkbox인 경우는 대부분 값을 여러 개 선택하기 위해 사용하므로 ❸ 처럼 getParameterValues( )로 받아야 합니다. 값이 2개 이상이므로 String 배열을 반환합니다. ❹ 그리고 for문을 이용해서 String 배열에 담긴 값들을 하나의 문자열로 합쳤습니다.
마지막으로 textarea 태그는 텍스트를 여러 줄 입력할 수 있습니다. ❺ 그래서 출력 시에는 enter 키를 태그로 변환해야 줄바꿈이 제대로 반영됩니다. enter 는 특수 기호 \r\n으로 입력됩니다.
다음은 전송 결과의 예시입니다.
2.3 HTTP 요청 헤더 정보 읽기
HTTP 프로토콜은 헤더에 부가적인 정보를 담도록 하고 있습니다. 웹 브라우저의 종류나 선호하는 언어 등 일반적인 HTML 문서 데이터 외의 추가 정보를 서버와 클라이언트가 교환할 수 있도록 문서의 선두에 삽입할 수 있습니다. 먼저 요청 헤더를 읽어오는 방법을 알아보죠.
‘요청 헤더 정보 읽기’를 클릭하면 아래 요청 헤더 읽기의 RequestHeader.jsp 코드가 실행됩니다.
▼ 요청 헤더 읽기
Use a different Browser
<%@ page import="java.util.Enumeration"%><%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
내장 객체 - request 3. 요청 헤더 정보 출력하기 <% Enumeration headers = request.getHeaderNames(); ❶ while (headers.hasMoreElements()) { ❷ String headerName = (String)headers.nextElement(); ❸ String headerValue = request.getHeader(headerName); ❹ out.print("헤더명 : " + headerName + ", 헤더값 : " + headerValue + " "); } %> 이 파일을 직접 실행하면 referer 정보는 출력되지 않습니다.
❶ 의 getHeaderNames( ) 메서드는 모든 요청 헤더의 이름을 반환합니다. 반환 타입은 Enumeration입니다. ❷ 에서는 while문에서 hasMoreElements( )를 이용해 출력할 요청 헤더명이 더 있는지 확인합니다. ❸ 헤더명이 더 있다면 요청 헤더의 이름을 얻어온 다음, ❹ getHeader( ) 메서드에 헤더명을 건네 헤더값을 얻어옵니다.
실행 결과는 다음과 같습니다.
user-agent : 웹 브라우저의 종류를 알 수 있습니다. 크롬, 파이어폭스, 익스플로러 등 여러가지 웹 브라우저에서 테스트해보면 조금씩 다른 결과가 출력될 것입니다.
referer : 리퍼러는 웹을 서핑하면서 링크를 통해 다른 사이트로 방문 시 남는 흔적을 말합니다. 예를 들어 [예제 2-1]에서 클릭해서 이동하면 리퍼러가 출력되지만, RequestedHeader. jsp를 직접 실행하면 리퍼러는 출력되지 않을 것입니다. 리퍼러는 웹 사이트 방문객이 어떤 경로로 접속하였는지 알아볼 때 유용합니다.
cookie : 요청 헤더를 통해 쿠키도 확인할 수 있습니다.
3. response 객체
request 내장 객체가 클라이언트의 요청 정보를 저장하는 역할을 했다면, response 내장 객체는 그와 반대로 요청에 대한 응답을 웹 브라우저로 보내주는 역할을 합니다. 주요 기능으로는 페이지 이동을 위한 리다이렉트redirect와 HTTP 헤더에 응답 헤더 추가가 있습니다. 이 두 기능 외에도 몇 가지가 더 있으나 JSP에서는 거의 사용하지 않습니다.
3.1 sendRedirect()로 페이지 이동하기
▼ 로그인 폼과 응답 헤더 설정 페이지
Use a different Browser
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
내장 객체 - response 1. 로그인 폼 <% String loginErr = request.getParameter("loginErr"); ❶ if (loginErr != null) out.print("로그인 실패"); ❷ %> ❸ 아이디 : 패스워드 : 2. HTTP 응답 헤더 설정하기
❶ 의 loginErr은 로그인 실패 여부를 알려주는 매개변수입니다. 곧이어 살펴볼 로그인 처리하기 예제에서 만약 로그인에 실패하면 이 매개변수에 값을 설정하도록 했습니다. ❷ 즉, 이 매개변수에 값이 들어 있다면 로그인에 실패했음을 뜻하므로 “로그인 실패”를 출력합니다. 그리고 ❸ 에서는 아이디와 패스워드를 입력받는 간단한 로그인 폼을 구성합니다.
❹ 에서는 응답 헤더 추가를 위한 입력 폼을 구성하며, ❺ 에서 헤더에 추가할 데이터의 형식별로 value 속성에 미리 입력해두었습니다. 이 부분은 다음 절에서 사용합니다.
실행 화면은 다음과 같습니다.
????Note: 날짜 형식의 응답 헤더를 지정하는 경우에는 반드시 날짜와 함께 시간을 추가하는 것이 좋습니다. 대한민국은 세계 표준시보다 9시간이 느립니다. 따라서 09:00을 추가하지 않으면 하루 전 날짜가 출력됩니다.
‘1. 로그인 폼’ 영역에 아이디와 패스워드를 입력한 후 [로그인] 버튼을 클릭하면 요청이 로그인 처리하기 예제의 ResponseLogin.jsp 페이지로 전송됩니다.
▼ 로그인 처리하기
Use a different Browser
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
내장 객체 - Response <%String id = request.getParameter("user_id"); ❶String pwd = request.getParameter("user_pwd"); if (id.equalsIgnoreCase("must") && pwd.equalsIgnoreCase("1234")) { ❷ response.sendRedirect("ResponseWelcome.jsp"); ❸}else { request.getRequestDispatcher("ResponseMain.jsp?loginErr=1") ❹ .forward(request, response); }%>
이 코드는 먼저 ❶ 에서 request 내장 객체로 전송된 매개변수를 얻어온 다음, ❷ 에서 회원 인증을 진행합니다. 아직 데이터베이스 연동법을 배우지 않았기 때문에 아이디와 패스워드를 각각 must”와 “1234”로 하드코딩해뒀습니다.
인증에 성공하면 ❸ 이 실행되며, sendRedirect( ) 메서드에 건넨 응답 페이지로 이동합니다. 자바스크립트의 location.href와 같은 기능이라 보면 됩니다. ResponseWelcome.jsp는 로그인 성공 페이지입니다.
❹ 반면 인증에 실패하면 request 내장 객체를 통해 로그인 페이지, 즉 ResponseMain.jsp로 포워드forward; 전달됩니다. 포워드는 페이지 이동과는 다르게 제어 흐름을 넘겨주고자 할 때 사용합니다. 이때 쿼리스트링으로 loginErr 매개변수를 전달하여 로그인 성공 여부를 알려주고 있습니다.
다음으로 회원 인증에 성공했을 때 이동되는 ResponseWelcome.jsp 파일을 보겠습니다.
▼ 로그인 성공 페이지
Use a different Browser
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
내장 객체 - response 로그인 성공
특별한 로직 없이 성공 여부만 간단히 알려줍니다.
하지만 로그인에 실패하면 로그인 처리하기 예제의 ❹ 에서 ResponseMain.jsp로 포워드하는데, 이때 매개변수 loginErr가 전달됩니다. 이를 통해 로그인 실패 메시지를 화면에 출력할 수 있습니다.
그런데 화면에는 분명 ResponseMain.jsp의 내용이 출력되었지만, 웹 브라우저의 주소표시줄을 보면 ResponseLogin.jsp로 표시되어 있습니다. 포워드는 이처럼 실행의 흐름만 특정한 페이지로 넘겨주는 역할을 합니다.
3.2 HTTP 헤더에 응답 헤더 추가하기
response 내장 객체는 응답 헤더에 정보를 추가하는 기능을 제공합니다. 정보 추가용 메서드는 add 계열과 set 계열이 있습니다. add 계열은 헤더값을 새로 추가할 때 사용하고, set 계열은 기존의 헤더를 수정할 때 사용합니다. 로그인 폼과 응답 헤더 설정 페이지 예제의 ‘2. HTTP 응답 헤더 추가 설정하기’ 부분에서 적당한 값을 입력한 후 [응답 헤더 설정 & 출력] 버튼을 클릭해보세요.
버튼을 클릭하면 응답 헤더에 값 추가하기 예제의 ResponseHeader.jsp가 실행되며, 이 페이지는 전달받은 값을 응답 헤더에 추가해 되돌려줍니다.
▼ 응답 헤더에 값 추가하기
Use a different Browser
<%@ page import="java.util.Collection"%><%@ page import="java.text.SimpleDateFormat"%><%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%// 응답 헤더에 추가할 값 준비 SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd HH:mm"); ❶long add_date = s.parse(request.getParameter("add_date")).getTime(); int add_int = Integer.parseInt(request.getParameter("add_int")); ❷String add_str = request.getParameter("add_str");// 응답 헤더에 값 추가response.addDateHeader("myBirthday", add_date);response.addIntHeader("myNumber", add_int);response.addIntHeader("myNumber", 1004); // 추가 ❸response.addHeader("myName", add_str);response.setHeader("myName", "안중근"); // 수정 ❹%>
내장 객체 - response 응답 헤더 정보 출력하기 ❺ <% Collection headerNames = response.getHeaderNames(); for (String hName : headerNames) { String hValue = response.getHeader(hName); %> <%= hName %> : <%= hValue %> <% } %> myNumber만 출력하기 ❻ <% Collection myNumber = response.getHeaders("myNumber"); for (String myNum : myNumber) { %> myNumber : <%= myNum %> <% } %>
우선 응답 헤더에 추가할 값들을 준비하는 코드를 살펴봅시다. ❶ 에서는 0000-00-00 00:00(년-월-일 시:분) 형식으로 전송된 add_date 매개변수의 값을 long 타입으로 변경합니다. 변경된 값은 타임스탬프(Timestamp)라고 표현하는데, 1970년 1월 1일 0시 0분 0초부터 현재까지의 시간을 밀리초 단위로 환산한 값을 말합니다. ❷ 한편, 폼값으로 전송되는 값은 항상 String 타입이므로 add_int도 문자열로 얻어집니다. 따라서 이를 정수 형태로 사용할 때는 반드시 변환해야 합니다.
다음은 응답 헤더에 값을 추가하는 코드 차례입니다. 먼저 add 계열의 메서드로 헤더값을 추가합니다. 특히 ❸ 에서는 바로 위에서 추가한 “myNumber”라는 동일한 헤더명으로 새로운 값을 추가하고 있는데, add 계열이므로 같은 헤더명으로 값이 하나 더 추가됩니다. 반면 ❹ 처럼 set 계열의 메서드를 사용하면 이전 값이 수정됩니다(같은 이름의 헤더가 없었다면 새로 추가됩니다).
❺ 부분의 실행 결과는 다음과 같습니다.
보다시피 “myNumber”가 두 번 출력되며 그 값은 모두 8282로 동일합니다. 이는 getHeader( ) 메서드의 특성으로, 값이 여러 개더라도 첫 번째 값만 가져오기 때문입니다.
반면 myName은 set 계열 메서드를 이용해서 수정되었으므로 “홍길동”이 아닌 “안중근”이 출력되었습니다.
그럼 이번에는 myNumber만 출력하는 ❻ 부분의 실행 결과를 보겠습니다.
헤더명은 같지만 다른 값을 출력했습니다. 이와 같이 add 계열 메서드는 헤더명이 같더라도 (덮어쓰지 않고) 계속 누적시킵니다.
????Note
add 계열 메서드: 새로운 헤더명으로 값을 추가합니다. 동일한 헤더명이 있으면 동일한 이름으로 값을 추가합니다.
set 계열 메서드: 기존의 헤더값을 수정합니다. 단, 동일한 헤더명이 존재하지 않는다면 새롭게 추가합니다.
4. out 객체
out 내장 객체는 웹 브라우저에 변수 등의 값을 출력할 때 주로 사용합니다. 하지만 JSP를 작성하면서 사용하는 일은 그리 많지 않습니다. 대부분 상황에서 이 객체보다는 표현식<%= %>이 더 편리하기 때문입니다. 하지만 스크립틀릿 내에서 변수를 웹 브라우저에 출력해야 한다면 표현식보다는 out 내장 객체를 사용하는 편이 좋습니다.
out 내장 객체는 버퍼를 사용합니다. 즉, 출력되는 모든 정보는 버퍼에 먼저 저장된 후 웹 브라우저에 출력됩니다. 예제를 살펴보시죠.
▼ out 객체로 값 출력하기
Use a different Browser
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
내장 객체 - out <% // 버퍼 내용 삭제하기 out.print("출력되지 않는 텍스트"); // 버퍼에 저장 ❶ out.clearBuffer(); // 버퍼를 비움(윗 줄의 출력 결과 사라짐) ❷ out.print("out 내장 객체 "); // 버퍼 크기 정보 확인 out.print("출력 버퍼의 크기 : " + out.getBufferSize() + " "); ❸ out.print("남은 버퍼의 크기 : " + out.getRemaining() + " "); ❹ out.flush(); // 버퍼 내용 출력 ❺ out.print("flush 후 버퍼의 크기 : " + out.getRemaining() + " "); ❻ // 다양한 타입의 값 출력 ❼ out.print(1); out.print(false); out.print('가'); %>
버퍼를 사용한다는 점만 주의하면 어렵지 않습니다. 우선 ❶ 에서 print( ) 메서드로 쓴 내용은 먼저 버퍼에 들어가게 되는데, ❷ 에서 clearBuffer( ) 메서드로 버퍼 안의 내용을 지워버렸습니다. 그래서 ❶ 에서 쓴 문자열은 출력되지 않습니다.
❸~❻ 에서는 버퍼의 크기 관련 정보를 얻는 예를 보여줍니다. 의 getBufferSize( )는 현재 페이지에 설정된 버퍼의 크기를 가져옵니다. 버퍼 크기를 page 지시어로 따로 선언하지 않았으므로 기본값인 8KB가 될 것입니다. 한편 getRemaining( ) 메서드는 사용하고 남은 버퍼의 크기를 알려줍니다. 그래서 ❹ 와 ❻ 은 각각 버퍼 플러시 전과 후의 남은 크기를 출력해줍니다.
❺ 의 flush( ) 메서드는 버퍼에 담긴 내용을 강제로 플러시합니다. 버퍼는 원래 모두 채워졌을 때 플러시되면서 내용을 출력하지만, 필요한 경우에는 이처럼 즉시 출력할 수 있습니다.
마지막으로 ❼ 은 print( ) 메서드를 이용해 다양한 타입의 데이터를 출력하는 예입니다. 문자열, 문자, 숫자, boolean 등 기본 자료형은 모두 가능합니다.
실행 결과는 다음과 같습니다.
print( )를 사용하면서 버퍼가 채워지다가, flush( )로 모두 출력한 후 크기가 복원된 것을 알 수 있습니다. print( ) 외에 println( )도 있는데, 차이점은 입력 끝에 줄바꿈 문자(\r\n)를 추가한다는 것뿐입니다. 여기서 오해를 하는 경우가 있는데요, 줄바꿈 문자가 추가되니 웹 브라우저에서 보이는 화면에서도 줄바꿈 처리가 되지 않을까 라는 생각을 하게 됩니다. 하지만 HTML 문서에서 줄을 바꾸려면 줄바꿈 문자가 아니라 태그를 사용해야 합니다. 따라서 print( )와의 차이는 띄어쓰기 한 칸이 적용되는 정도입니다.
2.5 application 객체
application 내장 객체는 웹 애플리케이션당 하나만 생성되며, 모든 JSP 페이지에서 접근할 수 있습니다. 앞서 내장 객체의 종류 표에서 언급했듯이 application 내장 객체는 ServletContext 타입입니다. 주로 웹 애플리케이션 전반에서 이용하는 정보를 저장하거나, 서버의 정보, 서버의 물리적 경로 등을 얻어오는 데 사용합니다.
이번에는 web.xml에 설정한 컨텍스트 초기화 매개변수를 읽어오고 폴더의 물리적 경로를 알아내는 모습을 보여드리겠습니다.
참고로 web.xml은 웹 애플리케이션에 대한 여러 가지 설정을 저장하는 곳으로, 배포 서술(Deployment Descriptor)라고 부릅니다. 물리적 경로란 특정 파일이나 폴더의 전체 경로, 즉 절대 경로를 말하며, 파일을 업로드하거나 입출력 작업 시에 주로 사용합니다.
먼저 WEB-INF 폴더에 있는 web.xml 파일을 열어서 아래 초기화 매개변수 추가하기 예제처럼 초기화 매개변수를 추가해주세요.
▼ 초기화 매개변수 추가하기
Use a different Browser
MustHaveJSP ... 생략 ... INIT_PARAM web.xml에 저장한 초기화 매개변수
보시는 것처럼 태그를 만들고, 그 안에 초기화 매개변수의 이름과 값을 입력하면 됩니다.
다음은 application 내장 객체를 이용하는 코드를 보겠습니다.
▼ 다양한 서버 정보 얻어오기
Use a different Browser
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
내장 객체 - application web.xml에 설정한 내용 읽어오기 초기화 매개변수 : <%= application.getInitParameter("INIT_PARAM") %> ❶ 서버의 물리적 경로 얻어오기 application 내장 객체 : <%= application.getRealPath("/02ImplicitObject") %> ❷ 선언부에서 application 내장 객체 사용하기 <%! public String useImplicitObject() { ❸ return this.getServletContext().getRealPath("/02ImplicitObject"); } public String useImplicitObject(ServletContext app) { ❹ return app.getRealPath("/02ImplicitObject"); } %> this 사용 : <%= useImplicitObject() %> ❺ 내장 객체를 인수로 전달 : <%= useImplicitObject(application) %> ❻
❶ 에서는 getInitParameter( ) 메서드를 이용해서 web.xml에 설정한 초기화 매개변수를 읽어왔습니다. web.xml에서 “INIT_PARAM”을 설정하지 않았다면 null을 반환할 것입니다.
❷ 에서는 getRealPath( ) 메서드로 현재 예제를 작성 중인 폴더(“/02ImplicitObject”)의 물리적 경로를 얻어와서 출력합니다. 인수로는 ‘컨텍스트 루트를 제외한’ 경로를 입력하면 됩니다.
❸ 과 ❹ 는 선언부에 정의한 메서드들입니다. 두 메서드 모두 “/02ImplicitObject”의 물리적 경로를 반환하지만, 이때 필요한 서블릿 컨텍스트를 ❸ 은 this로부터 얻는 데 반해 ❹ 는 매개변수로 받습니다.
마지막으로 ❺ 에서는 this를 이용하는 ❸ 을 호출하고, ❻ 에서는 application 내장 객체를 인수로 하여 ❹ 를 호출합니다.
실행 결과는 다음과 같습니다.
서버의 물리적 경로는 세 가지 모두 동일한 결과가 출력될 것입니다. 단지 사용 방법이 조금 다릅니다. 스크립틀릿이나 표현식에서 사용할 때는 application 내장 객체를 그대로 사용하면 됩니다. 하지만 선언부에서는 application 내장 객체를 바로 사용하는 것은 불가능합니다. 따라서 this를 통해 application 내장 객체를 얻어오거나, 인수로 전달해야지만 사용할 수 있습니다.
실행 결과를 보면 조금 의아한 점이 있을 것입니다. 분명히 우리는 02Workspace 하위에 프로젝트를 생성했는데 출력 내용은 뭔가 어마무시하게 길어져 있습니다. 이유는 우리가 이클립스를 사용했기 때문입니다. 작성한 JSP 파일을 실행하면 이클립스는 별도의 디렉터리를 생성하여 서블릿 변환과 컴파일을 진행하게 됩니다. 차후 19장에서 톰캣에 배포한 후 실행하면 JSP 파일이 있는 위치가 그대로 출력될 것입니다.
6. exception 객체
exception 내장 객체는 주로 오류명과 오류 메시지를 출력하는 부분에서 사용하며, JSP에서 그 이상으로 사용되는 경우가 거의 없기 때문에 이번에는 오류 페이지를 처리하는 또 다른 방식을 학습해보겠습니다.
JSP로 프로그래밍을 하다 보면 가장 빈번하게 발생되는 에러가 404, 405, 500 에러입니다.
▼ HTTP 에러 코드 설명 및 조치 방법
HTTP에서 발생되는 에러는 훨씬 다양하나, 위 표의 세 가지 정도만 알고 있어도 충분합니다.
이번에는 에러가 발생했을 때 에러별로 출력할 페이지를 분기하는 방법을 알아보겠습니다. 이 방법을 이용하려면 web.xml에 설정을 추가해야 합니다.
▼ web.xml에 에러별 출력 페이지 설정
Use a different Browser
... 생략 ...
보다시피 에러 코드를 정수로 명시하고, 해당 에러 발생 시 웹 브라우저에 출력할 페이지와 경로를 지정했습니다. 엘리먼트에 경로를 명시할 때는 컨텍스트 루트를 제외한 나머지를 기술하면 됩니다. 경로는 슬래시(/)로 시작해야 합니다.
편의상 Exception.jsp라는 파일 하나에서 모든 에러를 처리하도록 했습니다. 다음 예제는 출력 페이지의 코드입니다.
▼ 에러 출력 페이지
Use a different Browser
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
내장 객체 - exception <%int status = response.getStatus(); // response 내장 객체로부터 에러 코드 확인System.out.println(status);// 에러 코드에 따라 적절한 메시지 출력if (status == 404) { out.print("404 에러가 발생하였습니다."); out.print(" 파일 경로를 확인해주세요.");}else if (status == 405) { out.print("405 에러가 발생하였습니다."); out.print(" 요청 방식(method)을 확인해주세요.");}else if (status == 500) { out.print("500 에러가 발생하였습니다."); out.print(" 소스 코드에 오류가 없는지 확인해주세요.");}%>