數據庫大作業總結 android+Java web+mysql

這是我第一次做和網絡相關的程序。雖然之前做過app,但是都沒有和網絡交互,這次算是從零開始。廢話不多說,直接上乾貨。


開發工具:

  • android:android studio
  • java web:myEclipse(提取密碼:ia8f)各種版本,自選合適版本
  • mysql:參考這篇文章進行配置,我嘗試了phpMyadmin和mysql
    workbench 來管理數據庫,個人感覺phpMyadmin用的較爲熟練。
  • 模擬器:genymotion,強烈推薦這個模擬器,速度快,打開android studio創建的模擬器我要開半個小時!(下載genymotion很順利,但是下載模擬器十分艱難,具體可以參考本人的這篇文章)
  • 服務器:tomcat 7.x 配置方法參考這裏

以上環境如果能配置好,基本成功一半。(學習者一定要有耐心,配置環境花個一週我認爲很正常)
另外要強調的一點是要有充足的內存。本人是macbook pro 8g內存。如果是其它電腦,建議12g以上內存.


開發流程

其實可以說,要完成這個開發,你要走通3個helloworld:

  • android 端的helloworld,代表你的模擬器和android sdk配置完成
  • java web的helloworld代表你服務器端配置完成
  • 數據庫端的helloworld(就是一些select語句,這裏爲了工整使用helloworld代表)

如果以上信息不會,可以參考android hellowrold程序java web helloworld程序

android端就是平時我們的手機客戶端,java web程序放在服務器上,android與java web交互,獲取信息,收到android客戶端的信息後,java web向數據庫請求信息。具體見下面的流程

接下來描述程序的整體流程
1. android端發出http請求(Get請求或者Post請求,不理解也沒關係)
2. 服務器端java web程序接受請求。
3. 服務器端java web程序訪問數據庫,獲得返回結果。
4. 服務器端java web程序將返回結果傳輸給客戶端。
5. 客戶端得到結果,顯示給客戶使用。

這裏寫圖片描述

以上是最基本的概念,如果讀者還沒有跑通3個helloworld,請繼續配置環境,如果是已經跑通了所有的helloworld但是對android或者java web的程序結構不太清楚可以參考一下文章,如果都已經完成,那麼我們就可以開始開發了。

沒有必要完全搞懂,一邊做一邊學習即可。


通訊過程工具+關鍵代碼

到了這一部分,作者認爲讀者已經瞭解如何創建android和java web的程序,並且已經有了基本的sql語句的知識(增、刪、查、改)。這一部分紛呈兩個模塊,第一個模塊講述android如何發送請求,第二個模塊講述java web如何接受請求。

使用的包:

  • gson(將數據打包成json文件格式、將json解析爲對象、在android和java web端都可以使用,此包爲谷歌工程師開發,必屬精品)
  • xutils(此包集結了中國工程師們的智慧,幫助我們極大的簡化了網絡通訊,代碼簡化,各種高性能優點)

part one

以下是android端的核心代碼,發出一個網絡請求,收到查詢結果。這是一個登錄功能,界面就是兩個EditText,當點擊登錄按鈕時發送數據,當訪問成功,接收返回數據,在responseInfo.result中,將用戶信息存儲在sharedPreferce中,並記住登錄狀態。裏面用到了xutils的兩個功能

  • HttpUtils:
    send函數

    * 參數:方法(Post或者Get)、訪問的網址、參數、返回
    
  • ViewUtils:
    幫助我們方便的找到控件
    現在create方法中調用ViewUtils.Inject方法,在定義控件的時候採用註解的寫法,就不需要使用findviewbyid了

SharedPerference是我引入的一個工具類,在後面提供工具類的代碼。

LoginActivity.java

package com.example.wxc575843.hellotone.start;

import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.example.wxc575843.hellotone.Practice.PracticeMain;
import com.example.wxc575843.hellotone.R;
import com.example.wxc575843.hellotone.utils.SharePreferenceUtils;
import com.google.gson.Gson;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.ViewUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.RequestParams;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import com.lidroid.xutils.http.client.HttpRequest;
import com.lidroid.xutils.view.annotation.ViewInject;
import com.model.Global;
import com.model.User;

public class LoginActivity extends AppCompatActivity {

    private final String TAG = "LoginActivity";

    private String email;
    private String password;

    @ViewInject(R.id.login_email)
    EditText etMail;

    @ViewInject(R.id.login_password)
    EditText etPassword;

