杰瑞科技汇

Android Java服务器如何搭建与交互?

目录

  1. 核心概念:客户端与服务器
  2. 通信协议:HTTP/HTTPS
  3. 数据交换格式:JSON
  4. Android 端实现 (Java)
    • 使用 HttpURLConnection (原生,推荐理解)
    • 使用第三方库 OkHttp (业界标准,强烈推荐)
  5. 服务器端实现 (以 Java 为例)
    • 框架选择:Spring Boot (最流行、最简单)
    • 创建一个简单的 RESTful API
  6. 完整示例:从 Android 发送请求到服务器并接收响应
  7. 关键注意事项与最佳实践

核心概念:客户端与服务器

  • 客户端:在你的场景中,Android App,它负责发起请求,并展示服务器返回的数据。
  • 服务器:一个持续运行在远程计算机(或云服务,如 AWS, 阿里云)上的程序,它负责接收客户端的请求,处理业务逻辑(比如查询数据库),然后将结果返回给客户端。

它们之间的通信就像寄信:

Android Java服务器如何搭建与交互?-图1
(图片来源网络,侵删)
  • 客户端:写好信(请求数据),贴上邮票(URL),投入邮筒(发送请求)。
  • 服务器:邮局(网络)收到信,打开阅读,处理信中的要求(比如查资料),然后写回信(响应数据),再寄回去。

通信协议:HTTP/HTTPS

客户端和服务器之间需要一套“语言”来沟通,这套语言就是 协议,最常用的是 HTTP (HyperText Transfer Protocol) 和其更安全的版本 HTTPS (HTTP Secure)

  • HTTP: 定义了客户端如何向服务器发送请求,以及服务器如何响应请求,请求和响应都包含方法
    • 常用方法:
      • GET: 从服务器获取数据(最常用)。
      • POST: 向服务器提交数据(登录、注册、上传文件)。
      • PUT: 更新服务器上的数据。
      • DELETE: 删除服务器上的数据。
  • HTTPS: 在 HTTP 的基础上加入了 SSL/TLS 加密层,所有数据传输都是加密的,可以防止数据被窃听或篡改。现代 App 开发,强烈要求必须使用 HTTPS。

数据交换格式:JSON

当客户端和服务器之间传输数据时,不能直接传递 Java 对象,需要一种通用的、轻量级的数据格式。

  • JSON (JavaScript Object Notation) 是目前最主流的选择,它易于人阅读和编写,也易于机器解析和生成。

JSON 示例: 一个表示用户信息的 JSON 对象:

{
  "userId": 101,
  "username": "zhangsan",
  "email": "zhangsan@example.com",
  "isActive": true
}

Android 端需要将 Java 对象(如 User 类)转换成 JSON 字符串发送,再将收到的 JSON 字符串解析成 Java 对象来使用。

Android Java服务器如何搭建与交互?-图2
(图片来源网络,侵删)

Android 端实现 (Java)

Android 从 Android 9 (API 28) 开始,默认禁止使用非 HTTPS 的网络请求,这是一个重要的安全特性。

使用 HttpURLConnection (原生)

这是 Java 标准库自带的类,不需要额外依赖,虽然代码稍显繁琐,但有助于理解网络请求的本质。

示例:使用 HttpURLConnection 发送 GET 请求

