如果您查看链接到的答案,您会看到使用了StreamResult。在答案中,StringWriter 被传递给构造函数,但是如果你查看 Javadoc,它有一个重载的构造函数,它也接受一个 OutputStream。因此,如果您要返回StreamingOutput,只需将OutputStream 从StreamingOutput#write(OutputStream) 方法传递给StreamResult 构造函数。答案中的其他所有内容都应该相同。
return new StreamingOutput() {
@Override
public void write(OutputStream out)
throws IOException, WebApplicationException {
try {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
StreamResult result = new StreamResult(out);
DOMSource source = new DOMSource(doc);
transformer.transform(source, result);
out.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
};
这是我用来测试的完整资源类。请注意,我使用@Produces(MediaType.APPLICATION_XML)。如果数据是 XML1,则设置为 application/octet-stream 没有意义。
@Path("dom")
public class DomXmlResource {
@GET
@Produces(MediaType.APPLICATION_XML)
public StreamingOutput getXml() throws Exception {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("company");
doc.appendChild(rootElement);
Element staff = doc.createElement("Staff");
rootElement.appendChild(staff);
staff.setAttribute("id", "1");
Element firstname = doc.createElement("firstname");
firstname.appendChild(doc.createTextNode("yong"));
staff.appendChild(firstname);
return new StreamingOutput() {
@Override
public void write(OutputStream out)
throws IOException, WebApplicationException {
try {
Transformer transformer = TransformerFactory.newInstance()
.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
StreamResult result = new StreamResult(out);
DOMSource source = new DOMSource(doc);
transformer.transform(source, result);
out.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
};
}
}
更新
要自动下载文件(而不是显示 XML 结果),我们实际上需要添加带有 attachment 值的 Content-Disposition 标头。为此,我们应该返回Response,而不是从方法中返回StreamingOutput,其中实体将是StreamingOutput
@Path("dom")
public class DomXmlResource {
@GET
@Produces(MediaType.APPLICATION_XML)
public Response getXml() throws Exception {
...
StreamingOutput entity = new StreamingOutput() {
@Override
public void write(OutputStream out)
throws IOException, WebApplicationException {
...
}
};
return Response.ok(entity)
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment;filename=file.xml")
.build();
}
}
更新 2
如果您还不知道,您可以简单地返回您的 POJO(或它们的列表),它们会自动序列化为 XML。您不需要手动使用 DOM 类来创建 XML 结构。已经有Entity Providers 为我们处理从 POJO 到 XML 的转换。比如我们有如下POJO(需要用@XmlRootElement注解)
@XmlRootElement
public class User {
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
然后我们可以直接返回它,它会自动序列化为
<user><name>footer</name></user>
这是一个例子
@Path("pojo")
public class PojoXmlResource {
@GET
@Produces("application/xml")
public Response getXml() {
User user = new User();
user.setName("Jane Doe");
return Response.ok(user)
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment;filename=user.xml")
.build();
}
}
它不那么凌乱了,不是吗?如果要返回用户列表,则需要将其包装在GenericEntity中
List<User> users = Arrays.asList(user1, user2, user3);
GenericEntity<List<User>> entity = new GenericEntity<List<User>>(users){};
return Response.ok(entity)
...
.build();
1。见:Do I need Content-Type: application/octet-stream for file download?