一口气看完一个项目源码(一)之用户注册

今天咋们看的这个项目源码是一个微博客户端,和服务端通讯用socket写的,项目名称:口袋微博,和前面那个项目不同,这个项目略难一点,不过没关系,让我们一起来学习学习吧。

         按照使用流程,首先是注册页面,因此我们来写注册页面,先把注册页面的布局写了:

Xml代码  
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout  
  3.        xmlns:android="http://schemas.android.com/apk/res/android"  
  4.        android:orientation="vertical"  
  5.        android:gravity="center_horizontal"  
  6.        android:background="@drawable/back"  
  7.        android:paddingTop="25px"  
  8.        android:layout_width="fill_parent"  
  9.        android:layout_height="fill_parent"  
  10.        >                                                                                          <!-- 声明一个线性布局 -->  
  11.        <LinearLayout  
  12.               android:orientation="horizontal"  
  13.               android:layout_width="wrap_content"  
  14.               android:layout_height="wrap_content"       
  15.               >                                                                                   <!-- 声明一个显示昵称的线性布局 -->  
  16.               <TextView  
  17.                      android:text="@string/tvName"  
  18.                      android:layout_width="100px"  
  19.                      style="@style/text"  
  20.                      android:layout_height="wrap_content"  
  21.                      android:layout_gravity="center_vertical"  
  22.                      />  
  23.               <EditText  
  24.                      android:id="@+id/etName"  
  25.                      android:singleLine="true"  
  26.                      android:layout_width="160px"  
  27.                      android:layout_height="wrap_content"  
  28.                      />  
  29.               </LinearLayout>  
  30.        <LinearLayout  
  31.               android:orientation="horizontal"  
  32.               android:layout_width="wrap_content"  
  33.               android:layout_height="wrap_content"  
  34.               >                                                                                   <!-- 声明显示密码的线性布局 -->  
  35.               <TextView  
  36.                      android:text="@string/tvPwd"  
  37.                      style="@style/text"  
  38.                      android:layout_width="100px"  
  39.                      android:layout_height="wrap_content"  
  40.                      android:layout_gravity="center_vertical"  
  41.                      />  
  42.               <EditText  
  43.                      android:id="@+id/etPwd1"  
  44.                      android:singleLine="true"  
  45.                      android:password="true"  
  46.                      android:layout_width="160px"  
  47.                      android:layout_height="wrap_content"  
  48.                      />  
  49.               </LinearLayout>  
  50.        <LinearLayout  
  51.               android:orientation="horizontal"  
  52.               android:layout_width="wrap_content"  
  53.               android:layout_height="wrap_content"  
  54.               >                                                                            <!-- 声明显示确认密码的线性布局 -->  
  55.               <TextView  
  56.                      android:text="@string/tvPwd2"  
  57.                      style="@style/text"  
  58.                      android:layout_width="100px"  
  59.                      android:layout_height="wrap_content"  
  60.                      android:layout_gravity="center_vertical"  
  61.                      />                                                                    <!-- 声明TextView控件 -->  
  62.               <EditText  
  63.                      android:id="@+id/etPwd2"  
  64.                      android:singleLine="true"  
  65.                      android:password="true"  
  66.                      android:layout_width="160px"  
  67.                      android:layout_height="wrap_content"  
  68.                      />                                                                    <!-- 声明输入确认密码EditText控件 -->  
  69.               </LinearLayout>  
  70.        <LinearLayout  
  71.               android:orientation="horizontal"  
  72.               android:layout_width="wrap_content"  
  73.               android:layout_height="wrap_content"  
  74.               >                                                                            <!-- 声明包含Email输入的线性布局 -->  
  75.               <TextView  
  76.                      android:text="@string/tvEmail"  
  77.                      style="@style/text"  
  78.                      android:layout_width="100px"  
  79.                      android:layout_height="wrap_content"  
  80.                      android:layout_gravity="center_vertical"  
  81.                      />  
  82.               <EditText  
  83.                      android:id="@+id/etEmail"  
  84.                      android:singleLine="true"  
  85.                      android:layout_width="160px"  
  86.                      android:layout_height="wrap_content"  
  87.                      />  
  88.               </LinearLayout>  
  89.        <LinearLayout  
  90.               android:orientation="horizontal"  
  91.               android:layout_width="wrap_content"  
  92.               android:layout_height="wrap_content"  
  93.               >                                                                            <!-- 声明包含心情输入的线性布局 -->  
  94.               <TextView  
  95.                      android:text="@string/tvStatus"  
  96.                      style="@style/text"  
  97.                      android:layout_width="100px"  
  98.                      android:layout_height="wrap_content"  
  99.                      android:layout_gravity="center_vertical"  
  100.                      />  
  101.               <EditText  
  102.                      android:id="@+id/etStatus"  
  103.                      android:singleLine="true"  
  104.                      android:text="@string/etStatus"  
  105.                      android:layout_width="160px"  
  106.                      android:layout_height="wrap_content"  
  107.                      />  
  108.               </LinearLayout>  
  109.        <LinearLayout  
  110.               android:orientation="horizontal"  
  111.               android:layout_width="wrap_content"  
  112.               android:layout_height="wrap_content"  
  113.               >  
  114.               <Button  
  115.                      android:id="@+id/btnReg"  
  116.                      style="@style/button"  
  117.                      android:layout_width="120px"  
  118.                      android:layout_height="wrap_content"  
  119.                      android:text="@string/btnReg"  
  120.                      />  
  121.               <Button  
  122.                      android:id="@+id/btnBack"  
  123.                      style="@style/button"  
  124.                      android:layout_width="120px"  
  125.                      android:layout_height="wrap_content"  
  126.                      android:text="@string/btnBack"  
  127.                      />  
  128.               </LinearLayout>  
  129.        <LinearLayout  
  130.               android:orientation="vertical"  
  131.               android:visibility="visible"  
  132.               android:id="@+id/regResult"  
  133.               android:layout_width="wrap_content"  
  134.               android:layout_height="wrap_content"  
  135.               >  
  136.               <LinearLayout  
  137.                      android:orientation="horizontal"  
  138.                      android:layout_width="wrap_content"  
  139.                      android:layout_height="wrap_content"  
  140.                      >  
  141.                      <TextView  
  142.                             android:text="@string/regSuccess"  
  143.                             style="@style/text"  
  144.                             android:layout_width="wrap_content"  
  145.                             android:layout_height="wrap_content"  
  146.                             />  
  147.                      <EditText  
  148.                             android:id="@+id/etUno"  
  149.                             android:layout_width="wrap_content"  
  150.                             android:layout_height="wrap_content"  
  151.                             android:cursorVisible="false"  
  152.                             />  
  153.                      </LinearLayout>  
  154.               <Button  
  155.                      android:id="@+id/btnEnter"  
  156.                      style="@style/text"  
  157.                      android:layout_gravity="right"  
  158.                      android:text="@string/btnEnter"  
  159.                      android:layout_width="wrap_content"  
  160.                      android:layout_height="wrap_content"  
  161.                      />  
  162.               </LinearLayout>  
  163. </LinearLayout>  

