android与java web交互完成简单的登录和注册

   本文的知识点包括android客户端的网络编程、消息机制、IO流、多线程和java web服务器端的servlet、数据库操作、javabean技术、工具类和测试类的使用。

客户端

运行效果图


布局文件

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.ningxiaojian.clientlogindemo.MainActivity">

    <EditText
        android:id="@+id/et_username"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入登录账号"/>

    <EditText
        android:id="@+id/et_password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入登录密码"/>

    <Button
        android:id="@+id/bt_login"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="登录"
        android:onClick="login"/>

    <Button
        android:id="@+id/bt_register"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="注册"
        android:onClick="register"/>


</LinearLayout>
程序主入口
MainActivity

package com.ningxiaojian.clientlogindemo;

import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;

public class MainActivity extends AppCompatActivity {

    private EditText username;
    private EditText password;
    private String usernameStr;
    private String passwordStr;
    private final int LOGINSUCCESS=0;
    private final int LOGINNOTFOUND=1;
    private final int LOGINEXCEPT=2;
    private final int REGISTERSUCCESS=3;
    private final int REGISTERNOTFOUND=4;
    private final int REGISTEREXCEPT=5;

    @SuppressLint("HandlerLeak")
    Handler handler=new Handler(){//消息机制,用来在子线程中更新UI
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){//具体消息,具体显示
                case LOGINSUCCESS:
                    Toast.makeText(getApplicationContext(),(String)msg.obj,Toast.LENGTH_LONG).show();
                    break;
                case LOGINNOTFOUND:
                    Toast.makeText(getApplicationContext(),(String)msg.obj,Toast.LENGTH_LONG).show();
                    break;
                case LOGINEXCEPT:
                    Toast.makeText(getApplicationContext(),(String)msg.obj,Toast.LENGTH_LONG).show();
                    break;
                case REGISTERSUCCESS:
                    Toast.makeText(getApplicationContext(),(String)msg.obj,Toast.LENGTH_LONG).show();
                    break;
                case REGISTERNOTFOUND:
                    Toast.makeText(getApplicationContext(),(String)msg.obj,Toast.LENGTH_LONG).show();
                    break;
                case REGISTEREXCEPT:
                    Toast.makeText(getApplicationContext(),(String)msg.obj,Toast.LENGTH_LONG).show();
                    break;
            }
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //找到我们需要的控件
        username = (EditText) findViewById(R.id.et_username);
        password = (EditText) findViewById(R.id.et_password);


    }
    //登录按钮的点击事件,也可以用set监听器的方法,不过这种方法简单
    public void login(View v){
        //获取编辑框内的内容
        usernameStr = username.getText().toString().trim();
        passwordStr = password.getText().toString().trim();

        //判断是否输入为空(在这里就不再进行正则表达式判断了)
        if(usernameStr.equals("") || passwordStr.equals("")){
            Toast.makeText(MainActivity.this,"用户名或密码不能为空",Toast.LENGTH_SHORT).show();
        }//进行登录操作(联网操作要添加权限)
        else {
            //联网操作要开子线程,在主线程不能更新UI
            new Thread(){

                private HttpURLConnection connection;


                @Override
                public void run() {

                    try {
                        //封装成传输数据的键值对,无论get还是post,传输中文时都要进行url编码(RULEncoder)
                        // 如果是在浏览器端的话,它会自动进行帮我们转码,不用我们进行手动设置
                        String data2= "username="+ URLEncoder.encode(usernameStr,"utf-8")+"&password="+ URLEncoder.encode(passwordStr,"utf-8")+"&sign="+URLEncoder.encode("1","utf-8");
                        connection=HttpConnectionUtils.getConnection(data2);
                        int code = connection.getResponseCode();
                        if(code==200){
                            InputStream inputStream = connection.getInputStream();
                            String str = StreamChangeStrUtils.toChange(inputStream);//写个工具类流转换成字符串
                            Message message = Message.obtain();//更新UI就要向消息机制发送消息
                            message.what=LOGINSUCCESS;//用来标志是哪个消息
                            message.obj=str;//消息主体
                            handler.sendMessage(message);

                        }
                        else {
                            Message message = Message.obtain();
                            message.what=LOGINNOTFOUND;
                            message.obj="注册异常...请稍后再试";
                            handler.sendMessage(message);
                        }
                    } catch (Exception e) {//会抛出很多个异常,这里抓一个大的异常
                        e.printStackTrace();
                        Message message = Message.obtain();
                        message.what=LOGINEXCEPT;
                        message.obj="服务器异常...请稍后再试";
                        handler.sendMessage(message);
                    }
                }
            }.start();//不要忘记开线程
        }
    }
    //注册按钮的点击事件
    public void register(View v){
        usernameStr = username.getText().toString().trim();
        passwordStr = password.getText().toString().trim();
        if(usernameStr.equals("") || passwordStr.equals("")){
            Toast.makeText(MainActivity.this,"用户名或密码不能为空",Toast.LENGTH_SHORT).show();
        }
        else {
                new Thread(){

                    HttpURLConnection connection=null;
                    @Override
                    public void run() {
                        try {
                            String data= "username="+ URLEncoder.encode(usernameStr,"utf-8")+"&password="+ URLEncoder.encode(passwordStr,"utf-8")+"&sign="+URLEncoder.encode("2","utf-8");
                            connection=HttpConnectionUtils.getConnection(data);
                            int code = connection.getResponseCode();
                            if(code==200){
                                InputStream inputStream = connection.getInputStream();
                                String str = StreamChangeStrUtils.toChange(inputStream);
                                Message message = Message.obtain();
                                message.obj=str;
                                message.what=REGISTERSUCCESS;
                                handler.sendMessage(message);
                            }
                            else {
                                Message message = Message.obtain();
                                message.what=REGISTERNOTFOUND;
                                message.obj="注册异常...请稍后再试";
                                handler.sendMessage(message);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            Message message = Message.obtain();
                            message.what=REGISTEREXCEPT;
                            message.obj="服务器异常...请稍后再试";
                            handler.sendMessage(message);
                        }

                    }
                }.start();//不要忘记开线程

        }
    }
}

流转换成字符串的工具类
StreamChangeStrUtils
package com.ningxiaojian.clientlogindemo;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 流转换成字符串的工具类
 */

public class StreamChangeStrUtils {
    public static String toChange(InputStream inputStream) throws Exception {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();//数组流,在流的内部有个缓冲区,可以进行转换成字节
        //下面是属于io流的知识,在此不再赘述
        byte b[]=new byte[1024];
        int len=-1;
        while ((len=inputStream.read(b))!=-1){
            bos.write(b,0,len);
        }
        inputStream.close();//关闭流,数组流会自动关闭,关闭是否都可以
        String str = new String(bos.toByteArray());
        //服务器默认返回的是gbk,如果要在android端解决乱码,可以在此设置为gbk,一般提倡的是服务器解决
        // 让服务器给我们返回utf-8,因为在android本地默认的是utf-8
        return str;
    }
}

   联网工具类

HttpConnectionUtils

package com.ningxiaojian.clientlogindemo;

import android.os.Message;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLEncoder;

/**
 * 获取联网连接
 * Created by Justin on 2018/4/16.
 */

public class HttpConnectionUtils {
    public static HttpURLConnection getConnection(String data) throws Exception {

            //通过URL对象获取联网对象
            URL url= new URL("http://192.168.1.104:8080/AndroidLoginDemo/LoginServlet");
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");//设置post请求
            connection.setReadTimeout(5000);//设置5s的响应时间
            connection.setDoOutput(true);//允许输出
            connection.setDoInput(true);//允许输入
            //设置请求头,以键值对的方式传输(以下这两点在GET请求中不用设置)
            connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded ");
            connection.setRequestProperty("Content-Length",data.length()+"");//设置请求体的长度
            OutputStream outputStream = connection.getOutputStream();
            outputStream.write(data.getBytes());//进行传输操作
            //判断服务端返回的响应码,这里是http协议的内容
            return connection;
    }
}
   联网操作一定要在
