SpringMVC 中整合JSON、XML檢視二

五柳-先生發表於2016-04-20

上篇文章介紹了程式整合的準備工作、結合MarshallingView檢視完成jaxb2轉換XML、xStream轉換XML工作,這次將介紹castor、jibx轉換XML。

還有MappingJacksonView用Jackson轉換JSON,自己擴充AbstractView定義Jsonlib的檢視完成JSON-lib轉換JSON。

上一篇文章:http://www.cnblogs.com/hoojo/archive/2011/04/29/2032571.html

 

四、 用Castor轉換XML

1、 castor可以通過一個mapping.xml檔案對即將轉換的Java物件進行描述,然後可以將Java物件按照描述的情況輸出XML內容。利用castor轉換xml需要新增如下jar包:

clip_image002

如果你還不清楚castor,可以閱讀:

for csblogs:http://www.cnblogs.com/hoojo/archive/2011/04/25/2026819.html

for csdn:http://blog.csdn.net/IBM_hoojo/archive/2011/04/25/6360916.aspx

2、 你需要在dispatcher.xml中新增castor的相關檢視,配置如下:

<-- 
    繼承MarshallingView重寫locateToBeMarshalled方法
         解決物件新增到ModelAndView中轉換後的xml是BindingResult資訊的bug 
-->
<bean name="castorMarshallingView" class="com.hoo.veiw.xml.OverrideMarshallingView">
    <property name="marshaller">
        <bean class="org.springframework.oxm.castor.CastorMarshaller">  
            <property name="mappingLocations">
                <array>
                    <value>classpath:mapping.xml</value>
                </array>
            </property>
            <property name="encoding" value="UTF-8"/>
           </bean>  
    </property>
</bean>

mapping.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN" "http://castor.org/mapping.dtd">
<mapping>
    <class name="com.hoo.entity.Account" auto-complete="true">   
        <map-to xml="Account"/>
 
        <field name="id" type="integer">
            <bind-xml name="id" node="attribute" />
        </field>
 
        <field name="name" type="string">
            <bind-xml name="name" node="element" />
        </field>
 
        <field name="email" type="string">
            <bind-xml name="email" node="element" />
        </field>
 
        <field name="address" type="string">
            <bind-xml name="address" node="element" />
        </field>
 
        <field name="brithday" type="com.hoo.entity.Brithday">
            <bind-xml name="生日" node="element" />
        </field>
    </class>
 
    <class name="com.hoo.entity.Brithday" auto-complete="true">
        <map-to xml="brithday" />
 
        <field name="brithday" type="string">
            <bind-xml name="brithday" node="attribute" />
        </field>
    </class>
    
    <class name="com.hoo.entity.MapBean" auto-complete="true">
        <field name="map" collection="map">
            <bind-xml name="map">
                <class name="org.exolab.castor.mapping.MapItem">
                    <field name="key" type="java.lang.String">
                        <bind-xml name="key" node="attribute" />
                    </field>
                    <field name="value" type="com.hoo.entity.Account">
                        <bind-xml name="value" auto-naming="deriveByClass"/>
                    </field>
                </class>
            </bind-xml>
        </field>
    </class>
    
    <class name="com.hoo.entity.ListBean" auto-complete="true">
        <map-to xml="listBean"/>
        <field name="list" collection="arraylist" type="com.hoo.entity.Account">
            <bind-xml name="beans" auto-naming="deriveByClass"/>
        </field>
        <field name="name" type="string"/>
    </class>
    
    <class name="com.hoo.entity.AccountArray" auto-complete="true">
        <map-to xml="account-array"/>
        <field name="size" type="int" />
        <field name="accounts" collection="array" type="com.hoo.entity.Account">
            <bind-xml name="accounts" auto-naming="deriveByClass"/>
        </field>
    </class>
</mapping>

關於mapping.xml配置的介紹,你可以參考http://www.cnblogs.com/hoojo/archive/2011/04/25/2026819.html

這篇文章的第三欄目。

3、 在使用Spring的MarshallingView的時候,轉換的xml結果有時候會帶有BindingResult物件的資訊。所以解決辦法是重寫MarshallingView裡面的locateToBeMarshalled方法,這樣就可以解決了。下面是重新MarshallingView的class程式碼:

package com.hoo.veiw.xml;
 
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.BeansException;
import org.springframework.oxm.Marshaller;
import org.springframework.validation.BindingResult;
import org.springframework.web.servlet.view.xml.MarshallingView;
 
