thesunset 2022. 12. 13. 22:28

0. 환경 구성하기 

우클릭 > New > DynamicProject생성 > "ActionProject"으로 이름

- 폴더 구성

웰컴파일 생성
패키지 내 servlet생성


1. EL(Expression Language) 표현언어

기존에 사용했던 표현식(출력식) <% %>와 같이
JSP상에서 표현하고자하는 값을 ${ name }의 형식으로 표현해서 작성하는 것

1) EL기본구문에 대해서 먼저 배워보자

<a href="/el/el.do">01_EL</a>

<com.kh.controller.ElServlet> : /el.do

 

EL => 그동안 수하물들을 request, session, application, page에 담았음

                                            -JSP내장객체(Scope내장객체)-

 

(1) 데이터를 담을 수 있는 JSP내장객체 종류 4가지
ㄱ. ServletContext(=자료형) (application scope)
    한 어플리케이션(웹사이트) 당 단 1개 존재하는 객체
    이 영역에 담으면 어플리케이션 전역에서 사용가능
=> 공유범위가 가장 큼

ㄴ. HttpSession (session scope)
   한 브라우저당 1개 존재하는 객체
   이 영역에 데이터를 담으면 jsp/servlet단에서 사용가능
   값이 한 번 담기면 서버가 멈추거나, 브라우저가 닫히기 전까지는 사용 가능(로그인기능)
  => 공유범위가 다소 제한적

ㄷ. HttpServletRequest (request scope)
   요청 및 응답 시 매 번 생성되는 객체
   이 영역에 데이터를 담으면 해당 request객체를 포워딩 받는 응답 jsp에서만 사용가능(1회성)
   => 공유범위가 해당요청에 대한 응답 jsp 단 하나뿐

ㄹ. PageContext (page scope) 
   현재 그 jsp페이지에서만 사용가능
   => 공유범위가 가장 작음(해당페이지에서만 쓰임)

 => 객체들의 값을 담을 때 .setAttribute("key", value);
   값을 뽑을 때 .getAttribute("key", value); (Object형태)
   지우고자 할 때는 .removeAttribute("key");

 

* Person VO만들기 

package com.kh.model.vo;

public class Person {
	
	private String name;
	private int age; 
	private String address;
	
	
	public Person() {
		super();
	}


	public Person(String name, int age, String address) {
		super();
		this.name = name;
		this.age = age;
		this.address = address;
	}


	public String getName() {
		return name;
	}


	public void setName(String name) {
		this.name = name;
	}


	public int getAge() {
		return age;
	}


	public void setAge(int age) {
		this.age = age;
	}


	public String getAddress() {
		return address;
	}


	public void setAddress(String address) {
		this.address = address;
	}


	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", address=" + address + "]";
	}
	
}

 

(2) requestScope에 담기

request.setAttribute("classRoom", "C강의장");
request.setAttribute("student", new Person("김승혜", 20, "미아"));

(3) sessionScope에 담기

HttpSession session = request.getSession();
session.setAttribute("academy", "KH정보교육원");
session.setAttribute("lecture", new Person("이승철", 20, "남양주"));

원래, 항상 키값은 중복 X

 

하지만 테스트를 해본다면?

- 테스트 : requestScope와 sessionScope에 동일한 키값으로 데이터 담아보기 

request.setAttribute("scope", "request");
session.setAttribute("scope", "session");

(4) applicationScope에 담기

ServletContext application = request.getServletContext();
application.setAttribute("scope", "application");

 

응답 뷰 지정 => forword (파일경로를 지정할 때), sendRedirect방식(ContextPath로부터 재요청을 보낼경우)

request.getRequestDispatcher("views/1_EL/01_el.jsp").forward(request, response);

<views/1_EL/01_el.jsp>

1-2)  EL기본구문

(1) 기존 방식대로 스클립틀릿과 표현식을 이용해서 각 영역에 담겨있는 값 뽑아서 화면에 출력

<%
   //requestScope에 담긴 값 뽑기 => classRoom, Student
    String classRoom = (String)request.getAttribute("classRoom");
    Person student = (Person)request.getAttribute("student");

    //sessionScope에 담긴 값 뽑기 => academy, lecture
    String academy = (String)session.getAttribute("academy");
    Person lecture = (Person)session.getAttribute("lecture");
