问题描述
我想在使用Spring Marshaller时强制转义特殊字符.当我使用javax.xml.bind.Marshaller
I want to force escaping special characters when I use Spring Marshaller. Below code is perfectly working when I use javax.xml.bind.Marshaller
图书班
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时,相同类型的代码不起作用,下面是代码
But same kind of code is not working when I use org.springframework.oxm.jaxb.Jaxb2Marshaller, Below is the 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();
}
}
输出
<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>
第一个代码段未对特殊字符进行编码.但是,虽然我设置了属性,但是使用Spring的第二个片段确实进行了编码.我必须在项目中使用Spring才能不影响现有代码.有什么办法可以解决
The first snippet didn't encode the special characters. But the second snippet which is using Spring did encode though I set property. I have to use Spring in my project for not affecting existing code. Is there any way I can fix it
推荐答案
好,我遇到了同样的问题,并且我用这种方法解决了.
Ok, I had the same problem, and I solved it this way.
第一件事.您应该创建两个bean.一个用于Jaxb2Marshaller
,另一个用于MarshallingHttpMessageConverter
.我假设您想保留您的配置,所以我将使用您的代码.
First things first. You should create two beans. One for the Jaxb2Marshaller
and another MarshallingHttpMessageConverter
. I'm supposing that you want to keep your configuration, so I'm going to use your code.
创建Jaxb2Marshaller
bean:
@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");
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;
try {
fos = new FileOutputStream(selectedFile);
marshaller.marshal(book, new StreamResult(fos));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
fos.close();
}
}
return jaxb2Marshaller;
}
好,我使用的是 Java 8 ,所以我将 com.sun.xml.bind.marshaller.CharacterEscapeHandler 更改为 com.sun.xml.internal .bind.marshaller.CharacterEscapeHandler ,如上所示.
Well, I'm using Java 8 so I changed com.sun.xml.bind.marshaller.CharacterEscapeHandler to com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler as you can see above.
创建MarshallingHttpMessageConverter
bean:
@Bean
public MarshallingHttpMessageConverter getMarshallingHttpMessageConverter() {
return new MarshallingHttpMessageConverter(getJaxb2Marshaller());
}
您必须注意,我已经创建了自己的HttpMessageConverter来解决该问题.这是因为Spring每次需要将实体或DTO转换为XML对象时,都会使用自己的转换器创建一个新的Marshaller
实例.因此,我认为下面的代码将解决您的问题.希望对您有帮助.
You must notice that I've created my own HttpMessageConverter to solve the problem. That's because Spring uses it's own converter that creates a new Marshaller
instance everytime it needs to convert a entity or a DTO to XML objetct. So, I think the code below will solve your problem. Hope it helps you.
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 {
@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");
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;
try {
fos = new FileOutputStream(selectedFile);
marshaller.marshal(book, new StreamResult(fos));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
fos.close();
}
}
return jaxb2Marshaller;
}
@Bean
public MarshallingHttpMessageConverter getMarshallingHttpMessageConverter() {
return new MarshallingHttpMessageConverter(getJaxb2Marshaller());
}
}
这篇关于在春季强制将XML编组中的特殊字符转义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!