포스트

Day73 Java프로그래밍 기초(JSP/EL)

JSP

1. JSP의 구조

  • JSP Engine을 이용하여 Servlet 구현체를 만드는 과정이다.
  • JSP의 구조는 다음과 같다.

image

2. JSP의 구동원리

  • JSP는 아래 순서와 같이 구동한다.
    1. 웹브라우저가 서블릿 컨테이너를 호출한다.
    2. 서블릿 컨테이너가 JSP의 서블릿 객체를 찾는다. 1) 서블릿 객체가 있으면 service() -> _jspService() 를 호출한다. 2) 서블릿 객체가 없으면, JSP파일로 .class 파일을 컴파일 후 호출한다.
    3. 웹브라우저에 결과를 리턴한다.
  • JSP 파일은 Python이나 PHP 처럼 직접 그 스크립트가 인터프리팅이 아니다.
  • JSP 파일을 분석해서 JSP Engine이 class파일을 생성하는 template 기술이다.
  • JSP 파일로 Servlet을 구현하기위해서는 HttpJspPage를 구현해야한다.

image

3. JSP의 구성요소

1) Template Data

  • JSP 파일에 작성된 텍스트는 자바 출력 코드를 생성한다.
  • JSP 코드

    1
    
      <h1>템플릿 데이터(template data)</h1>
    
  • Java.class

    1
    
      out.write("템플릿 데이터(template data)")
    

image

2) Scriptlet

  • JSP파일에 작성된 Scriptlet은 그대로 자바코드로 복사된다.
  • JSP 코드

    1
    
    <% int i = 5; %>
    
  • Java.class
    1
    
    int i = 5;
    

    image

3) Expression element

  • 표현식은 할당된 값을 리턴하는 문장을 말한다.
  • 결과 값을 출력하기위해서 사용되는 요소이다.
  • 문장 끝에 ; 을 사용하지 않는다.
  • 주로 객체의 값을 웹에 출력하거나 연산결과를 HTML에 삽입할 때 사용된다.

  • JSP 코드

    1
    2
    3
    4
    5
    
    <%
    String name="집에가고싶다"
    %>
      
    <%=name%>
    
  • Java.class

    1
    2
    
    String name = "집에가고싶다"
    out.write(name);
    

    image

4) Declaration element

  • 선언부는 클래스에 멤버를 추가할 때 사용한다.
  • jspInit()나 jspDestroy()와 같은 메서드를 오버라이딩 할 때도 사용할 수 있다.
  • 선언되는 위치에 상관없이 _jspService()전에 삽입된다.

  • JSP 코드

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
    <%!
    // 다음과 같이 상속 받은 메서드를 오버라이딩 할 수 있다.
    public void jspInit() {
      System.out.println("ex06.jsp의 jspInit()");
    }
    %>
    <body>
    <h1>선언부(declaration element)</h1>
      
        100,000,000 입금 = <%=calculate(100000000)%>
    </body>
    <%!
    double interest = 0.025; // 인스턴스 변수
      
    private String calculate(long money) { // 인스턴스 메서드 
      return String.format("%.2f", money + (money * interest));
    }
    %>
      
    <%!
        { // 인스턴스 블록
        System.out.println("ex06 인스턴스 생성!");
    }
    %>
    
  • Java.class

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    { // 인스턴스 블록
        System.out.println("ex06 인스턴스 생성!");
    }
      
    public void jspInit() {
      System.out.println("ex06.jsp의 jspInit()");
    }
      
    private String calculate(long money) { // 인스턴스 메서드 
      return String.format("%.2f", money + (money * interest));
    }
      
    double interest = 0.025; // 인스턴스 변수
      
    protected void _jspService(){
      out.write("<body>");
      out.write("<h1>선언부(declaration element)</h1>");
      out.write("100,000,000 입금 = "+ calculate(100000000)");
      out.write("</body>");
    }
    

    image

5) Page(Directive element)

  • 서블릿 실행과 관련하여 특정 기능을 설정한다.
  • language: JSP에서 사용할 언어를 지정 (기본값은 java).
  • contentType: 클라이언트로 전송될 응답의 MIME 타입과 문자 인코딩을 설정 (text/html; charset=UTF-8).
  • pageEncoding: JSP 파일 자체의 인코딩 방식 설정 (예: UTF-8).
  • import: JSP에서 사용할 자바 클래스를 임포트 (여러 클래스를 쉼표로 구분하여 한 번에 임포트 가능).
  • trimDirectiveWhitespaces: JSP 페이지에서 불필요한 공백을 제거할지 여부 설정 (true로 설정 시 공백 제거).
  • buffer: 클라이언트로 전송할 데이터를 임시로 저장할 버퍼 크기 설정 (예: 8kb).
  • autoFlush: 버퍼가 가득 찼을 때 자동으로 클라이언트로 데이터를 전송할지 여부 설정 (false로 설정 시 자동 전송 안 함).

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    <%@ page 
        language="java" 
        contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"
        import="java.net.Socket"
        import="java.net.ServerSocket"
        import="java.util.List,java.util.Map,java.util.Set"
        trimDirectiveWhitespaces="true"
        buffer="8kb"
        autoFlush="false"
    %>
    

    image

