사실, 자바를 하다보면 이상하게 'java.io'패키지에 대한 막연한 두려움(?)이 있었는데요.

왠지 봐도봐도 머리에 안들어갔었다는.. ㅎㅎ

 

 각설하고^^, 이번글에서는  'java.io' 패키지에 속하는 'File' 클래스에 대해서 알아볼까 합니다.

우선, 'File' 클래스는 다음과 같은 역할을 한다고 볼 수 있겠습니다.

 

파일에 대해서 직접 읽고 쓰는 입·출력 기능이 아닌, 파일과 관련된 기능을 다음과 같이 제공합니다.

1. 빈 파일 및 디렉토리의 생성

2. 파일과 폴더의 삭제

3. 파일 이름의 확인

4. 파일 이름의 변경

5. 파일의 경로 확인

6. 파일의 접근 권한(실행, 쓰기, 읽기) 확인 및 설정

 등등


다음에서 생성자와 메소드를 확인하실 수 있습니다.       

 출저 : http://xrath.com/javase/ko/6/docs/ko/api/index.html 


우선, File에 접근을 할려면, File 객체를 생성해야 합니다.

 위에서 확인 가능한 생성자를 사용해서 파일 객체를 만든후 파일의 정보를 확인해 보겠습니다.

 

import java.io.File;

 

public class Test {

 public static void main(String[] args){

  File test= new File("c:");
  System.out.println("다음은 c드라이브에 있는 폴더와 파일의 목록입니다.");
  if(test.exists()){                                 //  파일이나 경로가 존재하는지 확인합니다.
   if (test.isDirectory()) {                      //  현재 객체가 디렉토리(폴더)인지 확인합니다.
    String[] testList =  test.list();          //  현재 디렉토리에 있는 하위의 디렉토리와 파일을 문자열 배열로 반환합니다.  
    for(int i =0; i < testList.length; i++){   //  만들어진 List를 반복문을 통해 나열합니다.
     System.out.print(testList[i] +"\t");
     if(i%3==0)
      System.out.println();
    }
   }else{System.out.println("폴더가 아닙니다.");}
  }else{
   System.out.println("폴더가 존재하지 않습니다.");
  }
 
  System.out.println("\n다음은 c:에 위치한 test.txt 파일의 정보입니다.");
  File test2 = new File("C:\\test.txt");  // 경로를 적을시 \\ 를 통해 \가 입력되도록 합니다.(주의)
  if(test2.exists()){
   if (test2.isFile()) {
    System.out.println("현재 파일의 경로 :"+ test2.getParent());
    System.out.println("현재 파일의 절대 경로 : "+ test2.getAbsolutePath());
    System.out.println("현재 파일명 : "+ test2.getName());
   }
  }else{
   System.out.println("폴더가 존재하지 않습니다.");
  }
 }

}

 

 꼭, java.io 패키지를 import 해야 합니다. 다음과 같이 선택할 수 있겠습니다.

1. import java.io.*;

2. import java.io.File;

 

다른 메소드도 많으니 위의 API를 참고하시고, 한번 사용해보세요 ^^


출처 - http://runtoyourdream.tistory.com/225


===================================================================================


boolean() :: 읽기가능 true
boolean canWrite() :: 파일 쓰기 가능하면 true
boolean delete() :: 파일 삭제후 true반환. 삭제안되면 false.
boolean equals(Object obj) :: 현재의 객체와 obj로 지정된 객체가 같은 파일을 가지면 true
boolean exists() :: 파일 존재하면 true
String getAbsolutePath() :: 파일에 대한 절대 경로 반환
String getCanonicalPath() :: 파일에 대한 정규 경로 반환
String getParent() :: 부모 디렉토리 이름 반환
String getName() :: 파일 이름 반환
String getPath() :: 파일의 경로 반환
boolean isAbsolute() :: 경로가 절대경로이면 true
boolean isDirectory() :: 디렉토리이면 true
boolean isFile() :: 현재의 객체가 파일이면 true
long lastModified() :: 마지막으로 수정된 날짜 반환
long length() :: 파일의 바이트 수 반환
String[] list() :: 지정된 디렉토리에 있는 파일과 디렉토리를 문자열 배열로 반환
boolean mkdir() :: 디렉토리 생성. 생성되면 true
boolean mkdirs() :: 디렉토리 생성. 경로로지정된 디렉토리 미존재시 생성후 디렉토리생성
boolean renameTo(File newName) :: 파일이나 디렉토리의 이름을 변경 true




===================================================================================





Posted by linuxism
,


Java에서 Xml파일 읽는 예제 샘플 소스입니다.

구글 검색해보면 많이 나오겠지만, 2주에 걸쳐 두가지 샘플을 올려보도록 하겠습니다.

그 첫번째 입니다.


addressbook.xml

