수업내용/Spring

[2022.12.22.목] EL, JSTL

주니어주니 2022. 12. 29. 22:59

 

 

* 요청파라미터, 속성, 초기화파라미터 

 

 

1. EL (Expression Language)

 

  • 표현 언어다.
  • JSP 2.0부터 jsp에 포함된 기술이다
  • EL은 값을 표현할 때 사용되는 스크립트 언어다.
  • 기능
    • 요청파라미터값, 초기화파라미터값의 표현
    • PageContext, 요청객체, 세션객체, 애플리케이션객체의 속성값 표현
    • 요청헤더정보, 쿠키값의 표현
    • 사칙연산, 비교연산, 논리연산자, 기타 연산자 제공
    • 메소드 호출 기능 제공

 

1-1. EL의 내장객체 

 

name value  
요청 파라미터
param ${param.파라미터명}  요청파라미터값을 조회할 수 있다.
request.getParameter("파라미터명")와 동일하다.
paramValues ${paramValues.파라미터명}  요청파라미터값을 조회할 수 있다.
request.getParameterValues("파라미터명")와 동일한다.
속성
pageScope ${pageScope.속성명}  PageContext에 저장된 속성(값, 객체)을 조회한다.
requestScope ${requestScope.속성명}  HttpServletRequest에 저장된 속성을 조회한다.
sessionScope ${sessionScope.속성명}  HttpSession에 저장된 속성을 조회한다.
applicationScope ${applicationScope.속성명}  ServletContext에 저장된 속성을 조회한다.
초기화파라미터
initParam ${initParam.초기화파라미터명}  초기화파라미터값을 조회한다.
쿠키와 헤더정보
cookie ${header.요청헤더명}  요청헤더정보에서 헤더명에 해당하는 값을 조회한다.
header ${cookie.쿠키명}  쿠키명에 해당하는 쿠키값을 조회한다.
pageContext 객체
pageContext ${pageContext.getter메소드이름}  PageContext의 getXXX()메소드의 실행결과를 조회한다.
JSP의 기본객체를 제공받을 수 있다.

 

 

 

 

* 요청파라미터 안에 있는 값을 표현할 때는 param, paramValues 를 통함

 

* 속성 안에 있는 값을 표현할 때는 requestScope라고 안하고 바로 속성명을 적어도 됨

( 속성은 pageContext -> request -> session -> servletContext 순서로 찾기 때문 )  

( 값이 없다면 -> null 이 아닌 빈 문자열 출력 ) 

 

 

 

 

1-2. 연산자 

 

연산   연산자 사용사례
덧셈   + ${표현식 + 표현식}
뺄셈 - ${표현식 - 표현식}
곱셈 * ${표현식 * 표현식}
나눗셈 div ${표현식 div 표현식}
나머지 mod ${표현식 mod 표현식}
크다 gt ${표현식 gt 표현식}
크거나 같다 ge ${표현식 ge 표현식}
작다 lt ${표현식 lt 표현식}
작거나 같다 le ${표현식 le 표현식}
같다 eq ${표현식 eq 표현식}
같지않다 ne ${표현식 ne 표현식}
논리곱 and ${표현식 gt 10000 && 표현식 eq 'VIP'}
논리합 or ${표현식 gt 50000 && 표현식 eq 5}
논리부정 not ${not 표현식 eq 'VIP'}
삼항연산 ? : ${표현식 비교연산자 비교값 ? 값1 : 값2}
기타 empty ${empty 표현식} 혹은 ${not empty 표현식} 

 

  • empty 연산자가 true를 반환하는 경우
    • 값이 null인 경우
    • "" 빈문자열인 경우
    • 배열이나 콜렉션의 길이가 0인 경우
    • 비어있는 맵인 경우

 

 

* FrontController

package com.sample.model2;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import com.sample.controllers.HomeController;
import com.sample.controllers.ListController;
import com.sample.controllers.LoginFormController;
import com.sample.controllers.RegisterFormController;

import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

public class FrontController extends HttpServlet {

	private Map<String, Controller> controllerMap = new HashMap<>();
	
	/**
	 * 서블릿의 초기화 메소드다. <br/>
	 * 서블릿 객체가 생성되면 톰캣이 딱 한번 호출해서 서블릿을 초기화시킨다.
	 */
	@Override
	public void init(ServletConfig config) throws ServletException {
		controllerMap.put("/home.hta", new HomeController());					// "/home.hta"를 입력하면 homecontroller()실행
		controllerMap.put("/register-form.hta", new RegisterFormController());	// "/register-form.hta"을 입력하면 registerFormcontroller()실행
		controllerMap.put("/login-form.hta", new LoginFormController());		// "/login-form.hta"을 입력하면 loginformcontroller()실행
		controllerMap.put("/list.hta", new ListController());					// "/list.hta"을 입력하면 listcontroller()실행
	}
	
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("### FrontController의 service(request, response) 메소드 실행.");
		
