瑞吉外卖-移动端验证码和菜品展示

移动端

短信发送

在阿里云申请

代码实现为:

添加以下两个依赖:

1
2
3
4
5
6
7
8
9
10
11
<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
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* 短信发送工具类
*/
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();
}
}

}

随机生成验证码工具类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.zlw.reggie.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;
}
}

手机验证码登录

image-20220816214823174

准备工作:

image-20220816214856763

准备之后,查看发送验证码和登录的url,为

1
2
"/user/sendMsg",
"/user/login"

因此要在过滤器中添加这两个地址,为了不进行拦截。

1
2
3
4
5
6
7
8
9
10
11
12
//设置那些请求不拦截,,不拦截的是访问的uri,而不是静态js
String [] s = new String[]{
"/employee/login",
"/employee/logout",
"/backend/**",
"/front/**",
"/common/upload",
"/common/download",
"/user/sendMsg",
"/user/login"

};

如果需要进行拦截,与则需要和之前一样的判断,判断是否已经登录,如果登录则放行。

1
2
3
4
5
6
7
8
9
10
//判断移动端的用户:根据userid进行判断是否放行
if (request.getSession().getAttribute("user")!=null){
log.info("是拦截路径,用户已经登录,id为:{}",request.getSession().getAttribute("user"));
long userId = (long) request.getSession().getAttribute("user");

BaseContext.setCurrentId(userId);

filterChain.doFilter(request,response);
return;
}

UserController.java的代码为:

发送验证码的url:

image-20220817111919962

登录的url:

image-20220817111939040

根据以上两个url进行编写Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {

@Autowired
private UserService userService;

/**
* 移动端发送验证码
*/
@PostMapping("/sendMsg")
public R<String> sendMsg(@RequestBody User user, HttpSession httpSession){
//获取手机号
String phone = user.getPhone();
//判断手机号是否为空
if (StringUtils.isNotEmpty(phone)){
//随机生成4为验证码,通过工具类
String code = ValidateCodeUtils.generateValidateCode(4).toString();
log.info("code={}",code);
//使用阿里云提供的短信服务API完成发送短信
// SMSUtils.sendMessage("瑞吉外卖","",phone,integer);

//将生成的验证码保存到session中
httpSession.setAttribute(phone,code);

return R.success("手机验证码短信发送成功");
}
return R.error("短信发送失败");
}
/**
* 移动端进行登录
*/
@PostMapping("/login")
public R<User> login(@RequestBody Map map,HttpSession httpSession){

//获取手机号
String phone = map.get("phone").toString();

//获取验证码
String code = map.gset("code").toString();

//获取session里面的验证码
Object codeInSession = httpSession.getAttribute(phone);
//比较是否相等
if (codeInSession!=null && codeInSession.equals(code)){
//如果相等则登录成功,从数据库中查询user,如果能查询到则是老用户已经注册,直接返回user,如果没有查到则要进行注册
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(User::getPhone,phone);
User user = userService.getOne(lambdaQueryWrapper);

//判断当前手机号对应的用户是否为新用户,如果是新用户则注册。
if (user==null){
user = new User();
user.setPhone(phone);
user.setStatus(1);
userService.save(user);
}
//登录成功,将用户的id加入到session中
httpSession.setAttribute("user",user.getId());
return R.success(user);
}
return R.error("登陆失败");
}

}

导入用户地址薄相关功能代码

image-20220817141604384

