okhttp實現安卓登陸註冊功能

準備工作:

  • 添加 okhttp 依賴,最新版爲 4.0.0,在 build.gradle 中添加如下代碼:
 implementation 'com.squareup.okhttp3:okhttp:4.0.0'
  • 申請網絡權限,在清單文件中添加如下代碼:
<uses-permission android:name="android.permission.INTERNET"/>

思路:

  • 註冊:後臺獲取客戶端數據,查詢數據庫此賬號是否已經註冊,沒有則插入數據庫,並返回註冊成功,否則返回註冊失敗。
  • 登陸:本質爲查詢操作,獲取客戶端數據,查詢數據庫是否存在該賬號,並判斷賬號密碼是否匹配,最後返回登陸結果。

注意事項:

  • 需要真機測試,不能採用模擬器測試。

一:安卓客戶端代碼。

1.佈局代碼

<?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">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_height="60dp"
        android:layout_width="match_parent"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp">

        <TextView
            android:layout_width="60dp"
            android:layout_height="wrap_content"
            android:text="賬號"
            android:layout_gravity="center_vertical"
            android:textSize="20sp"/>

        <EditText
            android:id="@+id/account"
            android:layout_height="wrap_content"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_gravity="center_vertical"/>

    </LinearLayout>

    <LinearLayout
        android:orientation="horizontal"
        android:layout_height="60dp"
        android:layout_width="match_parent"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp">

        <TextView
            android:layout_width="60dp"
            android:layout_height="wrap_content"
            android:text="密碼"
            android:layout_gravity="center_vertical"
            android:textSize="20sp"/>

        <EditText
            android:id="@+id/password"
            android:layout_height="wrap_content"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:inputType="textPassword"
            android:layout_gravity="center_vertical"/>

    </LinearLayout>

    <Button
        android:id="@+id/login_btn"
        android:layout_height="40dp"
        android:layout_width="match_parent"
        android:text="登陸"
        android:textSize="18sp"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"/>

    <Button
        android:id="@+id/register_btn"
        android:layout_height="40dp"
        android:layout_width="match_parent"
        android:text="註冊"
        android:textSize="18sp"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"/>

</LinearLayout>

效果如圖:
在這裏插入圖片描述

2.MainActivity

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    //賬號密碼文本框內容
    private EditText accountText;
    private EditText passwordText;

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

        accountText = (EditText) findViewById(R.id.account);
        passwordText = (EditText) findViewById(R.id.password);
        Button loginBtn = (Button) findViewById(R.id.login_btn);
        Button registerBtn = (Button) findViewById(R.id.register_btn);
        loginBtn.setOnClickListener(this);
        registerBtn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            //登陸按鈕
            case R.id.login_btn:
                String loginAccount = accountText.getText().toString();
                String loginPassword = passwordText.getText().toString();
                loginWithOkHttp(loginAccount,loginPassword);
                break;
            //註冊按鈕
            case R.id.register_btn:
                String registerAccount = accountText.getText().toString();
                String registerPassword = passwordText.getText().toString();
                registerWithOkHttp(registerAccount,registerPassword);
                break;
            default:
                break;
        }
    }

    //實現登陸
    private void loginWithOkHttp(String account, String password) {
        OkHttpUtil.loginWithOkHttp(account, password, new okhttp3.Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.d("MianActivity","登陸請求失敗");
            }

            //請求成功,獲取服務器返回數據
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                //獲取返回內容
                final String responseData = response.body().string();
                //在主線程更新ui和響應用戶操作
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (responseData.equals("true")) {
                            Toast.makeText(MainActivity.this,"登陸成功",Toast.LENGTH_SHORT).show();
                            Intent intent = new Intent(MainActivity.this,AppActivity.class);
                            intent.putExtra("login","登陸成功");
                            startActivity(intent);
                        } else {
                            Toast.makeText(MainActivity.this,"登陸失敗",Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            }
        });
    }

    //實現註冊
    private void registerWithOkHttp(String account,String password) {
        OkHttpUtil.registerWithOkHttp(account, password, new okhttp3.Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.d("MianActivity","註冊請求失敗");
            }

            //請求成功,獲取服務器返回數據
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                //獲取返回內容
                final String responseData = response.body().string();
                //在主線程更新ui和響應用戶操作
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (responseData.equals("true")) {
                            Toast.makeText(MainActivity.this,"註冊成功",Toast.LENGTH_SHORT).show();
                            Intent intent = new Intent(MainActivity.this,AppActivity.class);
                            intent.putExtra("login","註冊成功");
                            startActivity(intent);
                        } else {
                            Toast.makeText(MainActivity.this,"註冊失敗",Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            }
        });
    }
}

3 .okhttputil工具類,採用靜態方法,分別處理註冊和登陸請求。

