使用Httpclient來替代客戶端的jsonp跨域解決方案


最近接手一個項目,新項目需要調用老項目的接口,但是老項目和新項目不再同一個域名下,所以必須進行跨域調用了,但是老項目又不能進行任何修改,所以jsonp也無法解決了,於是想到了使用了Httpclient來進行服務端的“跨域”來替代jsonp的客戶端跨域方案。

 

上一篇博文中,詳細剖析了jsonp的跨域原理,本文使用Httpclient來替代jsonp的客戶端跨域方案。

先去 http://hc.apache.org/downloads.cgi 下載最新版httpclient。解壓tutorial文件夾中有html和PDF的使用介紹。

下面實現從8888端口的html4項目中跨域訪問8080端口的html5項目中的JsonServlet:

1)在html4中建立一個中間代理servelt和一個工具類,工具類代碼如下:

import java.io.IOException;
import java.io.OutputStream;
import org.apache.http.HttpEntity;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

public class HttpUtil
{
	public static boolean returnResponseOfUrl(String url, OutputStream os)
	{
		CloseableHttpClient httpclient = HttpClients.createDefault();
		HttpPost httpPost = new HttpPost(url);
		CloseableHttpResponse response = null;
		try{
			response = httpclient.execute(httpPost);
			
			StatusLine statusLine = response.getStatusLine();
			HttpEntity entity = response.getEntity();
			if(statusLine != null && statusLine.getStatusCode() >= 300){
				throw new HttpResponseException(statusLine.getStatusCode(),
												statusLine.getReasonPhrase());
			}
			if(entity == null){
				throw new ClientProtocolException("response contains no content");
			}
			
			entity.writeTo(os);
			return true;
		}catch(IOException e){
			e.printStackTrace();
			return false;
		}finally{
			if(response != null){
				try{
					response.close();
				}catch(IOException e){
					e.printStackTrace();
				}
			}
		}
	}
}

 

 中間代理servlet代碼如下:

@WebServlet("/HttpclientServlet")
public class HttpclientServlet extends HttpServlet 
{
	private static final long serialVersionUID = 1L;
       
    public HttpclientServlet() 
    {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
	{
		this.doPost(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
	{
		String url = request.getParameter("url");
		if(url != null){
			if(!HttpUtil.returnResponseOfUrl(url, response.getOutputStream())){
				if(!HttpUtil.returnResponseOfUrl(url, response.getOutputStream())){	// 如果出錯,再試一次
					// log.error("url:" + url);
				};	
			}
		}
	}

}

 html4項目中的訪問頁面代碼如下:

<!doctype html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="keywords" content="jsonp">
	<meta name="description" content="jsonp">
	<title>jsonp</title>
	<style type="text/css">
		*{margin:0;padding:0;}
		div{width:600px;height:100px;margin:20px auto;}
	</style>
</head>
<body>
	<div>
		<a href="javascript:;">jsonp測試</a>
	</div>
	
<script type="text/javascript" src="js/jquery-1.11.1.js"></script>
<script type="text/javascript">
$(function(){
	$("a").on("click", function(){		
		$.ajax({
			type:"post",
			url:"http://localhost:8888/html4/HttpclientServlet?url="+ecodeURIComponent("http://localhost:8080/html5/JsonServlet"),
			success:function(data) {
				console.log(data);
				console.log(data.name);
				console.log(data.age);
				var user = JSON.parse(data);
				console.log(user.name);
				console.log(user.age);
			}
		});
	})
});	
</script>
</body>
</html>

上面通過:url=http://localhost:8080/html5/JsonServlet 將我們最終要跨域訪問的url地址傳給自己服務器下的 HttpclientServlet. 然后在 HttpclientServlet 中使用httpclient訪問 跨域 url  中的servlet,成功之后,將返回的結果返回給客戶端

html5項目中被 跨域 訪問的servlet代碼如下:

@WebServlet("/JsonServlet")
public class JsonServlet extends HttpServlet 
{
    private static final long serialVersionUID = 4335775212856826743L;

    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException 
    {
        User user = new User();
        user.setName("yuanfang");
        user.setAge(100);
        Object obj = JSON.toJSON(user);
        
        System.out.println(user);            // com.tz.servlet.User@164ff87
        System.out.println(obj);            // {"age":100,"name":"yuanfang"}
        
        response.getWriter().println(obj);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException 
    {
        this.doPost(request, response);
    }
}

啟動8888和8080端口的tomcat,訪問 http://localhost:8888/html4/jsonp.html ,結果如下:

我們注意到第二和第三項都打印的是 undefined ,這是因為 中間代理的 HttpclientServlet,使用的是直接輸出流的方式,所以最終返回的結果不是Json對象,而是字符串,所以需要使用 var user = JSON.parse(data); 來進行解析成 javascript對象就可以,所以第四和第五項都正常輸出了結果。

如果想返回的是json對象,加一句代碼 response.setContentType("text/json;charset=utf-8"); 就可以:

if(url != null){
    response.setContentType("text/json;charset=utf-8");
    if(!HttpUtil.returnResponseOfUrl(url, response.getOutputStream())){
	if(!HttpUtil.returnResponseOfUrl(url, response.getOutputStream())){	// 如果出錯,再試一次
	    // log.error("url:" + url);
		};	
	}
}    

這樣的話,瀏覽器在看到 contentType: "text/json;charset=utf-8" 時,它的js執行引擎會自動幫助我們將字符串解析成json對象。也就是相當於自動調用了 JSON.parse(data) 的效果

簡單吧 ^__^


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM