Android通过Http连接MySQL 实现登陆/注册(数据库+服务器+客户端)_Vexento的博客-程序员秘密

技术标签: Android开发  

转载自http://www.cnblogs.com/yzxk/p/4749440.html


一、开发环境的部署

程序结构:

android+servlet+service+mysql

仅供参考:能实现相关功能即可

操作系统:ubuntu 14.10

数据库:mysql-5.5    数据库工具:emma

服务器:tomcat      服务器工具:Myeclipse 10

安卓端:真机 android4.4  安卓端工具:eclipse+adt

注意:

程序调试过程可能会产生乱码,只需保持所有工具编码方式相同即可。

 

二、数据库设计

表名:student

视图:

 

 

三、服务器端设计

1、新建Web Project,命名为HelloWeb

2、项目结构图如下:

 LogLet类和RegLet类分别用于处理客户端的登陆和注册请求;Service类用于完成servlet对数据库的具体操作;DBManager类用于进行数据库基本操作;

 左侧是项目图,右侧是web.xml配置文件截图。

   

 

3、项目代码:

 DBManager.java

 <1> 单例模式构建DBManager对象;       

 <2> 定义数据库连接、关闭以及增删改查的基本操作,返回结果集。

复制代码
package com.db;

import java.sql.*;

public class DBManager {

    // 数据库连接常量
    public static final String DRIVER = "com.mysql.jdbc.Driver";
    public static final String USER = "root";
    public static final String PASS = "root";
    public static final String URL = "jdbc:mysql://localhost:3306/test";

    // 静态成员,支持单态模式
    private static DBManager per = null;
    private Connection conn = null;
    private Statement stmt = null;

    // 单态模式-懒汉模式
    private DBManager() {
    }

    public static DBManager createInstance() {
        if (per == null) {
            per = new DBManager();
            per.initDB();
        }
        return per;
    }