		///////////////////////////////////////////////////////////////////////////
		// 요청 URI 분석하기
		///////////////////////////////////////////////////////////////////////////
		
		// Context Path(웹애플리케이션을 구분하는 고유한 경로다. 보통은 프로젝트명과 동일하다.) 조회하기
		String contextPath = request.getContextPath();		// 	/model2
		
		// 요청 URI 조회하기
		String requestURI = request.getRequestURI();
		requestURI = requestURI.replace(contextPath, "");	// 반복되는 /model2를 ""로 대체
		System.out.println("### 요청 URI: " + requestURI);	// /posts/detail.hta
		
		///////////////////////////////////////////////////////////////////////////
		// 요청 URI에 맞는 컨트롤러 실행하기
		///////////////////////////////////////////////////////////////////////////
		try {
			// HashMap객체에 저장된 Controller 인터페이스 구현객체 꺼내기 
			Controller controller = controllerMap.get(requestURI);
			// 조회된 컨트롤러 객체의 execute(request, response) 
			String viewName = controller.execute(request, response); 
			
			// 지정된 뷰페이지(viewName)으로 클라이언트의 요청을 이동시킨다. (=JSP를 실행시키는 것) 
			// 앞에 계속 붙는 "/WEB-INF/views/"를 아예 여기서 viewName 앞에 붙여줌
			viewName = "/WEB-INF/views/" + viewName;
			RequestDispatcher requestDispatcher = request.getRequestDispatcher(viewName);
			requestDispatcher.forward(request, response);
		} catch (Exception e) {
			throw new ServletException(e); 
		}
		
	}
}

 

* Controller 인터페이스

package com.sample.model2;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

/**
 * 모든 컨트롤러 구현 클래스가 구현할 추상메소드가 정의된 인터페이스다. <br />
 * 모든 컨트롤러 구현 클래스의 사용법을 통일시키기 위해서 정의된 인터페이스다. 
 * @author wnnns
 *
 */
public interface Controller {

	String execute(HttpServletRequest request, HttpServletResponse response) throws Exception;
	
}

 

* HomeController 구현객체

package com.sample.controllers;

import java.util.HashMap;
import java.util.Map;

import com.sample.model2.Controller;
import com.sample.vo.Product;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

public class HomeController implements Controller{
	
	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
		System.out.println("### HomeController의 execute(request, response) 실행");
		
		// 요청객체의 속성에 문자열 저장하기 
		request.setAttribute("message",	"안녕하세요");
		
		// 요청객체의 속성에 객체 저장하기
		Product product = new Product(100, "갤럭시폴더 4", "삼성전자", 2000000, 1750000, 3);
		request.setAttribute("bestGoods", product);
		
		// 요청객체의 속성에 배열 저장하기
		String[] keywords = {"크리스마스", "연말", "선물", "산타"};
		request.setAttribute("keywords", keywords);
		
		// 요청객체의 속성에 map 객체 저장하기
		Map<String, Object> map = new HashMap<>();
		map.put("name", "홍길동");
		map.put("kor", 100);
		map.put("eng", 80);
		map.put("math", 90);
		request.setAttribute("student", map);
		
		// 요청처리가 완료되면, 데이터를 표현할 뷰페이지 이름을 반환한다. 
		return "home.jsp";
	}

}

 

