국비교육(22-23)

42일차(1)/JSTL(1) : JSTL 사용법, 작성법

서리/Seori 2022. 12. 6. 16:27

42일차(1)/JSTL(1) : JSTL 사용법, 작성법

 

 

*mvnrepository : https://mvnrepository.com/

- 자바 의존 라이브러리를 다운받는곳

 

- jstl 을 검색해서 두번째 클릭 (사용자가 많은 쪽)

- JSTL이란 jsp의 기능을 더욱 확장한 라이브러리라고 할 수 있다.

 

- 1.2 버전으로 들어가준다.

 

- java의 빌드 시스템은 보통 maven / gradle 둘 중 하나이다.

- 이 경우 아래의 텍스트를 복사해서 붙여넣으면 된다.

 

- 그런데 지금 우리가 하고있는 프로젝트는 둘다 아니다.. 그래서 jar파일을 다운받았다.

 

- web-INF 안의 lib 안에 넣어주기

- 이 라이브러리가 있으면 jsp페이지의 기능을 더 확장해서 사용할 수 있다.

 


 

test_jstl 폴더생성

 

hello.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%--
	[ taglib ]
	
	uri="import 할 라이브러리 종류"
	prefix="해당 라이브러리를 사용할 접두어 설정"
	
	만일 접두어를 prefix="banana" 라고 설정한다면
	jsp페이지에서 <banana:xxx> 형태의 tag를 사용할 수 있다.
	
	위의 설정에서는 prefix="c"라고 설정했기 때문에 (core 라이브러리라는 의미에서 c)	
	<c:xxx> 형태의 tag 를 jsp페이지 내에서 사용할 수 있다.
	
 --%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/test_jstl/hello.jsp</title>
</head>
<body>
	<h1>JSTL의 core 라이브러리 사용해 보기</h1>
	<c:forEach var="i" begin="0" end="9" step="1">
		<p>안녕 JSTL <strong>${i }</strong></p>
	</c:forEach>
	<h1>JSTL을 사용하지 않고 java code를 활용해서 위와 같은 동작을 해 보세요.</h1>
	<%for(int i=0; i<10; i++){ %>
		<p>안녕 JSTL <strong><%=i %></strong></p>
	<%} %>
</body>
</html>

 

- jstl의 사용방법 : <%@ %> 안에 import하는 코드를 넣어주면 된다.

 

 * JSTL : JSP Standard Tag Library (JSP 표준 태그 라이브러리)

- taglib 는 tag library라는 뜻

 

 

- jar파일 안에 이 내용들이 있다. lib 안에 넣어서 이제 사용할 수 있게 된 것!

- http 형태로 되어있지만 저 jar 패키지에 있는 것을 import해오는 것이라고 생각하면 된다.

 

<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

 (전부 ctrl+space 자동완성으로 작성할 수 있다)

- 무엇을 import해서 어떤 접두어(prefix)로 사용할 것인지에 대한 설명!

 

[ taglib ]
uri = "import 할 라이브러리 종류"
prefix = "해당 라이브러리를 사용할 접두어 설정"

 

- prefix= " c " : c 부분은 자유롭게 지정 가능!

- core 라이브러리는 jsp페이지에서 많이 쓰인다.

 

- core 라이브러리에서 사용할 수 있는 코드가 14가지 정도 있다.

- java코드를 대체해 주는 역할을 한다.

 

<c:forEach>

- java의 for문을 대체하는 것이다. 태그 형태이기 때문에 속성을 부여할 수 있다.

 

- @는 attribute. forEach 안에서 작성할 수 있는 속성들이다.

 

- 만일 저 내용이 java 코드로 대체된다면 for문으로 바뀐다는 것을 알 수 있다.

 

- step을 3으로 바꾼경우 3단위로 숫자가 뛴다.

- var 변수명, begin 시작값, end 끝나는 값이라고 생각하면 된다.

 

<c:forEach var="i" begin="0" end="9" step="1">
    <p>안녕 JSTL <strong>${i }</strong></p>
</c:forEach>

