Dev/JSP & Servlet

JSP 실행구조, 페이지 요청 라이프 사이클

창문닦이 2019. 2. 14. 10:40

Servlet (서블릿)

웹에서 사용하고 있는 프로토콜 http는 비연결형 프로토콜이며, 네트워크 전송 효율을 높이는 데는 도움을 줄 수 있다. 
하지만 CGI에 적용하여 다양한 서비스를 개발하는 데 걸림돌이 되고 있다. 서블릿은 이러한 문제점을 해결하고, 빠른 속도를 제공하고자 하는 취지에서 개발되었다. 

JSP 실행구조

 

 

Servlet을 이용한 HTML 응답처리는 코드로 HTML을 제어하는 구조로 코드와 디자인의 효율적인 협업이 어렵다.

JSP는 HTML과 코드를 분리하고 HTML을 중심으로 코드를 구성해서 특히 HTML을 응답하는데 효과적인 방법을 제공한다.

별도의 컴파일 과정을 직접 처리하지않고 요청시에 Servlet 클래스를 동적으로 생성하고 컴파일한후 실행하는 과정을 수행한다.

 

 

JSP 페이지 요청 라이프 사이클

 

① jspInit() : JSP에 대한 첫 요청이 올 경우 서블릿으로 변환된 후 jspInit() 메서드 호출, 서블릿의 초기화 및 서비스를 시작하기 위한 준비, _jspService() 메서드호출
② jspService()  : 클라이언트의 요청을 처리하는 메서드
③ jspDestroy() : 서블릿 객체가 메모리에서 제거 될 때 호출되는 메서드

 

 

페이지 구성요소( 지시문, 주석, HTML 및 정적 텍스트, 실행문)

① 지시문(Directive)
JSP 페이지가 처리될 때 필요한 정보를 표시
형식: <%@ 지시문이름=“값” 이름2=“값2” … %>
종류: page 지시문, include 지시문등

② HTML 주석
서버에서 처리되지만 브라우저에서 표시되지 않는 내용 포함
형식:  <!-- 주석내용 -->

③ 서버 주석
서버에서 처리되지 않는 내용으로 응답에 포함되지 않습니다.
형식: <%--주석내용--%>
<%@ page contentType="text/html; charset=euc-kr"%>
<%@ page import="java.util.*"%>
<%@ include file=“포함될파일이름” %>

④ HTML 및 정적 텍스트 
: 별도의 처리과정없이 있는 그대로 HTML 응답에 포함되는 내용

⑤ 실행문
스크립트릿 : 일반 실행문 포함
형식: <% 실행문 %>
표현식 : 값으로 출력할 내용을 포함
형식: <%= 값 또는 값을 반환하는 코드 %>
선언문 : 변수 또는 메서드 선언 영역
형식: <%! 변수 선언 또는 메서드 선언 %>

 

예제를 통한 JSP 구조 조회

1. JSP 페이지를 생성하여 저장버튼을 누르면 물리적인 파일이 저장된다. index.jsp를 생성해보자.

 

<%@page import="java.util.Calendar"%>
<%@ page contentType="text/html; charset=UTF-8"%><!-- 지시어 아무곳에 넣어도 된다 -->
<% String str = String.format("%tF", Calendar.getInstance());/* Calendar import 시켜줘야됨 */ %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%=str %>
<% out.write("여기는 서블릿"); %>
</body>
</html>


2. Project Explorer에 동기화  



3. 서버에 JSP 파일 업로드 
[경로] D:\java\work\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\st2spr 

4. .java 파일로 컴파일 되고 .class(기계어로 번역됨)서블릿 객체가 생성된다. 
- 클라이언트의 요청에 따라 웹 서버에서 해당되는 jsp를 검색하여 java로 변환 뒤 서블릿 객체 생성이 되어진 모습을 조회할 수 있다. 
[경로] D:\java\work\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\st2spr\org\apache\jsp

 

 

 

5. 클라이언트가 index.jsp에 접근하였을때 웹의 실행 화면이다. 

- 서블릿 객체

index_jsp.java 안에 out.write 값이 servlet 방식

[경로] D:\java\work\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\st2spr\org\apache\jsp

init()로 들어가서 실행이 된 후 service()를 호출한다. 정상적으로 로그아웃을 한다면 Destroy()를 거쳐 나간다. 바로 service() 메소드로 들어갈 수 있지만, 자바에서 들어오고 나간것을 인지하지 못한다. 웹사이트에서 로그인 후 로그아웃을 하지 않으면 캐시가 남아서 로그인 상태를 유지하는 것과 유사하다. 중간에 끊어지는 이유는 세션을 끊는 시간을 정해놨기 때문이다.

package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.util.Calendar;
public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
		implements org.apache.jasper.runtime.JspSourceDependent {
	private static final javax.servlet.jsp.JspFactory _jspxFactory =
			javax.servlet.jsp.JspFactory.getDefaultFactory();
	private static java.util.Map<java.lang.String, java.lang.Long> _jspx_dependants;
	private volatile javax.el.ExpressionFactory _el_expressionfactory;
	private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;
	public java.util.Map<java.lang.String, java.lang.Long> getDependants() {
		return _jspx_dependants;
	}
	public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
		if (_el_expressionfactory == null) {
			synchronized (this) {
				if (_el_expressionfactory == null) {
					_el_expressionfactory = _jspxFactory
						.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
				}
			}
		}
		return _el_expressionfactory;
	}
	public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
		if (_jsp_instancemanager == null) {
			synchronized (this) {
				if (_jsp_instancemanager == null) {
					_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory
						.getInstanceManager(getServletConfig());
				}
			}
		}
		return _jsp_instancemanager;
	}
	public void _jspInit() {
	}
	public void _jspDestroy() {
	}
	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("\r\n");
			out.write("\r\n");
			String str = String.format("%tF", Calendar.getInstance());/* Calendar import 시켜줘야됨 */
			out.write('\r');
			out.write('\n');
			request.setCharacterEncoding("UTF-8");
			String cp = request.getContextPath();
			out.write("\r\n");
			out.write(
				"<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n");
			out.write("<html>\r\n");
			out.write("<head>\r\n");
			out.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\r\n");
			out.write("<title>Insert title here</title>\r\n");
			out.write("</head>\r\n");
			out.write("<body>\r\n");
			out.print(str);
			out.write("\r\n");
			out.write("\r\n");
			out.write("여기는 서블릿");
			out.write("\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);
		}
	}
}