1부에서는 HttpServletResonse의 getWriter()를 통해 마샬링한 데이터를 바로 출력하는 예제,

 

2부에서는 마샬링한 데이터를 OutputStream에 저장후 InputStream으로 변환하여 언마샬링 하는 예제를 작성해 봤습니다.

 

이번에는 마샬링 결과를 파일로 저장후 InputStreamReader를 통해 File을 읽어와서 언마샬링 하는 예제를 작성해 보겠습니다.

 

-----------------------------------------------------------------------------------------------------------------

※Object를 마샬링 후 파일로 저장

import com.thoughtworks.xstream.XStream;

 

XStream xstream = new XStream();
final String xmlPath = "D:\\test.xml";
OutputStreamWriter osw =  

new OutputStreamWriter(new FileOutputStream(new File(xmlPath)), "utf-8");

 

UserBltnListCollections userBltnListCollections = new UserBltnListCollections();
userBltnListCollections.setUserBltnList(list);
xstream.processAnnotations(UserBltnListCollections.class);
xstream.toXML(userBltnListCollections, osw); //마샬링한 데이터를 파일로 저장

-----------------------------------------------------------------------------------------------------------------

 - UserBltnListCollections Class

  import com.thoughtworks.xstream.annotations.XStreamAlias;
  import com.thoughtworks.xstream.annotations.XStreamImplicit;

 

  //루트 Element의 별칭을 지정해줌

  //주의점 : 당연한 결과겠지만 마샬링시 필드명에 Alias를 지정하여 필드명 변경등이

  //있을경우 언마샬링시에도 XStreamAlias를 사용해서 일치하게 설정해야 한다.
  @XStreamAlias(value="userBltnList")
  public class UserBltnListCollections {
 
  //하위 필드(Collection)에 대해 XStreamImplicit Annotation으로 지정함
  //(XAJB의 경우 @XmlElement(name="bltnList")로 지정함)

  //(UserBltnListVO클래스는 일반적인 getter/setter를 포함한 Value Object Class임)
  @XStreamAlias(value="bltnList")
  @XStreamImplicit(itemFieldName="bltnList")
  private List<UserBltnListVO> userBltnList = null;
  
  public List<UserBltnListVO> getUserBltnList() {
   if(userBltnList==null){
    userBltnList = new ArrayList<UserBltnListVO>();
  }
   return userBltnList;
  }

  public void setUserBltnList(List<UserBltnListVO> userBltnList) {
   this.userBltnList = userBltnList;
  }  
 }

-------------------------------------------------------------------------------------------------

- UserBltnListVO (ValueObject Class) 

 

import com.thoughtworks.xstream.annotations.XStreamOmitField

 

public class UserBltnListVO {
 
 //@XStreamAsAttribute로 지정시 속성으로 지정된다.
 //JAXB에서는 @XmlAttribute(name="xx")로 지정함 필드일 경우엔 마샬링시
 //JAXB와 마찬가지로 따로 지정할 필요는 없는것 같다.
 //JAXB는 마샬링시 모든 필드를 바인딩 하지만 XStream에서는
 //@XStreamOmitField가 지정된 필드는 제외시킨다. 
 
 @XStreamOmitField
 private String no = "";
 private String subject = "";
 private String writeDay = "";
 private String readNum = "";
 private String isSecret = "";
 private String name = "";

 ..

  getter/setter 생략

 ..

}

-----------------------------------------------------------------------------------------------------------------

※Object를 마샬링후 데이터를 저장한 파일을 InputStreamReader로 읽어와서 언마샬링

InputStreamReader isr = new InputStreamReader(new FileInputStream(xmlPath),"utf-8");
UserBltnListCollections userBltnListCollectionsToUnMarshall = null;

//지정된 XStream 관련 Annotation을 처리한다.
xstream.processAnnotations(UserBltnListCollections.class);   
//마샬링된 파일을 InputStreamReader로 읽어와서 언마샬링 함
userBltnListCollectionsToUnMarshall = (UserBltnListCollections)xstream.fromXML(isr);   

-----------------------------------------------------------------------------------------------------------------

JAXB에서 마샬링된 XML을 언마샬링 할때는 File클래스로 저장 후 바로 읽어와서 언마샬링 하도록 했으나 이번엔 방식은

 

비슷하나 Stream을 통해서 저장하는 방식으로 바꿔봤습니다. 예제에서는 작은 파일이기 때문에 어떤 방법으로 처리해도

 

IO에 무리가 되지 않으나 XML크기가 크고 빈번한 요청이 일어나는 Task라면 어떤 방식으로 처리할것인가를 고민해야 할

 

것으로 보입니다. 여기까지 XStream을 통한 마샬링, 언마샬링 방법에 대해서 알아봤습니다. 개념은 조금 다를지 몰라도

 

