6

Marshaller を使用するときに書式設定を有効にする方法については知っています。しかし、私は Apache CXF (JAX-RS) を使用しており、次のような応答を返していreturn Response.ok(entity).build();ます。

出力をフォーマットする方法が見つかりませんでした。どうすればいいですか?

4

2 に答える 2

11

まず、XMLのフォーマットされた出力を取得する方法は、マーシャラーに適切なプロパティを設定することです(通常、CXFを使用する場合はJAXBですが、JAXBは信頼できる仕事をするので問題ありません)。つまり、どこかでこれを行うことができます。

marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

問題は、必ずしもすべての出力をフォーマットする必要がないことです。オーバーヘッドがかなり増えます。幸いなことに、あなたはすでに明示的なを作成しているResponseので、その機能をさらに使用することができます。

Marshaller marshaller = JAXBContext.newInstance(entity.getClass()).createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
StringWriter sw = new StringWriter();
marshaller.marshal(entity, sw);

return Response.ok(sw.toString(), MediaType.APPLICATION_XML_TYPE).build();

別の方法がこのJIRAの問題で言及されています(それ自体は閉じていますが、それはあなたにとってそれほど問題ではありません):

回避策は、オプションのインデントを要求するために使用されるカスタムクエリをチェックできるカスタム出力ハンドラーを登録することです。

http://svn.apache.org/repos/asf/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/FormatResponseHandler.java

JAXBElementProviderとJSONProviderはJAXBMarshallerによって駆動されるため、デフォルトでは、現在のメッセージのMarshaller.JAXB_FORMATTED_OUTPUTプロパティをチェックします。

これにより、次のようなコードが生成されます。

public class FormattedJAXBInterceptor extends AbstractPhaseInterceptor<Message> {
    public FormattedJAXBInterceptor() {
        super(Phase.PRE_STREAM);
    }

    public void handleMessage(Message message) {
        message.put(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    }

    public void handleFault(Message message) {
        message.put(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    }
}

CXFサイトでは、インターセプターの登録について説明しています。

于 2012-04-14T17:53:20.730 に答える
1

を実装できますMessageBodyWriter。これは、オブジェクトを XML にマーシャリングする方法をオーバーライドできる JAX-RS メカニズムです。

package org.example;

import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;

import javax.ws.rs.*;
import javax.ws.rs.core.*;
import javax.ws.rs.ext.*;
import javax.xml.bind.*;

@Provider
@Produces(MediaType.APPLICATION_XML)
public class FormattingWriter implements MessageBodyWriter<Object>{

    @Context
    protected Providers providers;

    public boolean isWriteable(Class<?> type, Type genericType,
        Annotation[] annotations, MediaType mediaType) {
        return true;
    }

    public void writeTo(Object object, Class<?> type, Type genericType,
        Annotation[] annotations, MediaType mediaType,
        MultivaluedMap<String, Object> httpHeaders,
        OutputStream entityStream) throws IOException,
        WebApplicationException {
        try {
            ContextResolver<JAXBContext> resolver 
                = providers.getContextResolver(JAXBContext.class, mediaType);
            JAXBContext jaxbContext;
            if(null == resolver || null == (jaxbContext = resolver.getContext(type))) {
                jaxbContext = JAXBContext.newInstance(type);
            }
            Marshaller m = jaxbContext.createMarshaller();
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            m.marshal(object, entityStream);
        } catch(JAXBException jaxbException) {
            throw new WebApplicationException(jaxbException);
        }
    }

    public long getSize(Object t, Class<?> type, Type genericType,
        Annotation[] annotations, MediaType mediaType) {
        return -1;
    }

}

詳細については

MessageBodyWriter以下は、が JAX-RS サービスの一部として使用される完全な例へのリンクです。

于 2012-04-14T21:06:46.713 に答える