/**
 * <b>function:</b>繼承MarshallingView,重寫locateToBeMarshalled方法;
 * 解決物件新增到ModelAndView中,轉換後的xml是BindingResult資訊的bug
 * @author hoojo
 * @createDate 2010-11-29 下午05:58:45
 * @file OverrideMarshallingView.java
 * @package com.hoo.veiw.xml
 * @project Spring3
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
public class OverrideMarshallingView extends MarshallingView {
 
    private Marshaller marshaller;
 
    private String modelKey;
 
    public OverrideMarshallingView() {
        super();
    }
 
    public OverrideMarshallingView(Marshaller marshaller) {
        super(marshaller);
        this.marshaller = marshaller;
    }
 
    public void setMarshaller(Marshaller marshaller) {
        super.setMarshaller(marshaller);
        this.marshaller = marshaller;
    }
 
    public void setModelKey(String modelKey) {
        super.setModelKey(modelKey);
        this.modelKey = modelKey;
    }
 
    @Override
    protected void initApplicationContext() throws BeansException {
        super.initApplicationContext();
    }
 
    @SuppressWarnings("unchecked")
    @Override
    protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        super.renderMergedOutputModel(model, request, response);
    }
 
    @SuppressWarnings("unchecked")
    @Override
    protected Object locateToBeMarshalled(Map model) throws ServletException {
        if (modelKey != null) {
            Object o = model.get(modelKey);
            if (!this.marshaller.supports(o.getClass())) {
                throw new ServletException("Model object [" + o + "] retrieved via key [" + modelKey
                        + "] is not supported by the Marshaller");
            }
            return o;
        }
        for (Object o : model.values()) {
            
            //解決物件新增到ModelAndView中,轉換後的xml是BindingResult資訊的bug
            if (o instanceof BindingResult) {
                continue;
            }
 
            if (this.marshaller.supports(o.getClass())) {
                return o;
            }
        }
        return null;
    }
}

4、 下面來看看Castor來轉換普通JavaBean

package com.hoo.controller;
 
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.hoo.entity.Account;
import com.hoo.entity.Brithday;
import com.hoo.entity.ListBean;
import com.hoo.entity.MapBean;
import com.hoo.entity.User;
 
/**
 * <b>function:</b>利用MarshallingView檢視,配置CastorMarshaller將Java物件轉換XML
 * @author hoojo
 * @createDate 2011-4-28 上午10:14:43
 * @file CastorMarshallingViewController.java
 * @package com.hoo.controller
 * @project SpringMVC4View
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
@Controller
@RequestMapping("/castor/view")
public class CastorMarshallingViewController {
    
    @RequestMapping("/doBeanXMLCastorView")
    public ModelAndView doBeanXMLCastorView() {
        System.out.println("#################ViewController doBeanXMLCastorView##################");
        ModelAndView mav = new ModelAndView("castorMarshallingView");
        Account bean = new Account();
        bean.setAddress("北京");
        bean.setEmail("email");
        bean.setId(1);
        bean.setName("haha");
        Brithday day = new Brithday();
        day.setBrithday("2010-11-22");
        bean.setBrithday(day);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("day", day);
        map.put("account", bean);
        mav.addObject(bean);//重寫MarshallingView的locateToBeMarshalled方法
        //mav.addObject(BindingResult.MODEL_KEY_PREFIX, bean);
        //mav.addObject(BindingResult.MODEL_KEY_PREFIX + "account", bean);
        return mav;
    }
}

Account在mapping配置檔案中有進行配置描述。

在瀏覽器中請求http://localhost:8080/SpringMVC4View/castor/view/doBeanXMLCastorView.do

就可以看到結果了,結果如下:

<?xml version="1.0" encoding="UTF-8"?>
<Account id="1"><name>haha</name><email>email</email><address>北京</address><生日 brithday="2010-11-22"/></Account>

5、 轉換Map集合

@RequestMapping("/doMapXMLCastorView")
public ModelAndView doMapXMLCastorView() {
    System.out.println("#################ViewController doMapXMLCastorView##################");
    ModelAndView mav = new ModelAndView("castorMarshallingView");
    Account bean = new Account();
    bean.setAddress("北京");
    bean.setEmail("email");
    bean.setId(1);
    bean.setName("haha");
    Brithday day = new Brithday();
    day.setBrithday("2010-11-22");
    bean.setBrithday(day);
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("day", day);
    map.put("account", bean);
    MapBean differ = new MapBean();
    
    differ.setMap(map);
    
    mav.addObject(differ);
    return mav;
}

在瀏覽器中請求http://localhost:8080/SpringMVC4View/castor/view/doMapXMLCastorView.do

結果如下:

<?xml version="1.0" encoding="UTF-8"?>
<map-bean><map key="account"><Account id="1"><name>haha</name><email>email</email>
<address>北京</address><生日 brithday="2010-11-22"/></Account></map>
<map key="day"><brithday brithday="2010-11-22"/></map></map-bean>

6、 轉換List集合

@RequestMapping("/doListXMLCastorView")
public ModelAndView doListXMLCastorView() {
    System.out.println("#################ViewController doListXMLCastorView##################");
    ModelAndView mav = new ModelAndView("castorMarshallingView");
    List<Object> beans = new ArrayList<Object>(); 
    for (int i = 0; i < 3; i++) {
        Account bean = new Account();
        bean.setAddress("address#" + i);
        bean.setEmail("email" + i + "@12" + i + ".com");
        bean.setId(1 + i);
        bean.setName("haha#" + i);
        Brithday day = new Brithday();
        day.setBrithday("2010-11-2" + i);
        bean.setBrithday(day);
        beans.add(bean);
        
        User user = new User();
        user.setAddress("china GuangZhou# " + i);
        user.setAge(23 + i);
        user.setBrithday(new Date());
        user.setName("jack#" + i);
        user.setSex(Boolean.parseBoolean(i + ""));
        beans.add(user);
    }
    ListBean listBean = new ListBean();
    listBean.setList(beans);
    mav.addObject(listBean);
    return mav;
}

在WebBrowser中請求http://localhost:8080/SpringMVC4View/castor/view/doListXMLCastorView.do

<?xml version="1.0" encoding="UTF-8"?>
<listBean><Account id="1"><name>haha#0</name><email>email0@120.com</email>
<address>address#0</address><生日 brithday="2010-11-20"/></Account>
<user xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:java="http://java.sun.com" 
age="23" sex="false" xsi:type="java:com.hoo.entity.User">
<address>china GuangZhou# 0</address><name>jack#0</name><brithday>2011-04-28T14:41:56.703+08:00</brithday></user>
<Account id="2"><name>haha#1</name>
<email>email1@121.com</email><address>address#1</address><生日 brithday="2010-11-21"/></Account>
<user xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:java="http://java.sun.com" 
age="24" sex="false" xsi:type="java:com.hoo.entity.User">
<address>china GuangZhou# 1</address><name>jack#1</name><brithday>2011-04-28T14:41:56.703+08:00</brithday></user>
<Account id="3"><name>haha#2</name><email>email2@122.com</email>
<address>address#2</address><生日 brithday="2010-11-22"/></Account>
<user xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:java="http://java.sun.com" 
age="25" sex="false" xsi:type="java:com.hoo.entity.User">
<address>china GuangZhou# 2</address><name>jack#2</name>
<brithday>2011-04-28T14:41:56.703+08:00</brithday></user></listBean>

7、 轉換物件陣列

@RequestMapping("/doArrayXMLCastorView")
public ModelAndView doArrayXMLCastorView() {
    System.out.println("#################ViewController doArrayXMLCastorView##################");
    ModelAndView mav = new ModelAndView("castorMarshallingView");
    Object[] beans = new Object[3]; 
    for (int i = 0; i < 2; i++) {
        Account bean = new Account();
        bean.setAddress("address#" + i);
        bean.setEmail("email" + i + "@12" + i + ".com");
        bean.setId(1 + i);
        bean.setName("haha#" + i);
        Brithday day = new Brithday();
        day.setBrithday("2010-11-2" + i);
        bean.setBrithday(day);
        beans[i] = bean;
    }
    User user = new User();
    user.setAddress("china GuangZhou# ");
    user.setAge(23);
    user.setBrithday(new Date());
    user.setName("jack#");
    user.setSex(true);
    beans[2] = user;
    mav.addObject(beans);
    return mav;
}

在WebBrowser中請求http://localhost:8080/SpringMVC4View/castor/view/doArrayXMLCastorView.do

結果輸出:

<?xml version="1.0" encoding="UTF-8"?>
<array><Account xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="1" xsi:type="Account">
<name>haha#0</name><email>email0@120.com</email><address>address#0</address><生日 brithday="2010-11-20"/></Account>
<Account xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="2" xsi:type="Account"><name>haha#1</name>
<email>email1@121.com</email><address>address#1</address><生日 brithday="2010-11-21"/>
</Account><user xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:java="http://java.sun.com" age="23" sex="true" xsi:type="java:com.hoo.entity.User">
<address>china GuangZhou# </address><name>jack#</name>
<brithday>2011-04-28T14:43:43.593+08:00</brithday></user></array>

結果和List集合有點類似。

總結,使用castor可以轉換普通不經過封裝的Java型別,但是Map物件則需要進行簡單物件封裝,然後在mapping中進行描述才行。Castor和其他的框架不同的是,可以在xml配置中進行轉換物件的描述規則。

 

五、 用Jibx轉換XML

1、 jibx可以完成Java物件到xml的轉換,但是它需要bind.xml的配置以及多個工具類生成Jibx_BindList資訊。稍微有那麼點複雜,如果在Spring中利用Jibx的話,需要新增如下jar包:

clip_image004

如果你還不少很瞭解jibx轉換xml這方面的知識,可以閱讀:

For cnblogs:http://www.cnblogs.com/hoojo/archive/2011/04/27/2030205.html

For csdn:http://blog.csdn.net/IBM_hoojo/archive/2011/04/27/6366333.aspx

2、 下面你需要在dispatcher.xml中新增如下內容

<-- 需要先編譯生成bind.xml然後再進行繫結編譯生成jibx_bandList和執行所需的class -->
<bean name="jibxMarshallingView" class="org.springframework.web.servlet.view.xml.MarshallingView">
    <property name="marshaller">
        <bean class="org.springframework.oxm.jibx.JibxMarshaller">  
            <property name="targetClass" value="com.hoo.entity.Account"/>
           </bean>  
    </property>
</bean>

注意targetClass目標物件不能為空,必須配置。這個class就是你的物件從xml轉換到Java物件的那個物件型別。這裡不需要從xml轉換到Java,暫時就這樣配置就可以了。

3、 下面需要用到Account、User、ListBean、MapBean,除了User物件的程式碼沒有提供,其他的都提供了。下面看看User物件的程式碼:

package com.hoo.entity;
 
import java.io.Serializable;
import java.util.Date;
 
public class User implements Serializable {
 
    private static final long serialVersionUID = 8606788203814942679L;
    
    private String name;
    private int age;
    private boolean sex;
    private String address;
    private Date brithday;
    
    @Override
    public String toString() {
        return this.name + "#" + this.sex + "#" + this.address + "#" + this.brithday;
    }
}

4、 下面需要用rg.jibx.binding.BindingGenerator工具類為我們生成bind.xml內容,命令如下:

首先在dos命令控制檯進入到當前工程的WEB-INF目錄,然後輸入命令:

E:\Study\SpringMVC4View\WebRoot\WEB-INF>java -cp classes;lib/jibx-tools.jar;lib/log4j-1.2.16.jar 
org.jibx.binding.BindingGenerator -f bind.xml  
com.hoo.entity.Account com.hoo.entity.User com.hoo.entity.ListBean com.hoo.entity.MapBean

用空格分開要轉換到bind.xml中的JavaBean,執行上面的命令你可以看到如下結果:

Running binding generator version 0.4
Warning: field list requires mapped implementation of item classes
Warning: reference to interface or abstract class java.util.Map requires mapped implementation

生成bind.xml內容如下:

<?xml version="1.0" encoding="UTF-8"?>
<binding value-style="attribute">
  <mapping class="com.hoo.entity.Account" name="account">
    <value name="id" field="id"/>
    <value style="element" name="name" field="name" usage="optional"/>
    <value style="element" name="email" field="email" usage="optional"/>
    <value style="element" name="address" field="address" usage="optional"/>
    <structure field="brithday" usage="optional" name="brithday">
      <value style="element" name="brithday" field="brithday" usage="optional"/>
    </structure>
  </mapping>
  <mapping class="com.hoo.entity.User" name="user">
    <value style="element" name="name" field="name" usage="optional"/>
    <value name="age" field="age"/>
    <value name="sex" field="sex"/>
    <value style="element" name="address" field="address" usage="optional"/>
    <value name="brithday" field="brithday" usage="optional"/>
  </mapping>
  <mapping class="com.hoo.entity.ListBean" name="list-bean">
    <value style="element" name="name" field="name" usage="optional"/>
    <collection field="list" usage="optional" factory="org.jibx.runtime.Utility.arrayListFactory"/>
  </mapping>
  <mapping class="com.hoo.entity.MapBean" name="map-bean">
    <structure field="map" usage="optional"/>
  </mapping>
</binding>

這樣還沒有完,Map要經過特殊出來。我們要修改下MapBean的配置,修改後如下:

<mapping class="com.hoo.entity.MapBean" name="map-bean">
  <structure field="map" usage="optional" marshaller="com.hoo.util.HashMapper" unmarshaller="com.hoo.util.HashMapper"/>
</mapping>

HashMapper程式碼如下:

package com.hoo.util;
 
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.jibx.runtime.IAliasable;
import org.jibx.runtime.IMarshallable;
import org.jibx.runtime.IMarshaller;
import org.jibx.runtime.IMarshallingContext;
import org.jibx.runtime.IUnmarshaller;
import org.jibx.runtime.IUnmarshallingContext;
import org.jibx.runtime.JiBXException;
import org.jibx.runtime.impl.MarshallingContext;
import org.jibx.runtime.impl.UnmarshallingContext;
 
/**
 * <b>function:</b>http://www.java2s.com/Open-Source/Java/XML/JiBX/tutorial/example21/HashMapper.java.htm
 * @file HashMapper.java
 * @package com.hoo.util
 * @project WebHttpUtils
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
public class HashMapper implements IMarshaller, IUnmarshaller, IAliasable
{
    private static final String SIZE_ATTRIBUTE_NAME = "size";
    private static final String ENTRY_ELEMENT_NAME = "entry";
    private static final String KEY_ATTRIBUTE_NAME = "key";
    private static final int DEFAULT_SIZE = 10;
    
    private String m_uri;
    private int m_index;
    private String m_name;
    
    public HashMapper() {
        m_uri = null;
        m_index = 0;
        m_name = "hashmap";
    }
    
    public HashMapper(String uri, int index, String name) {
        m_uri = uri;
        m_index = index;
        m_name = name;
    }
    
    /* (non-Javadoc)
     * @see org.jibx.runtime.IMarshaller#isExtension(int)
     */
    
    public boolean isExtension(int index) {
        return false;
    }
 
    /* (non-Javadoc)
     * @see org.jibx.runtime.IMarshaller#marshal(java.lang.Object,
     *  org.jibx.runtime.IMarshallingContext)
     */
    
    @SuppressWarnings("unchecked")
    public void marshal(Object obj, IMarshallingContext ictx)
        throws JiBXException {
        
        // make sure the parameters are as expected
        if (!(obj instanceof HashMap)) {
            throw new JiBXException("Invalid object type for marshaller");
        } else if (!(ictx instanceof MarshallingContext)) {
            throw new JiBXException("Invalid object type for marshaller");
        } else {
            
            // start by generating start tag for container
            MarshallingContext ctx = (MarshallingContext)ictx;
            HashMap map = (HashMap)obj;
            ctx.startTagAttributes(m_index, m_name).
                attribute(m_index, SIZE_ATTRIBUTE_NAME, map.size()).
                closeStartContent();
            
            // loop through all entries in hashmap
            Iterator iter = map.entrySet().iterator();
            while (iter.hasNext()) {
                Map.Entry entry = (Map.Entry)iter.next();
                ctx.startTagAttributes(m_index, ENTRY_ELEMENT_NAME);
                if (entry.getKey() != null) {
                    ctx.attribute(m_index, KEY_ATTRIBUTE_NAME,
                        entry.getKey().toString());
                }
                ctx.closeStartContent();
                if (entry.getValue() instanceof IMarshallable) {
                    ((IMarshallable)entry.getValue()).marshal(ctx);
                    ctx.endTag(m_index, ENTRY_ELEMENT_NAME);
                } else {
                    throw new JiBXException("Mapped value is not marshallable");
                }
            }
            
            // finish with end tag for container element
            ctx.endTag(m_index, m_name);
        }
    }
 
    /* (non-Javadoc)
     * @see org.jibx.runtime.IUnmarshaller#isPresent(org.jibx.runtime.IUnmarshallingContext)
     */
     
    public boolean isPresent(IUnmarshallingContext ctx) throws JiBXException {
        return ctx.isAt(m_uri, m_name);
    }
 
    /* (non-Javadoc)
     * @see org.jibx.runtime.IUnmarshaller#unmarshal(java.lang.Object,
     *  org.jibx.runtime.IUnmarshallingContext)
     */
     
    @SuppressWarnings("unchecked")
    public Object unmarshal(Object obj, IUnmarshallingContext ictx)
        throws JiBXException {
        
        // make sure we're at the appropriate start tag
        UnmarshallingContext ctx = (UnmarshallingContext)ictx;
        if (!ctx.isAt(m_uri, m_name)) {
            ctx.throwStartTagNameError(m_uri, m_name);
        }
        
        // create new hashmap if needed
        int size = ctx.attributeInt(m_uri, SIZE_ATTRIBUTE_NAME, DEFAULT_SIZE);
        HashMap map = (HashMap)obj;
        if (map == null) {
            map = new HashMap(size);
        }
        
        // process all entries present in document
        ctx.parsePastStartTag(m_uri, m_name);
        while (ctx.isAt(m_uri, ENTRY_ELEMENT_NAME)) {
            Object key = ctx.attributeText(m_uri, KEY_ATTRIBUTE_NAME, null);
            ctx.parsePastStartTag(m_uri, ENTRY_ELEMENT_NAME);
            Object value = ctx.unmarshalElement();
            map.put(key, value);
            ctx.parsePastEndTag(m_uri, ENTRY_ELEMENT_NAME);
        }
        ctx.parsePastEndTag(m_uri, m_name);
        return map;
    }
 
    public boolean isExtension(String arg0) {
        return false;
    }
}