결과적으로 봐선 XStream을 사용하는것이 더 좋을것 같습니다. 좀더 유연하다고나 할까요? 시간이 되면 List<Map>을

 

언마샬링 하는 예제를 작성해 보려고 합니다. 이경우엔 따로 구현을 해야되는 것으로 알고 있습니다. JAXB 사용방법

 

예제를 작성할때도 잠깐 언급했지만 DomParser사용할때에 비해서 이렇게 비교가 안될정도로 편하게 쓸 수 있게 만들어준

 

개발자 분들에게 항상 존경과 감사함을 느낍니다.

1부에서는 HttpServletResonse의 getWriter()를 통해 마샬링한 데이터를 바로 출력하는 예제를 작성해 봤습니다.

 

이번에는 OutputStream으로 마샬링한 데이터를 저장하고 이를 InputStream으로 변환하여 언마샬링 처리하는 방법을

 

예제로 작성해보겠습니다. JAXB를 사용한 예제도 비슷하게 HttpUrlConnection을 통해 가져온 InputStream을

 

언마샬링 하는 예제가 있으니 참고하시기 바랍니다.

 

-----------------------------------------------------------------------------------------------------------------

※Object를 마샬링 후 OutputStream으로 저장한 후 InputStream으로 변환

  import com.thoughtworks.xstream.XStream;

 

  ByteArrayOutputStream ous = new ByteArrayOutputStream();
  ByteArrayInputStream ins = null;
  byte[] byteData= null;
  
  UserBltnListCollections userBltnListCollections = new UserBltnListCollections();
  userBltnListCollections.setUserBltnList(list); //list는 List Collection클래스임
  
  XStream xstream = new XStream();    

  //지정된 XStream 관련 Annotation을 처리한다.
  xstream.processAnnotations(UserBltnListCollections.class); 

  //UnMarshalling시 InputStream을 처리하기 위해 OutputStream으로 저장
  xstream.toXML(userBltnListCollections, ous); 
  byteData = ous.toByteArray();
  ins = new ByteArrayInputStream(byteData); //InputStream으로 변환 

-----------------------------------------------------------------------------------------------------------------

 - UserBltnListCollections Class

  import com.thoughtworks.xstream.annotations.XStreamAlias;
  import com.thoughtworks.xstream.annotations.XStreamImplicit;

 

  //루트 Element의 별칭을 지정해줌

  //주의점 : 당연한 결과겠지만 마샬링시 필드명에 Alias를 지정하여 필드명 변경등이

  //있을경우 언마샬링시에도 XStreamAlias를 사용해서 일치하게 설정해야 한다.
  @XStreamAlias(value="userBltnList")
  public class UserBltnListCollections {
 
  //하위 필드(Collection)에 대해 XStreamImplicit Annotation으로 지정함
  //(XAJB의 경우 @XmlElement(name="bltnList")로 지정함)

  //(UserBltnListVO클래스는 일반적인 getter/setter를 포함한 Value Object Class임)
  @XStreamAlias(value="bltnList")
  @XStreamImplicit(itemFieldName="bltnList")
  private List<UserBltnListVO> userBltnList = null;
  
  public List<UserBltnListVO> getUserBltnList() {
   if(userBltnList==null){
    userBltnList = new ArrayList<UserBltnListVO>();
  }
   return userBltnList;
  }

  public void setUserBltnList(List<UserBltnListVO> userBltnList) {
   this.userBltnList = userBltnList;
  }  
 }

-------------------------------------------------------------------------------------------------

- UserBltnListVO (ValueObject Class) 

 

import com.thoughtworks.xstream.annotations.XStreamOmitField

 

public class UserBltnListVO {
 
 //@XStreamAsAttribute로 지정시 속성으로 지정된다.
 //JAXB에서는 @XmlAttribute(name="xx")로 지정함 필드일 경우엔 마샬링시
 //JAXB와 마찬가지로 따로 지정할 필요는 없는것 같다.
 //JAXB는 마샬링시 모든 필드를 바인딩 하지만 XStream에서는
 //@XStreamOmitField가 지정된 필드는 제외시킨다. 
 
 @XStreamOmitField
 private String no = "";
 private String subject = "";
 private String writeDay = "";
 private String readNum = "";
 private String isSecret = "";
 private String name = "";

 ..

  getter/setter 생략

 ..

}

-----------------------------------------------------------------------------------------------------------------

 - InputStream을 언마샬링

 UserBltnListCollections userBltnListCollectionsToUnMarshall = null;  

 //지정된 XStream 관련 Annotation을 처리한다.
 xstream.processAnnotations(UserBltnListCollections.class);

 //InputStream을 읽어서 바인딩될 Object에 저장  
 userBltnListCollectionsToUnMarshall =  (UserBltnListCollections) xstream.fromXML(ins);

