아키텍처와 함께

블로그 이미지
by gregorio
  • Total hit
  • Today hit
  • Yesterday hit

Spring framework에서 Jaxb2Marshaller를 사용하는 경우 관련된 classesToBeBound 또는 packagesToScan를 속성을 이용하여 XML 변환이 필요한 객체를 찾는다.


classToBeBound를 사용하는 경우 해당 Class를 주입해야하고, packageToScan을 사용하는 경우 해당 package를 여러개 선언해야 한다.


■ classToBeBound 와 packageToScan 설정 예

<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">

    <property name="packagesToScan"-->

     <!-- set package name without * -->

    <list>

    <value>com.sample.vo</value>

    </list>

</property>

</bean>



<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">

<property name="classesToBeBound">

<list>

<value>com.sample.vo.ApiUserVo</value>

<value>com.sample.vo.ApiUserListVo</value>

</list>

       </property>

</bean>

 


상기의 방식을 적용하는 경우에는 XML 변환이 필요한 객체가 생성될 때마다 설정을 변경해야한다.


이와 같은 불편함을 해결하기 위해 package 단위로 관련 객체를 검색하는 방법을 구현한 소스를 인터넷에 찾아 약간의 변경을 하였다.


■Package 기준 객체 Scan 소스


public class PackageScanningJaxb2Marshaller  extends Jaxb2Marshaller{


    private static final Logger LOGGER = LoggerFactory.getLogger(ClasspathScanningJaxb2Marshaller.class);

    

    /** base package location **/

    private List<String> basePackages;

    

    /** XML Filter for scanning package **/

    private final TypeFilter[] jaxb2TypeFilters = new TypeFilter[]{

                new AnnotationTypeFilter(XmlRootElement.class, false),

                new AnnotationTypeFilter(XmlType.class, false),

                new AnnotationTypeFilter(XmlSeeAlso.class, false),

                new AnnotationTypeFilter(XmlEnum.class, false)

    };


    

     

     @Required

    public void setBasePackages(List<String> basePackages) { 

    this.basePackages = basePackages; 

    }

    

    /**

     * This method should scan base package with XML related annotation filters to find classes 

     */

    private Class<?>[] getXmlRootElementClasses() throws Exception {

        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);


        for (TypeFilter typeFilter : jaxb2TypeFilters) {

            scanner.addIncludeFilter(typeFilter);       

        }

        

        List<Class<?>> classes = new ArrayList<Class<?>>();

        

        /** Find classes with base package **/

        for (String basePackage : basePackages) {

            Set<BeanDefinition> definitions = scanner.findCandidateComponents(basePackage);

            for (BeanDefinition definition : definitions) {

                String className = definition.getBeanClassName();

               

                LOGGER.info("Found class: {}", className);

                

                classes.add(Class.forName(className));

            }

        }

        

        return classes.toArray(new Class[0]);

    }

    

    @PostConstruct

    public void init() throws Exception {

        setClassesToBeBound(getXmlRootElementClasses());

    }



PacakgeScanningJaxb2Marshaller는 Jaxb2Marshaller를 상속받아 구현하였으며, Bean이 생성된 후 정의된 Package에서 @XML annotation이 정의되어 있는 Class를 찾아 ClassesToBeBound에 해당 Class들을 Set하여 준다.


■ Bean 설정

 <bean id="jaxbMarshaller" class="com.spring.xml.ClasspathScanningJaxb2Marshaller">

    <property name="basePackages">

    <list>

    <value>com.sample</value>

    </list>

</property>

</bean>


■ xmlView 예제


<bean id="xmlView" class="org.springframework.web.servlet.view.xml.MarshallingView">

<!-- constructor-arg>

<bean class="org.springframework.oxm.xstream.XStreamMarshaller" />

</constructor-arg-->

<property name="marshaller" ref="jaxbMarshaller" />

</bean> 


xmlView는 marshller를 jaxbMarshller Bean을 참조한다.



■ Value Object 예제

import java.io.Serializable;


import javax.xml.bind.annotation.XmlAccessType;

