자바(JAVA)/JSP 웹 프로그래밍 공부 (성낙현의 JSP 자바 웹 프로그래밍 참고)

JAVA/JSP 5. 내장 객체 - 내장 객체란? Request, Response 객체

개발학생 2023. 3. 23. 00:04
반응형

*JSP의 내장 객체란?

  • JSP에 내장되어있는, 웹 프로그래밍에 있어 가장 핵심적이고 유용한 객체 (광범위하게 사용됨)
    → 클라이언트에서 요청받기, 클라이언트의 요청에 응답하기, 화면 출력, 세션, 페이지, 애플리케이션
        등을 내장 객체로 제공
  • 웹의 동작 방식: 아래 그림처럼 클라이언트가 서버로 요청을 보내면, 서버는 그에 맞는 결과를 응답으로 돌려주는 형태 → 이때 내장 객체가 요청, 응답, HTTP 헤더(header) 등의 정보를 쉽게 다룰 수 있도록 해 줌
  • JSP 페이지가 실행될 때 컨테이너가 자동으로 생성해 줌 (별도로 선언하거나 객체로 생성하지 않아도 즉시 사용 가능 → JSP가 실행될 때 자바 파일인 서블릿으로 변환되고 클래스 파일로 컴파일되는 과정에서,
        생성된 _jspService() 메소드 안의 코드가 중요

*윈도우 탐색기에서 이동
C:\[설정한 작업공간 경로 (필자는JavaMiniProject)]\.metadata\.plugins\org.eclipse.wst.server.core\ tmp0\work\Catalina\localhost\MustHaveJSP_origin\org\apache\jsp\_01DirectiveScript

→ ScriptElements.jsp 파일이 서블릿으로 변환된 .java파일과, 그후 컴파일이 완료된 .class파일이 존재함 (총 2개)
    : ScriptElements.jsp를 처음 실행했을 때, ScriptElements_jsp.java로 변환된 후 ScriptElements_jp.class로 컴파일된 것

→ 그 중 .java 파일을 메모장으로 열어봄 (마우스 우클릭 → [연결 프로그램] → 메모장)

// _jspService() 메소드 안의 코드-객체를 선언하고 초기화하는 선언문인 것을 알 수 있음
// =내장 객체의 참조 변수를 컨테이너가 생성하는 부분

public void _jspService() {
... 생략 ...

	  final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;

... 생략 ...
}

 

  • 컨테이너가 미리 선언해놓은 참조 변수를 이용해 사용
  • JSP 문서 안의 <% 스크립틀릿 %>과 <%= 표현식 %>에서만 사용 가능
  • <%! 선언부 %>에서는 즉시 사용 불가능 → 매개변수로 전달받아 사용하는 건 가능
  • 내장 객체의 종류 - page와 config는 거의 사용되지 않음
request javax.servlet.http.HttpServletRequest 클라이언트의 요청 정보 저장
response javax.servlet.http.HttpServletResponse 클라이언트의 요청에 대한 응답 정보 저장
out javax.servlet.jsp.JspWriter JSP 페이지에 출력할 내용을 담는 출력 스트림
session javax.servlet.http.HttpSession ‘웹 브라우저 정보를 유지하기 위한’ 세션 정보를 저장
application javax.servlet.ServletContext ‘웹 애플리케이션 관련’ 컨텍스트 정보 저장
pageContext javax.servlet.jsp.PageContext JSP 페이지에 대한 정보 저장
page java.lang.Object ‘JSP 페이지를 구현한’ 자바 클래스의 인스턴스
config javax.servlet.ServletConfig JSP 페이지에 대한 설정 정보를 저장
exception java.lang.Throwable 예외가 발생한 경우 사용

 

1. request 객체

  • JSP에서 가장 많이 사용되는, 클라이언트(주로 웹 브라우저)가 전송한 요청 정보를 담고 있는 객체

 

*클라이언트의 요청을 전송하기 위한 페이지(HTML로만 구성되어 있음)

// RequestMain.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head><title>내장 객체 - request</title></head>
<body>
    <h2>1. 클라이언트와 서버의 환경정보 읽기</h2>
    <a href="./RequestWebInfo.jsp?eng=Hello&han=안녕">  <!--1. GET 방식으로 요청-->
      GET 방식 전송
    </a>
    <br />
    <form action="RequestWebInfo.jsp" method="post">  <!--2. POST 방식으로 요청-->
        영어 : <input type="text" name="eng" value="Bye" /><br />
        한글 : <input type="text" name="han" value="잘 가" /><br />
        <input type="submit" value="POST 방식 전송" />
    </form>

    <h2>2. 클라이언트의 요청 매개변수 읽기</h2>
    <form method="post" action="RequestParameter.jsp">  <!--3. 다양한 <input> 태그 사용-->
        아이디 : <input type="text" name="id" value="" /><br />
        성별 :
        <input type="radio" name="sex" value="man" />남자
        <input type="radio" name="sex" value="woman" checked="checked" />여자
        <br />
        관심사항 :
        <input type="checkbox" name="favo" value="eco" />경제
        <input type="checkbox" name="favo" value="pol" checked="checked" />정치
        <input type="checkbox" name="favo" value="ent" />연예<br />
        자기소개:
        <textarea name="intro" cols="30" rows="4"></textarea>
        <br />
        <input type="submit" value="전송하기" />
    </form>

    <h2>3. HTTP 요청 헤더 정보 읽기</h2>
    <a href="RequestHeader.jsp">  <!--4. HTTP 요청 헤더 읽기-->
        요청 헤더 정보 읽기
    </a>    
</body>
</html>

1. GET 방식으로 요청

: 클라이언트의 요청에 따른 서버의 환경정보를 읽기 위해 링크 생성.

<a> 태그(한 페이지에서 다른 페이지 연결할 때 사용하는 하이퍼링크 정의)로 생성한 링크이므로 GET 방식으로 전송됨

링크 뒤에는 2개의 매개변수가 쿼리스트링(query string: URL 뒤에 “?키=값&키=값”형태로 덧붙여진 부분)으로 전달됨

 

2. POST 방식으로 요청

: 1. 과 똑같은 링크이나 <form> 태그를 사용하고 method 속성을 “post”로 설정하여 POST 방식으로 요청을 전송함         (method 속성을 ‘get’으로 설정하거나 아예 정의하지 않으면, GET 방식으로 요청을 전송함)

 

3. 다양한 <input> 태그 사용

: 2. 와 같이 <form> 태그를 통해 POST 방식으로 요청을 전송하는데,

 여기에, ‘type 속성에 따라 매개변수를 읽어오는 방식이 달라지는’ 다양한 <input>태그 사용

 

4. HTTP 요청 헤더 읽기

: 링크를 통해 이동했을 때와 직접 실행했을 때 출력되는 정보가 차이가 있음

   → 위에서 작성한 RequestMain.jsp 파일을 [Run As] → [Run on Server]하면 아래와 같은 화면이 나타난다.

 

주요 기능 1) 클라이언트와 서버의 환경 정보 읽기

  • 클라이언트는 웹 브라우저를 통해 서버 측으로 요청을 함
    → 이때 요청은 GET 방식/POST 방식으로 구분되고, 요청 URL/포트 번호/쿼리스트링 등을 명시 가능
  • RequestMain.jsp 페이지에서 ‘GET 방식 전송’ 링크나 [POST 방식 전송] 버튼을 클릭했을 때 나타나는 페이지의 소스 (request 내장 객체로부터 클라이언트와 서버의 환경정보를 읽어와 화면에 표시해줌)
