«

Android应用与Servlet进行数据交互

时间:2024-3-2 17:57     作者:韩俊     分类: Android


我们生在一个移动互联网的时代,强大的移动互联网让我们通过手机app可以随时随地与外界保持联通。所以android中少不了与服务器之间进行数据的交互,今天模拟一下app与服务器进行数据交互。如何模拟呢,就是写一个简单的用户登录与注册的程序。在这个程序中,用户登录时,手机app得到用户的输入,然后向服务器提交数据,服务器得到数据以后在数据库中进行查找,如何找到结果就向客户端发送数据,代表登录成功。用户注册时,手机app得到用户的输入,然后向服务器提交数据,服务器得到数据后先检查该用户名是否注册,如果未注册,则向数据库插入新的数据,如果已经注册,则通知用户已经注册。

手机app向服务器提交数据的形式多种多样。比如以地址参数的形式提交,参数较少时使用GET方式,参数较多时则用POST方式。如果参数特别多,也可以在客户端将参数整理成一个xml文件,将文件直接上传到服务器,服务器再进行解析就可以啦。当然也可以以JSON数据格式发送。此次程序中因为参数比较少,就使用最简单的GET方式,把用户的输入以地址参数的形式提交到服务器。

当然,双方要提前约定好地址参数提交时的格式。此次程序中包含三个参数,依次为requestType、userName、passWord。requestType为请求的方式,其值为“login”和“regist”,服务器会根据这些值来进行不同的操作,userName代表用户名,passWord代表用户密码。服务器向客户端的应答为“”success“或”failure“。用户登录时,”success“代表登录成功,”failure“代表用户名或密码错误。用户注册时,”success“代表注册成功,”failure“代表用户名已存在。听起来好像比较简单,是因为此次提交的参数不多,而且应答也比较简单,客户端和服务器端的代码由一个人来完成。如果做真正的项目时,提交的参数非常多,应答也会非常多,客户端与服务器端的代码由不同的人来完成,那么双方就要把通信协议以明文的形式写出来,xml文件中的节点以及代表的含义也要写的非常清楚,这样双方或者多方才能协调的工作。

开始写代码。

MainActivity中非常简单,只有两个button,负责启动登录页和注册页。这是MainActivity的界面以及代码


MainActivity:

package com.sunnix.main;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
    private Button mLoginButton;
    private Button mRegistButton;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mLoginButton=(Button)findViewById(R.id.loginButtonId);
        mRegistButton=(Button)findViewById(R.id.registButtonId);
        mLoginButton.setOnClickListener(new ButtonListener(1));
        mRegistButton.setOnClickListener(new ButtonListener(2));
    }
    class ButtonListener implements OnClickListener{
        int i;
        public ButtonListener(int i){
            this.i=i;
        }
        @Override
        public void onClick(View arg0) {
            if(i==1){
                Intent intent=new Intent(MainActivity.this, LoginActivity.class);
                startActivity(intent);
            }else if(i==2){
                Intent intent=new Intent(MainActivity.this, RegistActivity.class);
                startActivity(intent);
            }           
        }   
    }   
}

在定义两个button的监听器时偷了懒,本来生成一个对象就可以了,在onClick方法中区分两个button,在这里生成了两个对象,用构造函数传入的int参数来区分两个button。还有一个问题就是为了方便起见采取了硬编码的方式,”1“和”2“应该在常量类中定义好,以增加程序的可读性。

接下来是登录界面

LoginActivity:

package com.sunnix.main;
import com.sunnix.thread.UploadThread;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class LoginActivity extends Activity{
    private EditText mUserNameEditText;
    private EditText mPassWordEditText;
    private Button mCancelButton;
    private Button mLoginButton;
    public static MyResultHandler mResultHandler;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.activity_login);
        initView();
        super.onCreate(savedInstanceState);
    }
    private void initView(){
        mResultHandler=new MyResultHandler();
        mUserNameEditText=(EditText)findViewById(R.id.loUserNameEditId);
        mPassWordEditText=(EditText)findViewById(R.id.loPassWordEditId);
        mCancelButton=(Button)findViewById(R.id.loCancelButtonId);
        mLoginButton=(Button)findViewById(R.id.loLoginButtonId);
        mCancelButton.setOnClickListener(new ButtonListener(1));
        mLoginButton.setOnClickListener(new ButtonListener(2));     
    }
    class ButtonListener implements OnClickListener{
        int i;
        public ButtonListener(int i){
            this.i=i;
        }
        @Override
        public void onClick(View arg0) {
            String userName=mUserNameEditText.getText().toString();
            String passWord=mPassWordEditText.getText().toString();         
            if(i==1){
                LoginActivity.this.finish();
            }else if(i==2){
                if(userName.equals("")|passWord.equals("")){
                    Toast.makeText(LoginActivity.this, "用户名或密码不能为空", 
                                    Toast.LENGTH_SHORT).show();//判断一下输入是否为空
                }else{
                    new UploadThread("login", userName, passWord).start();//启动访问服务器的线程
                }               
            }                       
        }       
    }
    public class MyResultHandler extends Handler{<span style="white-space:pre"> //接收从线程发回的消息
        @Override
        public void handleMessage(Message msg) {
            String result=msg.obj.toString();
            if(result.equals("success")){<span style="white-space:pre">   //服务器的应答已经提前规定好
                Toast.makeText(LoginActivity.this, "恭喜你登录成功,两秒后返回", 
                                Toast.LENGTH_SHORT).show();
                Handler handler=new Handler();
                handler.postDelayed(finishActivity, 2000);//延迟两秒,关闭这个Activity
            }else if(result.equals("failure")){
                Toast.makeText(LoginActivity.this, "用户或密码错误", 
                                Toast.LENGTH_SHORT).show();
            }
            super.handleMessage(msg);
        }       
    }
    Runnable finishActivity=new Runnable() {    //延迟两秒,关闭这个Activity 
        @Override
        public void run() {
            LoginActivity.this.finish();            
        }
    };
}
注册界面以及代码:

RegistActivity:

package com.sunnix.main;
import com.sunnix.thread.UploadThread;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class RegistActivity extends Activity{
    private EditText mUserNameEditText;
    private EditText mPassWordEditText;
    private EditText mEnsurePassWordEditText;
    private Button mCancelButton;
    private Button mRegistButton;
    public static MyResultHandler mResultHandler;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.activity_regist);
        initView();
        super.onCreate(savedInstanceState);
    }
    private void initView(){
        mResultHandler=new MyResultHandler();
        mUserNameEditText=(EditText)findViewById(R.id.reUserNameEditId);
        mPassWordEditText=(EditText)findViewById(R.id.rePassWordEditId);
        mEnsurePassWordEditText=(EditText)findViewById(R.id.reEnsurePassWordEditId);
        mCancelButton=(Button)findViewById(R.id.reCancelButtonId);
        mRegistButton=(Button)findViewById(R.id.reRegistButtonId);
        mCancelButton.setOnClickListener(new ButtonListener(1));
        mRegistButton.setOnClickListener(new ButtonListener(2));
    }
    class ButtonListener implements OnClickListener{
        int i;
        public ButtonListener(int i){
            this.i=i;
        }
        @Override
        public void onClick(View arg0) {
            String userName=mUserNameEditText.getText().toString();
            String passWord=mPassWordEditText.getText().toString();
            if(i==1){
                RegistActivity.this.finish();
            }else if(i==2){
                if(userName.equals("")|passWord.equals("")){
                    Toast.makeText(RegistActivity.this, "用户名或密码不能为空", 
                            Toast.LENGTH_SHORT).show();
                }else{
                    if(!(passWord.equals(mPassWordEditText.getText().toString()))){
                        Toast.makeText(RegistActivity.this, "两次输入的密码不一致,请重新输入", 
                                Toast.LENGTH_SHORT).show();
                    }else{
                        new UploadThread("regist", userName, passWord).start();
                    }
                }
            }           
        }       
    }
    public class MyResultHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            String result=msg.obj.toString();
            if(result.equals("success")){
                Toast.makeText(RegistActivity.this, "恭喜你注册成功,两秒后返回", 
                        Toast.LENGTH_SHORT).show();
                Handler handler=new Handler();
                handler.postDelayed(finishActivity, 2000);
            }else if(result.equals("failure")){
                Toast.makeText(RegistActivity.this, "对不起用户已存在,注册失败", 
                        Toast.LENGTH_SHORT).show();
            }
            super.handleMessage(msg);
        }       
    }
    Runnable finishActivity=new Runnable() {        
        @Override
        public void run() {
            RegistActivity.this.finish();           
        }
    };
}
LoginActivity与RegistActivity中的代码都非常简单。接下来看app如何向服务器提交数据以及得到应答:

UploadThread:

package com.sunnix.thread;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import android.os.Message;
import com.sunnix.constant.Const;
import com.sunnix.main.LoginActivity;
import com.sunnix.main.RegistActivity;
public class UploadThread extends Thread{
    private String mRequestType;
    private String mUserName;
    private String mPassWord;
    private String mServiceUrl;
    public UploadThread(String requestType,String userName,String passWord){//构造函数,用来接收参数与生成地址
        this.mRequestType=requestType;
        this.mUserName=userName;
        this.mPassWord=passWord;
        if(!(mRequestType.equals("")|mUserName.equals("")|mPassWord.equals(""))){
            mServiceUrl=Const.SERVICE_URL+"?requestType="+mRequestType+"&userName="+
                        mUserName+"&passWord="+mPassWord;
        }//生成地址的方式有很多种,这次因此参数比较少,就直接拼凑了,Const.SERVICE_URL保存的是servlet服务器的地址

    }
    @Override
    public void run() {
        String result="";
        URL url=null;
        HttpURLConnection conn=null;
        try {
            url =new URL(mServiceUrl);
            conn=(HttpURLConnection)url.openConnection();
            if(conn.getResponseCode()==200){
                DataInputStream dis=new DataInputStream(conn.getInputStream());//得到服务器的应答
                result=dis.readUTF();
                dis.close();
            }
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        Message msg;
        if(mRequestType.equals("login")){//根据mRequestType的值来判断给哪个Activity发消息
            msg=LoginActivity.mResultHandler.obtainMessage();
            msg.obj=result;//将服务器的应答保存在消息中
            LoginActivity.mResultHandler.sendMessage(msg);//给不同的Activity发消息
        }else if(mRequestType.equals("regist")){
            msg=RegistActivity.mResultHandler.obtainMessage();
            msg.obj=result;
            RegistActivity.mResultHandler.sendMessage(msg);
        }
        super.run();
    }   
}
下面是服务器中的代码:
public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String type=request.getParameter("requestType");
        if(type.equals("login")){
            login(request, response);
        }else if(type.equals("regist")){
            regist(request, response);
        }

首先得到requestType中的参数,根据参数值不同来区分是执行登录操作还是注册操作,下面是登录操作
public void login(HttpServletRequest request, HttpServletResponse response){
        String userName=request.getParameter("userName");
        String passWord=request.getParameter("passWord");
        String result="";
        Connection conn=getConn();
        PreparedStatement pstmt=null;
        ResultSet rs=null;
        try {
            String sql="SELECT username FROM user WHERE username=? AND password=?";//sql语句
            pstmt=conn.prepareStatement(sql);
            pstmt.setString(1, userName);//设置参数
            pstmt.setString(2, passWord);
            rs=pstmt.executeQuery();
            if(rs.next()){
                result="success";//如果有返回值则代表成功
            }else{
                result="failure";//负责代表失败
            }
        }catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        DataOutputStream dos;
        try {
            dos = new DataOutputStream(response.getOutputStream());//打开输出流,给客户端做出应答
            dos.writeUTF(result);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }       
    }

下面是注册的操作:
public void regist(HttpServletRequest request, HttpServletResponse response){
        String result="";
        String userName=request.getParameter("userName");
        String passWord=request.getParameter("passWord");
        Connection conn=getConn();
        ResultSet rs=null;
        PreparedStatement pstmtQuery=null;
        PreparedStatement pstmtInsert=null;
        try {
            String sqlQuery="SELECT username FROM user WHERE username=?";
            pstmtQuery=conn.prepareStatement(sqlQuery);
            pstmtQuery.setString(1, userName);
            rs=pstmtQuery.executeQuery();
            if(!rs.next()){//如果数据库中没有记录,代表该用户名可以注册
                String sql="INSERT INTO user (username,password) VALUES (?,?)";
                pstmtInsert=conn.prepareStatement(sql);
                pstmtInsert.setString(1, userName);
                pstmtInsert.setString(2, passWord);
                pstmtInsert.executeUpdate();
                result="success";
            }else{      //否则代表该用户已注册
                result="failure";
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        DataOutputStream dos;
        try {
            dos = new DataOutputStream(response.getOutputStream());//打开输出流,给客户端做出应答
            dos.writeUTF(result);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
此次使用的是MySQL数据库,连接数据库时需要将mysql-connector-java-5.1.18-bin.jar放在tomcat服务器lib目录下,下面做一下测试,首先注册一个用户

为了方便起见,密码没有使用密文形式,查看起来比较方便。这时查看一下数据库中是否有数据



最后一行已经有了注册的用户,这时如果再注册


提示用户名已存在,登录一下



登录成功,如果随便输一个用户名和密码

提示用户名或密码错误。

到这里就这结束了,还有就是app中需要添加相应的访问网络的权限,如果是自己电脑上装的tomcat服务器,手机需要连接wifi,和电脑连在同一个路由上。



标签: android

热门推荐