EL과 JSP

기록하는 용도·2022년 10월 5일
0

EL(Expression Language)

JSP 버전이 상향되면서 추가된 스크립트 언어로 기존 Scriptlet tag의 표현식 ( <%= %> ) 의 업그레이드 된 버전 ( ${ } )이다.


JSP 속성영역 (request, session, application(ServletContext)) 에 저장된 객체의 property 를 출력하는 용도로 사용된다.


EL을 이용하면 별도의 import , Object Casting 절차 필요없이 바로 출력이 가능 , 다양한 연산 및 자동 형변환이 된다.
JSTL 과 연동이 가능
EL은 Model 객체의 get계열 메서드와 is계열의 메서드에만 접근 가능하다.



JSTL(Jsp Standard Tag Library)

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>





request와 session에 저장된 정보를 EL로 표현

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 순으로 정보를 표현한다.



client에서 전달한 query string 정보를 EL로 표현

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 VO의 getter와 is 계열 메소드를 실행해 정보를 확보

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() 메소드를 실행해 그 정보를 화면에 보여준 것을 할 수 있다.




JSTL if test

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>



JSTL choose when otherwise

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>

0개의 댓글

관련 채용 정보