AddressBookController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package com.zlw.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zlw.reggie.common.BaseContext;
import com.zlw.reggie.common.R;
import com.zlw.reggie.entity.AddressBook;
import com.zlw.reggie.service.AddressBookService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
* 地址簿管理
*/
@Slf4j
@RestController
@RequestMapping("/addressBook")
public class AddressBookController {

@Autowired
private AddressBookService addressBookService;

/**
* 新增
*/
@PostMapping
public R<AddressBook> save(@RequestBody AddressBook addressBook) {
addressBook.setUserId(BaseContext.getId());
log.info("addressBook:{}", addressBook);
addressBookService.save(addressBook);
return R.success(addressBook);
}

/**
* 设置默认地址
*/
@PutMapping("default")
public R<AddressBook> setDefault(@RequestBody AddressBook addressBook) {
log.info("addressBook:{}", addressBook);
LambdaUpdateWrapper<AddressBook> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(AddressBook::getUserId, BaseContext.getId());
//因为一个用户只能有一个默认地址,下面这个操作是将该用户下的所有地址全部设置为:不是默认地址
wrapper.set(AddressBook::getIsDefault, 0);
//SQL:update address_book set is_default = 0 where user_id = ?
addressBookService.update(wrapper);

//再将该地址设置为默认地址
addressBook.setIsDefault(1);
//SQL:update address_book set is_default = 1 where id = ?
addressBookService.updateById(addressBook);
return R.success(addressBook);
}

/**
* 根据id查询地址
*/
@GetMapping("/{id}")
public R get(@PathVariable Long id) {
AddressBook addressBook = addressBookService.getById(id);
if (addressBook != null) {
return R.success(addressBook);
} else {
return R.error("没有找到该对象");
}
}

/**
* 查询默认地址
*/
@GetMapping("default")
public R<AddressBook> getDefault() {
LambdaQueryWrapper<AddressBook> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(AddressBook::getUserId, BaseContext.getId());
queryWrapper.eq(AddressBook::getIsDefault, 1);

//SQL:select * from address_book where user_id = ? and is_default = 1
AddressBook addressBook = addressBookService.getOne(queryWrapper);

if (null == addressBook) {
return R.error("没有找到该对象");
} else {
return R.success(addressBook);
}
}

/**
* 查询指定用户的全部地址
*/
@GetMapping("/list")
public R<List<AddressBook>> list(AddressBook addressBook) {
addressBook.setUserId(BaseContext.getId());
log.info("addressBook:{}", addressBook);

//条件构造器
LambdaQueryWrapper<AddressBook> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(null != addressBook.getUserId(), AddressBook::getUserId, addressBook.getUserId());
queryWrapper.orderByDesc(AddressBook::getUpdateTime);

//SQL:select * from address_book where user_id = ? order by update_time desc
return R.success(addressBookService.list(queryWrapper));
}
}

image-20220817150645464

image-20220817150700003

菜品展示

需求分析

image-20220817150942789

代码实现

手动修改展示菜品所发送的请求

访问主页时,显示404,不展示菜品,但我们显示菜品的功能已经实现完成,为什么还不能展示呢,

因为前端发送了两次请求分别是categoryListApi和cartListApi

image-20220817161708673

其中categoryListApi的访问地址如下,功能已经实现完成,

image-20220817161737768

但另一个cartListApi(访问购物车内的商品)的访问地址如下。其中/shoppingCart/list还没有实现

image-20220817161906429

因此手动写一个静态的json,先进行展示,先实现页面的展示功能,之后再实现购物车的功能。

cartData.json

1
{"code":1,"msg":null,"data":[],"map":{}}

套餐中菜品的显示

改变后,则可以展示出菜品(但套餐中的套餐菜品不能展示,通过查看url的访问地址,发现没有实现功能):

image-20220817162216889

根据url,进行功能实现:

SetmealController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 移动端展示套餐
* @param setmeal
* @return
*/
@GetMapping("/list")
public R<List<Setmeal>> list(Setmeal setmeal){
LambdaQueryWrapper<Setmeal> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(setmeal.getCategoryId()!=null,Setmeal::getCategoryId,setmeal.getCategoryId());
lambdaQueryWrapper.orderByDesc(Setmeal::getUpdateTime);
lambdaQueryWrapper.eq(Setmeal::getStatus,1);
List<Setmeal> list = setmealService.list(lambdaQueryWrapper);

return R.success(list);
}

以上所有的菜品已经展示成功,

显示口味

但每个菜品都有口味的选择,所以如果选择某个菜品时,要进行口味的选择,应该显示选择规格进行选择,如下。

image-20220817162417361

如果没有口味则显示+号

image-20220817162452821

因此实现上述的功能,展示口味:

DishController.java修改其中list方法的代码,将口味加入进去,运用DishDto

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@GetMapping("/list")
public R<List<DishDto>> list(Dish dish){

LambdaQueryWrapper<Dish> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//根据分类id查询dish表中都有哪些菜品
lambdaQueryWrapper.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId());
lambdaQueryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);

//添加状态,查询状态为1的,1表示起售
lambdaQueryWrapper.eq(Dish::getStatus,1);
List<Dish> list = dishService.list(lambdaQueryWrapper);

//将口味加入进去
List<DishDto> dishDtoList = list.stream().map(((item)->{
DishDto dishDto = new DishDto();
BeanUtils.copyProperties(item,dishDto);
//获取菜品的ID
Long id = item.getId();
LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
lambdaQueryWrapper1.eq(DishFlavor::getDishId,id);
List<DishFlavor> list1 = dishFlavorService.list(lambdaQueryWrapper1);
dishDto.setFlavors(list1);
return dishDto;
})).collect(Collectors.toList());
return R.success(dishDtoList);
}

瑞吉外卖-移动端验证码和菜品展示
http://example.com/2022/08/18/瑞吉外卖-移动端/
作者
zlw
发布于
2022年8月18日
许可协议