JSP&Servlet/BASIC

JSTL 과 EL 문법 사용하기.

유혁스쿨 2020. 8. 29. 01:05
728x90
반응형

 

JSTLEL 라이브러리 세팅

 

DynamicWebProject

구글에 톰캣 이라고 검색후 최상단에 뜨는 Apache Tomcat® - Welcome!링크를 눌른 후

우측의 메뉴바에서 Download탭의 Taglibs을 누릅니다.

 

https://tomcat.apache.org/download-taglibs.cgi

페이지의 하단에 JarFiles영역의 3번째 EL : taglibs-standard-jstlel-1.2.5.jar(pgp, sha512) 하이퍼링크를 누르고

다운받습니다.

 

다운로드 된 jar파일을 프로젝트의 lib폴더에 넣어줍니다

(그냥 다른폴더경로에 저장한 jar파일을 BuildPath를 한다면 깨질수있음. )

 

1번째 방법 프로젝트 우측마우스 클릭 - build path - addExtenerArchives...를 누른 후 프로젝트 lib폴더 경로에 찾아가 라이브러리를 선택 - 열기

2번째 방법 프로젝트 우측마우스클릭 - properties - javaBuildPath - Add JARs - 프로젝트 lib경로 - 라이브러리 선택 - ok - Apply

 

두 방법중 하나의 방법으로 추가하면 됩니다.

 

SpringLegacyProject

		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

스프링에서는 SpringLegacyProject를 만들면 기본적으로 의존 라이브러리를 다운받도록 설정하는 pom.xml에 jstl라이브러리 설정이 기본적으로 세팅되어있습니다.

만약 적용이 되지 않는다면 해당 소스를 xml에서 servlet 버전을 설정해주는 <!-- Servlet -->태그의 최 하단에 작성해 주시면 됩니다.

 


EL(ExpressionLanguage)

Expression Language 즉 표현언어는 외부 라이브러리가 필요 없습니다.

 

파일 JSP페이지에 사용되는 선언문(<%!%>), 스크립트릿(<%%>), 표현식(<%=%>)과 같은 자바 코드를 대신

표현 언어는 좀 더 쉽고 자연스러운 형태로 태그(주로 액션태그)의 속성 값을 지정하고 객체의 메소드에 지정하는 방법을 제공합니다.

표현 언어는 다른 형태의 스크립트 언어로서 표현식 <%= (스크립트릿) 보다 간결하고 편리하기 때문에 많이 사용합니다.

JSTL(Jsp Standard Tag Library) 1.0 jsp 표현 언어는 규약에 소개된 내용으로서 2.0 버전부터 표현 언어가 jsp에 포함되어 있습니다 .

jsp 표현 언어는 값을 출력 표현하는 데 사용하는 스크립트 언어로 jsp의 스크립트 요소를 보완하는 역할을 합니다.

JSP 표현 언어를 사용하면 JSP 표현식(스크립트릿)을 사용하는 것 보다 간결한 코드를 사용해서 값을 출력할 수 있습니다.

<%= m.getMem_id()%> 표현식 보다 ${m.mem_id} 표현 언어로 출력하면 코드가 더 간결하고 이해가 습니다.

이런 이유로 실제 프로젝트에서는 표현식보다 표현 언어를 더 많이 사용합니다. 앞으론 표현 언어를 줄여서 EL로 표시합니다.

EL 은 JSP 스크립트 요소 (표현식, 선언부, 스크립트 릿) 를 제외한 나머지 부분에서 사용할 수 있으며 EL 을 통해서 표현식보다 더 편리하게 값을 출력할 수 습니다

jsp 2.1 버전부터는 ${exr} 형식뿐만 아니라 #{exr} 구문을 새롭게 지원하고 있으며 거의 대부분 ${exr} EL 출력형태를 사용합니다.

EL 은 자료타입 수치연산자, 논리연산자, 비교연산자 등을 제공한다. EL 타입으로 TRUE OR FALSE 의 boolean 타입, 정수 타입, 실수 타입, 문자열 타입, 널 타입을 제공합니다.

수치연산자는 {+},{-} ,{*} , {/ 또는 div(나눗셈)} , {% 또는 mod( 나머지)} , {-(단항연산자:뺄셈)} 까지 총 6개를 제공합니다.

empty 연산자는 검사할 객체가 텅 빈 객체인지를 검사하기 위해 사용합니다.

삼항 조건 연산자