%>
<p>
    학원명  : <%=academy %> <br>
    강의장 : <%= classRoom %> <br>
    강사정보 : <%= lecture.getName() %>, <%= lecture.getAge() %>, <%= lecture.getAddress() %>
    수강생 정보  <br>
    <ul>
        <li>이름 : <%=student.getName() %></li>
        <li>나이 : <%=student.getAge() %></li>
        <li>주소 : <%=student.getAddress() %></li>
    </ul>

</p>

(2) EL을 이용해서 쉽게 해당 Scope에 저장된 값들을 출력하기

EL은 getXXXX(getAttribute, getter메소드들)을 통해 값을 빼올 필요 없이 키값만 제시하면 바로 값에 접근 가능
내부적으로 해당 Scope영역에 해당 key값에 해당하는 value값을 가져올 수 있음 
기본적으로 EL은 JSP내장 객체 종류(4가지)를 구분하지 않고 자동적으로 모든 내장객체에서 키값을 검색해서 존재하는 경우 값을 가져옴

	<p>
		학원명 : ${academy} <br>
		강의장 : ${classRoom } <br>
		강사정보 : ${lecture.name }, ${lecture.age}, ${lecture.address}
        수강생정보 	<br>
			<ul>
			<li>이름 : ${student.name}</li>
			<li>나이 : ${student.age}</li>
			<li>주소 : ${student.address}</li>
		</ul>
	</p>
어떻게 필드값에 직접접근을?
lecture에 접근했을 때 value값이 Person타입 객체임
해당 Person객체에 각 필드에 담긴 값을 출력하고자 한다면 
key값, value명으로 접근

내부적으로 getter메소드를 찾아서 호출을 해서 값을 가져오는 구조
  => 항상 명심해야할 사항: getter메소드를 꼭 만들자

(3) EL사용 시 내장 객체들에 저장된 키값이 동일한 경우

scope키값에 담긴 벨류값 : ${scope} <br> <!-- request가 찍힘 -->

EL구문은 공유범위가 가장 작은  Scope에서부터 해당 키값을 검색함
page => request => session => application 순으로 키값을 찾음 ** 중요

 

표현식으로 없는 키값을 제시했을 경우 : &lt;%= aaa %&gt; <!-- 500에러 발생  -->
EL로 없는 키값을 제시하는 경우 : ${aaa}<br>

(4) 직접 Scope영역을 지정해서 접근하기

<%
    pageContext.setAttribute("scope", "page");
%>

Quiz : ${scope}를 작성하면 무슨값이 나올까? => page <br><br>

pageScope에 담긴 "scope"키값에 해당하는 벨류도 뽑고 싶고,
requestScop, sessionScope, applicationScope에 있는 "scope" 키값에 해당하는 value도 뽑고 싶다면?

pageScope에 담긴 값 : ${scope} 또는 ${pageScope.scope} <br>
requestScope에 담긴 값 : ${requestScope.scope } <br>
sessionScope에 담긴 값 : ${sessionScope.scope } <br>
applicationScope에 담긴 값 : ${applicationScope.scope } <br>

Quiz : ${sessionScope.classRoom} <br>

2) EL의 연산자에 대해서 배워보자

<a href="/el/operation.do">02_EL의 연산자</a>

<com.kh.controller>ELOperationServlet

request.setAttribute("big", 10);
request.setAttribute("small", 3);

request.setAttribute("sOne", "안녕");
request.setAttribute("sTwo", new String("안녕"));

request.setAttribute("pOne", new Person("홍길동", 10, "한양"));
request.setAttribute("pTwo", null);

ArrayList<String> list1 = new ArrayList();
request.setAttribute("lOne", list1);

ArrayList<String> list2 = new ArrayList();
list2.add("list2테스트중");
request.setAttribute("lTwo", list2);

request.getRequestDispatcher("views/1_EL/02_elOperation.jsp").forward(request, response);

<views/1_EL/02_elOperation.jsp>

2-2) EL연산

(1) 산술연산

* 기존방식

10 + 3 = <%=(int)request.getAttribute("big")+(int)request.getAttribute("small") %>

* EL연산

10 + 3 = ${big+small}<br>
10 - 3 = ${big-small}<br>
10 * 3 = ${big*small}<br>
10 / 3 = ${big/small} 또는 ${big div small}<br>
10 % 3 = ${big%small} 또는 ${big mod small}<br>