//RequestWebInfo.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head><title>내장 객체 - request</title></head>
<body>
    <h2>1. 클라이언트와 서버의 환경정보 읽기</h2>
    <ul>
        <li>데이터 전송 방식 : <%= request.getMethod() %></li>    //1.
        <li>URL : <%= request.getRequestURL() %></li>    //2.
        <li>URI : <%= request.getRequestURI() %></li>    //3.
        <li>프로토콜 : <%= request.getProtocol() %></li>
        <li>서버명 : <%= request.getServerName() %></li>
        <li>서버 포트 : <%= request.getServerPort() %></li>
        <li>클라이언트 IP 주소 : <%= request.getRemoteAddr() %></li>    //4.
        <li>쿼리스트링 : <%= request.getQueryString() %></li>    //5.
        <li>전송된 값 1 : <%= request.getParameter("eng") %></li>    //6-1.
        <li>전송된 값 2 : <%= request.getParameter("han") %></li>    //6-2.
    </ul>
</body>
</html>
  1. 여기의 getMethod() 메소드는 GET과 POST 같은 전송 방식을 반환함
    → ‘GET 방식 전송’ 링크를 클릭했다면 “GET”을, [POST 방식 전송] 버튼을 클릭했다면 “POST”를 반환
  2. 여기의 getRequestURL() 메소드는 요청 주소를 반환함. (URL은 호스트를 포함한 전체 주소를 뜻함)
  3. 여기의 getRequestURI() 메소드는 2.와 같이 요청 주소를 반환함.
    (URI는 호스트를 제외한 컨텍스트[호스트명 다음에 나오는 프로젝트명] 루트부터의 주소를 뜻함)
  4. 여기의 getRemoteAddr() 메소드는 클라이언트의 IP 주소를 반환함
    → localhost로 접속 시에는 0:0:0:0:0:0:0:1과 같이 출력됨
    (*윈도우 10에서는 위처럼 IPv6을 반환하는 게 기본인데, WAS 설정을 IPv4로 변경하면 localhost 접속 시 127.0.0.1을 출력함)
  5. 여기의 getQueryString() 메소드는 요청 주소 뒷부분의 매개변수를 전달하기 위한 쿼리스트링 전체를 반환함.
  6. 여기의 getParameter() 메소드는 요청 주소 뒷부분의 매개변수를 전달하기 위한 쿼리스트링 중 특정 키 값을 반환함 (이 메소드에 키 값을 인수로 넣어주면 됨)
  • RequestMain.jsp 실행화면 중 ‘1. 클라이언트와 서버의 환경정보 읽기’ 부분
    -> ‘GET 방식 전송’ 클릭 시 결과
         → 주소표시줄에 쿼리스트링으로 매개변수가 2개 전달되었고, 정상적으로 출력됨

      -> [POST 방식 전송] 버튼 클릭 시 결과
           → 주소표시줄에는 경로 외에 아무것도 표시되지 않음(=쿼리스트링 null 출력)

 

