Android+SpringBoot前后端分离实现登录注册

  • 一、登录
    • 1.界面设计
    • 2.Android端
      • (1)布局文件(activity_login)
      • (2)java文件(LoginActivity)
      • **下面给出找到IPv4地址的步骤**
        • 1.Win+R,输入ipconfig
        • 2.找到以太网适配器,下面的IPv4就是你电脑的IP地址了
      • (3)User
      • (4)CodeUtils
      • (5)SharedPreferencesUtil
      • (6)需要导入的依赖
      • (7)申请权限:在AndroidManifest.xml中加入以下代码
  • 二、注册
    • 1.界面设计
    • 2.Android端
      • (1)布局文件(activity_register)
      • (2)java文件(RegisterActivity)
      • (3)MD5Utils
  • 三、数据库
    • 1.数据库就是简单的一个user表
  • 四、SpringBoot端
    • 1.创建springboot项目
      • (1)项目基本结构
    • 2.配置文件(pom.xml)
    • 3.Controller层(TestController)
    • 4.entity层(User)
    • 5.mapper层(UserMapper)
    • 6.UserRepositoryImpl
    • 7.repository层(UserRepository)
    • 8.UserMapper.xml
    • 9.配置文件(application.properties)
      • **1.注意:这里的数据库端口号和数据库改为你自己的**
  • 五、功能实现步骤
    • 1.打开数据库
    • 2.运行SpringBoot
    • 3.运行Android

一、登录

1.界面设计

2.Android端

(1)布局文件(activity_login)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><include layout="@layout/main_title_bar"/><com.example.CircleImageViewandroid:id="@+id/iv_head"android:layout_width="wrap_content"android:layout_height="140dp"android:layout_gravity="center_horizontal"android:layout_marginTop="10dp"android:contentDescription="@null"android:src="@drawable/logo1" /><EditTextandroid:singleLine="true"android:id="@+id/et_user_name"android:layout_width="fill_parent"android:layout_height="48dp"android:background="@drawable/zcan3"android:layout_marginTop="35dp"android:layout_marginLeft="35dp"android:layout_marginRight="35dp"android:drawableLeft="@drawable/yhm1"android:paddingLeft="8dp"android:drawablePadding="10dp"android:hint="@string/name"android:gravity="center_vertical"android:textColorHint="#a3a3a3"android:textColor="#000000"android:textSize="14sp"/><EditTextandroid:singleLine="true"android:id="@+id/et_pwd"android:layout_width="fill_parent"android:layout_height="48dp"android:background="@drawable/zcan3"android:layout_marginTop="10dp"android:layout_marginLeft="35dp"android:layout_marginRight="35dp"android:drawableLeft="@drawable/mm2"android:paddingLeft="8dp"android:drawablePadding="10dp"android:inputType="textPassword"android:hint="@string/pwd"android:gravity="center_vertical"android:textColorHint="#a3a3a3"android:textColor="#000000"android:textSize="14sp"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="35dp"android:layout_marginRight="35dp"android:layout_marginTop="20dp"android:orientation="horizontal" ><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="40dp"android:background="@drawable/linearlayout" ><EditTextandroid:id="@+id/et_phoneCodes"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"android:background="@null"android:textColor="#000000"android:textColorHint="#a3a3a3"android:hint="请输入右侧验证码" /></LinearLayout><ImageViewandroid:id="@+id/iv_showCode"android:layout_width="100dp"android:layout_marginLeft="10dp"android:layout_height="match_parent" /></LinearLayout><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:layout_marginLeft="35dp"android:orientation="horizontal"><CheckBoxandroid:id="@+id/cb_box"android:layout_width="wrap_content"android:layout_height="wrap_content" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="记住密码"/></LinearLayout><Buttonandroid:text="@string/login"android:id="@+id/btn_login"android:layout_gravity="center_horizontal"android:layout_marginTop="15dp"android:layout_marginLeft="35dp"android:layout_marginRight="35dp"android:textColor="@android:color/white"android:textSize="20sp"android:textStyle="bold"android:layout_width="fill_parent"android:layout_height="50dp"android:background="@drawable/register_selector"/><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="fill_parent"android:layout_marginTop="15dp"android:layout_marginLeft="35dp"android:layout_marginRight="35dp"android:gravity="center_horizontal"android:orientation="horizontal"><TextViewandroid:id="@+id/tv_register"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center_horizontal"android:padding="8dp"android:text="@string/tv_register"android:textSize="14sp"android:textColor="@color/white"android:background="@drawable/register_selector"/><TextViewandroid:id="@+id/tv_find_pwd"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center_horizontal"android:padding="8dp"android:text="@string/find_pwd"android:textSize="14sp"android:textColor="@color/white"android:background="@drawable/register_selector"/></LinearLayout></LinearLayout>

(2)java文件(LoginActivity)

