병갈이 블록

EL(Expression Language)-표현언어. 본문

IT(Old)/JSP 공부 기록

EL(Expression Language)-표현언어.

woojang 2017. 6. 27. 18:45

표현언어 표기방법.

${ 식 } : 선언과 동시에 변수에 값이 대입됨. (추후 변경된 변수값으로 출력 불가.)

#{ 식 } : 선언에는 대입식으로 초기화. 실제 변수 접근시 그때마다 값을 대입시켜서 사용.(추후 변경된 변수값을 출력). (JSP 2.1부터)

 

특징.

- JSP의 네가지 기본객체의 속성 사용가능.

- 수치, 관계, 논리 연산자 제공.

- 자바 클래스 메서드 호출.

- 람다식 이용한 함수정의.

- 스트림 API를 통한 컬렉션 처리.

- 정적 메서드 실행.

 

구성.

- 액션태그, 커스텀 태그, 비스크립트 요소부분에서 값을 출력하기 위해 사용. (스크립트릿, 표현식, 선언부를 제외한 모든곳에서 사용.)

- #{}은 Deferred Expression이라 부른다. 즉, 바로 값이 생성되지 않기에 텍스트 템플릿에서 사용하면 에러 발생.(쉽게말해 일반 문자출력용으로 사용한다면)

이 표현식은 Deferred Expression을 허용한ㄴ 태그의 속성에만 위치할 수 있다.

 


 

EL 기본객체

 기본 객체

 설명 

pageContext 

 JSP의 pageContext와 동일

 pageScope 

 pageContext 기본객체에 저장된 속성의 <속성, 값> 매핑을 저장한 Map객체.

 requestScope 

 request 기본객체에 저장된 속성의 <속성, 값> 매핑을 저장한 Map객체.

 sessionScope 

 session 기본객체에 저장된 속성의 <속성, 값> 매핑을 저장한 Map객체.

 applicationScope 

 application 기본객체에 저장된 속성의 <속성, 값> 매핑을 저장한 Map객체.

 기본객체 없이 이름만 지정하면($) 위에서 부터 차례대로 기본객체에 name속성이 있는지 검사및 확인을 하고 존제하는 객체의 값을 사용. 

   param 

 요청파라미터의 <파라미터이름, 값> 매핑을 저장한 Map객체. request.getParameter("이름")의 결과와 동일.

   paramValues 

 요청파라미터의 <파라미터이름, 값 배열> 매핑을 저장한 Map객체. request.getParameterValues("이름")과 동일.

   header 

 요청헤더의 <헤더이름, 값>매핑을 저장한 Map객체. request.getHeader("이름")과 동일.

   headerValues 

 요청헤더의 <헤더이름, 값 배열>매핑을 저장한 Map객체. request.getHeaders("이름")과 동일.

 cookie 

 <쿠키이름, Cookie> 매핑을 저장한 Map객체.

 initParam 

 초기화 파라미터의 <이름, 값> 매핑을 저장한 Map객체. application.getInitParameter("이름")과 동일.

<이름, 값>으로 이루어진 객체의 경우...

"값"에 접근하는 방법.

- 식 : ${객체.이름} => "값" 을 출력한다. ( 객체.이름 == 객체[이름] 동일. )

but, cookie의 경우...<이름, 객체>이기 때문에 '객체.이름'으로만 식을 만들경우 '객체'주소를 출력한다.

그렇기때문에 '객체.이름.속성이름'까지 식에 적어야 쿠키의 속성값을 출력한다.

 

how? EL 기본객체가 값에 접근을 하는가...

A.B.C.... 이 있다고 볼때...두개씩 끊어서 본다. 앞에것을 표현1, 뒤에것을 표현2로 두고 보자.

1. '표현1'을 '값1'로 바꾼다. '값1'이 null이면 null을 반환, null이 아니면 '표현2'를 '값2'로 바꾼다.

2. '값2'가 null이면 null반환하고 하니면 아래 규칙으로 검사를 한다.

