1. 程式人生 > >axis2的方法呼叫以及302 Error: Moved Temporarily的解決方法

axis2的方法呼叫以及302 Error: Moved Temporarily的解決方法

AddBillSuccessCallBack.java是一個普通的action裡面的方法就是接受2個引數,並更新資料庫某個欄位,

把這個類配置到webservice中去。

其它配置就不說了,主要想說的是在呼叫的時候出現的問題,這是配置

services.xml

<!--
  ~ Licensed to the Apache Software Foundation (ASF) under one
  ~ or more contributor license agreements. See the NOTICE file
  ~ distributed with this work for additional information
  ~ regarding copyright ownership. The ASF licenses this file
  ~ to you under the Apache License, Version 2.0 (the
  ~ "License"); you may not use this file except in compliance
  ~ with the License. You may obtain a copy of the License at
  ~
  ~ http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing,
  ~ software distributed under the License is distributed on an
  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  ~ KIND, either express or implied. See the License for the
  ~ specific language governing permissions and limitations
  ~ under the License.
  -->

<service name="afterAddBillMessage">
    <description>
        This service is to give message to the calling for add a bill
    </description>
    <parameter name="ServiceClass">org.hd.axis2.device.AddBillSuccessCallBack</parameter>
    <operation name="hadAddBillForTheCall">
    <messageReceiver  class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
    </operation>
</service>
package org.hd.axis2.device;

import org.apache.log4j.Logger;
import org.hd.business.service.BusinessService;
import org.hd.business.summary.model.CallSummaryVo;
import org.hd.login.action.LoginAction;
import org.rd.framework.common.container.ContainerManager;

public class AddBillSuccessCallBack{
	private static final Logger logger = Logger.getLogger(AddBillSuccessCallBack.class.getName());
	private BusinessService businessService = (BusinessService)ContainerManager.getComponent(BusinessService.BEAN_ID);
	
	public String hadAddBillForTheCall(String callid,String billNumber){
		String resultMessage="";
		CallSummaryVo call=new CallSummaryVo();
		if(callid==null||callid.trim().equals("")){
			resultMessage="未獲取到通話callid,操作失敗!";
		}else if(billNumber==null||billNumber.trim().equals("")){
			resultMessage="未獲取到工單號billNumber,操作失敗!";
		}else{
			call.setVoiceid(callid);
			call.setBill_number(billNumber);
			businessService.updateSummaryByWebservice(call);
			resultMessage="收到資訊:callid="+callid+",billNumber="+billNumber;
		}
		System.out.println("呼叫webservice的結果資訊:"+resultMessage);
		logger.error("呼叫webservice的結果資訊:"+resultMessage);
		return resultMessage;
		
	}
}

上面我們配置好了webservice,現在就看看呼叫的效果,遇到一個錯誤:

Exception in thread "main" org.apache.axis2.AxisFault: Transport error: 302 Error: Moved Temporarily
at org.apache.axis2.transport.http.HTTPSender.handleResponse(HTTPSender.java:310)
at org.apache.axis2.transport.http.HTTPSender.sendViaPost(HTTPSender.java:194)
at org.apache.axis2.transport.http.HTTPSender.send(HTTPSender.java:75)
at org.apache.axis2.transport.http.CommonsHTTPTransportSender.writeMessageWithCommons(CommonsHTTPTransportSender.java:404)
at org.apache.axis2.transport.http.CommonsHTTPTransportSender.invoke(CommonsHTTPTransportSender.java:231)
at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:443)
at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:406)
at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:229)
at org.apache.axis2.client.OperationClient.execute(OperationClient.java:165)
at org.apache.axis2.client.ServiceClient.sendReceive(ServiceClient.java:555)
at org.apache.axis2.client.ServiceClient.sendReceive(ServiceClient.java:531)
at org.apache.axis2.rpc.client.RPCServiceClient.invokeBlocking(RPCServiceClient.java:102)
at org.hd.axis2.client.AddBillSuccessCallBackClient.main(AddBillSuccessCallBackClient.java:36)


302這個錯簡簡單單幾行也找不到原因,從網上看了看有個官方的解釋比較可信:

HTTP錯誤302 - 臨時移動

Introduction 介紹

Your Web server thinks that your URL has been temporarily redirected to another URL.您的Web伺服器認為您的網址已經被暫時重定向到另一個URL。 The client system is expected to immediately retry the alternate URL.客戶端系統立即重試替代的URL。

302 errors in the HTTP cycle 302中的錯誤的HTTP週期

Any client (eg your Web browser or our CheckUpDown robot) goes through the following cycle when it communicates with the Web server:任何客戶端(如Web瀏覽器或我們的CheckUpDown機器人)經過下一個週期,當它與Web伺服器進行通訊:

•Obtain an IP address from the IP name of the site (the site URL without the leading 'http://'). IP的站點名稱(網站URL沒有起始的'http://')獲得一個IP地址。 This lookup (conversion of IP name to IP address) is provided by domain name servers (DNSs).這個對應關係(IP名稱到IP地址的轉換)提供域名伺服器(DNSs)。
•Open an IP socket connection to that IP address.開啟一個IP套接字連線到該IP地址。
•Write an HTTP data stream through that socket.通過該套接字寫HTTP資料流。
•Receive an HTTP data stream back from the Web server in response.接收從Web伺服器響應的HTTP資料流。 This data stream contains status codes whose values are determined by the HTTP protocol.該資料流包括狀態編碼,其值是由HTTP協議。 Parse this data stream for status codes and other useful information.解析該資料流的狀態碼和其他有用的資訊。
This error occurs in the final step above when the client receives an HTTP status code that it recognises as '302'.這個錯誤發生在以上時,客戶端收到HTTP狀態程式碼,並識別其為'302'的最後一步。

Resolving 302 errors - general 解決302錯誤-一般

The 302 response from the Web server should always include an alternative URL to which redirection should occur. 302響應從Web伺服器應始終包括的替代URL重定向應該發生的。 If it does, a Web browser will immediately retry the alternative URL.如果是的話,Web瀏覽器會立即重試另一個URL。 So you never actually see a 302 error in a Web browser, unless perhaps you have a corrupt redirection chain eg URL A redirects to URL B which in turn redirects back to URL A. If your client is not a Web browser, it should behave in the same way as a Web browser ie immediately retry the alternative URL.所以,你從來沒有真正在Web瀏覽器中看到一個302錯誤,除非也許你有一個腐敗的重定向鏈,如一個URL重定向到網址B,這反過來又重定向到URL A.如果您的客戶端不是一個Web瀏覽器,它應該表現在以同樣的方式作為一個Web瀏覽器,即立即重試另一個URL。

If the Web server does not return an alternative URL with the 302 response, then either the Web server sofware itself is defective or the Webmaster has not set up the URL redirection correctly.如果Web伺服器沒有返回302響應的替代URL,然後的Web伺服器sofware本身是有缺陷的或管理員沒有設定正確的URL重定向。

Resolving 302 errors - CheckUpDown 解決302錯誤- CheckUpDown

Redirection of URLs may occur for low-level URLs (specific URLs within the Web site such aswww.isp.com/products/index.html ) when you reorganise the web site, but is relatively uncommon for the top-level URLs (such aswww.isp.com ) which most CheckUpDown users ask us to check.當你重定向的URL,可能會出現低級別的網址(網站內,如www.isp.com /產品/ index.html的特定URL)重組的網站,但相對少見的頂級的URL(例如作為www.isp.com)其中大部分的CheckUpDown使用者要求我們檢查。 So this error should be fairly infrequent.因此,這個錯誤應該是相當罕見的。

The 302 response from the Web server should always include an alternative URL to which redirection should occur. 302響應從Web伺服器應始終包括的替代URL重定向應該發生的。 If it does, CheckUpDown automatically tries the alternative URL.如果是這樣,的CheckUpDown會自動嘗試另一個URL。 This in turn may possibly lead to another redirection which CheckUpDown then tries.這反過來又可能導致另一個重定向的CheckUpDown然後嘗試。 This continues for a maximum of 5 redirections.這最多持續5重定向。 As soon as 5 redirections have occurred, CheckUpDown gives up and reports the 302 error for your account.只要5重定向時有發生,的CheckUpDown放棄,並報告302錯誤您的帳戶。 So you should only ever see the 302 error if 1) the Web server gives no alternative URL on the 302 response or 2) the number of redirections exceeds 5.所以,你應該只看到302錯誤:1)Web伺服器沒有給出替代URL的302響應或2)重定向的數量超過5個。 This second condition should be fairly unlikely - and may indicate a recursive pattern eg URL A redirects to URL B which in turn redirects back to URL A.這第二個條件應該是相當不可能的 - 一個可能表明一個遞迴模式,例如URL重定向到網址B,這反過來又重定向到URL A.

You first need to check that the IP name we use to check for your account is accurate.您首先需要檢查IP名稱,我們用它來檢查您的帳戶是準確的。 If you or your ISP have configured something so that any access using this name should now be redirected to another name, then you need to update your CheckUpDown account to start using the new name.如果您或您的ISP已經配置了一些東西,使任何接入使用這個名字,現在應該被重定向到另外一個名字,那麼你需要更新您的CheckUpDown帳戶,開始使用新的名稱。