주요 기능 2) 클라이언트가 전송한 요청 매개변수에 대한 정보 읽기

  • RequestMain.jsp 실행화면 중 ‘2. 클라이언트의 요청 매개변수 읽기’ 부분
    → 값을 적당히 입력하고 [전송하기] 버튼 클릭 시 POST 방식으로 RequestParameter.jsp에 전송

//RequestParameter.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head><title>내장 객체 - request</title></head>
<body>
<%
request.setCharacterEncoding("UTF-8");  //1.
String id = request.getParameter("id");   //2. 
String sex = request.getParameter("sex");
String[] favo = request.getParameterValues("favo");  //3. 
String favoStr = "";
if (favo != null) {   //4.
    for (int i = 0; i < favo.length; i++) {
        favoStr += favo[i] + " ";
    }
}
String intro = request.getParameter("intro").replace("\\r\\n", "<br/>");  //5. 
%>
<ul>
    <li>아이디 : <%= id %></li>
    <li>성별 : <%= sex %></li>
    <li>관심사항 : <%= favoStr %></li>
    <li>자기소개 : <%= intro %></li>
</ul>
</body>
</html>
  1. UTF-8: 다국어 지원 인코딩
  2. 전송되는 값이 하나일 경우 getParameter() 메소드 사용 - 주로 type 속성이 text, radio, password인 경우 사용
  3. 전송되는 값이 여러 개여야 할 때 getParameterValues() 메소드 사용 - 주로 type 속성이 checkbox인 경우 사용
    (값이 2개 이상이므로 String 배열을 반환)
  4. for문을 이용해서 String 배열에 담긴 값들을 하나의 문자열로 합침
  5. textarea 태그에서는 택스트를 여러 줄 입력할 수 있는데,
    출력 시에는 enter 키를 <br> 태그로 변환해야 줄바꿈이 제대로 반영됨. enter는 특수 기호 \r\n으로 입력됨
  • 아무 값을 입력하고 [전송하기] 버튼을 클릭했을 때 결과

 

주요 기능 3) HTTP 요청 헤더 및 쿠키 정보 읽기

  • ReuestMain.jsp 실행 화면에서 ‘3. HTTP 요청 헤더 및 쿠키 정보 읽기’ 부분
    → ‘요청 헤더 정보 읽기’ 하이퍼링크 클릭 시 RequestHeader.jsp 코드가 실행되게 함

// RequestHeader.jsp