    // 加载驱动
    public void initDB() {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 连接数据库,获取句柄+对象
    public void connectDB() {
        System.out.println("Connecting to database...");
        try {
            conn = DriverManager.getConnection(URL, USER, PASS);
            stmt = conn.createStatement();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        System.out.println("SqlManager:Connect to database successful.");
    }

    // 关闭数据库 关闭对象,释放句柄
    public void closeDB() {
        System.out.println("Close connection to database..");
        try {
            stmt.close();
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        System.out.println("Close connection successful");
    }

    // 查询
    public ResultSet executeQuery(String sql) {
        ResultSet rs = null;
        try {
            rs = stmt.executeQuery(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return rs;
    }

    // 增添/删除/修改
    public int executeUpdate(String sql) {
        int ret = 0;
        try {
            ret = stmt.executeUpdate(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return ret;
    }
}
复制代码

 

Service.java

  写到这里,可以预见:下一个类会通过调用本类方法完成登陆/注册的服务。

复制代码
package com.service;

import java.sql.ResultSet;
import java.sql.SQLException;

import com.db.DBManager;

public class Service {

    public Boolean login(String username, String password) {

        // 获取Sql查询语句
        String logSql = "select * from user where username ='" + username
                + "' and password ='" + password + "'";

        // 获取DB对象
        DBManager sql = DBManager.createInstance();
        sql.connectDB();

        // 操作DB对象
        try {
            ResultSet rs = sql.executeQuery(logSql);
            if (rs.next()) {
                sql.closeDB();
                return true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        sql.closeDB();
        return false;
    }

    public Boolean register(String username, String password) {
    
        // 获取Sql查询语句
        String regSql = "insert into student values('"+ username+ "','"+ password+ "') ";

        // 获取DB对象
        DBManager sql = DBManager.createInstance();
        sql.connectDB();

        int ret = sql.executeUpdate(regSql);
        if (ret != 0) {
            sql.closeDB();
            return true;
        }
        sql.closeDB();
        
        return false;
    }
}
复制代码

 

LogLet.java

  一个简单的Servlet,用于处理Http请求(get/post)。RegLet.java和该类近乎相同,此处省去~

复制代码
package com.servlet;

import java.io.IOException;
import java.io.PrintWriter;

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

import com.service.Service;

public class LogLet extends HttpServlet {

    private static final long serialVersionUID = 369840050351775312L;

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

        // 接收客户端信息
        String username = request.getParameter("username");
        username = new String(username.getBytes("ISO-8859-1"), "UTF-8");
        String password = request.getParameter("password");
        System.out.println(username + "--" + password);

        // 新建服务对象
        Service serv = new Service();

        // 验证处理
        boolean loged = serv.login(username, password);
        if (loged) {
            System.out.print("Succss");
            request.getSession().setAttribute("username", username);
            // response.sendRedirect("welcome.jsp");
        } else {
            System.out.print("Failed");
        }

        // 返回信息到客户端
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.print("用户名:" + username);
        out.print("密码:" + password);
        out.flush();
        out.close();

    }


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

    }

}
复制代码

 

 

四、客户端设计

1、新建Android App Project,命名为AndroidHTTPDemo

2、现在开始思考需要什么东西... 

 <1> 登陆和注册页面:布局文件

   login.xml , register.xml

 <2> 登陆和注册页面对应的Activity组件,在activity中进行具体操作

   login.java , register.java

 <3> 能够实现Http以get/post方式通信的类

   WebService.java , WebServicePost.java

 <4> 网络通信权限

        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
           <uses-permission android:name="android.permission.INTERNET" />

    OK,项目结构出炉,右侧是Manifeast配置文件的主要内容

3、现在,我们开始关注具体的代码。

  <1> 首先要做的,登陆注册界面,这个不用多说。我直接放图,大致就是下面这个样子,大家可以按照自己爱好设计。

  

<2> 在服务器端编程时我们了解到:服务器端接收客户端发送的信息,对信息进行一系列处理后,最终信息返回到客户端。

  首先要想的,就是获取信息并发送出去,然后接收信息并显示出来。

 (网络服务由于耗时问题,放在主线程很可能由于网络故障导致ANR;所以要开辟子线程留给http网络服务。当然不使用主线程也可以,只是不推荐)

      

<3> Login.java 有三点需要注意

  第一个是检测网络状态,只能检测流量,无法检测wifi;

  第二个是在子线程中,不能更改主线程的页面值,这里用了handle解决。

  第三个是这里有get/post两种http请求方式,两个实现类,。

复制代码
package com.httpdemo;

import com.rxz.androidhttpdemo.R;
import com.web.WebService;
import com.web.WebServicePost;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.os.Handler;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class Login extends Activity implements OnClickListener {

    // 登陆按钮
    private Button logbtn;
    // 调试文本,注册文本
    private TextView infotv, regtv;
    // 显示用户名和密码
    EditText username, password;
    // 创建等待框
    private ProgressDialog dialog;
    // 返回的数据
    private String info;
    // 返回主线程更新数据
    private static Handler handler = new Handler();

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

        // 获取控件
        username = (EditText) findViewById(R.id.user);
        password = (EditText) findViewById(R.id.pass);
        logbtn = (Button) findViewById(R.id.login);
        regtv = (TextView) findViewById(R.id.register);
        infotv = (TextView) findViewById(R.id.info);

        // 设置按钮监听器
        logbtn.setOnClickListener(this);
        regtv.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.login:
            // 检测网络,无法检测wifi
            if (!checkNetwork()) {
                Toast toast = Toast.makeText(Login.this,"网络未连接", Toast.LENGTH_SHORT);
                toast.setGravity(Gravity.CENTER, 0, 0);
                toast.show();
                break;
            }
            // 提示框
            dialog = new ProgressDialog(this);
            dialog.setTitle("提示");
            dialog.setMessage("正在登陆,请稍后...");
            dialog.setCancelable(false);
            dialog.show();
            // 创建子线程,分别进行Get和Post传输
            new Thread(new MyThread()).start();
            break;
        case R.id.register:
            Intent regItn = new Intent(Login.this, Register.class);
            // overridePendingTransition(anim_enter);
            startActivity(regItn);
            break;
        }
        ;
    }

    // 子线程接收数据,主线程修改数据
    public class MyThread implements Runnable {
        @Override
        public void run() {
            info = WebService.executeHttpGet(username.getText().toString(), password.getText().toString());
            // info = WebServicePost.executeHttpPost(username.getText().toString(), password.getText().toString());
            handler.post(new Runnable() {
                @Override
                public void run() {
                    infotv.setText(info);
                    dialog.dismiss();
                }
            });
        }
    }

    // 检测网络
    private boolean checkNetwork() {
        ConnectivityManager connManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connManager.getActiveNetworkInfo() != null) {
            return connManager.getActiveNetworkInfo().isAvailable();
        }
        return false;
    }

}
复制代码

 

<4> WebService.java   

  这里的IP是你的服务器IP,不确定时看下是否能用手机ping工具ping通。

  ① 你的服务器端程序已发布到互联网:这好办,就是你的IP地址。

  ② 你是在本地电脑上,这要求你的真机和你的电脑在同一个局域网。两种较方便的方法:路由器/笔记本的无线网卡

   conn.setConnectTimeout(3000);需要设置超时时间,否则会执行默认超时时间,30s ?

复制代码
package com.web;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class WebService {

    private static String IP = "10.42.0.1:8080";

    // 通过Get方式获取HTTP服务器数据
    public static String executeHttpGet(String username, String password) {

        HttpURLConnection conn = null;
        InputStream is = null;

        try {
            // 用户名 密码
            // URL 地址
            String path = "http://" + IP + "/HelloWeb/LogLet";
            path = path + "?username=" + username + "&password=" + password;

            conn = (HttpURLConnection) new URL(path).openConnection();
            conn.setConnectTimeout(3000); // 设置超时时间
            conn.setReadTimeout(3000);
            conn.setDoInput(true);
            conn.setRequestMethod("GET"); // 设置获取信息方式
            conn.setRequestProperty("Charset", "UTF-8"); // 设置接收数据编码格式

            if (conn.getResponseCode() == 200) {
                is = conn.getInputStream();
                return parseInfo(is);
            }

        }catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 意外退出时进行连接关闭保护
            if (conn != null) {
                conn.disconnect();
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
        return null;
    }

    // 将输入流转化为 String 型 
    private static String parseInfo(InputStream inStream) throws Exception {
        byte[] data = read(inStream);
        // 转化为字符串
        return new String(data, "UTF-8");
    }

    // 将输入流转化为byte型 
    public static byte[] read(InputStream inStream) throws Exception {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, len);
        }
        inStream.close();
        return outputStream.toByteArray();
    }
}
复制代码

 

<5> WebServicePost.java

复制代码
package com.web;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreConnectionPNames;

public class WebServicePost {

    private static String IP = "10.42.0.1:8080";

    // 通过 POST 方式获取HTTP服务器数据
    public static String executeHttpPost(String username, String password) {

        try {
            String path = "http://" + IP + "/HelloWeb/LogLet";

            // 发送指令和信息
            Map<String, String> params = new HashMap<String, String>();
            params.put("username", username);
            params.put("password", password);

            return sendPOSTRequest(path, params, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    // 处理发送数据请求
    private static String sendPOSTRequest(String path, Map<String, String> params, String encoding) throws Exception {

        List<NameValuePair> pairs = new ArrayList<NameValuePair>();
        if (params != null && !params.isEmpty()) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                pairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
        }

        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(pairs, encoding);

        HttpPost post = new HttpPost(path);
        post.setEntity(entity);
        DefaultHttpClient client = new DefaultHttpClient();
        // 请求超时
        client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);
        // 读取超时
        client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 5000);
        HttpResponse response = client.execute(post);

        // 判断是否成功收取信息
        if (response.getStatusLine().getStatusCode() == 200) {
            return getInfo(response);
        }

        // 未成功收取信息,返回空指针
        return null;
    }

    // 收取数据
    private static String getInfo(HttpResponse response) throws Exception {

        HttpEntity entity = response.getEntity();
        InputStream is = entity.getContent();
        // 将输入流转化为byte型
        byte[] data = WebService.read(is);
        // 转化为字符串
        return new String(data, "UTF-8");
    }
}
复制代码

 

五、运行效果

  以上工作完成后,只需要讲服务器端发布到本地(附上--mysql-jdbc驱动地址--),安卓端发布到手机,确保局域网内部,ip正确,即可正常访问。

  客户端截图:测试成功

           

  服务器端截图:测试成功

  

 


源码下载 

 


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_23035265/article/details/52625110

智能推荐

Mysql 报错:出现Table ‘performance_schema.session_status‘ doesn‘t [email protected]的博客-程序员秘密_performance_schema.session_status

在Centos下安装了mysql后,使用 数据库管理软件 HeidiSQL远程连接,报错:Table 'performance_schema.session_status' doesn't exist错误;解决办法1. 进入Mysql的安装目录的bin文件夹2. 打开cmd进入该目录执行mysql_upgrade -u root -p --force命令然后输入密码问题解决...

在Oracle中查询表的大小、表的占用情况和表空间的大小_hzp666的博客-程序员秘密

在Oracle中查询表的大小、表的占用情况和表空间的大小 有两种含义的表大小。一种是分配给一个表的物理空间数量,而不管空间是否被使用。可以这样查询获得字节数:select segment_name, bytes from user_segments where segment_type = 'TABLE'; 或者   Select Segment_Name,Sum(bytes)/...

程序员必背单词1_菜鸟腾飞的博客-程序员秘密_程序员必背单词

英语是程序员必备的一项技能,提高英语从单词开始,下面分享今天的单词 application 应用程式 应用、应用程序 application framework 应用程式框架、应用框架 应用程序框架 architecture 架构、系统架构 体系结构 argument 引数(传给函式的值)。叁见 parameter 叁数、实质叁数、实叁、自变量 array 阵列 数组 arrow ope

kali工具之Beef_wulanlin的博客-程序员秘密

*本工具仅供技术分享、交流讨论,严禁用于非法用途。简介Browser Exploitation Framework(BeEF) BeEF是日前最强大的浏览器开源渗透测试框架,通过X55漏洞配合JS脚本和 Metasploit进行渗透; BeEF是基于Ruby语言编写的,并且支持图形化界面,操作简单主要功能信息收集:1.网络发现2.主机信息3.Cookie获取4.会话劫持5.键盘记录6.插件信息持久化控制:1.确认弹框2.小窗口3.中间人社会工程:1

Mysql优化系列(1)--Innodb引擎下mysql自身配置优化_weixin_33923762的博客-程序员秘密

1.简单介绍InnoDB给MySQL提供了具有提交,回滚和崩溃恢复能力的事务安全(ACID兼容)存储引擎。InnoDB锁定在行级并且也在SELECT语句提供一个Oracle风格一致的非锁定读。这些特色增加了多用户部署和性能。没有在InnoDB中扩大锁定的需要,因为在InnoDB中行级锁定适合非常小的空间。InnoDB也支持FOREIGN KEY强...

服务器硬盘挂载(永久挂载UUID)_行万里路大于读万卷书的博客-程序员秘密_uuid挂载

1. lsblk命令可以清晰的获取全局的块设备布局,如果未挂载,moutpoint点是空的。该命令会显示服务器上所有的硬盘,包含未挂载的。 df -h 命令 只显示挂载的硬盘概况 2. 查看未挂载硬盘的UUIDls -l /dev/disk/by-uuid/ 获取UUID3.vi编辑/etc/fstab文件系统信息,在最后加入未挂载硬盘信息。挂载信息编写遵循这些字段《file system》 《mount point》 《type》 《options》 ...

随便推点

程序员是这样炼成的(5)-海纳百川_火山哥的博客-程序员秘密

      做程序员要"海纳百川",其实就是建议各位要做一个通才。当然做通才是有条件的,我总结了下前提有三:1.你已经是一个专才。熟练操作学一门像样的编程语言。2.有稳定的工作和收入支持。3.想得更多的挑战和机会。      作为项目经理和管理者而言,坦白的说,比较喜欢的还是专才,因为专才听话,你在他知晓的领域划一个圈,他能保证帮你完成任务,而且还不给你添麻烦,专才们在各自的领域的努力才会

nginx的五种负载均衡算法_parameter_的博客-程序员秘密_nginx负载均衡的算法

1.轮询 其nginx.conf文件编写如下upstream test {server 172.25.40.1:80;servse 172.25.40.2:8080;}可选择是否用于后备’backup’ 轮询的方法是通过按照时间顺序将请求往不同的后端服务器发送,来缓解服务器的压力,如果后台的某个服务器down掉了,则剔除它,可以设置权重,来分配访问的频率。 2.权重轮询 其nginx.

BLE-NRF51822教程3-sdk程序框架剖析_lilifang_2011的博客-程序员秘密

【IT168 技术】本讲为框架介绍,不会牵涉到太多代码细节。51822的官方SDK其实是没有框架依耐性的。什么叫框架,比如TI的BLE SDK中就有一个操作系统抽象层(OSAL)他是一个轮训的调度。你需要按照他的方式去创建任务等等。  而51822的SDK本质上只是提供了各种调用接口,比如开启初始化协议栈,初始化一些硬件功能模块,开始广播,发起链接等等。这些接口怎么用完全取决于自己。不过一

bzoj 2002 [Hnoi2010]Bounce 弹飞绵羊 [分块][特殊处理]_Freddddddddddd的博客-程序员秘密

[Hnoi2010]Bounce 弹飞绵羊Description某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被

[EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART1——为什么要使用Unity?..._baibi6400的博客-程序员秘密

今天继续微软企业库5.0的学习之路,今天将介绍微软企业库的重要模块——Unity。本篇文章将主要介绍:1、Unity模块的相关基本知识。2、为什么要使用Unity?3、在什么情况下需要使用Unity。4、Unity学习资源推荐一、Unity模块的相关基本知识在企业库4.0版本中,patterns &amp; practices小组对整...

记录关于IDEA的idea64.exe.vmoptions文件使用的误区_luffylv的博客-程序员秘密

我电脑中安装的是IDEA 2017.2.5 64位的这个版本,在IDEA安装目录下的bin目录下有一个idea64.exe.vmoptions文件。如下图:该文件的内容如下:我以为修改该文件中的-Xms和-Xmx参数可以改变程序运行时的堆内存大小。但是无论怎么修改都生效不了。做过如下尝试:点击功能栏中Help-&gt;Edit Custom VM Options,是的在用户目录中产生一份idea64.exe.vmoptions,修改该文件的内容——失败。在运行配置中新增环境变量:IDEA

推荐文章

热门文章

相关标签