最近接手一个项目,新项目需要调用老项目的接口,但是老项目和新项目不再同一个域名下,所以必须进行跨域调用了,但是老项目又不能进行任何修改,所以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) 的效果

简单吧 ^__^

使用Httpclient来替代客户端的jsonp跨域解决方案的更多相关文章

  1. 跨域问题解决方案(HttpClient安全跨域 & jsonp跨域)

    1 错误场景 今天要把项目部署到外网的时候,出现了这样的问题, 我把两个项目放到自己本机的tomcat下, 进行代码调试, 运行 都没有问题的, 一旦把我需要调用接口的项目B放到其他的服务器上, 就会 ...

  2. 跨域问题解决方式(HttpClient安全跨域 &amp; jsonp跨域)

    1 错误场景 今天要把项目部署到外网的时候,出现了这种问题, 我把两个项目放到自己本机的tomcat下, 进行代码调试, 执行 都没有问题的, 一旦把我须要调用接口的项目B放到其它的server上, ...

  3. 深入剖析jsonp跨域原理

    在项目中遇到一个jsonp跨域的问题,于是仔细的研究了一番jsonp跨域的原理.搞明白了一些以前不是很懂的地方,比如: 1)jsonp跨域只能是get请求,而不能是post请求: 2)jsonp跨域的 ...

  4. webapi 跨域访问设置基于jsonp跨域

    JSONP实现跨域 Web API并没有提供JSONP  Formatter,但是这并不能影响我们前进的脚步,我们可以自定义Formatter来实现JSONP功能.既然是利用JSONP跨域,那么就得简 ...

  5. 原生JS封装Ajax插件(同域&&jsonp跨域)

    抛出一个问题,其实所谓的熟悉原生JS,怎样的程度才是熟悉呢? 最近都在做原生JS熟悉的练习... 用原生Js封装了一个Ajax插件,引入一般的项目,传传数据,感觉还是可行的...简单说说思路,如有不正 ...

  6. jsonp 跨域请求

    背景: JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重要的安全性限制,被称为"Same-Origin Policy"(同源 ...

  7. 我的jsonp跨域问题

    关于jsonp跨域问题,在这个方面也是了解一点点,先记录下来,主要作为以后查看,之前下载并安装过wampserver,了解到了jsonp和json的区别,现在谈谈跨域这个问题: 首先什么是跨域,简单地 ...

  8. JSONP跨域的原理解析( 一种脚本注入行为)

    JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重要的安全性限制, 被称为“some-Origin Policy”(同源策略).这一策略对于Jav ...

  9. jsonp跨域问题

    JSONP是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式). 同源策略限制 ...

随机推荐

  1. sql server 调用webservice

    sql server版本2008以上,应该都可以 更改服务器配置 sp_configure ; GO RECONFIGURE; GO sp_configure ; GO RECONFIGURE; GO ...

  2. UWP开发入门(十七)——判断设备类型及响应VirtualKey

    蜀黍我做的工作跟IM软件有关,UWP同时会跑在电脑和手机上.电脑和手机的使用习惯不尽一致,通常我倾向于根据窗口尺寸来进行布局的变化,但是特定的操作习惯是依赖于设备类型,而不是屏幕尺寸的,比如聊天窗口的 ...

  3. CSS3魔法堂:背景渐变(Gradient)

    一.前言 很久之前就了解过CSS3的线性渐变(Linear-Gradient),这段时间决定进一步认知这一特性,以下笔记以便日后查阅. 二.CSS3的各种背景渐变   1. 线性渐变 示例——七彩虹 ...

  4. mysql获取插入时自增ID值的方法

    1.  LAST_INSERT_ID: LAST_INSERT_ID 是与table无关的,如果向表a插入数据后,再向表b插入数据,LAST_INSERT_ID会改变. LAST_INSERT_ID是 ...

  5. Brute Force & STL --- UVA 146 ID Codes

     ID Codes  Problem's Link:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&a ...

  6. jQuery实现星星评分功能

    一.这是我做的调查问卷中的一个功能.(第三方MVC框架) 二.功能说明:1.用户点击星星,将值放到隐藏域中.2.用户可以重新点击星星修改回答. 前台JS代码: <script type=&quo ...

  7. Winform开发框架之通用数据导入导出操作的事务性操作完善

    1.通用数据导入导出操作模块回顾 在我的Winfrom开发框架里面,有一个通用的导入模块,它在默默处理这把规范的Excel数据导入到不同的对象表里面,一直用它来快速完成数据导入的工作.很早在随笔< ...

  8. Winform开发框架之通用高级查询模块

    最近一直忙于公司的事情,虽然一直在做一些相关的技术研究,但是很久没能静下心来好好写写博客文章了,想想也有半个月之多了,这半个月来,也一直致力于改善我的WInform开发框架,使得自己及客户使用起来更加 ...

  9. istView的项移除

    如标题所言,是做删除ListView绑定项的功能的:鉴于这个功能当时确实花费了很多时间,并且网上也找不到删除所需的案例,所以,我就做了一份案例,仅供各位前辈和同行进行参考,如有不当之处,还望指点,我将 ...

  10. Mongodb 语法,update,insert,delete,find

    ---恢复内容开始--- db.Users.update({OrganizationCode:"Global"},{$set:{OrganizationCode:"Fre ...