直接在服務器與客戶端之間傳輸對象

客戶端與服務器之間傳輸對象


1、前言

1.網絡編程的使用十分普遍,且至關重要,一個有用的Android 程序必定涉及數據對象的傳輸處理。java

2.本文將以實例分析一個用戶對象是怎樣在網絡中傳輸的。android

具體實現以前,大體分析一下其過程原理:web

原理以下:編程

User對象 --> json 數據 --> 手機客戶端 --> 服務器 --> json 數據 --> User對象json


3.所用平臺:緩存

android studio ,MyEclipse 也可用 eclipsebash


2、原理分析詳解

其實就是在 android 客戶端實例化一個用戶 User 對象,或者說將一個已有的用戶對象 user 封裝成 json 數據;而後經過 http 協議從手機客戶端發送到服務器端;服務器接收到請求,並處理json 數據,解析 json 數據;其實很簡單;而後將解析後的數據給一個實例化的 用戶User u = new User(),經過 u.setter() 方法將數據設置爲對象的數據,這樣對象在客戶端與服務器之間的傳輸就成功了。服務器


如下文件名、類名、變量或者包名等名字的建立可自定義

3、Android 客戶端代碼實現

接下來上代碼實現該過程:網絡

首先android 客戶端:app

1.工程結構:


2.文件代碼

    (1)佈局文件 activity_main.xml

也不寫多複雜的界面了,就簡單的添加一個Button 按鈕控件,點擊按鈕觸發發送對象事件便可,

因此 layout 下 activity_main.xml 文件代碼很簡單:

代碼以下:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:tools="http://schemas.android.com/tools" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:paddingBottom="@dimen/activity_vertical_margin" 
android:paddingLeft="@dimen/activity_horizontal_margin" 
android:paddingRight="@dimen/activity_horizontal_margin" 
android:paddingTop="@dimen/activity_vertical_margin" 
android:background="@drawable/back" 
tools:context="rfeng.pers.winsock.MainActivity">  
  <Button android:id="@+id/button" 
                android:layout_width="80dp" 
                android:layout_height="30dp" 
                android:background="#fff" 
                android:gravity="center" 
                android:text="send" 
                android:textSize="15dp"/> 
</RelativeLayout>
複製代碼

    (2)用戶對象類 User.java

在新建model 包下建一個類 User :該類得實現 Serializable 接口,不然不能在網絡中傳輸

package rfeng.pers.model;

import java.io.Serializable;


/**  * Created by Administrator on 2016/8/14 0014.  */ 
public class User implements Serializable {
    private String username;
    private String gender;
    private int age;

  
    public User(String username, String gender, int age) {
        this.username = username;
        this.gender = gender;
        this.age = age;
    }

