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


    今天咋们看的这个项目源码是一个微博客户端,和服务端通讯用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.     };  

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

  • 相关阅读:
    监控 Linux 性能的 18 个命令行工具
    VS2015中无法查找或打开 PDB 文件
    C1853 编译器错误:fatal error C1853: 'pjtname.pch' precompiled header file is from a previous
    malloc用法
    C语言中i++和++i的区别
    vs未定义的标识符“round”ceil()和floor()
    error C2065: “uint8_t”: 未声明的标识符
    strtol 函数用法
    C++ “string”: 未声明的标识符
    C++ 中c_str()函数
  • 原文地址:https://www.cnblogs.com/xiaochao1234/p/4167374.html
Copyright © 2020-2023  润新知