(2) 숫자간 대소 비교 연산

* 기존방식 

10 > 3 : <%=(int)request.getAttribute("big") > (int)request.getAttribute("small") %>

* EL연산

10 &gt; 3 : ${ big > small } 또는 ${big gt small } <br>
10 &lt; 3 : ${ big < small } 또는 ${big lt small } <br>
10 &gt;= 3 : ${ big >= small } 또는 ${big ge small } <br>
10 &lt;= 3 : ${ big <= small } 또는 ${big le small }

(3) 동등 비교 연산

* 기존방식

10과 3이 일치합니까?

<%= (int)request.getAttribute("big") == (int)request.getAttribute("small") %> <br>
sOne과 sTwo가 일치합니까? (주소비교) : 
<%= (String)request.getAttribute("sOne") == (String)request.getAttribute("sTwo") %><br>
sOne과 sTwo가 일치합니까? (내용비교) : 
<%= ((String)request.getAttribute("sOne")).equals((String)request.getAttribute("sTwo")) %><br>

* EL 연산

10과 3이 일치합니까? : ${big == small } 또는 ${big eq small} <br>
big에 담긴값과 10이 일치합니까? : ${big == 10 } 또는 ${big eq 10 } <br>
sOne과 sTwo가 일치합니까? ${sOne == sTwo } <br>
<!--  EL에서의 문자열의 ==비교는 자바에서의 equals()메소드와 같은 동작을 함 -->

sOne과 sTwo가 일치하지 않습니까? : ${sOne != sTwo} 또는 ${sOne ne sTwo } <br>
<!-- ne : not equals -->

sOne에 담긴 값과 "안녕"이 일치합니까? : ${sOne == "안녕" } 또는 ${sOne eq "안녕"}
<!-- EL에서의 문자열 리터럴 제시 시 홑따옴표 / 쌍따옴표 상관없음 -->

(4) 객체가 null인지 또는 리스트가 비어있는지 체크하는 연산

* 기존 방식

- 객체가 null인지 알고 싶을 경우 객체명 == null로 비교하면 true또는 false가 나옴
- 리스트가 비어있는지 알고 싶을 경우 리스트명.isEmpty()사용하면 true또는 false가 나옴 
혹은 리스트명.size()==0을 사용해도 무방

* EL연산

pTwo가 null 입니까 ? : ${ empty pTwo } 또는 ${pTwo == null } 또는 ${pTwo eq null } <br>
pOne이 null이 아닙니까? : ${!empty pOne } 또는 ${pOne != null } 또는 ${pOne ne null } <br>

lOne이 텅 비어있습니까? : ${empty lOne }	<br>
lTwo가 텅 비어있습니까? : ${empty lTwo } <br>

(5) 논리연산자

*기존방식
&&(AND), ||(OR)

* EL연산 

AND연산 : ${true and true }  <br>
OR연산 : ${true or false }

- big이 small보다 크고 lOne이 텅 비어있나?

${(big gt small) and (empty lOne) }

- big과 small의 곱은 4의 배수인가?

${(big * small mod 4) eq 0 }

* JSP를 이루고 있는 구성인자

[1] JSP 스크립팅 원소 : JSP페이지에서 자바코드를 직접 기술할 수 있게하는 기술
예) 스크립틀릿, 표현식, 선언문
[2] 지시어 : JSP페이지 정보에 대한 내용을 포함한다거나 현재 페이지에 정보를 표현할 때 사용
예) Include지시어/page지시어/taglib지시어
[3] JSP 액션 태그 : ***XML기술***을 이용해서 기존의 JSP문법을 확장하는 기술을 제공하는 태그
- 표준 액션태그(Standard Action Tag)
: JSP페이지 내에서 바로 사용 가능한 태그
[표현법]
&lt; jsp:태그명&gt;&lt;/jsp:태그명&gt;
=> 모든 태그명 앞에 jsp: 이라는 접두어가 붙음

- 커스텀 액션태그(Custom Action Tag)
: JSP페이지 에서 바로 사용 불가능한 태그(별도의 연동이 필요함, taglib 지시어 사용)
=> 모든 태그명 앞에 jsp:이외의 다른 접두어가 붙음(종류가다양)
=> 제공되고 있는 대표적인 유용한 라이브러리가 있음(JSTL)

 

 3) JSP Action Tag