6) Include(Directive element)

  • 지정한 파일을 JSP로 포함시킨 후에 자바 서블릿 클래스를 생성한다.
  • 일반 텍스트 파일이면 된다. JSP 파일일 필요가 없다.
  • RequestDispatcher의 include()와 다르다.

    1
    
    <%@ include file="./ex08_header.txt"%>
    

    image

7) Tablib(Directive element)

  • 외부에 따로 정의된 JSP 확장 태그를 가져올 때 사용한다.
  • JSP 명세에 추가로 정의된 태그는 JSTL이라 한다.

image

8) action tage(Directive element)

  • JSP에서 기본으로 제공하는 JSP 전용 태그이다.

jsp:useBean

  • JSP에서 사용할 객체를 생성할 때 사용할 수 있다.
  • 보관소(ServletContext, HttpSession, ServletRequest, PageContext)에 저장된 객체를 꺼낼 때도 사용한다.
  • scope : 객체를 꺼내거나 생성된 객체를 저장할 보관소 이름, 기본이 page이다.
  • id : 객체를 꺼내거나 저장 할 때 사용할 이름이다.
  • class : 보관소에서 객체를 찾을 수 없을 때 생성할 객체의 클래스명이다.
  • type : 보관소에서 꺼낸 객체의 타입을 지정할 때 사용한다.

image image

jsp:setProperty

  • name: jsp:useBean에서 정의된 빈 객체의 id를 지정합니다. 이 빈 객체에 대해 속성을 설정한다.
  • property: 빈 객체의 속성 이름을 지정합니다. 이 속성에 값을 설정한다.
  • 특별한 값으로 *를 사용할 수 있는데, 이 경우 요청의 모든 매개변수를 자바빈의 동일한 이름을 가진 속성에 자동으로 매핑한다.
  • value: 속성에 설정할 을 직접 지정합니다. 이 값은 속성에 할당된다.

image

jsp:include

  • 다른 페이지로 실행을 위임한 후 그 실행 결과를 포함시킬 때 사용한다.
  • 실행이 끝난 후 제어권이 되돌아 온다.
  • page 속성에 지정하는 URL은 서블릿/JSP 이어야 한다. image

jsp:forward

  • 다른 페이지로 실행을 위임할 때 사용한다.
  • 제어권이 넘어가면 되돌아 오지 않는다.
  • page 속성에 지정하는 URL은 서블릿/JSP 이어야 한다.

9) errorPage

  • JSP를 실행하는 중에 오류가 발생했을 때 실행할 JSP를 지정할 수 있다.
  • <%@ page errorPage=”URL”%>

Expression Language 표기법

1. 용어정의

1) EL(Expression Language)

  • EL(Expression Language)은 콤마(.)와 대괄호([]) 등을 사용하여 객체의 프로퍼티나, 리스트, 셋, 맵 객체의 값을 꺼내고 설정하는 문법이다.
  • 단순화된 표현: JavaBean, Map, List, 배열 등의 데이터를 간단한 표현식으로 접근 가능하다.
  • 점 표기법(Dot Notation): 객체의 속성에 접근할 때 점(.)을 사용한다.
  • 대괄호 표기법(Bracket Notation): 배열이나 컬렉션의 특정 요소에 접근할 때 대괄호([]) 사용한다.
  • 기본 변수 접근: request, session, application 등의 범위 내에서 설정된 데이터에 간편하게 접근한다.

2) OGNL(Object Graph Navigation Language)의 정의

  • Java 언어에서 객체 그래프를 탐색하고 조작하기 위한 표현 언어다.
  • 객체의 프로퍼티 값을 가리킬 때 사용하는 문법이다.
  • 파일의 경로처럼 객체에 포함된 객체를 탐색하여 값을 쉽게 조회할 수 있다.

3) 객체 그래프(Object Graph)

  • 객체들 간에 관계를 나타내는 그래프 구조다.
  • 객체 그래프는 복잡한 데이터 구조를 표현하고 탐색하는 데 유용하며, 객체 간의 다양한 관계를 표현할 수 있다.
  • 객체 그래프를 사용하면 데이터를 계층적으로 구조화하고 관리할 수 있으며, 객체 간의 연결성을 효율적으로 관리할 수 있다.

EL 기본기능

1) 문법

1
2
${ 객체명.프로퍼티명.프로퍼티명.프로퍼티명 }
${ 객체명["프로퍼티명"]["프로퍼티명"]["프로퍼티명"] }


