CXF服务发布+HttpClient调用
使用CXF作为服务端发布一个服务,再通过HttpClient来建立一个客户端进行远程的服务调用。这里使用IDEA来进行开发,使用maven来进行依赖的管理。
服务端
CXF使用起来很简单,将相关的依赖包导入后编写服务接口和实现,可以使用两种方式来将服务发布出去。
依赖包:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-core</artifactId> <version>3.3.6</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>3.3.6</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http-jetty</artifactId> <version>3.3.6</version> </dependency>
|
CXF自带了jetty来作为服务器,所以最后一个包少了就会报java.io.IOException: Cannot find any registered HttpDestinationFactory from the Bus.
服务接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
@WebService(targetNamespace = "http://service/") public interface TestService {
public String sayHello(@WebParam(name = "p") String param); }
|
服务的实现
1 2 3 4 5 6 7 8
| @WebService(targetNamespace = "http://service/") public class SendMailServiceImpl implements SendMailService {
public String sayHello(@WebParam(name = "p") String param) { System.out.println("sayHello调用了,参数是 " + param); return "hello!"; } }
|
服务发布
这里可以使用两种方式来发布服务,这两种方式的效果是一样的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public static void createByFactoryBean(String address) { JaxWsServerFactoryBean jaxWsServerFactoryBean = new JaxWsServerFactoryBean(); jaxWsServerFactoryBean.setAddress(address); jaxWsServerFactoryBean.setServiceClass(SendMailService.class); jaxWsServerFactoryBean.setServiceBean(new SendMailServiceImpl()); jaxWsServerFactoryBean.create(); }
public static void createByEndpoint(String address) { Endpoint.publish(address, new SendMailServiceImpl()); }
public static void main(String[] args) { System.out.println("web service start"); String address = "http://localhost:8080/test"; createByEndpoint(address); System.out.println("web service started"); }
|
客户端
客户端在调用的时候就需要遵守以下soap协议了,soap是基于xml的,具体可以查看菜鸟教程的soap教程,里面对基础的soap协议的写法有作解释。需要调用api,肯定是要使用http来访问api接口的,首先需要用HttpClient
来创建连接,并发送soapXml数据来告知需要执行的service的方法是哪个。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class HttpClientUtils {
public static String soapPost(String url, String soapXml) throws IOException { CloseableHttpClient defaultHttpClient = HttpClients.createDefault(); HttpPost httpPost = new HttpPost(url); try { HttpEntity entity = new StringEntity(soapXml, "utf-8"); httpPost.setHeader("Content-Type", "application/soap+xml; charset=utf-8"); httpPost.setEntity(entity); HttpResponse response = defaultHttpClient.execute(httpPost); HttpEntity responseEntity = response.getEntity(); return EntityUtils.toString(responseEntity, "utf-8"); } catch (Exception e) { e.printStackTrace(); return null; } finally { defaultHttpClient.close(); } }
}
|
下面给出soapXml的写法,当时在写这个Xml时,不知道需要指定目标命名空间,卡了挺久的,也是因为XML的知识盲点,对XML不够了解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" <!-- 这个需要指定服务的命名空间 --> xmlns:ser="http://service/" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <soap:Header> </soap:Header> <soap:Body> <ser:sayHello> <p>123</p> </ser:sayHello> </soap:Body> </soap:Envelope>
|