public class OkHttpUtil {
    //登陸請求
    public static void loginWithOkHttp(String account,String password,okhttp3.Callback callback) {
        OkHttpClient client = new OkHttpClient();
        RequestBody body = new FormBody.Builder()
                .add("loginAccount",account)
                .add("loginPassword",password)
                .build();
        Request request = new Request.Builder()
                .url( "http://111.111.11.111:8081/AndroidLogin/LoginServlet")
                .post(body)
                .build();
        client.newCall(request).enqueue(callback);
    }
    //註冊請求
    public static void registerWithOkHttp(String account,String password,okhttp3.Callback callback) {
        OkHttpClient client = new OkHttpClient();
        RequestBody body = new FormBody.Builder()
                .add("registerAccount",account)
                .add("registerPassword",password)
                .build();
        Request request = new Request.Builder()
                .url("http://111.111.11.111:8081/AndroidLogin/RegisterServlet")
                .post(body)
                .build();
        client.newCall(request).enqueue(callback);
    }
}

安卓端到這裏就全部實現了。

二:服務器端。

  • 導入數據庫驅動
  • 在數據庫中建好數據庫和表。
  • 如果你的 servlet 生成了註解 @WebServlet ,那麼就不需要編輯 web.xml 文件了,否則會發生衝突。

1 .註冊 servlet

@WebServlet("/RegisterServlet")
public class RegisterServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
    
    public RegisterServlet() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("this is get");
		request.setCharacterEncoding("UTF-8");
		//獲取客戶端數據
		String registerAccount = request.getParameter("registerAccount");
        String registerPassword = request.getParameter("registerPassword");
        
        boolean result= Model.register(registerAccount,registerPassword);
        System.out.println("註冊賬號:"+registerAccount+",註冊密碼:"+registerPassword+",註冊結果"+result);
        
        //通過PrintWriter返回給客戶端操作結果
        PrintWriter writer = response.getWriter();
        writer.print(result);
        writer.flush();
        writer.close();
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("this is post");
		doGet(request, response);
	}

}

2 .登陸 servlet

@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
    
    public LoginServlet() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("this is get");
		request.setCharacterEncoding("UTF-8");
		
		//獲取客戶端傳遞值
		String loginAccount = request.getParameter("loginAccount");
		String loginPassword = request.getParameter("loginPassword");

		boolean result = Model.login(loginAccount,loginPassword);
		System.out.println("登陸賬號:" + loginAccount + "登陸密碼:" + loginPassword + "登陸結果:" + result);
		
		response.setCharacterEncoding("UTF-8");
		//返回客戶端結果
		PrintWriter writer = response.getWriter();
		writer.print(result);
		writer.flush();
        writer.close();
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("this is post");
		doGet(request,response);
	}

}

3 .數據庫操作類,採用靜態函數。

public class Model {
	
	private static String usr = "root";
	private static String password = "password";
	private static String driver = "com.mysql.cj.jdbc.Driver";
	private static String url = "jdbc:mysql://11.111.111.111:3306/test?serverTimezone=UTC";

	/**
	 *登陸操作,本質是數據庫查詢
	 *查詢數據庫是否存在此賬號
	 *存在返回true,不存在返回false
	 */
	public static boolean login(String loginAccount ,String loginPassword) {
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		int count = 0;
		try {
			Class.forName(driver);
			conn = DriverManager.getConnection(url,usr,password);
			pstmt = conn.prepareStatement("select count(*) from android where account=? and password=?");
			pstmt.setString(1, loginAccount);
			pstmt.setString(2, loginPassword);
			rs = pstmt.executeQuery();
			if (rs.next()) {
				count = rs.getInt(1);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			...//rs,pstmt,conn回收
		}
		
		if (count == 1) {
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * 註冊操作
	 * 註冊前查詢賬號是否存在
	 * 存在則註冊失敗
	 */
	public static boolean register(String registerAccount ,String registerPassword) {
		//如果數據庫存在該用戶,則註冊失敗
		if (Model.login(registerAccount ,registerPassword)) {
			return false;
		}
		Connection conn = null;
		PreparedStatement pstmt = null;
		int count = 0;
		try {
			Class.forName(driver);
			conn = DriverManager.getConnection(url,usr,password);
			pstmt = conn.prepareStatement("insert into android values(?,?)");
			pstmt.setString(1, registerAccount );
			pstmt.setString(2, registerPassword);
			//返回受影響的行數
			count = pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			...//pstmt,conn回收
		}
		
		if (count == 1) {
			return true;
		} else {
			return false;
		}
	}
}
	

服務器端到這裏就完成了。

三:登陸註冊結果。
真機中輸入賬號:123123,密碼:111
分別點擊註冊和登陸按鈕後,在 tomcat 中結果如圖:
在這裏插入圖片描述

  • 關於okhttp:okhttp 發起網絡請求很方便,網絡請求屬於耗時操作,不能在主線程中進行,否則會阻塞主線程,而 okhttp 在 enqueue 方法內部會自動幫我們開好線程,並在子線程中進行 http 請求,並將請求結果回調到 okhttp3.Callback 中。但要注意的是,更新 UI 操作是不能在子線程中進行的,所以需要使用 runOnUiThread 方法轉換爲主線程。

最後附上參考鏈接,感謝。
https://www.cnblogs.com/HenuAJY/p/10884055.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章