JSP 버전이 상향되면서 추가된 스크립트 언어로 기존 Scriptlet tag의 표현식 ( <%= %> ) 의 업그레이드 된 버전 ( ${ } )이다.
JSP 속성영역 (request, session, application(ServletContext)) 에 저장된 객체의 property 를 출력하는 용도로 사용된다.
EL을 이용하면 별도의 import , Object Casting 절차 필요없이 바로 출력이 가능 , 다양한 연산 및 자동 형변환이 된다.
JSTL 과 연동이 가능
EL은 Model 객체의 get계열 메서드와 is계열의 메서드에만 접근 가능하다.
View(jsp) 에서 자주 사용하는 기능(조건문 , 반복문, 자료구조의 데이터 표현)을 미리 구현해 놓은 태그로 라이브러리로 EL과 함께 사용해서 View 로직과 데이터를 표현한다.
환경설정 : WEB-INF\lib\jstl-1.2.jar 파일을 위치시킨다
다운로드 경로 : https://mvnrepository.com/artifact/javax.servlet/jstl/1.2
JSP 내에서 기본적으로 제공하는 객체로 생성이나 참조 코드 없이 바로 사용할 수 있고 JSP 가 Servlet으로 변환될 때 container가 작성한다.
• request : HttpServletRequest
• response : HttpServletResponse
• out : JspWriter - Servlet에서 PrintWriter 와 같은 역할
• session - HttpSession
• application - ServletContext
• config - ServletConfig
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>EL과 JSTL</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<div class="container pt-3">
<h5>View : EL과 JSTP</h5>
jsp 내장 객체<br>
request : <%=request %><br>
session : <%=session %><br>
ServletContext type의 application <%=application %><br><br>
</div>
</body>
</html>
index.jsp
<a href="Test1Servlet">EL Test1</a>
EL Test1 글씨를 누르면 Servlet으로 이동할 수 있도록 한다.
Test1Servlet
package org.kosta.webstudy16.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.kosta.webstudy16.model.MemberVO;
/**
* Servlet implementation class Test1Servlet
*/
@WebServlet("/Test1Servlet")
public class Test1Servlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
MemberVO memberVO = new MemberVO("java", "a", "아이유", "오리");
request.setAttribute("member",memberVO);
request.getRequestDispatcher("step1-el.jsp").forward(request, response);
}
}
member라는 atrribute name으로 memberVO를 attribute value를 setAttribute하였다.
step1-el.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>step1-el</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<div class="container pt-3">
<%-- request영역에 member로 넣었기때문에 가능 --%>
<%--
EL을 사용하면 import와 object casting 절차가 필요없어 바로 표현 가능
scope를 명시하지않으면 request -> session -> application순으로 정보를 표현한다.
--%>
request 객체에 저장된 회원 정보 :
회원아이디 ${member.id}
회원명 ${member.name}
주소 ${member.address}
<hr>
</div>
</body>
</html>
같은 내용의 정보를 session에도 저장할 수 있다.
Test1Servlet
MemberVO memberVO2 = new MemberVO("java2", "b", "박보검", "육리");
HttpSession session = request.getSession();
session.setAttribute("member", memberVO2);
request.getRequestDispatcher("step1-el.jsp").forward(request, response);
고의적으로 attribute name을 중복하도록 했다.
step1-el.jsp
<body>
<div class="container pt-3">
<%-- request영역에 member로 넣었기때문에 가능 --%>
<%--
EL을 사용하면 import와 object casting 절차가 필요없어 바로 표현 가능
scope를 명시하지않으면 request -> session -> application순으로 정보를 표현한다.
--%>
request 객체에 저장된 회원 정보 :
회원아이디 ${member.id}
회원명 ${member.name}
주소 ${member.address}
<hr>
session 객채에 저장된 회원 정보 :
회원아이디 ${member.id}
회원명 ${member.name}
주소 ${member.address}
</div>
</body>
scope를 명시하지않으면 request -> session -> application 순으로 정보를 표현한다.
index.jsp
<%-- client에서 전달한 query string 정보를 EL로 표현 --%>
<a href="Test2Servlet?nick=아바타스타&age=10">EL Test2</a><br><br>
EL Test2를 누르면 정해진 링크로 갈 수 있도록 한다.
Servlet
@WebServlet("/Test2Servlet")
public class Test2Servlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("menu",new FoodVO("돈까스", 8000));
request.getRequestDispatcher("step2-el-param.jsp").forward(request, response);
}
}
FoodVO 객체를 생성해 value에 넣어 menu라는 name으로 setAttribute한다.
<div class="container pt-3">
메뉴 이름 : ${menu.name} <br>
메뉴 가격 : ${menu.price}
</div>
<%=request.getParameter("nick") %> -> 기존방식으로, servlet에서 설정해준 setAttribute name으로 접근해 실제로는 getName() 메소드와 getPrice() 메소드를 실행해 화면해 출력한 것이다.
EL을 사용하면 client가 전달한 parameter에 대한 별도의 형변환이 필요없이 연산이 가능하다.
<%--클라이언트가 보낸 닉네임 파라미터--%>
${param.nick} ${param.age +2}
EL은 Model 객체의 get계열 메서드와 is계열의 메서드에만 접근 가능하다.
FoodVO
package org.kosta.webstudy16.model;
public class FoodVO {
private String name;
private int price;
public FoodVO(String name, int price) {
super();
this.name = name;
this.price = price;
}
public FoodVO() {
super();
}
public String getName() {
System.out.println("getName()");
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
System.out.println("getPrice()");
return price;
}
public void setPrice(int price) {
this.price = price;
}
public boolean isFlag() { //el은 get과 is계열 메소드만 접근 가능
System.out.println("isFlag");
return true;
}
public void testFlag() {
System.out.println("testFlag");
}
@Override
public String toString() {
return "FoodVO [name=" + name + ", price=" + price + "]";
}
}
FoodVO에 "getName()"과 "getPrice()"를 출력하고, isFlag() 메소드와 testFlag() 메소드를 추가했다.
Test4Servlet
@WebServlet("/Test4Servlet")
public class Test4Servlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("food",new FoodVO("돈까스", 8000));
request.getRequestDispatcher("step4-el-model.jsp").forward(request, response);
}
}
step4-el-model.jsp
<div class="container pt-3">
아이디 : ${param.id}<br>
음식명 : ${food.name}
가격 ${food.price}
<%-- isFlag 메소드에 접근해본다 --%>
${requestScope.food.flag} <%--is생략 --%>
<%-- testFlag 메소드는 접근 불가 --%>
<%--get메소드, is메소드만 있으면 인스턴스 변수에 접근가능 --%>
<%-- ${requestScope.food.testFlag}--%>
</div>
실행 화면과 콘솔에 출력된 내용이다.
실제로 EL을 작성하고 object에 접근해 getName() getPrice() 메소드를 실행해 그 정보를 화면에 보여준 것을 할 수 있다.
index.jsp
<a href="Test5Servlet?nick=아이유&age=33">JSTL if test</a><br><br>
Test5Servlet
package org.kosta.webstudy16.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class Test5Servlet
*/
@WebServlet("/Test5Servlet")
public class Test5Servlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("flag", true);
request.getRequestDispatcher("step5-jstl-if.jsp").forward(request, response);
}
}
flag라는 name에 true 값을 설정한다.
step5-jstl-if.jsp
<div class="container pt-3">
<h5>JSTL if test</h5>
flag : ${requestScope.flag} <br><br>
<c:if test="true">
jstl if test1
</c:if>
<c:if test="false">
jstl if test2
</c:if>
</div>
컨트롤러에서 넘어온 값으로 연산해 if문에 false인 부분은 출력되지않은것을 볼 수 있다.
또 다른 조건을 들어 화면에 출력할 수 있다.
nick : ${param.nick}
<%-- jstl if로 nick이 아이유일때 실행되도록 --%>
<br>
<c:if test="${param.nick=='아이유'}">
jstl if nick ${param.nick}
</c:if>
if문이 실행돼 한줄 추가된 것을 볼 수 있다.
<%-- nick이 아이유이고 age가 18세 초과하면 --%>
<c:if test="${param.age>18 && param.nick=='아이유'}">
jstl if age 성인 ${param.nick} ${param.age} 세
</c:if>
index.jsp
<a href="Test6Servlet">JSTL choose when otherwise</a>
Test6Servlet
@WebServlet("/Test6Servlet")
public class Test6Servlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("food",new FoodVO("돈까스", 11000));
request.getRequestDispatcher("step6-jstl-choose-when-otherwise.jsp").forward(request, response);
}
}
step6-jstl-choose-when-otherwise.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<div class="container pt-3">
food name : ${requestScope.food.name} food price : ${requestScope.food.price}
<%--
if ~else if ~ else
jstl 에서는 choose when otherwise
--%>
<hr>
<%-- food price가 20000원 이상 비싼 식사, 10000원 이상 약간 비싼 식사, 그저 그런 식사 --%>
<c:choose>
<c:when test="${reqeustScope.food.price>20000}">
${requestScope.food.name} 비싼 식사
</c:when>
<c:when test="${requestScope.food.price >10000}">
${requestScope.food.name} 약간 비싼 식사
</c:when>
<c:otherwise>
${requestScope.food.name} 평범한 식사
</c:otherwise>
</c:choose>
</div>
</body>
</html>
items : 배열 또는 컬렉션 계열 자료구조체(list, set, map 가능)
var : 요소를 담을 임시변수 (items의 첫번째 요소부터 마지막까지 순차적으로 요소를 할당)
vatStatus : index와 count를 사용할 수 있음
index는 0부터 시작, count는 1부터 시작
Test8Servlet
@WebServlet("/Test8Servlet")
public class Test8Servlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String phone[] = {"아이폰13", "갤럭시22", "롤리팝"};
request.setAttribute("phone", phone);
request.getRequestDispatcher("step8-jstl-forEach-Array.jsp").forward(request, response);
}
}
step8-jstl-forEach-Array
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<div class="container pt-3">
<c:forEach items="${requestScope.phone}" var="p" vatStatus="order">
index : ${order.index} count: ${order.count} ${p} <br>
</c:forEach>
</div>
</body>
</html>
jstl forEach로 컨트롤러에서 공유한 menuList 정보를 이용해 체크박스를 만든다.
servlet에 아래 코드를 추가해 예제를 풀어본다.
ArrayList<String> list = new ArrayList<>();
list.add("치킨");
list.add("피자");
list.add("맥주");
request.setAttribute("menuList", list);
request.getRequestDispatcher("step8-jstl-forEach-Array.jsp").forward(request, response);
list로 음식 메뉴를 담아 화면에 나타냈다.
<form action="Test9Servlet">
<%-- jstl forEach로 컨트롤러에서 공유한 menuList 정보를 이용해 체크박스를 만든다. --%>
<c:forEach items="${requestScope.menuList}" var="p">
<input type="checkbox" name="menu" value="${p}">${p}<br>
</c:forEach>
<button type="submit">주문하기</button>
</form>
Test9Servlet
@WebServlet("/Test9Servlet")
public class Test9Servlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("step9-jstl-forEach-paramValues.jsp").forward(request, response);
}
}
step9-jstl-forEach-paramValues.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<div class="container pt-3">
<%-- jsp 스크립틀릿 기존 방식과 el % jstl 적용 방식 비교 --%>
<%
String[] menu = request.getParameterValues("menu");
%>
<c:forEach items="${paramValues.menu}" var="m">
${m}
</c:forEach>
주문완료!
</div>
</body>
</html>