文章目录
1. 顾客登录功能
1.1 需求分析
为了方便顾客登录,移动端通常会使用短信验证码登录的功能。
我们看一下用户登录界面,用户填写手机号,输入验证码,然后进行登录。
1.2 代码开发
1.2.1 梳理交互过程
老规矩,开发之前,我们梳理一下交互过程
- 用户填写手机号码,点击获取验证码,页面发送Ajax请求,在服务端调相应的API给指定的手机号发送验证码短信
- 用户填写验证码,点击登录,页面发送ajax请求,我们服务端接收信息相应本次请求。
1.2.2 开发前准备工作
接下来我们做一下开发之前的准备工作
- 编写User实体类
- 编写UserDao接口
- 编写UserService接口以及UserServiceImpl实现类
- 编写UserController控制层代码
- 导入发送短信的工具类
这里我们就不真正发送短信验证码了,因为发送短信验证码得使用阿里云短信服务或其他短信服务提供商,不仅要钱还难以申请,因此我们将随机产生的验证码在控制台打印,登录的时候我们看一下控制台的验证码进行登录
随机产生短信验证码工具类
ValidateCodeUtils.java
package com.hx.utils;
import java.util.Random;
/**
* 随机生成验证码工具类
*/
public class ValidateCodeUtils {
/**
* 随机生成验证码
* @param length 长度为4位或者6位
* @return
*/
public static Integer generateValidateCode(int length){
Integer code =null;
if(length == 4){
code = new Random().nextInt(9999);//生成随机数,最大为9999
if(code < 1000){
code = code + 1000;//保证随机数为4位数字
}
}else if(length == 6){
code = new Random().nextInt(999999);//生成随机数,最大为999999
if(code < 100000){
code = code + 100000;//保证随机数为6位数字
}
}else{
throw new RuntimeException("只能生成4位或6位数字验证码");
}
return code;
}
/**
* 随机生成指定长度字符串验证码
* @param length 长度
* @return
*/
public static String generateValidateCode4String(int length){
Random rdm = new Random();
String hash1 = Integer.toHexString(rdm.nextInt());
String capstr = hash1.substring(0, length);
return capstr;
}
}
短信发送工具类SMSUtils
package com.hx.utils;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
/**
* 短信发送工具类
*/
public class SMSUtils {
/**
* 发送短信
* @param signName 签名
* @param templateCode 模板
* @param phoneNumbers 手机号
* @param param 参数
*/
public static void sendMessage(String signName, String templateCode,String phoneNumbers,String param){
DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "", "");
IAcsClient client = new DefaultAcsClient(profile);
SendSmsRequest request = new SendSmsRequest();
request.setSysRegionId("cn-hangzhou");
request.setPhoneNumbers(phoneNumbers);
request.setSignName(signName);
request.setTemplateCode(templateCode);
request.setTemplateParam("{\"code\":\""+param+"\"}");
try {
SendSmsResponse response = client.getAcsResponse(request);
System.out.println("短信发送成功");
}catch (ClientException e) {
e.printStackTrace();
}
}
}
需要注意的是,如果使用该发送短信工具类还需要导入相对应的Maven坐标
<!--阿里云短信服务-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.5.16</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>2.1.0</version>
</dependency>
1.2.3 发送短信验证码
前面我们完成了LoginCheckFilter过滤器开发,用于检测用户的登陆状态,我们在进行手机验证码登录时,发送的请求需要在此过滤器处理时直接放行。
ok,接下来我们填写手机号,发送验证码
页面发送POST请求,并将手机号提交到服务端,接下来我们在服务端响应此次请求
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/sendMsg")
public R<String> sendMsg(@RequestBody User user, HttpSession session) {
log.info(user.toString());
//获取手机号
String phone = user.getPhone();
if (Strings.isNotEmpty(phone)) {
//生成验证码
String code = ValidateCodeUtils.generateValidateCode(4).toString();
log.info("code:{}", code);
//调用阿里云提供的短信服务API完成发送短信
//SMSUtils.sendMessage("","","",code);
//将手机号作为key,code验证码作为值存入session
session.setAttribute(phone, code);
return R.success("发送成功");
}
return R.error("发送失败");
}
}
点击发送验证码后需要将手机号和验证码存入session,在登录时我们才能取出session中的验证码和用户输入的验证码比对,进行登录操作
1.2.4 用户登录功能
用户填写验证码点击登录,页面发送ajax请求,将手机号以及验证码提交服务端,我们编写代码响应此次请求。
可以看到,页面提交的参数是以键值对形式提交,也可以说是json格式,但我们没有定义手机号和验证码这样的类,因此,我们可以使用map集合去接收这种键值对的数据。
@PostMapping("/login")
public R<User> login(@RequestBody Map map, HttpSession session) {
log.info(map.toString());
//获取手机号
String phone = map.get("phone").toString();
//获取验证码
String code = map.get("code").toString();
//获取session中的验证码
String codeInSession = session.getAttribute(phone).toString();
//判断验证码是否相同
if (codeInSession != null && codeInSession.equals(code)) {
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getPhone, phone);
User user = userService.getOne(queryWrapper);
if(user == null){
user = new User();
user.setPhone(phone);
user.setStatus(1);
userService.save(user);
}
session.setAttribute("user",user.getId());
return R.success(user);
}
return R.error("登录失败");
}
登录成功前我们还需要将用户的id存入session,然后在过滤器添加判断条件,如果session中的user不为null,我们就将用户id存入我们的BaseContent中,然后放行,登录成功。用户id在接下去的操作中有大用途。
1.3 用户退出功能开发
用户点击退出按钮,页面切换到登录界面。我们只需要响应一下操作成功的信号,并将session中的user信息删除即可。
@PostMapping("/loginout")
public R<String> Logout(HttpSession session){
session.removeAttribute("user");
return R.success("退出成功");
}
用户登录和退出功能到这里我们就解释完毕了。
2. 收货地址功能开发
2.1 需求分析
用户点击个人中心的地址管理,进入地址管理页面,可以添加收货地址,查看收货地址,设置默认收货地址。接下来我们就需要响应这三种情况的请求。
2.2 新增收货地址
我们梳理一下交互过程:用户填写收货地址相关的信息,点击保存,页面发送ajax请求,将用户填写的信息以json的格式提交给服务端,我们就需要在服务端添加方法响应该次请求。
@RestController
@RequestMapping("/addressBook")
@Slf4j
public class AddressBookController {
@Autowired
public AddressBookService addressBookService;
/**
* 新增收获地址
* @param addressBook
* @return
*/
@PostMapping
public R<AddressBook> saveAddress(@RequestBody AddressBook addressBook){
addressBook.setUserId(BaseContent.getCurrentId());
log.info(addressBook.toString());
addressBookService.save(addressBook);
return R.success(addressBook);
}
}
2.3 查看收货地址
我们点击收获地址,页面就会发送ajax请求,查询当前用户添加的收获地址
@GetMapping("/list")
public R<List<AddressBook>> list(Long id){
id = BaseContent.getCurrentId();
log.info(id.toString());
LambdaQueryWrapper<AddressBook> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(AddressBook::getUserId,id);
List<AddressBook> addressBookList = addressBookService.list(queryWrapper);
return R.success(addressBookList);
}
2.4 设置默认地址
当用户有多个收获地址时,我们可以新增一个默认 地址选项,用户以后下单时就会默认使用该用户的默认地址。
用户点击默认地址按钮,页面发送ajax请求,将当前用户的id传给服务端,我们在服务端响应此次请求。
@PutMapping("/default")
public R<AddressBook> setDefault(@RequestBody AddressBook addressBook){
//获取当前id对应的地址信息
LambdaUpdateWrapper<AddressBook> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(AddressBook::getUserId,BaseContent.getCurrentId());
//将当前id所有的地址都设置成非默认地址
updateWrapper.set(AddressBook::getIsDefault,0);
addressBookService.update(updateWrapper);
//再将当前选择的地址设置为默认地址
addressBook.setIsDefault(1);
addressBookService.updateById(addressBook);
return R.success(addressBook);
}
ok,用户收获地址的开发功能到这里就结束了,看到这里的小伙伴记得点赞支持一下,前几天有点忙,就拖更到现在,呜呜呜呜。。。
接下去我会继续将用户添加购物车和下单以及用户订单界面的笔记陆续补上,感兴趣的关注一下,我们不见不散。