2016-07-14 71 views
3

我想在使用Spring Marshaller時強制轉義特殊字符。下面的代碼是完全工作時,我使用javax.xml.bind.Marshaller強制轉義XML中的特殊字符在春季編組

圖書類

package com.odr.core.action; 

import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlRegistry; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlRootElement(name = "book") 
public class Book { 

    private String name; 
    private String author; 
    private String publisher; 
    private String isbn; 

    @XmlJavaTypeAdapter(value=CDATAAdapter.class) 
    private String description; 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String getAuthor() { 
     return author; 
    } 

    public void setAuthor(String author) { 
     this.author = author; 
    } 

    public String getPublisher() { 
     return publisher; 
    } 

    public void setPublisher(String publisher) { 
     this.publisher = publisher; 
    } 

    public String getIsbn() { 
     return isbn; 
    } 

    public void setIsbn(String isbn) { 
     this.isbn = isbn; 
    } 

    public String getDescription() { 
     return description; 
    } 

    public void setDescription(String description) { 
     this.description = description; 
    } 

    @Override 
    public String toString() { 
     return "Book [name=" + name + ", author=" + author + ", publisher=" 
      + publisher + ", isbn=" + isbn + ", description=" + description 
      + "]"; 
    } 
} 

對象到XML

 writer = new BufferedWriter(new FileWriter(selectedFile)); 
     context = JAXBContext.newInstance(Book.class); 
     Marshaller m = context.createMarshaller(); 
     m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 

     m.setProperty("com.sun.xml.bind.marshaller.CharacterEscapeHandler", 
       new CharacterEscapeHandler() { 
        @Override 
        public void escape(char[] ch, int start, int length, 
          boolean isAttVal, Writer writer) 
          throws IOException { 
         writer.write(ch, start, length); 
        } 
       }); 
     m.marshal(book, writer); 

輸出:

<description> 
 

 
<![CDATA[<p>With hundreds of practice questions and hands-on exercises, <b>SCJP Sun Certified Programmer for Java 6 Study Guide</b> covers what you need to know--and shows you how to prepare--for this challenging exam. </p>]]> 
 
</description>

但是當我使用org.springframework.oxm.jaxb.Jaxb2Marshaller同樣的代碼不工作,下面是代碼

Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller(); 
    Map<String, Object> map = new HashMap<String, Object>(); 
    map.put("jaxb.formatted.output", true); 
    jaxb2Marshaller.setPackagesToScan("com.odr.core.action"); 
    // com.sun.xml.bind.characterEscapeHandler 
    // com.sun.xml.bind.marshaller.CharacterEscapeHandler 
    map.put("com.sun.xml.bind.marshaller.CharacterEscapeHandler", 
      new CharacterEscapeHandler() { 
       @Override 
       public void escape(char[] ac, int i, int j, boolean flag, 
         Writer writer) throws IOException { 
        writer.write(ac, i, j); 
       } 
      }); 
    jaxb2Marshaller.setMarshallerProperties(map); 

    org.springframework.oxm.Marshaller marshaller = jaxb2Marshaller; 
    FileOutputStream fos = null; 
    // String fileNamePath = directory.getAbsolutePath() + "\\" + fileName; 

    try { 
     // fos = new FileOutputStream(fileNamePath); 
     fos = new FileOutputStream(selectedFile); 
     marshaller.marshal(book, new StreamResult(fos)); 

     // File f = new File(directory,fileName); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } finally { 
     if (fos != null) { 
      fos.close(); 
     } 
    } 

輸出

<description>&lt;![CDATA[&lt;p&gt;With hundreds of practice questions and hands-on exercises, &lt;b&gt;SCJP Sun Certified Programmer for Java 6 Study Guide&lt;/b&gt; covers what you need to know--and shows you how to prepare--for this challenging exam. &lt;/p&gt;]]&gt;</description>

第一個片段沒有對特殊字符進行編碼。但是使用Spring的第二個代碼片段雖然我設置了屬性,但它編碼。我必須在我的項目中使用Spring,不會影響現有的代碼。有沒有什麼辦法可以修復它

+0

您使用的是哪個版本的Spring?我在Spring 4.x中試用了Jaxb2Marshaller的相同代碼,它適用於我。 –

+0

Im使用spring-oxm-4.1.5.RELEASE.jar –

+0

