一、Spring Boot集成WebService
Web Service是一种跨平台、跨语言的远程调用技术,它实现了不同系统之间的互操作。
Spring Boot可以通过一个叫做JAX-WS的标准API来调用Web Service接口。
下面是一个简单的示例代码,在Spring Boot中引入JAX-WS依赖,并通过@WebServiceClient注解指定要调用的Web Service接口地址及命名空间:
@Configuration public class WebServiceConfig { @Bean(name="helloWorld") public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema helloWorldSchema){ DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition(); wsdl11Definition.setPortTypeName("HelloWorldPort"); wsdl11Definition.setTargetNamespace("http://spring.io/guides/gs-producing-web-service"); wsdl11Definition.setLocationUri("/ws"); wsdl11Definition.setSchema(helloWorldSchema); return wsdl11Definition; } @Bean public XsdSchema helloWorldSchema() { return new SimpleXsdSchema(new ClassPathResource("xsd/helloworld.xsd")); } }
在Controller中通过@Autowired注入要调用的Web Service接口,然后就可以愉快地调用了:
@RestController @RequestMapping("/api") public class HelloWorldController { @Autowired private HelloWorldPortType helloWorldPortType; @GetMapping("/hello") public String sayHello() { String response = helloWorldPortType.sayHello("World"); return response; } }
二、指定Web Service接口方法
在一个Web Service接口中可能会有多个方法,我们可以通过@SOAPBinding注解的参数来指定要调用的方法:
@WebService(targetNamespace="http://spring.io/guides/gs-producing-web-service", name="HelloWorld") @SOAPBinding(style=Style.RPC) public interface HelloWorldPortType { @WebMethod(operationName="sayHello") String sayHello(@WebParam(name="arg0") String arg0); @WebMethod(operationName="getHelloWorldAsString") String getHelloWorldAsString(); }
注意上面的Web Service接口的注解,其中我们通过@SOAPBinding注解的style参数来指定为RPC模式。
三、传递复杂类型参数
有时候我们需要调用一个Web Service接口方法,需要传递一个复杂类型的参数。比如下面的Account类:
public class Account { private String accountNumber; private String accountHolderName; private String branch; private String location; // getter & setter }
在Web Service接口中我们可以通过@XmlRootElement注解将Account类转换为XML格式:
@XmlRootElement public class Account { private String accountNumber; private String accountHolderName; private String branch; private String location; // getter & setter }
然后将Account类作为Web Service方法的参数:
public interface Bank { @WebMethod(operationName="getAccountDetails") AccountDetails getAccountDetails(@WebParam(name="account") Account account); }
在调用Web Service接口方法时,我们同样需要将Account对象转换为XML格式。Spring Boot提供了一个JAXB2 Marshaller来完成这个任务:
@Configuration public class WebServiceConfig { @Bean public Jaxb2Marshaller marshaller() { Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); marshaller.setContextPath("com.example.wsdl.demo"); return marshaller; } @Bean public SoapClient soapClient(Jaxb2Marshaller marshaller) { SoapClient client = new SoapClient(); client.setDefaultUri("http://localhost:8080/ws"); client.setMarshaller(marshaller); client.setUnmarshaller(marshaller); return client; } }
然后就可以愉快地调用Web Service接口方法了:
@Service public class BankService { private final SoapClient soapClient; @Autowired public BankService(SoapClient soapClient) { this.soapClient = soapClient; } public AccountDetails getAccountDetails(String accountNumber) { Account account = new Account(); account.setAccountNumber(accountNumber); AccountDetails accountDetails = (AccountDetails) soapClient.callWebService("http://spring.io/guides/gs-producing-web-service", account); return accountDetails; } }
四、使用Cxf客户端
除了上文提到的JAX-WS API外,Spring Boot还可以使用Apache CXF这个强大的Web Service框架来调用Web Service接口。
我们可以通过Maven引入如下两个依赖:
<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-spring-boot-starter-jaxws</artifactId> <version>3.2.5</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.2.5</version> </dependency>
然后就可以愉快地使用CXF客户端来调用Web Service接口了:
@Service public class BankService { private final Bank bank; @Autowired public BankService(JaxWsProxyFactoryBean proxyFactoryBean) { this.bank = proxyFactoryBean.create(Bank.class); } public AccountDetails getAccountDetails(String accountNumber) { Account account = new Account(); account.setAccountNumber(accountNumber); AccountDetails accountDetails = bank.getAccountDetails(account); return accountDetails; } }
可以看到,在CXF客户端中我们可以直接通过Bank类来调用Web Service接口方法。