Servlet / JSP ) 11. JSP with Japser

60jong·2022년 6월 28일
0

Servlet / JSP

목록 보기
11/17

Server 공부 흐름

Servlet --[HTML코드 출력 문제]--> JSP --스파게티 코드 문제--> JSP MVC -> Spring MVC -> SpringBoot


JSP with Jasper

[Servlet / JSP ) 9. 동적 페이지의 필요성] 을 보면 동적 페이지 구현을 위해 java파일을 통해 html코드를 출력했다.

  • 하지만 html 코드가 길어지면 관리가 어렵고 실수가 생기기 마련이다.

따라서

문제점인 [HTML코드 출력 문제] 를 해결하기 위해 JSP, Japser를 활용하도록 한다.

Jasper는 JSP를 Servlet으로 컴파일해주는 Tomcat의 JSP엔진이다.


Jasper의 작동 원리

Jasper는

1. html 확장자가 아닌 jsp 확장자로 변환해주면 calculator.html > calculator.jsp


2. Japser는 jsp파일 내에 있는 코드를 모든 라인마다 out.println("~~~~~") 로 바꾸어서
calculator_jsp.java 파일 , 즉 calculator_jsp라는 Servlet을 만들어주게 되고 이 Servlet을 실행하게 된다.

2번에 집중해보자.

calculator.jsp

	<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Calc</title>
    <style>
        input{
            width: 50px;
            height: 50px;
        }
        .output{
            height: 50px;
            font-size: 24px;
            font-weight: bold;
            background: gray;
            text-align: right;
            padding-right: 5px;
        }
    </style>
</head>
<body>
<form action="calc" method="post">
    <table>
        <tr>
            <td class="output" colspan="4">${4+5}</td>
        </tr>
        <tr>
            <td><input type="submit" name="operator" value="CE"/></td>
            <td><input type="submit" name="operator" value="C"/></td>
            <td><input type="submit" name="operator" value=""/></td>
            <td><input type="submit" name="operator" value="÷"/></td>
        </tr>
        <tr>
            <td><input type="submit" name="value" value="7"/></td>
            <td><input type="submit" name="value" value="8"/></td>
            <td><input type="submit" name="value" value="9"/></td>
            <td><input type="submit" name="operator" value="×"/></td>
        </tr>
        <tr>
            <td><input type="submit" name="value" value="4"/></td>
            <td><input type="submit" name="value" value="5"/></td>
            <td><input type="submit" name="value" value="6"/></td>
            <td><input type="submit" name="operator" value=""/></td>
        </tr>
        <tr>
            <td><input type="submit" name="value" value="1"/></td>
            <td><input type="submit" name="value" value="2"/></td>
            <td><input type="submit" name="value" value="3"/></td>
            <td><input type="submit" name="operator" value=""/></td>
        </tr>
        <tr>
            <td><input type="submit" name="operator" value="±"/></td>
            <td><input type="submit" name="value" value="0"/></td>
            <td><input type="submit" name="dot" value="."/></td>
            <td><input type="submit" name="operator" value="="/></td>
        </tr>

    </table>

</form>
</body>
</html>

html과의 차이점은 중간에 ${4+5} 가 있는데 이것은 EL(Expression Languade)라고 한다. (뒤에서 설명)


이렇게 jsp 파일을 생성해주면

  • Jasper는 jsp파일을 한 줄씩 출력하는 Servlet을 만들어줌
  • 그렇게 생성된 Servlet은 한 줄씩 출력하며 html 파일을 생성해 클라이언트에게 응답한다.

실제로 C:\Users\s_rudwhd515\AppData\Local\JetBrains\IntelliJIdea2021.3\tomcat\01bd17f8-cf04-4e22-bb7d-ef88cfb18497\work\Catalina\localhost\ROOT\org\apache\jsp 해당 위치에

calculator_jsp.java가 생성된 것을 확인할 수 있다.

또한 해당 자바 파일 내에는

calculator_jsp.java

/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/9.0.63
 * Generated at: 2022-06-28 12:33:19 UTC
 * Note: The last modified time of this file was set to
 *       the last modified time of the source file after
 *       generation to assist with modification tracking.
 */
package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;

public final class calculator_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {

  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 static final java.util.Set<java.lang.String> _jspx_imports_packages;

