2014-06-25 3 views
2

JSF에서 XML 문서를 읽고 쓰는 방법에 대해서는 온라인으로 찾지 못했습니다. XALAN을 사용하는 JSTL과 함께 JSP에서 뭔가를 알고 있습니다. 예 :JSF에서 XML 파일 읽기 및 쓰기

다음 XML 파일은 /WEB-INF에 정의되어 있습니다.

<?xml version="1.0" encoding="UTF-8"?> 

<fruits> 
    <fruit> 
     <name>Orange</name> 
     <price>10</price> 
    </fruit> 

    <fruit> 
     <name>Banana</name> 
     <price>20</price> 
    </fruit> 

    <fruit> 
     <name>Apple</name> 
     <price>30</price> 
    </fruit> 
</fruits> 

이 문서는 다음과 같이 JSP로 읽을 수 있습니다.

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

<c:import var="items" url="/WEB-INF/TextXML.xml"/> 
<x:parse var="fruits" doc="${items}"/> 

<table rules="all" border="1"> 
    <tr> 
     <th>index</th> 
     <th>Fruit Name</th> 
     <th>Price</th> 
    </tr> 

    <x:forEach var="item" select="$fruits/fruits/fruit" varStatus="loop"> 
     <tr> 
      <td><c:out value="${loop.index+1}"/></td> 
      <td><x:out select="$item/name" /></td> 
      <td><x:out select="$item/price" /></td> 
     </tr> 
    </x:forEach> 
</table> 

이렇게하면 3 개의 열로 HTML 표가 채워집니다.

JSF에서 동일한 작업을 달성하려면 어떻게해야합니까? JAXB 또는 다른 것을 사용하면 어떻게 될까요?

답변

5

실제로이 경우 JAXB을 사용할 수 있습니다.

이미 <fruit>을 나타내는 javabean이 있다고 가정 해 보겠습니다. 기존 JPA 엔티티를 재사용 할 수도 있습니다.

public class Fruit { 

    private String name; 
    private BigDecimal price; 

    // Add/generate getters+setters. 
} 

<fruits>를 나타내는 또 다른 자바 빈즈를 생성, 이제

을 (그렇지 않으면 당신은 그 중 하나에 @XmlElement(name="actualXmlElementName")을 필요로하는 자바 빈즈 클래스를 기록하고 속성 이름은 정확히 XML 요소 이름 <fruit>, <name><price> 일치해야합니다) , 순전히 JAXB에서 사용하기위한 것입니다 (즉, XML 문서는 기본적으로 엔티티 목록 만 포함하지만 XML 루트 요소를 나타내는 @XmlRootElement 클래스가 필요합니다).

InputStream input = externalContext.getResourceAsStream("/WEB-INF/fruits.xml"); 

을하지만 쓰기는 따로 이야기 :

@XmlRootElement 
public class Fruits { // Classname must match <fruits>, otherwise set it as @XmlRootElement(name="fruits") 

    @XmlElement(name="fruit") // Name must thus match <fruit>. We could also make the property name "fruit" so that we can omit @XmlElement, but a getFruit() method returning a list of fruits isn't self-documenting. 
    private List<Fruit> list; 

    public Fruits() { 
     // Keep default c'tor alive. 
    } 

    public Fruits(List<Fruit> list) { 
     this.list = list; 
    } 

    public List<Fruit> getList() { 
     return list; 
    } 

} 

는 읽기/쓰기에 관해서는, 다음과 같이 JSF 완벽 /WEB-INF에서 읽을 수 있습니다. 배포 공간에 파일을 작성하지 않아도됩니다. WAR를 재배포 할 때마다 모든 변경 사항이 손실된다는 명백한 이유 때문에 영구 저장 위치로 의도되지 않습니다. 배포 공간 밖의 고정 경로에이 파일을 작성해야합니다. 아래의 예에서는 파일이 서버의 디스크 파일 시스템에있는 /var/webapp/fruits.xml으로 옮겨 졌다고 가정합니다.

그래서, 당신은 다음과 같이 관리 빈에서 XML 파일을 읽고 쓸 수 JAXB를 사용할 수 있습니다

@Named 
@RequestScoped 
public class Bean { 

    private File file = new File("/var/webapp/fruits.xml"); 
    private JAXBContext jaxb; // Can be application scoped. It's thread safe. 
    private List<Fruit> fruits; 

    @PostConstruct 
    public void init() throws JAXBException, IOException { 
     jaxb = JAXBContext.newInstance(Fruits.class); 
     fruits = ((Fruits) jaxb.createUnmarshaller().unmarshal(file)).getList(); 
    } 

    public void save() throws JAXBException { 
     jaxb.createMarshaller().marshal(new Fruits(fruits), file); 
    } 

    public List<Fruit> getFruits() { 
     return fruits; 
    } 

} 

당신은 JSF <h:dataTable> 일반적인 방법으로 편집을 표시 할 수 있습니다.

<h:dataTable value="#{bean.fruits}" var="fruit"> 
    <h:column><h:inputText value="#{fruit.name}" /></h:column> 
    <h:column><h:inputText value="#{fruit.price}" /></h:column> 
</h:dataTable> 
+0

매우 정확하고 간결한 예입니다. 많은 감사합니다. 이 방법으로 XML 파일에서 기본 CRUD 작업을 수행 할 수 있습니다 (기본적으로 select는 필자의 경우에만 필요하다). ('init()'메쏘드에서 던져지는 예외는'try ... catch {}'를 사용하여 던지기보다는 잡히게됩니다. 그렇지 않으면 컴파일 타임 오류가 발생하여 "*'@ PostConstruct' 주석이 붙은 메소드는 체크 된 예외를 던져서는 안된다. * "). – Tiny

+0

일반적으로 파일은 서버 디스크 파일 시스템에 저장됩니다. 나는 그것을 $ {GlassFishHome}/domains/domain1/applications/my_xml_folder/fruits.xml'에 넣었고'System.getenv ("XML_LOCATION")과 같이 설정 한 환경 변수를 사용하여 파일 경로를 얻었습니다. . 올바른 방법을 따르고 있습니까? – Tiny