然後,再編譯下就可以了。命令如下:

E:\Study\SpringMVC4View\WebRoot\WEB-INF>java -cp classes;lib/jibx-bind.jar org.jibx.binding.Compile -v bind.xml

這樣你就可以啟動tomcat伺服器,沒有錯誤就ok了。

5、 轉換JavaBean到XML

package com.hoo.controller;
 
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.hoo.entity.Account;
import com.hoo.entity.Brithday;
import com.hoo.entity.ListBean;
import com.hoo.entity.MapBean;
import com.hoo.entity.User;
 
/**
 * <b>function:</b>利用Jibx和JibxMarshaller轉換Java物件到XML
 * @author hoojo
 * @createDate 2011-4-28 下午03:05:11
 * @file JibxMarshallingViewController.java
 * @package com.hoo.controller
 * @project SpringMVC4View
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
@Controller
@RequestMapping("/jibx/view")
public class JibxMarshallingViewController {
    
    @RequestMapping("/doXMLJibxView")
    public ModelAndView doXMLJibxView() {
        System.out.println("#################ViewController doXMLJibxView##################");
        ModelAndView mav = new ModelAndView("jibxMarshallingView");
        Account bean = new Account();
        bean.setAddress("北京");
        bean.setEmail("email");
        bean.setId(1);
        bean.setName("haha");
        Brithday day = new Brithday();
        day.setBrithday("2010-11-22");
        bean.setBrithday(day);
        
        mav.addObject("中國");
        mav.addObject(bean);
        return mav;
    }
}

上面的ModelAndView配置的檢視就是我們在dispatcher中配置過的檢視

在WebBrowser中請求http://localhost:8080/SpringMVC4View/jibx/view/doXMLJibxView.do

結果如下:

<?xml version="1.0"?><account id="1"><name>haha</name><email>email</email><address>北京</address>
<brithday><brithday>2010-11-22</brithday></brithday></account>

6、 轉換List到XML

/**
 * <b>function:</b>轉換帶有List屬性的JavaBean
 * @author hoojo
 * @return
 */