  private static final java.util.Set<java.lang.String> _jspx_imports_classes;

  static {
    _jspx_imports_packages = new java.util.HashSet<>();
    _jspx_imports_packages.add("javax.servlet");
    _jspx_imports_packages.add("javax.servlet.http");
    _jspx_imports_packages.add("javax.servlet.jsp");
    _jspx_imports_classes = null;
  }

  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 java.util.Set<java.lang.String> getPackageImports() {
    return _jspx_imports_packages;
  }

  public java.util.Set<java.lang.String> getClassImports() {
    return _jspx_imports_classes;
  }

  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 {

    if (!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
      final java.lang.String _jspx_method = request.getMethod();
      if ("OPTIONS".equals(_jspx_method)) {
        response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
        return;
      }
      if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)) {
        response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
        response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP들은 오직 GET, POST 또는 HEAD 메소드만을 허용합니다. Jasper는 OPTIONS 메소드 또한 허용합니다.");
        return;
      }
    }

    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");
      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 lang=\"en\">\r\n");
      out.write("<head>\r\n");
      out.write("    <meta charset=\"UTF-8\">\r\n");
      out.write("    <title>Calc</title>\r\n");
      out.write("    <style>\r\n");
      out.write("        input{\r\n");
      out.write("            width: 50px;\r\n");
      out.write("            height: 50px;\r\n");
      out.write("        }\r\n");
      out.write("        .output{\r\n");
      out.write("            height: 50px;\r\n");
      out.write("            font-size: 24px;\r\n");
      out.write("            font-weight: bold;\r\n");
      out.write("            background: gray;\r\n");
      out.write("            text-align: right;\r\n");
      out.write("            padding-right: 5px;\r\n");
      out.write("        }\r\n");
      out.write("    </style>\r\n");
      out.write("</head>\r\n");
      out.write("<body>\r\n");
      out.write("<form action=\"calc\" method=\"post\">\r\n");
      out.write("    <table>\r\n");
      out.write("        <tr>\r\n");
      out.write("            <td class=\"output\" colspan=\"4\">");
      out.write((java.lang.String) org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate("${4+5}", java.lang.String.class, (javax.servlet.jsp.PageContext)_jspx_page_context, null));
      out.write("</td>\r\n");
      out.write("        </tr>\r\n");
      out.write("        <tr>\r\n");
      out.write("            <td><input type=\"submit\" name=\"operator\" value=\"CE\"/></td>\r\n");
      out.write("            <td><input type=\"submit\" name=\"operator\" value=\"C\"/></td>\r\n");
      out.write("            <td><input type=\"submit\" name=\"operator\" value=\"≪\"/></td>\r\n");
      out.write("            <td><input type=\"submit\" name=\"operator\" value=\"÷\"/></td>\r\n");
      out.write("        </tr>\r\n");
      out.write("        <tr>\r\n");
      out.write("            <td><input type=\"submit\" name=\"value\" value=\"7\"/></td>\r\n");
      out.write("            <td><input type=\"submit\" name=\"value\" value=\"8\"/></td>\r\n");
      out.write("            <td><input type=\"submit\" name=\"value\" value=\"9\"/></td>\r\n");
      out.write("            <td><input type=\"submit\" name=\"operator\" value=\"×\"/></td>\r\n");
      out.write("        </tr>\r\n");
      out.write("        <tr>\r\n");
      out.write("            <td><input type=\"submit\" name=\"value\" value=\"4\"/></td>\r\n");
      out.write("            <td><input type=\"submit\" name=\"value\" value=\"5\"/></td>\r\n");
      out.write("            <td><input type=\"submit\" name=\"value\" value=\"6\"/></td>\r\n");
      out.write("            <td><input type=\"submit\" name=\"operator\" value=\"-\"/></td>\r\n");
      out.write("        </tr>\r\n");
      out.write("        <tr>\r\n");
      out.write("            <td><input type=\"submit\" name=\"value\" value=\"1\"/></td>\r\n");
      out.write("            <td><input type=\"submit\" name=\"value\" value=\"2\"/></td>\r\n");
      out.write("            <td><input type=\"submit\" name=\"value\" value=\"3\"/></td>\r\n");
      out.write("            <td><input type=\"submit\" name=\"operator\" value=\"+\"/></td>\r\n");
      out.write("        </tr>\r\n");
      out.write("        <tr>\r\n");
      out.write("            <td><input type=\"submit\" name=\"operator\" value=\"±\"/></td>\r\n");
      out.write("            <td><input type=\"submit\" name=\"value\" value=\"0\"/></td>\r\n");
      out.write("            <td><input type=\"submit\" name=\"dot\" value=\".\"/></td>\r\n");
      out.write("            <td><input type=\"submit\" name=\"operator\" value=\"=\"/></td>\r\n");
      out.write("        </tr>\r\n");
      out.write("\r\n");
      out.write("    </table>\r\n");
      out.write("\r\n");
      out.write("</form>\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);
    }
  }
}