    @ViewInject(R.id.btnLogin)
    Button btnLogin;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        ViewUtils.inject(this);

        btnLogin.setOnClickListener(loginLinster);
    }

    Button.OnClickListener loginLinster = new Button.OnClickListener() {
        @Override
        public void onClick(View v) {
            email = etMail.getText().toString().trim();
            password = etPassword.getText().toString();

            Log.d(TAG+"email",email);
            Log.d(TAG+"password",password);
            if (email.isEmpty() || password.isEmpty()){
                Toast.makeText(LoginActivity.this,"sth empty",Toast.LENGTH_SHORT).show();
            }else {
                HttpUtils httpUtils = new HttpUtils();
                RequestParams requestParams = new RequestParams();
                requestParams.addBodyParameter("email",email);
                requestParams.addBodyParameter("password",password);

String url = http://172.29.105.107:8080/HelloToneWebService/servlet/SigninServlet;
            httpUtils.send(HttpRequest.HttpMethod.POST, url, requestParams, new RequestCallBack<String>() {
                    @Override
                    public void onSuccess(ResponseInfo<String> responseInfo) {
                        String rs = responseInfo.result;
                        Log.d(TAG,rs);
                        Gson gson = new Gson();
                        User user = gson.fromJson(rs, User.class);
                        Log.d(TAG,user.getStateCode()+"");
                        if (user.getStateCode()==1){
                            SharePreferenceUtils.putString(LoginActivity.this,"email",user.getEmail());
                            SharePreferenceUtils.putString(LoginActivity.this,"nickname",user.getNickName());
                            SharePreferenceUtils.putString(LoginActivity.this,"gender",user.getGender());
                            SharePreferenceUtils.putString(LoginActivity.this,"country",user.getCountry());
                            SharePreferenceUtils.putString(LoginActivity.this,"chineseLevel",user.getChineseLevel());
                            SharePreferenceUtils.putInt(LoginActivity.this, "level", user.getLevel());
                            SharePreferenceUtils.putString(LoginActivity.this, "headPicture", user.getHeadPicture());
                            SharePreferenceUtils.putInt(LoginActivity.this, "articleNum", user.getArticleNum());
                            SharePreferenceUtils.putInt(LoginActivity.this,"postNum",user.getPostNum());
                            SharePreferenceUtils.putInt(LoginActivity.this,"experience",user.getExperience());
                            SharePreferenceUtils.putString(LoginActivity.this, "password", password);
                            SharePreferenceUtils.putString(LoginActivity.this,"id",user.getId());

                            SharePreferenceUtils.putBoolean(LoginActivity.this,"loginState",true);

                            Log.d(TAG,user.getChineseLevel());

                            Intent intent = new Intent(LoginActivity.this,MainActivity.class);
                            startActivity(intent);
                            finish();
                        } else {
                            Toast.makeText(LoginActivity.this,R.string.login_wrong,Toast.LENGTH_SHORT).show();
                        }
                    }

                    @Override
                    public void onFailure(HttpException e, String s) {
                        Toast.makeText(LoginActivity.this,R.string.register_failed_network,Toast.LENGTH_SHORT).show();
                    }
                });
            }
        }
    };
}

SharePreferenceUtils.java

package com.example.wxc575843.hellotone.utils;

import android.content.Context;
import android.content.SharedPreferences;

/**
 * 專門訪問和設置SharePreference的工具類, 保存和配置一些設置信息
 * 
 * @author Kevin
 * 
 */
public class SharePreferenceUtils {

    private static final String SHARE_PREFS_NAME = "preference";
    private static SharedPreferences mSharedPreferences;

    public static void putBoolean(Context ctx, String key, boolean value) {
        if (mSharedPreferences == null) {
            mSharedPreferences = ctx.getSharedPreferences(SHARE_PREFS_NAME,
                    Context.MODE_PRIVATE);
        }

        mSharedPreferences.edit().putBoolean(key, value).commit();
    }

    public static boolean getBoolean(Context ctx, String key,
            boolean defaultValue) {
        if (mSharedPreferences == null) {
            mSharedPreferences = ctx.getSharedPreferences(SHARE_PREFS_NAME,
                    Context.MODE_PRIVATE);
        }

        return mSharedPreferences.getBoolean(key, defaultValue);
    }

    public static void putString(Context ctx, String key, String value) {
        if (mSharedPreferences == null) {
            mSharedPreferences = ctx.getSharedPreferences(SHARE_PREFS_NAME,
                    Context.MODE_PRIVATE);
        }

        mSharedPreferences.edit().putString(key, value).commit();
    }

    public static String getString(Context ctx, String key, String defaultValue) {
        if (mSharedPreferences == null) {
            mSharedPreferences = ctx.getSharedPreferences(SHARE_PREFS_NAME,
                    Context.MODE_PRIVATE);
        }

        return mSharedPreferences.getString(key, defaultValue);
    }

    public static void putInt(Context ctx, String key, int value){
        if (mSharedPreferences == null) {
            mSharedPreferences = ctx.getSharedPreferences(SHARE_PREFS_NAME,
                    Context.MODE_PRIVATE);
        }

        mSharedPreferences.edit().putInt(key,value).commit();
    }

    public static int getInt(Context ctx, String key, int defaultValue) {
        if (mSharedPreferences == null) {
            mSharedPreferences = ctx.getSharedPreferences(SHARE_PREFS_NAME,
                    Context.MODE_PRIVATE);
        }

        return mSharedPreferences.getInt(key, defaultValue);
    }
}

part two

以下時對應的java web端的代碼,接收了請求,進入數據庫查詢,講返回結果打包成json的形式返回給用戶。SigninServlet.java是響應用戶請求的後臺代碼,後面的配置文件和SqlManager代碼是連接數據庫的工具類

SigninServlet.java

package app.hellotone.web.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import app.hellotone.web.dao.SigninDao;
import app.hellotone.web.model.User;

import org.json.simple.JSONObject;

import com.google.gson.Gson;


public class SigninServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doPost(request, response);

    }


    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        String email = request.getParameter("email");
        String password = request.getParameter("password");
        User user;
        try {
            SigninDao siginDao = new SigninDao();
            user = siginDao.signIn(email, password);
            Gson gson = new Gson();
            response.setContentType("application/json");
            response.setCharacterEncoding("UTF-8");
            response.getWriter().write(gson.toJson(user));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }


}

SigninDao.java

package app.hellotone.web.dao;

import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;

import app.hellotone.web.model.User;

public class SigninDao {
    SqlManager manager;
    String sql = "";
    ResultSet rs;

    public SigninDao() throws IOException, ClassNotFoundException{
        manager = SqlManager.createInstance();
    }

    public User signIn(String username, String password) throws SQLException{
        boolean success = false;
        this.sql = "select * from UserFull where Email=? and Password=?";
        Object[] params = new Object[]{username,password};
        User user = new User();
        manager.connectDB();
        rs=manager.executeQuery(sql, params);
        if(rs.next()) {
            user.setStateCode(1);
            user.setId(Integer.parseInt(rs.getString("ID")));
            user.setNickName(rs.getString("Nickname"));
            user.setEmail(rs.getString("Email"));
            user.setGender(rs.getString("Gender"));
            user.setCountry(rs.getString("Country"));
            user.setLevel(rs.getInt("ULevel"));
            user.setChineseLevel(rs.getString("漢語水平"));
            user.setHeadPicture(rs.getString("頭像"));
            user.setArticleNum(rs.getInt("ArticleNum"));
            user.setPostNum(rs.getInt("PostNum"));
            user.setExperience(rs.getInt("Experience"));
        }
        manager.closeDB();
        return user;
    }
}

Config.propertise

#Set *.properties default encoding UTF-8

#\u6570\u636e\u5e93\u5e95\u5c42\u64cd\u4f5c\u7c7b\u914d\u7f6e\u6587\u4ef6

#\u6307\u5b9a\u4e3b\u673a\u5730\u5740
DBhost=localhost
#\u6307\u5b9a\u7aef\u53e3\u53f7
DBport=3306
#\u6307\u5b9a\u8fde\u63a5\u6570\u636e\u5e93
DBname=HelloTone
#\u6307\u5b9a\u7528\u6237\u540d
DBuser=root
#\u6307\u5b9a\u5bc6\u7801
DBpassword=123456

SqlManager.java

package app.hellotone.web.dao;

/*
 * 數據庫操作類,進行數據庫底層操作
 * 配置信息在Config.properties文件中
 * Made By:coolszy
 * 2009.07.07
 */

import java.io.IOException;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.PropertyResourceBundle;

public class SqlManager
{
    private static SqlManager manager = null; // 靜態成員變量,支持單態模式
    private PropertyResourceBundle bundle; // 配置資源文件
    private static String jdbcDrive = null; // JDBC驅動類型
    private String DBhost = ""; // 數據庫主機地址
    private String DBname = ""; // 數據庫名
    private String DBprot = ""; // 數據庫端口
    private String DBuser = ""; // 數據庫用戶名
    private String DBpasswd = ""; // 數據庫密碼
    private String strcon = null; // 連接字符串

