使用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) 的效果。
简单吧 ^__^
使用Httpclient来替代客户端的jsonp跨域解决方案的更多相关文章
- 跨域问题解决方案(HttpClient安全跨域 & jsonp跨域)
1 错误场景 今天要把项目部署到外网的时候,出现了这样的问题, 我把两个项目放到自己本机的tomcat下, 进行代码调试, 运行 都没有问题的, 一旦把我需要调用接口的项目B放到其他的服务器上, 就会 ...
- 跨域问题解决方式(HttpClient安全跨域 & jsonp跨域)
1 错误场景 今天要把项目部署到外网的时候,出现了这种问题, 我把两个项目放到自己本机的tomcat下, 进行代码调试, 执行 都没有问题的, 一旦把我须要调用接口的项目B放到其它的server上, ...
- 深入剖析jsonp跨域原理
在项目中遇到一个jsonp跨域的问题,于是仔细的研究了一番jsonp跨域的原理.搞明白了一些以前不是很懂的地方,比如: 1)jsonp跨域只能是get请求,而不能是post请求: 2)jsonp跨域的 ...
- webapi 跨域访问设置基于jsonp跨域
JSONP实现跨域 Web API并没有提供JSONP Formatter,但是这并不能影响我们前进的脚步,我们可以自定义Formatter来实现JSONP功能.既然是利用JSONP跨域,那么就得简 ...
- 原生JS封装Ajax插件(同域&&jsonp跨域)
抛出一个问题,其实所谓的熟悉原生JS,怎样的程度才是熟悉呢? 最近都在做原生JS熟悉的练习... 用原生Js封装了一个Ajax插件,引入一般的项目,传传数据,感觉还是可行的...简单说说思路,如有不正 ...
- jsonp 跨域请求
背景: JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重要的安全性限制,被称为"Same-Origin Policy"(同源 ...
- 我的jsonp跨域问题
关于jsonp跨域问题,在这个方面也是了解一点点,先记录下来,主要作为以后查看,之前下载并安装过wampserver,了解到了jsonp和json的区别,现在谈谈跨域这个问题: 首先什么是跨域,简单地 ...
- JSONP跨域的原理解析( 一种脚本注入行为)
JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重要的安全性限制, 被称为“some-Origin Policy”(同源策略).这一策略对于Jav ...
- jsonp跨域问题
JSONP是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式). 同源策略限制 ...
随机推荐
- C#语法糖之 ReflectionSugar 通用反射类
用法很简单: ReflectionSugar rs = new ReflectionSugar(100);//缓存100秒 ,可以不填默认不缓存 rs.有嘛点嘛 性能测试: 性能测试类源码: ht ...
- 基于HTML5的燃气3D培训仿真系统
最近上线了的基于HTML5的燃气3D培训仿真系统,以前的老系统是采用基于C++和OpenGL的OpenSceneGraph引擎设计的,OSG引擎性能和渲染效果各方面还是不错的,但因为这次新产品需求要求 ...
- HTTP请求中的Body构建——.NET客户端调用JAVA服务进行文件上传
PS:今日的第二篇,当日事还要当日毕:) http的POST请求发送的内容在Body中,因此有时候会有我们自己构建body的情况. JAVA使用http—post上传file时,spring框架中 ...
- 重新想象 Windows 8.1 Store Apps (85) - 警报通知(闹钟), Tile 的新特性
[源码下载] 重新想象 Windows 8.1 Store Apps (85) - 警报通知(闹钟), Tile 的新特性 作者:webabcd 介绍重新想象 Windows 8.1 Store Ap ...
- Csharp: create word file using Open XML SDK 2.5
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- [PE结构分析] 9.导出表 IMAGE_EXPORT_DIRECTORY
typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; // 未使用,总为0 DWORD TimeDateStamp; // 文 ...
- JavaMail入门第二篇 创建邮件
JavaMail API使用javax.mail.Message类来表示一封邮件,Message类是一个抽象类,所以我们需要使用其子类javax.mail.internet.MimeMessage类来 ...
- u-boot中nandflash初始化流程分析(转)
u-boot中nandflash初始化流程分析(转) 原文地址http://zhuairlunjj.blog.163.com/blog/static/80050945201092011249136/ ...
- gene框架文档 - 路由类 gene_router
路由类 Gene\Router 介绍 Gene\Router 是gene框架的核心类之一,本框架区别于其他常见框架的最大地方就是独特.强大.简单的路由定义等.路由强大灵活,支持回调.类方法:支持res ...
- java中的代码块执行顺序
/* 代码块:在Java中,使用{}括起来的代码被称为代码块. 根据其位置和声明的不同,可以分为 局部代码块:局部位置,用于限定变量的生命周期. 构造代码块:在类中的成员位置,用{}括起来的代码.每次 ...