一、SpringBoot接口分类
springboot后端接口分为3种,@RequestBody类型,@RequestParam类型以及@RequestParam("file") MultipartFile file类型,下面对这三种类型分别说明。
1.@RequestBody类型
在postman中使用body发送JSON语句
对于该种类型的接口,代码如下
String json = "{\n" + //发送的json格式语句直接复制过来 "}"; OkHttpClient client = new OkHttpClient();//创建Http客户端 Request request = new Request.Builder() .url("http://***.***.**.***:xxxx/ / ")//***.***.**.***为本机IP,xxxx为端口,/ / 为访问的接口后缀 .post(RequestBody.create(MediaType.parse("application/json"),json)) .build();//创建Http请求 Response response = client.newCall(request).execute();//执行发送的指令 final String responseData = response.body().string();//获取返回的结果
若返回的结果为json格式,可用JSONObject或JSONArray进行转换,以JSONArray为例
JSONArray jsonArray = new JSONArray(responseData); for(int i = 0; i < jsonArray.length(); i++){//遍历 JSONObject jsonObject = jsonArray.getJSONObject(i); String result = jsonObject.getString("xxx");//xxx为JSON语句中的key值,get到的为value值 }
2.@RequestParam类型
在postman中改变value的同时会改变url
对于该种类型的接口,代码如下(注解请参考1.类型中注解)
FormBody.Builder params = new FormBody.Builder(); params.add("xx",**); params.add("xx",**);//xx为key,**为value OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("http://***.***.**.**:xxxx/ / ") .post(params.build()) .build(); Response response = client.newCall(request).execute(); final String responseData = response.body().string();
若返回的结果为json格式,同上
3.@RequestParam("file") MultipartFile file
用于上传文件、图片等,目前还未用到,会补全。
二、对OkHttp的使用
在以上代码的运行过程中遇到一些网络访问的问题,下面一一讲解
首先,使用OkHttp之前需导入包。在Build.gradle(app)中添加
在AndroidManifest.xml中添加网络访问权限
运行发现第一个报错:CLEARTEXT communication to xxxx not permitted by network security policy
查询资料发现
在Android P系统的设备上,如果应用使用的是非加密的明文流量的http网络请求,则会导致该应用无法进行网络请求,https则不会受影响,同样地,如果应用嵌套了webview,webview也只能使用https请求。
故有三种方法,我采用的第三种方法
1、APP改用https请求
2、targetSdkVersion 降到27以下
3、在 res 下新增一个 xml 目录,然后创建一个名为:network_security_config.xml 文件(名字自定) ,内容如下,大概意思就是允许开启http请求
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="true" /> </network-security-config>
然后在APP的AndroidManifest.xml文件下的application标签增加以下属性
<application ... android:networkSecurityConfig="@xml/network_security_config" ... />
运行发现第二个报错(阿巴阿巴现在调不出来了)
在AndroidManifest.xml中添加
然后卸载app,重新运行
附:如果出现fail to connect to报错,检查一下ip地址是否有问题
三、android studio的多任务执行
android studio中发送post请求需放在子线程中,因为请求可能失败,为了不影响主线程,故建立子线程。
假设我点击按钮然后发送post请求,那么代码如下
public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { //请求代码 } }).start(); }
如果在线程中需要改变UI,需要在子线程中调用函数,将改变UI的代码扔回给主线程执行,不然会报错
假设我需要在子线程中show一个Toast
Toast.makeText(UserLoginActivity.this,"登录成功",Toast.LENGTH_SHORT).show();
有三种方式可以把请求回调给主线程
1.Activity.runOnUiThread(Runnable)
新增toast就是用这个函数
runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(UserLoginActivity.this,"登录成功",Toast.LENGTH_SHORT).show(); } });
2.View.post(Runnable)
改变UI部件则使用这个函数
假设我
TextView username = findViewById(R.id.username);
那么当我需要在线程中改变username的内容时,就把setText放到以下函数中
username.post(new Runnable() { public void run() { username.setText("用户名"); } });
3.View.postDelayed(Runnable,long)
与2相同,Delay了long的时间延迟响应
四、对post请求的说明
建立post请求可能存在通信不成功的情况,故在android studio中需把请求放在try函数中,结合上文改变UI的说明,代码如下
try { //post请求 }catch (Exception e){ e.printStackTrace(); runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(UserLoginActivity.this,"网络错误",Toast.LENGTH_SHORT).show(); } }); }
示例代码登录(方法1)
username = findViewById(R.id.username); password = findViewById(R.id.password); loginButton = findViewById(R.id.button); loginButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { usernameLogin = username.getText().toString(); passwordLogin = password.getText().toString(); new Thread(new Runnable() { @Override public void run() { try { String json = "{\n" + " \"storePhone\": \"" + usernameLogin + "\",\n" + " \"storePwd\": \"" + passwordLogin + "\"\n" + "}"; OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("http://192.168.43.178:23333/store/login") .post(RequestBody.create(MediaType.parse("application/json"),json)) .build(); Response response = client.newCall(request).execute(); final String responseData = response.body().string(); if(responseData.equals("true")){ runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(ShopLoginActivity.this,"登录成功",Toast.LENGTH_SHORT).show(); } }); } else if(responseData.equals("false")){ runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(ShopLoginActivity.this,"用户名或密码错误",Toast.LENGTH_SHORT).show(); } }); } }catch (Exception e){ e.printStackTrace(); runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(ShopLoginActivity.this,"网络错误",Toast.LENGTH_SHORT).show(); } }); } } }).start(); } });
运行结果