Java for Web学习笔记(八五):SOAP(2)小例子
2017-10-03 09:39
549 查看
加入soap上下文
soap上下文配置
和spring framework不同,spring web service不支持代码配置,小例子中,我们采用了混合配制的方式,通过SoapServletContextConfiguration扫描@org.springframework.ws.server.endpoint.annotation.Endpoint标记,同时导入ws的soapServletContext.xml配置文件。//... ... import org.springframework.ws.server.endpoint.annotation.Endpoint; @Configuration @ComponentScan( basePackages = "cn.wei.flowingflying.customer_support.site", useDefaultFilters = false, includeFilters = @ComponentScan.Filter(Endpoint.class) ) @ImportResource("classpath:cn/wei/flowingflying/customer_support/config/soapServletContext.xml") public class SoapServletContextConfiguration { /* The explicit messageFactory bean (the name is important) overrides the default message factory so * that the supported SOAP version is 1.2 instead of the default 1.1. */ @Bean public WebServiceMessageFactory messageFactory(){ SaajSoapMessageFactory factory = new SaajSoapMessageFactory(); factory.setSoapVersion(SoapVersion.SOAP_12); return factory; } }我们在src/main/resources下,建立cn/wei/flowingflying/customer_support/config/soapServletContext.xml文件,用于告诉spring
web service使用哪个XSD schema文件来生成WSDL。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:sws="http://www.springframework.org/schema/web-services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/web-services http://www.springframework.org/schema/web-services/web-services-2.0.xsd"> <sws:annotation-driven marshaller="jaxb2Marshaller" unmarshaller="jaxb2Marshaller" /> <sws:dynamic-wsdl id="support" portTypeName="Support" locationUri="/services/Soap/" createSoap11Binding="false" createSoap12Binding="true" targetNamespace="http://www.example.org/support"> <sws:xsd location="/WEB-INF/xsd/soap/support.xsd" /> </sws:dynamic-wsdl> </beans>这里targetNamespace是定义自动生成wdsl的targetNamespace,可以和我们在xsd schema中定义的不一样,例如http://www.example.org/support123,那么生成的wsdl为:
<wsdl:definitions targetNamespace="http://www.example.org/support123"> <wsdl:types> <schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.example.org/support"> <element name="ticketsRequest" type="support:ticketsRequestType"/> <complexType name="ticketsRequestType"/> ......虽然这是允许的,但是就代码的可读性和可维护性而言,我们应当将两者设置为相同。
root上下文中不扫描@Endpoint
@ComponentScan( basePackages = "cn.wei.chapter16.site", excludeFilters = @ComponentScan.Filter({Controller.class, ControllerAdvice.class, Endpoint.class}) ) public class RootContextConfiguration
启动时加载soap dispatcher servlet
AnnotationConfigWebApplicationContext soapContext = new AnnotationConfigWebApplicationContext(); soapContext.register(SoapServletContextConfiguration.class); //Spring Web Service提供了一个Dispather MessageDispatcherServlet来处理soap请求 MessageDispatcherServlet soapServlet = new MessageDispatcherServlet(soapContext); soapServlet.setTransformWsdlLocations(true); dispatcher = container.addServlet("springSoapDispatcher", soapServlet); dispatcher.setLoadOnStartup(3); dispatcher.addMapping("/services/Soap/","/services/Soap/support.wsdl");
我们注意到在启动时,为dispatcher设置了mapping "/services/Soap/",当然我们也可以写成"/services/Soap/*",这涉及到soap消息如何定位。
在配置文件soapServletContext.xml文件中,有
locationUri="/services/Soap/",但经过我们测试,并不实际起作用。但如果不提供,启动时会报错,虽然不起作用,我们应保持配置文件中的设置和启动代码的一致。
ws区分soap消息,依靠的消息中的namespace,也即依赖于soap消息里面的内容,而不是底层承载的http的url。因此对于soap接口,指定一个url即可。
如果使用了"/services/Soap/*",那么对于某个SOAP消息,访问/services/Soap/可以得到正确的结果,访问/services/Soap/123也可以,这可能不是我们需要的。
处理提供soap接口外,还提供查看wsdl的接口,例如http://localhost:8080/customer-support/services/Soap/support.wsdl,我们必须允许这个链接是soap上下文的。如果有很多的xsd schema文件,且可能在开发过程中进行调整,这是使用
/services/Soap/*可能会更为方便。
实现SOAP Endpoint
@Endpoint //ws的标记 public class TicketSoapEndpoint { private static final Logger logger = LogManager.getLogger(); private static final String NAMESPACE = "http://www.example.org/support"; @Inject private TicketService ticketService; // Spring Web Service提供了@PayloadRoot、@SoapAction和@Action来过滤请求 //@PayloadRoot中namespace配置很重要,这是soap消息的匹配。在soapServletContext.xml的配置文件中有targetNamespace,在wsdl文件support.xsd中有targetNamespace。而这里的namespace是检查请求消息中的namespace,并进行过滤,虽然可以和配置文件以及wsdl文件中设置得不一样,不影响其找到相应的wsdl接口定义,但是我们仍应三处保持一致。 // @ResponsePayload或者RequestPayload表示soapbody中的净荷。 @PayloadRoot(namespace = NAMESPACE, localPart = "ticketsRequest") @ResponsePayload public TicketWebServiceList read(){ TicketWebServiceList list = new TicketWebServiceList(); list.setValue(this.ticketService.getAllTickets()); return list; } /* 这里prefix设置为s,只是将s作为prefix的标记,用于在@XPathParam进行标识,并发要求真的为s。 下面合法的匹配消息: <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"> <soap:Header/> <soap:Body> <support:ticketRequest xmlns:support="http://www.example.org/support"> <id>1</id> </support:ticketRequest> </soap:Body> </soap:Envelope> soap body也可以写成 <ticketRequest xmlns="http://www.example.org/support"> <id>1</id> </ticketRequest> 或者 <a:ticketRequest xmlns:a="http://www.example.org/support"> <id>1</id> </a:ticketRequest> */ @PayloadRoot(namespace = NAMESPACE, localPart = "ticketRequest") @Namespace(uri = NAMESPACE, prefix = "s") @ResponsePayload public Ticket read(@XPathParam("/s:ticketRequest/id") long id) { Ticket ticket = this.ticketService.getTicket(id); logger.info("ticket create time : {}", ticket.getDateCreated()); return ticket; } /* 将soap消息体整个作为对象传递进来 */ @PayloadRoot(namespace = NAMESPACE, localPart = "createTicket") @ResponsePayload public Ticket create(@RequestPayload CreateTicket form) { ...... } ...... }
我们看看消息的交互,需要注意,请求消息中应该设置Content-type和Accept为application/soap+xml,否则会返回500的错误,ws认为不是合法的soap消息。
相关链接:
我的Professional Java for Web Applications相关文章
相关文章推荐
- Java for Web学习笔记(八四):SOAP(1)小例子准备
- Java for Web学习笔记(九九):持久化初探(4)JPA小例子(下)
- Java for Web学习笔记(六七):Service和Repository(2)抽象分层例子
- Java for Web学习笔记(八十):RESTful和SOAP:一般性了解
- Java for Web学习笔记(二五):JSTL(1)使用JSTL
- Java for Web学习笔记(二一):EL(1)什么是EL
- Java for Web学习笔记(四六):WebSocket(3)Java Server
- Java for Web学习笔记(二三):EL(3)EL的视图
- Java for Web学习笔记(五六):Spring框架简介(5)自动识别
- Java for Web学习笔记(五七):Spring框架简介(6)代码设置
- Java for Web学习笔记(四十):Filter(2)AsyncContext和Filter
- Java for Web学习笔记(四七):WebSocket(4)Java Client和二进制消息
- Java for Web学习笔记(十):Servlet(8)下发文件
- Java for Web学习笔记(五一):Log(3)代码中使用log4j2
- Java for Web学习笔记(四四):WebSocket(1)演化历程
- Java for Web学习笔记(四一):Filter(3)用于Log
- Java for Web学习笔记(九):Servlet(7)上传文件
- Java for Web学习笔记(二六):JSTL(2)Core Tag(上)
- Java for Web学习笔记(三八):自定义tag(6)一些注意
- Java for Web学习笔记(二四):EL(4)流(Stream)