{'조건식' ? '값1' : '값2'} 조건식이 참이면 값 1을 실행시키고 거짓이면 값 2를 실행시켜라.

; 세미콜론 연산자

EL 3.0에서 추가된 연산자 입니다. ${A;B}를 사용하면 A값은 출력되지않고 B값만 출력됩니다.

할당 연산자

${val1 = 10}을 사용해서 EL변수 val1을 생성할 수 있습니다. 할당 연산자를 사용하면 그 자체도 출력결과를 생성한다는 점 입니다.

특수 문자 처리\

\${expr} 또는 \#{expr}하면 ${expr} 또는 #{expr}이 문자열로 출력됩니다.

EL 3.0부터는 web.xml 등에서 복잡한 과정을 설정할 필요 없이 바로 jsp에서 정적 메서드를 호출할 수 있습니다.

EL 3.0부터는 람다식도 지원합니다.

 

EL표현식의 비교/논리 연산자

비교연산자 종류

==

eq

같다

!=

ne

같지 않다

<

lt

~ 보다 작다

>

gt

~ 보다 크다

<=

le

~ 보다 작거나 같다

>=

ge

~ 보다 크거나 같다

논리연산자 종류

&&

and

논리곱

||

or

논리합

!

not

논리부정

 

EL표현식의 내장객체

 

내장 객체는 ${sessionScope.id}와 같이 표현식에서 사용가능합니다.

sessionScope

session 영역 객체

applicationScope

application 영역 객체

param

요청 파라미터 객체. 파라미터 값을 얻어낼 때 사용하는 것으로 request.getParameter()와 같은 역할을 수행

pageScope

page 영역 객체

requestScope

request 영역 객체

paramValues

요청 파라미터 컬렉션. 복수의 값을 갖는 파라미터로부터 값을 얻어낼 때 사용하는 것으로 request.getParameterValues()와 같은 역할을 수행

header

HTTP 요청 헤더 객체. 헤더 값을 얻어낼 때 사용하는 것으로 request.getHeader()와 같은 역할을 수행

headerValues

HTTP 요청 헤더 객체 컬렉션. 복수의 값을 갖는 헤더로부터 값을 얻어낼 때 사용는 것으로 request.getHeaders()와 같은 역할을 수행

cookie

모든 쿠키 값 컬렉션. 요청객체로부터 모든 쿠키값을 얻어낼 때 사용하는 것으로 request.getCookies()와 같은 역할을 수행

initParam

모든 애플리케이션의 초기화 파라미터 이름을 얻어내는 컬렉션. config.getInitParamer()와 같다.

pageContext

현재 JSP 페이지의 컨텍스트(Context). 주로 다른 내장 객체 servletContext, session, request, response를 구할 때 사용

 

 

정수형 : ${13} <hr /> <%-- ${갑}형태로 정수값을 출력합니다. --%>
실수형 : ${13.3} <hr />
문자열형 : ${'홍길동'} <hr />
논리형 : ${true} <hr />
null : ${null} <hr /> <%-- 표현언어는 자바와 다르게 null을 적용할 때 예외를 발생하지 않습니다.
					EL 표현언어는 MVC패턴 사이트 개발에서 뷰페이지 출력용도로 많이 활용됩니다. --%>
\${5+2} = ${5+2} <hr /> <%-- 덧셈한 7이 출력 --%>
\${5/2} = ${5/2} <hr /> <%-- EL로 나눗셈한 2.5가 출력됩니다. --%>
\${5 mod 2} = ${5 mod 2} <hr /> <%-- mod는 나머지 연산, 1이 출력  --%>

 

표현언어 닷(.) 연산자 사용법

우선 jsp페이지에서 ${} EL표현식으로 값을 받을수 있도록 값을 전송해주는 서블릿을 만듭니다.

@WebServlet("/el01") 
public class EL01Controller extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
		request.setAttribute("name", "이순신");
		//name키이름에 이순신값 저장
		RequestDispatcher el_forward = request.getRequestDispatcher("./EL_JSTL/EL_02.jsp");
		el_forward.forward(request, response); 
	}
}

 

requestScope : 표현언어 내장객체 JSP내장객체의 request에 해당합니다.

${requestScope.name}

서블릿에서 request.setAttribute("name",이순신) 으로 name키이름에 저장된 이순신 값을 가져와 출력합니다.

 

${requestScope.name}