2) EL에서 사용할 수 있는 빌트인 객체

  • pageContext : JSP의 PageContext 객체
  • servletContext : ${ pageContext.servletContext.프로퍼티명 } => 자바코드 => pageContext.getServletContext().get프로퍼티()
  • session : ${ pageContext.session.프로퍼티명 } => pageContext.getSession().get프로퍼티명();
  • request: ${ pageContext.request.프로퍼티명 }
  • response : ${ pageContext.response.프로퍼티명 }
  • param : ${ param.파라미터명 } => request.getParameter(“파라미터명”);
  • paramValues : ${ paramValues.파라미터명 } => request.getParameterValues(“파라미터명”);
  • header : ${ header.헤더명 } => request.getHeader(“헤더명”);
  • headerValues : ${ headerValues.헤더명 } => request.getHeaders(“헤더명”);
  • cookie
    • ${ cookie.쿠키명 }
    • ${ cookie.쿠키명.name }
    • ${ cookie.쿠키명.value }
  • initParam : ${ initParam.파라미터명 }

보관소에서 값 꺼내기

  • 보관소명.프로퍼티명을 사용하여 보관소에서 값을 꺼낸다.
  • 보관소의 이름을 지정하지 않으면 다음 순서로 값을 찾는다.
    • pageScope ==> requestScope ==> sessionScope ==> applicationScope
  • 보관소에 저장된 값을 찾지 못하면 빈 문자열을 리턴한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    <h1>EL - 보관소에  꺼내기</h1>
    <%
    pageContext.setAttribute("name", "홍길동");
    request.setAttribute("name", "임꺽정");
    session.setAttribute("name", "유관순");
    application.setAttribute("name", "안중근");
    %>
      
    PageContext 보관소 : ${pageScope.name}<br>
    PageContext 보관소 : <%=pageContext.getAttribute("name")%><br>
      
    ServletRequest 보관소 : ${requestScope.name}<br>
    ServletRequest 보관소 : <%=request.getAttribute("name")%><br>
      
    HttpSession  보관소 : ${sessionScope.name}<br>
    HttpSession 보관소 : <%=session.getAttribute("name")%><br>
      
    ServletContext 보관소 : ${applicationScope.name}<br>
    ServletContext 보관소 : <%=application.getAttribute("name")%><br>
    
  • EL은 로컨 변수를 사용할 수 없다. 아래의 배열에서는 값을 꺼낼 수 없다.

    1
    
    String[] names = new String[]{"홍길동","임꺽정","유관순"};
    
  • EL은 오직 보관소에 저장된 값을 꺼낼 수 있다.

    1
    2
    3
    4
    5
    6
    7
    8
    
    <%
    pageContext.setAttribute("names", new String[]{"홍길동","임꺽정","유관순"});
    %>
      
    ${names[0]}<br>
    ${names[1]}<br>
    ${names[2]}<br>
    ${names[3]}<br>
    


EL 연산자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<h1>EL - 연산자</h1>

<h2>산술연산자</h2>
100 + 200 = ${100 + 200}<br>
100 - 200 = ${100 - 200}<br>
100 * 200 = ${100 * 200}<br>
100 / 200 = ${100 / 200}<br>
100 div 200 = ${100 div 200}<br>
100 % 200 = ${100 % 200}<br>
100 mod 200 = ${100 mod 200}<br>

<h2>논리연산자</h2>
true && false = ${true && false}<br>
true and false = ${true and false}<br>
true || false = ${true || false}<br>
true or false = ${true or false}<br>
!true = ${!true}<br> 
not true = ${not true}<br>

<h2>관계 연산자</h2>
100 == 200 = ${100 == 200}<br>
100 eq 200 = ${100 eq 200}<br>
100 != 200 = ${100 != 200}<br>
100 ne 200 = ${100 ne 200}<br>
100 > 200 = ${100 > 200}<br>
100 gt 200 = ${100 gt 200}<br>
100 >= 200 = ${100 >= 200}<br>
100 ge 200 = ${100 ge 200}<br>
100 &lt; 200 = ${100 < 200}<br>
100 lt 200 = ${100 lt 200}<br>
100 &lt;= 200 = ${100 <= 200}<br>
100 le 200 = ${100 le 200}<br>

<h2>empty</h2>
<p>보관소에 해당 객체가 없는지 검사한다. 없으면 true, 있으면 false.</p>
<%
pageContext.setAttribute("name", new String("홍길동"));
%>
name 값이 없는가? ${empty name}<br>
name2 값이 없는가? ${empty name2}<br>

<h2>조건 연산자 - 조건 ? 식1 : 식2 </h2>
name == "홍길동" : ${name == "홍길동" ? "맞다!" : "아니다!"}<br>

<%
String a = "홍길동";
String b = new String("홍길동");
if (a == b) { // 인스턴스의 주소를 비교!
    out.println("== : 같다!<br>");
} else {
    out.println("== : 다르다!<br>");
}

if (a.equals(b)) { // 인스턴스의 값을 비교!
    out.println("equals() : 같다!<br>");
} else {
    out.println("equals() : 다르다!<br>");
}
%>
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.