@RequestMapping("/doListXMLJibx")
public ModelAndView doListXMLJibxView() {
    System.out.println("#################ViewController doListXMLJibxView##################");
    ModelAndView mav = new ModelAndView("jibxMarshallingView");
    List<Object> beans = new ArrayList<Object>(); 
    for (int i = 0; i < 3; i++) {
        Account bean = new Account();
        bean.setAddress("address#" + i);
        bean.setEmail("email" + i + "@12" + i + ".com");
        bean.setId(1 + i);
        bean.setName("haha#" + i);
        Brithday day = new Brithday();
        day.setBrithday("2010-11-2" + i);
        bean.setBrithday(day);
        beans.add(bean);
        
        User user = new User();
        user.setAddress("china GuangZhou# " + i);
        user.setAge(23 + i);
        user.setBrithday(new Date());
        user.setName("jack#" + i);
        user.setSex(Boolean.parseBoolean(i + ""));
        beans.add(user);
    }
    
    ListBean list = new ListBean();
    list.setList(beans);
    mav.addObject(list);
    
    return mav;
}

在瀏覽器中請求http://localhost:8080/SpringMVC4View/jibx/view/doListXMLJibx.do

結果如下:

<?xml version="1.0"?><list-bean><account id="1"><name>haha#0</name><email>email0@120.com</email><address>address#0</address>
<brithday><brithday>2010-11-20</brithday></brithday></account>
<user age="23" sex="false" brithday="2011-04-28T08:27:23.046Z"><name>jack#0</name><address>china GuangZhou# 0</address></user>
<account id="2"><name>haha#1</name><email>email1@121.com</email><address>address#1</address><brithday>
<brithday>2010-11-21</brithday></brithday></account><user age="24" sex="false" brithday="2011-04-28T08:27:23.046Z">
<name>jack#1</name><address>china GuangZhou# 1</address></user>
<account id="3"><name>haha#2</name><email>email2@122.com</email><address>address#2</address>
<brithday><brithday>2010-11-22</brithday></brithday></account>
<user age="25" sex="false" brithday="2011-04-28T08:27:23.046Z"><name>jack#2</name>
<address>china GuangZhou# 2</address></user></list-bean>