<?xml version="1.0" encoding="utf-8" ?>
<addressbook>
	<person>
		<name>이XX</name>
		<tel>010-1245-1234</tel>
		<address>서울</address>
	</person>
	<person>
		<name>김XX</name>
		<tel>010-1245-1234</tel>
		<address>경기</address>
	</person>
</addressbook>

위와 같이 xml은 태그 형식으로만 되어 있는 간단한 형식입니다.


그다음은 자바 코드입니다.

Java샘플 코드(XmlReaderExample.java)

import java.io.File;
 
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
 
public class XmlReaderExample {
 
	public static void main(String argv[]) {
 
		try {
			File file = new File("./addressbook.xml");
			DocumentBuilderFactory docBuildFact = DocumentBuilderFactory.newInstance();
			DocumentBuilder docBuild = docBuildFact.newDocumentBuilder();
			Document doc = docBuild.parse(file);
			doc.getDocumentElement().normalize();
 
			System.out.println("Root element : " + doc.getDocumentElement().getNodeName());
			System.out.println();
 
			// person엘리먼트 리스트
			NodeList personlist = doc.getElementsByTagName("person");
 
			for (int i = 0; i < personlist.getLength(); i++) {
 
				System.out.println("---------- personNode "+ i + "번째 ------------------");
 
				Node personNode = personlist.item(i);
 
				if (personNode.getNodeType() == Node.ELEMENT_NODE) {
					// person엘리먼트 
					Element personElmnt = (Element) personNode;
 
					// name 태그
					NodeList nameList= personElmnt.getElementsByTagName("name");
					Element nameElmnt = (Element) nameList.item(0);
					Node name = nameElmnt.getFirstChild();
					System.out.println("name    : " + name.getNodeValue());
 
					// tel 태그
					NodeList telList= personElmnt.getElementsByTagName("tel");
					Element telElmnt = (Element) telList.item(0);
					Node tel = telElmnt.getFirstChild();
					System.out.println("tel     : " + tel.getNodeValue());
 
					// address 태그
					NodeList addressList= personElmnt.getElementsByTagName("address");
					Element addressElmnt = (Element) addressList.item(0);
					Node address = addressElmnt.getFirstChild();
					System.out.println("address : " + address.getNodeValue());
				}
 
				System.out.println("---------------------------------------------");
				System.out.println();
			}
 
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}


저도 처음에 다른 xml샘플 소스를 봤을땐 이게 뭔가 싶었는데....

이것만 봤을때는 좀 이해가 잘 가지 않았습니다.

근데 이게 젤 쉬운 샘플 코드입니다. ^^;

조금 설명 하자면...

personlist는 태그가 person이라는 태그로 시작해서 끝나는 person태그의 리스트를 말합니다.

person태그 안에는 다시 name태그, tel태그, adress태그가 들어있어서 그것들을 빼내오는 겁니다.

정말, 간단하죠.... ^^;



실행결과는 다음과 같습니다.

Root element : addressbook

---------- personNode 0번째 ------------------
name    : 이XX
tel     : 010-1245-1234
address : 서울
---------------------------------------------

---------- personNode 1번째 ------------------
name    : 김XX
tel     : 010-1245-1234
address : 경기
---------------------------------------------


다음 시간에는 조금 다른 케이스의 xml로 해보겠습니다.

감사합니다.





저번 시같에 xml파일 읽기를 해봤습니다.

이번 시간은 저번과 좀 다른 xml을 가지고 샘플을 만들어 봤습니다.


xml은 다음과 같습니다. (comboBox.xml)

<?xml version="1.0" encoding="utf-8" ?>
<combolist>
	<comboBox name="sex">
		<option value="1"></option>
		<option value="2"></option>
	</comboBox>
	<comboBox name="hobby">
		<option value="1">음악감상</option>
		<option value="2">영화보기</option>
		<option value="3">축구</option>
		<option value="4">야구</option>
		<option value="5">골프</option>
		<option value="6">기타</option>
	</comboBox>
</combolist>

저번 시간의 xml과 틀린점은 

저번시간 xml에는 태그만 있었지만, 위xml에는 태그안에 속성이 들어 있는게 틀린점입니다.

comboBox name과 option value가 속성입니다.


그럼, Java소스 코드를 보겠습니다.

import java.io.File;
 
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
 
public class XmlReaderExample2 {
 
	public static void main(String argv[]) {
 
		try {
			File file = new File("./comboBox.xml");
			DocumentBuilderFactory docBuildFact = DocumentBuilderFactory.newInstance();
			DocumentBuilder docBuild = docBuildFact.newDocumentBuilder();
			Document doc = docBuild.parse(file);
			doc.getDocumentElement().normalize();
 
			System.out.println("Root element : " + doc.getDocumentElement().getNodeName());
			System.out.println();
 
			// comboBox엘리먼트 리스트
			NodeList comboBoxlist = doc.getElementsByTagName("comboBox");
 
			for (int i = 0; i < comboBoxlist.getLength(); i++) {
 
				System.out.println("---------- comboBoxNode "+ i + "번째 ------------------");
 
				Node comboBoxNode = comboBoxlist.item(i);
 
				if (comboBoxNode.getNodeType() == Node.ELEMENT_NODE) {
					// comboBox엘리먼트 
					Element comboBoxElmnt = (Element) comboBoxNode;
 
					// 콤보박스 명
					System.out.println("comboBox name : " + comboBoxElmnt.getAttribute("name"));
 
					// option 태그
					NodeList optList= comboBoxElmnt.getElementsByTagName("option");
					for (int j = 0; j < optList.getLength(); j++) {
						Element optElmnt = (Element) optList.item(j);
						Node name = optElmnt.getFirstChild();
						System.out.println("option : " + name.getNodeValue() + "   value : " +optElmnt.getAttribute("value"));
					}
 
				}
 
				System.out.println("---------------------------------------------");
				System.out.println();
			}
 
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

Java코드도 저번시간과 거의 비슷하지만,  속성값을 취득하는  comboBoxElmnt.getAttribute("name"),  optElmnt.getAttribute("value"부분이 추가 되었습니다.


실행결과는 다음과 같습니다.

[실행결과]

Root element : combolist

---------- comboBoxNode 0번째 ------------------
comboBox name : sex
option : 남   value : 1
option : 여   value : 2
---------------------------------------------

---------- comboBoxNode 1번째 ------------------
comboBox name : hobby
option : 음악감상   value : 1
option : 영화보기   value : 2
option : 축구   value : 3
option : 야구   value : 4
option : 골프   value : 5
option : 기타   value : 6
---------------------------------------------


저번 시간의 Java샘플과 이번 시간의 Java샘플 두개를 비교 해보면서 해보시면 쉽게 할 수 있을꺼라 생각됩니다.

저만 그렇게 생각 하는 건가요? ^^;


감사합니다.



Posted by linuxism
,


: SpEL의 [] 연산자는 java.util.Porperties 컬렉션에서 값을 조회하는데에도 사용할 수 있다.

 

아래의 예를 보자.

<util:properties id="profileProps" location="classpath:/profile/local/properties/local.properties"/>

 

위와 같이 프로퍼티 설정파일을 로드한다고 했을때, SpEL을 이용하여 Map 멤버에 액세스하는 동일한 방법으로 해당 파일의 프로퍼티를 액세스할 수 있다.

 

아래의 예와 같이 위 profileProps 빈의 프로퍼티 속성에 접근할 수 있다.

<!-- oracle  -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
        <property name="driverClass" value="#{profileProps['Globals.DriverClass']}"/>
        <property name="url" value="#{profileProps['Globals.Url']}"/>
        <property name="username" value="#{profileProps['Globals.UserName']}"/>
        <property name="password" value="#{profileProps['Globals.Password']}"/>
    </bean>

--> 위의 예는 프로퍼티 파일에 설정된 데이터베이스의 DataSource 설정값을 SpEL을 이용해서 설정하는 예이다.

위의 예에서 SpEL을 이용해서 profileProps 빈, 즉 프로퍼티 파일의 Globals.DriverClass 키의 값에 액세스하는것을 볼 수 있다.

 

 

 

 아래와 같이 변수에 직접 프로퍼티파일내의 값을 DI 할수도 있다.

@Value("#{profileProps['Globals.DriverClass']}"

private String driverClass;



또는 아래와 같이 Properties 타입의 레퍼런스 변수로 값을 DI 할 수도 있다.

@Value("#{profileProps}")

priavte Properties profileProps;



출처 - http://cafe.daum.net/ITVillage/Pgbk/11?docid=1DpW4Pgbk1120120503115030






이 문서는 개인적인 목적이나 배포하기 위해서 복사할 수 있다. 출력물이든 디지털 문서든 각 복사본에 어떤 비용도 청구할 수 없고 모든 복사본에는 이 카피라이트 문구가 있어야 한다.



7.5 언어 레퍼런스

7.5.1 리터럴 표현식
지 원하는 리터럴 표현식의 타입은 문자열, 날짜, 숫자값(int, real, hex), 불리언, null이다. 문자열은 따옴표로 구분된다. 문자열내에 따옴표를 사용하려면 2개의 따옴표를 사용해라. 다음 예제에서 리터럴의 사용방법을 간단히 보여준다. 보통은 이 예제처럼 단독적으로 쓰이지 않고 더 복잡한 표현식의 일부로써 사용한다. 예를 들면 논리적인 비교연산의 한쪽부분에 리터럴을 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
ExpressionParser parser = new SpelExpressionParser();
 
// "Hello World"로 평가된다
String helloWorld = (String) parser.parseExpression("'Hello World'").getValue();
 
double avogadrosNumber  = (Double) parser.parseExpression("6.0221415E+23").getValue(); 
 
// 2147483647로 평가된다
int maxValue = (Integer) parser.parseExpression("0x7FFFFFFF").getValue(); 
 
boolean trueValue = (Boolean) parser.parseExpression("true").getValue();
 
Object nullValue = parser.parseExpression("null").getValue();

숫자는 음수기호, 지수표시, 소수점을 지원한다. 기본적으로 실제 숫자는 Double.parseDouble()로 파싱한다.


7.5.2 프로퍼티, 배열, 리스트, 맵, 인덱서
프 로퍼티 참조를 탐색하는 것은 쉬운데 그냥 중첩된 프로퍼티 값을 가리키는 마침표를 사용해라. Inventor 클래스의 pupin과 tesla 인스턴스에는 예제에 사용한 클래스들 섹션에 나온 데이터들이 있다. 다음의 표현식을 사용해서 Tesla가 태어난 해솨 Pupin이 태어난 도시를 탐색한다.
1
2
3
4
// 1856으로 평가된다.
int year = (Integer) parser.parseExpression("Birthdate.Year + 1900").getValue(context);
 
String city = (String) parser.parseExpression("placeOfBirth.City").getValue(context);

프로퍼티명의 첫글자는 대소문자를 구별하지 않는다. 배열과 리스트의 내용은 대괄호를 사용해서 획득한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ExpressionParser parser = new SpelExpressionParser();
 
// 발명품 배열
StandardEvaluationContext teslaContext = new StandardEvaluationContext(tesla);
 
// "Induction motor"로 평가된다.
String invention = parser.parseExpression("inventions[3]").getValue(teslaContext, String.class);
 
// 회원 리스트
StandardEvaluationContext societyContext = new StandardEvaluationContext(ieee);
 
// "Nikola Tesla"로 평가된다.
String name = parser.parseExpression("Members[0].Name").getValue(societyContext, String.class);
 
// 리스트와 배열 탐색
// "Wireless communication"로 평가된다.
String invention = parser.parseExpression("Members[0].Inventions[6]").getValue(societyContext, String.class);

대괄호로 키값 리터럴을 지정해서 맵의 내용을 획득한다. 아래 예제의 경우 Officers 맵의 키가 문자열이므로 문자열 리터럴을 지정할 수 있다.
1
2
3
4
5
6
7
8
// Officer의 딕션어리
Inventor pupin = parser.parseExpression("Officers['president']").getValue(societyContext, Inventor.class);
 
// "Idvor"로 평가된다
String city = parser.parseExpression("Officers['president'].PlaceOfBirth.City").getValue(societyContext, String.class);
 
// 값을 설정한다
parser.parseExpression("Officers['advisors'][0].PlaceOfBirth.Country").setValue(societyContext, "Croatia");


7.5.3 인라인 리스트
리스트는 {} 표시법을 사용한 표현식으로 직접 나타낼 수 있다. 
1
2
3
4
// 4개의 숫자를 담고 있는 자바 리스트로 평가된다
List numbers = (List) parser.parseExpression("{1,2,3,4}").getValue(context);
 
List listOfLists = (List) parser.parseExpression("{{'a','b'},{'x','y'}}").getValue(context);

단독으로 {}를 사용하면 비어있는 리스트를 의미한다. 성능때문에 리스트 자체가 고정된 리터럴로 구성되어 있다면 각 평가마다 새로운 리스트를 만드는 것이 아니라 표현식을 나타내는 변하지 않는 리스트를 생성한다.

7.5.4 배열 생성
배열은 자바문법과 유사하게 만들 수 있고 선택적으로 생성시에 존재해야 하는 배열을 갖는 initializer를 제공할 수 있다. 
1
2
3
4
5
6
7
int[] numbers1 = (int[]) parser.parseExpression("new int[4]").getValue(context);
 
// initializer가진 배열
int[] numbers2 = (int[]) parser.parseExpression("new int[]{1,2,3}").getValue(context);
 
// 다차원 배열
int[][] numbers3 = (int[][]) parser.parseExpression("new int[4][5]").getValue(context);

현재는 다차원 배열을 생성할 때 initializer를 제공할 수 없다.

7.5.5 메서드
메서드는 전형적인 자바 프로그래밍 문법을 사용해서 호출한다. 리터럴에서 메서드를 호출할 수도 있다. 가변인자(Varargs)도 지원한다.
1
2
3
4
5
// 문자열 리터럴, "bc"로 평가된다
String c = parser.parseExpression("'abc'.substring(2, 3)").getValue(String.class);
 
// true로 평가된다.
boolean isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue(societyContext, Boolean.class);


7.5.6 연산자(Operators)

7.5.6.1 관계 연산자
표준 연산자 표기법을 사용해서 같다, 같지 않다, 작다, 작거나 같다, 크다, 크거나 같다 등의 관계 연산자를 지원한다.
1
2
3
4
5
6
7
8
// true로 평가된다
boolean trueValue = parser.parseExpression("2 == 2").getValue(Boolean.class);
 
// false로 평가된다
boolean falseValue = parser.parseExpression("2 < -5.0").getValue(Boolean.class);
 
// true로 평가된다
boolean trueValue = parser.parseExpression("'black' < 'block'").getValue(Boolean.class);

표준 관계 연산자뿐만 아니라 SpEL은 'matches' 연산자에 기반한 정규표현식과 'instanceof'를 지원한다.
1
2
3
4
5
6
7
8
// false로 평가된다
boolean falseValue = parser.parseExpression("'xyz' instanceof T(int)").getValue(Boolean.class);
 
// true로 평가된다
boolean trueValue = parser.parseExpression("'5.00' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
 
// false로 평가된다
boolean falseValue = parser.parseExpression("'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);

각 심볼릭 연산자는 순수하게 연문자로 지정할 수도 있다. 표현식을 내장하는 문서형식에서(예를 들면 XML 문서) 특별한 의미를 가지는 기호를 사용할 때 발생할 수 있는 문제를 피하기 위해서 사용한다. 문자표현은 다음과 같다. lt ('<'), gt ('>'), le ('<='), ge ('>='), eq ('=='), ne ('!='), div ('/'), mod ('%'), not ('!'). 대소문자는 구별하지 않는다.

7.5.6.2 논리 연산자
and, or, not 같은 논리 연산자를 지원한다. 사용방법은 다음 예제에 나온다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// -- AND --
 
// false로 평가된다
boolean falseValue = parser.parseExpression("true and false").getValue(Boolean.class);
 
// true로 평가된다
String expression =  "isMember('Nikola Tesla') and isMember('Mihajlo Pupin')";
boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);
 
// -- OR --
 
// true로 평가된다
boolean trueValue = parser.parseExpression("true or false").getValue(Boolean.class);
 
// true로 평가된다
String expression =  "isMember('Nikola Tesla') or isMember('Albert Einstien')";
boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);
 
// -- NOT --
 
// false로 평가된다
boolean falseValue = parser.parseExpression("!true").getValue(Boolean.class);
 
// -- AND and NOT --
String expression =  "isMember('Nikola Tesla') and !isMember('Mihajlo Pupin')";
boolean falseValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);


7.5.6.3 수식 연산자
더 하기 연산자를 숫자, 문자열 날짜에서 사용할 수 있다. 빼기는 숫자와 날짜에서 사용할 수 있다. 곱하기와 나누기는 숫자에서만 사용할 수 있다. 다른 수식 연산자로 계수(%)와 지수(^)를 지원한다. 표준 연산자를 우선적으로 처리한다. 이러한 연산자는 다음 예제에서 보여준다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 더하기
int two = parser.parseExpression("1 + 1").getValue(Integer.class); // 2
 
String testString = parser.parseExpression("'test' + ' ' + 'string'").getValue(String.class);  // 'test string'
 
// 빼기
int four =  parser.parseExpression("1 - -3").getValue(Integer.class); // 4
 
double d = parser.parseExpression("1000.00 - 1e4").getValue(Double.class); // -9000
 
// 곱하기
int six =  parser.parseExpression("-2 * -3").getValue(Integer.class); // 6
 
double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class); // 24.0
 
// 나누기
int minusTwo =  parser.parseExpression("6 / -3").getValue(Integer.class); // -2
 
double one = parser.parseExpression("8.0 / 4e0 / 2").getValue(Double.class); // 1.0
 
// 계수(Modulus)
int three =  parser.parseExpression("7 % 4").getValue(Integer.class); // 3
 
int one = parser.parseExpression("8 / 5 % 2").getValue(Integer.class); // 1
 
// 연산자 우선순위
int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class); // -21


7.5.7 할당
할당 연산자를 사용해서 프로퍼티를 설정한다. 이는 보통 setValue 호출내에서 이뤄지지만 getValue호출내에서도 이뤄질 수 있다.
1
2
3
4
5
6
7
Inventor inventor = new Inventor();       
StandardEvaluationContext inventorContext = new StandardEvaluationContext(inventor);
 
parser.parseExpression("Name").setValue(inventorContext, "Alexander Seovic2");
 
// 대신에
String aleks = parser.parseExpression("Name = 'Alexandar Seovic'").getValue(inventorContext, String.class);


7.5.8 타입
특 수한 'T' 연산자를 java.lang.Class ('type')의 인스턴스를 지정하는 데 사용할 수 있다. 정적 메서드도 이 연산자를 사용해서 호출한다. StandardEvaluationContext는 타입을 찾으려고 TypeLocator를 사용하고 StandardTypeLocator(교체할 수 있다)는 java.lang 패키지로 만들어진다. 즉, java.lang 내에서 타입을 참조하는 T()는 정규화될 필요는 없지만 다른 모든 타입참조는 정규화되어야 한다.
1
2
3
4
5
6
7
Class dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class.class);
 
Class stringClass = parser.parseExpression("T(String)").getValue(Class.class);
 
boolean
 trueValue = parser.parseExpression("T(java.math.RoundingMode).CEILING
< T(java.math.RoundingMode).FLOOR").getValue(Boolean.class);


7.5.9 생성자
생성자는 새로운 연산자를 사용해서 호출할 수 있다. 프리미티브 타입과 String 외에는(int, float등이 사용될 수 있는) 모두 정규화된 클래스명을 사용해야 한다.
1
2
3
4
5
6
Inventor einstein = p.parseExpression("new org.spring.samples.spel.inventor.Inventor('Albert Einstein', 'German')")
                                                                   .getValue(Inventor.class);
 
//리스트의 add 메서드내에서 새로운 inventor 인스턴스를 생성한다
p.parseExpression("Members.add(new org.spring.samples.spel.inventor.Inventor('Albert Einstein', 'German'))")
                                                                   .getValue(societyContext);


7.5.10 변수
#변수명 문법을 사용해서 표현식내에서 변수를 참조할 수 있다. StandardEvaluationContext에서 setVariable 메서드를 사용해서 변수를 설정한다.
1
2
3
4
5
6
7
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
StandardEvaluationContext context = new StandardEvaluationContext(tesla);
context.setVariable("newName", "Mike Tesla");
 
parser.parseExpression("Name = #newName").getValue(context);
 
System.out.println(tesla.getName()) // "Mike Tesla"


7.5.10.1 #this와 #root 변수
#this 변수는 항상 정의되어 있고 현재 평가객체를(정규화되지 않은 참조를 처리하는 것에 대비해서) 참조한다. #root변수도 항상 정의되어 있고 루트 컨텍스트 객체를 참조한다. #this가 평가되는 표현식 컴포넌트에 따라 다양하지만 #root는 항상 루트를 참조한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// create an array of integers
List<Integer> primes = new ArrayList<Integer>();
primes.addAll(Arrays.asList(2,3,5,7,11,13,17));
 
// 파서를 생성하고 'primes' 변수를 정수 배열로 설정한다
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setVariable("primes",primes);
 
// 리스트에서 10보다 큰 모든 소수(?{...} 선택을 사용)
// [11, 13, 17]로 평가된다
List<Integer>
 primesGreaterThanTen = (List<Integer>)
parser.parseExpression("#primes.?[#this>10]").getValue(context);


7.5.11 함수
표현식 문자열내에서 호출할 수 있는 사용자 정의 함수를 등록해서 SpEL을 확장할 수 있다. 사용자 정의 함수는 메서드를 사용해서 StandardEvaluationContext에 등록한다.
1
public void registerFunction(String name, Method m)

자바 메서드에 대한 참조는 함수의 구현체를 제공한다. 예를 들어 다음에서 문자열을 뒤집는 유틸리티 메서드를 보여준다.
1
2
3
4
5
6
7
8
9
10
public abstract class StringUtils {
 
  public static String reverseString(String input) {
    StringBuilder backwards = new StringBuilder();
    for (int i = 0; i < input.length(); i++)
      backwards.append(input.charAt(input.length() - 1 - i));
    }
    return backwards.toString();
  }
}

이 메서드를 평가 컨텍스트에 등록하고 표현식 문자열내에서 사용할 수 있다.
1
2
3
4
5
6
7
8
9
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
 
context.registerFunction("reverseString",
                         StringUtils.class.getDeclaredMethod("reverseString",
                                                             new Class[] { String.class }));
 
String helloWorldReversed =
          parser.parseExpression("#reverseString('hello')").getValue(context, String.class);


7.5.12 빈(Bean) 참조
평가 컨텍스트가 빈 리졸버로 설정되었다면 (@) 기호를 사용해서 표현식에서 빈을 검색하는 것이 가능하다. 
1
2
3
4
5
6
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setBeanResolver(new MyBeanResolver());
 
// 평가하는 동안 MyBeanResolver에서 resolve(context,"foo")를 호출할 것이다
Object bean = parser.parseExpression("@foo").getValue(context);


7.5.13 3항 연산자 (If-Then-Else)
표현식에서 if-then-else 조건을 위해 3항 연산자를 사용할 수 있다. 다음은 간단한 예제다.
1
String falseString = parser.parseExpression("false ? 'trueExp' : 'falseExp'").getValue(String.class);

이 경우에 false 불리언값으로 'falseExp' 문자열값을 리턴한다. 다음은 좀 더 실제적인 예제다.
1
2
3
4
5
6
7
8
9
parser.parseExpression("Name").setValue(societyContext, "IEEE");
societyContext.setVariable("queryName", "Nikola Tesla");
 
expression = "isMember(#queryName)? #queryName + ' is a member of the ' " +
             "+ Name + ' Society' : #queryName + ' is not a member of the ' + Name + ' Society'";
 
String queryResultString =
                    parser.parseExpression(expression).getValue(societyContext, String.class);
// queryResultString = "Nikola Tesla is a member of the IEEE Society"

3항 연산자의 더 간단한 문법은 다은 섹션의 엘비스 연산자를 봐라.

7.5.14 엘비스(Elvis) 연산자
엘비스 연산자는 3항 연산자 문법의 단축형으로 Groovy 언어에서 사용된다. 보통 3항 연산자에서는 변수를 두번 반복해야 한다. 예를 들면 다음과 같다.
1
2
String name = "Elvis Presley";
String displayName = name != null ? name : "Unknown";

대신에 엘비스의 헤어스타일과 유사한 엘비스 연산자를 사용할 수 있다.
1
2
3
4
5
ExpressionParser parser = new SpelExpressionParser();
 
String name = parser.parseExpression("null?:'Unknown'").getValue(String.class);
 
System.out.println(name);  // 'Unknown'

좀 더 복잡한 예제를 보자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
ExpressionParser parser = new SpelExpressionParser();
 
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
StandardEvaluationContext context = new StandardEvaluationContext(tesla);
 
String name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, String.class);
 
System.out.println(name); // Mike Tesla
 
tesla.setName(null);
 
name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, String.class);
 
System.out.println(name); // Elvis Presley


7.5.15 안전한 탐색(Navigation) 연산자
안 전한 탐색 연산자는 NullPointerException를 피하기 위해 사용하고 Groovy 언어에서 가져왔다. 보통 객체를 참조할 때 메서드에 접근하거나 객체의 프로퍼티에 접근할 때 null이 아닌지 확인해야 한다. 이 작업을 하지 않기 위해 안전한 탐색 연산자는 예외를 던지는 대신에 null을 반환한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ExpressionParser parser = new SpelExpressionParser();
 
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan"));
 
StandardEvaluationContext context = new StandardEvaluationContext(tesla);
 
String city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, String.class);
System.out.println(city); // Smiljan
 