calculator.jsp를 한 줄씩 출력해주고 있음을 확인할 수 있다.


JSP의 코드 블럭과 EL(Expression Language)

JSP 코드 블럭의 종류

  • 출력 코드

JSP 코드 블록 <% %> 태그를 활용해 java파일로 출력을 전달할 수 있다.

<%
	out.write("Hello JSP~");
%>
  • 코드 블럭

JSP 코드 블록 <% %> 태그를 활용해 JSP 파일 내에 변수를 선언할 수 있다.

<%
	int x = 1;
    int y = 2;
%>
  • 변수 할당

JSP 코드 블록 <%= %> 태그를 활용해 JSP 파일 내에 변수를 선언할 수 있다.

y 값은 <% = y %>
  • 선언문

JSP 코드 블록 <%! %> 태그를 활용해 JSP 파일 내에 함수를 선언할 수 있다.

<%!
  public int sum(int a, int b) {
      return a+b;
  }
%>
  • Page 지시자

JSP 코드 블록 <%@ %> 태그를 활용해 JSP 파일의 페이지 설정을 할 수 있다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"
%>

jsp 파일 상단에 추가해주면,

calculator_jsp.java

	~~~
   out = pageContext.getOut();
      _jspx_out = out;


    int x = 1;
    int y = 2;

      out.write("\r\n");
      out.write("\r\n");
      out.write("<!DOCTYPE html>\r\n");
    ~~~

자바 코드로 추가가 됨을 확인할 수 있다.

EL(Expression Language)

JSP 컨테이너가 EL 표현식을 해석할 수 있게 도어 표준 액션 태그, 커스텀 태그, 템플릿 데이터와 같이 자바코드를 사용해야 했던 모든 곳에 EL을 사용하게 된다.

${...} 형식으로 적게 되고

  • EL 표현식
    ${true}
    ${false}
    ${123+123}
    ${3.14}
    ${"JAVA"}
    ${'java'}

  • EL 연산자
    산술연산자: +, -, *, /, %, mode
    논리연산자: &&, ||, !, and, or, not
    비교연산자: ==, !=, <, >, <=, >=, eq, ne, lt, get, le, ge
    empty연산자: 값이 null이거나 공백문자인지를 판단하는 연산자
    ${empty ""} → true
    ${empty null} → true

Request 객체 내

- 변수 -
<%= request.getAttribute("model"); %> --> ${model}

- 리스트 -
<%= ((List)request.getAttribute("list")).get(0); %> --> ${list[0]}

--
<%= ((Map)request.getAttribute("map")).get("title"); %> --> %{map.title}


map.title은 사실 map.getTitle()이다.
EL에서는 getter만 호출이 가능하기 때문에 get과 괄호를 때고 첫 글자는 소문자로 바꿔줌으로써 구현한다.

!! EL 표현식 안에서 연산이 가능함이 특징이다.


JSP 저장소

JSP또한 일반 Servlet처럼 상태 유지를 위한 저장소가 있는데

  • PageContext : JSP 페이지의 저장소
  • Request : 요청, request에 데이터들 담아 전달할 수 있다.
  • Session : Servlet처럼 사용자에 따라 Session으로 상태 유지를 할 수 있다.
  • Page : page 전체에 대한 정보를 담고 있는 page객체
  • Cookie : Servlet처럼 데이터가 브라우저에 저장되도록 할 수 있다.
profile
울릉도에 별장 짓고 싶다

0개의 댓글