    public User() {
        super();
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
複製代碼

    (3)對象數據相關操做處理類TransObjectToWeb.java

在新建包 web 下建一個類 TransObjectToWeb:實現對象的封裝,與http 協議請求的發送及與服務器的交互

package rfeng.pers.web;  
  
import android.util.Log;  
  
import org.json.JSONArray;  
import org.json.JSONObject;  
  
import java.io.BufferedReader;  
import java.io.BufferedWriter;  
import java.io.InputStream;  
import java.io.InputStreamReader;  
import java.io.OutputStream;  
import java.io.OutputStreamWriter;  
import java.net.HttpURLConnection;  
import java.net.URL;  
  
import rfeng.pers.model.User;  
  
/** 
 * Created by Administrator on 2016/8/14 0014. 
 */  
public class TransObjectToWeb {  
    /** 
     * 建立方法:將對象傳輸到 web 端 
     * @param user 
     */  
    private Boolean flag = false;  
    public boolean sendToWeb(User user){  
  
        try {  
            // (1)服務器的訪問路徑  
            Log.i("TAG","建立鏈接");  
            URL url = new URL("http://192.168.0.28:8080/WinSockWeb/WinSockForAndroid");  
            HttpURLConnection http = (HttpURLConnection) url.openConnection();  //實例化鏈接對象  
            http.setDoInput(true);  //可讀可寫  
            http.setDoOutput(true);  
            http.setUseCaches(false);  //不容許使用緩存  
            http.setRequestMethod("POST");  //設置傳輸方式爲 post  
            http.connect();  //建立鏈接  
            Log.i("TAG","建立鏈接成功");  
  
            // (2)數據寫入流發送至服務器  
            OutputStream os = http.getOutputStream();  
            OutputStreamWriter osw = new OutputStreamWriter(os);  
            BufferedWriter bw = new BufferedWriter(osw);  
            Log.i("TAG","建立json 對象");  
            JSONArray jsonArray = new JSONArray();  //建立 json 對象  
            JSONObject jsonObject = new JSONObject();  
  
            jsonObject.put("username",user.getUsername());  //寫入對象數據  
            jsonObject.put("gender",user.getGender());  
            jsonObject.put("age",user.getAge());  
            jsonArray.put(jsonObject);  
            bw.write(jsonArray.toString());  
            bw.flush();  
  
            // (3)數據讀取流接收數據  
            InputStream is = http.getInputStream();  
            InputStreamReader isr = new InputStreamReader(is);  
            BufferedReader br = new BufferedReader(isr);  
  
            String result = br.readLine();  //獲取web 端返回的數據  
            if (result.equals("succeed")) {  //若是返回數據爲 succeed 處理成功,不然失敗  
                flag = true;  
            }  
  
            // (4)關閉相關流  
            if (os != null)  os.close();  
            if (osw != null)  osw.close();  
            if (is != null)  is.close();  
            if (isr != null)  isr.close();  
            if (br != null)  br.close();  
            if (bw != null)  bw.close();  
  
        } catch (Exception e){e.printStackTrace();}  
        return flag;  
    }  
}  
複製代碼

    (4)MainActivity.java

在MainActivity 中寫代碼相關操做:實現點擊事件的觸發,調用 TransObjectToWeb 中傳輸對象的方法,實現對象傳輸

package rfeng.pers.winsock;  
  
import android.os.Looper;  
import android.support.v7.app.AppCompatActivity;  
import android.os.Bundle;  
import android.view.View;  
import android.widget.Button;  
import android.widget.Toast;  
  
import rfeng.pers.model.User;  
import rfeng.pers.web.TransObjectToWeb;  
  
public class MainActivity extends AppCompatActivity {  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
  
        Button btn = (Button)findViewById(R.id.button);  
        btn.setOnClickListener(new View.OnClickListener() {  
            @Override  
            public void onClick(View v) {  
  
                new Thread(new Runnable() {  
                    @Override  
                    public void run() {  
  
  
                        User user = new User("張小凡","男",19);  //實例化用於測試的傳輸對象  
                        TransObjectToWeb toWeb = new TransObjectToWeb();//實例化該類對象,調用其傳輸對象方法  
                        boolean flag = toWeb.sendToWeb(user);  
                        if (flag) {  
                            Looper.prepare();  
                            Toast.makeText(MainActivity.this, "對象傳輸成功!", Toast.LENGTH_SHORT).show();  
                            Looper.loop();  
                        } else {  
                            Looper.prepare();  
                            Toast.makeText(MainActivity.this, "網絡繁忙!", Toast.LENGTH_SHORT).show();  
                            Looper.loop();  
                        }  
                    }  
                }).start();  
  
            }  
        });  
  
    }  
}  
複製代碼

AndroidManifest.xml 配置文件:

<?xml version="1.0" encoding="utf-8"?>  
<manifest xmlns:android="http://schemas.android.com/apk/res/android"  
    package="rfeng.pers.winsock">  
    <!--  
    網絡權限:部分不添加該權限也可實現網絡鏈接,但建議添加該權限  
    -->  
    <uses-permission android:name="android.permission.INTERNET" />  
    <application  
        android:allowBackup="true"  
        android:icon="@mipmap/ic_launcher"  
        android:label="@string/app_name"  
        android:supportsRtl="true"  
        android:theme="@style/AppTheme">  
        <activity android:name=".MainActivity">  
            <intent-filter>  
                <action android:name="android.intent.action.MAIN" />  
  
                <category android:name="android.intent.category.LAUNCHER" />  
            </intent-filter>  
        </activity>  
    </application>  
  
</manifest>  
複製代碼

4、服務器端

而後是服務器端:

新建web project 工程命名爲:WinSockWeb;

導入json 相關包;

(1)用戶對象類User.java

在新建包model 下:建立類 User ,與android 客戶端對應,由於傳輸的對象有相同的屬性,方法;

package cn.hpu.edu.model;  
  
public class User {  
    private String username;  
    private String gender;  
    private int age;  
    public String getUsername() {  
        return username;  
    }  
    public void setUsername(String username) {  
        this.username = username;  
    }  
    public String getGender() {  
        return gender;  
    }  
    public void setGender(String gender) {  
        this.gender = gender;  
    }  
    public int getAge() {  
        return age;  
    }  
    public void setAge(int age) {  
        this.age = age;  
    }  
  
}  
複製代碼

(2)servlet 文件

在新建包android 下新建 servlet 文件命名爲:WinSockForAndroid

實現接收客戶端的請求,並作出相關處理後,返回結果給客戶端:

package cn.hpu.edu.android;  
  
import java.io.BufferedReader;  
import java.io.BufferedWriter;  
import java.io.IOException;  
import java.io.InputStream;  
import java.io.InputStreamReader;  
import java.io.OutputStream;  
import java.io.OutputStreamWriter;  
  
import javax.servlet.ServletException;  
import javax.servlet.http.HttpServlet;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
  
  
import org.json.JSONArray;  
import org.json.JSONObject;  
  
import cn.hpu.edu.model.User;  
  
public class WinSockForAndroid extends HttpServlet {  
  