tesla.setPlaceOfBirth(null);
 
city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, String.class);
 
System.out.println(city); // null - NullPointerException을 던지지 않는다!!!
Note
엘비스 연산자를 표현식의 기본값을 설정하는데 사용할 수 있다. 예를 들어 @Value 표현식에서 다음과 같이 사용한다.

1
@Value("#{systemProperties['pop3.port'] ?: 25}")

이는 시스템 프로퍼티 pop3.port가 정의되어 있다면 pop3.port를 주입하고 정의되어 있지 않다면 25를 주입한다.


7.5.16 컬렉션 선택기능(Selection)
선택기능(Selection)은 소스 컨텍션에서 언트리를 선택해서 다른 컬렉션으로 변환하는 강력한 표현식 언어의 기능이다.

선 택기능은 ?[selectionExpression]의 문법을 사용한다. 선택기능은 컬렉션을 필터링해서 원래 요소의 서브셋을 가진 새로운 컬렉션을 반환한다. 예를 들어 선택기능으로 세르비아(Serbian) 발명가의 리스트를 쉽게 얻을 수 있다.
1
2
List<Inventor> list = (List<Inventor>)
      parser.parseExpression("Members.?[Nationality == 'Serbian']").getValue(societyContext);

선 택기능은 리스트와 맵에서 도무 사용할 수 있다. 리스트의 경우 선택 크리테리아는 개별 리스트요소에 대해 평가되고 맵에서 선택 크리테리아는 맵의 각 엔트리에 대해 평가된다. (Map.Entry 자바 타입의 객체들) 맵 엔트리는 선택기능에서 사용하기 위해 프로퍼티로 접근할 수 있는 키와 값을 가진다.

다음 표현식은 원래의 맵에서 27보다 작은 값을 가진 엔트리로 이루어진 새로운 맵을 반환한다.
1
Map newMap = parser.parseExpression("map.?[value<27]").getValue();

게다가 선택된 모든 요소에서 첫번째나 마지막 값을 획득하는 것도 가능한다. 선택기능의 ^[...] 문법을 사용해서 매칭된 첫 엔트리를 획득하고 $[...]로 마지막 엔티르를 획득한다.

7.5.17 컬렉션 투영(Projection)
투 영기능은 컬렉션에 하위 표현식을 평가해서 새로운 컬렉션을 반환한다. 투영 문법은 ![projectionExpression]이다. 예제로 이해하는 것이 가장 쉬운데 발명가들의 리스트를 가지고 있지만 발명가들이 테어난 도시의 리스트를 원한다고 가정해보자. 발명가 리스트에서 모든 인트리에 대해 'placeOfBirth.city'를 효율적으로 평가하기를 원한다. 다음과 같이 투영을 사용한다.
1
2
// [ 'Smiljan', 'Idvor' ]를 반환한다.
List placesOfBirth = (List)parser.parseExpression("Members.![placeOfBirth.city]");

맵에서도 투영기능을 사용할 수 있고 맵의 경우 투영 표현식은 맵의 각 엔트리마다(자바 Map.Entry로 표현되는) 평가된다. 맵의 투영결과는 맵의 각 엔트리에 대한 투영 표현식의 평가결과로 이루어진 리스트이다.

