Spring 引导 - 如何将自定义 headers 添加到 SOAP 响应?
Spring Boot - How add custom headers to SOAP Response?
我目前有以下端点,我的目的是将自定义 header 添加到默认情况下始终为空的当前响应 header。
目前我有以下 classes/configurations:
@Endpoint
public class AddressEndPoint extends WebServiceGatewaySupport {
@Autowired
private AddressService addressService;
@Autowired
private ConfigProperties configProperties;
@PayloadRoot(namespace = "http://www.swisscom.com/wsg/bb/v42", localPart = "getAddressRequest")
@ResponsePayload
public GetAddressResponse getAddressRequest(@RequestPayload GetAddressRequest request)
throws DatatypeConfigurationException
{
UUID uuid = UUID.randomUUID();
GetAddressResponse response = new GetAddressResponse();
response.setAddress(addressService.getAddress(request.getCity())); //Get the city from AddressService method by passing as parameter the city of the request obj
response.setDnType(DnType.BBCS_QUALIFY.getType());
response.setBasisContrEleId(BasisContrEleId.BBCS_BASISCONTR.getType());
response.setBbType(BbType.BBCS_BBTYPE.getType());
response.setContrEleId(ContrEleId.BBCS_CONTRELE.getType());
response.setIspId(Integer.parseInt(configProperties.getConfigValue("ispId")));
response.setQualifExtRef(uuid.toString());
response.setReturnSpeedAtNok(Boolean.TRUE);
response.setSfSlaId(SetSfSlaId.FIRST_POSSIBLE.getType());
GregorianCalendar gcal = new GregorianCalendar();
XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(gcal);
response.setCustomerWishDate(xgcal);
//GetAddressResponse testResponse = getWebServiceTemplate().marshalSendAndReceive((GetAddressResponse) response, new SoapRequestHeaderModifier());
//return (GetAddressResponse) getWebServiceTemplate().marshalSendAndReceive(response, new SoapRequestHeaderModifier());
return response;
}
}
以及以下 SOAP 配置:
@EnableWs
@Configuration
public class SoapWebServiceConfig extends WsConfigurerAdapter {
//Add this in package-info.java
/*xmlns = {
@XmlNs(prefix = "v42", namespaceURI="http:xxxxxxxx.com/xx/xx/v42")
},*/
@Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext context){
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(context);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/soapWS/*");
}
//Added for WS Security
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("com.swisscom.wsg.bb.v42");
return marshaller;
}
@Bean
public XsdSchema userSchema() {
return new SimpleXsdSchema(new ClassPathResource("users.xsd"));
}
@Bean
public XsdSchema addressSchema(){
return new SimpleXsdSchema(new ClassPathResource("address.xsd"));
}
@Bean
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema userSchema){
DefaultWsdl11Definition definition = new DefaultWsdl11Definition();
definition.setSchema(userSchema);
definition.setLocationUri("/soapWS");
definition.setPortTypeName("UserServicePort");
definition.setTargetNamespace("http://www.swisscom.com/wsg/bb/v42");
return definition;
}
}
我的意图是在 Security
下的响应 header 中添加一个 usernameToken
元素,其中包含 username
和 password
.
示例:
<wsse:Security soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next" soapenv:mustUnderstand="0" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>xxxx</wsse:Username>
<wsse:Password>xxxxx</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
我已经尝试了一些示例,正如您从我的注释代码中看到的那样,但没有成功。
如有任何帮助,我们将不胜感激。
我设法通过以下方式解决了我的问题:
private static final String TARGET_NAMESPACE = "http://www.swisscom.com/wsg/bb/v42";
@PayloadRoot(namespace = "http://www.swisscom.com/wsg/bb/v42", localPart = "getAddressRequest")
@ResponsePayload
public GetAddressResponse getAddressRequest(@RequestPayload GetAddressRequest request, MessageContext messageContext) throws DatatypeConfigurationException, JAXBException {
//Create Response Body and Header
SaajSoapMessage soapResponse = (SaajSoapMessage) messageContext.getResponse();
SoapHeader soapResponseHeader = soapResponse.getSoapHeader();
//New UsernameHeader Object
UsernameHeader usernameToken = new UsernameHeader();
//Set UsernameHeader Object values
usernameToken.setUsername("SandyAPI");
usernameToken.setPassword("Test_Password");
//Create SecurityHeader Object that will contain the UsernameHeader Object
SecurityHeader securityHeader = new SecurityHeader();
securityHeader.setUsernameHeader(usernameToken);
//Genetare random UUID
UUID uuid = UUID.randomUUID();
//Create new GetAddressResponse Object and set the values (body)
GetAddressResponse response = new GetAddressResponse();
response.setAddress(addressService.getAddress(request.getCity())); //Get the city from AddressService method by passing as parameter the city of the request obj
response.setDnType(DnType.BBCS_QUALIFY.getType());
response.setBasisContrEleId(BasisContrEleId.BBCS_BASISCONTR.getType());
response.setBbType(BbType.BBCS_BBTYPE.getType());
response.setContrEleId(ContrEleId.BBCS_CONTRELE.getType());
response.setIspId(Integer.parseInt(configProperties.getConfigValue("ispId")));
response.setQualifExtRef(uuid.toString());
response.setReturnSpeedAtNok(Boolean.TRUE);
response.setSfSlaId(SetSfSlaId.FIRST_POSSIBLE.getType());
GregorianCalendar gcal = new GregorianCalendar();
XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(gcal);
response.setCustomerWishDate(xgcal);
//Send Response back (Classes marshalled)
JAXBContext jaxbContext = JAXBContext.newInstance(SecurityHeader.class);
jaxbContext.createMarshaller().marshal(securityHeader, soapResponseHeader.getResult());
return response;
}
输出:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<wsse:Security>
<wsse:UsernameToken>
<wsse:Username>SandyAPI</wsse:Username>
<wsse:Password>Test_Password</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<v42:getAddressResponse xmlns:v42="http://www.swisscom.com/wsg/bb/v42">
<v42:ispId>100032</v42:ispId>
<v42:basisContrEleId>120</v42:basisContrEleId>
<v42:contrEleId>100</v42:contrEleId>
<v42:bbType>2</v42:bbType>
<v42:dnType>1</v42:dnType>
<v42:address>
<v42:city>Bellinzona</v42:city>
<v42:street>Viale Stazione</v42:street>
<v42:house>33</v42:house>
<v42:zip>6500</v42:zip>
</v42:address>
<v42:qualifExtRef>a390c3a4-2810-4b49-a48a-6c9de98beab1</v42:qualifExtRef>
<v42:returnSpeedAtNok>true</v42:returnSpeedAtNok>
<v42:sfSlaId>1</v42:sfSlaId>
<v42:customerWishDate>2019-11-26+01:00</v42:customerWishDate>
</v42:getAddressResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
我目前有以下端点,我的目的是将自定义 header 添加到默认情况下始终为空的当前响应 header。
目前我有以下 classes/configurations:
@Endpoint
public class AddressEndPoint extends WebServiceGatewaySupport {
@Autowired
private AddressService addressService;
@Autowired
private ConfigProperties configProperties;
@PayloadRoot(namespace = "http://www.swisscom.com/wsg/bb/v42", localPart = "getAddressRequest")
@ResponsePayload
public GetAddressResponse getAddressRequest(@RequestPayload GetAddressRequest request)
throws DatatypeConfigurationException
{
UUID uuid = UUID.randomUUID();
GetAddressResponse response = new GetAddressResponse();
response.setAddress(addressService.getAddress(request.getCity())); //Get the city from AddressService method by passing as parameter the city of the request obj
response.setDnType(DnType.BBCS_QUALIFY.getType());
response.setBasisContrEleId(BasisContrEleId.BBCS_BASISCONTR.getType());
response.setBbType(BbType.BBCS_BBTYPE.getType());
response.setContrEleId(ContrEleId.BBCS_CONTRELE.getType());
response.setIspId(Integer.parseInt(configProperties.getConfigValue("ispId")));
response.setQualifExtRef(uuid.toString());
response.setReturnSpeedAtNok(Boolean.TRUE);
response.setSfSlaId(SetSfSlaId.FIRST_POSSIBLE.getType());
GregorianCalendar gcal = new GregorianCalendar();
XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(gcal);
response.setCustomerWishDate(xgcal);
//GetAddressResponse testResponse = getWebServiceTemplate().marshalSendAndReceive((GetAddressResponse) response, new SoapRequestHeaderModifier());
//return (GetAddressResponse) getWebServiceTemplate().marshalSendAndReceive(response, new SoapRequestHeaderModifier());
return response;
}
}
以及以下 SOAP 配置:
@EnableWs
@Configuration
public class SoapWebServiceConfig extends WsConfigurerAdapter {
//Add this in package-info.java
/*xmlns = {
@XmlNs(prefix = "v42", namespaceURI="http:xxxxxxxx.com/xx/xx/v42")
},*/
@Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext context){
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(context);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/soapWS/*");
}
//Added for WS Security
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("com.swisscom.wsg.bb.v42");
return marshaller;
}
@Bean
public XsdSchema userSchema() {
return new SimpleXsdSchema(new ClassPathResource("users.xsd"));
}
@Bean
public XsdSchema addressSchema(){
return new SimpleXsdSchema(new ClassPathResource("address.xsd"));
}
@Bean
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema userSchema){
DefaultWsdl11Definition definition = new DefaultWsdl11Definition();
definition.setSchema(userSchema);
definition.setLocationUri("/soapWS");
definition.setPortTypeName("UserServicePort");
definition.setTargetNamespace("http://www.swisscom.com/wsg/bb/v42");
return definition;
}
}
我的意图是在 Security
下的响应 header 中添加一个 usernameToken
元素,其中包含 username
和 password
.
示例:
<wsse:Security soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next" soapenv:mustUnderstand="0" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>xxxx</wsse:Username>
<wsse:Password>xxxxx</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
我已经尝试了一些示例,正如您从我的注释代码中看到的那样,但没有成功。
如有任何帮助,我们将不胜感激。
我设法通过以下方式解决了我的问题:
private static final String TARGET_NAMESPACE = "http://www.swisscom.com/wsg/bb/v42";
@PayloadRoot(namespace = "http://www.swisscom.com/wsg/bb/v42", localPart = "getAddressRequest")
@ResponsePayload
public GetAddressResponse getAddressRequest(@RequestPayload GetAddressRequest request, MessageContext messageContext) throws DatatypeConfigurationException, JAXBException {
//Create Response Body and Header
SaajSoapMessage soapResponse = (SaajSoapMessage) messageContext.getResponse();
SoapHeader soapResponseHeader = soapResponse.getSoapHeader();
//New UsernameHeader Object
UsernameHeader usernameToken = new UsernameHeader();
//Set UsernameHeader Object values
usernameToken.setUsername("SandyAPI");
usernameToken.setPassword("Test_Password");
//Create SecurityHeader Object that will contain the UsernameHeader Object
SecurityHeader securityHeader = new SecurityHeader();
securityHeader.setUsernameHeader(usernameToken);
//Genetare random UUID
UUID uuid = UUID.randomUUID();
//Create new GetAddressResponse Object and set the values (body)
GetAddressResponse response = new GetAddressResponse();
response.setAddress(addressService.getAddress(request.getCity())); //Get the city from AddressService method by passing as parameter the city of the request obj
response.setDnType(DnType.BBCS_QUALIFY.getType());
response.setBasisContrEleId(BasisContrEleId.BBCS_BASISCONTR.getType());
response.setBbType(BbType.BBCS_BBTYPE.getType());
response.setContrEleId(ContrEleId.BBCS_CONTRELE.getType());
response.setIspId(Integer.parseInt(configProperties.getConfigValue("ispId")));
response.setQualifExtRef(uuid.toString());
response.setReturnSpeedAtNok(Boolean.TRUE);
response.setSfSlaId(SetSfSlaId.FIRST_POSSIBLE.getType());
GregorianCalendar gcal = new GregorianCalendar();
XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(gcal);
response.setCustomerWishDate(xgcal);
//Send Response back (Classes marshalled)
JAXBContext jaxbContext = JAXBContext.newInstance(SecurityHeader.class);
jaxbContext.createMarshaller().marshal(securityHeader, soapResponseHeader.getResult());
return response;
}
输出:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<wsse:Security>
<wsse:UsernameToken>
<wsse:Username>SandyAPI</wsse:Username>
<wsse:Password>Test_Password</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<v42:getAddressResponse xmlns:v42="http://www.swisscom.com/wsg/bb/v42">
<v42:ispId>100032</v42:ispId>
<v42:basisContrEleId>120</v42:basisContrEleId>
<v42:contrEleId>100</v42:contrEleId>
<v42:bbType>2</v42:bbType>
<v42:dnType>1</v42:dnType>
<v42:address>
<v42:city>Bellinzona</v42:city>
<v42:street>Viale Stazione</v42:street>
<v42:house>33</v42:house>
<v42:zip>6500</v42:zip>
</v42:address>
<v42:qualifExtRef>a390c3a4-2810-4b49-a48a-6c9de98beab1</v42:qualifExtRef>
<v42:returnSpeedAtNok>true</v42:returnSpeedAtNok>
<v42:sfSlaId>1</v42:sfSlaId>
<v42:customerWishDate>2019-11-26+01:00</v42:customerWishDate>
</v42:getAddressResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>