由于工作需要使用到webservice,项目框架为spring,webservice框架为CXF。
一.如何使用CXF发布一个webservice服务
1.首先下载CXF的程序压缩包,作者下载的是apache-cxf-3.1.8,将其中的lib目录下的包拷贝到项目的根目录下,由于作者的项目用的是spring框架,所以要把其中的有关spring的架包删除,要不然会冲突,记得将架包引入到项目中,如果使用maven也可以直接使用maven来引入。
2.修改项目的配置文件,即spring的配置文件:
修改bean的元素描述,其中红色部分为新增行
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
在配置文件尾部加入需要引入的xml文件,下面俩个文件都是在CXF的架包中,作者将他们直接拿到了配置文件目录下。3.1.8版本只需要引入这俩个文件,早期的版本可能会需要引用三个。
<import resource="cxf.xml"/> <import resource="cxf-servlet.xml"/>
在web.xml文件中加入以下配置,启用CXF的servlet,并且将匹配/webservice/*的请求解析为请求webservice。
<servlet> <servlet-name>CXFServlet</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>CXFServlet</servlet-name> <url-pattern>/webservice/*</url-pattern> </servlet-mapping>3.编写webservice服务端代码:
webservice服务端代码分为俩个类,一个为服务接口,一个为接口实现类。
接口HelloInteface.java
<pre name="code" class="java">package com.zy.webservice; import javax.jws.WebParam; import javax.jws.WebService; @WebService public interface HelloInteface{ public String sayHello(@WebParam(name = "userName")String name); }
实现HelloIntefaceImpl
<pre name="code" class="java">package com.zy.webservice; import javax.jws.WebService; @WebService(endpointInterface= "com.zy.webservice.HelloInteface") public class HelloIntefaceImpl implements HelloInteface{ @Override public String sayHello(String name) { return "hello"+name; } }
4.发布代码为webservice:
在spring的配置文件中将上面的实现类配置为webservice:
<pre name="code" class="java"><jaxws:endpoint id="helloworld" implementor="com.zy.webservice.HelloIntefaceImpl" address="/hello"/>
5.启动服务,在浏览器中输入localhost:8080/myweb/webservice/hello?wsdl,如果页面显示出wsdl文件的内容即发布
成功。记住要加上?wsdl。
二.如何调用现有的webservice
准备工作:获取到webservice的wsdl地址,如果需要验证则需要用户名以及密码。
1.将wsdl解析为java代码
进入cxf.3.1.8的bin目录,运行wsdl2java 你的wsdl地址,如果该地址无需账户验证可以直接解析,如果需要验证,则先使用网页打开wsdl地址,输入用户名密码验证后会显示相应的内容,再将页面另存为wsdl文件,最后使用wsdl2java解析即可。
解析后的文件一般有一下几个:一个接口类,该接口的服务类,XXXXRequest(接口方法所需要的参数),XXXXResponse(方法的返回值),ObjectFactory,package-info.java。后面俩个文件不需要去管。
首先创建一个测试类:
public class TestWebservice
{
public static void main(String[]] args)
{
服务类 service=new 服务类();
接口类 port=service.getXXXport();
XXXXRequest request=new XXXXRequest();
XXXXResponse reponse=port.XXXfunction(request);
}
}
上面的类表现出了大概的调用过程,具体的情况要看具体的需求,可能会出现没有返回值,参数等等。
特别需要注意的是,如果调用的wsdl需要用户验证怎么办。这边引入一片外文,作者使用的是方法二。
HTTP basic authentication with JAX-WS (Client) Labels: java, web services JAX-WS does not do very well with HTTP basic authentication. In general, to create and use a web-service client you have to perform the following steps: 1. Use wsimport to generate the stub files 2. Create a service class in the client 3. Retrieve a proxy to the service, also known as a port All three steps could require HTTP basic authentication. And for each step it have to be handled in a different way. 1. The stub files generation If access to a wsdl file is restricted with basic authentication, wsimport fails to get it. Unfortunately it does not support the common approach to write access credentials right into the URL (RFC 1738). It is not a big deal to resolve this issue. You just need to create a server authentication file: $HOME/.metro/auth. This file should have the WSDL URL with username and password in the RFC 1738 format: http[s]://user:password@host:port// You can have line delimited multiple entries in this file and they can be used for various sites that need basic authentication. 2. The service class creation A constructor of the service object requires access to the WSDL. And again it does not support basic authentication out of the box. You have an option to download the wsdl file and use it locally. Another option is to use the default authenticator: Authenticator.setDefault(new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication( USER_NAME, PASSWORD.toCharArray()); } }); 3. The service class configuration And the last but not least part of our adventure is configuration of the service port: OurWebService service = new OurWebService (); OurWebServicePortType port = service.getOurWebServicePortType(); BindingProvider bindingProvider = (BindingProvider)port; Map requestContext = bindingProvider.getRequestContext(); requestContext.put(BindingProvider.USERNAME_PROPERTY, USER_NAME); requestContext.put(BindingProvider.PASSWORD_PROPERTY, PASSWORD); Done! Now you are able to use methods of the port object to communicate with a web service.方法二的初始化方法需要加入到service类中,最后的service应该类似于下面:
@WebServiceClient(name = "AdminWebServiceService", targetNamespace = "http://server3.wservice3", wsdlLocation = "http://localhost:9001/wservice3/services/AdminWebService?wsdl") public class AdminWebServiceService extends Service { private final static URL ADMINWEBSERVICESERVICE_WSDL_LOCATION; private final static Logger logger = Logger.getLogger(com.myapp.test.wservice3.server3.AdminWebServiceService.class.getName()); static { Authenticator.setDefault(new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication( "myusername", "mypassword".toCharArray()); } }); URL url = null; try { URL baseUrl; baseUrl = com.myapp.test.wservice3.server3.AdminWebServiceService.class.getResource("."); url = new URL(baseUrl, "http://localhost:9001/wservice3/services/AdminWebService?wsdl"); } catch (MalformedURLException e) { logger.warning("Failed to create URL for the wsdl Location: 'http://localhost:9001/wservice3/services/AdminWebService?wsdl', retrying as a local file"); logger.warning(e.getMessage()); } ADMINWEBSERVICESERVICE_WSDL_LOCATION = url; } public AdminWebServiceService(URL wsdlLocation, QName serviceName) { super(wsdlLocation, serviceName); } public AdminWebServiceService() { super(ADMINWEBSERVICESERVICE_WSDL_LOCATION, new QName("http://server3.wservice3", "AdminWebServiceService")); } @WebEndpoint(name = "AdminWebService") public AdminWebService getAdminWebService() { return super.getPort(new QName("http://server3.wservice3", "AdminWebService"), AdminWebService.class); } @WebEndpoint(name = "AdminWebService") public AdminWebService getAdminWebService(WebServiceFeature... features) { return super.getPort(new QName("http://server3.wservice3", "AdminWebService"), AdminWebService.class, features); } }