Jsonp Solves the Cross-domain Problem of ajax

Keywords: JSP Javascript JQuery JSON

http://blog.csdn.net/saytime/article/details/51540876

1. Homology strategy

Browsers have an important concept - Same-Origin Policy. The so-called homology refers to the same domain name, protocol and port. Different source client scripts (javascript, ActionScript) can not read and write each other's resources without explicit authorization.

2,JSONP

JSONP (JSON with Padding) is a "usage mode" of JSON, which can be used to solve the problem of cross-domain data access in mainstream browsers. Owing to the Same-Origin strategy, web pages located in server1.example.com are generally unable to communicate with servers that are not server1.example.com, with the exception of script elements in HTML. With the open strategy of <script> elements, web pages can get JSON data dynamically generated from other sources, and this mode of use is called JSONP. The data captured with JSONP is not JSON, but arbitrary JavaScript, executed with a JavaScript literal translator rather than parsed with a JSON parser.

Two, practice

1. Simulate cross-domain requests

Two Tomcats with ports of 8080 and 8888, respectively, satisfy the condition of non-homology. If you send ajax from one port to get data from another port, you will surely report cross-domain requests.

There are two projects, jsonp (8080), other (8888), in the jsonp project index.jsp is as follows:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Insert title here</title>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript">
    function jsonp_fun(){
        $.ajax({
            url:'http://localhost:8888/other/index.jsp',
            type:'post',
            dataType:'text',
            success:function(data){
                console.log(data);
            }
        });
    }
</script>
</head>
<body>
    <input type="button" value="jsonp" onclick="jsonp_fun()"/>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Insert title here</title>
<script type="text/javascript" src="js/jquery.min.js"></script>
</head>
<body>
    other domain
</body>
</html>

In fact, what I saw above is just clicking on the button ajax in the jsonp page to get the data in the other page.

The results are as follows:

XMLHttpRequest cannot load http://localhost:8888/other/index.jsp. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.

The above hints refer to cross-domain problems, and the resources of 8888 domain can not be accessed from 8080 domain.

2. Use script tags to access other domain js files

Because the src of the < script > tag supports cross-domain requests. The most common is the application of CDN services, for example, in my project, if you want to use jquery, but there is no js file, it will take a long time to download, and the version is not known under the right, then you can Baidu search jquery cdn, I can find one at will, such as bootstrap cdn: http://www.bootcdn.cn/jquery/ There are many versions for you to choose. As long as you add them to the project, the biggest disadvantage is that if you don't have the Internet, you won't be able to introduce them.
2.1 Create a js/other.js file in the other root path as follows:

alert("this is other(8888) js");

2.2 In jsonp/index.jsp, add script tag and introduce other's js

<script type="text/javascript" src="http://localhost:8888/other/js/other.js"></script>

Enter http://localhost:8080/jsonp/index.jsp, and alert pops up immediately, indicating that the imported js file is automatically executed and the cross-domain request for js is successful.

2.3 Similarly, direct reference will immediately execute alert, then write functions in other.js, also can be invoked in jsonp/index.jsp, which is not demonstrated. This is mostly done in project development. Pages are separated from js/css.

2.4 Another point is that if there is a function in other.js that calls something in 8080 through ajax, it is also possible to call this function after it is introduced, but if the function Ajax in other.js calls something in 8888, after it is introduced, it is also cross-domain to call this function.

3. script implements cross-domain requests

3.1 Simple Analog Server Returns Data
Change jsonp/index.jsp to the following: Note that the location of other.js introduced here is after the function getResult, and if it precedes it, the function does not exist. The JS loading sequence starts from the top, which was not created before and could not be successfully invoked. Note that this refers to the imported JS file. If it is in the same JS file or the JS of the current page, it is not a problem to execute the call first and then write the function. But if the function in the imported JS file is invoked first and then the JS file is introduced, the function will be prompted not to exist.

<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript">
    function jsonp_fun(){
        $.ajax({
            url:'http://localhost:8888/other/index.jsp',
            type:'post',
            dataType:'text',
            success:function(data){
                console.log(data);
            }
        });
    }

    function getResult(data){
        alert(data.result);
    }
</script>
<script type="text/javascript" src="http://localhost:8888/other/js/other.js"></script>

Then other.js

getResult({"result":"this is other domain's data"});

That is to say, write the function on the jsonp/index.jsp page, and then introduce the js input parameters of other domains to call the function. The parameters here can be regarded as the data returned by the interface of other domain servers.

Refresh the page, of course.

Pop-up alert box, this is another domain's data

3.2 Analog Interface Access
See here, will you still not understand, what the above JS do, pass a dead data, what is the practical significance? In fact, the src of script can not only accept the address of js, but also the address of servlet, that is, the address of http interface. So next, I am too lazy to write servlet. Here, I still write jsp as the interface, and create another. jsp page in other project. The content is as follows:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
    String params = request.getParameter("params");
    out.println("ajax cross success,the server receive params :"+params);
%>

The content is simple, that is, to accept a params parameter and return the data to the caller.

We add in jsonp/index.jsp

<script type="text/javascript" src="http://localhost:8888/other/other.jsp?params=fromjsonp"></script>

See this address, you are not familiar with, unfamiliar proof that you use servlets foolish, jsp is also a servlet, the process is when the page loads, script tags will send requests, and then return data. So let's refresh the page and see the effect.

Uncaught SyntaxError: Unexpected identifier

Wrong report, as above, and then the code is wrong? No, if you click on the error, you will see that the request is also printed out, which is to prompt the error, indicating that the browser does not know this thing, in fact, script does not know it.

I don't understand yet, so you go to the page and add the following content, you can read the newspaper correctly!! Affirmative error