布局写好以后,我们需要给这些布局添加点击事件(主要是注册),通过自定义一个MyConnection指定地址和端口号连接socket得到DataOutputStream和一个DataInputStream,把要发送的注册信息封装好(这里封装用的是消息头+分隔符的形式)把消息发给服务端,然后通过DataInputStream读取服务端返回的结果,如果服务端返回结果的请求头为<#REG_SUCCESS#>代表注册成功,同时用一个变量记住返回的结果,否则就是注册失败。

注册代码如下:

Java代码  
  1. /** 
  2.      * 方法:连接服务器,进行注册 
  3.      */  
  4.     public void register(){  
  5.        new Thread(){  
  6.            public void run(){  
  7.               Looper.prepare();  
  8.               //1.获得用户输入的数据并进行验证  
  9.               EditText etName = (EditText)findViewById(R.id.etName);         //获得昵称EditText对象  
  10.               EditText etPwd1 = (EditText)findViewById(R.id.etPwd1);         //获得密码EditText对象  
  11.               EditText etPwd2 = (EditText)findViewById(R.id.etPwd2);         //获得确认密码EditText对象  
  12.               EditText etEmail = (EditText)findViewById(R.id.etEmail);       //获得邮箱EditText对象  
  13.               EditText etStatus = (EditText)findViewById(R.id.etStatus);     //获得心情EditText对象  
  14.               String name = etName.getEditableText().toString().trim();      //获得昵称  
  15.               String pwd1 = etPwd1.getEditableText().toString().trim();      //获得密码  
  16.               String pwd2 = etPwd2.getEditableText().toString().trim();      //获得确认密码  
  17.               String email = etEmail.getEditableText().toString().trim();    //获得邮箱  
  18.               String status = etStatus.getEditableText().toString().trim();  //获得状态  
  19.               if(name.equals("") || pwd1.equals("") || pwd2.equals("") || email.equals("") || status.equals("")){  
  20.                   Toast.makeText(RegActivity.this, "请将注册信息填写完整", Toast.LENGTH_LONG).show();  
  21.                   return;  
  22.               }  
  23.               if(!pwd1.equals(pwd2)){            //判断两次输入的密码是否一致  
  24.                   Toast.makeText(RegActivity.this, "两次输入的密码不一致!", Toast.LENGTH_LONG).show();  
  25.                   return;  
  26.               }  
  27.               //2.连接服务器开始传数据  
  28.               try{  
  29.                   mc = new MyConnector(SERVER_ADDRESS, SERVER_PORT);  
  30.                   String regInfo = "<#REGISTER#>"+name+"|"+pwd1+"|"+email+"|"+status;  
  31.                   mc.dout.writeUTF(regInfo);  
  32.                   String result = mc.din.readUTF();  
  33.                   pd.dismiss();  
  34.                   if(result.startsWith("<#REG_SUCCESS#>")){     //返回信息为注册成功  
  35.                      result= result.substring(15);      //去掉信息头  
  36.                      uno = result;            //记录用户的ID  
  37.                      myHandler.sendEmptyMessage(0);            //发出Handler消息  
  38.                      Toast.makeText(RegActivity.this, "注册成功!", Toast.LENGTH_LONG).show();  
  39.                   }  
  40.                   else{      //注册失败  
  41.                      Toast.makeText(RegActivity.this, "注册失败!请重试!", Toast.LENGTH_LONG).show();  
  42.                   }  
  43.               }  
  44.               catch(Exception e){  
  45.                   e.printStackTrace();  
  46.               }  
  47.            }  
  48.        }.start();  
  49.     }  

 接下来我们来写服务端的代码,因为服务端用的socket,因此需要一个入口函数,这个入口在Server.java文件中,通过它开启一个服务线程:

Java代码  
  1. public class Server{  
  2.     public static void main(String args[]){  
  3.         try{  
  4.             ServerSocket ss = new ServerSocket(8888);  
  5.             ServerThread st = new ServerThread(ss);  
  6.             st.start();  
  7.             System.out.println("Listening...");  
  8.         }catch(Exception e){  
  9.             e.printStackTrace();  
  10.         }  
  11.     }  
  12. }  

 我们转到这个线程类里面,发现实现是通过调用serverSocket的accept()方法,监听客户端请求。对于请求过来的数据,专门写一个代理类ServerAgent.java来处理。

Java代码  
  1. package wpf;  
  2.   
  3. import java.net.ServerSocket;  
  4. import java.net.Socket;  
  5. import java.net.SocketException;  
  6.   
  7. public class ServerThread extends Thread{  
  8.     public ServerSocket ss;     //声明ServerSocket对象  
  9.     public boolean flag = false;  
  10.       
  11.     public ServerThread(ServerSocket ss){   //构造器  
  12.         this.ss = ss;     
  13.         flag = true;  
  14.     }  
  15.     public void run(){  
  16.         while(flag){  
  17.             try{  
  18.                 Socket socket = ss.accept();  
  19.                 ServerAgent sa = new ServerAgent(socket);  
  20.                 sa.start();  
  21.             }  
  22.             catch(SocketException se){  
  23.                 try{  
  24.                     ss.close();  
  25.                     ss = null;  
  26.                     System.out.println("ServerSocket closed");  
  27.                 }catch(Exception ee){  
  28.                     ee.printStackTrace();  
  29.                 }  
  30.             }  
  31.             catch(Exception e){  
  32.                 e.printStackTrace();  
  33.             }  
  34.         }  
  35.     }  
  36. }  

 我们来看ServerAgent是怎么实现的。

代理线程通过构造函数拿到数据输入和输出流,然后在run方法里面处理用户请求。接下来就是对请求头的判断,我们这里先只讲注册请求,收到的是注册请求,解析用户发过来的数据,然后通过写一个数据库工具类DBUtil类处理用户发送过来的数据。并将处理结果返回给客户端,然后客户端通过判断从服务器获取的请求结果更新ui界面。两个主要的方法:

Java代码  
  1. public ServerAgent(Socket socket){  
  2.        this.socket = socket;  
  3.        try {  
  4.            this.din = new DataInputStream(socket.getInputStream());  
  5.            this.dout = new DataOutputStream(socket.getOutputStream());  
  6.            flag =true;  
  7.        } catch (IOException e) {  
  8.            e.printStackTrace();  
  9.        }  
  10.     }  
  11.    
  12. public void run(){  
  13.        while(flag){  
  14.            try {  
  15.               String msg = din.readUTF();        //接收客户端发来的消息  
  16. //            System.out.println("收到的消息是:"+msg);  
  17. if(msg.startsWith("<#REGISTER#>")){           //消息为用户注册  
  18.                   msg = msg.substring(12); //获得字符串值  
  19.                   String [] sa = msg.split("\|");   //切割字符串  
  20.                   String regResult = DBUtil.registerUser(sa[0], sa[1], sa[2], sa[3], "1");  
  21.                   if(regResult.equals(REGISTER_FAIL)){      //注册失败  
  22.                      dout.writeUTF("<#REG_FAIL#>");  
  23.                   }  
  24.                   else{  
  25.                      dout.writeUTF("<#REG_SUCCESS#>"+regResult);  
  26.                   }  
  27.               }  
  28. }  

于是,我们转到DbUtil类里面,看书怎么保存到数据库中的。我们发现存储使用一般存储方式,只是里面有设置存储编码方式,还用到了prepareStatement。处理结束返回处理结果,如果连接为null返回连接失败,如果保存到数据库成功就返回注册完的用户id,否则返回注册失败。完了之后不要忘了释放资源。

//方法:注册用户

   

Java代码  
  1. public static String registerUser(String u_name,String u_pwd,String u_email,String u_state,String h_id){  
  2.       String result=null;  
  3.       Connection con = null;      //声明数据库连接对象  
  4.       PreparedStatement ps = null;       //声明语句对象  
  5.       try{  
  6.           con = getConnection();  
  7.           if(con == null){         //判断是否成功获取连接  
  8.              result = CONNECTION_OUT;  
  9.              return result;       //返回方法的执行  
  10.           }  
  11.           ps = con.prepareStatement("insert into user(u_no,u_name,u_pwd,u_email,u_state,h_id)" +  
  12.                  "values(?,?,?,?,?,?)");     //构建SQL语句  
  13.           String u_no = String.valueOf(getMax(USER));   //获得分配给用户的帐号  
  14.           u_name = new String(u_name.getBytes(),"ISO-8859-1");    //转成ISO-8859-1以插入数据库  
  15.           u_state = new String(u_state.getBytes(),"ISO-8859-1");      //转成ISO-8859-1以插入数据库  
  16.           int no = Integer.valueOf(u_no);  
  17.           int hid = Integer.valueOf(h_id);  
  18.           ps.setInt(1, no);        //设置PreparedStatement的参数  
  19.           ps.setString(2, u_name);  
  20.           ps.setString(3, u_pwd);  
  21.           ps.setString(4, u_email);  
  22.           ps.setString(5, u_state);  
  23.           ps.setInt(6,hid);  
  24.           int count = ps.executeUpdate();        //执行插入  
  25.           if(count == 1){      //如果插入成功  
  26.              result = u_no;       //获得玩家的帐号  
  27.           }  
  28.           else{                    //如果没有插入数据  
  29.              result = REGISTER_FAIL;     //获得出错信息  
  30.           }  
  31.       }catch(Exception e){  
  32.           e.printStackTrace();  
  33.       }  
  34.       finally{  
  35.           try{  
  36.              if(ps != null){  
  37.                  ps.close();  
  38.                  ps = null;  
  39.              }  
  40.           }catch(Exception e){  
  41.              e.printStackTrace();  
  42.           }  
  43.           try{  
  44.              if(con != null){  
  45.                  con.close();  
  46.                  con = null;  
  47.              }  
  48.           }catch(Exception e){  
  49.              e.printStackTrace();  
  50.           }  
  51.       }  
  52.       return result;  
  53.    }  

 接下来便是客户端处理服务端返回数据:

客户端处理完服务端发过来的数据,就通过handler更新界面,让进入个人中心这个按钮可见,同时拿到用户id转到个人中心页面。这样,一个用户注册的模块写好了。

Java代码  
  1. Handler myHandler = new Handler(){  
  2.        @Override  
  3.        public void handleMessage(Message msg) {  
  4.            switch(msg.what){  
  5.            case 0:        
  6.               View linearLayout = (LinearLayout)findViewById(R.id.regResult);    //获得线性布局  
  7.               linearLayout.setVisibility(View.VISIBLE);     //设置可见性  
  8.               EditText etUno = (EditText)findViewById(R.id.etUno);  
  9.               etUno.setText(uno);       
  10.               break;  
  11.            }  
  12.            super.handleMessage(msg);  
  13.        }  
  14.     };  

 下一篇介绍用户登录时如何实现的。

原文地址:https://www.cnblogs.com/xiaochao1234/p/4167374.html