: XML기술을 이용해서 기존의 JSP문법을 확장시키는 기술을 제공하는 태그들

(1) 표준 액션 태그

: JSP페이지에서 별도의 라이브러리 연동없이 곧바로 사용가능한 액션태그

<a href="views/2_StandardAction/01_include.jsp">01_jsp:include</a>

<views/2_StandardAction/footer.jsp>

<%
    //Date 객체 => new Date()를 하면 오늘 날짜가 나옴
    //오늘 날짜 기준으로 년도만 뽑아서 채워 넣을 것
    //=> SimpleDateFormat객체를 이용해서 년도만 뽑아보자

    String year = new SimpleDateFormat("yyyy").format(new Date());
%>

Copyright © 1998-<%=year %> KH Information Educational Institute All Right Reserved


<br>

01_include.jsp로 부터 전달받은 test라는 키값의 벨류를 출력 <br>
test : ${param.test }

<views/2_StandardAction/01_include.jsp>

* include : 또 다른 페이지를 포함할 때 쓰는 방법

(1) 기존의 include지시어를 이용한 방법(정적include방식 == 컴파일 시 포함되는 형태)

<%@ include file="footer.jsp" %>

특징 : include하고 있는 페이지 상에 선언되어있는 변수를 현재 페이지에서도 사용 가능함

year변수값 : <%=year %> 

<%
    String year = "2222";
%>
=> 오류

(2) JSP표준 액션태그를 이용한 방식(동적 include방식 == 런타임 시 포함되는 형태)

<jsp:include page="footer.jsp"/>

!!!반드시!!! 시작태그와 종료태그를 같이 써야한다.
단, 시작태그와 종료태그 사이에 넣을 값이 따로 없다면 <시작태그/>로 표현이 가능 /이 없으면 오류 발생

 

특징1 : include하고 있는 페이지에 선언된 변수를 공유하지 않음(즉, 동일한 이름의 변수 선언가능)

<%
    String year = "2022";
%>

특징 2 : 포함 시 include하는 페이지로 값을 전달할 수 있음

<jsp:include page="footer.jsp">
    <jsp:param value="Hello" name="test"/>

</jsp:include>
<br>
<jsp:include page="footer.jsp">
    <jsp:param value="Bye" name="test"/>

</jsp:include>

 

<a href="views/2_StandardAction/02_forward.jsp">02_jsp:forward</a>

<views/2_StandardAction/02_forward.jsp>

* forward 페이지

url로는 http://localhost:8001/el/views/2_StandardAction/02_forward.jsp가 찍혀있음
jsp:forward 화면을 전환시켜주는 태그 특성상 url은 그대로고 화면만 바뀐다.

<jsp:forward page="footer.jsp" />

(2) 커스텀 액션태그

<a href="views/3_CustomAction/jstl.jsp">JSTL</a>

* JSTL이란?

JSP Standard Tag Library의 약자로 JSP에서 사용하는 커스텀 액션태그 
공통적으로 사용하는 코드들의 집합을 보다 쉽게 사용할 수 있도록 태그화해서 표준으로 제공하는 라이브러리

 

* 라이브러리 다운로드 후 추가 방법

1> https://tomcat.apache.org/download-taglibs.cgi로 접속
2>Standard-1.2.5 Jar files 4개 다 다운로드 
3> WEB-INF/lib폴더에 추가

jstl다운로드

* JSTL 선언방법

JSTL을 사용하고자 하는 jsp페이지 상단에 taglib지시어를 사용해서 선언함 

[표현법] 
<%@ taglib prefix="접두어" uri="라이브러리 파일상의 uri주소" %>

 

* JSTL 분류

1> JSTL Core Library *** 중요 

: 변수와 조건문, 반복문 등의 로직과 관련된 문법을 제공

<a href="01_core.jsp">core library</a>

<views/3_CustomAction/01_core.jsp>

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

** jsp페이지 상단에 taglib지시어를 사용해서 선언

 

* JSTL Core Library

 

(1) 변수

● 변수선언(<c:set var="변수명" value="리터럴" scope="scope영역지정(생략가능) /&>")
- 변수를 선언하고 초기값을 대입해두는 기능을 제공
- 더 나아가서 해당 변수를 어떤  scope영역에 담아둘건지 지정 가능함
(생략 시 pageScope에 담김)

