在线登录注册功能(android客户端+javaweb服务端+腾讯云服务器+腾讯云数据库)

完整的项目已上传github仓库,链接在文章最下面

注:笔者在安卓客户端部分写了kotlin语言和java语言两种,编译运行以java的为准,kotlin是笔者练习所写

开发工具

Android Studio 3.5

Eclipse 2020

tomcat 9.0

jdk 13.0

腾讯云服务器 Window Server 2012 R2

腾讯云数据库 Mysql 5.7

java web项目部署在腾讯云服务器

https://blog.csdn.net/zhangjin2024/article/details/101173520?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param

腾讯云数据库配置

首先要购买一个腾讯云数据库,我买的是学生活动价36一年的。

进入控制台,可以看到我们的实例:

点击实例ID,将外网地址打开,记下外网地址和外网端口,java web连接时要用:

然后登录数据库实例:

新建自己app要用到的数据库,并建立项目用到的表:

客户端(Android Studio)

功能页

app启动页

登录页面

注册页面

忘记密码页面

重置密码页面

app启动页

app启动时默认是白屏,为了好看,我们加上app的特色启动页面,先看效果图:

实现这个非常容易,只需要在styles.xml中添加如下:

然后在mainfest文件的启动页面里添加:

登录页面

效果如下:

包含用户名和密码的输入,密码的可见或不可见切换,登录按钮,忘记密码文本点击以及注册新用户的文本点击,功能还包括对用户输入合法性的判断。使用忘记密码功能时,接收用户输入的用户名,提交至后台验证用户是否存在,若存在则跳转至找回密码界面。

登录时客户端接收到用户输入的用户名以及密码,提交至后端服务器,与数据库中的已存信息比较验证合法性,然后将判断结果传回客户端显示登录成功或失败。

与服务器建立连接:

其中132.232.81.77:8080是我腾讯云服务器的公网ip,后面是打包的javaweb项目war包名称以及用到的对应页面的servlet文件名。

登录界面完整代码:

package com.example.yiyu;import androidx.appcompat.app.AppCompatActivity;import android.content.Intent;
import android.os.Bundle;
import android.text.method.HideReturnsTransformationMethod;
import android.text.method.PasswordTransformationMethod;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;public class Login2Activity extends AppCompatActivity implements View.OnClickListener{Button login;ToggleButton pswsee;EditText name1;EditText password1;TextView textRegister;TextView textForget;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_login2);login = this.findViewById(R.id.login);pswsee = this.findViewById(R.id.pswsee);name1 = this.findViewById(R.id.name);password1 = this.findViewById(R.id.password);textRegister = this.findViewById(R.id.newuser);textForget = this.findViewById(R.id.forgetpsw);login.setOnClickListener(this);textRegister.setOnClickListener(this);textForget.setOnClickListener(this);pswsee.setOnCheckedChangeListener(new ToggleButtonClick());}@Overridepublic void onClick(View view) {switch (view.getId()) {case R.id.login:final String name = name1.getText().toString().trim();final String password = password1.getText().toString().trim();if (name.isEmpty()) {Toast.makeText(this, "请输入用户名", Toast.LENGTH_SHORT).show();} else if (password.isEmpty()) {Toast.makeText(this, "请输入密码", Toast.LENGTH_SHORT).show();} else {//调用Java后台登录接口new Thread() {@Overridepublic void run() {try {String path = "http://132.232.81.77:8080/ForAndroid/loginServlet?name=" + name + "&password=" + password;URL url = new URL(path);HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.connect();int responseCode = connection.getResponseCode();if (responseCode == 200) {InputStream is = connection.getInputStream();ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len = -1;while ((len = is.read(buffer)) != -1) {baos.write(buffer, 0, len);}final String result = baos.toString();runOnUiThread(new Runnable() {@Overridepublic void run() {if (result.equals("1")) {Intent intent =new Intent(Login2Activity.this, MainActivity.class);Toast.makeText(Login2Activity.this, "登录成功", Toast.LENGTH_SHORT).show();startActivity(intent);} else {Toast.makeText(Login2Activity.this, "登录失败", Toast.LENGTH_SHORT).show();}}});}} catch (Exception e) {e.printStackTrace();}}}.start();}break;case R.id.newuser:startActivity(new Intent(Login2Activity.this, Register2Activity.class));break;case R.id.forgetpsw:final String name2 = name1.getText().toString().trim();if(name2.isEmpty()){Toast.makeText(this,"请输入用户名",Toast.LENGTH_SHORT).show();}else {Intent intent=new Intent(Login2Activity.this, Forget2Activity.class);intent.putExtra("name",name2);startActivity(intent);}break;}}//密码可见性按钮监听private class ToggleButtonClick implements CompoundButton.OnCheckedChangeListener{@Overridepublic void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {//5、判断事件源的选中状态if (isChecked){//显示密码//etPassword.setInputType(InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);password1.setTransformationMethod(HideReturnsTransformationMethod.getInstance());}else {// 隐藏密码//etPassword.setInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_VARIATION_PASSWORD);password1.setTransformationMethod(PasswordTransformationMethod.getInstance());}//6、每次显示或者关闭时,密码显示编辑的线不统一在最后,下面是为了统一password1.setSelection(password1.length());}}
}

注册界面

效果如下:

注册包含昵称、密码、和手机,手机号用于用户忘记密码时重置密码。将用户输入的信息提交至后台服务器,插入云数据库中,完成注册。

对用户输入注册内容的合法性判断:

忘记密码界面

效果如下:

接收用户输入的手机号,提交至后台验证与用户注册时预留的手机号是否一致,一致则跳转至重置密码界面。

这里短信验证码服务采用MobTech平台的SMSSDK短信验证服务,附上平台链接:https://new.dashboard.mob.com/#/SMSSDK,按照教程在平台创建应用,会得到一个app key和app secret,如下:

在android studio完成相应的配置即可使用,附上配置教程:https://www.mob.com/wiki/detailed?wiki=SMSSDK_for_Android_kuaisujicheng&id=23

我的配置如下:

在project的build.gradle里:

在module的build.gradle里加上:

用户输入手机号,点击获取验证码,这时候会有弹窗向用户确认是否发送验证码(防止用户不小心输错手机号而把验证码发到别人的手机上),效果如下:

确认则下发验证码,同时按钮变为不可点击状态,并显示倒计时,效果如下:

用户点击提交按钮后,判断验证码是否正确,并后台验证手机号与用户注册时绑定的手机号是否一致

该界面的代码如下:

package com.example.yiyu;import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;import com.mob.MobSDK;import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;
import java.util.regex.Matcher;
import java.util.regex.Pattern;import cn.smssdk.EventHandler;
import cn.smssdk.SMSSDK;public class Forget2Activity extends AppCompatActivity implements View.OnClickListener{EditText telenum;EditText yzm;Button getyzm;Button submit;TimerTask tt;Timer tm;int TIME=60;String country="86";int code_again=1;String name;String phone;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_forget2);telenum=findViewById(R.id.phone);yzm=findViewById(R.id.yzm);getyzm=findViewById(R.id.getyzm);submit=findViewById(R.id.submit);getyzm.setOnClickListener((View.OnClickListener) this);submit.setOnClickListener((View.OnClickListener) this);name = getIntent().getStringExtra("name");MobSDK.init(this);SMSSDK.registerEventHandler(eh) ;//注册短信回调(记得销毁,避免泄露内存)}private void toast(final String str) {runOnUiThread(new Runnable() {@Overridepublic void run() {Toast.makeText(Forget2Activity.this, str, Toast.LENGTH_SHORT).show();}});}public void forgetpsw(final String name,final String phone){//调用Java后台登录接口new Thread() {@Overridepublic void run() {try {String path = "http://132.232.81.77:8080/ForAndroid/forgetPasswordServlet?name=" + name + "&phone=" + phone;URL url = new URL(path);HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.connect();int responseCode = connection.getResponseCode();if(responseCode == 200){InputStream is = connection.getInputStream();ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] buffer= new byte[1024];int len = -1;while((len=is.read(buffer))!=-1){baos.write(buffer,0,len);}final String result = baos.toString();runOnUiThread(new Runnable() {@Overridepublic void run() {if(result.equals("1")){Toast.makeText(Forget2Activity.this,"手机号与预留匹配",Toast.LENGTH_SHORT).show();Intent intent =new Intent(Forget2Activity.this, ChangePassword2Activity.class);intent.putExtra("name",name);startActivity(intent);}else{Toast.makeText(Forget2Activity.this,"手机号与预留不匹配",Toast.LENGTH_LONG).show();}}});}} catch (Exception e) {e.printStackTrace();}}}.start();}@Overridepublic void onClick(View view) {switch(view.getId()){case R.id.getyzm:phone = telenum.getText().toString().trim();if (!TextUtils.isEmpty(phone)) {//定义需要匹配的正则表达式的规则String REGEX_MOBILE_SIMPLE =  "[1][3578]\\d{9}";//把正则表达式的规则编译成模板Pattern pattern = Pattern.compile(REGEX_MOBILE_SIMPLE);//把需要匹配的字符给模板匹配,获得匹配器Matcher matcher = pattern.matcher(phone);// 通过匹配器查找是否有该字符,不可重复调用重复调用matcher.find()if (matcher.find()) {//匹配手机号是否存在alterWarning();} else {toast("手机号不正确 ");}} else {toast("请输入手机号");}break;case R.id.submit://获得用户输入的验证码String code = yzm.getText().toString().replaceAll("/s","");if (!TextUtils.isEmpty(code)) {//判断验证码是否为空//验证SMSSDK.submitVerificationCode( country,  phone,  code);}else{//如果用户输入的内容为空,提醒用户toast("请输入验证码");}break;}}Handler hd = new Handler() {@Overridepublic void handleMessage(Message msg) {if (msg.what == code_again) {getyzm.setEnabled(true);submit.setEnabled(true);tm.cancel();//取消任务tt.cancel();//取消任务TIME = 60;//时间重置getyzm.setText("再次获取");}else {getyzm.setText(TIME + "秒后再次获取");}}};//回调EventHandler eh=new EventHandler(){@Overridepublic void afterEvent(int event, int result, Object data) {if (result == SMSSDK.RESULT_COMPLETE) {if (event == SMSSDK.EVENT_SUBMIT_VERIFICATION_CODE) {toast("验证码正确!");phone = telenum.getText().toString().trim();forgetpsw(name,phone);}else if (event == SMSSDK.EVENT_GET_VERIFICATION_CODE){       //获取验证码成功toast("获取验证码成功");}else if (event ==SMSSDK.EVENT_GET_SUPPORTED_COUNTRIES){//如果你调用了获取国家区号类表会在这里回调//返回支持发送验证码的国家列表}}else{//错误等在这里(包括验证失败)//错误码请参照http://wiki.mob.com/android-api-错误码参考/这里我就不再继续写了((Throwable)data).printStackTrace();String str = data.toString();//toast(str);toast("验证码错误!");}}};//弹窗确认下发private void alterWarning() {//构造器AlertDialog.Builder builder = new AlertDialog.Builder(this);builder.setTitle("提示"); //设置标题builder.setMessage(phone + " 将会收到验证码"); //设置内容
//        builder.setIcon(R.mipmap.ic_launcher);//设置图标,图片id即可builder.setPositiveButton("好的", new DialogInterface.OnClickListener() {//设置确定按钮@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss(); //关闭dialog//通过sdk发送短信验证(请求获取短信验证码,在监听(eh)中返回)SMSSDK.getVerificationCode(country, phone);//做倒计时操作Toast.makeText(Forget2Activity.this, "已发送", Toast.LENGTH_SHORT).show();getyzm.setEnabled(false);submit.setEnabled(true);tm = new Timer();tt = new TimerTask() {@Overridepublic void run() {hd.sendEmptyMessage(TIME--);}};tm.schedule(tt,0,1000);}});builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { //设置取消按钮@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();Toast.makeText(Forget2Activity.this, "已取消" , Toast.LENGTH_SHORT).show();}});//参数都设置完成了,创建并显示出来builder.create().show();}//销毁短信注册@Overrideprotected void onDestroy() {super.onDestroy();// 注销回调接口registerEventHandler必须和unregisterEventHandler配套使用,否则可能造成内存泄漏。SMSSDK.unregisterEventHandler(eh);}
}

重置密码界面

效果如下:

这里判断密码合法的话,就提交至后台服务器,在数据库修改用户密码

代码如下:

package com.example.yiyu;import androidx.appcompat.app.AppCompatActivity;import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;public class ChangePassword2Activity extends AppCompatActivity implements View.OnClickListener{EditText password1;EditText password2;Button submit;String name;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_change_password2);password1=this.findViewById(R.id.password1);password2=this.findViewById(R.id.password2);submit=this.findViewById(R.id.submit);name = getIntent().getStringExtra("name");submit.setOnClickListener((View.OnClickListener) this);}public boolean check()  {boolean isok =false;String psw=password1.getText().toString();if(psw.isEmpty()){Toast.makeText(this,"密码不能为空",Toast.LENGTH_LONG).show();return isok;}if(psw.length()>16){Toast.makeText(this,"密码不能超过16位",Toast.LENGTH_LONG).show();return isok;}String psw2=password2.getText().toString();if(!psw2.equals(psw)){Toast.makeText(this,"两次密码不一致",Toast.LENGTH_LONG).show();return isok;}else{isok=true;return isok;}}public void onClick(View view) {switch (view.getId()) {case R.id.submit:final String password = password1.getText().toString();//Toast.makeText(this,name+password,Toast.LENGTH_LONG).show();if (check()) {new Thread() {@Overridepublic void run() {try {String path = "http://132.232.81.77:8080/ForAndroid/changePasswordServlet?name=" + name + "&password=" + password;URL url = new URL(path);HttpURLConnection connection = (HttpURLConnection) url.openConnection();connection.connect();int responseCode = connection.getResponseCode();if (responseCode == 200) {InputStream is = connection.getInputStream();ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len = -1;while ((len = is.read(buffer)) != -1) {baos.write(buffer, 0, len);}final String result = baos.toString();runOnUiThread(new Runnable() {@Overridepublic void run() {if (result.equals("1")) {Toast.makeText(ChangePassword2Activity.this, "密码重置成功", Toast.LENGTH_LONG).show();startActivity(new Intent(ChangePassword2Activity.this, Login2Activity.class));} else {Toast.makeText(ChangePassword2Activity.this, "密码重置失败", Toast.LENGTH_LONG).show();}}});}} catch (Exception e) {e.printStackTrace();}}}.start();}break;}}
}

Java web服务端

主要框架:

bean:封装数据,是数据库中person的映射

dao:实现数据的持久化操作,如增删改查

db:连接数据库

service:业务逻辑的实现

servlet:实现客户端和服务端的通信

Select.jsp:查看后台数据库中的数据

下面主要说一下连接腾讯云数据库和servlet部分

ConnDB.java

package android.db;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;public class ConnDB {/*** 打开数据库*/public static Connection openConn() {// 1.导驱动包mysql-connector-java-5.1.7-bin.jar// 2.创建Connection连接对象Connection conn = null;try {// 3.获取mysql驱动Class.forName("com.mysql.jdbc.Driver");// 4.获取url路径String url = "jdbc:mysql://cdb-fmhwq8ww.cd.tencentcdb.com:10074/yiyu";// 5.获取mysql连接账号String mysql_name = "root";String mysql_password = "b980227l";// 6.进行连接conn = DriverManager.getConnection(url, mysql_name, mysql_password);} catch (Exception e) {e.printStackTrace();}//return conn;}/*** 关闭数据库*/public static void closeConn(ResultSet rs, PreparedStatement ps, Connection conn) {try {if (rs != null) {rs.close();}if (ps != null) {ps.close();}if (conn != null) {conn.close();}} catch (Exception e) {e.printStackTrace();}}}

这个部分就是上面说到的云数据库的外网地址的外网端口。

LoginServlet.java

package android.servlet;
import java.io.IOException;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import android.bean.Person;
import android.service.PersonService;public class LoginServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("utf-8");String name = request.getParameter("name");String password = request.getParameter("password");Person person =new Person();person.setName(name);person.setPassword(password);PersonService personService = new PersonService();int num = personService.loginPerson(person);response.getWriter().write(num + "");}}

接收客户端传来的用户名和密码,与数据库中的数据比较,验证登录的合法性,并将结果传回给客户端做出相应的响应。调用PersonDao中的loginPerson函数实现验证,该函数如下:

其他的servlet类似,大家可以直接下载代码看

另外,提醒一点,大家可能会发现在安卓模拟器上一切正常,但是app安装到真机上就无法访问腾讯云数据库了。这是因为安卓9.0系统已经默认不支持http请求了,谷歌默认要求链接是加密链接了,解决方法如下:https://blog.csdn.net/qq_41117896/article/details/109011794

查看后台数据库中的数据

Select.jsp

浏览器输入http://132.232.81.77:8080/ForAndroid/Select.jsp

完整项目

github:https://github.com/guyuanjunxi/yiyu
csdn:https://download.csdn.net/download/qq_41117896/12918776

在线登录注册功能(android客户端+javaweb服务端+腾讯云服务器+腾讯云数据库)相关推荐

  1. 胖葵酒店管理系统(android客户端+javaweb服务端+腾讯云服务器+腾讯云数据库)

    胖葵酒店管理系统app 完整项目已上传github,链接在文章下面 先看效果图: 登录: 主页面(点击右上角图标进入个人中心页面): 经理模块(客房管理模块和员工管理模块与经理管理模块类似,员工管理模 ...

  2. 【Android 开发】: Android客户端与服务端之间使用JSON交互数据。

    在前面的两讲中,我们讲解了JSON数据格式的一些基本知识,以及做一些小Demo,这一讲我们在前面的基础上来做一个综合的可扩展的Demo,主要是针对Android客户端解析服务端传递过来的JSON数据. ...

  3. android客户端访问服务端,服务端返回json数据

    json这里选用了fast-json 先看服务端代码如下 package novelserver.servlet;import java.io.IOException; import java.io. ...

  4. Android 客户端与服务端的数据交互问题

    Android客户端是如何与服务端的数据进行交互的呢? 一般就是客户端向服务端发送请求,服务端对数据进行相关处理,返回json数据返回给客户端,客户端再进行相关操作. 说明:主要是用登录功能来进行详解 ...

  5. android客户端访问服务端tomcat

    为什么80%的码农都做不了架构师?>>>    首先,服务器端已经存在一个项目,该项目基于SSH,已经部署在tomcat上并且正在运行了.我在这个项目的action层新建了一个包,该 ...

  6. 小程序登录注册获取openid解密手机号服务端实现

    文章目录 前言 一.openId是什么 1.如何确认微信和小程序唯一身份 2.为什么使用openId 3.如何获得openId 1:前端示例代码 2:服务端示例代码 二.解密微信绑定手机号 1:前端示 ...

  7. 2023年微信小程序获取手机号授权登录注册详细教程,包含服务端教程

    前言 小程序中有很多地方都会用到用户的手机号,比如登陆注册,填写收货地址等等.有了这个组件可以快速获取微信绑定手机号码,无须用户填写. 网上大多数教程还是往年的,而微信官方的api已做了修改.本篇文章 ...

  8. Android客户端和服务端如何使用Token和Session

    对于初学者来说,对Token和Session的使用难免会限于困境,开发过程中知道有这个东西,但却不知道为什么要用他?更不知道其原理,今天我就带大家一起分析分析这东西. 一.我们先解释一下他的含义: 1 ...

  9. android客户端和服务端交互,谈谈android客户端和网站数据交互的实现

    android客户端一般不直接访问网站数据库,而是像浏览器一样发送get或者post请求,然后网站返回客户端能理解的数据格式,客户端解析这些数据,显示在界面上,常用的数据格式是xml和json. 可以 ...

最新文章

  1. 这些基本职业技术---programmer
  2. 华为交换机的配置及:access、trunk、hybird端口详解
  3. Visitor(访问者)--对象行为型模式
  4. 【PA2014】【BZOJ3709】Bohater(贪心,排序)
  5. 每日算法系列【LeetCode 523】连续的子数组和
  6. 重定向ISA日志到SQL2000
  7. 如何在 M1 Mac 上运行英特尔应用程序?
  8. 软件测试精要,软件测试精要.ppt
  9. freemaker word转html,ftl文件-word文档转化成ftl文件
  10. 微信抢票——迭代周期一结束后感想
  11. 《杭州区块链行业发展报告》披露市场现状
  12. 我的世界服务器修改个人游戏模式吗,我的世界1period;12指令更改模式 | 手游网游页游攻略大全...
  13. qgg包-续2-大数据集教程
  14. CA认证的原理和流程以及https完整通信过程
  15. Orace登录及建库
  16. linux convert 常用命令
  17. [英文缩写]英文聊天中btw,g2g,ttyl,brb是什么意思?
  18. 一年2000店,苏宁零售云的县镇市场进化简史 | 一点财经
  19. 推荐一些硬核的公众号
  20. 用visual_studio编写c51单片机程序

热门文章

  1. 纳米红光更安全的养生方式——红光光浴#大健康#红光光浴#红光#种光光学
  2. 示例填充图片_填充内容:工具,技巧和动态示例
  3. 美国加州大学河滨分校陈雪梅教授北大招聘Co-PI
  4. 不明觉厉!用了近10年,才有人读懂这篇论文
  5. 1.合宙Air32F103调试GPIO
  6. iOS 改变图片颜色
  7. h5、微信、app互相跳转
  8. asp.net 鲜花销售系统1058毕业设计
  9. 【视频】马尔可夫链蒙特卡罗方法MCMC原理与R语言实现|数据分享
  10. 在安卓中实现Zigbee串口设备采集模块