环境:
1. 服务端是一个webservbice服务。
2. 我这边做为客户端,用服务端给的wsdl,利用asix2自动生成java代码。
问题:
1. 登录webservice服务器的时候,会返回 307 termporary redirect。并在头部的Location中返回重定向的url,后续发起的业务请求到这个url。但是由到axis2的原码上,没有处理http307而是把它归到exception中,导至无法获取到Header中的Location。
(说明:该方法位于org.apache.axis2.transport.http. HTTPSender这个类中,因为,我们要把axis2-transport-http-1.6.2.jar这个包去掉,换用源码。源码:axis2-1.6.2-src.zip可直接去官网下载)
/**
* Used to handle the HTTP Response
*
* @param msgContext - The MessageContextof the message
* @param method - The HTTP method used
* @throws IOException - Thrown in case anexception occurs
*/
private void handleResponse(MessageContextmsgContext,
HttpMethodBasemethod) throws IOException {
int statusCode =method.getStatusCode();
log.trace("Handling response -" + statusCode);
if (statusCode == HttpStatus.SC_OK) {
// Save the HttpMethod so that wecan release the connection when cleaning up
msgContext.setProperty(HTTPConstants.HTTP_METHOD, method);
processResponse(method,msgContext);
} else if (statusCode ==HttpStatus.SC_ACCEPTED) {
/*When an HTTP 202 Accepted code has been received, this will be the case of anexecution
* of an in-only operation. In such a scenario,the HTTP response headers should be returned,
* i.e. session cookies. */
obtainHTTPHeaderInformation(method,msgContext);
// Since we don't expect any content with a 202response, we must release the connection
method.releaseConnection();
} else if (statusCode ==HttpStatus.SC_INTERNAL_SERVER_ERROR ||
statusCode ==HttpStatus.SC_BAD_REQUEST) {
// Save the HttpMethod so that wecan release the connection when cleaning up
msgContext.setProperty(HTTPConstants.HTTP_METHOD, method);
Header contenttypeHeader =
method.getResponseHeader(HTTPConstants.HEADER_CONTENT_TYPE);
String value = null;
if (contenttypeHeader != null) {
value =contenttypeHeader.getValue();
}
OperationContext opContext =msgContext.getOperationContext();
if(opContext!=null){
MessageContext inMessageContext=
opContext.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
if(inMessageContext!=null){
inMessageContext.setProcessingFault(true);
}
}
if (value != null) {
processResponse(method,msgContext);
}
if(org.apache.axis2.util.Utils.isClientThreadNonBlockingPropertySet(msgContext)){
throw newAxisFault(Messages.getMessage("transportError",
String.valueOf(statusCode),
method.getStatusText()));
}
}else {
// Since wedon't process the response, we must release the connection immediately
method.releaseConnection();
throw newAxisFault(Messages.getMessage("transportError",
String.valueOf(statusCode),
method.getStatusText()));
}
}
解决方法(红色代码为解决方法):
/**
* Used to handle the HTTP Response
*
* @param msgContext - The MessageContext of the message
* @param method - The HTTPmethod used
* @throws IOException - Thrown in case an exception occurs
*/
private void handleResponse(MessageContext msgContext,
HttpMethodBasemethod) throws IOException {
int statusCode = method.getStatusCode();
log.trace("Handling response - " + statusCode);
if (statusCode == HttpStatus.SC_OK) {
// Save the HttpMethod so that we can release the connection whencleaning up
msgContext.setProperty(HTTPConstants.HTTP_METHOD, method);
processResponse(method, msgContext);
} else if (statusCode == HttpStatus.SC_ACCEPTED) {
/* When an HTTP 202Accepted code has been received, this will be the case of an execution
* of an in-only operation. In such a scenario,the HTTP response headers should be returned,
* i.e. session cookies. */
obtainHTTPHeaderInformation(method,msgContext);
// Since we don't expectany content with a 202 response, we must release the connection
method.releaseConnection();
} else if (statusCode == HttpStatus.SC_INTERNAL_SERVER_ERROR ||
statusCode ==HttpStatus.SC_BAD_REQUEST) {
// Save the HttpMethod so that we can release the connection whencleaning up
msgContext.setProperty(HTTPConstants.HTTP_METHOD, method);
Header contenttypeHeader =
method.getResponseHeader(HTTPConstants.HEADER_CONTENT_TYPE);
String value = null;
if (contenttypeHeader != null) {
value =contenttypeHeader.getValue();
}
OperationContext opContext = msgContext.getOperationContext();
if(opContext!=null){
MessageContext inMessageContext=
opContext.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
if(inMessageContext!=null){
inMessageContext.setProcessingFault(true);
}
}
if (value != null) {
processResponse(method,msgContext);
}
if(org.apache.axis2.util.Utils.isClientThreadNonBlockingPropertySet(msgContext)){
throw new AxisFault(Messages.getMessage("transportError",
String.valueOf(statusCode),
method.getStatusText()));
}
}else if ( statusCode == 307){
msgContext.setProperty(HTTPConstants.HTTP_METHOD,method);
processResponse(method,msgContext);
}else {
// Since we don't process the response, we must release the connectionimmediately
method.releaseConnection();
throw new AxisFault(Messages.getMessage("transportError",
String.valueOf(statusCode),
method.getStatusText()));
}
}
2. 获取到Location后,后面的业务请求,要在同一连接中进行,也就是业务请求和登录要在同一个连接中。但如果按照axis2自动生成的代码去执么,会在业务请求时,建立一个新的连接。
解决问题:
A. 登录接口的连接不要断开(注释掉标红色的代码):
//此处省略很多代码
throw f;
}
}else{
throw f;
}
} finally {
//_messageContext.getTransportOut().getSender().cleanup(_messageContext);
}
}
B. 在业务请求的时候,用该连接去提交Sessionid(其中url的形式为:http://IP:port/sessionid):
List list = testLGI();
String url = (String)list.get(0);
soap.ScfMobileSoapStub stub =(soap.ScfMobileSoapStub)list.get(1);
stub._getServiceClient().getOptions().setTo(new org.apache.axis2.addressing.EndpointReference(
url));