* home.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" >
<title>웹 애플리케이션</title>
</head>
<body>
<div class="container mb-3">
   <div class="row mb-3">
   		<div class="col-12">
   			<h1>홈</h1>
   		</div>
   </div>
   
   <div class="row mb-3">
   		<div class="col-12">
   			<a href="list.hta?page=1">1</a>
   			<a href="list.hta?page=2">2</a>
   			<a href="list.hta?page=3">3</a>
   			<a href="list.hta?page=4">4</a>
   		</div>
   </div>
   
   <div class="row mb-3">
   		<div class="col-12">
   			<p>${message }</p>
   		</div>
   </div>
   <div class="row mb-3">
   		<div class="col-12">
   			<p>
   				<span class="badge bg-secondary">${keywords[0] }</span>
   				<span class="badge bg-secondary">${keywords[1] }</span>
   				<span class="badge bg-secondary">${keywords[2] }</span>
   				<span class="badge bg-secondary">${keywords[3] }</span>
 			</p>
   		</div>
   </div>
   <div class="row mb-3">
   		<div class="col-12">
   			<table class="table">
   				<thead>
   					<tr>
   						<th>이름</th>
   						<th>국어점수</th>
   						<th>영어점수</th>
   						<th>수학점수</th>
   						<th>총점</th>
   						<th>평균점수</th>
   						<th>합격여부</th>
  					</tr>
  				</thead>
  				<tbody>
  					<td>${student.name }</td>
  					<td>${student.kor }</td>
  					<td>${student.eng }</td>
  					<td>${student.math }</td>
  					<td>${student.kor + student.eng + student.math }</td>
  					<td>${(student.kor + student.eng + student.math)/3 }</td>
  					<td>${(student.kor + student.eng + student.math)/3 >= 60 ? "합격" : "불합격" }</td>
  				</tbody>
   			</table>
   		</div>
   </div>
   <div class="row mb-3">
   		<div class="col-12">
   			<table class="table">
   				<colgroup>
   					<col width="15%">
   					<col width="35%">
   					<col width="15%">
   					<col width="35%">
   				</colgroup>
   				<tbody>
   					<tr>
   						<th>상품번호</th><td>${bestGoods.no }</td>
   						<th>재고수량</th><td>${bestGoods.stock }</td>
					</tr>
   					<tr>
   						<th>상품명</th><td>${bestGoods.name }</td>
   						<th>제조회사</th><td>${bestGoods.maker }</td>
					</tr>
   					<tr>
   						<th>가격</th><td>${bestGoods.price } 원</td>
   						<th>할인가격</th><td>${bestGoods.discountPrice } 원</td>
					</tr>
   				</tbody>
   			</table>
   		</div>
   		<div>
   			<a href="cart.hta?no=${bestGoods.no }" class="btn btn-primary btn-sm">장바구니 추가</a>
   			<a href="order.hta?no=${bestGoods.no }" class="btn btn-success btn-sm">바로구매</a>
   		</div>
   </div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
</body>
</html>

 

 

 

 

* ListController 

package com.sample.controllers;

import com.sample.model2.Controller;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

public class ListController implements Controller{

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
		System.out.println("### ListController의 execute(request, response) 실행");
		
		// 업무로직 메소드 호출해서 값 획득 
		
		// 획득된 값을 요청객체의 속성에 저장
		
		// 뷰페이지 이름 반환
		return "list.jsp";
	}
}

 

* list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" >
<title>웹 애플리케이션</title>
</head>
<body>
<div class="container">
	<div class="row mb-3">
		<div class="col-12">
			<h1>목록 페이지</h1>
		</div>
	</div>
	<div class="row mb-3">
		<div class="col-12">
			<p>게시글 목록을 확인하세요<span class="float-end">현재 페이지: <strong>${param.page }</strong></span></p>
		</div>
	</div>
	
	<div class="row mb-3">
      <div class="col-12 ">
         <form class="row row-cols-sm-auto g-3 align-items-center float-end" method="get" action="list.hta">
            <input type="hidden" name="page" value="${param.page }"/>
            <div class="col-12">
               <select class="form-select" name="opt">
                  <option value="title ${param.opt == 'title' ? 'selected' : '' }"> 제목</option>
                  <option value="writer ${param.opt eq 'writer' ? 'selected' : '' }"> 작성자</option>
                  <option value="content ${param.opt eq 'content' ? 'selected' : '' }"> 내용</option>
               </select>
            </div>
            <div class="col-12">
               <input type="text" class="form-control" name="keyword" value="${param.keyword }" />
            </div>
            <div class="col-12">
               <button type="submit" class="btn btn-primary">검색</button>
            </div>
         </form>
      </div>
   </div>
	
	<div class="row mb-3">
      <div class="col-12">
         <nav aria-label="Page navigation example">
            <ul class="pagination justify-content-center">
               <li class="page-item ${param.page <= 1 ? 'disabled' : '' }">
                  <a class="page-link" href="list.hta?page=${param.page - 1 }">이전</a>
               </li>
               <li class="page-item"><a class="page-link ${param.page eq 1 ? 'active' : '' }" href="list.hta?page=1">1</a></li>
               <li class="page-item"><a class="page-link ${param.page eq 2 ? 'active' : '' }" href="list.hta?page=2">2</a></li>
               <li class="page-item"><a class="page-link ${param.page eq 3 ? 'active' : '' }" href="list.hta?page=3">3</a></li>
               <li class="page-item"><a class="page-link ${param.page eq 4 ? 'active' : '' }" href="list.hta?page=4">4</a></li>
               <li class="page-item"><a class="page-link ${param.page eq 5 ? 'active' : '' }" href="list.hta?page=5">5</a></li>
                <li class="page-item ">
                  <a class="page-link" href="list.hta">다음</a>
               </li>
            </ul>
         </nav>
      </div>
   </div>
   
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
</body>
</html>

 

 

 

 

 


 