<%for(int i=0; i<10; i++){ %>
    <p>안녕 JSTL <strong><%=i %></strong></p>
<%} %>

 

- java코드로 똑같은 코드 작성해보기

- java for문을 사용하면 <% %> <%= %> 등을 작성해야 하는 것이 불편하다.

 

- java 변수에 있는 값은 EL로 참조는 안된다.

 

- JSTL과 EL을 잘 활용하면 java코드를 없앨 수 있다.

- 마크업과 jstl은 잘 어우러진다. 하지만 <% %>로 작성하는 java 코드는 좀 이질감이 있어서 불편하다.

 그래서 EL과 JSTL을 함께 사용하는 코드를 많이 쓴다.

 


 

<test01>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/test_jstl/test01.jsp</title>
</head>
<body>
	<h1>JSTL (Jsp Standard Tag Library)</h1>
	<c:forEach var="i" begin="1" end="5">
		<p>안녕 ${i }</p>
	</c:forEach>
</body>
</html>

 

- <c:forEach> 안에 넣은 p요소는 총 5개 출력됨

- 1씩 증가하는 경우 step은 생략 가능!

 


 

<test02>

<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>  
<%
	//테스트를 위해 sample 데이터를 request scope 에 담는다.
	List<String> names=new ArrayList<String>();
	names.add("바나나");
	names.add("딸기");
	names.add("복숭아");
	
	request.setAttribute("list", names);
%>  
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/test_jstl/test02.jsp</title>
</head>
<body>
	<%
		//request영역에 "list"라는 키값으로 저장된 값을 읽어와서 원래 type으로 casting
		List<String> list=(List<String>)request.getAttribute("list");
	%>
	<h1>친구 목록</h1>
	<ul>
		<%for(String tmp:list){ %>
			<li><%=tmp %></li>
		<%} %>
	</ul>
	
	<h1>친구 목록</h1>
	<ul>
		<c:forEach var="tmp" items="${list }" >
			<li>${tmp }</li>
		</c:forEach>
	</ul>
	
	<h1>친구 목록 입니다. 인덱스 표시</h1>
	<ul>
		<c:forEach var="tmp" items="${list }" varStatus="status">
			<li>${tmp } <strong>${status.index }</strong></li>
		</c:forEach>
	</ul>
	
	<h1>친구 목록 입니다. 순서표시</h1>
	<ul>
		<c:forEach var="tmp" items="${list }" varStatus="status">
			<li>${tmp } <strong>${status.count }</strong></li>
		</c:forEach>
	</ul>	
	
	<h1>친구 목록 입니다. 첫번째 인지 여부</h1>
	<ul>
		<c:forEach var="tmp" items="${list }" varStatus="status">
			<li>${tmp } <strong>첫번째 : ${status.first}</strong></li>
		</c:forEach>
	</ul>
	
	<h1>친구 목록 입니다. 마지막 인지 여부</h1>
	<ul>
		<c:forEach var="tmp" items="${list }" varStatus="status">
			<li>${tmp } <strong>마지막 : ${status.last}</strong></li>
		</c:forEach>
	</ul>
</body>
</html>

 

- 샘플 데이터를 request 영역에 담음

- request.getAttribute("list"); : request 에 담은 내용 추출해서 캐스팅해주기!

 

- 이후에는 1은 서블릿, 2는 jsp로 작성될 것. 작업을 분업화한다.

- 1 → 2로 forward 이동해서 응답해줄 것이다.

 

- 같은 내용을 응답했지만, 작성된 코드는 다르다.

- 2번이 훨씬 편리하다. EL과 JSTL만으로 요청을 읽어와서 웹브라우저에 응답했다.

 

 

- EL의 경우 list라는 키 값으로 저장되어 있다는 것만 알면 된다.

- EL키 값만으로도 값을 읽어오는 기능이 있다.

 

- ${list} 는 원래는 ${requestScope.list} 라고 써야하는데 생략 가능한 것

- 특정 키가 순서대로 담겨있는 배열 형태이면 items 속성을 이용할 수 있다.

 ex) request.getParameter("id")도 ${id} 라고만 쓰면 된다.

 

 