으로 접근하면 null이 나옵니다. 이럴 때

 ${pageContext.request.name}

으로 접근해야 합니다.

 

${name}

서블릿 자바에서 request.setAttribute("name","이순신")에서 name키이름을 참조해서 이순신값을 가져와 출력합니다.

 

${param.id} <hr />

웹 브라우저 주소창에서 실행되는 매핑주소 값인 el_01?id=아이디로 노출되는 get으로 전달된 네임파라미터 이름 id에 실려온 아이디값을 가져와 EL로 출력합니다.

 

 

브라켓 연산자 ([])로 접근

${requestScope['name']} <br />
${param["id"]}<hr />

 

 

 

 

기본적으로 자바에서 A와 B 두 클래스가 있습니다.

두 클래스 B 클래스에서 A클래스의 필드에 접근하고자 할때, 접근하여 그 값을 가져오려 할때에는 A클래스의 객체 a를 생성하고 a.필드명 으로 해당 필드값을 얻어올 수 있습니다.

class A{
    String a1= "A클래스의 변수 a"
    private String a2;


}
public class B{
    A a = new A();
    String b = a.a1;
    Sytem.out.println(b);
}

 

 

하지만 만약 자바에서 어떤 객체가 있고 그 객체의 클래스에는 필드들이 캡슐화(private)가 되어있다는 가정을 합니다.

이때에 필드정보를 얻기위해서는 자바 코드에서는

class A{
    String a1= "A클래스의 변수 a"
    private String a2;

    public String getA2(){
        return a2;
    }
    public String setA2(String a2){
        this.a2=a2;
    }    
}
public class B{
    A a2 = new A();
    //String b = a.a2;
    String b = a.getA2();    
    Sytem.out.println(b);
}

객체명.getter()메서드를 통해 접근하여 필드의 값을 가져올 수 있습니다.

 

 

EL표현식또한 객체에 대한 필드정보를 똑같이 접근하면 됩니다.

public class UserVO {
	private String userId;
	private String userPw;
	private String userName;
	public String getUserId() {
		return userId;
	}
	public void setUserId(String userId) {
		this.userId = userId;
	}
	public String getUserPw() {
		return userPw;
	}
	public void setUserPw(String userPw) {
		this.userPw = userPw;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
}

접근하려는 필드가 존재하는 클래스의 객체명.getter()

 

 

먼저, 자바코드로 받는다면 어떻게될까요?

<body>
<%@page import="com.spring.web.model.UserVO"%>
<%@page import="javax.servlet.http.HttpServletRequest"%>

	<%
	UserVO user = (UserVO)request.getAttribute("user");
    out.println("# 아이디 : " + user.getUserId());
    out.println("# 비밀번호 : " + user.getUserPw());
    out.println("# 이름 : "+ user.getUserName());
    %>
</body>

 

컨트롤러로부터 받아야할 VO객체 와 request객체를 import로 선언해주셔야 합니다.

그리고 Model 객체로부터 addAttribute()로 넘겨받았았으므로 request.getAttribute()로 받아와야합니다.

(습관적으로 getParameter()로 받느라 코드 다 작성해두고 null값이 나와서 한 이십분쯤 해맸네요.)

받아온 후 UserVO 객체에 담아주시고 List형태로 빈클래스에 선언했기 때문에 get메서드로 받아옵니다!

 

 

다음은 EL표현식으로 코드해봅니다

<body>
	# 아이디 : ${user.getUserId()} <br />
	# 비밀번호 : ${user.getUserPw()}<br />
	# 이름 : ${user.getUserName()}{<br />
</body>

${객체명.getter()} 으로 접근하거나

 

 

아래와 같이

<body>
	#회원정보 : ${user} <br />
	# 아이디 : ${user.userId} <br />
	# 비밀번호 : ${user.userPw}<br />
	# 이름 : ${user.userName}<br />
</body>

${객체명.필드명} get메서드 대신 필드명만 선언해주는 방식으로 접근을 할 수 있습니다.

 

이때, "어? 근데 프라이빗인데 어떻게 참조할수 있는거지?" 라고 생각이 듭니다.

두번째 필드로 접근하는 방법은 사실은 해당 필드에 직접 접근하는것이 아니라 getter메서드가 갖고있는 필드명,

그 필드명을 적어주시면 getter()메서드가 작동하는것입니다.

public class UserVO {
	private String userId;
	private String userPw;
	private String userName;
	public String getUserId() {
	    System.out.println("getUserId() 호출");
		return userId;
	}
	public void setUserId(String userId) {
		this.userId = userId;
	}
	public String getUserPw() {
	    System.out.println("getUserPw() 호출");
		return userPw;
	}
	public void setUserPw(String userPw) {
		this.userPw = userPw;
	}
	public String getUserName() {
	    System.out.println("getUserName() 호출");
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
}

${EL}표현식에서 객체명.필드명 했을때 콘솔창에는 필드명과 일치한 getter메서드를 호출했다는 메서드가 출력됩니다 


왠지 필드명 자체가 캡슐화(private)가 되어있으므로 EL이 내부적으로는 필드에 접근했을때 
해당 필드를 초기화해주는 메서드에 접근하도록 설계되있지않을까 생각이듭니다.

 

 

+ ps) 음,, private를 지우고 public을 선언해줘도 get메서드를 삭제하면 작동이 안되는것을 볼수 잇습니다.

public class UserVO {
	public String userId;
	private String userPw;
	private String userName;
	