-----------------------------------------------------------------------------------------------------------------

 

JAXB로 마샬링후 언마샬링 처리할때와 방식은 거의 비슷합니다. JAXB나 XStream둘 중 한가지라도 써보셨다면 결국

 

마샬링이나 언마샬링을 처리하는 부분의 약간의 차이, 어노테이션 이름 차이정도가 있으며 결국 맵핑을 얼마나 잘 시켜서

 

사용하느냐가 관건인 듯 싶습니다.

XStream을 통한 마샬링, 언마샬링 처리에 대해서 알아보겠습니다. 최근 JAXB(Java Architecture for XML Binding)

 

API와 더불어 OXM(Object/Xml Mapping)에 많이 사용되고 있는 것 같네요. 스프링 프레임워크를 쓰시는 분들은

 

JAXB, XStream 모두 Spring OXM에 포함되어 있으므로 간단히 의존성 주입후 사용하시면 되겠습니다.

 

저는 따로 라이브러리를 받아서 사용 했습니다. 마샬링, 언마샬링 구현 방식은 JAXB와 거의 유사합니다만

 

가독성은 XStream이 더 간결했으며 대략적인 개념은 비슷한 라이브러리 들이지만 약간씩 차이가 있습니다.

 

개인적으로는 편의성만 보면 XStream이 쓰기 더 편하게 느껴집니다. 이제 간단한 예제부터 한번 보겠습니다.

 

대략적인 설명은 예제의 주석 부분을 보시면 이해 되실겁니다. 실습해보면서 나름 이해한 내용이라 잘못된 이해일수도

 

있습니다.

 

*JAXB를 통한 Marshalling, UnMarshalling 방법은 아래 링크들을 참고하시면 됩니다.

 

1부 : 파일을 통한 마샬링, 언마샬링 처리

2부 : HttpUrlConnection을 통해 얻어온 InputStream을 언마샬링

3부 : 마샬링된 데이터를 OutputStream에 저장하고 다시 InputStream으로 변환 후 언마샬링

 

 

※마샬링 후 출력

  import com.thoughtworks.xstream.XStream

 

  UserBltnListCollections userBltnListCollections = new UserBltnListCollections();
  userBltnListCollections.setUserBltnList(list);

 

  //마샬링시 xpp3 라이브러리의 종속성을 피하기 위해 DomDriver를 사용하도록 설정

  //할수 있다. 일부에선 속도저하가 심각하므로 꿈에서도 사용하지 말라는 소리가 있지만

  //그렇게 방대한 XML이 아니라면 상관 없을 듯 싶다.

  //ex) XStream xstream = new XStream(new DomDriver("utf-8"));


  XStream xstream = new XStream();

  //지정된 XStream관련 Annotation을 처리한다. 
  xstream.processAnnotations(UserBltnListCollections.class);
  xstream.toXML(userBltnListCollections, response.getWriter());   //출력

 

------------------------------------------------------------------------------------------------

 - UserBltnListCollections Class

  import com.thoughtworks.xstream.annotations.XStreamAlias;
  import com.thoughtworks.xstream.annotations.XStreamImplicit;

 

  //루트 Element의 별칭을 지정해줌

  //주의점 : 당연한 결과겠지만 마샬링시 필드명에 Alias를 지정하여 필드명 변경등이

  //있을경우 언마샬링시에도 XStreamAlias를 사용해서 일치하게 설정해야 한다.
  @XStreamAlias(value="userBltnList")
  public class UserBltnListCollections {
 
  //하위 필드(Collection)에 대해 XStreamImplicit Annotation으로 지정함
  //(XAJB의 경우 @XmlElement(name="bltnList")로 지정함)
  @XStreamAlias(value="bltnList")
  @XStreamImplicit(itemFieldName="bltnList")
  private List<UserBltnListVO> userBltnList = null;
  
  public List<UserBltnListVO> getUserBltnList() {
   if(userBltnList==null){
    userBltnList = new ArrayList<UserBltnListVO>();
  }
   return userBltnList;
  }

  public void setUserBltnList(List<UserBltnListVO> userBltnList) {
   this.userBltnList = userBltnList;
  }  
 }

------------------------------------------------------------------------------------------------

 

마샬링한 데이터를 곧바로 HttpServletResponse의 getWriter()를 통해 출력하는 예제를 작성해봤습니다. JAXB로 마샬링

 

할때와 결과는 동일하지만 가독성에 있어서는 XStream이 간결해 보입니다. 다음 예제에서는 OutputStream으로 저장한

 

마샬링 데이터를 InputStream으로 변환하여 출력하는 예제를 작성해 보겠습니다.