If you believe that the IP name we use is exact (should not be redirected), please try accessing the current URL using a Web browser.如果您認為我們使用的IP名稱是準確的(不應該被重定向),請嘗試使用Web瀏覽器訪問的URL。 Note carefully which URL actually gets displayed, because your browser may silently switch to a substitute URL if it receives an 302 message from the Web server.請注意的URL被顯示,因為您的瀏覽器可能會靜靜地切換到一個替代URL,如果它接收到一個302訊息從Web伺服器。 If you see any evidence of a new URL, try accessing that directly from your browser.如果你看到任何證據的一個新的URL,請嘗試訪問,直接從您的瀏覽器。 If this works (you see the Web site as expected), then this new URL is what you may need to update on your CheckUpDwon account.如果這樣的作品(你看的網站如預期),那麼這個新的網址是什麼,你可能需要更新在您的CheckUpDwon帳戶。 If this is a temporary redirection, then you may also need to reinstate the original IP name at a later date when the redirection is no longer effective.如果這是一個臨時的重定向,那麼你可能還需要在以後的日子不再有效時,重定向恢復原來的IP名稱。

If none of the above help, we can analyse the underlying HTTP data streams we receive from the Web server.如果沒有上述的幫助,我們可以分析的基礎我們收到來自Web伺服器的HTTP資料流。 These can provide additional information about the new URL(s) which the Web server thinks we should be accessing.這些新的URL(S)認為,我們應該訪問的Web伺服器,可以提供額外的資訊。 Before doing this, we prefer you to identify any deliberate changes on your side, liaising with your ISP if needs be.在此之前,我們更,你識別任何故意的變化就在你身邊,與你的ISP聯絡,如果需要的話。

302 errors should occur infrequently, because top-level URLs do not change often. 302錯誤應該很少發生,因為頂級的URL不經常更改。 If they do change, then this is typically because a redirection URL is being suggested.如果他們不改變,那麼這通常是因為重定向URL建議。 This pervasive change is unlikely to occur by accident, so most often we can resolve this error by updating our system records for your account following a deliberate change of URL on your part, whether this change is temporary or permanent.這種無處不在的變化是不太可能發生意外,所以多數時候我們可以解決這個錯誤,更新我們的系統記錄您的帳戶後,故意URL上的變化,這種變化是暫時的還是永久的。

也就是說url不對,我以前呼叫過是可以成功呼叫的,後來就不對了,讓我很疑惑。後來想到是不是被攔截了,

查看了一下工程中的攔截器過濾器,在裡面加上了這個地址,讓工程不攔截這個地址,最後果然成功了。

web.xml

    <filter>
        <filter-name>securityFilter</filter-name>
        <filter-class>org.rd.framework.common.filter.SecurityFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>securityFilter</filter-name>
        <url-pattern>*</url-pattern>
    </filter-mapping> 

org.rd.framework.common.filter.SecurityFilter

package org.rd.framework.common.filter;

import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.rd.framework.util.Constants;

public class SecurityFilter extends AbstractFilter {

	@Override
	protected void doFilterInternal(HttpServletRequest request,
			HttpServletResponse response, FilterChain chain)
			throws ServletException, IOException {

		HttpSession session = request.getSession();
		String userid = (String) session.getAttribute(Constants.CURRENT_USER_ID);
		if (userid != null && !"".equals(userid)) {
//			session.setAttribute(Constants.CURRENT_USER_ID, userid);
			chain.doFilter(request, response);
			return;
		}
		String suffixal = request.getRequestURI().substring(request.getRequestURI().lastIndexOf(".") + 1);
		if ("css".equals(suffixal) || 
		    "gif".equals(suffixal) ||
		    "jpg".equals(suffixal) ||
		    "html".equals(suffixal) ||
		    "htm".equals(suffixal) ||
			"js".equals(suffixal) || 
			"png".equals(suffixal) ||
			//"jsp".equals(suffixal) ||
			"xml".equals(suffixal)) {
			chain.doFilter(request, response);
			return;
		}
		if(request.getRequestURI().contains("afterAddBillMessage")||request.getRequestURI().contains("services")){
			chain.doFilter(request, response);
			System.out.println("webservice請求,經過過濾!");
			return;
		}
		suffixal = request.getRequestURI().substring(request.getRequestURI().lastIndexOf("/") + 1);
		if ("login.action".equals(suffixal)) {
			chain.doFilter(request, response);
			return;
		}
		
		if ("hdlogin.jsp".equals(suffixal)) {
			chain.doFilter(request, response);
			return;
		}
		
		if ("loginOut.action".equals(suffixal)) {
			chain.doFilter(request, response);
			return;
		}
		if ("ajaxLogin.action".equals(suffixal)) {
			chain.doFilter(request, response);
			return;
		}
		
		/*if ("left.action".equals(suffixal)) {
			chain.doFilter(request, response);
			return;
		}
		
		if ("right.action".equals(suffixal)) {
			chain.doFilter(request, response);
			return;
		}*/
		
//		if (null == suffixal || "".equals(suffixal)) {
//			chain.doFilter(request, response);
//			return;
//		}
//		
//		if (request.getRequestURI().indexOf("test") > -1 ) {
//			chain.doFilter(request, response);
//			return;
//	    }
		response.sendRedirect(request.getContextPath() + "/hdlogin.jsp");
	}

}

 關於wbservice,我還想說一說方法的呼叫,一般我們需要使用java程式碼來呼叫,

也就是客戶端程式碼,這樣的程式碼有很多種,我想說的不是這個而是在瀏覽器位址列的呼叫。

寫好了webservice肯定要除錯,如果都在main函式中呼叫,每次都要run一下,

其實webservice就是xml,我們在瀏覽器中完全可以直接呼叫!

比如上面的例子,如果我的專案名叫HelpDesk,埠使用8095

那麼在瀏覽器位址列輸入

這樣能看到完整的webservice的xml內容,其中wsdl和xsd是不同的解析協議(猜的),

不同的協議達到的效果是一樣的。

如果要呼叫上面類中的方法可以輸入:

改成:

成功!
返回結果:
- <ns:hadAddBillForTheCallResponse xmlns:ns="
http://device.axis2.hd.org">
  <ns:return>收到資訊:callid=449758D8FFFFFFF900C44EA936870D14,billNumber=ceshi1</ns:return>
  </ns:hadAddBillForTheCallResponse>

- <soapenv:Reason xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
  <soapenv:Text xml:lang="en-US">unexpected token: 449758D near line 1, column 88 [select call from org.hd.business.summary.model.CallSummaryVo call where call.voiceid=''449758D8FFFFFFF900C44EA936870D14'']; nested exception is org.hibernate.hql.ast.QuerySyntaxException: unexpected token: 449758D near line 1, column 88 [select call from org.hd.business.summary.model.CallSummaryVo call where call.voiceid=''449758D8FFFFFFF900C44EA936870D14'']</soapenv:Text>
  </soapenv:Reason>

根據返回資訊原來是sql拼寫的錯誤,看一看傳參,就是多加了單引號。

以下是客戶端呼叫程式碼,可作比較:

package org.hd.axis2.client;

import javax.xml.namespace.QName;
import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.rpc.client.RPCServiceClient;

public class AddBillSuccessCallBackClient {
	
	public static void main(String args[]) throws AxisFault {
		// 使用RPC方式呼叫WebService
		RPCServiceClient serviceClient = new RPCServiceClient();
		Options options = serviceClient.getOptions();
		// 指定呼叫WebService的URL
		//http://10.23.130.118:8095/HelpDesk/services/afterAddBillMessage
		
		
		//以下測試埠是80,工程名是ROOT(為了配置域名不用寫工程名和埠),所以預設不用寫;另外在hosts中
		//配置了lsy.helpdesk.citicsinfo.com對應127.0.0.1,所以和localhost等效
		// http://localhost/services/afterAddBillMessage 成功
		// http://127.0.0.1/services/afterAddBillMessage 成功
		// http://127.0.0.1:80/services/afterAddBillMessage 成功
		// http://lsy.helpdesk.citicsinfo.com/services/afterAddBillMessage  成功
		// http://lsy.helpdesk.citicsinfo.com:80/services/afterAddBillMessage  成功
		EndpointReference targetEPR = new EndpointReference(
				"http://lsy.helpdesk.citicsinfo.com:80/services/afterAddBillMessage");
		options.setTo(targetEPR);
		// 指定hadAddBillForTheCall方法的引數值
		Object[] opAddEntryArgs = new Object[] { "449758D8FFFFFFF900C44EA936870D14","22lumberIUERREO9834-SDF" };
		// 指定sayHelloToPerson方法返回值的資料型別的Class物件
		Class[] classes = new Class[] { String.class };
		// 指定要呼叫的sayHelloToPerson方法及WSDL檔案的名稱空間
		// QName opAddEntry = new QName("http://ws.apache.org/axis2",
		// "sayHelloMethod");
		// QName opAddEntry = new QName("http://service", "sayHelloMethod");
		QName opAddEntry = new QName("http://device.axis2.hd.org",
				"hadAddBillForTheCall");

		// 呼叫sayHelloToPerson方法並輸出該方法的返回值
		System.out.println(serviceClient.invokeBlocking(opAddEntry,
				opAddEntryArgs, classes)[0]);
	}
}