2. JSTL (JSP Standard Tag Library) 

 

  • JSP 표준태그 라이브러리
  • 스크립틀릿을 사용해서 작성했던 자바코드를 대체할 수 있다.
    • 변수 선언/삭제, 값 출력, 제어문 처리, 반복문 처리, 숫자나 날짜에 대한 포맷팅, 국제화처리, URL처리
  • 사용법
    • JSTL 파일을 다운받아서 WEB-INF/lib에 복사한다.
      (C:\app\apache-tomcat-10.0.27\webapps\examples\WEB-INF\lib) 
    • JSP 파일에 사용할 태그라이브러리를 지시어를 사용해서 정의한다.
        <%@ taglib prefix="별칭" uri="태그라이브러리식별자" %>
        <별칭:태그명 value="${EL표현식}" />

 

 

 

2-1. JSTL 태그라이브러리의 태그 종류 

 

  • core 태그
    • 가장 많이 사용되는 태그 라이브러디다.
    • 변수/출력/제어문/반복문/URL 처리를 지원한다.
    • JSP에 아래의 지시어를 정의한다.
      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

     

  • fmt 태그
    • 숫자나 날짜에 대한 포맷팅을 지원한다.
    • 국제화처리를 지원한다.
    • JSP에 아래의 지시어를 정의한다.
      <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

 

 