    private static final long serialVersionUID = 1L;  
      
    public void doGet(HttpServletRequest request, HttpServletResponse response)  
            throws ServletException, IOException {  
        this.doPost(request, response);  
      
          
    }  
  
    public void doPost(HttpServletRequest request, HttpServletResponse response)  
            throws ServletException, IOException {  
        request.setCharacterEncoding("utf-8");  //設置編碼方式  
        response.setCharacterEncoding("utf-8");  
        System.out.println("接收到請求");  
          
        User user = null;  //初始化接收的傳輸對象爲空  
          
        //(1) 獲取android 請求,對傳輸對象的數據進行處理  
        InputStream is = request.getInputStream();  
        InputStreamReader isr = new InputStreamReader(is,"utf-8");  
        BufferedReader br = new BufferedReader(isr);  
        String userjson = br.readLine();  
          
        System.out.println("userjson:"+userjson.toString());  //輸出 json 格式數據  
          
        try {  
            JSONArray userarr = new JSONArray(userjson);  
            JSONObject userobj = userarr.getJSONObject(0);  
              
            user = new User();  //實例化 user 對象,不然報空指針異常  
            user.setUsername(userobj.getString("username"));  
            user.setGender(userobj.getString("gender"));  
            user.setAge(userobj.getInt("age"));  
              
            System.out.println("該傳輸對象:\n"  
                    +"姓名: "+user.getUsername()  
                    +"\n性別: "+user.getGender()  
                    +"\n年齡: "+user.getAge());  
              
            // (2)返回結果,成功或失敗  
            OutputStream os = response.getOutputStream();  
            OutputStreamWriter osw = new OutputStreamWriter(os,"utf-8");  
            BufferedWriter bw = new BufferedWriter(osw);  
              
              
            if (user != null)   
                bw.write("succeed");  
            else   
                bw.write("error");  
              
            bw.flush();  
            if (os != null)  os.close();  
            if (osw != null)  osw.close();  
            if (is != null)  is.close();  
            if (isr != null)  isr.close();  
            if (br != null)  br.close();  
            if (bw != null)  bw.close();  
  
        } catch (Exception e){e.printStackTrace();}  
    }  
      
  
}  
複製代碼

    (5)配置文件

web.xml 配置:

在 Myeclipse平臺下自動生成,在 eclipse通常本身寫

<?xml version="1.0" encoding="UTF-8"?>  
<web-app version="3.0"  
    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_0.xsd">  
  <servlet>  
    <description>This is the description of my J2EE component</description>  
    <display-name>This is the display name of my J2EE component</display-name>  
    <servlet-name>WinSockForAndroid</servlet-name>  
    <servlet-class>cn.hpu.edu.android.WinSockForAndroid</servlet-class>  
  </servlet>  
  
  
  <servlet-mapping>  
    <servlet-name>WinSockForAndroid</servlet-name>  
    <url-pattern>/WinSockForAndroid</url-pattern>  
  </servlet-mapping>  
  
</web-app>  
複製代碼

5、實現效果

讓咱們看一下運行結果:

實例化對象


而後調用方法傳輸該用戶對象

手機客戶端點擊 send 發送按鈕,出發事件,調用相關方法封裝對象發送至服務器,接收到請求後解析數據,對數據進行處理,後返回相關結果。


客戶端運行界面,沒多加修飾,僅一個Button 控件


點擊按鈕,發送對象,提示成功



成功狀況下:服務器端控制檯輸出以下:



android studio 控制檯也打印日誌:http 協議請求服務器成功



6、總結

注意:

1.此工程可用,需注意,主要是經過 json 數據的封裝與解析來處理對象在網絡傳輸中的數據類型,須導入 json 相關包,纔可;

2.配置文件也需注意;

3.同時 android 端需注意用戶 User 對象必須實現接口 Serializable ;

4.其中重點json 數據的封裝與解析其實也很簡單,在 TransObjectToWeb 和 WinSockForAndroid 中都涉及到此問題。

相關文章
相關標籤/搜索