<%@ page import="java.util.Enumeration"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head><title>내장 객체 - request</title></head>
<body>
    <h2>3. 요청 헤더 정보 출력하기</h2>
    <%
    Enumeration headers = request.getHeaderNames();    //1.
    while (headers.hasMoreElements()) {    //2.
        String headerName = (String)headers.nextElement();    //3.  
        String headerValue = request.getHeader(headerName);    //4.
        out.print("헤더명 : " + headerName + ", 헤더값 : " + headerValue + "<br/>");
    }
    %>
    <p>이 파일을 직접 실행하면 referer 정보는 출력되지 않습니다.</p>
</body>
</html>
  1. 이 줄의 getHeaderNames() 메소드는 모든 요청 헤더의 이름을 반환(반환 타입은 Enumeration)
  2. 이 줄에서는 while문에서 hasMoreElements()를 이용해 출력할 요청 헤더명이 더 있는지 확인
  3. hasMoreElements()를 이용해 출력할 요청 헤더명이 더 있다면, 요청 헤더의 이름을 얻어옴
  4. getHeader() 메소드에 요청 헤더의 이름을 건네 헤더값을 얻어옴
  • ‘요청 헤더 정보 읽기’ 하이퍼링크 클릭 시 결과

 

*user-argent: 웹 브라우저의 종류를 나타냄. 크롬, 파이어폭스, 익스플로러 등 여러가지 웹 브라우저에서 테스트해보면 조금씩 다른 결과가 출력됨.

*referer: 웹을 서핑하면서 하이퍼링크 클릭을 통해 다른 사이트로 방문 시 남는 흔적. 웹 사이트 방문객이 어떤 경로로 접속했는지 알아볼 때 유용함

*cookie: 요청 헤더를 통해 확인 가능(4장 ‘쿠키’에서 자세히 알아볼 것)

 

*개발환경 변경함!! - 이클립스 2022-12, jdk 11, Apache Tomcat 9.0.7.0

2. response 객체

  • request 객체와는 반대로, 요청에 대한 응답을 웹 브라우저로 보내주는 객체
  • 아래 두 주요 기능 외에, 다른 기능들은 거의 사용하지 않음
  • 간단한 로그인 폼 제작 - 로직, 코드

//ResponseMain.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head><title>내장 객체 - response</title></head>
<body>
    <h2>1. 로그인 폼</h2>
    <% 
    String loginErr = request.getParameter("loginErr");    //1.
    if (loginErr != null) out.print("로그인 실패");    //2.
    %>
    <form action="./ResponseLogin.jsp" method="post">    //3.
        아이디 : <input type="text" name="user_id" /><br />
        패스워드 : <input type="text" name="user_pwd" /><br />
        <input type="submit" value="로그인" />
    </form>

    <h2>2. HTTP 응답 헤더 설정하기</h2>
    <form action="./ResponseHeader.jsp" method="get">    //4.
        날짜 형식 : <input type="text" name="add_date" value="2021-10-25 09:00" /><br />    //5.
        숫자 형식 : <input type="text" name="add_int" value="8282" /><br />
        문자 형식 : <input type="text" name="add_str" value="홍길동" /><br />
        <input type="submit" value="응답 헤더 설정 & 출력" />
    </form>
</body>
</html>
  1. loginErr는 로그인 실패 여부를 알려주는 매개변수 (로그인에 실패하면 매개변수에 값을 설정)
  2. 위의 매개변수에 설정한 값이 들어있다면 “로그인 실패” 출력
  3. 아이디와 패스워드를 입력받는 간단한 로그인 폼 구성
  4. 응답 헤더 추가를 위한 입력 폼 구성
  5. 응답 헤더에 추가할 데이터의 형식 별로, value 속성에 입력해 둠
    → 위에서 작성한 RequestMain.jsp 파일을 [Run As] → [Run on Server]하면 아래와 같은 화면이 나타난다.
         (빨간색 숫자는 주요기능 1,2번을 나타냄)

 

주요 기능 1) sendRedirect()로 페이지 이동

  • response 내장 객체의 sendRedirect()를 이용
//ResponseLogin.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head><title>내장 객체 - Response</title></head>
<body>
<%
String id = request.getParameter("user_id");    //1.
String pwd = request.getParameter("user_pwd");    //1. 
if (id.equalsIgnoreCase("must") && pwd.equalsIgnoreCase("1234")) {    //2.
    response.sendRedirect("ResponseWelcome.jsp");    //3.
}
else {
    request.getRequestDispatcher("ResponseMain.jsp?loginErr=1")    //4.
       .forward(request, response); 
}
%>
</body>
</html>
  1. request 내장 객체로 전송된 매개 변수를 얻어옴
  2. 회원 인증 진행-아이디 must, 비밀번호 1234
  3. 회원 인증에 성공하면 실행. sendRedirect() 메소드에 건넨 응답 페이지로 이동.
    (ResponseWelcome.jsp는 로그인 성공 페이지)
  4. 회원 인증에 실패하면,
    request 내장 객체를 통해 로그인 페이지(ResponseMain.jsp)로
    포워드(forward/전달, 제어 흐름을 넘겨주고자 할 때 사용)됨
    → 쿼리스트링으로 loginErr 매개변수 전달하여 로그인 성공 여부 알려줌

 

  • 로그인 성공 화면
