利用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要導包

image_thumb,右鍵工程,Build Path—>Add External Archives會彈出文件瀏覽器,選擇要添加的額外的包

 

去自己的tomcat目錄下面找

image_thumb11,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文件,編譯我就不說了,

image_thumb2,class文件上級目錄web,將web文件夾復制,粘到哪里呢,先等等。

先要部署tomcat,在tomcat的webapps目錄下面新建一個文件夾testsendpack。里面添加子文件夾WEB-INF,然后再WEB-INF目錄下添加classes目錄,將剛要粘貼的web文件夾粘貼到這里。在classes文件夾同目錄下新建一個web.xml配置文件。

image_thumb3

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,

附上結果image_thumb1,好了,江山股份的行情查到了,字段啥意思,不想研究了,get請求和post請求的轉發都實現了,post不寫例子不要怪我,我找不着。。。

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

最后最后,有啥問題可以給我留言,歡迎吐槽相愛


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM