【程式設計新實務】Lab4 系統登入/註冊模組(Android app)的開發

CodeFriday發表於2020-12-12

前言

本次是本學期程式設計新實務最後一次實驗,四次實驗不斷迭代最後總能得到一個屬於自己的東西。
之前也沒接觸過java,這門課啥都是從0開始基本上。也參考了很多學長的部落格和很多大佬的部落格!
由於之前Lab2已經實現部署到雲伺服器,因此本次實驗相對省心不少。我在Lab2的基礎上修改了servlet實現後端傳輸一個json資料給安卓客戶端解析,大多數工作交給了後端完成,傳回安卓客戶端實際就一個操作結果。比如註冊成功/失敗,修改密碼成功/失敗,登入成功/失敗(此處多返回name,username,age,telephone等資料),由於一直在前面實驗基礎上迭代,因此資料庫表都懶得改了!!!

具體影響比如:
密碼只能八位,username11位,name11位都是實驗一留下的東西,懶得改了。
然後我把實驗一中person表中主鍵由原來的name改為username,這樣整個安卓登入註冊,唯一不能重複的就是username了,我覺得這樣更符合實際一點。

完後還加了一個mob平臺的簡訊驗證,沒別的原因,主要免費!!!

傳送門(本人的):
實驗一,java程式設計運算元據庫
實驗二,servlet+jsp實現javaweb資料庫操作
實驗二部署到雲伺服器
參考的部落格:
mob平臺使用
阿里圖示庫超級全

展示

在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

安卓前端

此部分主要是實現UI的編碼
安卓實現UI一般有4種方式,純xml佈局檔案,在java程式碼中控制UI,java+xml,自定義view
一般的話都是xml加java程式碼,xml實現頁面佈局相對直觀
java程式碼實現互動,如button按鈕,edittext的內容合法性判斷。
而xml一般使用4種佈局管理器,相對佈局,幀佈局,線性佈局,網格佈局。

更多基礎知識請移步這兒補:
安卓從入門到入土
登入:

在這裡插入圖片描述
忘記密碼:
在這裡插入圖片描述
註冊:
在這裡插入圖片描述
歡迎:
在這裡插入圖片描述

程式碼稍後上傳Github

安卓後端

登入和註冊主要用到
AsyncTask實現一個非同步通訊多執行緒
一個xml佈局檔案對應一個java類
例如:mainactivity程式碼如下:

package com.example.client;

import androidx.appcompat.app.AppCompatActivity;
import android.os.AsyncTask;
import  android.widget.Button;
import android.os.Bundle;
import android.view.*;
import android.content.*;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import org.json.JSONObject;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class MainActivity extends AppCompatActivity {
    private EditText username;
    private EditText password;
    private TextView err;
    private Button b1;//註冊按鈕
    private Button b2;//登入按鈕
    private Button b3;//忘記密碼按鈕
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        username = (EditText) findViewById(R.id.username);
        password = (EditText) findViewById(R.id.password);
        err = (TextView) findViewById(R.id.message);
        b1 = (Button) findViewById(R.id.register);
        b2 = (Button) findViewById(R.id.login);
        b3 = (Button) findViewById(R.id.login_error);
    }

    public void sign(View view) {    //登入按鍵的響應按鍵
        String user = username.getText().toString();
        String pass = password.getText().toString();
        if (user.isEmpty() || pass.isEmpty()) {
            err.setText("登入失敗,使用者名稱或密碼不能為空");
            err.setVisibility(View.VISIBLE);
        } else {
            err.setText(null);
            err.setVisibility(View.INVISIBLE);
            new SignInProcess().execute(user,pass);
        }
    }

    public void signUp(View view) {   //註冊按鍵的響應按鍵
        Intent intent = new Intent(MainActivity.this, RegisterActivity.class);
        startActivity(intent);
    }

    public void forget(View view) {   //註冊按鍵的響應按鍵
        Intent intent = new Intent(MainActivity.this, ChangepassActivity.class);
        startActivity(intent);
    }

    private class SignInProcess extends AsyncTask<String, String, String> {
        @Override
        protected String doInBackground(String... params) {
            String username = params[0];
            String password = params[1];
            String result = "";
            String s_url = "http://42.194.181.52:8080/lab4/Sign?username="+username+"&password="+password;
            System.out.println(s_url);
            try {
                URL url = new URL(s_url);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setUseCaches(false);
                conn.connect();
                InputStream is = conn.getInputStream();
                InputStreamReader reader = new InputStreamReader(is, "UTF-8");//獲取伺服器資料實現從位元組流到字元流轉換
                int temp;
                while((temp=reader.read()) != -1) {
                    result += (char)temp;
                }
            } catch(Exception e) {
                err.setText("登入失敗,網路錯誤");
                err.setVisibility(View.VISIBLE);
                e.printStackTrace();
            }
            System.out.println(result);
            return result;
        }

        @Override
        protected void onPostExecute(String result) {
            try {
                JSONObject result_json = new JSONObject(result);
                if(result_json.has("error")) {
                    String error_code;
                    error_code = result_json.getString("error");
                    err.setText(error_code);
                    err.setVisibility(View.VISIBLE);
                    password.setText(null);
                } else {
                    SignInSuccess(result_json);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    private void SignInSuccess(JSONObject info) {
        Intent intent=new Intent();
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setClass(this,WelcomeActivity.class);

        Toast.makeText(this,"登入成功",Toast.LENGTH_SHORT).show();
        try {
            intent.putExtra("username", info.getString("username"));
            intent.putExtra("name", info.getString("name"));
            intent.putExtra("age", info.getString("age"));
            intent.putExtra("teleno", info.getString("teleno"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        startActivity(intent);
    }
}

主要通過HttpURLConnection實現與伺服器後端通訊,由於實驗二搞的不是很嚴謹,沒有用https通訊,呼叫servlet是明文,密碼會被抓包直接得到。。。等後續有空再完善!!!

伺服器後端

以登入為例子:

package Servlet;

import net.sf.json.JSON;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import lab2.*;

//註冊介面

/**
 * Servlet implementation class Sign
 */
@WebServlet("/Sign")
public class Sign extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public Sign() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.setContentType("text/html;charset=UTF-8");
        String username = request.getParameter("username").trim();
        String password = request.getParameter("password").trim();
        PrintWriter out = response.getWriter();
        UserOp uo = new UserOp();
        PersonOp po = new PersonOp();
        DB_conn_op sjk = null;
        try {
            sjk = new DB_conn_op();
        } catch (Exception e) {
            e.printStackTrace();
        }
        JSONObject res = new JSONObject();
        boolean flag = false;//username是否存在
        try {
            flag = uo.findUser1(new User(username,password),sjk);
            if(flag){//如果找到user
                Person p = po.findPerson1(username,sjk);
                res.put("username",p.getUsername());
                res.put("name",p.getName());
                if(p.getAge()!=null)
                res.put("age",p.getAge().toString());
                else res.put("age","");
                if(p.getTeleno()!=null)
                res.put("teleno",p.getTeleno());
                else res.put("teleno","");
            }
            else res.put("error","登陸失敗,使用者名稱或密碼錯誤");

        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(res);
        out.println(res);
        out.close();
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}

總結

遇到bug不要慌,冷靜下來慢慢搞!

相關文章