2016-07-14 10 views
3

Ich möchte Sonderzeichen erzwingen, wenn ich Spring Marshaller verwende. Im Folgenden Code funktioniert perfekt, wenn ich javax.xml.bind.MarshallerErzwingen von Sonderzeichen Sonderzeichen beim XML-Marshalling im Frühjahr

Buch Klasse

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 
      + "]"; 
    } 
} 

Objekt zu 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); 

Ausgabe verwenden:

<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>

Aber gleiche Art von Code funktioniert nicht, wenn ich org.springframework.oxm.jaxb.Jaxb2Marshaller verwenden, ist unter dem Code

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(); 
     } 
    } 

Ausgabe

<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>

Das erste Snippet hat die Sonderzeichen nicht codiert. Aber das zweite Snippet, das Spring verwendet, hat zwar eine Eigenschaft codiert, aber ich habe es festgelegt. Ich muss Spring in meinem Projekt verwenden, um den vorhandenen Code nicht zu beeinflussen. Gibt es eine Möglichkeit, ich kann es beheben

+0

Welche Version von Spring verwenden Sie? Ich habe den gleichen Code von Jaxb2Marshaller mit Spring 4.x versucht und es funktioniert für mich. –

+0

Ich benutze Spring-oxm-4.1.5.RELEASE.jar –

+0

Können Sie die Buchklasse teilen? –

Antwort

0

Ok, ich hatte das gleiche Problem, und ich löste es so.

Erste Dinge zuerst. Sie sollten zwei Beans erstellen. Eine für die Jaxb2Marshaller und eine andere MarshallingHttpMessageConverter. Ich nehme an, dass Sie Ihre Konfiguration behalten möchten, also werde ich Ihren Code verwenden.

Erstellen der Jaxb2Marshaller Bohne:

@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; 
} 

Nun, ich bin mit Java 8 so änderte ich com.sun.xml.bind.marshaller.CharacterEscapeHandler zu com.sun.xml. intern.bind.marshaller.CharacterEscapeHandler wie Sie oben sehen können.

Erstellen die MarshallingHttpMessageConverter Bohne:

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

Sie müssen feststellen, dass ich meinen eigenen HttpMessageConverter erstellt habe, das Problem zu lösen. Das liegt daran, dass Spring einen eigenen Konverter verwendet, der jedes Mal eine neue Marshaller Instanz erstellt, wenn eine Entität oder ein DTO in ein XML-Objekt konvertiert werden muss. Also, ich denke der folgende Code wird dein Problem lösen. Hoffe es hilft dir.

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()); 
    } 
}