* 요청파라미터, 속성, 초기화파라미터
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표현식}" />
- JSTL 파일을 다운받아서 WEB-INF/lib에 복사한다.
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인 경우 표현할 값을 지정한다.
- 생략가능
- value
- <c:if> 태그
- if문과 동일한 역할을 수행한다.
- else에 해당하는 태그는 없다.
- 사용법
<c:if test="${표현식}"> HTML 컨텐츠 </c:if> <!-- test에서 제시한 조건이 true면 HTML 컨텐츠가 화면에 출력된다. --->
- 주요 속성
- test
- 검사조건을 정의한다.
- 결과값이 boolean 타입이어야 한다.
- 생략할 수 없다.
- test
- <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에는 프로젝트 내부 파일 및 외부파일(다른 웹서버의 파일) 포함 가능
'수업내용 > Spring' 카테고리의 다른 글
[2022.12.28.수] model2로 할 일(Todo) 실습 (0) | 2022.12.29 |
---|---|
[2022.12.27.화] model2로 댓글(comment) 실습 (0) | 2022.12.29 |
[2022.12.26.월] model2로 사용자(user), 게시물(post) 실습 (0) | 2022.12.29 |
[2022.12.23.금] EL, JSTL (2) (0) | 2022.12.29 |
[2022.12.21.수] 모델2(MVC 패턴) (0) | 2022.12.21 |