	public void setUserId(String userId) {
		this.userId = userId;
	}
	public String getUserPw() {
        System.out.println("getUserPw() 호출");
		return userPw;
	}
	public void setUserPw(String userPw) {
		this.userPw = userPw;
	}
	public String getUserName() {
    	System.out.println("getUserName() 호출");
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
}

userId를 public으로 지정해주고 get메서드를 없애면 오류가뜹니다.

만약 내부적으로 필드명을 초기화해주는 get메서드에 접근되는게 맞다면

이런 실험을 통해서 조건이 필드의 캡슐화(private) 때문은 아닌게 확인이 됩니다

 

사실상 내부적으로는 필드에 접근하도록 구조화 되있는건 맞지만 접근하기 위해서는 무조건 get메서드를 통해서 초기화가되기 때문에 내부적으로는 어!캡슐화되있네? 이게아니라 아 너 xx필드접근할려고? 그래 그럼 xx필드값을 초기화 해주는 getXx()으로 필드에 접근해~ 이렇게 작동되는거 일수도 있습니다.

만약 이것도아니라면 만약에 진짜로 이게 아니라면! 그냥 무조건 get방식으로 쓰게만든거에요.

분명 생성자와 객체접근방식으로도 접근할수있거든요?ㅋㅋㅋㅋ 근데 필드에 public선언하고 get메서드를 지웠는데도 get이 없다고 굳이 오류띄우면서까지 get으로만 필드에 접근되도록 해놓은거라면

웹이나 앱개발로 사용되는 스프링,다이나믹 이런게 내부적으로 VO클래스에 접근할때는 무조건 getter() setter()만 사용해서 접근하도록 기능이 구현되있는거 라고 생각하시면 맘이편하답니당~

 

이것은 또한, c:유즈빈 태그에서의 set/getPropery 혹은 스프링 의존성주입에서

set메서드를를통한 의존성 주입의 property옵션과 매우 유사합니다.

 

주의할 점은 접근하려는 객체의 클래스에 getter()메서드가 존재하지 않는다면 돌아가지 않습니다.

또한 필드명이 아닌 getter메서드의 이름이 기준이된다는 사실입니다.

만약 메서드명이 EL로 참조할때의 메서드의 이름과 다르다면 PropertyNotFoundExceptiond을 발생시킵니다.

 

정확하게는 getter()메서드가 존재하지 않거나 참조하는 이름이 메서드의 이름과 다르다면 실행되지 않습니다.

필드명이 아닌 getter메서드의 이름이 기준이 됩니다.

 

 

+추가로 getter()를 부르는 방법이 하나 더 있습니다.

바로 브라켓연산자를 사용하는 방법 입니다.

<body>
	#회원정보 : ${user} <br />
	# 아이디 : ${user.["userId"]} <br />
	# 비밀번호 : ${user.["userPw"]}<br />
	# 이름 : ${user.["userName"]}<br />
</body>

브라켓 연산자 안에 접근하고자하는 필드명을 적으신다면 해당필드명의 getter가 호출되어 필드에 접근하게됩니다.

 

 

이번엔 EL표현식으로 이전 컨트롤러에서 특정 객체를 통한 attribute("user",user) 메서드로 넘겨받은 user라는 데이터값을 출력합니다.

<body>
	#회원정보 : ${user} <br />
</body>

 

뷰페이지에는 해쉬값이 출력되버립니다.

 

<body>
<%@page import="com.spring.web.model.UserVO"%>
<%@page import="javax.servlet.http.HttpServletRequest"%>

