利用servlet做转发,实现js跨域解决同源问题
做前端开发,避免不了跨域这个问题,跨域具体什么概念,不赘述,博客里太多。简单说下,我们用js发请求,不管post还是get,如果发请求的对象和当前web页面不在同一域名下,浏览器的同源策略会限制发请求,也就是说,如果单独写个HTML,用js发远程请求,是发布出去的,浏览器会认为这是不安全的,js在这里能做的很有限。
网上看了很多文章,小弟愚钝,只用js一直没解决这个问题,jQuery的Ajax据说可以,但是测试后发现不行,也许是浏览器版本的原因。有种方法是jsonp,但是好像需要服务器支持,我对服务器端程序了解的少,不懂。再就是script,动态的添加script标签,在src里面填要发的请求地址,但是很明显,只能以get方式发请求,那么post怎么办?反正折磨了很有一段时间,狠下心来,不用js去处理了,用java代码做中转,学过一点皮毛,参考一下网上代码,问题得以解决。
其实分析起来问题很简单,servlet不难,tomcat去处理,很多细节我们不用关心,再就是用java发请求了,之前一直找错方向饶了不少弯路。
首先写个java类,处理get和post请求
参考这篇文章http://www.cnblogs.com/zhuawang/archive/2012/12/08/2809380.html,注释写得比较详细,我就简单剽窃一下吧
package web;
//注意打包的地方,因为后面servlet会用到
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map; public class SendPack {
//发送get请求 url?a=x&b=xx形式
public static String sendGet(String url,String param){
String result = "";
BufferedReader in = null;
try{
String urlName = "";
if(param.length() != 0){
urlName = url + "?" +param;
}
else urlName = url;
URL resUrl = new URL(urlName);
URLConnection urlConnec = resUrl.openConnection();
urlConnec.setRequestProperty("accept", "*/*");
urlConnec.setRequestProperty("connection", "Keep-Alive");
urlConnec.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
urlConnec.connect();
Map<String, List<String>> map = urlConnec.getHeaderFields();
for (String key : map.keySet()) {
System.out.println(key + "--->" + map.get(key));
}
// 定义 BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(urlConnec.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
}catch(Exception e){
System.out.println("发送get请求失败"+e);
e.printStackTrace();
}finally{
try{
if(in != null){
in.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
return result;
}
//发送post请求
public static String sendPost(String url,String param){
String result = "";
PrintWriter out = null;
BufferedReader in = null;
try{
URL resUrl = new URL(url);
URLConnection urlConnec = resUrl.openConnection();
urlConnec.setRequestProperty("accept", "*/*");
urlConnec.setRequestProperty("connection", "Keep-Alive");
urlConnec.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 发送POST请求必须设置如下两行
urlConnec.setDoInput(true);
urlConnec.setDoOutput(true); out = new PrintWriter(urlConnec.getOutputStream());
out.print(param);//发送post参数
out.flush();
// 定义 BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(urlConnec.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
}catch(Exception e){
System.out.println("post请求发送失败"+e);
e.printStackTrace();
}finally{
try{
if(in != null){
in.close();
}
if(out != null){
out.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
return result;
}
/**测试
* 说明:这里用新浪股票接口做get测试,新浪股票接口不支持jsonp,至于post,因为本人用的公司的接口就不展示了,一样的,一个url,一个数据包
*/
/*
public static void main(String[] args) {
// TODO Auto-generated method stub
String resultGet = sendGet("http://hq.sinajs.cn/list=sh600389","");
System.out.println(resultGet);
}
*/ }
然后是servlet程序,写servlet需要一点基础知识
本人用Eclipse开发,没有正式写J2ee,暂时不管了,不偷懒的好处是流程可以学得更清楚,好了。
注意一点,建的工程,要写servlet要导包
,右键工程,Build Path—>Add External Archives会弹出文件浏览器,选择要添加的额外的包
去自己的tomcat目录下面找
,servlet-api.jar包,包含进来。
好了,接下来是servlet代码
package web;
//注意打包的地方,因为后面servlet会用到
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import web.SendPack; public class ForwardRequest extends HttpServlet{ public void doGet(HttpServletRequest req,HttpServletResponse res) throws ServletException{
res.setCharacterEncoding("utf-8");
String addr=req.getParameter("address");//前端规定送的url地址,不懂就去了解一下json
String param=req.getParameter("param"); //同上,传的参数,字符串类型(不管什么格式,字符串传了再说,指定啥格式,前端再解析)
try {
PrintWriter pw = res.getWriter();
String result = SendPack.sendGet(addr, param);//get请求
pw.print(result);//把数据返回给前端
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void doPost(HttpServletRequest req,HttpServletResponse res) throws ServletException{
res.setCharacterEncoding("utf-8");
String addr=req.getParameter("address");
String param=req.getParameter("param");
try {
PrintWriter pw = res.getWriter();
String result = SendPack.sendPost(addr, param);//post请求
pw.print(result);//把数据返回给前端
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
}
好了,现在编译下,找到class文件,编译我就不说了,
,class文件上级目录web,将web文件夹复制,粘到哪里呢,先等等。
先要部署tomcat,在tomcat的webapps目录下面新建一个文件夹testsendpack。里面添加子文件夹WEB-INF,然后再WEB-INF目录下添加classes目录,将刚要粘贴的web文件夹粘贴到这里。在classes文件夹同目录下新建一个web.xml配置文件。
web.xml内容如下(可以直接去root目录或其他目录找,这里我就把自带的注释删掉)
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd"
version="3.1"
metadata-complete="true"> <display-name>servlet ajax</display-name>
<description>
servlet ajax
</description> <servlet>
<servlet-name>ajaxreq</servlet-name><!--给自己的servlet取个名字-->
<servlet-class>web.ForwardRequest</servlet-class><!--这里就是servlet代码里强调的包问题,就是servlet的class文件但没有后缀-->
</servlet>
<servlet-mapping>
<servlet-name>ajaxreq</servlet-name><!--这里要注意跟上面取的servlet名字一致-->
<url-pattern>/forwardreq</url-pattern>
<!--这里是设置servlet的url路径,在用js发送请求时url就是webapps下的建的文件夹名加上这个,这里是testsendpack/forwardreq -->
</servlet-mapping>
</web-app>
好了,环境已经搭好了,让我们来做测试吧
我们在testsendpack目录下面新建一个html文件,名字自己去取啦,我取index,这里我就偷个懒,就jq发Ajax请求,方便点。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ajax发请求servlet处理</title>
<script type="text/javascript" src="jquery-1.8.2.js"></script>
</head>
<body>
<button id='btnget'>get</button>
<button id='btnpost'>post</button>
<script type="text/javascript">
function sendPack(sendType,url,para,asyn){
/*
* 参数依次为发送类型,post还是get,url地址,参数,是否异步,默认异步
*/
if(asyn == undefined) asyn = true;
$.ajax({
url:"/testsendpack/forwardreq",//servlet地址
type: sendType,
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
dataType:"text",
data:{
address:url,
param : para
},
async : asyn,
success:function (data){
alert(data);
},
error: function(xhr, state, err) {
alert('与后台通信失败。故障信息:' + err);
}
});
}
$(function(){
$("#btnget").click(function(){
sendPack("GET","http://hq.sinajs.cn/list=sh600389","");
});
$("#btnpost").click(function(){
//sendPack();
});
});
</script>
</body>
</html>
因为post的例子是公司的,不好放出来,哪位仁兄知道有公共的post例子可以提供下,经测试post是没有问题的,如果有问题,留言问我。
开启tomcat,bin目录下的startup.bat,弹出的黑框,可以看到servlet被加载没有,如果你看到testsendpack并且没有一大坨乱七八糟的东西,那么恭喜,离成功仅一步之遥。如果你出现黑框一闪即逝,不要慌,用记事本打开startup.bat,在最后一行加上pause,好了,在跑一下,你可以看到什么错误信息,八成是jre环境没找到吧,配java环境简单说下,找到jdk目录,复制路径,系统环境变量里新建JAVA_HOME,粘上路径,然后在path的最后面加上;%JAVA_HOME%bin就可以了。
最后运行一下吧,浏览器里输入127.0.0.1:8080/testsendpack/index.html,
附上结果,好了,江山股份的行情查到了,字段啥意思,不想研究了,get请求和post请求的转发都实现了,post不写例子不要怪我,我找不着。。。
返回的字符串,想怎么处理就怎么处理吧。
最后最后,有啥问题可以给我留言,欢迎吐槽。
利用servlet做转发,实现js跨域解决同源问题的更多相关文章
- JS跨域解决iframe高度自适应(IE8/Firefox/Chrome适用)
参考园友的js跨越实现,有提到三种方式: 1. 中间页代理方式,利用iframe的location.hash 参见:http://www.5icool.org/a/201203/a1129.html ...
- JS跨域解决方式 window.name
window.name 传输技术,原本是 Thomas Frank 用于解决 cookie 的一些劣势(每个域名 4 x 20 Kb 的限制.数据只能是字符串.设置和获取 cookie 语法的复杂等等 ...
- js跨域解决方式
什么是跨域? 概念:仅仅要协议.域名.port有不论什么一个不同,都被当作是不同的域.(所谓同源是指,域名.协议,port同样.),对于port和协议的不同,仅仅能通过后台来解决. URL 说明 是否 ...
- [转]JS跨域解决方式 window.name
本文转自:http://www.cnblogs.com/lichuntian/p/4909465.html window.name 传输技术,原本是 Thomas Frank 用于解决 cookie ...
- 黄聪:Access-Control-Allow-Origin,JS跨域解决办法
.htaccess添加下面代码: <IfModule mod_headers.c> Header add Access-Control-Allow-Origin "*" ...
- JavaScript跨域解决方法大全
跨域的定义:JavaScript出于安全性考虑,同源策略机制对跨域访问做了限制.域仅仅是通过“URL的首部”字符串进行识别,“URL的首部”指window.location.protocol +win ...
- 利用JS跨域做一个简单的页面访问统计系统
其实在大部分互联网web产品中,我们通常会用百度统计或者谷歌统计分析系统,通过在程序中引入特定的JS脚本,然后便可以在这些统计系统中看到自己网站页面具体的访问情况.但是有些时候,由于一些特殊情况,我们 ...
- 利用JS跨域做一个简单的页面訪问统计系统
事实上在大部分互联网web产品中,我们一般会用百度统计或者谷歌统计分析系统,通过在程序中引入特定的JS脚本,然后便能够在这些统计系统中看到自己站点页面详细的訪问情况.可是有些时候,因为一些特殊情况,我 ...
- js跨域请求解决方案
什么是跨域? 跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的. 广义的跨域: 1.) 资源跳转: A链接.重定向.表单提交 2.) 资源嵌入: <link>.&l ...
随机推荐
- 推荐一个很好的富文本web编辑器UEditor
前天产品提了一个编辑器的bug,本人找是找到了问题的症结,就是不好改.框架是压缩兼混淆后的代码.查一下,好多年前的框架... 咨询了一个同事有关旧框架的事情,他也建议我升级编辑器并帮忙帮我找了UEdi ...
- TortoiseSVN客户端重新设置用户名和密码[转]
在第一次使用TortoiseSVN从服务器CheckOut的时候,会要求输入用户名和密码,这时输入框下面有个选项是保存认证信息,如果选了这个选项,那么以后就不用每次都输入一遍用户名密码了. 不过,如果 ...
- FC网络学习笔记01
1.Fibre Channel 也就是“网状通道”的意思,简称FC,可以称其为FC协议.FC网络或FC互联. 2.像TCP/IP一样,FC协议集同样具备TCP/IP协议集以及以太网中的概念,比如FC交 ...
- richTextBox插入表格
附件:http://files.cnblogs.com/xe2011/richTextBox_InsertTable.rar 插入表格 /// <summary> /// 插入表格 /// ...
- W5500问题集锦(持续更新中)
在"WIZnet杯"以太网技术竞赛中,有非常多參赛者在使用中对W5500有各种各样的疑问,对于这款WIZnet新推出的以太网芯片,使用中大家是不是也一样存在下面问题呢?来看一看: ...
- Spring框架:Spring容器具体解释
Spring容器 Spring容器能够帮助你管理所有的Bean对象.专业术语称之为IoC控制反转.在传统的程序中.对象的生成都是由开发人员完毕的.而在控制反转中,对象的生成所有都交给框架完毕.这种优点 ...
- 【Android XMPP】 学习资料收集贴(持续更新)
系列一: 基于xmpp openfire smack开发之openfire介绍和部署[1] 基于xmpp openfire smack开发之smack类库介绍和使用[2] 基于xmpp openfir ...
- xshell连接本地Linux虚拟机!
终端输入ifconfig获取本地虚拟机的IP地址; 安装openssh-server sudo apt-get install openssh-server 查看server是否启动: ps -ef ...
- sql执行万条update语句优化
几个月没有更新笔记了,最近遇到一个坑爹的问题,顺道记录一下.. 需求是这样的:一次性修改上万条数据库. 项目是用MVC+linq的. 本来想着用 直接where() 1 var latentCusto ...
- react-native之站在巨人的肩膀上
react-native之站在巨人的肩膀上 前方高能,大量图片,不过你一定会很爽.如果爽到了,请告诉我