導包
在build.gradle文件中添加代碼
dependencies {
compile 'com.squareup.okhttp3:okhttp:3.6.0'
}
使用方法##
定義一些後面將統一用到的變量
public static String targetIp = "http://192.168.191.1:8080/" +
"okhttp/" +
"login.action?" +
"username=99&password=110";//get方法參數放在請求鏈接中
public static String mBaseUrl="http://192.168.191.1:8080/okhttp/";//post方法使用的請求ip
private TextView textView;
private ImageView imageView;
private OkHttpClient okHttpClient;
- doGet()(用戶名,密碼什麼的)
public void doGet(View view)throws IOException{
//1.構造request
Request.Builder builder=new Request.Builder();//構造者設計模式
Request request=builder.
get().
url(targetIp).//自定義的targetIp變量
build();
//3.將request封裝成call
Call call=okHttpClient.newCall(request);
//4.執行call
//Response response=call.execute();同步方法
/*
異步方法
* */
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
L.e("onFailure:" + e.getMessage());//自定義打印日誌類就不說了
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
L.e("onResponse:");
final String res = response.body().string();
L.e(res);
runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText(res);//將返回內容顯示在TextView中
}
});//UI線程 因爲callback在子線程中,更新UI需要在主線程(UI線程)中
}
});
}
後臺相應接收前臺doGet()方法
public String login() throws IOException{
System.out.println(username+","+password);
System.out.println(ServletActionContext.getRequest().getSession().toString());
HttpServletResponse response=ServletActionContext.getResponse();
PrintWriter writer =response.getWriter();
writer.write("login success!");//返回數據給前臺“login success!”
writer.flush();
return null;
}
2.doPost()上傳表單數據
public void doPost(View view){
//2.構造request
//2.1 構造FormBody(post)表單
FormBody formbody=new FormBody.Builder()//建post方法發送信息的表單
.add("username","wu")
.add("password","2017")
.build();
//2.1構造request
Request.Builder builder=new Request.Builder();
Request request=builder.
post(formbody).
url(mBaseUrl+"login.action").
build();
//3.將request封裝成call
Call call=okHttpClient.newCall(request);
//4.執行call
//Response response=call.execute();同步方法
/*
異步方法
* */
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
L.e("onFailure:" + e.getMessage());
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
L.e("onResponse:");
final String res = response.body().string();
L.e(res);
runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText(res);
}
});
}
});
}
大家是不是發現了什麼
第3步:將request封裝成call
第4步:執行call在doGet()方法和doPost()方法中都有出現,有一句話,程序猿都是懶的,咱能封裝就儘量要封裝
於是我們可以把3.4步封裝成函數executeRequest(Request request)
private void executeRequest(Request request) {
//3.將request封裝成call
Call call=okHttpClient.newCall(request);
//4.執行call
//Response response=call.execute();同步方法
/*
異步方法
* */
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
L.e("onFailure:" + e.getMessage());
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
L.e("onResponse:");
final String res = response.body().string();
L.e(res);
runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText(res);
}
});
}
});
}
之前出現這段代碼的地方可以直接替換,傳入一個Request類型變量即可
3.doPostString()上傳字符串,例如json格式字符串
public void doPostString(View view){
RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain;chaset=utf-8"),
"{username:wuzi,password:1996}");
Request.Builder builder=new Request.Builder();
Request request=builder
post(requestBody ).
url(mBaseUrl+"postString.action").
build();
//3.將request封裝成call
//4.執行call
executeRequest(request);
}
後臺相應接收代碼
public String postString() throws IOException{
HttpServletRequest request=ServletActionContext.getRequest();
ServletInputStream isInputStream=request.getInputStream();
StringBuilder sbBuilder=new StringBuilder();
int len=0;
byte[] buf =new byte[1024];
while((len=isInputStream.read(buf))!=-1){
sbBuilder.append(new String(buf,0,len));
}
System.out.println(sbBuilder.toString());
isInputStream.close();
return null;
}
4.doPostFile()上傳文件
public void doPostFile(View view){
File file =new File(Environment.getExternalStorageDirectory(),"banner2.jpg");//獲得手機目錄第一層
if (!file.exists()){
L.e(file.getAbsolutePath()+" not exist!");
return;
}
RequestBody requestBody = RequestBody.create(MediaType.parse("application/octec-steam"),//不知道發送的數據MIME格式可用這字符串代替
file);
Request.Builder builder=new Request.Builder();
Request request=builder.
post(requestBody).
url(mBaseUrl+"postFile.action").
build();
executeRequest(request);
}
後臺相應接收
public String postFile() throws IOException{
HttpServletRequest request=ServletActionContext.getRequest();
ServletInputStream isInputStream=request.getInputStream();
String dirString=ServletActionContext.getServletContext().getRealPath("/file2");
File file=new File(dirString,"banner2.jpg");
FileOutputStream fo=new FileOutputStream(file);
int len=0;
byte[] buf =new byte[1024];
while((len=isInputStream.read(buf))!=-1){//isInputStream輸入流讀操作讀到“()”內容中
fo.write(buf,0,len);//fo輸出流寫操作寫入與fo綁定的文件中
}
System.out.println("postfile");
fo.flush();
fo.close();
return null;
}
5.doUpload()上傳文件攜帶參數
public void doUpload(View view){
File file =new File(Environment.getExternalStorageDirectory(),"banner2.jpg");
if (!file.exists()){
L.e(file.getAbsolutePath()+" not exist!");
return;
}
RequestBody requestBodyfile = RequestBody.create(MediaType.parse("application/octec-steam"), file);
//MultiPartBuilder已被MultiPartBody替代
//MultipartBody extends RequestBody
MultipartBody requestBody=new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("username","wu")
.addFormDataPart("password","1996")
.addFormDataPart("mphoto","banner2.jpg"
,requestBodyfile).build();
Request.Builder builder=new Request.Builder();
Request request=builder.
post(requestBody).
url(mBaseUrl+"uploadInfo.action").
build();
executeRequest(request);
}
後臺相應接收
public String uploadInfo() throws IOException{
System.out.print(username+","+mphotoFileName+"\n");
if(mphoto==null){
System.out.print(mphotoContentType+mphotoFileName+"no exist");
}
if(mphoto!=null){
String dir=ServletActionContext.getServletContext().getRealPath("/file2");//文件位置在運行哪個服務器就在他存儲目錄下file2
//E:\study\JAVA\MyEclipse\MyeclipseProject\.metadata\.me_tcat\webapps\okhttp\file2
//或下載的tomcat位置
File file=new File(dir,mphotoFileName);
FileUtils.copyFile(mphoto,file);//把mPhoto文件copy在file文件目錄下
}
return null;
}
特別說明下這種方法,本人覺得此方法是比較簡便的傳圖方法,後臺獲取圖片也相對容易,[鍵值對]方式需要名字相同
6.doDownLoad()下載文件
public void doDownload(View view){
Request.Builder builder=new Request.Builder();
final Request request=builder.
get().
url(mBaseUrl+"file2/banner2.jpg").//目標文件地址
build();
Call call=okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
L.e("onFailure:" + e.getMessage());
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final InputStream is = response.body().byteStream();//文件下載,流方式
/*
* 下載文件事圖片及其顯示方法
* */
final Bitmap bitmap=BitmapFactory.decodeStream(is);//圖片解碼字節流
runOnUiThread(new Runnable() {
@Override
public void run() {
imageView.setImageBitmap(bitmap);
}
});
/*
* 下載文件及其儲存方法
* */
FileOutputStream fos=new FileOutputStream
(new File(Environment.getExternalStorageDirectory(),"bannerdownload.jpg"));
int len=0;
byte[] buf=new byte[1024];
while((len=is.read(buf))!=-1){//什麼都讀不到返回-1 //循環讀取會自動read到的位置++
fos.write(buf,0,len);
}
fos.flush();
fos.close();
is.close();
}
});
}
大家發現沒有,這幾個函數還是有許多的重複代碼
OkHttp要交互只需要requestbody->request->call
於是我們可以再封裝下OkHttp
這是我自己的封裝方式,有點菜
封裝成類 OkHttpEncapsulation
public class OkHttpEncapsulation {
public static String mBaseUrl="http://192.168.191.1:8080/okhttp/";
public OkHttpClient okHttpClient=new OkHttpClient();
private RequestBody requestBody;
private String targetFun;
public OkHttpEncapsulation setRequestBody(RequestBody requestBody){
this.requestBody=requestBody;
return this;
}
public OkHttpEncapsulation setTargetFun(String targetFun){
this.targetFun=targetFun;
return this;
}
public void execute(Callback callback){
//創建request
if (requestBody!=null){
Request.Builder builder=new Request.Builder();
Request request=builder.
post(requestBody).
url(mBaseUrl+targetFun).
build();
//call請求
Call call=okHttpClient.newCall(request);
call.enqueue(callback);
}
else {//get方法不需要requestBody
Request.Builder builder=new Request.Builder();
Request request=builder.
get().
url(mBaseUrl+targetFun).
build();
Call call=okHttpClient.newCall(request);
call.enqueue(callback);
}
}
}
使用封裝類方法:
*使用方法
new OkHttpEncapsulation()
.setRequestBody(RequestBody類型)
.setTargetFun(“目標後臺函數映射名”)
.execute(Callback類型)
如doPostString()函數可寫成
public void doPostString(View view){
RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain;chaset=utf-8"),
"{username:wuzi,password:1996}");
new OkHttpEncapsulation()
.setRequestBody(requestBody)
.setTargetFun("postString.action")
.execute(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
}
相較之前還是簡潔一點的,代碼能簡潔一點都是好的嘛
參考資料 慕課網視頻