背景相关

项目涉及向三方单方向访问 WebService 服务,选择 Spring-WS 主要基于两点,一、项目开发框架采用了 Spring 框架,二、Spring-WS 相对来说比较轻量级,WebService 使用了自定义的请求头,且文件传输过程中使用 base64的方式。下面记录了开发过程中遇到的问题

主要问题

  • 版本的区别主要在于 SOAP 的版本,分为 SOAP 1.1 与 SOAP 1.2。

  • 请求与响应的个性化处理:添加请求头、解析响应头、记录 xml 报文。一种方法是分别继承 WebServiceMessageExtractor、WebServiceMessageCallback 进行处理。另外一种就是实现拦截器进行处理。项目中采用了第一种,是因为请求头和响应头是完整交易的一部分,需要和报文体一起记录下来。所以抽象出了WebService Client。 以 base64String 传输文件时,需考虑报文中文件的过滤问题。

  • 对于 DOM 树处理上有 SAAJ 和 Axiom 两种。由于文件以 base64String 形式传输,项目中使用了第一种。实际上文件以 Mtom 方式传输时,Spring-WS 的 SAAJ 设计是有问题的。SAAJ 在文件传输处理上,传输时以流的方式打开文件,然后包装成 DataSource 和 DataHandler,接受文件时反之写入文件,默认为 base64String 格式。若需要以 MTOM 附件方式传输,显示开启 MtomEnable,后台需要遍历 Attachment,获取到对应附件,然后以流的方式写入文件。

  • 对于实例化 Marshaller 与 Unmarshaller 的时候,显式创建对象工厂,并指名所在的包路径

  • Spring-WS 作为 Spring Framework 子模块秉承了约定优于配置的原则,使用 sws:annotation-driven 将显式注册XmlRootElementPayloadMethodProcessor 与 JaxbElementPayloadMethodProcessor,注册顺序早于MarshallingPayloadMethodProcessor,导致自定义的 Marshaller 与 unmarshaller不会调用,即客户端指定的 MtomEnable 不生效,文件将变为 base64String 类型。解决办法就是手动指定 MarshallingPayloadMethodProcessor 注册顺序早于前两个处理器。另外一个问题就是 sws:annotation-driven 可以允许在 Enpoint 的方法中以 SoapHeader 注解的方式接受请求头;而为了 Mtom 传输自定义处理器的注册顺序,请求和 Endpoint 的处理方法以方法签名严格映射,无法处理 SoapHeader。

总结

Spring-WS 整体设计上还是松散的,自由度高意味着不好用,需要的功能自己定制。如果能够使用 Springboot,依照官方的示例,配置上将非常省心。。如果需求较为复杂时,建议使用 Apache CXF。

参考资料