你可以分享Book類嗎? –

回答

0

好吧,我有同樣的問題,我解決了這個問題。

第一件事第一件事。你應該創建兩個bean。一個用於Jaxb2Marshaller,另一個用於MarshallingHttpMessageConverter。我假設你想保留你的配置,所以我要使用你的代碼。

創建Jaxb2Marshaller豆:

@Bean 
public Jaxb2Marshaller getJaxb2Marshaller() { 
    Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller(); 
    Map<String, Object> map = new HashMap<String, Object>(); 
    map.put("jaxb.formatted.output", true); 
    jaxb2Marshaller.setPackagesToScan("com.odr.core.action"); 
    // com.sun.xml.bind.characterEscapeHandler 
    // com.sun.xml.bind.marshaller.CharacterEscapeHandler 
    map.put("com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler", 
      new CharacterEscapeHandler() { 
       @Override 
       public void escape(char[] ac, int i, int j, boolean flag, 
            Writer writer) throws IOException { 
        writer.write(ac, i, j); 
       } 
      }); 
    jaxb2Marshaller.setMarshallerProperties(map); 

    org.springframework.oxm.Marshaller marshaller = jaxb2Marshaller; 
    FileOutputStream fos = null; 
    // String fileNamePath = directory.getAbsolutePath() + "\\" + fileName; 

    try { 
     // fos = new FileOutputStream(fileNamePath); 
     fos = new FileOutputStream(selectedFile); 
     marshaller.marshal(book, new StreamResult(fos)); 

     // File f = new File(directory,fileName); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } finally { 
     if (fos != null) { 
      fos.close(); 
     } 
    } 

    return jaxb2Marshaller; 
} 

好,我使用的Java 所以我改變com.sun.xml.bind.marshaller.CharacterEscapeHandler了com.sun.xml。你可以在上面看到internal.bind.marshaller.CharacterEscapeHandler

創建MarshallingHttpMessageConverter豆:

@Bean 
public MarshallingHttpMessageConverter getMarshallingHttpMessageConverter() { 
    return new MarshallingHttpMessageConverter(getJaxb2Marshaller()); 
} 

你必須看到,我已經創建了自己的HttpMessageConverter來解決問題。這是因爲Spring使用自己的轉換器,每次需要將實體或DTO轉換爲XML objetct時,都會創建一個新的Marshaller實例。所以,我認爲下面的代碼將解決您的問題。希望它可以幫助你。

import com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.http.converter.xml.MarshallingHttpMessageConverter; 
import org.springframework.oxm.jaxb.Jaxb2Marshaller; 

@Configuration 
public class XmlParseConfig { 

    /** 
    * Constrói o bean de marshall e unmarshall. 
    * 
    * @return A instância do BEAN usando a implementação de {@link Jaxb2Marshaller} 
    */ 
    @Bean 
    public Jaxb2Marshaller getJaxb2Marshaller() { 
     Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller(); 
     Map<String, Object> map = new HashMap<String, Object>(); 
     map.put("jaxb.formatted.output", true); 
     jaxb2Marshaller.setPackagesToScan("com.odr.core.action"); 
     // com.sun.xml.bind.characterEscapeHandler 
     // com.sun.xml.bind.marshaller.CharacterEscapeHandler 
     map.put("com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler", 
       new CharacterEscapeHandler() { 
        @Override 
        public void escape(char[] ac, int i, int j, boolean flag, 
             Writer writer) throws IOException { 
         writer.write(ac, i, j); 
        } 
       }); 
     jaxb2Marshaller.setMarshallerProperties(map); 

     org.springframework.oxm.Marshaller marshaller = jaxb2Marshaller; 
     FileOutputStream fos = null; 
     // String fileNamePath = directory.getAbsolutePath() + "\\" + fileName; 

     try { 
      // fos = new FileOutputStream(fileNamePath); 
      fos = new FileOutputStream(selectedFile); 
      marshaller.marshal(book, new StreamResult(fos)); 

      // File f = new File(directory,fileName); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } finally { 
      if (fos != null) { 
       fos.close(); 
      } 
     } 

     return jaxb2Marshaller; 
    } 

    @Bean 
    public MarshallingHttpMessageConverter getMarshallingHttpMessageConverter() { 
     return new MarshallingHttpMessageConverter(getJaxb2Marshaller()); 
    } 
}