	<%
	out.println("#회원정보 : " + user);
    %>
</body>

 

자바에서는 이렇게 객체를 출력하면 참조되는 레퍼런스 주소를 뿜어댑니다.

이것과 같이 user는 단순한 객체이기 때문에 뷰페이지에서는 레퍼런스 주소를 뿜게됩다.

 

 

El로 객체를 통으로 지정한다면 해쉬값이 나오게됩니다

UserVO클래스에 toString()메서드 재정의를 해주면 각 요소들을 toString으로 출력시켜줄수있도록 도와줍니다

public class UserVO {
	private String userId;
	private String userPw;
	private String userName;
	@Override/
	public String toString() {
		return "UserVO [userId=" + userId + ", userPw=" + userPw + ", userName=" + userName + ", hobby=" + hobby + "]";
	}
}

 

UserVO 클래스에 이렇게 toString()메서를 오버라이딩 하게 되면 해당 객체의 각 필드정보들을 한번에 모아서 출력시킬수 있습니다.

오브젝트가 전달한, 상속으로 내려준 toString을 오버라이딩해 주면 해쉬값이 안나오고 필드정보들이 나오기 때문입니다.


JSTL(JSP Standart Tag Library)

 

1. jsp는 <jsp:include>와 같은 태그를 개발자가 추가할 수 있는 기능을 제공하는데 이를 사용자 정의 즉 커스텀 태그라고 합니다.

커스텀 태그 중에서 많이 사용되는 것을 모아서 JSTL(Jsp Standard Tag Library)이라는 표준태그를 만들었습니다.

이 표준 태그 라이브러리를 사용하면 스크립트릿 코드의 사용을 줄이면서 더욱 간결하고 이해하기 쉬운 JSP코드를 작성할 수 있습니다.

 

2.JSP는 스크립트릿과 표현식 등의 스크립트 코드와 html 코드가 섞여 있어면 알아보기가 쉽지 않습니다. 즉 가독성이 나빠집니다.

 

3.JSTL 태그의 종류

 

라이브러리

주요기능

접두어

관련 uri

코어

변수지원,흐름제어

URL처리

c

http://java.sun.com/jsp/jstl/core

XML

XML 코어,흐름제어

XML 변환

x

http://java.sun.com/jsp/jstl/xml

국제화

지역, 메시지 형식

숫자 및 날짜 형식

fmt

http://java.sun.com/jsp/jstl/fmt

데이터베이스

SQL

sql

http://java.sun.com/jsp/jstl/sql

함수

컬렉션 처리

String 처리

fn

http://java.sun.com/jsp/jstl/functions