- list의 제너릭타입은 <String> 이다.

- var="tmp"라고 적어놓은것만 봐서는 tmp의 타입이 확인되지 않지만, String 이라는 것을 인지하고 있어야 한다.

 제너릭이 String이기 때문에 String 타입인 것이다.

 

- String 타입이므로 바로 출력 가능하다.

(만약 dto이면 바로 출력할수는 없다. getter 사용해야 한다)

 

 

- varStatus 속성을 사용해서 인덱스 표시 가능, 순서 표시 가능.

- 해당 아이템이 배열에서 제일 첫번째/마지막인지 여부를 boolean을 통해 알 수도 있다.

 

- varStatus="status" ← 이 녹색 부분의 이름은 마음대로 지으면 된다.

- 변수의 이름이 아니라 .index / .count / .first / .last 가 중요하다. (이 부분은 고정!)

 


 

<test03>

<%@page import="java.util.ArrayList"%>
<%@page import="test.file.dto.FileDto"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>  
<%
	//Servlet 단에서 담은 sample  데이터라고 가정하자
	List<FileDto> list=new ArrayList<>();
	FileDto dto1=new FileDto();
	dto1.setNum(1);
	dto1.setWriter("바나나");
	dto1.setTitle("제목1");
	
	FileDto dto2=new FileDto();
	dto2.setNum(2);
	dto2.setWriter("딸기");
	dto2.setTitle("제목2");
	
	FileDto dto3=new FileDto();
	dto3.setNum(3);
	dto3.setWriter("복숭아");
	dto3.setTitle("제목3");
	
	list.add(dto1);
	list.add(dto2);
	list.add(dto3);
	// EL 로 추출할수 있도록 request  영역에 담는다. 
	request.setAttribute("list", list);
%>  
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/test_jstl/test03.jsp</title>
</head>
<body>
	<h1>List 에 들어 있는 Dto 활용</h1>
	<table>
		<thead>
			<tr>
				<th>번호</th>
				<th>작성자</th>
				<th>제목</th>
			</tr>
		</thead>
		<tbody>
			<c:forEach var="tmp" items="${list }">
				<tr>
					<td>${tmp.num }</td>
					<td>${tmp.writer }</td>
					<td>${tmp.title }</td>
				</tr>
			</c:forEach>
		</tbody>
	</table>
</body>
</html>

 

List<FileDto> list : 이번 list에는 FileDto가 들어 있다.

- 따라서 바로 출력할 수 없다.(FileDto는 숫자도 문자도 아니므로...)

- list라는 키값으로 담겨있는 list<FileDto> 타입을 가져온다.

 

- 이 <> 제너릭(FileDto)이 아래 tmp의 타입이 된다.

- tmp의 타입을 기억해서 바로 인지할 수 있도록 하기!

 

- FileDto 타입이기 때문에 . 점 찍어서 해당 내용을 출력하도록 한다.

 

- 원래는 위와 같이 써야하지만, 번거로우므로 줄여서 쓸 수 있다. 아래와 같이 써도 무방하다.

→ 단 getter, setter가 작성규약에 맞게끔 작성되어 있을 경우에만!

- EL을 이용해서 getter 메소드를 호출할 수 있다.

 

- 서블릿 에서 윗부분의 작업을 하고

응답을 위해 jsp로 포워드 이동이 되었다면, 문제없이 아래 list를 출력할 수 있다.

- EL과 JSTL만 잘 활용해도 java code없이 출력 가능하다!

 

 

- list를 읽어와서 tmp라는 공간에 FileDto type을 담은 것이라고 할 수 있다.

 


 

<test04>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>  
<%
	// test 를 위해 sample data 를 request 영역에 담기
	request.setAttribute("jumsu", 75);