    private Connection conn = null; // 連接對象
    private PreparedStatement pstm = null;
    private CallableStatement cstm = null;

    /**
     * 私有構造函數,不可實例化
     * 
     * @throws IOException
     */
    private SqlManager() throws IOException
    {
        // 讀取配置文件
        bundle = new PropertyResourceBundle(SqlManager.class
                .getResourceAsStream("Config.properties"));
        this.DBhost = getString("DBhost"); // 讀取主機名
        this.DBname = getString("DBname"); // 讀取用戶名
        this.DBprot = getString("DBport"); // 讀取端口
        this.DBuser = getString("DBuser"); // 讀取用戶
        this.DBpasswd = getString("DBpassword"); // 讀取密碼
        // 設置mysql數據庫的驅動程序和連接字符
        jdbcDrive = "com.mysql.jdbc.Driver";
        strcon = "jdbc:mysql://" + DBhost + ":" + DBprot + "/" + DBname;
    }

    /**
     * 讀取配置文件中的值
     * 
     * @param key
     *            配置文件的key
     * @return key對應的值
     */
    private String getString(String key)
    {
        return this.bundle.getString(key);
    }

    /**
     * 單態模式獲取實例
     * 
     * @return SqlManager對象
     * @throws IOException
     * @throws ClassNotFoundException 
     */
    public static SqlManager createInstance() throws IOException, ClassNotFoundException
    {
        if (manager == null)
        {
            manager = new SqlManager();
            manager.initDB();
        }
        return manager;
    }

    /**
     * 初始化連接參數,由指定的DBType生成
     * 
     * @throws ClassNotFoundException
     */
    public void initDB() throws ClassNotFoundException
    {
        Class.forName(jdbcDrive);
    }

    /**
     * 連接數據庫
     * 
     * @throws SQLException
     */
    public void connectDB() throws SQLException
    {
        conn = DriverManager.getConnection(strcon, DBuser, DBpasswd); // 獲取連接
        conn.setAutoCommit(false); // 設置自動提交爲false
    }

    /**
     * 斷開數據庫
     * 
     * @throws SQLException
     */
    public void closeDB() throws SQLException
    {
        if (pstm != null)
        {
            pstm.close();
        }
        if (cstm != null)
        {
            cstm.close();
        }
        if (conn != null)
        {
            conn.close();
        }
    }

    /**
     * 設置PrepareStatement對象中Sql語句中的參數
     * 
     * @param sql
     *            sql語句
     * @param params
     *            參數列表
     * @throws SQLException
     */
    private void setPrepareStatementParams(String sql, Object[] params)
            throws SQLException
    {
        pstm = conn.prepareStatement(sql); // 獲取對象
        if (params != null)
        {
            for (int i = 0; i < params.length; i++) // 遍歷參數列表填充參數
            {
                pstm.setObject(i + 1, params[i]);
            }
        }
    }

    /**
     * 執行查詢
     * 
     * @param sql
     *            sql語句
     * @param params
     *            參數列表
     * @return 返回ResultSet類型的查詢結果
     * @throws SQLException
     */
    public ResultSet executeQuery(String sql, Object[] params)
            throws SQLException
    { // 執行查詢數據庫接口
        ResultSet rs = null;
        manager.setPrepareStatementParams(sql, params); // 填充參數
        rs = pstm.executeQuery(); // 執行查詢操作
        return rs;
    }

    /**
     * 更新數據庫操作
     * 
     * @param sql
     *            sql語句
     * @param params
     *            參數列表
     * @return 執行操作的結果
     * @throws SQLException
     */
    public boolean executeUpdate(String sql, Object[] params)
            throws SQLException // 執行無返回數據的數據查詢,返回值是被改變的書庫的數據庫項數
    {
        boolean result = false;
        manager.setPrepareStatementParams(sql, params); // 填充參數
        pstm.executeUpdate(); // 執行更新
        manager.commitChange();
        result = true;
        return result;
    }

    /**
     * 提交信息到數據庫
     * 
     * @throws SQLException
     */
    private void commitChange() throws SQLException
    {
        conn.commit();
    }
}

到此爲止,我們已經完成了總體的交互過程,希望大家能夠有所收穫,如果還有不明白的,活着我沒有講清楚的地方歡迎在下面提問,我看到會盡快回答。

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