내부 객체(Implicit Object)
- 자바 클래스 또는 인터페이스의 형태로 JSP 컨테이너 내에 이미 인스턴스화 된 상태로 제공된다.
- JSP페이지 작성시 해당 객체를 이용해 동적으로 페이지를 작성할 수 있다.
- JSP Script, Directive, Action Tag등과 같은 JSP의 문법 요소들과 함께 동작해 사용자의 요청을 적절히 처리할 수 있다.
- 서블릿의 _jspService()메서드 안에서 선언되기 때문에 선언문(<%! ... %>)내에서는 사용할 수 없다.
내부 객체의 사용 범주에 따른 분류
- 입출력 관련 객체
- request, response, out
- 외부 환경 정보 제공 객체
- session. application, pageContext
- 서블릿 관련 객체
- page, config
- 예외 관련 객체
- exception
pageContext , request, session, application 객체
- 임의 속성 값(attribute)을 저장하고 읽을 수 있는 메서드를 제공한다.
- 속성 값을 저장하고 읽을 수 있는 기능은 JSP페이지간 또는 서블릿 간에 정보를 주고받을 수 있게 해준다.
입출력 관련 객체
- JSP페이지의 입출력과 관련한 내부 객체
- 클라이언트로부터 JSP 페이지의 호출에 의해서 전달되는 데이터의 요청과 응답 그리고 출력을 담당한다.
클래스 | 객체 | 설명 |
HttpServletRequest | request | 클라이언트에서 JSP페이지로 전달되는 데이터의 묶음 HTTP 헤더와 HTTP 바디로 구성되어 있다. JSP컨테이너는 요청된 HTTP 메서드와 해당 내부객체를 이용해 전달된 데이터를 사용할 수 있다. 여러가지 요청에 대한 정보를 제공하는 메서드를 제공하며, 폼 태그로부터 넘어오는 요청정보를 분석할 수 있는 기능또한 지원한다. 웹 브라우저와 웹 서버의 정보를 가져오기 위해 사용되기도 한다. |
HttpServletResponse | response | 요청을 시도한 클라이언트로 전송할 응답을 나타내는 데이터 묶음 |
JspWriter | out | JSP페이지의 결과를 클라이언트에게 전송해주는 출력 스트림 java.io.Writer 클래스를 상속받았다. 표현식 <%= %>는 서블릿 변환시 내부객체인 out.print()로 변환이 되어 실행되므로, 이 둘은 똑같은 역할을 한다. 단지 개발자의 편의성을 위해 내부객체를 표현식을 통해 사용할 수 있을 뿐이다. 버퍼를 사용하기 때문에 flush되기 이전에는 화면에 출력되지 않는다. 때문에 printWriter와 함께 사용시 오차가 발생할 수 있다. |
request 예제1
- form태그를 통해 request.jsp 페이지에 새 요청을 보낸다.
- 이때 form태그 내부에 name속성은 서버로 제출된 form data를 참조하기 위해 사용된다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Request Example1</h1>
<form action="request.jsp" method="post">
<div>이름 : <input type="text" name="name"></div>
<div>학번 : <input type="text" name="studentnum"></div>
<div>
<span>성별 : </span>
<label for="man">남자 : </label>
<input type="radio" name="gender" value="man" id="man">
<label for="woman">여자 : </label>
<input type="radio" name="gender" value="woman" id="man">
</div>
<div>
<span>전공 : </span>
<select name="major" multiple>
<option value="국문학과" selected>국문학과</option>
<option value="영문학과" selected>영문학과</option>
<option value="수학학과" selected>수학학과</option>
<option value="정치학과" selected>정치학과</option>
<option value="체육학과" selected>체육학과</option>
</select>
</div>
<input type="submit" value="보내기">
</form>
</body>
</html>
- form의 actaion속성으로 이동된 jsp페이지
- request의 setCharacterEncoding("Enctype") 메서드는 Form data전송시 HTTP POST 방식으로 데이터가 전송된경우, 해당 데이터의 인코딩 타입을 설정하기 위해 사용된다.
- request의 getParameter("name") 메서드를 사용해, 서버로 전송된 form data를 참조할 수 있으며, 이때 인자로 사용되는 name은 form data전송시 각 태그에 설정한 name태그와 동일하다.
- request의 getParameterValues("name") 메서드는 서버로 전송된 동일한 name을 갖는 form data를 배열형식으로 가져온다.
- request의 getParameterNames()는 해당 JSP로 넘어온 모든 데이터의 ''name"을 Enumeration객체로 반환한다.
<%@page import="java.util.Enumeration"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
request.setCharacterEncoding("UTF-8");
String name = request.getParameter("name");
String studentNum = request.getParameter("studentnum");
String gender = request.getParameter("gender");
String[] majors = request.getParameterValues("major");
Enumeration<String> names = request.getParameterNames();
String major = "";
if(gender != null && gender.equals("man")) gender = "남자";
else gender = "여자";
for(int i=0; i<majors.length; i++) {
major += majors[i];
if(i != majors.length-1) major += ", ";
}
%>
<h1>Request Example</h1>
<h2>getParameterNames()</h2>
<% while(names.hasMoreElements()) { %>
<div>
<% out.println(names.nextElement());%>
</div>
<% } %>
<hr>
<h2>getParameter('name'), getParameterValues('name')</h2>
<div>성명 : <%= name %></div>
<div>학번 : <%= studentNum %></div>
<div>성별 : <%= gender %></div>
<div>학과 : <%= major %></div>
</body>
</html>
결과
- 물른 request객체는 form태그만을 통해 페이지간 데이터를 주고받을 수 있는것은 아니다.
- JSP페이지에서는 forward의 특성을 이용해 데이터를 넘겨줄 수 있다.
- 데이터를 넘겨주기 위해 reqeust.setParameter('name', object)메서드를 사용할 수 있으며, 객체의 전송이가능하다.
request 예제2
- request객체는 서버로부터 넘어오는 요청정보를 가져오는 것 외에도 웹서버와 웹브라우저의 정보를 가져올 수 있다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String protocol = request.getProtocol();
String serverName = request.getServerName();
int serverPort = request.getServerPort();
String remoteAddr = request.getRemoteAddr();
String remoteHost = request.getRemoteHost();
String method = request.getMethod();
StringBuffer requestURL = request.getRequestURL();
String requestURI = request.getRequestURI();
String useBrowser = request.getHeader("User-Agent");
String fileName = request.getHeader("Accept");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Request Example</h1>
<div>protocol : <%= protocol %></div>
<div>serverName : <%= serverName%></div>
<div>serverPort : <%= serverPort%></div>
<div>사용자 컴퓨터의 주소 : <%= remoteAddr%></div>
<div>사용자 컴퓨터의 이름 : <%= remoteHost%></div>
<div>method : <%= method%></div>
<div>requestURL : <%= requestURL%></div>
<div>requestURI : <%= requestURI%></div>
<div>useBrowser : <%= useBrowser%></div>
<div>fileName : <%= fileName%></div>
</body>
</html>
결과
- 여기서 사용자 컴퓨터의 주소인 0:0:0:0:0:0:0:1 또는 :::1은 루프백 주소로써, 루프백 인터페이스를 식벽하는 데 사용되며, 노드가 자신에게 패킷을 보낼 수 있도록한다. 이 주소는 IPv4의 루프백 주소인 127.0.0.1과 같다.
- 루프백주소가 지정된 패킷은 링크에서 전송되거나 라우터에 의해 전달되면 안된다.
response 예제
- response1_1.jsp페이지에서 response1.jsp페이지로 redirect하는 예제이다.
- response객체의 sendRedirect("URL") 을통해 페이지간 redirect가 가능하다.
response1.jsp페이지
<h1>Response Example</h1>
<% response.sendRedirect("response1_1.jsp"); %>
response1_1.jsp 페이지
- Paragma : http 1.0
- Chache-Control : http 1.1
- Paragma와 Chache-Control은 같은 의미이나 사용되는 HTTP의 버전이 다르다.
- 브라우저나 프록시 서버로 하여금 요청 시에 cache된 문서 처리를 위한 헤더이다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
/* 브라우저가 캐시에 저장하여 사용하지 않고 매번 새로운 요청을 통해 서버로부터 전송받도록 설정됨 */
if(request.getProtocol().equals("HTTP/1.1")) response.setHeader("Cache-Control", "no-store");
else if(request.getProtocol().equals("HTTP/1.0")) response.setHeader("Pragma", "no-cache");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Response Example</h1>
<div>response1.jsp redirect response1_1.jsp</div>
<div><%= response.getCharacterEncoding() %></div>
</body>
</html>
결과
- redirect시 주목해야할점은 forward방식과 달리 클라이언트에서 전환을 담당하므로, URL이 변경되고 이전에 사용되던 객체가 재사용될 수 없다는 점이다.
- 또한 getCharacterEncoding() 메서드를 통해 요청에 사용된 Query 문장을 반환할 수 있으며
- setHeader(name, value), setcontentType(type)을 통해 응답 Header와 출력되는 페이지의 contentType을 설정하는 메서드 또한 지원한다.
out 예제
response.getWirter()의 출력스트림과 JspWriter 객체 out의 차이점
- response
- 내장객체인 response객체를 통해 서블릿 클래스 작성시 데이터를 출력하기 위한 PrintWirter를 얻을 수 있다.
- 버퍼를 사용하지 않는다.
- out
- JSP페이지가 servlet으로 변환될 때 표현식 <%= %>이 JspWriter의 객체인 out.print()로 변환된다.
- servlet에서 사용하는 PrintWirter객체와 사용목적은 같으나 버퍼를 사용한다.
- 버퍼의 사용유무로 인해 목적은 같으나, 동작방식에 차이가 발생하게된다.
- JspWriter와 PrintWriter를 동시에 사용하면, 클라이언트측에 두개의 스트림이 열리게되는데 버퍼를 사용하지 않은 PrintWriter는 곧바로 출력되고, 버퍼를 사용한 JspWirter는 flush가 되어야만 출력된다.
- 그렇기 때문에 PrintWirter의 출력 내용이 먼저 브라우저에 출력이 된후 JspWriter의 출력 내용이 출력된다.
<%@page import="java.io.PrintWriter"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" buffer="5kb" %>
<%
PrintWriter out2 = response.getWriter();
int totalBuffer = out.getBufferSize();
int remainBuffer = out.getRemaining();
int userBuffer = totalBuffer - remainBuffer;
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<div>현재 페이지의 Buffer 상태</div>
<div>출력 Buffer의 전체 크기 : <%= totalBuffer %></div>
<div>남은 Buffer의 크기 : <%= remainBuffer %></div>
<div>현재 Buffer의 사용량 : <%= userBuffer %></div>
<%
out2.println("for문 시작 전 <br>");
for(int i=1; i<=10; i++) {
if(i%2 == 0) out.println("짝수 = " + i + "<br>");
else out.println("짝수 = " + i + "<br>");
}
out2.println("for문 종료 후 <br>");
%>
</body>
</html>
결과
- JSP페이지가 Servlet으로 변환시 <%= %>표현식이 JspWriter의 내부객체인 out으로 변환되고, Servlet의 HTML표현을 위한 PrintWirter과는 달리 버퍼를 사용한다는것을 알리기위한 예제일뿐이므로, 이 둘을 같이 사용하지는 말자
외부 환경 정보 제공 객체
- 현재 실행되는 페이지의 외부 환경정보(Context)와 관련된 내부 객체
클래스 | 객체 | 설명 |
PageContext | pageContext | 현재 실행중인 JSP의 Context를 나타낸다. 해당 객체를 통해 다른 내부 객체에 접근이 가능하다. |
HttpSession | session | 웹 브라우저에서 서버가 클라이언트의 정보를 저장하고 요청을 시도한 특정 클라이언트를 다른 클라이언트와 구별하기 위해 각각의 클라이언트에 대한 정보를 지속적으로 관리하는 객체이다. page지시자의 session속성을 통해 세션의 사용유무를 결정할 수 있다. |
ServletContext | application | 어플리케이션이 실행되는 서버의 정보와 서버 측 자원에 대한 정보를 얻어내거나 어플리케이션이 실행하고 있는 동안에 발생할 수 있는 이벤트 로그와 관련된 기능들을 제공한다. |
Context
- 사전적 의미로 '문맥', '전후관계'를 의미한다.
- 웹 환경에서의 Context는 서로 독립된 영역에 존재하는 온전한 하나의 어플리케이션 영역의 정보를 지칭한다.
- 사용자가 URL을 통해 웹 어플리케이션에 접근시 서버내의 웹 어플리케이션을 구분하기 위해 server.xml 파일에 각 웹 어플리케이션의 <Context>태그를 추가하여 웹 컨테이너 내에 어떤 웹 어플리케이션이 사용되는지를 알 수 있다.
- 클라이언트 -> Request(URL) -> Container(server.xml의 context 확인) -> Context에 해당하는 웹 어플리케이션 접근 -> Request에 해당하는 웹 어플리케이션 폴더 내 자원 반환
pageContext 예제
- getRequest(), getResponse(), getOut()등의 메서드를 통해 ServletRequest, ServletResponse, JspWirter같은 해당 JSP페이지의 내장객체에 대한 정보를 모두 얻어올 수 있다.
- 때문에 직접 사용할 경우는 적지만, JSP가 Servlet으로 변환시 _jspService()메서드에서 pageContext의 메서드 호출을 통해 해당 JSP의 Context를 얻어와 내부적으로 변환한다는것을 알면된다.
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
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;
try {
response.setContentType("text/html; charset=UTF-8");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write("<!DOCTYPE html>\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write("<meta charset=\"UTF-8\">\r\n");
out.write("<title>Scriptlet Example</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
out.write("</body>\r\n");
out.write("</html>");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
session 예제
- session은 HTML의 무상태성, 무연결성의 문제점을 해결하기 위해 만들어졌다.
- session은 서버의 메모리에 클라이언트의 session id와 session정보를 저장한 뒤, 클라이언트에게 session id를넘겨 저장시키고 이후 요청에 매번 session id의 비교를 통해 해당 클라이언트에 저장된 상태정보로 동적페이지를 제공함으로써 마치 연결된것과 같이 사용할 수 있게된다.
- session의 정보는 브라우저의 종료시 또는 유효시간동안 유효하다.
session.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="session.jsp" method="POST">
<div>id : <input type="text" name="id"></div>
<div>pw : <input type="password" name="pw"></div>
<input type="submit" value="login">
</form>
</body>
</html>
session.jsp
- form을통해 전송된 id를 session에 등록하고, session의 연결시간을 설정
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" session="true" %>
<%
request.setCharacterEncoding("UTF-8");
String id = request.getParameter("id");
String pw = request.getParameter("pw");
session.setAttribute("idKey", id);
session.setMaxInactiveInterval(60*5); //id를 idkey로 세션에 연결을 설정하고, 연결시간을 5분으로 설정하였다. 5분이 지나가면 해당 정보는 사라진다.
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="session2.jsp" method="get">
<div>
<h1>좋아하는 계절</h1>
<label for="spring">봄</label>
<input type="radio" name="season" value="봄" id="spring">
<label for="summer">여름</label>
<input type="radio" name="season" value="여름" id="summer">
<label for="fall">가을</label>
<input type="radio" name="season" value="가을" id="fall">
<label for="winter">겨울</label>
<input type="radio" name="season" value="겨울" id="winter">
</div>
<input type="submit" value="전송">
</form>
</body>
</html>
session2.jsp
- 이후 session에 등록된 정보는 클라이언트가 웹 애플리케이션에 요청하는 모든 웹 페이지 내에서 사용이 가능하다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" session="true" %>
<%
request.setCharacterEncoding("UTF-8");
String id = (String)session.getAttribute("idKey");
String sessionId = session.getId();
int intervalTime = session.getMaxInactiveInterval();
//session.invalidate(); //모든 세션정보 삭제
String season = request.getParameter("season");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<% if(id != null) { %>
<h1>Session Example</h1>
<div>id : <%= id %></div>
<div>sessionId : <%= sessionId %></div>
<div>intervalTime : <%= intervalTime %></div>
<% } %>
</body>
</html>
결과
- 이때 sessionId는 브라우저의 구분을 위해 서버측에서 발급하는 일련번호이며, 서버와 클라이언트 양측에서 저장하고, 매 요청시마다 session id의 비교를 통해 어떤 클라이언트가 요청을했는지 식별이 가능해진다.
application 예제
- 어플리케이션이 실행되는 서버의 정보와 서버 측 자원에 대한 정보를 얻어내거나 어플리케이션이 실행하고 있는 동안에 발생할 수 있는 이벤트 로그와 관련된 기능들을 제공한다.
- getServerInfo(), getMimeType(), getRealPath() 등을 통해 해당 서버의 정보와 해당 웹 애플리케이션의 실제 저장경로를 얻을 수 있다.
- 물론 application또한 setAttribute('name', 'object')메서드를 통해 서버에 데이터를 저장할 수 있으나, session과는 달리 해당 웹 애플리케이션의 모든 클라이언트가 공유하며, 웹 애플리케이션이 종료되기 이전까지 메모리를 차지한다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String serverInfo = application.getServerInfo();
String mimeType = application.getMimeType("request.html");
String realPath = application.getRealPath("/");
application.log("application 내부 객체 로그 테스트");
//pageContext.forward();
//response.sendRedirect();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>application test</h1>
<div>서블릿 컨테이너의 이름과 버전 : <%= serverInfo %></div>
<div>request.html의 Mime Type : <%= mimeType %></div>
<div>로컬 파일 시스템 경로 : <%= realPath %></div>
</body>
</html>
결과
서블릿 관련 객체
- JSP 페이지가 변환된 서블릿과 관련된 내용에 접근할 수 있도록 하는 객체
- 이 둘은 잘 사용되지 않으므로 따로 다루지는 않았다.
클래스 | 객체 | 설명 |
HttpJspPage | page | JSP페이지 그 자체를 나타내는 객체이기 때문에 JSP페이지 내에서 this키워드로 자기 자신의 참조가 가능하다. JSP페이지가 Servlet으로 변환된 그 자체를 의미한다. 대부분의 JSP컨테이너는 Java만을 스크립트 언어로 지원하기 때문에 거의 사용되지 않는다. |
ServletConfig | config | Servlet에게 Servlet을 초기화하는 동안 참조해 할 정보를 전달하는 역할을 한다. |
예외 관련 객체
클래스 | 객체 | 설명 |
Exception | exception | JSP페이지에서 발생한 예외를 처리하는 페이지를 지정한 경우, 에러 페이지에 전달되는 예외 객체이다. page지시자의 isErrorPage속성을 true로 지정한 JSP페이지 내에서만 사용이 가능하다. 일반적인 JSP페이지에서는 생성되지 않는다. |
exception 예제
- page지시자의 errorPage속성에 에러발생시 이동할 page를 지정한다.
- 에러처리를 담당할 jsp페이지의 page지시자에 isErrorPage속성을 true로 설정하여 container에게 해당 페이지가 에러페이지임을 알린다.
- 이후 스크립트릿영역에서 0으로 나누어 강제로 예외를 발생시켰다.
- 예외 발생페이지로 이동하는 방식은 forward방식이다.
excpetion.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" errorPage="exceptionPage.jsp"%>
<%
int one = 1;
int zero = 0;
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>exception occurred</title>
</head>
<body>
<div>1 division zero : <%= one/zero %></div>
</body>
</html>
exceptionPage.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isErrorPage="true"%>
<%
String message = exception.getMessage();
String objectMessage = exception.toString();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Error page</title>
</head>
<body>
<h1>Exception Page</h1>
<div>에러 메시지 : <%= message %></div>
<div>에러 실체의 클래시명과 에러 메시지 : <%= objectMessage %></div>
</body>
</html>
결과
- forwarding 방식으로 에러페이지로 이동하기 때문에 URL의 변화가 없다.
'JSP' 카테고리의 다른 글
[WEB] HTTP 프로토콜에서 상태를 지속시키기 위한 방법들 (1) | 2023.03.15 |
---|---|
[JSP] Java Beans와 JSP 빈즈태그 (0) | 2023.03.15 |
[JSP]JSP의 지시자와 액션태그 (0) | 2023.03.15 |
[JSP]JSP의 스크립트 요소 (0) | 2023.03.14 |
[JSP]Model1, Model2 (0) | 2023.03.14 |