利用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不写例子不要怪我,我找不着。。。

返回的字符串,想怎么处理就怎么处理吧。

最后最后,有啥问题可以给我留言,欢迎吐槽

时间: 2024-11-12 01:08:13

利用servlet做转发,实现js跨域解决同源问题的相关文章

JS跨域解决方式 window.name

window.name 传输技术,原本是 Thomas Frank 用于解决 cookie 的一些劣势(每个域名 4 x 20 Kb 的限制.数据只能是字符串.设置和获取 cookie 语法的复杂等等)而发明的(详细见原文:<Session variables without cookies>),后来Kris Zyp 在此方法的基础上强化了 window.name 传输 ,并引入到了 Dojo(dojox.io.windowName),用来解决跨域数据传输问题. window.name 的美妙

Js跨域解决方法总结

本文转载自网易博客 出于安全性的考虑,在AJAX应用中,浏览器通常都会限制跨域提交数据.但由于经常和其他部门有接口对接的业务需求,需要跨域获取数据. IE对于跨域访问的处理是,弹出警告框,提醒用户.如果用户将该网站纳入可信任网站,或者调低安全级别,那么这个问题IE就不会在提醒你.    FireFox等其它非微软的浏览器遇到跨域访问,则解决方案统一是拒绝访问. Huodong.qq.com 下的网站前端要获取act.qzone.qq.com下的接口数据 有3种解决方法 1.服务器端做代理 服务器

黄聪:Access-Control-Allow-Origin,JS跨域解决办法

.htaccess添加下面代码: <IfModule mod_headers.c> Header add Access-Control-Allow-Origin "*" </IfModule> web.config设置下面代码: .... <system.webServer> <httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origi

问卷项目--js跨域

项目中因为要把问卷投放到第三方,并且对方要收集统计数据,因此在调用对方接口的时候就会存在跨域的问题. 1. 什么叫js跨域 浏览器不允许javascript跨域请求其他域名下的内容.端口号不同,主域相同子域不同,协议不同,不同域名等等情况 下面表格里的a.js是无法获取b.js的内容的. 情况 举例 端口号不同 http://www.baidu.com/a.js   vs.  http://www.baidu.com:8080/b.js 主域相同子域不同 http://www.baidu.com

JavaScript跨域解决方法大全

跨域的定义:JavaScript出于安全性考虑,同源策略机制对跨域访问做了限制.域仅仅是通过"URL的首部"字符串进行识别,"URL的首部"指window.location.protocol +window.location.host,也可以理解为"Domains, protocols and ports must match".实际上,同源策略就是浏览器的一种保护机制,只要请求双方的URL协议.域名(主机).端口有任何一个不同,都被当作是跨域.

利用JS跨域做一个简单的页面访问统计系统

其实在大部分互联网web产品中,我们通常会用百度统计或者谷歌统计分析系统,通过在程序中引入特定的JS脚本,然后便可以在这些统计系统中看到自己网站页面具体的访问情况.但是有些时候,由于一些特殊情况,我们需要自己来设计统计系统.由于前段时间公司的业务需求,我也是自己尝试了下,本文提供的是一个基本思路,统计系统也比较简单. 几个基本统计需求: 1.统计web每个页面用户访问量 2.统计用户访问者的和IP地址信息 3.页面之间的跳转情况 4.访问高峰时间段 服务器结构: 数据库表设计: 以上只是我简单列

利用JS跨域做一个简单的页面訪问统计系统

事实上在大部分互联网web产品中,我们一般会用百度统计或者谷歌统计分析系统,通过在程序中引入特定的JS脚本,然后便能够在这些统计系统中看到自己站点页面详细的訪问情况.可是有些时候,因为一些特殊情况,我们须要自己来设计统计系统.因为前段时间公司的业务需求,我也是自己尝试了下,本文提供的是一个基本思路,统计系统也比較简单. 几个基本统计需求: 1.统计web每一个页面用户訪问量 2.统计用户訪问者的和IP地址信息 3.页面之间的跳转情况 4.訪问高峰时间段 server结构: 数据库表设计: 以上仅

js 利用iframe和location.hash跨域解决办法,java图片上传回调JS函数跨域

奶奶的:折腾了我二天,终于解决了!网上有很多例子. 但跟我的都不太一样,费话不多说了,上图   上代码: IE ,firefix,chrome 测试通过 js :这个主页面,部分代码, function submitUpload(id){ $("#imgSrc" + id +"").attr("alt", "图片上传中--"); var imgID = id; if(id>0){ imgID = 1; } var for

js跨域问题的解决

js提交请求给别的应用实例或者别的服务器,由于同源策略,存在js跨域的情况,我所知道两种处理方式: 1.jquery ajax+jsonp <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript"> $.ajax({ url:"", dataType:'jsonp', dat