前言
經過打勞工的不懈努力,終于敲出了多層封裝的安卓前後端分離項目的雛形。
前期準備
開發環境:
(1)jdk1.8
(2)Android stdio 4.1 (包含自帶的Gradle)
(3)IntelliJ IDEA 2020.2.3 x64 (包含配置好的的Maven)
項目架構及依賴
安卓用了OKHttp
後端用了springboot+mybatis-plus
安卓前端的gradle依賴
dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'com.squareup.okhttp3:okhttp:4.2.2'
implementation 'com.google.code.gson:gson:2.7'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
springboot項目的maven依賴
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
</dependencies>
後端搭建
1.通過mybatis-plus模闆生成
根據資料庫中的表user建立
生成mvc代碼:Generate.java(要放在包的最外層,與初始的springboot啟動類平級的位置,例如:放在com.example下)
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.ArrayList;
import java.util.List;
public class Generate {
public static void main(String[] args) {
//建立generator對象
AutoGenerator autoGenerator = new AutoGenerator();
//資料源
DataSourceConfig dataSourceConfig = new DataSourceConfig();
dataSourceConfig.setDbType(DbType.MYSQL);
dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
dataSourceConfig.setUsername("root");
dataSourceConfig.setPassword("123456");
dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/dbName");
autoGenerator.setDataSource(dataSourceConfig);
//全局配置
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setOutputDir(System.getProperty("user.dir")+"/src/main/java");
globalConfig.setAuthor("admin");
globalConfig.setOpen(false);
globalConfig.setServiceName("%sService");
autoGenerator.setGlobalConfig(globalConfig);
//包資訊
PackageConfig packageConfig = new PackageConfig();
packageConfig.setParent("com.example");//包名
packageConfig.setEntity("entity");
packageConfig.setMapper("mapper");
packageConfig.setService("service");
packageConfig.setServiceImpl("service.impl");
packageConfig.setController("controller");
autoGenerator.setPackageInfo(packageConfig);
//政策配置
StrategyConfig strategyConfig = new StrategyConfig();
String tablesName="user";
strategyConfig.setInclude(tablesName);
strategyConfig.setNaming(NamingStrategy.underline_to_camel);
strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
strategyConfig.setEntityLombokModel(true);
autoGenerator.setStrategy(strategyConfig);
//運作
autoGenerator.execute();
}
}
生成結果:(沒有util)
建立一個結果類Result,用來裝結果集(第三個參數裝json字元串)
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class Result {
private int code;
private String msg;
private String result;
public void setSuccess(String msg, String result){
this.code=200;
this.msg="success-"+msg;
this.result=result;
}
public void setInfo(String msg, String result){
this.code=400;
this.msg="warning-"+msg;
this.result=result;
}
}
配置檔案application改成yml字尾
application.yml内容為:
spring:
datasource:
url: jdbc:mysql://localhost:3306/db_name
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath:com/example/mapper/xml/*.xml
server:
port: 8081
控制層:
import com.campus.book.entity.Result;
import com.campus.book.entity.User;
import com.campus.book.service.UserService;
import com.campus.book.util.JsonBean;
import com.google.gson.Gson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.io.Serializable;
@RestController
@RequestMapping("//user")
public class UserController {
@Autowired
private UserService userService;
Gson gson= new GsonBuilder().serializeNulls().create();
Result result=new Result();
@PostMapping("/insert")
public Result insert(String json){
User user=null;
try{
user=gson.fromJson(json,User.class);
}catch (Exception e){
e.printStackTrace();
}
if(userService.getById(user.getId())!=null){//id重複!
result.setInfo("該賬号已注冊!",null);
}else{
userService.save(user);
result.setSuccess("注冊成功!",gson.toJson(user));
}
return result;
}
@DeleteMapping("/delete/{id}")
public Result delete(@PathVariable("id") Serializable id) {
result.setSuccess("删除成功!", null);
boolean is=this.userService.removeById(id);
if(is){
}else{
result.setInfo("删除失敗!",null);
}
return result;
}
@PutMapping("/update")
public Result update(String json) {
result.setInfo("更改失敗!",json);
User user=null;
try{
user=gson.fromJson(json,User.class);
if(this.userService.updateById(user)){
result.setSuccess("更改成功!",gson.toJson(userService.getById(user.getId())));
}
}catch (Exception e){
e.printStackTrace();
}
return result;
}
@GetMapping("/list")
public Result list() {
result.setSuccess("查詢成功!", gson.toJson(this.userService.list()));
return result;
}
@GetMapping("/line/{id}")
public Result getUser(@PathVariable("id") Serializable id){
User user=userService.getById(id);
if(user!=null){//存在
result.setSuccess("查詢成功!",gson.toJson(user));
}else{//不存在
result.setSuccess("沒有找到相關資料!",null);
}
return result;
}
@PostMapping("/login")
public Result login(String json){
User user=null;
User user1=null;
try{
user=gson.fromJson(json,User.class);
}catch (Exception e){
e.printStackTrace();
}
user1=userService.getById(user.getId());
if(user1!=null){//存在該賬戶
if(user1.getPassword().equals(user.getPassword())){//密碼正确
result.setSuccess("登入成功!",gson.toJson(user1));
}else{//密碼錯誤
result.setInfo("使用者名或密碼錯誤!",null);
}
}else{//不存在該賬戶
result.setInfo("該賬号不存在!",null);
}
return result;
}
}
springboot 的啟動類
添加如下注解(定位mapper的位置)
@SpringBootApplication
@MapperScan("com.example.mapper")
好了,後端初步搭建完成。
下面就是安卓前端,
安卓前端(直接上代碼,有些冗長,跳着看吧)
首先是okHttp的工具類(沒有檔案上傳下載下傳)
用到了一個接口
import java.io.IOException;
import okhttp3.Response;
public interface OkHttpCallback {
void onFailure(IOException e);
void onSuccess(Response response);
}
import android.util.Log;
import com.campus.book.util.http.OkHttpCallback;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
/**
* @since 2021-04-28
* 異步請求會放到線程池中執行
* 同步請求會阻塞目前線程
* 一般使用異步請求居多
*/
public class OKHttpUtil {
private static Request request = null;
private static int TimeOut = 120;
//單例擷取ohttp3對象
private static OkHttpClient client = null;
/**
* OkHttpClient的構造方法,通過線程鎖的方式構造
* @return OkHttpClient對象
*/
private static synchronized OkHttpClient getInstance() {
if (client == null) {
client = new OkHttpClient.Builder()
.readTimeout(TimeOut, TimeUnit.SECONDS)
.connectTimeout(TimeOut, TimeUnit.SECONDS)
.writeTimeout(TimeOut, TimeUnit.SECONDS)
.build();
}
return client;
}
/**
* callback接口
* 異步請求時使用
*/
static class MyCallBack implements Callback {
private OkHttpCallback okHttpCallBack;
public MyCallBack(OkHttpCallback okHttpCallBack) {
this.okHttpCallBack = okHttpCallBack;
}
@Override
public void onFailure(Call call, IOException e) {
okHttpCallBack.onFailure(e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
okHttpCallBack.onSuccess(response);
}
}
/**
* 獲得同步get請求對象Response
* @param url
* @return Response
*/
private static Response doSyncGet(String url) {
//建立OkHttpClient對象
client = getInstance();
request = new Request.Builder()
.url(url)//請求連結
.build();//建立Request對象
try {
//擷取Response對象
Response response = client.newCall(request).execute();
return response;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* 獲得異步get請求對象
* @param url 請求位址
* @param callback 實作callback接口
*/
private static void doAsyncGet(String url,OkHttpCallback callback) {
MyCallBack myCallback = new MyCallBack(callback);
client = getInstance();
request = new Request.Builder()
.url(url)
.get()
.build();
client.newCall(request).enqueue(myCallback);
}
/**
* 同步get請求
* 例如:請求的最終位址為:http://127.0.0.1:8081/user/getUser/123
* @param url 基本請求位址 例子: http://127.0.0.1:8081
* @param args 請求的參數 args[]=new String[]{"user","getUser","123"}
* @return String
*/
public static String getSyncRequest(String url,String... args) {
List<String> result=new ArrayList<>();//傳回值
String address=url;
for(int i=0;i<args.length;i++){
address=address+"/"+args[i];
}
final String finalAddress = address;
new Thread(new Runnable() {
@Override
public void run() {
Response finalResponse = doSyncGet(finalAddress);
String res = null;
try {
Log.d("同步get請求請求位址:",finalAddress);
if (finalResponse.isSuccessful()) {//請求成功
ResponseBody body = finalResponse.body();//拿到響應體
res = body.string();
result.add(res);
Log.d("HttpUtil", "同步get請求成功!");
Log.d("請求對象:", res);
} else {
Log.d("HttpUtil", "同步get請求失敗!");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
/**因為函數傳回是立刻執行的,而result要在請求完成之後才能獲得
* 是以需要等待result獲得傳回值之後再執行return*/
while(result.size()==0){
try {
TimeUnit.MILLISECONDS.sleep(10);//等待xx毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return result.get(0);
}
/**
* 異步get請求
* 例如:請求的最終位址為:http://127.0.0.1:8081/user/getUser/123
* @param url 基本請求位址 例子: http://127.0.0.1:8081
* @param args 請求的參數 args[]=new String[]{"user","getUser","123"}
* @return String
*/
public static String getAsyncRequest(String url,String... args){
List<String> result=new ArrayList<>();
String address=url;
for(int i=0;i<args.length;i++){
address=address+"/"+args[i];
}
final String finalAddress = address;
doAsyncGet(finalAddress, new OkHttpCallback() {
@Override
public void onFailure(IOException e) {
Log.d("異步get請求位址:",finalAddress);
Log.d("HttpUtil", "異步get請求失敗!");
}
@Override
public void onSuccess(Response response) {
Log.d("異步get請求位址:",finalAddress);
String res = null;
try {
res = response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
result.add(res);
Log.d("HttpUtil", "異步get請求成功!");
Log.d("請求對象:", res);
}
});
/**因為函數傳回是立刻執行的,而result要在請求完成之後才能獲得
* 是以需要等待result獲得傳回值之後再執行return*/
while(result.size()==0){
try {
TimeUnit.MILLISECONDS.sleep(10);//等待xx毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return result.get(0);
}
/**
* 同步post請求
* 例如:請求的最終位址為:http://127.0.0.1:8081/user/getUser/123
* @param url 基本請求位址 例子: http://127.0.0.1:8081
* @param json 送出的json字元串
* @param args 請求的參數 args[]=new String[]{"user","getUser","123"}
* @return
*/
public static String postSyncRequest(String url,String json,String... args){
List<String> result=new ArrayList<>();
String address=url;
for(int i=0;i<args.length;i++){
address=address+"/"+args[i];
}
final String finalAddress = address;
new Thread(new Runnable() {
@Override
public void run() {
client=getInstance();
Log.d("同步post請求位址:",finalAddress);
FormBody.Builder formBody = new FormBody.Builder();
formBody.add("json",json);
request=new Request.Builder()
.url(finalAddress)
.post(formBody.build())
.addHeader("device-platform", "android")
.build();
try{
Response response=client.newCall(request).execute();
String res=response.body().string();
result.add(res);
Log.d("HttpUtil", "同步post請求成功!");
Log.d("請求對象:", res);
}catch (Exception e){
Log.d("HttpUtil", "同步post請求失敗!");
e.printStackTrace();
}
}
}).start();
/**因為函數傳回是立刻執行的,而result要在請求完成之後才能獲得
* 是以需要等待result獲得傳回值之後再執行return*/
while(result.size()==0){
try {
TimeUnit.MILLISECONDS.sleep(10);//等待xx毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return result.get(0);
}
/**
* 異步post請求
* 例如:請求的最終位址為:http://127.0.0.1:8081/user/getUser/123
* @param url 基本請求位址 例子: http://127.0.0.1:8081
* @param json 送出的json字元串
* @param args 請求的參數 args[]=new String[]{"user","getUser","123"}
* @return
*/
public static String postAsyncRequest(String url,String json,String... args){
List<String> result=new ArrayList<>();
String address=url;
for(int i=0;i<args.length;i++){
address=address+"/"+args[i];
}
final String finalAddress = address;
Log.d("異步post請求位址:",finalAddress);
client=getInstance();
FormBody.Builder formBody = new FormBody.Builder();//建立表單請求體
formBody.add("json",json);
request = new Request.Builder()
.url(finalAddress)
.post(formBody.build())
.addHeader("device-platform", "android")
.build();
Call call=client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
new Thread(new Runnable() {
@Override
public void run() {
Log.d("HttpUtil","異步post請求失敗!");
}
}).start();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
new Thread(new Runnable() {
@Override
public void run() {
String res = null;
try {
res = response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
result.add(res);
Log.d("HttpUtil","異步post請求成功!");
Log.d("請求對象",res);
}
}).start();
}
});
/**因為函數傳回是立刻執行的,而result要在請求完成之後才能獲得
* 是以需要等待result獲得傳回值之後再執行return*/
while(result.size()==0){
try {
TimeUnit.MILLISECONDS.sleep(10);//等待xx毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return result.get(0);
}
/**
* 異步delete請求
* 例如:請求的最終位址為:http://127.0.0.1:8081/user/getUser/123
* @param url 基本請求位址 例子: http://127.0.0.1:8081
* @param json 送出的json字元串
* @param args 請求的參數 args[]=new String[]{"user","getUser","123"}
* @return
*/
public static String deleteAsyncRequest(String url,String json,String... args){
List<String> result=new ArrayList<>();
String address=url;
for(int i=0;i<args.length;i++){
address=address+"/"+args[i];
}
final String finalAddress = address;
Log.d("異步delete請求位址:",finalAddress);
client=getInstance();
FormBody.Builder formBody = new FormBody.Builder();//建立表單請求體
formBody.add("json",json);
request = new Request.Builder()
.url(finalAddress)
.delete(formBody.build())
.addHeader("device-platform", "android")
.build();
Call call=client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
new Thread(new Runnable() {
@Override
public void run() {
Log.d("HttpUtil","異步delete請求失敗!");
}
}).start();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
new Thread(new Runnable() {
@Override
public void run() {
String res = null;
try {
res = response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
result.add(res);
Log.d("HttpUtil","異步delete請求成功!");
Log.d("請求對象",res);
}
}).start();
}
});
/**因為函數傳回是立刻執行的,而result要在請求完成之後才能獲得
* 是以需要等待result獲得傳回值之後再執行return*/
while(result.size()==0){
try {
TimeUnit.MILLISECONDS.sleep(10);//等待xx毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return result.get(0);
}
/**
* 異步put請求
* 例如:請求的最終位址為:http://127.0.0.1:8081/user/getUser/123
* @param url 基本請求位址 例子: http://127.0.0.1:8081
* @param json 送出的json字元串
* @param args 請求的參數 args[]=new String[]{"user","getUser","123"}
* @return
*/
public static String putAsyncRequest(String url,String json,String... args){
List<String> result=new ArrayList<>();
String address=url;
for(int i=0;i<args.length;i++){
address=address+"/"+args[i];
}
final String finalAddress = address;
Log.d("異步put請求位址:",finalAddress);
client=getInstance();
FormBody.Builder formBody = new FormBody.Builder();//建立表單請求體
formBody.add("json",json);
request = new Request.Builder()
.url(finalAddress)
.put(formBody.build())
.addHeader("device-platform", "android")
.build();
Call call=client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
new Thread(new Runnable() {
@Override
public void run() {
Log.d("HttpUtil","異步put請求失敗!");
}
}).start();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
new Thread(new Runnable() {
@Override
public void run() {
String res = null;
try {
res = response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
result.add(res);
Log.d("HttpUtil","異步put請求成功!");
Log.d("請求對象",res);
}
}).start();
}
});
/**因為函數傳回是立刻執行的,而result要在請求完成之後才能獲得
* 是以需要等待result獲得傳回值之後再執行return*/
while(result.size()==0){
try {
TimeUnit.MILLISECONDS.sleep(10);//等待xx毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return result.get(0);
}
}
封裝的httpUrl
public class HttpUrl {
//通過cmd指令行輸入 ipconfig IpV4位址即為本地的ip位址
final private static String baseUrl="http://192.168.xx.1:8081";
public static String getBaseUrl() {
return baseUrl;
}
}
封裝的位址參數
import java.io.Serializable;
public class HttpAddress {
private static String[] args;
final private static String userAddress="user";
public static String user(){
return userAddress;
}
/**
*
* @param address 首位址 例如:“user”
* @param method 位址中的方法 例如: “insert”
* @return
*/
public static String[] get(String address,String method){
switch (method){
case "login":args=getLoginAddress();
break;
case "insert":args=getInsertAddress(address);
break;
case "update":args=getUpdateAddress(address);
break;
case "list":args=getListAddress(address);
break;
}
return args;
}
/**
*采用方法重載,分别處理兩種情況,帶id和不帶id
* @param address 首位址 例如:“user”
* @param method 位址中的方法 例如: “delete”
* @param id id則為相應參數 delete後的id參數
* @return
*/
public static String[] get(String address,String method,Serializable id){
switch (method){
case "delete":args=getDeleteAddress(address,id);
break;
case "line":args=getLineAddress(address,id);
break;
}
return args;
}
private static String[] getLoginAddress(){
args=new String[]{userAddress,"login"};
return args;
}
private static String[] getInsertAddress(String address){
args=new String[]{address,"insert"};
return args;
}
private static String[] getDeleteAddress(String address, Serializable id){
args=new String[]{address,"delete", String.valueOf(id)};
return args;
}
private static String[] getUpdateAddress(String address){
args=new String[]{address,"update"};
return args;
}
private static String[] getLineAddress(String address, Serializable id){
args=new String[]{address,"line", String.valueOf(id)};
return args;
}
private static String[] getListAddress(String address){
args=new String[]{address,"list"};
return args;
}
}
在安卓端模拟出一個資料庫增删改查的工具類(實際上是通過發起請求實作的)
import com.campus.book.entity.Result;
import com.campus.book.util.gson.JsonBean;
import com.campus.book.util.gson.JsonUtil;
import com.campus.book.util.http.HttpUrl;
import com.campus.book.util.http.OKHttpUtil;
import com.google.gson.Gson;
import java.util.ArrayList;
import java.util.List;
/**
* 增删改查
* 增:post請求
* 删:delete請求
* 改:put請求
* 查:get請求
*/
public class DatabaseUtil {
final private static String baseUrl= HttpUrl.getBaseUrl();
//final private static Gson gson= JsonBean.getGson();
final private static Gson gson=new GsonBuilder().serializeNulls().create()
private static String jsonForm=null;
private static String jsonResult=null;
private static Result result=null;
/**
* 通過異步post請求
* 資料庫插入操作----增 --例子
* @param bean bean對象 user
* @param args 請求位址參數 {"user","insert"}
* @return
*/
public static Result insert(Object bean,String... args){
try{
jsonForm=gson.toJson(bean);
}catch (Exception e){
e.printStackTrace();
return null;
}
jsonResult= OKHttpUtil.postAsyncRequest(baseUrl,jsonForm,args);
if(jsonResult==null){//請求失敗
result.setInfo("發送請求錯誤!",null);
}else{//請求成功
result=gson.fromJson(jsonResult,Result.class);
if(result.getCode()==200){//插入失敗
}else if(result.getCode()==400){//插入成功
}
}
return result;
}
/**
* 通過異步delete請求
* 資料庫插入操作----通過 id 删除
* @param args 請求位址參數 args[]={"user","delete",id}
* @return
*/
public static Result deleteById(String... args){
jsonForm= "";
jsonResult= OKHttpUtil.deleteAsyncRequest(baseUrl,jsonForm,args);
if(jsonResult==null){//請求失敗
result.setInfo("發送請求錯誤!",null);;
}else{//請求成功
result=gson.fromJson(jsonResult,Result.class);
if(result.getCode()==200){//删除失敗
}else if(result.getCode()==400){//删除成功
}
}
return result;
}
/**
* 通過異步put請求
* 資料庫更新操作----通過 id 改 ---例子
* @param bean user
* @param args {"user","update"}
* @return
*/
public static Result updateById(Object bean,String... args){
try{
jsonForm=gson.toJson(bean);
}catch (Exception e){
e.printStackTrace();
return null;
}
jsonResult= OKHttpUtil.putAsyncRequest(baseUrl,jsonForm,args);
if(jsonResult==null){//請求失敗
result.setInfo("發送請求錯誤!",null);;
}else{//請求成功
result=gson.fromJson(jsonResult,Result.class);
if(result.getCode()==200){//插入失敗
}else if(result.getCode()==400){//插入成功
}
}
return result;
}
/**
* 資料庫操作--查詢,查詢單個對象
* @param args 請求位址參數 {"user","line",id}
* @return
*/
public static Result selectLineById(String... args){
jsonResult= OKHttpUtil.getAsyncRequest(baseUrl,args);
if(jsonResult==null){//請求失敗
result.setMsg("發送請求錯誤!");
}else{//請求成功
result=gson.fromJson(jsonResult,Result.class);
if(result.getCode()==200){//查詢失敗
}else if(result.getCode()==400){//查詢成功
}
}
return result;
}
/**
* 資料庫操作--查詢,查詢對象集合
* @param args 請求位址參數 {"user","list"}
* @return
*/
public static Result selectList(String... args){
jsonResult= OKHttpUtil.getAsyncRequest(baseUrl,args);
if(jsonResult==null){//請求失敗
result.setMsg("發送請求錯誤!");
}else{//請求成功
result=gson.fromJson(jsonResult,Result.class);
if(result.getCode()==200){//查詢失敗
}else if(result.getCode()==400){//查詢成功
}
}
return result;
}
/**
* 通過Result擷取bean對象
* @param result
* @param cls
* @param <T>
* @return
*/
public static <T> T getEntity(Result result,Class<?> cls){
T entity=null;
try {
entity= (T) gson.fromJson(result.getResult(),cls);
} catch (Exception e) {
e.printStackTrace();
}
return entity;
}
/**
* 通過Result擷取對象集合
* @param result
* @return
*/
public static List getList(Result result){
List list=new ArrayList<>();
try{
list= (List) gson.fromJson(result.getResult(), List.class);
}catch (Exception e){
e.printStackTrace();
}
return list;
}
}
同樣,安卓端也有一個結果集類
public class Result {
private int code;
private String msg;
private String result;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
@Override
public String toString() {
return "Result{" +
"code=" + code +
", msg='" + msg + '\'' +
", result='" + result + '\'' +
'}';
}
public void setSuccess(String msg, String result){
this.code=200;
this.msg="success-"+msg;
this.result=result;
}
public void setInfo(String msg, String result){
this.code=400;
this.msg="warning-"+msg;
this.result=result;
}
}
下面是使用執行個體:activity
MainActvity.java
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.campus.book.entity.Result;
import com.campus.book.entity.User;
import com.campus.book.util.DatabaseUtil;
import com.campus.book.util.http.HttpAddress;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private TextView tv=null;
EditText userId = null;
EditText pwd = null ;
Button login=null;
private Button registry=null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_layout);
setTitle("登入");
login = (Button)findViewById(R.id.login);
registry = (Button)findViewById(R.id.registry);
userId=(EditText) findViewById(R.id.userId);
pwd=findViewById(R.id.pwd);
login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String id = userId.getText().toString();
String password=pwd.getText().toString();
User user1=new User(id,password);
/**插入單條資料
Result result=DatabaseUtil.insert(user1,
HttpAddress.get(HttpAddress.user(),"insert"));
System.out.println(result.toString());
// */
/**删除單個資料
Result result=DatabaseUtil.deleteById(HttpAddress.
get(HttpAddress.user(),"delete",id));
System.out.println(result.toString());
// */
/**更新單個資料
Result result=DatabaseUtil.updateById(user1,
HttpAddress.get(HttpAddress.user(),"update"));
System.out.println(result.toString());
//*/
/**查單行資料
Result result=DatabaseUtil.selectLineById(
HttpAddress.get(HttpAddress.user(),"line",id));
User user=DatabaseUtil.getEntity(result,User.class);
System.out.println(user.toString());
// */
/**查清單資料
Result result =DatabaseUtil.selectList(
HttpAddress.get(HttpAddress.user(),"list"));
List<User> users=DatabaseUtil.getList(result);
System.out.println(users.toString());
// */
}
});
registry.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
}
});
}
}
布局檔案:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tv"
android:text="内容:"/>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/mainBg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/login" />
<[email protected]/login改成相應的背景圖,放在drawable檔案夾下-->
<TableLayout
android:layout_width="350dp"
android:layout_height="match_parent"
android:stretchColumns="*"
android:layout_marginBottom="150sp"
android:layout_gravity="center" >
<TableRow android:layout_height="match_parent">
<EditText
android:id="@+id/userId"
android:layout_column="0"
android:layout_span="2"
android:hint="請輸入手機号"
android:textColorHint="#FFFFFF"
android:textColor="#FFFFFF"
android:textCursorDrawable="@drawable/cursor_color"
android:textSize="15sp" />
</TableRow>
<TableRow android:layout_height="match_parent" >
<EditText
android:id="@+id/pwd"
android:inputType="textPassword"
android:layout_column="0"
android:layout_span="2"
android:hint="請輸入密碼"
android:textColorHint="#FFFFFF"
android:textColor="#FFFFFF"
android:textCursorDrawable="@drawable/cursor_color"
android:textSize="15sp" />
</TableRow>
<TableRow android:layout_height="match_parent">
<Button
android:id="@+id/login"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:background="#000000"
android:layout_margin="8dp"
android:textSize="15sp"
android:text="登入" />
<Button
android:id="@+id/registry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:background="#000000"
android:layout_margin="8dp"
android:textSize="15sp"
android:text="注冊" />
</TableRow>
</TableLayout>
</FrameLayout>
</LinearLayout>
cursor_color.xml也放在drawable檔案夾下
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<size android:width="2dp" />
<solid android:color="@android:color/black" />
</shape>
忘記說了,要在Android中使用okHttp,要在AndroidMainfest.xml中添加網絡權限
檔案圖檔如下:
添加内容如下(附加了sd卡的權限,視情況需要使用的可以一起加上去):
<!-- 聯網權限 -->
<uses-permission android:name="android.permission.INTERNET" />
<!--接入wifi狀态-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- SD卡權限 -->
<!--讀-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!--寫-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--在sdcard中建立/删除檔案的權限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" tools:ignore="ProtectedPermissions" />
<!--android:usesCleartextTraffic="true"表示使用明文通信-->
另外,不加這個可能會在發起請求時報錯:需要使用明文通信。具體原因未查明。
前端也搭建完成。
運作方式
先運作後端springboot的啟動類,後運作安卓端,可通過修改MainActivity中被注釋的操作内容來嘗試實際效果。都是“登入”按鈕觸發的哦!
類似于這樣的:
本次内容有些長,能看到這的都點贊、留言、收藏支援一下吧!
源碼都在上面了,如有問題在留言吧!