1). '값1'이 Map, List, 배열인 경우...

a. Map인 경우.

- 값1.containsKey(값2)가 false이면 null을, 아니라면 값1.get(값2)의 결과를 리턴한다.

b. List, 배열일 경우.

- '값2'가 정수인지 검사.(정수가 아니면 error발생)

- 값1.get(값2) or Array.get(값1, 값2)의 결과를 리턴.

- 예외 발생시 에러발생.

2). '값1'이 다른 객체이면..(Map, List, 배열이 아니면..)

a. '값2'를 문자열로 반환

b. '값1'객체가 '값2'의 프로퍼티를 가지고 있다면 프로퍼티의 값을 리턴.(get이겠져.)

c. 아니면 에러발생.

 


 

연산자.

1. 수치 연산자.

: +, -, *, /(div), %(mod), -단항연산자.

a. "+" 연산자는 기본적으로 숫자에만 적용된다. 

   (java처럼 "문자"+"이름" = "문자이름"과 같이 문자열을 이어주는 기능은 없다. +연산자와 문자열이 만나면 에러 발생. 문자열 연결은 "+="연산자 사용.)

b. A와 B를 연산할 때...둘 중 표현영역이 큰 값의 자료형으로 자동 형변환한다.

실수연산 => Big자료형이 있으면 BigDecimal로 변환. Big자료형이 없으면 Double로 변환. 

정수연산 => Big자료형이 있으면 BigInteger로 변환. 없으면 Long으로 변환.

 


 

컬렉션 사용.

(** 값을 숫자로 하려면 ""없이 입력. 값을 문자열로 입력하려면 ""안에 값을 입력.)

* EL 2.2에서는 컬렉션을 위한 표현방식을 미지원.

* EL 2.2에서 List 객체를 생성하기 위한 코드.

<% List<자료형> values = Arrays.asList(값1, 값2, 값3, ... ); %> //List객체 생성.

<c:set var="vals" value="<%=values%>" /> //val변수에 List객체 대입. 

: 기본적으로 스크릿트립을 이용해야된다. 

: <c:set>을 이용하기 위해선 JSTL라이브러리를 WEB-INF/lib 폴더에 복사해야한다.

* EL 3.0에선 직접 객체구현이 가능.

- List 

_선언시 : [값0, 값1, 값2, ... ] 중괄호 사용. ->${[값0, 값1]}

_사용시 : 변수[번호]로 값 호출.(배열처럼 0이 첫번째 값)

- Map 

_선언시 : {'키1' : 값1 , '키2' : 값2 , ...} 대괄호 사용. - '키'와 '값'은 :로 구분하고 한 쌍.(키, 값)은 ,로 구분. 

_사용시 : ${ 변수이름.키이름 } 으로 사용.

- Set

_선언시 : {값1, 값2, 값3, ... } 대괄호 사용.

_사용시 : $ 

- Map과 List의 혼합.

_선언시 : [ {'code' : '1234', 'name' : 'Haha' }, { 'code' : '4567' , 'name' : 'Nuga'} ]형태로 List의 원소로 Map의 객체를 둔다.

_사용시 : ${ 변수이름[1].code }, ${ 변수이름[0].name }

 

할당.

EL 2.2까지는 변수를 생성하기 위해 아래 두가지 방법을 사용해야 한다.

1. <% request.setAttribute("변수이름", ""); %>

2. <c:set var="변수이름" value="${""}" />

EL 3.0부터는 변수에 값을 할당하는 할당 연산자를 제공한다.

${ 변수이름 = 값 }

단, 이 식은 '값' 출력을 동반한다. 출력을 제외시키려면 식 뒤에 세미콜론과 ''(그냥 따옴표 두개. 빈 문자열)를 입력한다.

${ 변수이름 = 값; ''} <= 이렇게 입력하면 변수생성및 초기화가 이루어지고 빈 문자열('')이 출력되어서 결과적으로 값 출력은 되지 않는다.

 


 