7.5.18 표현식 템플릿
표현식 템플릿으로 하나 이상의 평가 블럭을 가진 리터럴 문자를 섞을 수 있다. 각 평가 블럭은 사용자가 정의할 수 있는 접두사와 접미사로 구분되고 일반적으로는 구분자로 #{ }를 사용한다. 다음 예제를 보자.
1
2
3
4
5
String randomPhrase =
   parser.parseExpression("random number is #{T(java.lang.Math).random()}",
                          new TemplateParserContext()).getValue(String.class);
 
// "random number is 0.7038186818312008"로 평가된다

#{ } 구분자내의 표현식을 평가한 결과(이 예제에서는 random() 메서드를 호출한 결과이다.)와 'random number is ' 리터럴 문자를 연결해서 문자열을 평가한다. parseExpression() 메서드의 두번째 아규먼트는 ParserContext의 타입이다. ParserContext 인터페이스는 표현식 템플릿 기능을 지원하려고 표현식을 어떻게 파싱하는 지에 영향을 주려고 사용한다. TemplateParserContext의 정의는 다음에 나와있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class TemplateParserContext implements ParserContext {
 
  public String getExpressionPrefix() {
    return "#{";
  }
 
  public String getExpressionSuffix() {
    return "}";
  }
   
  public boolean isTemplate() {
    return true;
  }
}


