2

状況は、ベンダーが、私のサービスに送信できる XML ドキュメントの XML スキーマを提供したということです。私は彼らのスキーマが気に入らなかったので、受信した XML を変換する XSLT と共に独自のスキーマを作成しました。私のスキーマは JAXB の xjc ツールで使用され、いくつかの pojo を適切なオブジェクト モデルにバインドする .java ファイルを生成しました。変換ステップが必要であるという事実がなければ、これを Spring MVC に実装するのは簡単です。

受信した XML は、JAXB クラスにマップされる前に、まず変換する必要があります。次のスニペットにほぼ類似しています。

@RequestMapping(value="/receiveXml", method=RequestMethod.POST )
public ResponseEntity<String> receiveXml( @RequestBody String vendorXmlPayload )         {      
  // 1.  Make sure vendorXmlPayload adheres to vendor's schema
  vendorSchema.newValidator().validate(new StreamSource(new StringReader(vendorXmlPayload)));

  // 2.  Transform xml payload to my schema
  StringWriter sw = new StringWriter();
  transformer.transform(new StreamSource(new StringReader(vendorXmlPayload)), new StreamResult(sw))

  // 3.  Validate transformed XML against my schema
  mySchema.newValidator().validate(new StreamSource(new StringReader(sw.toString())));

  // 4.  Unmarshall to JAXB-annotated classes
  DomainObject obj = (DomainObject) unmarshaller.unmarshal(new StreamSource(new StringReader(sw.toString())));


  (errors != null) ? return ... HttpStatus.BAD_REQUEST : return ..... HttpStatus.OK
}    

MVC コントローラーにすべてを凝縮するためのエレガントな Spring アノテーションはありますか? つまり、 @RequestBody アノテーションなどを使用して変換と非整列化を実行する方法はありますか? おそらく、この架空のスニペットのように:

@RequestMapping(value="/receiveXml", method=RequestMethod.POST )
@Transform(transformer="myTransform.xslt")
public ResponseEntity<String> receiveXml( @RequestBody DomainObj domainObj)         
{
  // Process my DomainObj as I normally would
  (errors != null) ? return ... HttpStatus.BAD_REQUEST : return ..... HttpStatus.OK
}

@InitBinder は、このシナリオに適合しているようには見えません。ほとんどの「Spring MVC XSLT」検索は、入力ではなく出力の変換を扱います。

4

1 に答える 1

3

箱から出してすぐにこのようなものがあるかどうかは疑問ですが、次の行に沿って再利用可能なものを構築できるはずです:

@XmlWithTransform などの新しいアノテーションを自分で定義します。これは、次のようにコントローラーで指定できる xslt の場所などのパラメーターを受け取ります。

@RequestMapping(value="/receiveXml", method=RequestMethod.POST )
    public ResponseEntity<String> receiveXml( @XmlWithTransform(usingxslt="anxsl.xsl")     CustomType customType )

次に、リクエスト ボディ xml を取り込めるカスタムを記述し、HandlerMethodArgumentResolver注釈の xslt 引数を使用して変換し、引数として指定された型にバインドします。

import java.io.StringReader;

import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;

import org.springframework.core.MethodParameter;
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

public class XsltTransformingHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver{

    Unmarshaller unmarshaller;
    @Override
    public boolean supportsParameter(MethodParameter parameter){
        return (parameter.getMethodAnnotation(XmlWithTransform.class)!=null);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        XmlWithTransform xmlWithTransform = parameter.getMethodAnnotation(XmlWithTransform.class);
        Class<?> parameterType = parameter.getParameterType();
        String xsltLocation = xmlWithTransform.usingxstl();
        ServletServerHttpRequest servletRequest = new ServletServerHttpRequest(webRequest.getNativeRequest(HttpServletRequest.class));
        String xmlFromVendor = IOUtils.toString(servletRequest.getBody(), "UTF-8");

        String xmlInternal = transform(xmlFromVendor, xsltLocation);
        return unmarshaller.unmarshal(new StreamSource(new StringReader(xmlInternal)));
    }
}

この引数リゾルバーを Spring MVC に登録します。

<mvc:annotation-driven> 
   <mvc:argument-resolvers>
        <bean class="XsltTransformingHandlerMethodArgumentResolver"></bean>
   </mvc:argument-resolvers>
</mvc:annotation-driven>
于 2012-09-25T02:32:10.797 に答える