  •  

4.JSTL Core 태그

기능 분류

태그

설명

변수 지원

set

jstl 변수 설정.변수를 만듬

remove

설정한 변수 제거

흐름제어

if

조건에 따라 내부 코드 수행

choose

다중 조건을 처리할 때 사용

forEach

컬렉션,배열,Map의 자료를 처리할 때 사용

forTokens

구분자로 분리된 각각의 토큰문자열을 처리할 때 사용. 즉 문자열 파싱을 한다.

url 처리

import

url을 사용하여 다른 자원의 결과를 삽입한다.

redirect

지정한 경로로 이동한다.

url

url을 재작성한다.

기타태그


 

catch

예외 처리

out

내용을 출력한다.

param

파라미터 설정

 

5.c:forEach 반복문 태그의 속성 설명

속성명

표현식/EL

타입

설명

var

사용불가

String

몸체에서 사용할 EL 변수이름

items

사용 가능

컬렉션,배열,

Map,

Iterator,

Enumeration

반복 처리할 데이터

begin

사용가능

int

시작 인덱스 값

end

사용가능

int

끝 인덱스 값

step

사용가능

int

인덱스 증분값

 

6.JSTL fmt 태그 특징

 

# 가.

국제화 태그는 특정 지역에 따라 알맞은 메시지를 출력해야 할 때 사용합니다.

예를 들어, 한글 브라우저에서 접속하면 한글 메시지를 출력하고, 영문 브라우저에서 접속하면 영문 메시지를 출력할 때 국제화 태그를 사용합니다.

# 나.

이런 기능을 제공하기 위해 언어마다 별도의 jsp페이지를 작성해야 한다면 개발자는 똑같은 jsp 페이지를 복사하고 수정하느라 시간을 다 보내게 될 것입니다.

jstl은 이런 중복 작업을 덜고 하나의 JSP 페이지에서 다양한 언 어에 맞는 메시지를 출력할 수 있도록 해주는 태그를 제공한다.

# 다.

날짜와 시간에는 시간대라는 것이 존재합니다. 한국 시간과 미국 LA의 시간은 차이가 나며, 시간대별로 권역을 묶어 같은 시간을 사용하고 있습니다.

시간대별로 시간을 처리할 수 있는 기능을 제공하는데 이때 사용되는 태그가 바로 <fmt:timeZone> 태그와<fmt:setTimeZone> 태그입니다.

 

JSTL(JSP Standard Tag Library) 은 표준 커스텀 태그(Custom Tag) 입니다

커스텀 태그 : 사용자 정의 태그

JSTL은 JSP 페이지의 로직을 담당하는 부분인 제어문 및 데이터베이스 처리 등을 표준 커스텀 태그로 제공합니다.

 

코드를 깔끔하게 하고 가독성을 좋게 합니다.

JSTL은 많은 태그를 제공하며, 이들을 사용하기 위해 각각 네임스페이스로 라이브러리를 제공합니다.

Core(코어), XML, I18N(국제화, 포매팅), SQL(데이터베이스), Functions(함수)

 

라이브러리들은 URI로 제공되며 이들을 사용할 때는 접두어(prefix)를 사용합니다

JSTL 라이브러리에서 제공하는 태그를 사용합니다

 

taglib 디렉티브에 사용할 라이브러리의 prefix 속성과 uri 속성에 해당하는 값을 기술하여야 합니다.

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

 

라이브러리 : ⓒore(코어)

URI : http://java.sun.com/jsp/jstl/core

Prefix : c

제공 기능

- 변수의 선언 및 삭제 등의 변수와 관련된 작업

- if, for문 등과 같은 제어문

- URL처리 및 그밖에 예외처리 및 화면에 출력

 

 

JSTL 예제코드

 

1

<%@ page contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
// JSTL 코어 태그립 추가 --%>
이름 : <c:out value="${'홍길동' }"/> <hr />
// c:out 태그는 JSTL에서 출력해준다.
이름 : ${'홍길동'} <hr /> // EL 표현언어로 홍길동을 출력한다.

 

2

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%-- prefix = "접두어" --%>
<c:set var="msg" value="${'hello'}"/> //c:set JSTL태그로 msg변수에 'hello'문자열저장 
<c:set var="age">${27}</c:set> //c:set 쌍태그로 age변수에 정수값 27을 저장 
${msg} <hr />
//EL로 변수값 출력 
나이:${msg} <hr />

<c:remove var="age"/> //age변수 제거 
age변수 제거하고 값 출력 : ${age} <hr />

<c:catch var="errmsg"> // c:catch jstl태그는 예외처리하고 예외 처리 메시지를 errmsg변수에 저장 
    예외 발생전 <hr />
    <%=10/0 %> //숫자를 0으로 나누면 예외가 발생
</c:catch>
예외 발생=${errmsg}<hr />

 

 

3

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="fruit" value="${param.name}"></c:set>
/*param.name은 JSTL_03.jsp?name=값 주소창에 노출되는 get방식으로 
name파라미터 이름에 담겨져서 전달된 값을 받아서 fruit변수에 저장 */
파라미터name에 실려온 값 :
<c:if test="${!empty fruit }">//<%--fruit변수값이 비어있지 않다면 참 --%>
    ${fruit}
</c:if>
//c:else문이 없다.
<hr />
<c:choose>//다중조건문
	<c:when test="${fruit == 'grape'}"> //fruit변수가 grape와 같다면
	    ${fruit} : 포도	//url에 name=grape로 입력 했을때 포도를 출력한다..
	</c:when>
	<c:when test="${fruit == 'apple'}">
	    ${fruit} : 사과
	</c:when>
	    <c:otherwise> 해당 조건이 없을때 실행 </c:otherwise>
	    //<c:otherwise> switch case문에서 default문과 역할이 같다. 
</c:choose>

 

4

@WebServlet("/foreach")
public class ForEachController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {

		int[] score= {100,90,100};
		request.setAttribute("score", score); 	
		RequestDispatcher forForward = request.getRequestDispatcher("./EL_JSTL/JSTL_05.jsp");
		forForward.forward(request, response);

	}
}
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
score배열 원소값 :
<c:forEach var="a" items="${score}">
/* items속성값의 EL ${score}에서 score는 ForEachController.java에서 저장된 키이름이다.
 이 이름을 참조해서 배열원소값을 가져와서 a변수에 저장한다. */
    ${a}&nbsp; // &nbsp;은 한칸 빈공백을 띄우라는 특수문자 
    <c:set var="total" value="${total+a}"></c:set>
</c:forEach> //<c:forEach> 가 JSTL의 반복문 --%>
<hr />
score배열원소 누적합=${total} <hr />
/*문제) JSTL c:forEach반복문을 사용하여 1부터 10까지 자연수 중에서 홀수값만 출력해보고
 홀수 누적합을 JSTL변수 sum에 저장한 다음 출력한다. */
<c:forEach var="num" begin="1" end="10" step="2">//1부터 10까지 자연수를 2씩 증가한다.
    홀수 : ${num}
    <c:set var="sum" value="${sum+num}" />
</c:forEach>
<hr />

홀수 누적합 = ${sum} <hr />

 

5

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
String phone="010-777-9999";
request.setAttribute("phone", phone);
%>
분리된 폰 번호 : 
<c:forTokens var="p" items="${phone}" delims="-">
/* 폰번호를 -기호 기준으로 분리한다.
분리된 폰번호를 토큰 문자열이라고 한다.
이러한 경우를 문자열 파싱이라고 한다.
동일기능 자바클래스 java.util.StringTokenizer api이다.
주로 회원관리에서 정보수정에 활용되는 경우가 발생한다. */
    ${p} <hr />

6

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:import url="http://localhost:8081/MVC/EL_JSTL/name.jsp" var="test"/>
//url주소를 읽어들여서 출력결과값을 test변수에 저장 
    ${test}

 

7

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<c:url var="test" value="ji.jpg"/>
// test변수에 ji.jpg를 저장 

<h2>${test}</h2>
<img src="${test}" width="250" height="200" alt="지리산 계곡" />

 

8

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<c:redirect url="http://www.naver.com" />
// JSTL c:redirect 태그는 지정한 곳으로 이동시켜준다. 

 

 

 

 

 

JSTL과 EL활용

 

먼저 스크립트 릿을 활용하여 간단하게 자바코드로 받아오는법을 보겠습니다.

<body>
<%@page import="com.spring.web.model.UserVO"%>
<%@page import="javax.servlet.http.HttpServletRequest"%>
	# 취미 :
	<%
	UserVO user = (UserVO)request.getAttribute("user");
        out.println(user.getHobby());
    %>
</body>
user.getHobby()

 getHobby()메서드는 체크된 요소들을 List형태로 담고있는 List<String> hobby 를 가리키고 있습니다.

public List<String> getHobby() { return hobby; }

제네릭으로 String 타입을 반환받는 List인 List<String> 를 반환하므로 List 제네릭 타입입니다.

 

 

다음은 EL표현식입니다.

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <body>
	    # 취미 : ${user.getHobby()}<br />
    </body>
</html>

코드라인이 확 줄었죠?

hobby의 return Type은 List입니다. 이렇게 출력도 가능하지만 이렇게 출력한다면 리스트의형태인 대괄호[]에 묶여서 출력됩니다.

선택된 요소를 하나씩 빼서 반복문으로 처리해야하면 리스트의 형태가 아닌 요소 하나하나가 출력됩니다.

 

 

만약 <%%>스크립트릿을 사용해서 자바코드로 구현해 보겠습니다.

(코딩 초보라... 쉬운 코드지만 구현하는데 꽤 시간을 잡아먹었네요.... 뻘짓입니다..)

<body>
<%@page import="com.spring.web.model.UserVO"%>
<%@page import="javax.servlet.http.HttpServletRequest"%>

	# 취미 :
	<%
	UserVO user = (UserVO)request.getAttribute("user");
    if(user.getHobby() != null) {
	    	for(String h:user.getHobby()) {
		        out.println(h);
		    }
	    }
	    else if(user.getHobby() == null) {
		    out.println("선택된 취미가 없습니다!");
	    }
    %>
</body>

반환타입이 List의 형태인 user.getHobby()가 만약 비어있지않다면 향상된 for문으로 리스트에 담겨있는 문자열을 String h 변수에 하나씩 담아서 출력해줍니다.

 

 

이것을 JSTL과 EL을 활용하여 구현해보겠습니다.

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