=> 해당 scope영역에 setAttribute라는 메소드를 이용해서 key+value형태로 데이터를 담아둔다라고 생각하면 됨
=> c : set 을 통해 선언된 변수는  EL로 접근해서 사용가능(스크립팅원소로는 접근불가능)

* 주의사항
- 변수의 타입을 별도로 지정하지 않음
- 반드시 해당 변수에 담아두고자하는 값(value속성에 담긴 리터럴)을 무조건 셋팅해야 함
(즉, 선언과 동시에 초기화)

<c:set var="num1" value="10"/> <!-- pageScope에 담김 pageContext.setAttribute("num1", "10"> -->
<c:set var="num2" value="20" scope="request"/>
<!-- requestScope에 담김 request.setAttribute("num2", 20); -->

num1 변수값 : ${num1} <br>
num2 변수값 : ${num2} <br>

<c:set var="result" value="${num1+num2 }" scope="session"/> <!-- sessionScope에 담김 -->

result 변수값 : ${result }<br>

<!-- 
    변수명만 제시하면 공유범위가 작은 곳부터 찾음
    (스코프영역.변수명을 권장)
 -->

${pageScope.num1 }<br>
${requestScope.num2 }<br>
${sessionScope.result }<br><br>

Quiz : ${requestScope.result }<br><br>

<c:set var="result" scope="request">9999</c:set>
<!-- value속성 말고 시작태그와 종료태그 사이에도 대입할 값을 기술 가능 -->

${requestScope.result}<br>
${sessionScope.result}<br>

 

● 변수삭제(< c:remove var="제거하고자하는변수명" scope="스코프영역지정(생략가능)"/>)
- 해당 변수를 scope에서 찾아서 제거하는 태그
- scope지정 생략시 모든 scope에서 해당 변수를 다 찾아서 제거함
=> 해당 scope에 .removeAttribute("키값"); 메소드를 이용해서 제거하는 것과 같다고 생각하면 됨

 

삭제 전 result : ${result }

> 특정 scope를 지정해서 삭제

<c:remove var="result" scope="request"/>
request에서 삭제 후 result : ${result }

>  모든 scope에서 삭제

<c:remove var="result"/>
모든 scope에서 삭제 후 result : ${result }<br>

● 변수 출력(< c:out value="출력하고자하는값" default="기본값(생략가능)" escapeXml="true(기본값, 생략가능)"/>)
- 데이터를 출력하고자 할 때 사용하는 태그 
- default : 기본값, value속성에 출력하려는 값이 없을 경우 대체해서 기본값으로 출력할 내용물을 기술(생략 가능)

result를 EL구문으로 출력 : ${result }<br>
result를 c:out으로 출력 : <c:out value="${result }"/><br>
result를 c:out으로 출력할건데 default를 지정해서 출력 : <c:out value="${result }" default="값이 없음"/><br><br>

=> if문 대신 활용해서 사용할 수 있음

 

* escapeXml테스트 

- 테스트를 하기 위한 변수 선언

<c:set var="outTest" value="<b>출력테스트</b>"/>

outTest를 c:out으로 출력할건데: <c:out value="${outTest }"/> <br>

outTest를 c:out으로 출력할건데 escapeXml속성을 false로 지정하고 출력 : <c:out value="${outTest }" escapeXml="false"/>

(2) 조건문 : if

- JAVA의 단일 if문과 비슷한 역할을 하는 태그 
- 조건식을 test라는 속성에 작성(***************조건을 작성할 경우에는 반드시 EL구문으로 작성해야함)

<c:if test="${num1 gt num2 }">
<b> num1이 num2보다 큽니다. </b>
</c:if>

<c:if test="${num1 le num2 }">
    <b>num1이 num2보다 작거나 같습니다.</b>
</c:if>

<c:set var="str" value="안녕하세요." />

<c:if test="${str eq '안녕하세요' }">
    <mark>같지않음</mark>
</c:if>

(3) 조건문 : choose, when, otherwise

[표현법]
< c:choose >
     < c:when test="조건1" > ~~~ </c:when>
     < c:when test="조건1"> ~~~ </c:when>
     ....
     < c:otherwise> ~~~ < /c:otherwise > => else블럭 / switch문의 defalut
</c:choose>

- JAVA의 if-else, switch문과 비슷한 역할을 하는 태그 
- 각 조건들을 c:choose의 하위요소로 c:when을 통해서 작성
- c:otherwise에는 조건을 적어주지 않음

<c:choose>
    <c:when test="${num1 eq 20 }"> <!-- if블록 -->
        <b>num1은 20</b>
    </c:when>
    <c:when test="${num1 eq 10 }"> <!--else if 블록-->
        <b>num1은 10</b>
    </c:when>
    <c:otherwise> <!-- else블록 -->
        <b>조건없음</b>
    </c:otherwise>
</c:choose>

*  c:choose안에 주석을 넣으면 에러가 발생 <주의하기>

(4) 반복문 : forEach

[표현법]
for loop문
< c:forEach var="변수명" begin="초기값" end="끝값" step="증가시킬값(생략가능)" >
반복적으로 실행할 코드
</c:forEach>
=> step은 생략 시 기본값이 1

향상된 for문
<c: forEach var="변수명" items="순차적으로 접근할 배열명 또는 컬렉션명">
  반복적으로 실행할 코드 
<c:forEach>

var속성으로 선언된 변수에 접근할 때 반드시 EL구문으로 접근해야 함

<c:forEach var="i" begin="1" end="10">
    반복확인 : ${i } <br>
</c:forEach>

<br>

<!-- i+2 -->

<c:forEach var="i" begin="1" end="10" step="2">
    반복확인 : ${i } <br>
</c:forEach>

<c:forEach var="i" begin="1" end="6">
    <h${i}>태그안에도 반복 적용이 가능하다</h${i}>
</c:forEach>


<br>

<!-- 향상된 for문 -->
<c:set var="colors">
    green, blue, yellow, red, black, brown
</c:set>

color 값 : ${colors } <br>

<ul>
    <c:forEach var="c" items="${colors }">
    <li style="color:${c}">${c}</li>
    </c:forEach>
</ul>

- 이전에 실행했던 구문 EL구문을 이용해 다시 작성해보기

<c:forEach var="i" begin="1" end="10">
    반복확인 : ${i } <br>
</c:forEach>

<br>

<!-- i+2 -->

<c:forEach var="i" begin="1" end="10" step="2">
    반복확인 : ${i } <br>
</c:forEach>

<c:forEach var="i" begin="1" end="6">
    <h${i}>태그안에도 반복 적용이 가능하다</h${i}>
</c:forEach>


<br>

<!-- 향상된 for문 -->
<c:set var="colors">
    green, blue, yellow, red, black, brown
</c:set>

color 값 : ${colors } <br>

<ul>
    <c:forEach var="c" items="${colors }">
    <li style="color:${c}">${c}</li>
    </c:forEach>
</ul>

(5) 반복문 : forTokens 

[표현법]

<c:forTokens var="각 값을 보관할 변수명" items="분리시키고자하는 문자열" delims="구분자" >
반복적으로 실행할 구문(출력만)
</c:forToken>

- 구분자를 통해서 분리된 각각의 문자열에 순차적으로 접근하면서 반복수행
- JAVA의 split("구분자")또는 StringTokenizer와 비슷한 역할

 

● 테스트할 문자열 변수 만들기

<c:set var="dream" value="로또당첨, 집사기/퇴근하기-잠자기.주식대박"/>

<ul>
    <c:forTokens var="d" items="${dream }" delims=",/-.">
        <li>${d }</li>
    </c:forTokens>
</ul>

(6) 쿼리스트링 관련 태그

[표현법]
< c:url var="변수명" value="요청할url"/ >
    < c:param name="키값" value="밸류값"/ >
    < c:param name="키값" value="밸류값"/ >
    < c:param name="키값" value="밸류값"/ >
    < c:param name="키값" value="밸류값"/ > 
    ...     
</c:url >

- url경로를 생성하고, 쿼리스트링을 정의할 수 있는 태그 

- 기존방식

<a href="list.do?cPage=1&num=2">기존방식으로 요청</a>

- c:url방식

<c:url var="query" value="list.do">
    <c:param name="cPage" value="1"/>
    <c:param name="num" value="2"/>
</c:url>

<a href="${query }">c:url방식으로 요청</a>

2> JSTL Fomatting Library *알면 편할 수 있음

: 숫자, 날짜 및 시간 데이터의 출력형식을 지정할 때 사용하는 문법을 제공

<a href="02_fomatting.jsp">fomatting library</a>

<02_formatting.jsp>

1) formatNumber 태그

