Android(或者Java)通過HttpUrlConnection向SpringMVC請求資料(資料繫結)

來源:互聯網
上載者:User

標籤:over   process   malformed   sonar   javase   utils   number   value   需要   

問題描述

    當我們使用SpringMVC作為服務端的架構時,有時不僅僅要應對web前端(jsp、javascript、Jquery等)的訪問請求,有時還可能需要響應Android和JavaSE(案頭應用)這些用戶端的請求,因此,除了web使用form表單或者ajax作為用戶端擷取Controller響應之外,純Java語言向SpringMVC的Controller提供參數和請求結果也是必須要實現的。web前端使用form和ajax來擷取Controller響應在本篇部落格暫不深究,本篇博課著力於實現純Java用戶端來實現請求Controller並擷取響應。(如果不想看下面的方法探索,可以直接跳到第三部分)

方法探索

    確定了需要解決的問題之後,我開始搜尋相關的部落格和問答,發現這種問題相關解決方案不是很多,找了很多部落格都是牛頭不對馬嘴,但是還是有一些對解決問題有協助的內容,之後又翻了很久的書,對這個問題的解決方案有了基本的認識。
    看網上說的行之有效方法是使用HttpClient來實現這個功能,不過需要匯入HttpClient和HttpCore兩個jar包,當時研究了一下覺得可行。但是在實際操作過程中,在向Android(IDE:Android Studio)build.gradle裡面匯入上述兩個jar包的依賴後,同步的時候Android Studio給出了兩個警告,大意是HttpClient已經到期云云,然後我又專門去查了一個HttpClient這個東西和Android之間的關係,發現Android6.0以及之後的版本放棄了對HttpClient的支援,強行匯入jar包也不行。(據說有人用了非常麻煩的方法匯入成功過 = =)那好嘞,不讓用算了,那就不用唄。看參考書《瘋狂Android講義》對HttpClient還那麼推崇,也是有點醉。具體不讓用的原因就不再深究了,接下來就研究使用HttpUrlConnection來解決上述問題吧。
    在使用HttpURLConnection的過程中代碼實現照著套路來問題不大,遇到的問題是SpringMVC的Controller怎麼接收資料,接收的資料格式是什嗎?我應該傳什麼類型的資料?
    Controller怎麼接收資料這個問題經過前段時間的學習我已經有個大概的認識,SpringMVC的Controller工作原理就是用戶端向 項目地址+Controller前面的value值 這個url發出請求,這個請求會帶有一些參數,而SpringMVC會將請求攜帶的參數轉換為Controller對應value下面的方法的參數,然後在這個方法進行相關的操作再返回用戶端一些參數,至於返回的結果就有幾種可能了。如果上面沒有@ResponseBody注釋,返回的資料有可能是jsp頁面的名字,則web會跳轉到對應的jsp頁面如果是ModelAndView也會跳轉到對應的頁面而如果加上@ResponseBody,那麼返回的就是json類型的資料了,用戶端會接收到Controller返回的參數。那麼,明白了springmvc的工作原理,那麼怎麼使用HttpUrlConnection來訪問Controller就大概清楚了:我們就把請求地址拼接好,然後把攜帶的資料發送過去就可以等著拿到Controller返回的資料了。那麼第二個問題就來了,請求的地址清楚了,攜帶的資料應該是什麼格式的呢?
    剛開始我以為和傳回值一樣是Json格式的索引值對形式,比如說使用者登入的userName和userPassword,(Controller的參數形式為 doLogin(String userName,String userPassword))開始我以為應該發送json格式資料,可是服務端不鳥我,沒有獲得參數。後來我又試了jsonArray形式也不行,試了map的索引值對形式不行。我就疑惑了到底是什麼形式的。最後找了半天看了ajax發出同樣請求時的http報文結構才知道了資料格式是什麼樣子的。是這樣的:

中間是一個&串連了兩個參數,索引值中間是=,好吧,終於明白了。當然這是Controller參數為兩個單獨的String值的時候的類型,有一種更好的辦法是直接把Controller的參數設定為一個,然後在Controller裡面解析Json資料,這樣其實更方便一點,以後還更容易做加密工作,不過目前改起來太麻煩就不改了吧,現在弄明白了controller是兩個參數的時候是這種結構的。至於其它的list,bean以及json類型這裡就不探究了,因為我看到很多別的博主都講了怎麼轉了。廢話了這麼多,下面放代碼。

解決問題

    SpringMVC對應Controller代碼(result單詞拼錯了,懶得改咯):

@RequestMapping(value="/doLogin",method=RequestMethod.POST)    @ResponseBody    public Map<String,Object> doLogin(String userName,String userPassword,HttpSession httpSession){        String resoult="fail";        User user = userService.getUser(userName);        UserDetail userDetail = userDetailService.getUserDetail(userName);        if(user!=null){            if(Objects.equals(userDetail.getUserDetailPassword(), userPassword)){                httpSession.setAttribute("currentUser",user);                resoult = "success";            }            else{                resoult = "wrong";            }        }        else{            resoult = "unexist";        }        Map<String, Object> resoults = new HashMap<String,Object>();        resoults.put("resoult", resoult);        return resoults;    }

    Android端或者java端寫的一個HttpPostUtils工具類