7.6 예제에 사용한 클래스들
Inventor.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package org.spring.samples.spel.inventor;
 
import java.util.Date;
import java.util.GregorianCalendar;
 
public class Inventor {
 
  private String name;
  private String nationality;
  private String[] inventions;
  private Date birthdate;
  private PlaceOfBirth placeOfBirth;
   
   
  public Inventor(String name, String nationality)
  {
    GregorianCalendar c= new GregorianCalendar();
    this.name = name;
    this.nationality = nationality;
    this.birthdate = c.getTime();
  }
  public Inventor(String name, Date birthdate, String nationality) {
    this.name = name;
    this.nationality = nationality;
    this.birthdate = birthdate;
  }
   
  public Inventor() {
  }
 
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getNationality() {
    return nationality;
  }
  public void setNationality(String nationality) {
    this.nationality = nationality;
  }
  public Date getBirthdate() {
    return birthdate;
  }
  public void setBirthdate(Date birthdate) {
    this.birthdate = birthdate;
  }
  public PlaceOfBirth getPlaceOfBirth() {
    return placeOfBirth;
  }
  public void setPlaceOfBirth(PlaceOfBirth placeOfBirth) {
    this.placeOfBirth = placeOfBirth;
  }
  public void setInventions(String[] inventions) {
    this.inventions = inventions;
  }
  public String[] getInventions() {
    return inventions;
  }      
}

PlaceOfBirth.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package org.spring.samples.spel.inventor;
 
public class PlaceOfBirth {
 
  private String city;
  private String country;
 
  public PlaceOfBirth(String city) {
    this.city=city;
  }
  public PlaceOfBirth(String city, String country)
  {
    this(city);
    this.country = country;
  }
  public String getCity() {
    return city;
  }
  public void setCity(String s) {
    this.city = s;
  }
  public String getCountry() {
    return country;
  }
  public void setCountry(String country) {
    this.country = country;
  }
}

Society.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package org.spring.samples.spel.inventor;
 
import java.util.*;
 
public class Society {
 
  private String name;
 
  public static String Advisors = "advisors";
  public static String President = "president";
 
  private List<Inventor> members = new ArrayList<Inventor>();
  private Map officers = new HashMap();
 
  public List getMembers() {
    return members;
  }
 
  public Map getOfficers() {
    return officers;
  }
 
  public String getName() {
    return name;
  }
 
  public void setName(String name) {
    this.name = name;
  }
 
  public boolean isMember(String name)
  {
    boolean found = false;
    for (Inventor inventor : members) {
      if (inventor.getName().equals(name))
      {
        found = true;
        break;
      }
    }       
    return found;
  }   
}



출처 - http://blog.outsider.ne.kr/837?category=2





Posted by linuxism
,