AndroidManifest.xml加上权限
<uses-permission android:name="android.permission.INTERNET"/>

服务器端(Tomcat)

首先去mysql创建一个数据库,表结构如下
因为使用到mysql,所以要把jdbc的驱动类添加到webcontent->web-inf->lib中
mysql-connector-java-5.1.45-bin.jar

在eclipse创建以下包名

com.ningxiaojian.dao:dao层接口
com.ningxiaojian.dao.impl:dao层接口的实现
com.ningxiaojian.domain:javabean对象
com.ningxiaojian.service:逻辑层的接口
com.ningxiaojian.service.impl:逻辑层的实现
com.ningxiaojian.web.control:存放servlet
com.ningxiaojian.utils:存放工具类
com.ninxiaojian.test:存放测试类

创建java对象
User.java
package com.ningxiaojian.domain;

/**
 *
 *设置一个javabean对象,用来封装dao层取出的数据
 * @author Justin
 *
 */
public class User {
	private String username;
	private String password;
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	
}

dao层接口
UserDao.java
package com.ningxiaojian.dao;

import java.util.List;

import com.ningxiaojian.domain.User;

public interface UserDao {
	//找到所有元素,用来验证登录信息
	public  List<User> findAll();
	//插入元素,用来注册
	public void insertElement(User people);
	
}
dao层实现类
UserDaoImpl.java
package com.ningxiaojian.dao.impl;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.ningxiaojian.dao.UserDao;
import com.ningxiaojian.domain.User;
import com.ningxiaojian.utils.JDBCUtils;

public class UserDaoImpl implements UserDao {

	Connection connection=null;
	PreparedStatement ps=null;
	ResultSet rs=null;
	