package com.example.activity;import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.graphics.Color;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;import androidx.preference.PreferenceManager;import com.example.MainActivity;
import com.example.R;
import com.example.bean.User;
import com.example.utils.CodeUtils;
import com.example.utils.SharedPreferencesUtil;
import com.zhy.http.okhttp.OkHttpUtils;
import com.zhy.http.okhttp.callback.StringCallback;import java.util.ArrayList;
import java.util.List;import okhttp3.Call;
import okhttp3.OkHttpClient;public class LoginActivity extends Activity {private TextView tv_main_title;//标题private TextView tv_back;      //返回按钮private TextView tv_register,tv_find_pwd;//立即注册、找回密码的控件private Button btn_login;  //登录按钮private RelativeLayout rl_title_bar;//标题布局private EditText et_user_name,et_pwd;//用户名、密码的控件private String username,pwd,spPwd;//用户名、密码的控件的获取值private CheckBox cb_box;//验证码private ImageView iv_showCode;private EditText et_phoneCode;//产生的验证码private String realCode;private  List<User> userList = new ArrayList<>();private SharedPreferencesUtil su;OkHttpClient client = new OkHttpClient();private SharedPreferences pref;private SharedPreferences.Editor editor;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.activity_login);//设置此界面为竖屏setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);init();//验证码reacode();
//        getData();}//验证码private void reacode() {//将验证码用图片的形式显示出来iv_showCode.setImageBitmap(CodeUtils.getInstance().createBitmap());realCode =CodeUtils.getInstance().getCode();}private void init() {// TODO Auto-generated method stubtv_main_title = (TextView) findViewById(R.id.tv_main_title);tv_main_title.setText("登录");tv_back = ((TextView) findViewById(R.id.tv_back));tv_register = (TextView) findViewById(R.id.tv_register);tv_find_pwd = (TextView) findViewById(R.id.tv_find_pwd);pref = PreferenceManager.getDefaultSharedPreferences(this);su = SharedPreferencesUtil.getInstance(getApplicationContext());btn_login = (Button) findViewById(R.id.btn_login);et_user_name = (EditText) findViewById(R.id.et_user_name);rl_title_bar = (RelativeLayout) findViewById(R.id.title_bar);et_pwd = (EditText) findViewById(R.id.et_pwd);cb_box = (CheckBox) findViewById(R.id.cb_box);rl_title_bar.setBackgroundColor(Color.parseColor("#30b4ff"));//验证码et_phoneCode = (EditText) findViewById(R.id.et_phoneCodes);iv_showCode = (ImageView) findViewById(R.id.iv_showCode);boolean isremember = pref.getBoolean("cb_box", false);if (isremember) {//将账号和密码全部设置到文本框中String phone = pref.getString("phone", "");String password = pref.getString("password", "");et_user_name.setText(phone);et_pwd.setText(password);cb_box.setChecked(true);}//图片验证码刷新iv_showCode.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubiv_showCode.setImageBitmap(CodeUtils.getInstance().createBitmap());realCode = CodeUtils.getInstance().getCode();}});//返回按钮的点击事件tv_back.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubLoginActivity.this.finish();}});//立即注册控件的点击事件tv_register.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubIntent intent = new Intent(LoginActivity.this, RegisterActivity.class);startActivityForResult(intent, 1);}});//找回密码点击事件tv_find_pwd.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stub//跳转到找回密码界面(此界面暂时未创建)Intent intent = new Intent(LoginActivity.this, FindPswActivity.class);startActivityForResult(intent, 1);}});//登录按钮点击事件btn_login.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubusername = et_user_name.getText().toString().trim();pwd = et_pwd.getText().toString().trim();OkHttpUtils.get().url("http://192.168.119.1:8086/login").addParams("userId", username).addParams("password", pwd).build().execute(new StringCallback() {@Overridepublic void onError(Call call, Exception e, int i) {}@Overridepublic void onResponse(String response, int i) {//                                if(response.equals("true"))
//                                    Toast.makeText(MainActivity.this, "登录成功!", Toast.LENGTH_LONG).show();
//                                else
//                                    Toast.makeText(MainActivity.this, "登录失败", Toast.LENGTH_LONG).show();if (TextUtils.isEmpty(username)) {Toast.makeText(LoginActivity.this, "请输入用户名", Toast.LENGTH_SHORT).show();return;} else if (TextUtils.isEmpty(pwd)) {Toast.makeText(LoginActivity.this, "请输入密码", Toast.LENGTH_SHORT).show();return;} else if (response.equals("true")) {String phoneCode = et_phoneCode.getText().toString();if (phoneCode.equals(realCode)) {Toast.makeText(LoginActivity.this, "登录成功", Toast.LENGTH_SHORT).show();//把登录状态和登录的用户名保存到SharedPreferences里面saveLoginStatus(true,username);//  System.out.println("...............................................");byOkHttp(username);//登录成功后通过Intent把登录成功的状态传递到MainActivity.java中Intent data = new Intent();data.putExtra("status", true);setResult(RESULT_OK, data);//setResult为OK,关闭当前页面LoginActivity.this.finish();//在登录的时候,如果用户还没有注册则注册。注册成功后把注册成功后的用户名返回给前一个页面startActivity(new Intent(LoginActivity.this, MainActivity.class));editor = pref.edit();if (cb_box.isChecked()) {editor.putBoolean("cb_box", true);editor.putString("phone", username);editor.putString("password", pwd);} else {editor.clear();}editor.apply();} else {Toast.makeText(LoginActivity.this, phoneCode + "验证码错误", Toast.LENGTH_SHORT).show();}return;} else if (!byOkHttpUtils(username) && !response.equals(true)) {Toast.makeText(LoginActivity.this, "用户名或密码错误", Toast.LENGTH_SHORT).show();return;} else {Toast.makeText(LoginActivity.this, "此用户不存在", Toast.LENGTH_SHORT).show();}}});// String md5Pwd=MD5Utils.MD5(pwd);// spPwd=readPwd(username);}public Boolean byOkHttpUtils(String userId){final Boolean[] flag = {false};OkHttpUtils.get().addParams("userId",userId)// .addParams("userName",userName)//  .addParams("password",password).url("http://169.254.21.102:8086/register").build().execute(new StringCallback() {@Overridepublic void onError(Call call, Exception e, int i) {}@Overridepublic void onResponse(String response, int i) {if (response.equals("true")) {flag[0] = true;//Toast.makeText(RegisterActivity.this, "注册成功!", Toast.LENGTH_LONG).show();}// else//Toast.makeText(RegisterActivity.this, "注册失败,可能已存在当前账号", Toast.LENGTH_LONG).show();}
//// return response.equals("true");//return return_value.equals("true")}});return flag[0];}public void byOkHttp(String userId){//创建OkHttpClient对象OkHttpUtils.get().url("http://169.254.21.102:8086/update").addParams("userId", userId)// .addParams("status", String.valueOf(status)).build();if(userId!=null){//从注册界面传递过来的用户名//String username=data.getStringExtra("username");System.out.println(true);if(!TextUtils.isEmpty(username)){et_user_name.setText(username);//设置光标的位置上et_user_name.setSelection(username.length());}}//获取返回的json数据//String return_value = response.body().toString();
//                if(return_value.equals("true")){//                    Toast.makeText(register.this, "注册成功!", Toast.LENGTH_LONG).show();
//                }
//                else {//                    Toast.makeText(register.this, "注册失败,可能已存在当前账号邮箱", Toast.LENGTH_LONG).show();
//                }// return return_value.equals("true");}//从SharedPreferences中根据用户名读取密码
//    private String readPwd(String username){//        SharedPreferences sp=getSharedPreferences("loginInfo", MODE_PRIVATE);
//        return sp.getString(username,"");
//    }//保存登录状态和登录用户名到SharedPrefarences中private void saveLoginStatus(boolean status,String username){//loginInfo表示文件名SharedPreferences sp=getSharedPreferences("loginInfo", MODE_PRIVATE);SharedPreferences.Editor editor=sp.edit();//获取编辑器editor.putBoolean("isLogin", status);editor.putString("loginUserName", username);//存入登录时的用户名editor.commit();//提交修改}
//    @Override
//    protected void onActivityResult(int requestCode,int resultCode,
//                                    Intent data){//        super.onActivityResult(requestCode, resultCode, data);
//        if(data!=null){//            //从注册界面传递过来的用户名
//            String username=data.getStringExtra("username");
//            if(!TextUtils.isEmpty(username)){//                et_user_name.setText(username);
//                //设置光标的位置上
//                et_user_name.setSelection(username.length());
//            }
//            }
//   }});}
}