EL에서 객체의 매서드 호출하기.

1. 사용할 자바코드가 입력된 자바파일을 WEB-INF/src/페키지이름/자바파일.java 경로로 저장하고 WEB-INF/src/페키지이름/ 위치에 컴파일해서 클래스 생성.

2. JSP페이지에서 java class를 import한다. (%@ page import="packname.javaFile" %>)

3. 스크릿트립에서 기본객체에 임포트한 클래스의 변수를 생성하고 setAttribute를 이용하여 값에 변수를 할당한다.

<%    javaFile javafile = new javaFile();    기본객체.setAttribute("ttt", javafile);    %>

4. 이제 EL에서 "ttt"라는 변수의 이름으로 자바클래스에 정의된 함수를 호출할 수 있다.

${ ttt.getYourName("you") }    // getYourName(String name)이라는 함수가 정의되어 있다고 했을 경우...

 

EL에서 정적 메서드 사용하기.

메서드 사용하기위한 방법. 2가지.

1. EL의 함수로 지정. ( TLD파일 작성 -> web.xml에 TLD내용 추가 -> EL에서 사용.)

1) TLD 파일 등록. 파일은 WEB-INF/tlds/이름.tld 로 저장한다.

: 하나의 함수는 하나의 <function>태그로 정의한다.

: 사용할 함수의 이름을 정의한다.

: 실제 함수가 정의되어 있는 클래스 전체이름을 등록.(페키지이름.파일이름)

: 실제 사용할 클래스 내 함수의 정보를 등록한다. -> 반환형 함수이름(매개변수1의 자료형, 매개변수2의 자료형, ... )

- 클래스에 정의된 함수의 반환형이 기본자료형이 아니면 전체경로를 입력.(String이면 java.lang.String 으로 입력.)

- 클래스에 정의된 함수의 이름.

- 클래스에 정의된 함수에 들어갈 매개변수의 자료형이 기본자료형이 아니면 전체경로 입력. 단, 변수의 이름은 입력하지 않는다.

2) web.xml에 TLD파일의 정보 등록.

: <jsp-config>하래 <tlib>태그에 등록.

: <tlib-uri>와 <tlib-location>을 등록. 둘 다 루트로 부터 파일 위치의 경로를 등록한다.

3) EL에서 사용하기.

<%@ taglib prefix="pre" uri="TLD파일경로" %> // taglib 디렉티브로 prefix를 등록한다. (원하는 이름으로...)

${pre:functionName(arg1, arg2, ...) }    // 등록한 prefix를 이용하여 TLD에 등록한 함수의 이름을 이용하여 클래스 함수를 사용.

**상당히 복잡하다......ㅜㅜ

포인트!!!!

- TLD파일에 내가 사용하려는 클래스의 함수를 새로운 이름(실제 EL에서 사용할 이름)으로 등록을 한다.

- 실제 사용하려는 클래스의 함수를 부를 새로운 이름을 등록한 정보가 담긴 TLD파일을 web.xml파일에 등록해서 초기화때 관련정보가 등록되게 한다.

- 이제 내가 사용할 함수의 닉네임이 실제함수이름과 연결되어 있으니 EL을 통해서 닉네임을 사용한다.

- 이 방법은 EL 2.0부터 지원하는 기능이다.

 

2. EL 3.0부터 사용가능한 새로운 방법.

1) <%@ page import="페키지이름.클래스이름" %>으로 컴파일한 클래스파일을 임포트한다.

2) EL에서 클래스이름을 직접 사용하여 실제 함수에 접근한다. 

${ ClassName.functionname(arg1, arg2, ... ) } => page 디렉티브에서 임포트한 클래스파일의 이름을 직접 사용하여 클래스 내 함수를 사용한다.

 

- 매우 간단하다...........

 


 

람다식(EL 3.0부터 지원)

java의 람다식을 그대로 사용할 수 있다.

1. 람다식의 예 

: (파라미터1, 파라미터2, ... ) -> EL식 (**파라미터가 1개이면 괄호를 생략해도 된다.**)