숫자형 데이터의 포맷(형식)을 지정
- 표현하고자 하는 수자 데이터의 형식을 통화기호, %등 원하는 쓰임에 맞게 지정하는 태그 

 

[표현법]
<fmt:formatNumber value="출력할값" groupingUsed="true/false" type="percent/currency" currencySymbol="$" />

(groupingUsed, type, currencySymbol은 생략 가능한 속성)

 

- 테스트할 변수 생성

더보기

*오류 참고

Unknown tag : 라이브러리 선언을 안해서 나는 오류(taglib지시어를 사용)
Missing end tag : 종료태그를 안 쓴 것

<c:set var="num1" value="123456789"/>
<c:set var="num2" value="0.56"/>
<c:set var="num3" value="60000"/>

출력해보면, 

num1의 경우 <br>
그냥 출력: ${num1 } <br>
세 자리마다 구분해서 출력 : <fmt:formatNumber value="${num1}"/>
숫자 그대로 출력 : <fmt:formatNumber value="${num1 }" groupingUsed="false"/>

num2의 경우 <br>
percent : <fmt:formatNumber value="${num2 }" type="percent"/> <br> <br>

* type="percent" : 소수점을 백분율로 변경해서 보여줌

num3의 경우  <br>
currency : <fmt:formatNumber value="${num3 }" type="currency" currencySymbol="$"/>