//ResponseWelcome.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head><title>내장 객체 - response</title></head>
<body>
    <h2>로그인 성공</h2>
</body>
</html>

  • 로그인 실패 화면: 화면에는 ResponseMain.jsp의 내용이 출력되었지만,
                                 웹 브라우저의 주소표시줄에는 ResponasMain.jsp로 표시되어 있음
    → 로그인 실패 시 ResponseMain.jsp로 포워드하는데,
        이때 매개변수 loginErr이 전달되고 ‘로그인 실패’ 메시지가 출력됨

 

주요 기능 2) HTTP 헤더에 응답 헤더 추가하기

  • response 내장 객체는 응답 헤더에 정보를 추가하는 기능을 제공
  • 정보 추가 메소드: 헤더값을 새로 추가하는 add 계열과 기존의 헤더를 수정할 때 사용하는 set 계열이 있음
    → add 계열 메소드: 새로운 헤더명으로 값 추가 (동일한 헤더명이 있으면 동일한 이름으로 값 추가)
    → set 계열 메소드: 기존의 헤더값 수정(동일한 헤더명이 존재하지 않으면 새롭게 추가)
//ResponseHeader.jsp
<%@ 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");    //1.
long add_date = s.parse(request.getParameter("add_date")).getTime();    //1.
int add_int = Integer.parseInt(request.getParameter("add_int"));    //2.
String add_str = request.getParameter("add_str");

// 응답 헤더에 값 추가
response.addDateHeader("myBirthday", add_date);
response.addIntHeader("myNumber", add_int);
response.addIntHeader("myNumber", 1004); //3. 추가
response.addHeader("myName", add_str);
response.setHeader("myName", "안중근");  //4. 수정
%>
<html>
<head><title>내장 객체 - response</title></head>
<body>
    <h2>응답 헤더 정보 출력하기</h2>
		// 5.
    <%
    Collection<String> headerNames = response.getHeaderNames();
    for (String hName : headerNames) {
        String hValue = response.getHeader(hName);
    %>
        <li><%= hName %> : <%= hValue %></li>
    <%
    }   
    %>
    
    <h2>myNumber만 출력하기</h2>
		// 6.
    <%
	Collection<String> myNumber = response.getHeaders("myNumber");
	for (String myNum : myNumber) {
	%>
		<li>myNumber : <%= myNum %></li>
	<%
	}
	%>
</body>
</html>
  1. 0000-00-00(년-월-일) 형식으로 전송된 add_date 매개변수의 값을 long 타입으로 변경
    (변경된 값: 타임스탬프→1970년 1월 1일 0시 0분 0초부터 현재까지의 시간을 밀리초 단위로 환산한 값)
  2. 폼값으로 전송되는 값은 항상 String 타입이므로, add_int도 문자열로 얻어짐
    (*정수 형태로 사용 시 반드시 변환해야 함)
  3. add 계열의 메소드로 새로운 값 추가
    -바로 위에서 추가한 ‘myNumber’라는 동일한 헤더명으로 새로운 값을 추가하고 있는데,
      add 계열이므로 같은 헤더명으로 값이 하나 더 추가됨
  4. set 계열의 메소드로 값 수정-이전 값이 수정됨(같은 이름의 헤더가 없다면 새로 헤더가 추가됨)
  • 아래 화면에서 ‘응답 헤더 설정&출력’ 클릭

 

 

5. 부분 실행 결과

  • myNumber는 두 번 출력되며 그 값은 모두 8282로 동일함
    -> addHeader 메소드-같은 헤더명으로 값이 하나 더 추가됨
    -> getHeader() 메소드-값이 여러 개라도 첫 번째 값만 가져옴)

 

  • myName은 ‘안중근’이 출력됨(setHeader 메소드-입력값을 ‘안중근’으로 수정함)

 

6. 부분 실행 결과

반응형