	# 취미 :
	<c:if test="${user.hobby.size() !=0 }"> 
	    <c:forEach var="h" items="${user.hobby}">
	        ${h}&nbsp; 
	    </c:forEach>
	</c:if>
	<c:if test="${empty user.hobby}">
	    <c:forEach var="h" items="${user.hobby}"> 
	         선택한 취미가 없습니다! &nbsp;
	    </c:forEach>
	</c:if>
	<br />
	</p>
</body>
</html>

코드라인에서 확연한 차이없군요? 그렇다면 왜쓰는걸까요? 이유는 마지막에 설명드리고, 코드를 분석해보겠습니다.

 

 

우선 JSTL 코어태그립 (C) 문법을 사용하기위해서는 jsp파일 최 상단에 uri를 선언해줘야합니다

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

 

JSTL 코어태그립을 사용할때 절대적으로 필요한 코드입니다. (없으면 정상작동 되지 않습니다.)

 

 

 

자바코드에서 if 조건문과 같은 역할을 해주는 태그인 <c:if> 태그 입니다.

	<c:if test="${user.hobby.size() !=0 }"> </c:if>

 

test속성에 조건을 담습니다.

현재 조건은 EL표현식으로 비교연산자를 사용하였습니다

만약 user.hobby의 크기가 0이 아니라면 즉, user.getHobby()를 하여 List객체의 크기가 0이 아니라면 체크박스에 체크가 된것입니다.

 

자바코드에서 확장 for 반복문과 같은 기능을 해주는 태그인 <c:forEach> 태그 입니다.

<c:forEach var="h" items="${user.hobby}"> </c:forEach>

 

var 속성에는 반복해서 담을 변수를 지정합니다.

item 속성에는 반복해서 꺼낼 대상이 되는 배열, 객체 혹은 리스트를 넣습니다.

item속성에 선언된 객체에서 반복해서 var변수 로 꺼내옵니다

 

여기서 저는 이렇게 햇갈린적이 있었습니다.

음... 객체상태인건데... 만약 하나를빼고 다시 처음으로 돌아간다면 뺀 값이 객체에 그대로 저장되있지 않나?

그럼 같은값을 또 뽑아낼수도 있는거 아니야?

바보같고 어이가 없으실수 있습니다.(웃어주세요 하하하)

사실 저는 생각이 좀 많이 짧습니다.

상식적으로 객체나 배열 혹은 List 안에 저장된 값을 '반복문' 을 통해 빼낸다면

반복문이라는 자체가 순차적으로 정해진 범위만큼 끝까지 딱 한사이클만 돕니다.

한 사이클은 반복문을 한번 실행했을때 조건이 끝날때까지이기 때문에 한 사이클에서 한번 빼낸 사용된 데이터는 해당 대상에서 제외가 됩니다. (데이터는 살아있으나 반복문을 돌리는 시점에서 중복으로 추출하지않음 인덱스 형식의 반복문을 생각해보기.)

 

우리가 코드상에서는 <c:if> 반복태그를 두번을 선언했습니다.

만약 자바코드처럼 if else처리를 하기위해서는 c:choose c:when c:otherwise를 쓸수있으나 더 복잡해지기 때문에 가독성적인 측면에서도 <c:if>태그를 두번 써주는방법이 오히려 더 편할수있습니다.

또 , 만약 user.hobby가 반복되는게 맘에안든다면 <c:set> 태로 user.hobby를 var속성에 변수로 지정하실 수 있습니다.

 

 

${el} EL표현식만 활용했을때는 분명 코드라인이 줄어들거나 가독성이 높은 장점이 있습니다.

하지만 JSTL c:코어태그립을 추가로 사용하는 이유는 코드라인과 가독성 보다는 프론트엔드와 겹치지않기위해 사용하는것 입니다

스크립트릿으로 자바코드로 표현할수있지만 이때는 코드의 일관성도 없고, html과 섞였을때 블록태그 하나 막으려고 또 스크립트릿을 열어야합니다.

코드의 구조적 특징이나 프론트엔드와 협업할때 실수로 코드가 지워질수 있기 때문에 방지하기 위해서 html과 일관성을 유지하기위해 자바코드를 html처럼쓰는것이 jstl 코어태그립 방법 입니다.

 

728x90
반응형