簡易的伺服器介面開發入門教程

奈何緣淺發表於2021-07-03

前沿

為了解決伺服器介面開發的問題,因此學習了關於Spring Boot的知識,然後再自己摸索總結後臺的開發經驗。所以這篇文章就是面向搞移動開發同時又想了解後臺開發的朋友,講解如何使用Spring Boot開發伺服器介面,然後在Android客戶端呼叫該介面進行資料請求。

Spring Boot特點

  • 建立獨立的Spring應用程式
  • 嵌入的Tomcat,無需部署WAR檔案
  • 簡化Maven配置
  • 自動配置Spring
  • 提供生產就緒型功能,如指標,健康檢查和外部配置
  • 絕對沒有程式碼生成並且對XML也沒有配置要求

基本要求

  • 熟悉Java語言
  • 對Java Web開發,Spring框架等有所瞭解。
  • 會Android開發,熟悉常用的網路請求框架。
  • 會使用IDEA,Android Studio開發工具。
  • 對網路知識有所瞭解。
  • 擁有JDK 1.8的開發環境。

服務端開發

現在開始進行服務端的介面開發,例子是當客戶端上傳的使用者的暱稱,年齡,性別,服務端返回相關的資料。介面設計如下:

介面地址:http:// ip address :8080/api/test

返回格式:json

請求方式:http get/post

請求示例:http:// ip address :8080/api/test?nickname=lake&age=20&gender=male

開始使用IDEA構建專案

一、啟動 IDEA,選擇"Create New Project"。

二、選擇"Spring Initializr",然後點選"Next"。

三、這一步填寫好 Group 和 Artifact ,然後點選"Next"。

四、勾選"Web"依賴,然後點選"Next"。

五、選擇好專案建立的相關目錄位置,然後點選"Finish"即可。

六、當進入到主介面可以看到 IDEA 自動生成相關的類和檔案。

  • /src/main/java/ 存放專案所有原始碼目錄
  • /src/main/resources/ 存放專案所有資原始檔以及配置檔案目錄
  • /src/test/ 存放測試程式碼目錄
  • pom.xml 配置檔案

七、先建立兩個Java bean,一個名稱為Info的實體類,用於接收客戶端傳輸的資料,一個名稱為Data的實體類,用於返回資料到客戶端。如下圖所示:

Info類完整程式碼如下:

package com.example.demo.entity;

public class Info {

    private String nickname;
    private String gender;
    private int age;

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public String getNickname() {
        return nickname;
    }

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

    public String getGender() {
        return gender;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }
}

Data類完整程式碼如下:

package com.example.demo.entity;

public class Data {

    private int code;
    private String result;

    public Data setCode(int code) {
        this.code = code;
        return this;
    }

    public int getCode() {
        return code;
    }

    public Data setResult(String result) {
        this.result = result;
        return this;
    }

    public String getResult() {
        return result;
    }
}

八、再建立一個名稱為ApiController的類,該類裡面分別有get,post,dealWith三個方法。get方法用於接收客戶端的GET請求,post方法用於接收客戶端的POST請求,dealWith方法用於處理客戶端傳輸來資料並返回處理的結果。

get方法會自動把客戶端傳來的表單的資料解析出來再儲存到info變數中,該方法的返回值是一個物件時,會預設將物件轉換為Json格式返回。post方法的傳入形參和返回的值的流程差不多,不同的是,POST請求時把請求體的資料解析出來再儲存到info變數中,而且請求體的資料格式必須為Json格式。

下面解釋一下ApiController類中的各個註解的作用。
@RestController:處理http請求,返回的資料格式為json格式。

@RequestMapping:配置url對映,可以作用於類和方法上。可以使用method指定GET,POST,DELETE,PUT四種標準請求,預設為GET請求。

@GetMapping:相當於@RequestMapping + RequestMethod.GET。用於GET請求。

@PostMapping:相當於@RequestMapping + RequestMethod.POST。用於POST請求。

使用這些註解配置Url對映,即可獲得你設計的API介面:http:// ip address :8080/api/test

ApiController類的完整的原始碼如下:

package com.example.demo.controller;

import com.example.demo.entity.Data;
import com.example.demo.entity.Info;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping(value = "/api")
public class ApiController {

    @GetMapping(value = "/test")
    public Data get(Info info) {
        return dealWith(info);
    }

    @PostMapping(value = "/test")
    public Data post(Info info) {
        return dealWith(info);
    }

    /**
     * @param info  使用者的資訊
     * @return      處理使用者資訊的結果
     */
    private Data dealWith(Info info) {
        String nickname = info.getNickname();
        String gender = info.getGender();
        int age = info.getAge();

        if (StringUtils.isEmpty(nickname)) {
            return new Data().setCode(-1).setResult("Nickname can not be blank.");
        }

        if (StringUtils.isEmpty(gender)) {
            return new Data().setCode(-2).setResult("Gender can not be blank.");
        }else if (gender.equals("male")) {
            gender = "boy";
        }else if (gender.equals("female")) {
            gender = "girl";
        }else {
            return new Data().setCode(-2).setResult("Gender is not legal");
        }

        if (age < 0) {
            return new Data().setCode(-3).setResult("Age can not be less than zero.");
        }

        String result = nickname + "'s age is " + age + " year old, " + "he(she) is a " + gender;
        return new Data().setCode(0).setResult(result);
    }
}

九、最後進行本地測試,點選啟動按鈕,當操控臺輸出“ Completed initialization...... ”的文字,說明該專案啟動成功了,然後開啟Microsoft Edge瀏覽器,位址列中輸入如下url並訪問。

http://localhost:8080/api/test?nickname=Lake&gender=male&age=20 

