2016-07-14 111 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()); 
    } 
}