7、 轉換Map到XML

/**
 * <b>function:</b>轉換帶有Map屬性的JavaBean
 * @author hoojo
 * @return
 */
@RequestMapping("/doMapXMLJibx")
public ModelAndView doMapXMLJibxView() {
    System.out.println("#################ViewController doMapXMLJibxView##################");
    ModelAndView mav = new ModelAndView("jibxMarshallingView");
    
    MapBean mapBean = new MapBean();
    
    Map<String, Object> map = new HashMap<String, Object>();
    Account bean = new Account();
    bean.setAddress("北京");
    bean.setEmail("email");
    bean.setId(1);
    bean.setName("jack");
    Brithday day = new Brithday();
    day.setBrithday("2010-11-22");
    bean.setBrithday(day);
    map.put("NO1", bean);
    
    bean = new Account();
    bean.setAddress("china");
    bean.setEmail("tom@125.com");
    bean.setId(2);
    bean.setName("tom");
    day = new Brithday("2011-11-22");
    bean.setBrithday(day);
    map.put("NO2", bean);
    
    mapBean.setMap(map);
    
    mav.addObject(mapBean);
    
    return mav;
}

在瀏覽器中請求:http://localhost:8080/SpringMVC4View/jibx/view/doMapXMLJibx.do

結果如下:

<?xml version="1.0"?>
<map-bean><hashmap size="2"><entry key="NO2"><account id="2"><name>tom</name><email>tom@125.com</email><address>china</address>
<brithday><brithday>2011-11-22</brithday></brithday></account>
</entry><entry key="NO1"><account id="1"><name>jack</name><email>email</email><address>北京</address>
<brithday><brithday>2010-11-22</brithday></brithday></account></entry></hashmap></map-bean>

總結,jibx應用比較廣,在WebService中都有使用jibx。Jibx速度比較快,就是在開始部署使用的時候需要寫bind.xml檔案。不過官方提供了工具類,這個也不麻煩。

 

六、 Jackson轉換Java物件

1、 jackson有專門的檢視MappingJacksonJsonView,只需用配置這個檢視就可以完成轉換json了。使用jackson需要新增如下jar包:

clip_image006

如果你對Jackson轉換Java物件還沒有什麼瞭解的話,你可以參考:

For cnblogs:http://www.cnblogs.com/hoojo/archive/2011/04/22/2024628.html

For csdn:http://blog.csdn.net/IBM_hoojo/archive/2011/04/22/6340762.aspx

2、 然後需要在dispatcher.xml中新增檢視配置,配置如下:

<bean name="jsonView" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
    <property name="encoding">
        <value type="org.codehaus.jackson.JsonEncoding">UTF8</value>
    </property>
    <property name="contentType" value="text/html;charset=UTF-8"/>
</bean>

3、 將Java物件轉換JSON

package com.hoo.controller;
 
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.hoo.entity.Account;
import com.hoo.entity.Brithday;
import com.hoo.entity.User;
 
/**
 * <b>function:</b>用MappingJacksonJsonView檢視和Jackson轉換Json
 * @author hoojo
 * @createDate 2011-4-28 下午04:52:23
 * @file JacksonJsonViewController.java
 * @package com.hoo.controller
 * @project SpringMVC4View
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
@Controller
@RequestMapping("/jackson/view")
public class JacksonJsonViewController {
    
    /**
     * <b>function:</b>轉換普通Java物件
     * @author hoojo
     * @createDate 2011-4-28 下午05:14:18
     * @return
     */
    @RequestMapping("/doBeanJsonView")
    public ModelAndView doBeanJsonView() {
        System.out.println("#################ViewController doBeanJsonView##################");
        ModelAndView mav = new ModelAndView("jsonView");
        User user = new User();
        user.setAddress("china GuangZhou");
        user.setAge(23);
        user.setBrithday(new Date());
        user.setName("jack");
        user.setSex(true);
        
        Account bean = new Account();
        bean.setAddress("北京");
        bean.setEmail("email");
        bean.setId(1);
        bean.setName("haha");
        Brithday day = new Brithday();
        day.setBrithday("2010-11-22");
        bean.setBrithday(day);
        
        mav.addObject(bean);
        return mav;
    }
}

上面使用了剛才我們配置的jsonView檢視,通過這個檢視就可以將ModelAndView中的資料轉換成JSON資料。

在瀏覽器中請求:http://localhost:8080/SpringMVC4View/jackson/view/doBeanJsonView.do

結果如下:

{"account":{"address":"北京","name":"haha","id":1,"email":"email","brithday":{"brithday":"2010-11-22"}}}

4、 轉換Map到JSON

/**
 * <b>function:</b>轉換Map集合
 * @author hoojo
 * @createDate 2011-4-28 下午05:14:33
 * @return
 */