	/**
	 * dao层,从数据库里面取出数据
	 */
	@Override
	public List<User> findAll() {
		List<User> list=null;
		try {
			//通过工具类获得连接
			connection = JDBCUtils.getConnetion();
			//通过连接对象获取操作数据库的对象
			String sql="SELECT * FROM user;";//查询sql语句
			ps=connection.prepareStatement(sql);
			//返回查询结果集
			rs=ps.executeQuery();
			//遍历rs,并封装数据
			list=new ArrayList<User>();
			while(rs.next()) {
				User user=new User();
				user.setUsername(rs.getString(2));//索引从1开始,id参数不用取
				user.setPassword(rs.getString(3));
				list.add(user);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally{
			JDBCUtils.close(connection, ps, rs);//关闭连接
			
		}
		return list;
	}

	@Override
	public void insertElement(User people) {
		try {
			connection=JDBCUtils.getConnetion();
			String sql="INSERT INTO user(username,password) VALUES(?,?);";//插入语句
			ps=connection.prepareStatement(sql);
			ps.setString(1,people.getUsername());//使用prepareStatement可以防止sql注入
			ps.setString(2,people.getPassword());
			//执行更新语句
			ps.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			JDBCUtils.close(connection, ps, rs);
		}
	}

}

jdbc工具类
JDBCUtils.java

package com.ningxiaojian.utils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;



/**
 * 因为要多次用到以下的步骤,所以写一个工具类来操作jdbc
 * @author Justin
 *在这里不要导错包,import com.mysql.jdbc.PreparedStatement;是错的
 */
public class JDBCUtils {
	/**
	 * 获得jdbc连接
	 */
	static Connection connection=null;
	public static Connection getConnetion() throws Exception {
		//加载jdbc驱动
		Class.forName("com.mysql.jdbc.Driver");
		//创建连接数据库的路径
		String url = "jdbc:mysql://localhost/android_login?user=root&password=12345";
		//通过url获得与数据库的连接
		connection = DriverManager.getConnection(url);
		return connection;
	}
	
	public static void close(Connection connection,PreparedStatement ps,ResultSet rs) {
		//一定要确保关闭连接,以下关闭步骤是参照官方文档的,有权威性
		if(rs!=null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if(ps!=null) {
			try {
				ps.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if(connection!=null) {
			try {
				connection.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}

测试dao层方法的test类(仅作测试作用)
TestDao.java
package com.ninxiaojian.test;

import java.util.List;

import org.junit.jupiter.api.Test;

import com.ningxiaojian.dao.UserDao;
import com.ningxiaojian.dao.impl.UserDaoImpl;
import com.ningxiaojian.domain.User;

class TestDao {

	/**
	 * 测试类,测试dao层那两个方法是否查询和插入正确
	 */
	@Test
	void testFindAll() {
		UserDao dao=new UserDaoImpl();
		List<User> list = dao.findAll();
		for(int i=0;i<list.size();i++) {//遍历list
			User user=list.get(i);
			System.out.println("username:"+user.getUsername());
			System.out.println("password:"+user.getPassword());
		}
	}
	@Test
	void testInsertElement() {
		UserDao dao=new UserDaoImpl();
		User people=new User();
		people.setUsername("hhhhh");
		people.setPassword("66666");
		dao.insertElement(people);
	}

}

servlet类
LoginServlet.java
package com.ningxiaojian.web.control;

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

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

import com.ningxiaojian.domain.User;
import com.ningxiaojian.service.UserService;
import com.ningxiaojian.service.impl.UserServiceImpl;


@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
   
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");//解决请求乱码(post)
		response.setCharacterEncoding("UTF-8");//解决响应乱码,下面要以字符流输出(若字节流输出则要再次编码)
		String username=request.getParameter("username");
		String password=request.getParameter("password");
		String sign=request.getParameter("sign");
		PrintWriter out=response.getWriter();
		//把传来的数据封装进javabean中
		User user=new User();
		user.setUsername(username);
		user.setPassword(password);
		UserService service=new UserServiceImpl();
		if("1".equals(sign)) {//登录操作(设置了一个标记)
			String loginInfo=service.checkLogin(user);
			out.print(loginInfo);
		}
		else if("2".equals(sign)) {//注册操作
			String registerInfo=service.register(user);
			out.print(registerInfo);
		}
		
		System.out.println(username);//在控制台输出
		System.out.println(password);
		System.out.println(sign);
		
	
	}

	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

service接口层
UserService.java
package com.ningxiaojian.service;

import com.ningxiaojian.domain.User;

public interface UserService {
	//查验登录
	public String checkLogin(User user);
	//注册用户
	public String register(User user);
}

service实现层,服务端的主要逻辑
UserServiceImpl.java
package com.ningxiaojian.service.impl;

import java.util.List;

import com.ningxiaojian.dao.UserDao;
import com.ningxiaojian.dao.impl.UserDaoImpl;
import com.ningxiaojian.domain.User;
import com.ningxiaojian.service.UserService;

public class UserServiceImpl implements UserService {

	UserDao dao=new UserDaoImpl();
	
	/*
	 * 主要的逻辑实现
	 */
	@Override
	public String checkLogin(User user) {
		List<User> list = dao.findAll();
		for(int i=0;i<list.size();i++) {//遍历集合
			User user2=list.get(i);
			if(user2.getUsername().equals(user.getUsername()) && user2.getPassword().equals(user.getPassword())) {
				return "登录成功";
			}
		}
		return "登录失败,密码输入错误";
	}

	@Override
	public String register(User user) {
		List<User> list = dao.findAll();
		for(int i=0;i<list.size();i++) {
			User user2=list.get(i);
			if(user2.getUsername().equals(user.getUsername())) {
				return "注册失败,该用户名已存在!";
			}
		}
		dao.insertElement(user);
		return "注册成功";
	}

}

以上就是全部的代码,每句代码都会有详细的解释

猜你喜欢

转载自blog.csdn.net/weixin_38802061/article/details/79968203