package cn.justwithme.withme.Utils;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;/** * Created by 桐木木 on 2017/2/8. * 發送Http請求,擷取Controller返回的資料 * */public class HttpPostUtils {    public static String doPostRequest(String path,Object content){        PrintWriter out = null;        BufferedReader in = null;        String resoult = "";        try {            System.out.println("要發送的資訊是:"+content);            /*拼接url,Android這裡需要換上遠程地址,因為Android端沒辦法訪問localhost,java的話本地tomcat啟動並執行話倒是無妨*/            String address = http://localhost:8080/WithMe/"+path;            URL url = new URL(address);            HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();            //這兩個參數必須加            httpURLConnection.setDoInput(true);            httpURLConnection.setDoOutput(true);            //設定逾時時間            httpURLConnection.setReadTimeout(10*1000);            httpURLConnection.setConnectTimeout(10*1000);            httpURLConnection.setRequestMethod("POST");            httpURLConnection.connect();            out = new PrintWriter(httpURLConnection.getOutputStream());            //在輸出資料流中寫入參數            out.print(content);            out.flush();            if(httpURLConnection.getResponseCode() == 200){                in = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream(),"utf-8"));                String line;                while((line=in.readLine())!=null){                    resoult+=line;                }            }            System.out.println("伺服器返回的結果是:"+resoult);            return resoult;        } catch (MalformedURLException e) {            System.out.println("URL異常");            e.printStackTrace();        } catch (IOException e) {            System.out.println("IO異常");            e.printStackTrace();        }finally {            try{                if(out!=null)                    out.close();                if(in!=null)                    in.close();            }catch (IOException e) {                e.printStackTrace();            }        }        return null;    }}

    工具類寫好之後我們分別在Android端和Java端進行一些測試,(在我的服務端我已經註冊過14121047的前提下,你如果只是測試把服務端查詢資料庫校正密碼改成字串匹配就成了)。
Android
LoginActivity.java

package cn.justwithme.withme.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.Button;import android.widget.EditText;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import java.util.HashMap;import java.util.Map;import cn.justwithme.withme.R;import cn.justwithme.withme.Utils.HttpPostUtils;public class LoginActivity extends AppCompatActivity {    private String result;    private Handler mHanlder = new Handler() {        @Override        public void handleMessage(Message message) {            result = (String) message.obj;            JSONObject resultJson = JSON.parseObject(result);            String finalResult = resultJson.getString("resoult");            System.out.println("結果是:"+finalResult);            if(finalResult.equals("success")){                System.out.println("登陸成功");            }            else                System.out.println("使用者名稱或密碼錯誤");        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_login);        final EditText userNameInput = (EditText)findViewById(R.id.userName);        final EditText passwordInput = (EditText)findViewById(R.id.password);        Button login = (Button)findViewById(R.id.login);        login.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                String userName = userNameInput.getText().toString();                String userPassword = passwordInput.getText().toString();                final Map<String,Object> userInfo = new HashMap<String,Object>();                userInfo.put("userName",userName);                userInfo.put("userPassword",userPassword);//                UserLogin userInfo = new UserLogin();//                userInfo.setUserName(userName);//                userInfo.setUserPassword(userPassword);                final String user = "userName="+userName+"&userPassword="+userPassword;                if(userName!= null && !userName.equals("") && userPassword!=null && !userPassword.equals("")){                    /*這裡需要留意的是httpPostUtils請求在Android裡面不能放在主線程裡面,必須建立一個子線程,然後通過Hanlder把子線程的值傳過來更新UI(因為子線程不能直接更改UI)*/                    new Thread() {                        public void run() {                            String response = HttpPostUtils.doPostRequest("doLogin",user);                            Message message = Message.obtain();                            message.obj = response;                            mHanlder.sendMessage(message);                        }                    }.start();                }                else{                    System.out.println("使用者名稱密碼不可為空");                }            }        });    }}

    好吧,這是非常簡陋的代碼,畢竟Android用戶端才剛剛開始寫,activity_login.xml就不放了,兩個輸入框一個按鈕而已,可以再下面查看輸出結果來判斷功能是否實現:

    下面是Java的測試代碼,用的工具類和Android用的一樣的,

package httpPost;public class test {    public static void main(String[] args){    String test = "userName=14121047&userPassword=14121047";    String ans = HttpPostUtils.doPostRequest("doLogin", test);    System.out.println("伺服器返回的資料為:"+ans);    }}

    測試結果為:

要發送的資訊是:userName=14121047&userPassword=14121047伺服器返回的結果是:{"resoult":"success"}伺服器返回的資料為:{"resoult":"success"}
結束語

    當然,我這裡示範的知識一個非常簡單的android和java向springmvc發送請求的例子,但是,既然中間的道理和方法明白了,那之後無論是什麼格式的資料都不是很難了。Json資料的那隻用一個參數就好了咯,兩個參數都傳了一個參數不是很容易嗎?要傳bean的先把Bean轉json到服務端再把json轉bean就好了咯。233。。。(這裡只是討論一下兩個參數怎麼傳,並不是不想用json。)
    好好學習,天天向上,加油!

Android(或者Java)通過HttpUrlConnection向SpringMVC請求資料(資料繫結)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.