@RequestMapping("/doMapJsonView")
public ModelAndView doMapJsonView() {
    System.out.println("#################ViewController doBeanJsonView##################");
    ModelAndView mav = new ModelAndView("jsonView");
    User user = new User();
    user.setAddress("china GuangZhou");
    user.setAge(23);
    user.setBrithday(new Date());
    user.setName("jack");
    user.setSex(true);
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("user", user);
    map.put("success", true);
    mav.addObject(map);
    mav.addObject("title", "ViewController doBeanJsonView");
    return mav;
}

在WebBrowser中請求:http://localhost:8080/SpringMVC4View/jackson/view/doMapJsonView.do

結果如下:

{"hashMap":{"success":true,"user":{"address":"china GuangZhou","name":"jack","age":23,"sex":true,"brithday":1303982296953}},
"title":"ViewController doBeanJsonView"}

5、 轉換List到JSON

/**
 * <b>function:</b>轉換List集合
 * @author hoojo
 * @createDate 2011-4-28 下午05:14:54
 * @return
 */
@RequestMapping("/doListJsonView")
public ModelAndView doListJsonView() {
    System.out.println("#################ViewController doBeanJsonView##################");
    ModelAndView mav = new ModelAndView("jsonView");
    List<User> list = new ArrayList<User>();
    for (int i = 0; i < 3; i++) {
        User user = new User();
        user.setAddress("china GuangZhou#" + i);
        user.setAge(23 + i);
        user.setBrithday(new Date());
        user.setName("jack_" + i);
        user.setSex(true);
        list.add(user);
    }
    
    mav.addObject(list);
    return mav;
}

在瀏覽器中請求http://localhost:8080/SpringMVC4View/jackson/view/doListJsonView.do

結果如下:

{"userList":[{"address":"china GuangZhou#0","name":"jack_0","age":23,"sex":true,"brithday":1303982399265},
{"address":"china GuangZhou#1","name":"jack_1","age":24,"sex":true,"brithday":1303982399265},
{"address":"china GuangZhou#2","name":"jack_2","age":25,"sex":true,"brithday":1303982399265}]}

總結,spring對jackson提供了專門的檢視,整合起來也比較方便。而且jackson也比較簡單易用。

 

七、 JSON-lib轉換Java到JSON

1、 Spring沒有提供JSON-lib的view檢視,不過沒有關係。我們可以自己擴充套件一個,只需用繼承AbstractView類,實現裡面的方法就可以了。首先你需要了解JSON-lib,如果你還不瞭解JSON-lib的話,建議閱讀:

For cnblogs: http://www.cnblogs.com/hoojo/archive/2011/04/21/2023805.html

For csdn: http://blog.csdn.net/IBM_hoojo/archive/2011/04/21/6339246.aspx

然後你需要在工程中新增如下jar檔案:

clip_image008

2、 因為Spring沒有提供view,我們需要自己實現一個。程式碼如下:

package com.hoo.veiw.xml;
 
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONSerializer;
import net.sf.json.JsonConfig;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.servlet.view.AbstractView;
 
/**
 * <b>function:</b>擴充套件AbstractView 實現JSON-lib檢視
 * @author hoojo
 * @createDate 2011-4-28 下午05:26:43
 * @file MappingJsonlibVeiw.java
 * @package com.hoo.veiw.xml
 * @project SpringMVC4View
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
public class MappingJsonlibVeiw extends AbstractView {
    
    public static final String DEFAULT_CONTENT_TYPE = "application/json";
    
    public static final String DEFAULT_CHAR_ENCODING = "UTF-8";
 
    private String encodeing = DEFAULT_CHAR_ENCODING;
 
    public void setEncodeing(String encodeing) {
        this.encodeing = encodeing;
    }
 
    private Set<String> renderedAttributes;
    
    private JsonConfig cfg = null;
    
    public void setCfg(JsonConfig cfg) {
        this.cfg = cfg;
    }
 
    public MappingJsonlibVeiw() {
        setContentType(DEFAULT_CONTENT_TYPE);
    }
    
    @Override
    protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        model = filterModel(model);
        response.setCharacterEncoding(encodeing);
        
        PrintWriter out = response.getWriter();
        if (cfg == null) {
            out.print(JSONSerializer.toJSON(model));
        } else {
            out.print(JSONSerializer.toJSON(model, cfg));
        }
    }
 
    /**
     * Filters out undesired attributes from the given model.
     * <p>Default implementation removes {@link BindingResult} instances and entries not included in the {@link
     * #setRenderedAttributes(Set) renderedAttributes} property.
     */
    protected Map<String, Object> filterModel(Map<String, Object> model) {
        Map<String, Object> result = new HashMap<String, Object>(model.size());
        Set<String> renderedAttributes =
                !CollectionUtils.isEmpty(this.renderedAttributes) ? this.renderedAttributes : model.keySet();
        for (Map.Entry<String, Object> entry : model.entrySet()) {
            if (!(entry.getValue() instanceof BindingResult) && renderedAttributes.contains(entry.getKey())) {
                result.put(entry.getKey(), entry.getValue());
            }
        }
        return result;
    }
}

上面的程式碼不是很複雜,首先我們設定contentType,這個屬性在AbstractView這個父類中有setter方法可以完成設定。

然後就是預設的編碼格式,這個編碼格式設定到response上。預設UTF-8編碼。在renderMergedOutputModel方法中可以看到設定。

第三就是filterModule方法,這個方法是得到ModelAndView中我們新增物件,過濾掉BindingResult的資訊。

最後就是renderMergedOutputModel方法,這個方法最為核心,但也很簡單。過濾model獲得要轉換的model資料,設定response編碼格式。利用response的Writer輸出JSON資訊,通過JSONSerializer轉換Java到JSON。

3、 在dispatcher.xml中配置jsonlibView這個檢視

<-- 自定義JSONlib的json檢視 -->
<bean name="jsonlibView" class="com.hoo.veiw.xml.MappingJsonlibVeiw">
    <property name="contentType" value="text/html;charset=UTF-8"/>
    <property name="encodeing" value="gbk"/>
</bean>

4、 轉換普通Java物件

package com.hoo.controller;
 
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.hoo.entity.Account;
import com.hoo.entity.Brithday;
import com.hoo.entity.User;
 
/**
 * <b>function:</b>
 * @author hoojo
 * @createDate 2011-4-28 下午05:58:02
 * @file JsonlibMappingViewController.java
 * @package com.hoo.controller
 * @project SpringMVC4View
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
@Controller
@RequestMapping("/jsonlib/view")
public class JsonlibMappingViewController {
    /**
     * <b>function:</b>轉換普通Java物件
     * @author hoojo
     * @createDate 2011-4-28 下午05:14:18
     * @return
     */
    @RequestMapping("/doBeanJsonView")
    public ModelAndView doBeanJsonView() {
        System.out.println("#################ViewController doBeanJsonView##################");
        ModelAndView mav = new ModelAndView("jsonlibView");
        User user = new User();
        user.setAddress("china GuangZhou");
        user.setAge(23);
        user.setBrithday(new Date());
        user.setName("jack");
        user.setSex(true);
        
        Account bean = new Account();
        bean.setAddress("北京");
        bean.setEmail("email");
        bean.setId(1);
        bean.setName("haha");
        Brithday day = new Brithday();
        day.setBrithday("2010-11-22");
        bean.setBrithday(day);
        
        mav.addObject(bean);
        return mav;
    }
}

在WebBrowser中請求http://localhost:8080/SpringMVC4View/jsonlib/view/doBeanJsonView.do

結果如下:

{"account":{"address":"北京","brithday":{"brithday":"2010-11-22"},"email":"email","id":1,"name":"haha"}}

5、 轉換Map到JSON

/**
 * <b>function:</b>轉換Map集合
 * @author hoojo
 * @createDate 2011-4-28 下午05:14:33
 * @return
 */
@RequestMapping("/doMapJsonView")
public ModelAndView doMapJsonView() {
    System.out.println("#################ViewController doBeanJsonView##################");
    ModelAndView mav = new ModelAndView("jsonlibView");
    User user = new User();
    user.setAddress("china GuangZhou");
    user.setAge(23);
    user.setBrithday(new Date());
    user.setName("jack");
    user.setSex(true);
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("user", user);
    map.put("success", true);
    mav.addObject(map);
    mav.addObject("title", "ViewController doBeanJsonView");
    return mav;
}

在WebBrowser中請求http://localhost:8080/SpringMVC4View/jsonlib/view/doMapJsonView.do

結果如下:

{"hashMap":{"success":true,"user":{"address":"china GuangZhou","age":23,
"brithday":{"date":28,"day":4,"hours":18,"minutes":20,"month":3,"seconds":8,
"time":1303986008703,"timezoneOffset":-480,"year":111},"name":"jack","sex":true}},
"title":"ViewController doBeanJsonView"}

發現時間被分解成一個物件了,這裡需要用JSONConfig的JsonValueProcessor將brithday過濾下,然後用SimpleDateFormate進行格式轉換。

6、 轉換List集合

/**
 * <b>function:</b>轉換List集合
 * @author hoojo
 * @createDate 2011-4-28 下午05:14:54
 * @return
 */
@RequestMapping("/doListJsonView")
public ModelAndView doListJsonView() {
    System.out.println("#################ViewController doBeanJsonView##################");
    ModelAndView mav = new ModelAndView("jsonlibView");
    List<User> list = new ArrayList<User>();
    for (int i = 0; i < 3; i++) {
        User user = new User();
        user.setAddress("china GuangZhou#" + i);
        user.setAge(23 + i);
        user.setBrithday(new Date());
        user.setName("jack_" + i);
        user.setSex(true);
        list.add(user);
    }
    
    mav.addObject(list);
    return mav;
}

在瀏覽器中請求http://localhost:8080/SpringMVC4View/jsonlib/view/doListJsonView.do

結果如下:

{"userList":[{"address":"china GuangZhou#0","age":23,"brithday":{"date":28,"day":4,"hours":19,"minutes":2,"month":3,"seconds":54,
"time":1303988574328,"timezoneOffset":-480,"year":111},"name":"jack_0","sex":true},
{"address":"china GuangZhou#1","age":24,"brithday":{"date":28,"day":4,"hours":19,"minutes":2,"month":3,"seconds":54,
"time":1303988574328,"timezoneOffset":-480,"year":111},"name":"jack_1","sex":true},{"address":"china GuangZhou#2","age":25,
"brithday":{"date":28,"day":4,"hours":19,"minutes":2,"month":3,"seconds":54,"time":1303988574328,"timezoneOffset":-480,"year":111},
"name":"jack_2","sex":true}]}

相關文章