import android.os.Bundle;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class MainActivity extends AppCompatActivity {
    private TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textView);
        // 在子线程中执行网络请求,不能在主线程(UI线程)中操作
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 1. 创建 URL 对象
                    URL url = new URL("https://your-api-endpoint.com/users/101");
                    // 2. 打开连接
                    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET"); // 设置请求方法
                    connection.setConnectTimeout(15000); // 连接超时时间 (毫秒)
                    connection.setReadTimeout(15000);  // 读取超时时间 (毫秒)
                    // 3. 获取响应码
                    int responseCode = connection.getResponseCode();
                    System.out.println("Response Code: " + responseCode);
                    if (responseCode == HttpURLConnection.HTTP_OK) { // 200 表示成功
                        // 4. 读取输入流 (服务器返回的数据)
                        BufferedReader in = new BufferedReader(
                                new InputStreamReader(connection.getInputStream()));
                        String inputLine;
                        StringBuilder response = new StringBuilder();
                        while ((inputLine = in.readLine()) != null) {
                            response.append(inputLine);
                        }
                        in.close();
                        // 5. 处理响应数据 (这里直接显示)
                        // 注意:更新 UI 必须回到主线程
                        final String finalResponse = response.toString();
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                textView.setText(finalResponse);
                            }
                        });
                    } else {
                        System.out.println("GET request failed");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

缺点:

  • 代码冗长。
  • 处理 JSON 需要手动解析(如使用 org.json 库)。
  • 处理回调比较麻烦。

使用第三方库 OkHttp (业界标准)

OkHttp 是目前 Android 开发中最流行的网络请求库,它更高效、更易用,并内置了对 JSON 的支持(通过 OkHttp + Gson/Moshi/Jackson 组合)。

添加依赖

app/build.gradle 文件的 dependencies 代码块中添加:

// OkHttp
implementation("com.squareup.okhttp3:okhttp:4.12.0")
// Gson for JSON parsing
implementation("com.google.code.gson:gson:2.10.1")

添加网络权限

app/src/main/AndroidManifest.xml 中添加:

<uses-permission android:name="android.permission.INTERNET" />

从 Android 9 开始,如果目标是 API 28+,还需要在 application 标签中声明 usesCleartextTraffictrue(仅用于开发或特定场景,生产环境应强制使用 HTTPS):

<application
    ...
    android:usesCleartextTraffic="true"
    ...>
</application>

OkHttp GET 请求示例

import android.os.Bundle;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.google.gson.Gson;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
    private TextView textView;
    private OkHttpClient client = new OkHttpClient();
    private Gson gson = new Gson();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textView);
        // 定义一个数据类来匹配 JSON 结构
        class User {
            int userId;
            String username;
            String email;
            @Override
            public String toString() {
                return "User{" +
                        "userId=" + userId +
                        ", username='" + username + '\'' +
                        ", email='" + email + '\'' +
                        '}';
            }
        }
        // 创建请求
        Request request = new Request.Builder()
                .url("https://your-api-endpoint.com/users/101")
                .build();
        // 新建一个线程来执行请求 (OkHttp 本身是同步的)
        new Thread(() -> {
            try (Response response = client.newCall(request).execute()) {
                if (!response.isSuccessful()) {
                    throw new IOException("Unexpected code " + response);
                }
                // 获取响应体字符串
                String responseBody = response.body().string();
                // 使用 Gson 解析 JSON 字符串到 User 对象
                User user = gson.fromJson(responseBody, User.class);
                // 更新 UI
                runOnUiThread(() -> {
                    textView.setText(user.toString());
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }
}

服务器端实现 (以 Java 为例)

服务器端的选择非常多,如 Node.js (Express), Python (Django/Flask), Go, Java (Spring Boot, Jakarta EE) 等,这里我们使用 Spring Boot,因为它极大地简化了 Java Web 应用的创建和部署。

创建 Spring Boot 项目

你可以使用 Spring Initializr 网站,选择以下依赖:

  • Spring Web: 用于构建 RESTful API。
  • Spring DevTools: 用于热部署,方便开发。

下载项目并导入到你喜欢的 IDE (如 IntelliJ IDEA 或 Eclipse)。

创建一个简单的 Controller

src/main/java 下创建一个包,com.example.demo,然后在这个包里创建一个 UserController.java 文件。

package com.example.demo;
import org.springframework.web.bind.annotation.*;
// @RestController 告诉 Spring 这是一个 RESTful 控制器
@RestController
public class UserController {
    // @GetMapping 表示这是一个处理 GET 请求的方法
    // "/users/{id}" 是 URL 路径,{id} 是一个路径变量
    @GetMapping("/users/{id}")
    public User getUserById(@PathVariable int id) {
        // 在实际应用中,这里会去数据库查询用户
        // 这里我们直接返回一个模拟的用户对象
        System.out.println("Server received request for user with id: " + id);
        if (id == 101) {
            return new User(101, "zhangsan", "zhangsan@example.com");
        } else {
            // 如果找不到用户,返回一个 null 或抛出异常
            // Spring 会自动将其序列化为 JSON
            return null;
        }
    }
    // 定义一个 User 类,和 Android 端的结构一致
    static class User {
        private int userId;
        private String username;
        private String email;
        public User(int userId, String username, String email) {
            this.userId = userId;
            this.username = username;
            this.email = email;
        }
        // Getters and Setters (省略,实际项目中需要)
        // 为了方便打印,可以加上 toString()
        @Override
        public String toString() {
            return "User{" +
                    "userId=" + userId +
                    ", username='" + username + '\'' +
                    ", email='" + email + '\'' +
                    '}';
        }
    }
}

运行服务器

运行 DemoApplication.java (主启动类),默认情况下,服务器会在 http://localhost:8080 启动。

你可以用浏览器访问 http://localhost:8080/users/101,你应该会看到如下 JSON 响应:

{
  "userId": 101,
  "username": "zhangsan",
  "email": "zhangsan@example.com"
}

完整示例:从 Android 发送请求到服务器并接收响应

现在我们把两端连接起来。

  1. 确保服务器正在运行
  2. 修改 Android 代码中的 URL: 将 https://your-api-endpoint.com/users/101 改为 http://10.0.2.2:8080/users/101
    • 0.2.2 是 Android 模拟器访问本地电脑(宿主机)的特殊 IP 地址,如果你用真机测试,需要将电脑和手机连接到同一个 Wi-Fi 下,并使用电脑的局域网 IP (如 http://192.168.1.100:8080/...)。
  3. 运行 Android App

点击 App 后,它会向本地的 Spring Boot 服务器发送一个 GET 请求,服务器返回 JSON 数据,App 解析后显示在界面上。


关键注意事项与最佳实践

  1. 禁止在主线程进行网络请求 Android 的 UI 线程(主线程)不能被阻塞,网络请求是耗时操作,如果在主线程进行,会导致应用 ANR (Application Not Responding) 错误,必须使用子线程、AsyncTask (已废弃)、ExecutorServiceHandler 或现代的 Kotlin Coroutines / RxJava 来处理。

  2. 使用 HTTPS 永远不要在生产环境中使用 HTTP,使用 HTTPS 保护用户数据安全,你可以通过购买 SSL 证书或使用 Let's Encrypt 的免费证书来实现。

  3. 异步处理 OkHttp 本身是同步的,但通常我们会配合 Callback 来实现异步请求,避免手动管理线程,OkHttp 的 enqueue() 方法就是为此设计的。

    OkHttp 异步 GET 示例:

    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            // 请求失败,在子线程中处理
            e.printStackTrace();
        }
        @Override
        public void onResponse(Call call, Response response) throws IOException {
            // 请求成功,在子线程中处理响应
            if (response.isSuccessful()) {
                String responseBody = response.body().string();
                // ... 解析 JSON ...
                // ... runOnUiThread 更新 UI ...
            }
        }
    });
  4. 数据解析库 不要手动拼接或解析 JSON,使用成熟的库如 Gson (Google), Moshi (Square), JacksonKotlinx Serialization,它们能将 JSON 字符串自动映射到你的 Java/Kotlin 对象,大大减少出错的可能。

  5. 错误处理 始终处理可能发生的网络异常(如 IOException)和服务器返回的错误状态码(如 404 Not Found, 500 Internal Server Error)。

  6. 安全性

    • 不要在代码中硬编码 API 密钥或敏感信息,使用 local.properties 文件和 BuildConfig 来管理。
    • 对用户输入进行验证和清理,防止 SQL 注入或 XSS 攻击(这通常是服务器端的职责,但客户端也应做基本校验)。
  7. 现代 Android 开发趋势

    • Kotlin: 现代安卓开发的首选语言,提供了更简洁的语法和协程等强大特性。
    • MVVM (Model-View-ViewModel): 推荐的架构模式,它能更好地分离 UI 和业务逻辑,配合 Jetpack 的 ViewModelLiveData/StateFlow,能轻松处理网络请求和 UI 更新。
    • Retrofit: 一个基于 OkHttp 的类型安全的 HTTP 客户端,它将网络请求接口化,让你可以用像调用普通 Java 方法一样的方式发起网络请求,是目前 Android 网络请求的 事实标准,如果你要深入学习 OkHttp,下一步一定要学习 Retrofit。
分享:
扫描分享到社交APP
上一篇
下一篇