2-2. Core 태그 라이브러리 

 

  • <c:out> 태그
    • 값을 출력한다.
    • <%=값 %>, ${표현식} 과 동일한 작업을 수행한다.
    • XSS(Cross Site Scripting) 취약점 공격에 대한 가장 기본적인 방어을 지원한다.
      • XSS는 악의적인 사용자가 공격하려는 사이트에 스크립트를 넣어서 쿠키나 세션아이디와 같은 정보를 취득하는 것을 말한다.
      • 주로 공개된 게시판의 게시글에 html과 script 코드를 입력해서 해당 스크립트(나쁜)를 실행시키는 것이다.
      • 사이트 이용자가 작성하는 컨텐츠는 반드시 <c:out />태그를 사용해서 출력하자.
    • 사용법
      <c:out value="${표현식}" />
    • 주요 속성
      • value
        • 출력할 값을 지정한다.
        • 생략할 수 없음
          <c:out value="${book.title}" />
      • escapeXml
        • 특수문자(< > " ' &)를 변환할지 여부를 지정한다.
        • 기본값은 true다. -> excapeXml="false"로 설정하면 특수문자 적용
        • 생략가능
      • default
        • value에서 지정한 값이 null인 경우 표현할 값을 지정한다.
        • 생략가능

 

  • <c:if> 태그
    • if문과 동일한 역할을 수행한다.
    • else에 해당하는 태그는 없다.
    • 사용법
      <c:if test="${표현식}">
        HTML 컨텐츠
      </c:if>
      <!-- test에서 제시한 조건이 true면 HTML 컨텐츠가 화면에 출력된다. --->
    • 주요 속성
      • test
        • 검사조건을 정의한다.
        • 결과값이 boolean 타입이어야 한다.
        • 생략할 수 없다.

 

  • <c:choose> <c:when> <c:otherwise> 태그
    • if ~ else if ~ else if ~ else 와 동일한 역할을 수행한다.
    • 사용법
      <c:choose>
        <c:when test="${조건식1}">
          HTML 컨텐츠
          <!-- test에서 제시한 조건식1이 true면 HTML 컨텐츠가 화면에 출력된다. --->
        </c:when>
        <c:when test="${조건식2}">
          HTML 컨텐츠
          <!-- test에서 제시한 조건식2이 true면 HTML 컨텐츠가 화면에 출력된다. --->
        </c:when>
        <c:when test="${조건식3}">
          HTML 컨텐츠
          <!-- test에서 제시한 조건식3이 true면 HTML 컨텐츠가 화면에 출력된다. --->
        </c:when>
        <c:otherwise>
          HTML 컨텐츠
          <!-- test에서 제시한 조건식1, 조건식2, 조건식3이 전부 false면 HTML 컨텐츠가 화면에 출력된다. --->
        </c:otherwise>
      </c:choose>
    • <c:when>과 <c:otherwise>는 반드시 <c:choose>안에 위치해야 한다.
    • <c:when>은 조건식을 다르게 해서 여러 번 정의할 수 있다.
    • <c:otherwise>는 생략할 수 있고, 맨 마지막 <c:when> 다음에 정의해야 한다.
    • <c:when>으로 제시한 조건식이 true가 되면 남아있는 <c:when>은 검사하지 않는다.
    • <c:otherwise>는 <c:when>으로 제시한 조건이 모두 false로 판정될 때만 실행된다.

 

 

----------------------------------------------------------------예시---------------------------------------------------------------------------

 

* CoreController 

package com.sample.controllers;

import com.sample.model2.Controller;
import com.sample.vo.Product;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

public class CoreController implements Controller {

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception {
		
		request.setAttribute("content1", "안녕하세요");
		request.setAttribute("content2", "<button>버튼</button>");
		request.setAttribute("content3", "<script>alert('다 훔쳐갈거야!')</script>");
		
		request.setAttribute("score", 80);
		
		HttpSession session = request.getSession();
		session.setAttribute("LOGIN_USER_ID", "hong");	
		
		Product product = new Product(100, "맥북 프로", "애플", 2500000, 245000, 6);
		request.setAttribute("product", product);
		
		return "core.jsp";
	}
}

 

* core.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" >
<title>애플리케이션</title>
</head>
<body>
<div class="container">
   <div class="row mb-3">
   		<div class="col-12">
   			<h1>Core 태그 라이브러리</h1>
   		</div>
   </div>
   
   <div class="row mb-3">
   		<div class="col-12">
   			<h3>out 태그</h3>
   			<p>EL 표현식으로 값 표현: ${content1 }</p>
   			<p>EL 표현식으로 값 표현: ${content2 }</p>
   			<p>EL 표현식으로 값 표현: ${content3 }</p>
   			<p>out 태그로 값 표현: <c:out value="${content1 }" /></p>
   			<p>out 태그로 값 표현: <c:out value="${content2 }"/></p>
   			<p>out 태그로 값 표현: <c:out value="${content3 }"/></p>
   			<p>out 태그로 값 표현: <c:out value="${content3 }" escapeXml="false"/></p>
   		</div>
   </div>
   
   <div class="row mb-3">
   		<div class="col-12">
   			<h3>if 태그</h3>
   			
   			<p>점수에 따라서 합격여부 출력하기</p>
   			<c:if test="${score >= 60 }">
	   			<p>합격입니다.</p>
	   			<c:if test="${score >= 97 }">
	   				<p>장학금 지급대상입니다.</p>
	   			</c:if>
   			</c:if>
   			
   			<p>속성명을 조회한 값의 존재 여부로 콘텐츠 출력하기</p>
   			<c:if test="${empty LOGIN_USER_ID }">
   				<a href="loginform.hta">로그인</a>
   			</c:if>
   			<c:if test="${not empty LOGIN_USER_ID }">
   				<a href="logout.hta">로그아웃</a>
   			</c:if>
   			
   			<p>속성명으로 조회된 객체가 가지고 있는 값에 따라서 콘텐츠 출력하기</p>
   			<table class="table">
   				<thead>
   					<tr>
   						<th>상품명</th>
   						<th>할인가격 (가격)</th>
   						<th>재고량</th>
   						<th>비고</th>
  					</tr>
   				</thead>
   				<tbody>
   					<tr>
   						<td>${product.name }</td>
   						<td><strong>${product.discountPrice }원</strong> <small>(${product.price }원)</small></td>
   						<td>${product.stock }개</td>
   						<td>
   							<c:if test="${product.stock == 0 }">
	   							<a href="addAlarm.jsp?no=${product.no }" class="btn btn-secondary btn-sm">입고시 알림받기</a>
   							</c:if>
   							<c:if test="${product.stock > 0 && product.stock < 5 }">
	   							<a href="order.jsp?no=${product.no }" class="btn btn-danger btn-sm">매진임박 지금주문하세요!</a>
   							</c:if>
   							<c:if test="${product.stock >= 5 }">
	   							<a href="order.jsp?no=${product.no }" class="btn btn-primary btn-sm">주문하기</a>
   							</c:if>
						</td>
   					</tr>
   				</tbody>
   				<tbody>
   					<tr>
   						<td>${product.name }</td>
   						<td><strong>${product.discountPrice }원</strong> <small>(${product.price }원)</small></td>
   						<td>${product.stock }개</td>
   						<td>
   							<c:choose>
	   							<c:when test="${product.stock == 0 }">
		   							<a href="addAlarm.jsp?no=${product.no }" class="btn btn-secondary btn-sm">입고시 알림받기</a>
	   							</c:when>
	   							<c:when test="${product.stock < 5 }">
		   							<a href="order.jsp?no=${product.no }" class="btn btn-danger btn-sm">매진임박 지금주문하세요!</a>
	   							</c:when>
	   							<c:otherwise>
		   							<a href="order.jsp?no=${product.no }" class="btn btn-primary btn-sm">주문하기</a>
	   							</c:otherwise>
   							</c:choose>
						</td>
   					</tr>
   				</tbody>
   			</table>
   			
   		</div>
   </div>
   
   <div class="row mb-3">
   		<div class="col-12">
   			<h3>choose ~ when ~ otherwise 태그</h3>
   			
   			<p>성적에 따라서 등급 출력하기</p>
   			<c:choose>
   				<c:when test="${score >= 90 }">
   					<p>A 학점</p>
   				</c:when>
   				<c:when test="${score >= 80 }">
   					<p>B 학점</p>
   				</c:when>
   				<c:when test="${score >= 70 }">
   					<p>C 학점</p>
   				</c:when>
   				<c:when test="${score >= 60 }">
   					<p>D 학점</p>
   				</c:when>
   				<c:otherwise>
   					<p>F 학점</p>
   				</c:otherwise>
   			</c:choose>
   		</div>
   </div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
</body>
</html>

 

 

 

 

 

 

 


 

 

  • <c:forEach> 태그
    • for문과 같은 역할을 수행한다.
    • 배열 혹은 콜렉션(List, Set)에 대해서 그 항목의 갯수만큼 반복작업을 수행한다.
    • 사용법
      <c:forEach var="변수명" items="${표현식}">
        <p>${변수명}<p>
      </c:forEach>
    • items의 표현식으로 찾은 값이 반드시 배열 혹은 콜렉션이어야 한다.
    • 검색된 배열 혹은 콜렉션의 요소 갯수만큼 컨텐츠를 반복 출력한다.
    • var는 배열 혹은 콜렉션에서 처음부터 끝까지 반복수행시 저장되는 변수의 이름을 지정한다.

      <c:forEach var="변수명1" items="${표현식}" varStatus="변수명2">
        <p>${변수명2.count} ${변수명1}<p>
      </c:forEach>
    • varStatus에 지정된 변수에는 현재 반복상태정보를 담고 있는 객체가 전달된다.
    • 반복상태 정보
      • index : 현재 추출한 요소의 인덱스번호(0부터 시작)
      • count : 현재 반복횟수(1부터 시작)
      • first : 첫번째 요소인 경우 true
      • last : 마지막번째 요소인 경우 false

      <c:forEach var="변수명" begin="${표현식}" end="${표현식}" step="${증감치}>
        <a href="list.hta?pageno=${변수명}">${변수명}</a>
      </c:forEach>
    • begin은 시작값, end는 끝값을 지정한다.
    • begin과 end는 정수값이어야 한다.
    • begin, end의 구간만큼 컨텐츠를 반복출력한다.
    • var는 현재 숫자값을 저장하는 변수의 이름을 지정한다.
    • pagination 출력에 주로 사용 

 

 

 

------------------------------------------------------------예시----------------------------------------------------------------------

 

 

(1) 기본자료형/문자열이 여러 개 저장된 배열, List 출력하기

 

* controller 

    String[] names = {"홍길동", "김유신", "강감찬", "이순신"};
    List<String> menus = new ArrayList<>();
    menus.add("아메리카노");
    menus.add("바닐라 라떼");
    menus.add("카페 모카");
    menus.add("에스프레소");
    menus.add("카라멜 마키아또");

    request.setAttribute("names", names);
    request.setAttribute("menus", menus);

 

* jsp

    <p>기본자료형/문자열이 여러 개 저장된 배열 출력하기</p>
    <c:forEach var="name" items="${names }">
        <span class="badge bg-secondary">${name }</span>
    </c:forEach>

    <p>기본자료형/문자열이 여러 개 저장된 List 출력하기</p>
    <c:forEach var="menu" items="${menus }">
        <span class="badge bg-secondary">${menu }</span>
    </c:forEach>

 

 

 


 

 

 

(2) VO 객체가 여러개 저장된 List 출력하기 

 

* controller

    List<Category> categories = new ArrayList<>();
    categories.add(new Category(100, "국내도서"));
    categories.add(new Category(200, "외국도서"));
    categories.add(new Category(300, "전자책"));
    categories.add(new Category(400, "음반/CD"));

    request.setAttribute("categories", categories);

 

 

* jsp

    <p>VO 객체가 여러개 저장된 List 출력하기</p>
    <select name="catNo">
        <c:forEach var="cat" items="${categories }">
            <option value="${cat.no }"> ${cat.name }</option>
        </c:forEach>
    </select>

 

 

 

 

 

*controller

    List<Product> products = new ArrayList<>();
    products.add(new Product(100, "맥북 프로", "애플", 250, 245, 10));
    products.add(new Product(101, "맥북 에어", "애플", 250, 245, 10));
    products.add(new Product(102, "레노버 싱크패드", "레노버", 280, 245, 10));
    products.add(new Product(103, "아수스 게이밍 노트북", "아수스", 450, 445, 10));
    products.add(new Product(104, "LG 그램 울트라", "LG", 350, 345, 10));
    products.add(new Product(105, "맥프로", "애플", 650, 600, 10));

    request.setAttribute("products", products);

 

*jsp 

    <table class="table">
        <thead>
            <tr>
                <th>번호</th>
                <th>상품명</th>
                <th>제조사</th>
                <th>할인가격 (가격)</th>
                <th></th>
            </tr>
        </thead>
        <tbody>
        <c:forEach var="product" items="${products }">
            <tr>
                <td>${product.no }</td>
                <td>${product.name }</td>
                <td>${product.maker }</td>
                <td><strong class="text-danger">${product.discountPrice } 만원</strong> <small>(${product.price } 만원)</small></td>
                <td>
                    <a href="detail.hta?no=${product.no }">상세보기</a>
                    <a href="order.hta?no=${product.no }">바로구매</a>
                </td>
            </tr>
        </c:forEach>
        </tbody>
    </table>

 

 


 

 

 

(3) Map 객체를 여러개 저장하고 있는 리스트 출력하기

 

* controller

    List<Map<String, Object>> list = List.of(
            Map.of("no", 100, "title", "이것이 자바다", "price", 35000),
            Map.of("no", 200, "title", "자바의 정석", "price", 30000),
            Map.of("no", 300, "title", "혼자서 공부하는 자바", "price", 37000)
    );

    request.setAttribute("books", list);

 

* jsp 

    <p>Map객체를 여러 개 저장하고 있는 리스트 출력하기</p>
    <table class="table">
        <thead>
            <tr>
                <th>번호</th>
                <th>제목</th>
                <th>가격</th>
            </tr>
        </thead>
        <tbody>
            <c:choose>
                <c:when test="${empty books }">
                    <tr>
                        <td colspan="3" class="text-center">검색된 책이 없습니다.</td>
                    </tr>
                </c:when>
                <c:otherwise>
                    <c:forEach var="book" items="${books }">
                        <tr>
                            <td>${book.no }</td>
                            <td><a href="detail.hta?no=${book.no }">${book.title }</a></td>
                            <td>${book.price }</td>
                        </tr>
                    </c:forEach>
                </c:otherwise>
            </c:choose>
        </tbody>
    </table>

 

 

 


 

 

 

(4) foreach의 varStatus 활용하기

 

* controller

    List<Product> products = new ArrayList<>();
    products.add(new Product(100, "맥북 프로", "애플", 250, 245, 10));
    products.add(new Product(101, "맥북 에어", "애플", 250, 245, 10));
    products.add(new Product(102, "레노버 싱크패드", "레노버", 280, 245, 10));
    products.add(new Product(103, "아수스 게이밍 노트북", "아수스", 450, 445, 10));
    products.add(new Product(104, "LG 그램 울트라", "LG", 350, 345, 10));
    products.add(new Product(105, "맥프로", "애플", 650, 600, 10));
    products.add(new Product(100, "맥북 프로", "애플", 250, 245, 10));
    products.add(new Product(101, "맥북 에어", "애플", 250, 245, 10));
    products.add(new Product(102, "레노버 싱크패드", "레노버", 280, 245, 10));
    products.add(new Product(103, "아수스 게이밍 노트북", "아수스", 450, 445, 10));
    products.add(new Product(104, "LG 그램 울트라", "LG", 350, 345, 10));
    products.add(new Product(105, "맥프로", "애플", 650, 600, 10));

    request.setAttribute("products", products);

 

* jsp 

    <p>forEach의 varStatus 활용하기</p>
    <table class="table">
        <thead>
            <tr>
                <th>index</th>
                <th>count</th>
                <th>first</th>
                <th>last</th>
                <th>번호</th>
                <th>상품명</th>
                <th>가격</th>
            </tr>
        </thead>
        <tbody>
            <c:forEach var="product" items="${products }" varStatus="x">
                <tr class="${x.first ? 'table-success' : '' }">
                    <td>${x.index }</td>
                    <td>${x.count }</td>
                    <td>${x.first }</td>
                    <td>${x.last }</td>
                    <td>${product.no }</td>
                    <td>${product.name }</td>
                    <td>${product.price }</td>
            </c:forEach>
        </tbody>
    </table>

 

 

 


 

 

(5) 페이지네이션 

 

*jsp

    <p>페이지네이션 출력하기</p>
    <c:forEach var="number" begin="1" end="5">
        <a href="list.hta?page=${number }">${number }</a>
    </c:forEach>

 

 

 


 

 

 

 

  • <c:set> 태그
    • EL로 표현할 수 있는 값을 가진 변수를 선언한다.
    • 사용법
      <c:set var="변수명" value="${표현식}" />
      <c:set var="변수명" value="값" />
      <c:set var="변수명" value="<%=값 %>" />
    • var 지정된 이름으로 값이 저장된다.
    • ${변수명}으로 저장된 값을 표현할 수 있다.
    • scope는 값이 저장될 객체를 지정한다.
      <c:set var="a" value="길동" />
      <%-- pageContext.setAttribute("a", "길동"); --%>
      <p>${a}</p>
      
      <c:set var="b" value="길동" scope="page"/>
      <%-- pageContext.setAttribute("b", "길동"); --%>
      <p>${b}</p>
    
      <c:set var="c" value="유신" scope="request"/>
      <%-- request.setAttribute("c", "유신"); --%>
      <p>${c}</p>
    
      <c:set var="d" value="감찬" scope="session"/>
      <%-- session.setAttribute("d", "감찬"); --%>
      <p>${d}</p>
    
      <c:set var="e" value="순신" scope="application"/>
      <%-- application.setAttribute("e", "순신"); --%>
      <p>${e}</p>

 

- scope를 지정하지 않으면 PageContext (jsp 내부에서 사용하는 것들을 저장)에 저장 

 

 

* <%@include %> 지시어와 태그 사용의 차이점  (태그는 모델2에서 거의 사용 x)

<%@ include %>

navbar.jsp가 home.jsp에 하나의 자바 파일로 합쳐짐 

-> 같은 PageContext를 공유해서 사용 

 

 

 

------------------------------------------------------------예시----------------------------------------------------------------------

 

 

* header.jsp

 

 

* home.jsp

<%@ include 헤더%> 추가,

<%@ taglib %> 추가 -> <c:set /> 을 이용해서 PageContext 객체에 속성 추가

 

 

 

 

 

* core.jsp

 

 

 

 

 

 

* fmt.jsp

 

 


 

 

 

  • <c:remove> 태그
    • 지정된 이름의 값(객체)을 속성에서 삭제한다.
    • 사용법
      <c:remove var="변수명" /> 
      
      <c:remove var="a" />
      <%-- pageContext.removeAttribute("a"); --%>
      
      <c:remove var="b" scope="page"/>
      <%-- pageContext.removeAttribute("b"); --%>
      
      <c:remove var="c" scope="request"/>
      <%-- request.removeAttribute("c"); --%>
      
      <c:remove var="d" scope="session"/>
      <%-- session.removeAttribute("d"); --%>
      
      <c:remove var="e" scope="application" />
      <%-- application.removeAttribute("e"); --%>				

 

 

 


 

 

  • <c:url> 태그
    • url을 생성한다.
    • 사용법
      <c:url var="변수명" value="경로">
        <c:param name="이름1" value="값1" />
        <c:param name="이름2" value="값2" />
        <c:param name="이름3" value="값3" />
      </c:url>
    
      <a href="${변수명}">링크</a>
      <%-- <a href="경로?이름1=값1&이름2=값2&이름3=값3">링크</a> --%>

     

     

<div class="mb-3">
    <div class="col-12">
        <p>url 태그로 링크 생성하기</p>
        <c:url value="list.hta" var="link">
            <c:param name="page" value="2" />
            <c:param name="row" value="10" />
            <c:param name="sort" value="date" />
            <c:param name="direction" value="desc" />
        </c:url>
        <a href="${link }">링크</a>
    </div>
</div>

 

 

 

 

 

 


 

 

 

  • <c:import> 태그
    • 지정된 파일을 include한다.
    • 사용법
      <c:import url="포함시킬파일의 경로" />
    • url에는 프로젝트 내부 파일 및 외부파일(다른 웹서버의 파일) 포함 가능