<script type="text/javascript">
    ajax cross success,the server receive params : jsonp_param
</script>

So js can't be parsed. Let's change our thinking. If we output a JSON string or a string that calls the current page function, it's similar to the one returned in 3.1.
getResult({"result":"this is other domain's data"});

So change it to something else. JSP

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
    String params = request.getParameter("params");
    //out.println("ajax cross success,the server receive params :"+params);
    out.println("getResult({'result':'"+params+"'})");
%>

Don't forget that we defined it in jsonp/index.jsp before, so after adding a reference, we still remember the sequence of getResult function and introduced function.

<script type="text/javascript">
    function getResult(data){
        alert(data.result);
    }
</script>
<script type="text/javascript" src="http://localhost:8888/other/other.jsp?params=fromjsonp"></script>

So far, most of the principles have been explained, and there is another problem. Here the server returns getResult (xxxx), where xxx can be treated as a value that has been processed by the interface and then inserted. But this getResult function name is the same as how the caller agrees with the other domain servers, and many companies do it themselves. Well, the developers of other companies call it. Does everyone go to the company to agree on the name of the calling function? How can it be possible, so someone came up with a solution, of course not me, but it's very simple, that is to say, the name of the callback function can not be passed along with the past, so the code is as follows:

<script type="text/javascript" src="http://localhost:8888/other/other.jsp?params=fromjsonp&callback=getResult"></script>


other.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
    String params = request.getParameter("params");
    String callback = request.getParameter("callback");
    // After a series of operations on the interface, data is obtained and returned to the caller.
    String data = "{'result':'"+params+"'}";
    out.println(callback + "("+data+")");
%>

The code is very simple, that is, passing the parameter name of a callback function, and then through a series of operations of the interface, the return data is stuffed into the callback function. The function at the calling end gets the data of the interface, which is similar to the succsss: function(data) in ajax, and then processing data. The success callback function here is equivalent to the getResult function above. Of course, you can also write elegantly, such as:

function CreateScript(src) {
        $("<script><//script>").attr("src", src).appendTo("body")
    }

    function jsonp_fun(){
         CreateScript("http://localhost:8888/other/other.jsp?params=fromjsonp&callback=getResult")
    }

4. JSONP of Jquery

So far, the principle of cross-domain requests has been clarified, but there is still a problem. I always think it is a little strange to use this method. If we use jquery, the call is very simple. In fact, the underlying implementation of jQuery is also spelled a script, and then specify src. As mentioned above, just jQuery is encapsulated, which is more elegant, not as bad as ajax calls. Many, so easy to remember, the code is as follows:

<script type="text/javascript">
    function getResult(data){
        alert("through jsonp,receive data from other domain : "+data.result);
    }

    function jsonp_fun(){
        $.ajax({
            url:'http://localhost:8888/other/other.jsp',
            type:'post',
            data:{'params':'fromjsonp'},
            dataType: "jsonp",
            jsonp: "callback",//The parameter name passed to the request handler or page to obtain the jsonp callback function name (generally default: callback)
            jsonpCallback:"getResult",//Custom jsonp callback function name, default to jQuery automatically generated random function name, can also not write this parameter, jQuery will automatically process data for you
            success: function(data){
            },
            error: function(){
                alert('fail');
            }
        });
    }
</script>
<body>
    <input type="button" value="jsonp" onclick="jsonp_fun()"/>
</body>

Here's jsonCallback, the callback function is set to getResult, then the code in the getResult function will be called first after returning, and then the code in the success function will be called. Normally, the getResult function is not defined. Similarly, the jsonCallback does not need to be set, so only the code in the success will be executed, just like the usual ajax.
So the practical usage is as follows:

function jsonp_fun(){
        $.ajax({
            url:'http://localhost:8888/other/other.jsp',
            type:'post',
            data:{'params':'fromjsonp'},
            dataType: "jsonp",
            jsonp: "callback",//The parameter name passed to the request handler or page to obtain the jsonp callback function name (generally default: callback)
            success: function(data){
                alert("through jsonp,receive data from other domain : "+data.result);
            },
            error: function(){
                alert('fail');
            }
        });
    }
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
    String params = request.getParameter("params");
    String callback = request.getParameter("callback");
    // After a series of operations on the interface, data is obtained and returned to the caller.
    String data = "{\"result\":\""+params+"\"}";
    out.println(callback + "("+data+")");
%> 

There is no jsonpCallback specified here. In fact, a function name is assembled at the bottom of jquery. Of course, the rules for generating functions are not studied.

Supplement:

1. The two technologies of Ajax and jsonp "look" very similar in the way of invocation, and the same purpose is to request a url, and then process the data returned by the server. Therefore, jquery and ext frameworks encapsulate jsonp as a form of ajax.

2. But ajax and jsonp are essentially different things. The core of ajax is to obtain non-home content through XmlHttpRequest, while the core of jsonp is to dynamically add < script > tags to invoke js scripts provided by the server.

3. So in fact, the difference between ajax and jsonp is not whether or not it is cross-domain. ajax can achieve cross-domain through server-side proxy, and jsonp itself does not exclude data acquisition in the same domain.

4. What's more, jsonp is a way or non-mandatory protocol. Like ajax, it doesn't have to use json format to transfer data. If you want, strings will do, but this is not conducive to using jsonp to provide public services.

In addition, I would like to add a final point:

In fact, the ajax cross-domain requests that Jsonp can solve are quite limited. CROS is recommended because the request of Jsonp can only be get. Although in the above demonstration, the type I set up is post, the request actually sent is get, so in case my request is post, what should I do? If the cross-domain ajax file is uploaded, what should I do?

Posted by jhenary on Sat, 18 May 2019 08:09:38 -0700