前沿

为了解决服务器接口开发的问题,因此学习了关于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"。

简易的服务器接口开发入门教程-LMLPHP

二、选择"Spring Initializr",然后点击"Next"。

简易的服务器接口开发入门教程-LMLPHP

三、这一步填写好 Group 和 Artifact ,然后点击"Next"。

简易的服务器接口开发入门教程-LMLPHP

四、勾选"Web"依赖,然后点击"Next"。

简易的服务器接口开发入门教程-LMLPHP

五、选择好项目创建的相关目录位置,然后点击"Finish"即可。

简易的服务器接口开发入门教程-LMLPHP

六、当进入到主界面可以看到 IDEA 自动生成相关的类和文件。

  • /src/main/java/ 存放项目所有源代码目录
  • /src/main/resources/ 存放项目所有资源文件以及配置文件目录
  • /src/test/ 存放测试代码目录
  • pom.xml 配置文件

简易的服务器接口开发入门教程-LMLPHP

七、先创建两个Java bean,一个名称为Info的实体类,用于接收客户端传输的数据,一个名称为Data的实体类,用于返回数据到客户端。如下图所示:

简易的服务器接口开发入门教程-LMLPHP

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

简易的服务器接口开发入门教程-LMLPHP

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文本会说明错误的原因和对应的错误码。

简易的服务器接口开发入门教程-LMLPHP

简易的服务器接口开发入门教程-LMLPHP

简易的服务器接口开发入门教程-LMLPHP

十、简易的服务端接口开发完成了,把这个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 这个网络请求框架,这框架我也是第一次用,先试试看。

一、编写客户端程序的布局界面,因为界面的布局比较简单,所以文章中就不贴出布局文件的代码了,界面布局如下图所示:

简易的服务器接口开发入门教程-LMLPHP

二、在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安装到手机上,就可以体验到自己亲手设计的接口了。效果图如下:

简易的服务器接口开发入门教程-LMLPHP

结语

简易服务器接口开发入门教程已经写完了,文章没有涉及到数据库的内容,还有和Spring Boot密切相关的maven也没有提起,就是为了让文章写得更通俗易懂。这篇文章只能让你了解一下简单的接口开发过程,如果要学会使用Spring Boot开发实用的后台接口,还是需要学好基础知识,再找一本与Spring Boot相关的书籍进行学习。因为我的专业主要是搞网络相关,而不是搞开发的,搞开发是课余时间的兴趣爱好,所以文章有写的不妥之处,望大家指正和谅解。

07-03 15:54