1.项目开发中多模块交互一般采用接口相互调用,调用方式一般包括webservice和http,对于安全性要求较高的接口(比如外网)一般采用webservice,而对于项目开发内网接口编程二者均可,不过post的调用会比较方便。下面来简单介绍这两种方式,有什么不对的地方还请大神多多指教!!!
对于webservice接口编程,其最底层是使用SOAP协议,目前最常用封装好的工具有Axis和XFire,首先去Apache官方下载axis,我用的是axis2-1.2这个版本,最新是axis2-1.3的版本,把下载的war包放到tomcat的webapps目录,启动tomcat服务,在浏览器地址栏输入http://localhost:8080/axis2/(根据每个人的tomcat配置的不同,这个路径可能不同) ,如果出现Apache界面就说明ws服务没有问题了,下面写个简单测试:TeestAxis.java
package com;
public class TestAxis{
public String axis1() {
return "hello,world";
}
}
在再src下面建一个meta-inf的文件夹,创建一个services.xml的文件,文件内容如下:
<service name="AXIS">
<Description>
test Axis
</Description>
<parameter name="ServiceClass" locked="false">com.axis.TestAxis</parameter>
<operation name="axis1">
<messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
</operation>
</service>
在上面的xml描述中,com.Hello是指你建立的类名称,hw是对应的方法,Hello是对应的服务名称。
把这个工程打包为jar文件,然后把扩展名jar改为aar,放到TomCat目录\webapp\axis2\WEB-INF\services的目录下面,启动tomcat服务。
在地址栏输入:http://localhost:8080/axis2/services/listServices ,如果服务正常,在浏览器页面中会出现处于Active状态的Hello的服务名称
客户端调用
目前我用了2种调用方法
Client.java
package com;
import org.apache.axiom.om.OMElement;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.rpc.client.RPCServiceClient;
import javax.xml.namespace.QName;
import javax.xml.rpc.ServiceException;
import java.net.MalformedURLException;
import java.rmi.RemoteException;
import java.util.Iterator;
public class Client {
//
public static void main(String[] args) throws RemoteException, ServiceException, MalformedURLException {
/* **************** 调用方法1 *********************** */
RPCServiceClient rpcClient = new RPCServiceClient();
Options opt = new Options();
opt.setTo(new EndpointReference("http://localhost:8080/axis2/services/AXIS"));
opt.setAction("urn:axis1");
rpcClient.setOptions(opt);
OMElement element = rpcClient.invokeBlocking(new QName("http://com.axis", "axis1"), new Object[]{null});
System.out.println(element);
System.out.println(element.getFirstElement().getText());
Iterator value = element.getChildElements();
while(value.hasNext()){
OMElement ome = (OMElement)value.next();
System.out.println(ome.getText());
}
/* **************** 调用方法2 *********************** */
String method = "hw";
Service service = new Service();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress(new java.net.URL("http://localhost:8080/axis2/services/Hello"));
call.setOperationName(new QName("http://com/", method));
call.setUseSOAPAction(true);
call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);
call.setSOAPActionURI("http://com/GetServerList");
String k = (String)call.invoke(new Object[]{}); //因为返回值是String类型,所以这里调用的返回值也是String类型
System.out.println(">>> "+k); //返回值输出
}
}
这样然后就OK了。
下面来介绍XFire,首先,当然是要下包啦,http://xfire.codehaus.org/Download可以到这里去下,可以下all也可以下distribution,但建议还是下all的。
xfire与其他webservice框架的不同,它最大的不同之处在于它需要一个接口,而且如果需要用xfire来调用相应的webservice必须知道接口的定义,感觉这里有点限制了。但除了这点,xfire调用webservice,那是相当的方便,就跟调用本地方法一样。我们直接来看例子:
接口:
public interface TestAPI {
public String test01(String memberxml);
public String test02(String memberxml);
}
接口实现:
public class TestAPIImpl implements TestAPI {
public String test01(String memberxml) {
return "{succ:'true',msg:'调用成功',data:{a:'8'}}";
}
@Override
public String test02(String memberxml) {
return "{succ:'true',msg:'调用成功',data:{a:'8'}}";
}
}
src目录下新建一个文件夹META-INF,再建它的一个字文件夹xfire,里面建立文件services.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<service xmlns="http://xfire.codehaus.org/config/1.0">
<name>ICService</name>
<serviceClass>
com.sinosoft.xire.services.TestAPI
</serviceClass>
<implementationClass>
com.sinosoft.xire.services.TestAPIImpl
</implementationClass>
<style>wrapped</style>
<use>literal</use>
<scope>application</scope>
</service>
</beans>
web.xml配置xfire
<servlet>
<servlet-name>xfire</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>xfire</servlet-name>
<url-pattern>*.ws</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>XFireServlet</servlet-name>
<servlet-class>org.codehaus.xfire.transport.http.XFireConfigurableServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>XFireServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
我们在浏览器上直接输入:
http://localhost:8080/项目名称/services/可以看到接口wsdl
最后一步就是客户端了:
public class ReaderClient {
public static void main(String[] args) throws Exception {
String readerServiceUrl = "http://localhost:8080/ws/services/ICService";
Client c = new Client(new URL(readerServiceUrl+"?wsdl"));
Object[] p = new Object[1];
p[0]="";
Object[] results = c.invoke("test01", p);
System.out.println(results[0]);
}
}
这样就ok了,返回数据:{succ:'true',msg:'调用成功',data:{a:'8'}}
但现在的最新的版本,xfire已经停止开发,被apache合并为CXF项目,CXF最近没时间搞,有时间在做!先简单的加一点:
还是包的问题,在http://cxf.apache.org/download.html这里可以下到最新版的CXF,当然,我用的是最新版的。接下来还是那句废话,建WEB项目,放入JAR包。而JAR包我们就不选择了,一堆全部放入。
我们会看到它包含了spring的JAR包,CXF自带了一个轻量的容器服务,相当于spring自己提供了IOC容器一样后面当我们需要把CXF作为WEB项目部署时,就需要用到spring的配置文件,这个后面再讲。
同Xfire一样写个接口和实现类接口发布测试:
- public static void main(String[] args) {
- System.out.println("Server is starting...");
- TestAPI readerService = new TestAPI();
- Endpoint.publish("http://localhost:8080/readerService ",readerService);
- System.out.println("Server is started...");
- }
接着启动浏览器看看是否成功了。
直接在浏览器输入http://localhost:8080/readerService?wsdl
客户端调用类似于Xfire:
public class ReaderClient {
public static void main(String[] args) throws Exception {
String readerServiceUrl ="http://localhost:8080/readerService";
Client c = new Client(new URL(readerServiceUrl+"?wsdl"));
Object[] p = new Object[1];
p[0]="";
Object[] results = c.invoke("test01", p);
System.out.println(results[0]);
}
}
可参考:http://cxshun.iteye.com/blog/1275408
下面来说下post方式调用接口:
public static String post(String url, String body)
throws ApplicationException {
// HTTP客户端
HttpClient client = null;
PostMethod method = null;
try {
client = HttpClientManager.getHttpClient();
method = new PostMethod(url);
method.setRequestEntity(new ByteArrayRequestEntity(body
.getBytes("UTF-8")));
logger.info("HTTP调用请求报文:" + body);
} catch (UnsupportedEncodingException e) {
logger.error("HTTP服务调用异常(客户端异常)");
logger.error(ItsExceptionUtil.getStackTrace(e));
throw new ApplicationException(ErrorCode.PBIN0001, url);
} catch (IOException e) {
logger.error("HTTP服务调用异常(客户端异常)");
logger.error(ItsExceptionUtil.getStackTrace(e));
throw new ApplicationException(ErrorCode.PBIN0001, url);
}
// 执行调用
return clientInvoke(client, method, url);
}
private static String clientInvoke(HttpClient client, PostMethod method,
String url) {
InputStream stream = null;
BufferedReader br = null;
StringBuffer buf = null;
// 执行调用
try {
logger.info("HTTP调用请求URL:" + url);
int statusCode = client.executeMethod(method);
// 获取返回消息
stream = method.getResponseBodyAsStream();
br = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
buf = new StringBuffer();
String line;
while (null != (line = br.readLine())) {
buf.append(line).append("\n");
}
logger.info("HTTP调用返回报文:" + buf.toString());
logger.info("HTTP调用状态码:" + statusCode);
if (Constant.HTTP_CODE_200 == statusCode) {
logger.info("HTTP调用成功");
} else if (Constant.HTTP_CODE_400 == statusCode) {
throw new ApplicationException(ErrorCode.PBIN0002, url,
statusCode, "错误的请求.请求参数有误.");
} else if (Constant.HTTP_CODE_404 == statusCode) {
throw new ApplicationException(ErrorCode.PBIN0002, url,
statusCode, "请求失败");
} else if (Constant.HTTP_CODE_500 == statusCode) {
throw new ApplicationException(ErrorCode.PBIN0002, url,
statusCode, "服务端程序出错");
} else {
throw new ApplicationException(ErrorCode.PBIN0002, url,
statusCode, "未知");
}
} catch (HttpException e) {
logger.error("HTTP服务调用异常");
logger.error(ItsExceptionUtil.getStackTrace(e));
throw new ApplicationException(ErrorCode.PBIN0001, url);
} catch (IOException e) {
logger.error("HTTP服务调用异常");
logger.error(ItsExceptionUtil.getStackTrace(e));
throw new ApplicationException(ErrorCode.PBIN0001, url);
} finally {
// 释放连接
method.releaseConnection();
try {
if (stream != null)
stream.close();
if (br != null)
br.close();
} catch (IOException e) {
logger.error("HTTP服务调用异常");
logger.error(ItsExceptionUtil.getStackTrace(e));
throw new ApplicationException(ErrorCode.PBIN0001, url);
}
}
return buf == null ? null : buf.toString();
}
这个基本上就是post方式的代码了,希望对大家学习有用,有什么不对的地方还请多多指正!