转载自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> 网络通信权限

        
           

    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 params = new HashMap();            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 params, String encoding) throws Exception {        List pairs = new ArrayList();        if (params != null && !params.isEmpty()) {            for (Map.Entry 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正确,即可正常访问。

  客户端截图:测试成功

           

  服务器端截图:测试成功

  

 


源码下载 

 




更多相关文章

  1. Android读取JSON格式数据
  2. ProGuard代码混淆详细攻略
  3. 在android 输出log 信息 用于调试
  4. Android Day03-SQLite数据库操作及ListView详解
  5. Android联系人数据库全解析-2.0以上
  6. Android 在代码中同时给控件设置圆角和背景色
  7. Android webview调用js代码无效 webView.loadUrl("javascript:al

随机推荐

  1. Android 学习 之 关闭应用程序的方法
  2. Android(安卓)RecyclerView聊天界面控件
  3. 分享一款android的日历组件
  4. android 系统广播
  5. Android(安卓)汉字的正则表达式
  6. Android中调用系统摄像并且保存到指定位
  7. android中各种数据类型之间转换
  8. Android(安卓)6.0关于权限的问题
  9. 记录来电
  10. Android(安卓)APK瘦身实践