: ex> (a, b) -> a > b ? true : false 

2. 실제 사용.

1) 변수에 할당

${ greaterThan = (a, b) -> a > b ? true : false ; '' } // 세미콜론과 공백을 추가하지 않으면 결과(여기선 객체의 이름)가 출력된다.

${ greaterThan(15, 20) } => 15 > 20 ? true : false 의 식이 연산을 하고 그 결과를 반환한다. 이 식에서는 false를 반환한다.

2) 변수에 할당 없이 바로 사용.

(람다식)(식에 넣을 값들..)

${ ((a, b) -> a > b ? true : false)(15, 20) } 위와 같은 결과가 나온다.

** 람다식은 재귀호출도 가능하다.

 


 

스트림 API 사용하기.

기본 형태.

: 컬렉션.stream().map([람다식]).toList() 

- .stream() : 컬렉션에서 스트림객체를 생성해서 중간연산 및 최종연산이 가능하게 한다.

- .map([람다식]) : 위에서 생성된 스트림 객체를 이용하여 map함수를 수행하는 중간연산구간이다. 함수에서 수행할 내용을 람다식으로 입력이 가능하다.

- .toList() : 최종연산구간이고 여기에서는 toList를 사용했기 때문에 중간연산의 결과를 List객체로 반환하는 연산을 한다.

- 중간연산은 여러번 수행가능하다. 스트림생성 -- 최종연산 사이에 필요한 만큼 사용이 가능.

 

1. stream을 이용한 스트림 생성.

- Map 타입을 제외한 모든 컬렉션에서 stream()을 사용할 수 있다.

- Map타입에서는 entrySet()메서드를 사용하여 컬렉션 타입 객체를 생성한 다음 stream()메서드를 사용할 수 있다.

=> Map.entrySet().stream()....

2. 중간연산.

1) filter() : 특정 조건에 맞는 데이터만을 생성. 파라미터의 결과가 true인 원소만을 제공.(*true, false를 반환하는 람다식을 파라미터로 갖는다. )

- ex> .filter( X -> X*3 == 15 ) 

2) map() : 새로운 스트림을 생성. 람다식의 파라미터를 가지고 식이 있다면, 각 원소의 연산의 결과가 적용된 새로운 스트림을 생성한다.

- 변수의 특정 속성값으로만 이루어진 스트림 생성이 가능하다. (회원목록에서 회원의 나이만 가진 스트림, 혹은 회원이 이름만 가진 스트림 등으로 사용 가능)

- 필터와 함께 사용해서 특정한 조건에 부합하는 정보만을 가져올 수 있다.

- ex> .map( mem -> mem.age )    //mem이라는 회원정보가 든 클래스의 변수에서 나이만 가진 스트림을 만들기 위해 age속성값을 리턴하는 람다식.

3) sorted() : 기본적으로 오름차순정렬을 하는 함수.

- 기본적으로 Comparable인터페이스가 구현되어 있는 클래스에 한해서 동작한다.

- Comparable 인터페이스가 구현되어있지 않거나, 오름차순이 아닌 다른 방식의 정렬을 원한다면 '람다식'을 파라미터로 전달한다.

ex> .sorted((a,b) -> a.age.compareTo(b.age) ) || .sorted((a,b) -> a>b ? 1 : -1 ) //둘다 정렬을 위한 기준값(a가 작으면 +값, 크면 -값, 같으면 0을 반환)

내림차순으로 정렬하고 싶다면 값의 크기에 따른 반환값을 오름차순의 반대로 지정.

4) limit([n]) : 앞에서 생성된 스트림 중 상위 n개의 스트림만 생성.

5) toList(), toArray() 

- toList() : java 리스트객체를 생성. 각 속성의 값을 문자열로 변환 후 출력한다.

- toArray() : java 배열객체를 생성. 각 속성의 값을 출력하지 않고 배열객체의 문자열표현을 출력한다.(값이 아니다.) 어따쓰는지는 아직.....