進行GET請求測試時,當請求成功後會看到瀏覽器會顯示一行Json文字,若請求時中填寫的引數不正確,伺服器返回的Json文字會說明錯誤的原因和對應的錯誤碼。

十、簡易的服務端介面開發完成了,把這個Spring Boot專案打包成一系列的jar包,然後上傳到一臺已安裝JDK 1.8的伺服器上,開啟命令列視窗,輸入命令,"java -jar xxx.jar",該專案即可啟動,若要後臺執行,輸入命令"nohup java -jar xxx.jar &",因篇幅有限,關於打包和部署到伺服器上的操作步驟,暫時不在本文詳寫了。你可能會問伺服器需要安裝Tomcat嗎?答案是:不需要,因為Spring Boot的專案已內建Tomcat,所以不必自己再安裝Tomcat了。伺服器開發流程到此完畢,接下來到客戶端開發。

客戶端開發

使用Android Studio開發Android專案,相信各位朋友都會熟練建立一個空的Android專案了,所以這裡不再詳述建立專案的步驟了。Android網路請求框架一般有 OkHttp,Retrofit 等,但是本次我使用的是 OkGo 這個網路請求框架,這框架我也是第一次用,先試試看。

一、編寫客戶端程式的佈局介面,因為介面的佈局比較簡單,所以文章中就不貼出佈局檔案的程式碼了,介面佈局如下圖所示:

二、在AndroidManifest.xml檔案中新增聯網的許可權,同時在app模組中的build.gradle檔案中新增OkGo的依賴。

AndroidManifest.xml檔案中新增聯網許可權的程式碼:

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

在build.gradle檔案中新增依賴的程式碼:

implementation 'com.lzy.net:okgo:3.0.4'

三、在MainActivity類中寫相關的程式碼,initView方法用於初始化佈局控制元件,request方法用於請求服務端的資料,RequestMethod介面用於選擇請求的方式(GET/POST),字串常量URL是服務端的介面地址。

MainActivity類的完整程式碼如下:

package com.example.demo;

import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.TextView;

import com.lzy.okgo.OkGo;
import com.lzy.okgo.callback.StringCallback;
import com.lzy.okgo.model.Response;

import java.util.Objects;

public class MainActivity extends AppCompatActivity {

    //伺服器的介面地址
    private final static String URL = "http://192.168.43.188:8080/api/test";

    /**
     * 請求的型別
     */
    private interface RequestMethod {
        int GET = 1;
        int POST = 2;
    }

    private EditText activity_main_nickname_et;
    private EditText activity_main_age_et;
    private RadioButton activity_main_male_rb;
    private RadioButton activity_main_female_rb;
    private TextView activity_main_log_tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    /**
     * 初始化佈局
     */
    private void initView() {
        activity_main_nickname_et = findViewById(R.id.activity_main_nickname_et);
        activity_main_age_et = findViewById(R.id.activity_main_age_et);
        activity_main_male_rb = findViewById(R.id.activity_main_male_rb);
        activity_main_female_rb = findViewById(R.id.activity_main_female_rb);
        activity_main_log_tv = findViewById(R.id.activity_main_log_tv);

        //軟鍵盤管理
        final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        final View view = getWindow().peekDecorView();
        Objects.requireNonNull(imm);

        findViewById(R.id.activity_main_get_btn)
                .setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
                        request(RequestMethod.GET);
                    }
                });

        findViewById(R.id.activity_main_post_btn)
                .setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
                        request(RequestMethod.POST);
                    }
                });
    }

    /**
     * 資料請求
     * @param requestType
     */
    private void request(final int requestType) {
        String nickname = activity_main_nickname_et.getText().toString();
        String age = activity_main_age_et.getText().toString();
        String gender = (activity_main_male_rb.isChecked()) ? "male" : "female";

        if (requestType == RequestMethod.GET) {
            OkGo.<String>get(URL)
                    .params("nickname", nickname)
                    .params("gender", gender)
                    .params("age", age)
                    .execute(new StringCallback() {
                        @Override
                        public void onSuccess(Response<String> response) {
                            String log = "GET請求:\n" + response.body();
                            activity_main_log_tv.setText(log);
                        }
                    });
        }else if (requestType == RequestMethod.POST) {
            OkGo.<String>post(URL)
                    .params("nickname", nickname)
                    .params("gender", gender)
                    .params("age", age)
                    .execute(new StringCallback() {
                        @Override
                        public void onSuccess(Response<String> response) {
                            String log = "POST請求:\n" + response.body();
                            activity_main_log_tv.setText(log);
                        }
                    });
        }
    }
}

四、客戶端的程式碼大概就是這樣,現在來測試一下客戶端與服務端的互動。本地測試,先保證電腦和手機連線了同一個網路並且電腦需要開啟8080埠,例如連線同一個WiFi,或者手機開熱點,電腦連線手機的熱點。 然後獲取電腦的IP地址,再把客戶端的程式碼中MainActivity類的URL常量的IP地址改為你電腦(伺服器)的IP地址。把IDEA中的服務端程式啟動,再把客戶端Demo安裝到手機上,就可以體驗到自己親手設計的介面了。效果圖如下:

結語

簡易伺服器介面開發入門教程已經寫完了,文章沒有涉及到資料庫的內容,還有和Spring Boot密切相關的maven也沒有提起,就是為了讓文章寫得更通俗易懂。這篇文章只能讓你瞭解一下簡單的介面開發過程,如果要學會使用Spring Boot開發實用的後臺介面,還是需要學好基礎知識,再找一本與Spring Boot相關的書籍進行學習。因為我的專業主要是搞網路相關,而不是搞開發的,搞開發是課餘時間的興趣愛好,所以文章有寫的不妥之處,望大家指正和諒解。

相關文章