* type="currency" : 통화(돈) 단위로 보여짐 현재 내가 사용하고 있는 로컬운영체제의 정보에 따라서 단위가 정해짐
* curencySymbol="$" : 통화기호 문자의 종류를 지정하는 속성

 

 2) formatDate 태그

날짜 및 시간 데이터에 포맷(형식)을 지정
단, java.util.Date클래스의 객체를 이용해야만 한다. 

-  테스트할 변수 만들기

<c:set var="current" value="<%= new java.util.Date() %>"/>

current 그냥 출력 : ${current } <br>

<ul>
    <li>
        현재 날짜 : <fmt:formatDate value="${current }" type="date"/>
    </li>
    <li>
        현재 시간 : <fmt:formatDate value="${current }" type="time"/>
    </li>
    <li>
        날짜 및 시간 : <fmt:formatDate value="${current }" type="both"/>
    </li>
    <li>
        long: <fmt:formatDate value="${current }" type="both" dateStyle="long" timeStyle="long"/>
    </li>
    <li>
        full: <fmt:formatDate value="${current }" type="both" dateStyle="full" timeStyle="full"/>
    </li>
    <li>
        short : <fmt:formatDate value="${current }" type="both" dateStyle="short" timeStyle="short"/>
    </li>
    <li>
        customizing : <fmt:formatDate value="${current }" type="both" pattern="yyyy-MM-dd(E) a HH:mm:ss" />
    </li>
</ul>

* 날짜, 시간 형식 지정할 떄 고려할 점
반드시 dateStyle하고 timeStyle을 동일하게 맞출 필요가 X
- pattern속성을 이용해서 디테일하게 형식을 지정할 수 있다. 
yyyy: 4자리 년도
MM: 2자리 월수
dd: 2자리 일수

E:요일
a:오전/오후

HH:2자리 시간
mm:2자리 분
ss:2자리 초


3> JSTL Functions Library * 몰라도 무방

: EL구문 안에서 사용할 수 있는 메소드들을 제공

<a href="03_function.jsp">function library</a>

function 라이브러리는 따로 태그를 제공하는 형태는 아님 
EL구문 안에서 메소드를 호출하는 형태로 사용 
주로 문자열과 관련된 메소드를 제공
=> 주로 접두어 : 메소드명(인자값)형식으로 사용

<c:set var="str" value="How are you?"/>

str : ${str }<br>

문자열의 길이 : ${fn:length(str) }글자<br>
문자열의 길이 : ${str.length() }글자<br>

모두 대문자로 출력 : ${fn:toUpperCase(str) }<br>
모두 소문자로 출력 : ${fn:toLowerCase(str) }<br>

are의 시작 인덱스 : ${fn:indexOf(str,"are")}번째 <br>


<c:if test="${fn:contains(str, 'are')}">
    존재
</c:if>
<c:if test="${!fn:contains(str, 'are')}">
    존재 X
</c:if>