import javax.xml.bind.annotation.XmlAccessorType;

import javax.xml.bind.annotation.XmlRootElement;

import javax.xml.bind.annotation.XmlType;

@XmlAccessorType( XmlAccessType.FIELD )

@XmlType( name = "" , 

propOrder = { "clientId", 

    "authCode", 

    "authTime", 

} )

@XmlRootElement(name="ApiUser")

public class ApiUserVo  implements Serializable{

/**

*/

private static final long serialVersionUID = -6929037986045167263L;


private String clientId;

private String authCode;

private String authTime;

public String getClientId() {

return clientId;

}

public void setClientId(String clientId) {

this.clientId = clientId;

}

public String getAuthCode() {

return authCode;

}

public void setAuthCode(String authCode) {

this.authCode = authCode;

}

public String getAuthTime() {

return authTime;

}

public void setAuthTime(String authTime) {

this.authTime = authTime;

}


import java.io.Serializable;

import java.util.ArrayList;

import java.util.List;


import javax.xml.bind.annotation.XmlAccessType;

import javax.xml.bind.annotation.XmlAccessorType;

import javax.xml.bind.annotation.XmlElement;

import javax.xml.bind.annotation.XmlRootElement;


@XmlRootElement(name="ApiUsers")

@XmlAccessorType (XmlAccessType.FIELD)

public class ApiUserListVo implements Serializable{


/**

*/

private static final long serialVersionUID = 1L;

@XmlElement(name="apiUser")

private List<ApiUserVo> apiUsers;

public ApiUserListVo() {

apiUsers = new ArrayList<ApiUserVo>();

}


public List<ApiUserVo> getApiUsers() {

return apiUsers;

}


public void setApiUsers(List<ApiUserVo> apiUsers) {

this.apiUsers = apiUsers;

}



■ Controller 예제

@RequestMapping(value="/sample/searchApiUserXml.do", method={RequestMethod.POST, RequestMethod.GET},  produces={MediaType.APPLICATION_XML_VALUE})


public ModelAndView selectApiUserXml(NexacroMapDTO dto, Model model) throws Exception {

ModelAndView modelAndView = NexacroUtil.getModelAndView(dto);

SBSessionVo sessionVo = SessionUtil.getSession(BaseConstants.DEFAULT_SESSION_NAME);

ApiUserVo vo = new ApiUserVo();

vo.setClientId(sessionVo.getUserId());

List<ApiUserVo> resultList = apiUserService.selectApiUserXml(vo);


ApiUserListVo voList = new ApiUserListVo();

voList.setApiUsers(resultList);

modelAndView.setViewName("xmlView");

modelAndView.addObject("result", voList);

return modelAndView;

}


■ 결과


<ApiUsers>
<apiUser>
<clientId>aaaa</clientId>
<authCode>db78f6a0-344f-485e-a8a9-71a5d54ee7a1</authCode>
<authTime>20184528130242</authTime>
</apiUser>
<apiUser>
<clientId>bbbb</clientId>
<authCode>38bf5d71-c422-42b4-a2f8-f5414fe6d6f0</authCode>
<authTime>20184628130217</authTime>
</apiUser>
</ApiUsers> 


XML을 생성할 때 base package만 정의하면 간단하게 객체를 XML으로 변환이 가능하다.



'Spring Framrwork' 카테고리의 다른 글

Mybatis include sql  (0) 2018.03.23
Spring Framework File Upload with Drag and Drop  (0) 2018.03.16
spring framework interceptor  (0) 2018.03.02
Google Map javascript API 사용법  (0) 2018.02.07
C3 Bar Chart  (0) 2018.02.05
AND

ARTICLE CATEGORY

분류 전체보기 (56)
Spring Framrwork (33)
Linux (1)
APM (1)
Java (8)
python (0)
ant (1)
chart (1)
OS (1)
tomcat (1)
apache (1)
database (0)

RECENT ARTICLE

RECENT COMMENT

CALENDAR

«   2024/10   »
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

ARCHIVE

LINK