这里注意要将接口地址改为你自己电脑的IPv4地址

下面给出找到IPv4地址的步骤

1.Win+R,输入ipconfig

2.找到以太网适配器,下面的IPv4就是你电脑的IP地址了

(3)User

package com.example.bean;/***/public class User {private String uid;private String username;private String upassword;private String uname;public User(String uid, String username, String upassword, String uname) {this.uid = uid;this.username = username;this.upassword = upassword;this.uname = uname;}public User(String username, String upassword,String uname) {this.username = username;this.upassword = upassword;this.uname = uname;}public User() {}public String getUid() {return uid;}public void setUid(String uid) {this.uid = uid;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getUpassword() {return upassword;}public void setUpassword(String upassword) {this.upassword = upassword;}public String getUname() {return uname;}public void setUname(String uname) {this.uname = uname;}
}

(4)CodeUtils

package com.example.utils;import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;import java.util.Random;public class CodeUtils {//随机码集private static final char[] CHARS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9','a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm','n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z','A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M','N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};private static CodeUtils mCodeUtils;private int mPaddingLeft, mPaddingTop;private StringBuilder mBuilder = new StringBuilder();private Random mRandom = new Random();//Default Settingsprivate static final int DEFAULT_CODE_LENGTH = 4;//验证码的长度  这里是4位private static final int DEFAULT_FONT_SIZE = 60;//字体大小private static final int DEFAULT_LINE_NUMBER = 3;//多少条干扰线private static final int BASE_PADDING_LEFT = 20; //左边距private static final int RANGE_PADDING_LEFT = 30;//左边距范围值private static final int BASE_PADDING_TOP = 70;//上边距private static final int RANGE_PADDING_TOP = 15;//上边距范围值private static final int DEFAULT_WIDTH = 200;//默认宽度.图片的总宽private static final int DEFAULT_HEIGHT = 100;//默认高度.图片的总高private static final int DEFAULT_COLOR = Color.rgb(0xee, 0xee, 0xee);//默认背景颜色值private String code;public static CodeUtils getInstance() {if (mCodeUtils == null) {mCodeUtils = new CodeUtils();}return mCodeUtils;}//生成验证码图片public Bitmap createBitmap() {mPaddingLeft = 0; //每次生成验证码图片时初始化mPaddingTop = 0;Bitmap bitmap = Bitmap.createBitmap(DEFAULT_WIDTH, DEFAULT_HEIGHT, Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(bitmap);code = createCode();canvas.drawARGB(0, 0, 0, 0);canvas.drawColor(DEFAULT_COLOR);Paint paint = new Paint();paint.setTextSize(DEFAULT_FONT_SIZE);for (int i = 0; i < code.length(); i++) {randomTextStyle(paint);randomPadding();canvas.drawText(code.charAt(i) + "", mPaddingLeft, mPaddingTop, paint);}//干扰线for (int i = 0; i < DEFAULT_LINE_NUMBER; i++) {drawLine(canvas, paint);}canvas.save();//保存canvas.restore();return bitmap;}/*** 得到图片中的验证码字符串** @return*/public String getCode() {return code;}//生成验证码public String createCode() {mBuilder.delete(0, mBuilder.length()); //使用之前首先清空内容for (int i = 0; i < DEFAULT_CODE_LENGTH; i++) {mBuilder.append(CHARS[mRandom.nextInt(CHARS.length)]);}return mBuilder.toString();}//生成干扰线private void drawLine(Canvas canvas, Paint paint) {int color = randomColor();int startX = mRandom.nextInt(DEFAULT_WIDTH);int startY = mRandom.nextInt(DEFAULT_HEIGHT);int stopX = mRandom.nextInt(DEFAULT_WIDTH);int stopY = mRandom.nextInt(DEFAULT_HEIGHT);paint.setStrokeWidth(1);paint.setColor(color);canvas.drawLine(startX, startY, stopX, stopY, paint);}//随机颜色private int randomColor() {mBuilder.delete(0, mBuilder.length()); //使用之前首先清空内容String haxString;for (int i = 0; i < 3; i++) {haxString = Integer.toHexString(mRandom.nextInt(0xEE));if (haxString.length() == 1) {haxString = "0" + haxString;}mBuilder.append(haxString);}return Color.parseColor("#" + mBuilder.toString());}//随机文本样式private void randomTextStyle(Paint paint) {int color = randomColor();paint.setColor(color);paint.setFakeBoldText(mRandom.nextBoolean());  //true为粗体,false为非粗体float skewX = mRandom.nextInt(11) / 10;skewX = mRandom.nextBoolean() ? skewX : -skewX;paint.setTextSkewX(skewX); //float类型参数,负数表示右斜,整数左斜paint.setUnderlineText(mRandom.nextBoolean()); //true为下划线,false为非下划线paint.setStrikeThruText(mRandom.nextBoolean()); //true为删除线,false为非删除线}//随机间距private void randomPadding() {mPaddingLeft += BASE_PADDING_LEFT + mRandom.nextInt(RANGE_PADDING_LEFT);mPaddingTop = BASE_PADDING_TOP + mRandom.nextInt(RANGE_PADDING_TOP);}
}

(5)SharedPreferencesUtil

package com.example.utils;import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;/*** 状态保存工具类*/
public class SharedPreferencesUtil {private static final String TOKEN = "TOKEN";// SharedPreferences是Android平台上一个轻量级的存储辅助类private static SharedPreferences myPreferences;private static SharedPreferences.Editor editor;private static SharedPreferencesUtil mSharedPreferencesUtil;private final Context context;public SharedPreferencesUtil(Context context) {this.context = context.getApplicationContext();// 调用Context对象的getSharedPreferences()方法获得的SharedPreferences对象可以被同一应用程序下的其他组件共享.myPreferences = this.context.getSharedPreferences("TAG", Context.MODE_PRIVATE);editor = myPreferences.edit();}/*** 单例实现* @param context* @return*/public static SharedPreferencesUtil getInstance(Context context) {if(mSharedPreferencesUtil == null ) {mSharedPreferencesUtil = new SharedPreferencesUtil(context);}return mSharedPreferencesUtil;}/*** 设置值* @param key* @param value*/public void setValue(String key, String value) {editor.putString(key, value);editor.commit();}/*** 清空*/public void clear() {editor.clear();editor.commit();}/*** 获取值* @param key* @return*/public String getValue(String key) {return myPreferences.getString(key, "");}/*** 设置登陆状态(存入token)* @param token*/public void toLogin(String token) {setValue(TOKEN, token);}public boolean isLogin() {String token = getValue(TOKEN);Log.e("token", token);if("".equals(token)) {return false;} else {return true;}}}

(6)需要导入的依赖

    implementation 'com.squareup.okhttp3:okhttp:3.14.0'implementation 'com.squareup.okhttp:okhttp:2.7.5'implementation 'com.zhy:okhttputils:2.6.2'

(7)申请权限:在AndroidManifest.xml中加入以下代码

    <uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

二、注册

1.界面设计

2.Android端

(1)布局文件(activity_register)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/activity_register"android:orientation="vertical" ><include layout="@layout/main_title_bar" /><com.example.CircleImageViewandroid:layout_width="wrap_content"android:layout_height="150dp"android:layout_gravity="center_horizontal"android:layout_marginTop="10dp"android:contentDescription="@null"android:src="@drawable/logo1" /><EditTextandroid:singleLine="true"android:id="@+id/et_user_name"android:layout_width="fill_parent"android:layout_height="48dp"android:background="@drawable/zcan3"android:layout_marginTop="35dp"android:layout_marginLeft="35dp"android:layout_marginRight="35dp"android:drawableLeft="@drawable/yhm1"android:paddingLeft="8dp"android:drawablePadding="10dp"android:hint="@string/name"android:gravity="center_vertical"android:textColorHint="#a3a3a3"android:textColor="#000000"android:textSize="14sp"/><EditTextandroid:id="@+id/et_pwd"android:layout_width="fill_parent"android:layout_height="48dp"android:layout_marginLeft="35dp"android:layout_marginRight="35dp"android:background="@drawable/zcan3"android:drawableLeft="@drawable/mm2"android:drawablePadding="10dp"android:gravity="center_vertical"android:hint="@string/pwd"android:inputType="textPassword"android:paddingLeft="8dp"android:singleLine="true"android:textColor="#000000"android:textColorHint="#a3a3a3"android:textSize="14sp" /><EditTextandroid:singleLine="true"android:id="@+id/et_pwd_again"android:layout_width="fill_parent"android:layout_height="48dp"android:background="@drawable/zcan3"android:layout_marginLeft="35dp"android:layout_marginRight="35dp"android:drawableLeft="@drawable/mm2"android:paddingLeft="8dp"android:drawablePadding="10dp"android:inputType="textPassword"android:hint="@string/pwd_again"android:gravity="center_vertical"android:textColorHint="#a3a3a3"android:textColor="#000000"android:textSize="14sp"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="45dp"android:layout_marginLeft="15dp"android:layout_marginRight="15dp"android:layout_marginTop="30dp"android:background="@drawable/zcan3"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_vertical"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="20dp"android:layout_marginRight="20dp"android:text="中国+86"android:textColor="#A2CD5A"android:textSize="16sp" /><Viewandroid:layout_width="0.1dp"android:layout_height="match_parent"android:background="#FF7F00" /><EditTextandroid:id="@+id/et_forgetPass_PhoneNum"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="20dp"android:background="@null"android:digits="0123456789"android:hint="请填入您的手机号"android:inputType="number"android:maxLength="11"android:textSize="16sp" /></LinearLayout></LinearLayout><!--    <LinearLayout--><!--        android:layout_width="match_parent"-->
<!--        android:layout_height="wrap_content"-->
<!--        android:layout_marginLeft="15dp"-->
<!--        android:layout_marginRight="15dp"-->
<!--        android:layout_marginTop="20dp"-->
<!--        android:orientation="horizontal">--><!--        <LinearLayout-->
<!--            android:layout_width="wrap_content"-->
<!--            android:layout_height="45dp"-->
<!--            android:background="@drawable/zcan3">-->
<!--            <EditText-->
<!--                android:id="@+id/et_phoneCodes"-->
<!--                android:layout_width="match_parent"-->
<!--                android:layout_height="match_parent"-->
<!--                android:layout_marginLeft="10dp"-->
<!--                android:layout_marginRight="10dp"-->
<!--                android:background="@null"-->
<!--                android:hint="请输入右侧验证码" />-->
<!--        </LinearLayout>--><!--        <ImageView-->
<!--            android:id="@+id/image"-->
<!--            android:layout_width="100dp"-->
<!--            android:layout_height="match_parent"-->
<!--            android:layout_marginLeft="10dp" />--><!--    </LinearLayout>-->
<!--    <Button-->
<!--        android:id="@+id/but_forgetpass_toSetCodes"-->
<!--        android:layout_width="match_parent"-->
<!--        android:layout_height="wrap_content"-->
<!--        android:layout_margin="35dp"-->
<!--        android:background="@drawable/register_selector"-->
<!--        android:text="获取验证码"-->
<!--        android:textColor="#fff" />--><Buttonandroid:text="@string/btn_register"android:id="@+id/btn_register"android:layout_gravity="center_horizontal"android:layout_marginTop="30dp"android:layout_marginLeft="35dp"android:layout_marginRight="35dp"android:textColor="@android:color/white"android:textSize="20sp"android:textStyle="bold"android:layout_width="fill_parent"android:layout_height="50dp"android:background="@drawable/register_selector"/></LinearLayout>

(2)java文件(RegisterActivity)

package com.example.activity;import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;import com.example.R;
import com.example.utils.MD5Utils;
import com.zhy.http.okhttp.OkHttpUtils;
import com.zhy.http.okhttp.callback.StringCallback;import okhttp3.Call;public class RegisterActivity extends Activity {private TextView tv_main_title;//标题private TextView tv_back;        //返回按钮private RelativeLayout rl_title_bar;//标题布局private Button btn_register;    //注册按钮private EditText et_user_name,et_pwd,et_pwd_again;//用户名、密码、再次输入的密码的控件private String username,pwd,pwd_again;//用户名、密码、再次输入的密码的控件的获取值private Bitmap bitmap;private String code;//验证码private ImageView iv_showCode;private EditText et_phoneCode;//产生的验证码private String realCode;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.activity_register);init();
//        //验证码
//        reacode();
//        //获取需要展示图片验证码的ImageView
//        final ImageView image = (ImageView) findViewById(R.id.image);
//        //获取工具类生成的图片验证码对象
//        bitmap = CodeUtils.getInstance().createBitmap();
//        //获取当前图片验证码的对应内容用于校验
//        code = CodeUtils.getInstance().getCode();
//        image.setImageBitmap(bitmap);
//        image.setOnClickListener(new View.OnClickListener() {//            @Override
//            public void onClick(View view) {//                bitmap = CodeUtils.getInstance().createBitmap();
//                code = CodeUtils.getInstance().getCode();
//                image.setImageBitmap(bitmap);
//                Toast.makeText(RegisterActivity.this, code, Toast.LENGTH_SHORT).show();
//            }
//        });}//验证码
//    private void reacode() {//
//        //将验证码用图片的形式显示出来
//        iv_showCode.setImageBitmap(CodeUtils.getInstance().createBitmap());
//        realCode =CodeUtils.getInstance().getCode();
//    }private void init() {// TODO Auto-generated method stub//从main_title_bar.xml页面布局中获取对应的UI控件//抽取成员变量ctrl+alt+Ftv_main_title = (TextView) findViewById(R.id.tv_main_title);tv_main_title.setText("注册");tv_back = ((TextView) findViewById(R.id.tv_back));rl_title_bar = (RelativeLayout) findViewById(R.id.title_bar);
//        rl_title_bar.setBackgroundColor(Color.TRANSPARENT);rl_title_bar.setBackgroundColor(Color.parseColor("#30b4ff"));//从activity_register.xml页面布局中获取对应的UI控件btn_register = (Button) findViewById(R.id.btn_register);et_user_name = (EditText) findViewById(R.id.et_user_name);et_pwd = (EditText) findViewById(R.id.et_pwd);et_pwd_again = (EditText) findViewById(R.id.et_pwd_again);//验证码et_phoneCode = (EditText) findViewById(R.id.et_phoneCodes);iv_showCode = (ImageView) findViewById(R.id.iv_showCode);
//        //图片验证码刷新
//        iv_showCode.setOnClickListener(new View.OnClickListener() {//
//            @Override
//            public void onClick(View arg0) {//                // TODO Auto-generated method stub
//                iv_showCode.setImageBitmap(CodeUtils.getInstance().createBitmap());
//                realCode = CodeUtils.getInstance().getCode();
//            }
//        });tv_back.setOnClickListener(new View.OnClickListener() {@Override//关闭页面的点击事件public void onClick(View view) {//设置按钮可以关闭当前页面RegisterActivity.this.finish();}});//注册按钮点击事件btn_register.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//点击后获取输入在响应控件中的字符串getEditstring();//判断字符串是否为空if(TextUtils.isEmpty(username)){Toast.makeText(RegisterActivity.this, "请输入用户名", Toast.LENGTH_SHORT).show();return;}else if (TextUtils.isEmpty(pwd)){Toast.makeText(RegisterActivity.this, "请输入密码", Toast.LENGTH_SHORT).show();return;}else if (TextUtils.isEmpty(pwd_again)){Toast.makeText(RegisterActivity.this, "请再次输入密码", Toast.LENGTH_SHORT).show();return;}else if (!pwd.equals(pwd_again)){Toast.makeText(RegisterActivity.this, "两次输入的密码不一样", Toast.LENGTH_SHORT).show();return;} else if (byOkHttpUtils(username,username,pwd)){Toast.makeText(RegisterActivity.this, "此用户已经存在", Toast.LENGTH_SHORT).show();return;}else {Toast.makeText(RegisterActivity.this, "注册成功", Toast.LENGTH_SHORT).show();//把用户名和密码保存到SharedPreferences里面//byOkHttp(username,username,pwd);saveRegisterInfo(username,pwd);//注册成功后通过Intent把用户名传递到LoginActivity.java中Intent data=new Intent();data.putExtra("username",username);setResult(RESULT_OK,data);//setResult为OK,关闭当前页面RegisterActivity.this.finish();//在登录的时候,如果用户还没有注册则注册。注册成功后把注册成功后的用户名返回给前一个页面}}});}private void saveRegisterInfo(String username, String pwd) {String md5Pwd= MD5Utils.MD5(pwd);//把密码用MD5加密//loginInfo是sp的文件名SharedPreferences sp=getSharedPreferences("loginInfo",MODE_PRIVATE);//通过getSharedPreferences传入loginInfo注册登录相关的信息SharedPreferences.Editor editor = sp.edit();//通过sp.edit()获取到sp的编辑器对象//username作为key,密码作为valueeditor.putString(username,md5Pwd);editor.commit();//提交修改}/*** 从SharedPreferences中读取输入的用户名,判断SharedPreferences中是否有用户名* @return*/
//    private boolean isExistUserName(String username) {//        boolean has_userName=false;//表示是否有用户名
//        SharedPreferences sp=getSharedPreferences("loginInfo",MODE_PRIVATE);
//        String spPwd = sp.getString(username,""); //通过sp.getString传值用户名获取到密码
//        if (!TextUtils.isEmpty(spPwd)){ //判断这个密码是否为空
//            has_userName=true;//该用户是否保存了这一个密码
//        }
//        return has_userName;
//    }public Boolean byOkHttpUtils(String userId,String userName,String password){final Boolean[] flag = {false};OkHttpUtils.get().addParams("userId",userId).addParams("userName",userName).addParams("password",password).url("http://192.168.119.1:8086/register").build().execute(new StringCallback() {@Overridepublic void onError(Call call, Exception e, int i) {}@Overridepublic void onResponse(String response, int i) {if (response.equals("true")) {flag[0] = true;//Toast.makeText(RegisterActivity.this, "注册成功!", Toast.LENGTH_LONG).show();}// else//Toast.makeText(RegisterActivity.this, "注册失败,可能已存在当前账号", Toast.LENGTH_LONG).show();}
//// return response.equals("true");//return return_value.equals("true")}});return flag[0];}
//    private void byOkHttp(String userId,String userName,String password){//        //创建OkHttpClient对象
//        OkHttpClient okHttpClient = new OkHttpClient();
//
//        //建立请求表单,添加上传服务器的参数
//        RequestBody formBody = new FormEncodingBuilder()
//                .add("userId", userId)
//                .add("password", password)
//                .add("userName",userName)
//                .build();
//
//        // 建立请求并绑定数据
//        Request request = new Request.Builder()
//                .url("http://169.254.21.102:8086/register")
//                .post(formBody)
//                .build();
//
        //响应
//        Response response = null;
//        try {//            response = okHttpClient.newCall(request).execute();
//        } catch (IOException e) {//            e.printStackTrace();
//        }
//
//        //获取返回的json数据
//          String return_value = response.body().toString();
//        if(return_value.equals("true")){//            Toast.makeText(RegisterActivity.this, "注册成功!", Toast.LENGTH_LONG).show();
//           // return  true;
//        }
//        else {//           Toast.makeText(RegisterActivity.this, "注册失败,可能已存在当前账号", Toast.LENGTH_LONG).show();
//           // return false;
//        }
//
//    }/*** 获取控件中的字符串*/private void getEditstring() {username=et_user_name.getText().toString().trim();pwd = et_pwd.getText().toString();pwd_again = et_pwd_again.getText().toString().trim();}
}


这里注意也要将接口地址改为你自己电脑的IPv4地址

(3)MD5Utils

package com.example.utils;import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;public class MD5Utils {/*** md5加密的算法* @param text* @return*/public static String MD5(String text){try {MessageDigest digest = MessageDigest.getInstance("md5");byte[] result = digest.digest(text.getBytes());StringBuffer sb=new StringBuffer();for (byte b:result){int number =b & 0xff;String hex=Integer.toHexString(number);if (hex.length()==1){//如果0xff为一个字节sb.append("0"+hex);}else {sb.append(hex);}}return sb.toString();} catch (NoSuchAlgorithmException e) {e.printStackTrace();return "";//如果发生异常}}}

三、数据库

1.数据库就是简单的一个user表

四、SpringBoot端

1.创建springboot项目



注意:在develorper toots,web,sql选中相应右边的选项一共7个

(1)项目基本结构

2.配置文件(pom.xml)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>demo</artifactId><version>0.0.1-SNAPSHOT</version><name>demo</name><description>demo</description><properties><java.version>8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jdbc</artifactId></dependency>
<!--        <dependency>-->
<!--            <groupId>org.springframework.boot</groupId>-->
<!--            <artifactId>spring-boot-starter-data-jpa</artifactId>-->
<!--        </dependency>--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.project-lombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>

3.Controller层(TestController)

package com.example.demo.controller;import com.example.demo.repository.UserRepository;import com.example.demo.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;@RestController
public class TestController {@Autowiredprivate UserRepository userRepository;
//    private JdbcTemplate jdbcTemplate;@RequestMapping(value="/getUsers",method = RequestMethod.GET)@ResponseBodypublic List<User> findAll(){List<User> userList = userRepository.findAll();return  userList;}@RequestMapping(value = "/register",method = RequestMethod.GET)public boolean register(@RequestParam("userId") String userId,@RequestParam("userName") String userName,@RequestParam("password") String password){try {userRepository.register(userId,userName,password);System.out.println("可以正常执行");return true; //注册成功则返回true} catch (Exception e) {e.printStackTrace();}return false;}@RequestMapping(value ="/login",method = RequestMethod.GET)public boolean login(@RequestParam("userId") String userId,@RequestParam("password") String password){User user=null;user = userRepository.login(userId,password);//对比密码,相同则返回true,正常情况会加密解密,为求简单就不那么做了if(user.getPassword().equals(password))return true;return false;}}

4.entity层(User)

package com.example.demo.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {String userId;String userName;String password;public String getUserId() {return userId;}public void setUserId(String userId) {this.userId = userId;}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;}}

5.mapper层(UserMapper)

package com.example.demo.mapper;import com.example.demo.entity.User;
import org.apache.ibatis.annotations.Mapper;import java.util.List;@Mapper
public interface UserMapper {List<User> findAll();void register(String userId, String userName,String password);User login(String userId,String password);// Boolean update(String userId,Boolean status);
}

6.UserRepositoryImpl

package com.example.demo.repository.Impl;import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;import java.util.List;@Repository
public class UserRepositoryImpl implements UserRepository {@AutowiredUserMapper userMapper;@Overridepublic List<User> findAll() {return userMapper.findAll();}@Overridepublic void register(String userId, String userName,String password) {userMapper.register(userId, userName,password);}@Overridepublic User login(String userId, String password) {return userMapper.login(userId,password);}//  @Override// public Boolean update(String userId,Boolean status){return userMapper.update(userId,status);}
}

7.repository层(UserRepository)

package com.example.demo.repository;import com.example.demo.entity.User;import java.util.List;public interface UserRepository {public List<User> findAll();public void register(String userId,String userName,String password);public User login(String userId,String password);// public Boolean update(String userId,Boolean status);
}

8.UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper"><select id="findAll" resultType="com.example.demo.entity.User">select * from user</select><insert id="register" parameterType="com.example.demo.entity.User">insert USER values (#{userId},#{userName},#{password});</insert><select id="login" parameterType="com.example.demo.entity.User" resultType="com.example.demo.entity.User">select *from USER where userId=#{userId}</select><!--    <update id="update" parameterType="com.example.demo.entity.User">-->
<!--        update USER set status=#{status}-->
<!--        where userId = #{userId}-->
<!--    </update>-->
<!--    ,userName=#{userName},password=#{password},-->
</mapper>

9.配置文件(application.properties)


#============ thymeleaf???? ?? start ==============
#????
server.port=8086
spring.thymeleaf.prefix=classpath:/pages/
#????
spring.thymeleaf.suffix=.html
#??
spring.thymeleaf.mode=LEGACYHTML5
#??
spring.thymeleaf.encoding=utf-8
#Servlet????
spring.thymeleaf.servlet.content-type=text/html
#???????,?????????????????
spring.thymeleaf.cache=false
#======================?????============================
#?????
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#????????
#spring.datasource.url=jdbc:mysql://localhost:3306/student?serverTimezone=GMT%2B8&verifyServerCertificate=false&useSSL=false
spring.datasource.url=jdbc:mysql://localhost:3307/testandorid?useUnicode=true&characterEncoding=UTF-8&useSSL=false
#???
spring.datasource.username=root
#??
spring.datasource.password=123456#===================??Mybatis???=======================
#?????????
mybatis.mapper-locations=classpath:mapper/*.xml

1.注意:这里的数据库端口号和数据库改为你自己的


五、功能实现步骤

1.打开数据库

2.运行SpringBoot

3.运行Android

到这里一个简单的Android+SpringBoot前后端分离实现登录注册就结束了,希望能给你带来帮助和启发!有不懂的地方欢迎交流学习

Android+SpringBoot前后端分离实现登录注册相关推荐

  1. springboot前后端分离后权限原理浅谈

    1. 需求描述 最近在梳理springboot前后端分离后的权限管理问题.前段时间,已经把shiro的实现和spring security 的实现进行了初步的了解.如果深入细节,一个篇幅怕是不够.本文 ...

  2. SpringBoot后台管理+Uniapp(混合APP)前端 之 酒店住宿+景点下单管理系统(SpringBoot前后端分离)

    酒店住宿+景点下单管理系统(SpringBoot前后端分离) 之 SpringBoot后台管理+Uniapp(混合APP)前端 SpringBoot前后端分离项目-Thymeleaf模板引擎景区旅游管 ...

  3. 基于SpringBoot前后端分离的众筹系统(附源码)

    基于SpringBoot前后端分离的众筹系统源码下载链接: https://download.csdn.net/download/weixin_47367099/85441573 一.运行步骤 1.环 ...

  4. 基于vue springboot 前后端分离的电影院会员管理系统

    基于vue springboot 前后端分离的电影院会员管理系统 文章目录 基于vue springboot 前后端分离的电影院会员管理系统 前言 一.主要功能 二.运行截图 1.前端package. ...

  5. B站云E办Vue+SpringBoot前后端分离项目——MVC三层架构搭建后台项目

    本项目来源B站云E办,笔记整理了项目搭建的过程和涉及的知识点.对于学习来说,不是复制粘贴代码即可,要知其然知其所以然.希望我的笔记能为大家提供思路,也欢迎各位伙伴的指正. 项目前端学习笔记目录 B站云 ...

  6. 新手摸爬滚打:vue+springboot前后端分离项目演示(三)——axios实现前后端交互

    导语:路漫漫其修远兮,吾将上下而求索 前篇: 新手摸爬滚打:vue+springboot前后端分离项目演示(一)--vue cli创建vue2项目 新手摸爬滚打:vue+springboot前后端分离 ...

  7. SpringBoot前后端分离项目中如何制作前端jar包(类似swaggerUI前端jar包制作方法)

    SpringBoot前后端分离项目中如何制作前端jar包(类似swaggerUI前端jar包制作方法) 可用于SpringBoot引用的前端UI的Jar包,类似于SwaggerUI包 WABJAR介绍 ...

  8. Django前后端分离实现登录验证码功能

    Django前后端分离实现登录验证码功能 当下最流行最热门的开发方式当属前后端分离开发,分工也更加明确与专注,前端也是越来越难,几天不学习就跟不上节奏,一个月不学习可以好不夸张的说,你已经不适合这个行 ...

  9. springboot前后端分离项目(图书+博客+聊天室)

    一.项目简介 项目名称:blc management system(blc MS) 基于Vue CLI4 + SpringBoot开发的前后端分离项目. 基本功能:对博客和书籍进行增删改查,在聊天室点 ...

最新文章

  1. 【Java】Java连接Mysql数据库的demo示例
  2. 【内推】腾讯优图(深圳)实验室招计算机视觉算法实习生
  3. POJ2253 Frogger(最短路径)
  4. java compareTo() 用法注意点
  5. 机器学习接口代码之 Ridge、Lasso、Elasitc Net
  6. 有些文档,本来想整理整理贴出来,
  7. 心有多高 未来就有多远
  8. 容器技术Docker K8s 48 服务网格(ASM)-阿里云服务网格使用
  9. 长文预警-超详细的熊猫烧香病毒分析_01
  10. 站长SEO优化排名选择什么样的站群服务器
  11. 观影感受 之 《都挺好》
  12. 数控车椭圆编程实例带图_数控车床椭圆怎么编程
  13. android.benign病毒,benign virus
  14. Day18-恶魔低语: [递归迭代], 两种方法掌握一下
  15. INET的定制使用OMNET++
  16. 《见识》读书笔记思维导图精华版赏析!
  17. 论坛灌水机与注册机问题
  18. 关于虚拟现实(VR)内容开发综述
  19. java 利用AudioPlayer循环播放音乐
  20. 安卓dip和px相互转换

热门文章

  1. 杭州市安全技术防范行业协会第八届(换届)会员大会暨第八届第一次理事、监事会议顺利召开... 1
  2. 【万字总结】以终为始,详细分析高考志愿该怎么填
  3. 数据分析实战(六):Python 数据清洗 —— XX
  4. windows7搭建phonegap3 Android开发环境
  5. python连接sql server数据库并模糊查询
  6. java中使用句号问号和感叹号分割_逗号,句号,感叹号和问号
  7. 微信小程序之提示框弹框
  8. HDU 1237 简单计算器(模拟)
  9. 【笔记】《Bootstrap实战》——第6章 单页营销网站
  10. nodejs 菜鸟教程,nodejs个人博客