%>  
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/test_jstl/test04.jsp</title>
</head>
<body>
	<c:if test="true">
		<p>오잉 true 네</p>
	</c:if>

	<c:if test="${ 10%2 eq 0 }">
		<p>10 은 짝수 입니다.</p>
	</c:if>
	
	<c:if test="${ 11%2 eq 0 }">
		<p>11 은 짝수 입니다.</p>
	</c:if>
	<c:if test="${jumsu%2 eq 0 }">
		<p>${jumsu } 는 짝수 입니다.</p>
	</c:if>
	
	<p> 획득한 점수는 <strong>${jumsu }</strong> 입니다.</p>
	<p>
		따라서 이번 학기 학점은
		<c:choose>
			<c:when test="${jumsu ge 90 }">A</c:when>
			<c:when test="${jumsu ge 80 }">B</c:when>
			<c:when test="${jumsu ge 70}">C</c:when>
			<c:when test="${jumsu ge 60 }">D</c:when>
			<c:otherwise>F</c:otherwise>
		</c:choose>
		입니다
	</p>	
	<p>
		<strong>${jumsu }</strong> 는
		<c:choose>
			<c:when test="${jumsu%2 eq 0}">
				짝수
			</c:when>
			<c:otherwise>
				홀수
			</c:otherwise>
		</c:choose>
		입니다.
	</p>
	
	<%
		String id=(String)session.getAttribute("id");
	%>
	
	<%if(id == null){ %>
		<p> 로그인이 필요 합니다.</p>
	<%}else{ %>
		<p> <strong><%=id %></strong> 님 로그인중...</p>
	<%} %>
	
	<c:choose>
		<c:when test="${ empty id }">
			<p>로그인이 필요 합니다.</p>
		</c:when>
		<c:otherwise>
			<p> <strong>${id }</strong> 님 로그인중...</p>
		</c:otherwise>
	</c:choose>
</body>
</html>

 

- request에 jumsu라는 키값으로 숫자값을 담아 둠

 

${requestScope.jumsu}

${jumsu}

- 75라는 숫자값을 읽어오는 방법 2가지

 

<c:if test=""> xxx </c:if>

- 태그 안에 있는 내용을 클라이언트에게 출력을 할지 말지를 정하는 태그

- test=" " 안의 참조값이 false이면 xxx가 출력되지 않는다.

 

<c:if test="${requestScope.jumsu%2 eq 0 }">

<c:if test="${jumsu%2 eq 0 }">

- 같은 것이다. requestScope 를 생략해 사용할 수 있는 것

 

 

- 출력된 75를 when 안의 내용으로 검증한다. 조건에 맞지 않으면 다음단계를 검증한다.(elseif)

 

 

 

c:choose / when / when / when / otherwise 로 대체해야 한다. (다중if문)

- JSTL에 if~else문은 없다

 

- 양자택일 구현시 c:choose / when / otherwise (양자택일. 단일if문)

 

- jsp에서 java 코드를 없애기! EL과 JSTL을 사용하여 대체하기

- EL과 JSTL로 구조를 잘 짜면 시각적으로보이는 java코드는 없앨 수 있다.

 


 

<test05>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>    
<%
	//sample 데이터
	request.setAttribute("size", 123456789);
	request.setAttribute("price", 2500000);
%>    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>test05.jsp</title>
</head>
<body>
	<p>
		파일의 크기는 
		<fmt:formatNumber value="123456789" pattern="#,###"/>
		byte 입니다.
	</p>
	<p>
		파일의 크기는 
		<fmt:formatNumber value="${size }" pattern="#,###"/>
		byte 입니다.
	</p>
	<p>
		가격은
		<fmt:formatNumber value="2500000" type="currency"/>
		입니다.
	</p>
	<p>
		가격은
		<fmt:formatNumber value="${price }" type="currency"/>
		입니다.
	</p>
	<p>
		가격은
		<fmt:formatNumber value="${price }" type="currency" currencySymbol="$"/>
		입니다.
	</p>
</body>
</html>

 

<%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>   

- import한 태그 라이브러리가 다르다.

- format : 숫자형식을 사용하는 라이브러리 (숫자와 관련된 라이브러리)

 

 

- taglib 1줄을 추가하면 이런 형태의 태그 라이브러리들을 사용할 수 있는 것이다.

 

- format 라이브러리 안에 다양한 기능들이 있다.

- pattern : 숫자를 어떤 패턴으로 출력하고 싶을 때

 

