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


<?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.CircleImageView
android: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" />
<EditText
android: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"/>
<EditText
android: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"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="35dp"
android:layout_marginRight="35dp"
android:layout_marginTop="20dp"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="@drawable/linearlayout" >
<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:textColor="#000000"
android:textColorHint="#a3a3a3"
android:hint="请输入右侧验证码" />
</LinearLayout>
<ImageView
android:id="@+id/iv_showCode"
android:layout_width="100dp"
android:layout_marginLeft="10dp"
android:layout_height="match_parent" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginLeft="35dp"
android:orientation="horizontal">
<CheckBox
android:id="@+id/cb_box"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="记住密码"/>
</LinearLayout>
<Button
android: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"/>
<LinearLayout
android: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">
<TextView
android: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"/>
<TextView
android: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>
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;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.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 stub
tv_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() {
@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 arg0) {
// TODO Auto-generated method stub
LoginActivity.this.finish();
}
});
//立即注册控件的点击事件
tv_register.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent(LoginActivity.this, RegisterActivity.class);
startActivityForResult(intent, 1);
}
});
//找回密码点击事件
tv_find_pwd.setOnClickListener(new View.OnClickListener() {
@Override
public 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() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
username = 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() {
@Override
public void onError(Call call, Exception e, int i) {
}
@Override
public 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() {
@Override
public void onError(Call call, Exception e, int i) {
}
@Override
public 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地址

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;
}
}
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 Settings
private 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);
}
}
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;
}
}
}
implementation 'com.squareup.okhttp3:okhttp:3.14.0'
implementation 'com.squareup.okhttp:okhttp:2.7.5'
implementation 'com.zhy:okhttputils:2.6.2'
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>


<?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.CircleImageView
android:layout_width="wrap_content"
android:layout_height="150dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:contentDescription="@null"
android:src="@drawable/logo1" />
<EditText
android: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"/>
<EditText
android: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" />
<EditText
android: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"/>
<LinearLayout
android: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">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android: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" />
<View
android:layout_width="0.1dp"
android:layout_height="match_parent"
android:background="#FF7F00" />
<EditText
android: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" />-->
<Button
android: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>
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;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.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+F
tv_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() {
@Override
public 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,密码作为value
editor.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() {
@Override
public void onError(Call call, Exception e, int i) {
}
@Override
public 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地址
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 "";//如果发生异常
}
}
}



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

<?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>
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 {
@Autowired
private UserRepository userRepository;
// private JdbcTemplate jdbcTemplate;
@RequestMapping(value="/getUsers",method = RequestMethod.GET)
@ResponseBody
public 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;
}
}
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;
}
}
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);
}
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 {
@Autowired
UserMapper userMapper;
@Override
public List<User> findAll() {
return userMapper.findAll();
}
@Override
public void register(String userId, String userName,String password) {
userMapper.register(userId, userName,password);
}
@Override
public User login(String userId, String password) {
return userMapper.login(userId,password);
}
// @Override
// public Boolean update(String userId,Boolean status){return userMapper.update(userId,status);}
}
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);
}
<?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>
#============ 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





到这里一个简单的Android+SpringBoot前后端分离实现登录注册就结束了,希望能给你带来帮助和启发!有不懂的地方欢迎交流学习😊😊😊
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO
作为新的阿里云用户,您可以50免费试用多种优惠,价值高达1,700美元(或8,500美元)。这将让您了解和体验阿里云平台上提供的一系列产品和服务。如果您以个人身份注册免费试用,您将获得价值1,700美元的优惠。但是,如果您是注册公司,您可以选择企业免费试用,提交基本信息通过企业实名注册验证,即可开始价值$8,500的免费试用!本教程介绍了如何设置您的帐户并使用您的免费试用版。关于免费试用在我们开始此试用之前,您还必须遵守以下条款和条件才能访问您的免费试用:只有在一年内创建的账户才有资格获得阿里云免费试用。通过此免费试用优惠,用户可以免费试用免费试用活动页面上列出的每种产品一次。如果您有多个帐
遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg
最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路
通常,数组被实现为内存块,集合被实现为HashMap,有序集合被实现为跳跃列表。在Ruby中也是如此吗?我正在尝试从性能和内存占用方面评估Ruby中不同容器的使用情况 最佳答案 数组是Ruby核心库的一部分。每个Ruby实现都有自己的数组实现。Ruby语言规范只规定了Ruby数组的行为,并没有规定任何特定的实现策略。它甚至没有指定任何会强制或至少建议特定实现策略的性能约束。然而,大多数Rubyist对数组的性能特征有一些期望,这会迫使不符合它们的实现变得默默无闻,因为实际上没有人会使用它:插入、前置或追加以及删除元素的最坏情况步骤复
我在我的项目中有一个用户和一个管理员角色。我使用Devise创建了身份验证。在我的管理员角色中,我没有任何确认。在我的用户模型中,我有以下内容:devise:database_authenticatable,:confirmable,:recoverable,:rememberable,:trackable,:validatable,:timeoutable,:registerable#Setupaccessible(orprotected)attributesforyourmodelattr_accessible:email,:username,:prename,:surname,:
在ruby中,你可以这样做:classThingpublicdeff1puts"f1"endprivatedeff2puts"f2"endpublicdeff3puts"f3"endprivatedeff4puts"f4"endend现在f1和f3是公共(public)的,f2和f4是私有(private)的。内部发生了什么,允许您调用一个类方法,然后更改方法定义?我怎样才能实现相同的功能(表面上是创建我自己的java之类的注释)例如...classThingfundeff1puts"hey"endnotfundeff2puts"hey"endendfun和notfun将更改以下函数定