6) count() : 원소의 개수를 리턴한다. (Long형)

7) Optional 타입 : 결과값이 존재하지 않을수도 있는 연산의 결과.

- 결과값이 Optional타입으로 생각될 경우 아래 4가지 메서드를 사용할 수 있다.

 get()

 값이 존재하면 해당값을 리턴. 없으면 예외발생(ELException)

 orElse(other)

 값이 존재하면 해당값을 리턴. 없으면 other을 리턴.

 orElseGet( () -> T )

 값이 존재하면 해당값을 리턴. 없으면 람다식 T를 실행한 결과를 리턴. 

 ifPresent( (x) -> (S) )

 값이 존재하면 해당하는 값을 람다식의 파라미터로 전달하고 람다식 S을 실행한 결과를 리턴.

8) sum(), average() : 숫자로된 스트림의 원소들을 모두 더하거나 평균값을 반환. 

- average()는 Optional타입을 반환한다. 되도록이면 get를 제외한 다른 3가지 함수를 사용하도록 한다. 

9) min(), max() : 최소, 최대값을 구하는 함수. 

- 스트림의 원소가 Comparable을 구현하고 있다면 사용하능하다. 아니라면 람다식을 파라미터로 이용할 수 있다. Optional타입을 반환한다.

10) anyMatch(), allMatch(), noneMatch() : Boolean을 반환하는 람다식을 조건식으로 사용가능.

- anyMatch() : 한 원소라도 조건에 부합하면 true를 리턴. (하나라도 맞으면)

- allMatch() : 모든 원소가 조건에 부합할때 true를 리턴. (모두 맞아야)

- nonMatch() : 한 원소라도 조건에 부합하지 않으면 true를 리턴. (하나라도 틀리면)

 


 

표현언어 비활성.

1. web.xml파일에 비활성화 옵션 지정.

2. JSP페이지에 비활성화 옵션 지정.

3. web.xml파일을 서블릿 2.3 or 2.4버전에 맞게 작성.

 

1. 두가지 모두 비활성 혹은 하나만 비활성

$, # 두가지 모두 비활성 : <jsp-config>아래 <jsp-property-group>아래 <el-ignored>true</el-ignored>를 삽입.

#만 비활성 : 위에 코드가 삽입된 상태에서 <jsp-config>아래 새로운 <jsp-property-group>아래 

<deferred-syntax-allowed-as-literal>true</deferred-syntax-allowed-as-literal>를 삽입한다.

2. page디렉티브의 속성

- isELIgnored : true이면 EL을 일반 문자열로 처리.

- deferredSyntaxAllowedAsLiteral : true일 경우 #{형식만 비활성화(문자열처리)한다.

ex> <%@ page isELIgnored="true" %>    // ${ 와 #{ 모두 문자열 철.

<%@ page deferredSyntaxAllowedAsLiteral="true" %>    // #{ 만 문자열처리

3. 서블릿 버전 변경.

- 2.3 : EL 미지원. (JSP 1.2 사용)

"http://java.sun.com/dtd/web-app_2_3.dtd"

- 2.4 : #{ 만 미지원

... xmlns="http://java.sun.com/xml/nsj2ee"

... xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version"2.4">

- 2.5 이상(3.0, 3.1) : 둘다 지원

 

우선순위.

xml및 page설정이 둘다 되어있지 않다면. => 서블릇 버전에 따라...

둘중 하나라도 설정이 되어 있다면... => page 디렉티브가 우선된다.(즉, page디렉티브가 설정되어 있지 않으면 xml설정에 따른다.)

그냥 1, 2번 중에 하나로....

 

 

 

'IT(Old) > JSP 공부 기록' 카테고리의 다른 글

MySQL  (0) 2017.06.30
JSTL 사용시 URI오류 해결...  (0) 2017.06.28
세션.  (0) 2017.06.22
쿠키 - 2  (0) 2017.06.22
쿠키.  (0) 2017.06.22
Comments