本文使用的是webservice開發接口的axis+rpc遠程過程調用方式,基於soap通信協議(axis本質就是soap)。
導入jar包
jaxrpc.jar
axis.jar
axis-ant.jar
wsdl4j.jar
commons-discovery-0.2.jar
commons-logging-1.0.4.jar
saaj.jar
dom4j.jar
2. 服務器端的開發:
首先編寫一個類,這個類中的方法作爲接口函數,供客戶端調用。
注意這個類要繼承ServletEndpointSupport
(原因:是爲了使用其中的onInit方法。比如說,如果這個接口是service,需要調用dao層的方法操作數據庫,用new的方法可以,但是無法保證service事務,所有用上下文方式獲取dao。
protected void onInit() {
if(cormDao==null)
cormDao = (CormDao)WebAppContextUtil.getInstance().getBean("cormDao");
}
如果,不繼承此類也可以,用如下方法獲取dao也可以:
if(countTypeDao == null) {
WebApplicationContext context=ContextLoader.getCurrentWebApplicationContext();
countTypeDao = (CountTypeDao) context.getBean("countTypeDao");
}
)
先在web.xml文件中配置:
<!-- 定義AxisServlet-->
<servlet>
<servlet-name>AxisServlet</servlet-name>
<servlet-class>org.apache.axis.transport.http.AxisServlet</servlet-class>
</servlet>
<!-- 映射AxisServlet,使用通配符 -->
<servlet-mapping>
<servlet-name>AxisServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
然後,在server-config.wsdd配置文件中進行配置:
<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<handler name="LocalResponder" type="java:org.apache.axis.transport.local.LocalResponder" />
<handler name="URLMapper" type="java:org.apache.axis.handlers.http.URLMapper" />
<!--服務名稱和服務類 -->
<service name="EkkNameService" provider="java:RPC">
<parameter name="allowedMethods" value="*" />
<!--注意,如果只公開類中部分函數則:<parameter name="allowedMethods" value="queryInfo,queryProject,queryItem" />->
<parameter name="className" value="com.main.service.EkkNameService" />
</service>
<transport name="http">
<requestFlow>
<handler type="URLMapper" />
<handler type="java:org.apache.axis.handlers.http.HTTPAuthHandler" />
<!-- 權限認證 -->
<handler name="IpAuthentication" type="java:com.ws.IpAuthenticationHandler" />
</requestFlow>
</transport>
<transport name="local">
<responseFlow>
<handler type="LocalResponder" />
</responseFlow>
</transport>
</deployment>
3.編寫IpAuthenticationHandler類,來進行調用接口時的權限處理。(比如:校驗此ip是否有權限調用此接口)
package com.ws;
import java.sql.Timestamp;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.apache.axis.AxisFault;
import org.apache.axis.MessageContext;
import org.apache.axis.handlers.BasicHandler;
import org.apache.axis.transport.http.HTTPConstants;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import com.common.util.WebAppContextUtil;
/**
* 根據Ip地址來進行權限過濾
* 這是ws處理權限的統一框架。所有ws調用都會到這裏統一處理。
* @author Administrator
*
*/
public class IpAuthenticationHandler extends BasicHandler {
private static final Logger logger = Logger.getLogger(IpAuthenticationHandler.class);
private static final long serialVersionUID = 1L;
/**
* 錯誤編號:權限錯誤——未申請權限
*/
private static final String ERROR_CODE_HAS_NO_AUTH = "099";
/**
* 操作類型:調用
*/
private static final String OPER_TYPE_INVOKE = "1";
/**
* 操作結果:成功
*/
private static final String INVOKE_RESULT_SUCCESS = "0";
/**
* 操作結果:失敗
*/
private static final String INVOKE_RESULT_FAIL = "9";
/**
* 初始化
*/
@Override
public void init() {
super.init();
}
@Override
public void invoke(MessageContext msgContext) throws AxisFault {
logger.info(msgContext.getSOAPActionURI());
logger.info(msgContext.getTargetService());
logger.info(msgContext.getOperation().getName());
logger.info(msgContext.getAllPropertyNames());
logger.info( msgContext.getUsername());
logger.info(msgContext.getPassword());
InterfaceInfo interfaceInfo = new InterfaceInfo();
HttpServletRequest request = (HttpServletRequest)msgContext.getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST);
String remoteAddr = request.getRemoteAddr();
logger.debug("請求來自:"+remoteAddr);
if(false){//此處寫條件
//權限表中沒有此ip
logger.error("ip認證不通過");
//記錯誤日誌。
saveLog(INVOKE_RESULT_FAIL,ERROR_CODE_HAS_NO_AUTH,"師徒調用未授權的接口。",remoteAddr,interfaceInfo);
throw new AxisFault("Server.Unauthenticated","權限認證失敗!", null,null);
}
}
}
3.客戶端調用接口:
String endpointUrl = "http://localhost:8080/webServices/services/EkkNameService";
Service service = new Service();
Call call;
try {
call = (Call) service.createCall();
call.setTargetEndpointAddress(new java.net.URL(endpointUrl));
// 參數分別爲服務名稱和方法名稱
QName qName = new QName("EkkNameService", "getEkkNameByNameId");
call.setOperationName(qName);
// 設定參數
call.addParameter("nameId",XMLType.XSD_STRING, ParameterMode.IN);
call.setReturnType(XMLType.XSD_STRING);
// 給參數賦值
Object[] objectArray = new Object[] {"12345"};
String strResponse = (String) call.invoke(objectArray);
System.out.println("webservice結果:" + new String(strResponse));
} catch (Exception e) {
throw new RuntimeException(e);
}
4.可以訪問http://localhost:8080/webServices/EkkNameService?wsdl來查看接口描述