- java 코드로하면 상당히 귀찮은 작업인데, fmt가 알아서 해주도록 만들 수 있다.

 

currency : 통화/화폐 타입

- 3자리마다 하나씩 ',' 지정하기

- 통화의 심볼이 다르면 속성에 currencySymbol="$" 을 따로 지정해주면 된다.

 


 

<test06>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> 
<%
	//sample 데이터
	request.setAttribute("hobby", "game/programming/piano");
	request.setAttribute("friends", "바나나,딸기,복숭아");
%>    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/test_jstl/test06.jsp</title>
</head>
<body>
	<h1>forTokens 활용</h1>
	<h2>취미 목록</h2>
	<ul>
		<c:forTokens var="tmp" items="${hobby }" delims="/">
			<li>${tmp }</li>
		</c:forTokens>
	</ul>
	<h2>친구 목록</h2>
	<ul>
		<c:forTokens var="tmp" items="${friends }" delims=",">
			<li>${tmp }</li>
		</c:forTokens>
	</ul>
</body>
</html>

 

- 구분자로 구분된 문자열을 활용할 때, forToken 을 사용하면 쉽게 하나씩 빼낼 수 있다.

 

 

- items 안에 이 문자열을 넣어주고 delims=" / " 델리미터 " " 안에 구분할 기호를 넣어주면

 / 로 구분해서 순서대로 하나씩 참조해서 넣어준다.

 

- DB에서 위와 같은 문자열을 저장해야 할 때가 있다. 그럴때 유용하게 사용된다!

 


 

<test07>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>  
<%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>  
<%
	//sample 데이터
	request.setAttribute("msg", "abcde바나나1234");
	request.setAttribute("str", "<div></div> 는 문단을 나타내는 요소 입니다.");
	request.setAttribute("content", "하나\n두울\n세엣");
	request.setAttribute("newLine", "\n");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/test_jstl/test07.jsp</title>
</head>
<body>
	<h1>JSTL function (EL 코드 블럭 안에서 사용하는 함수) 활용</h1>
	<p> "바나나" 가 포함되어 있는지 여부 : ${fn:contains(msg, '바나나')}</p>
	<c:if test="${fn:contains(msg,'바나나') }">
		<p>메세지에 "바나나" 가 포함되어 있군요!</p>
	</c:if>
	<p>${str }</p>
	<p>${fn:escapeXml(str) }</p>
	<p>${content }</p>
	<%-- content 문자열에서 개행 기호를  <br> 로 바꿔서 출력 --%>
	<p>${fn:replace(content, newLine, '<br>') }</p>
</body>
</html>

 

- \n 은 개행기호이다.

 

<%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>  

- 이번에는 core 와 함께 functions를 import 해주었다.

- fn은 사용하는 방식이 조금 다르다. EL 안에서 사용하는 함수라고 생각하면 된다.

 

${fn:contains()}

- 어디에 뭐가 포함되어 있는지 확인하는 함수

${fn:excapeXml()}

- 이 문자열에서 xml을 탈출하는 것 → () 안의 내용을 xml로 간주하지 않는 것을 의미한다!

${fn:replace(content, newLine, '<br>') }

- textarea로 전달받으면(개행기호를 같이 전달받는데) 바꿔서 출력해주도록 하는 기능

 

- 위의 선언이 있기때문에 fn: 을 사용할 수 있는 것이다.

 

 

- excapeXml : 문자를 출력했음에도 불구하고 html로 해석하고 있지 않다. 텍스트로 출력해준다.

- 화면에서 어떻게 나타나는지, 원본 소스와 비교해서 브라우저에서는 어떻게 해석되는지 알아두기

 

- replace는 개행기호 대신 <br>로 바꾸어 줌.

- 웹브라우저에서 개행기호를 해석하지 않기 때문에 넣어준 것이다.

 


 

참고) Snippet 설정

 

- Window-Preference-Emmet-Snippets

- taglib 1줄을 부분을 자주 삽입하여 사용할 예정이므로 복사해서 Snippet으로 저장해 두기! (core)