苍穹外卖学习笔记(七)

一. 缓存菜品

通过 Redis 来缓存菜品数据,减少数据库查询操作

缓存菜品

根据分类 ID 缓存菜品
key : value

DishController.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
package com.sky.controller.user;

import com.sky.constant.StatusConstant;
import com.sky.entity.Dish;
import com.sky.result.Result;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
* @author Jie.
* @description: TODO
* @date 2024/9/25
* @version: 1.0
*/
@RestController("userDishController")
@RequestMapping("/user/dish")
@Api(tags = "菜品管理")
@Slf4j
public class DishController {

@Autowired
private DishService dishService;

@Autowired
private RedisTemplate redisTemplate;

/**
* 根据分类id查询菜品
*/
@GetMapping("/list")
@ApiOperation("根据分类id查询菜品")
public Result<List<DishVO>> list(Long categoryId) {
//构造redis key
String key = "dish_" + categoryId;
//从redis中获取数据
List<DishVO> list = (List<DishVO>) redisTemplate.opsForValue().get(key);
if (list != null && !list.isEmpty()) {
return Result.success(list);
}
Dish dish = new Dish();
dish.setCategoryId(categoryId);
dish.setStatus(StatusConstant.ENABLE);
//如果缓存中没有数据,查询数据库
list = dishService.listWithFlavor(dish);
redisTemplate.opsForValue().set(key, list);
return Result.success(list);
}
}

清除缓存数据

当我们新增菜品、修改菜品、批量删除菜品、起售、停售菜品时清理缓存
DishController.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package com.sky.controller.admin;

import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Set;

/**
* @author Jie.
* @description: TODO
* @date 2024/9/13
* @version: 1.0
*/
/**
* 菜品管理
*/
@RestController("adminDishController")
@RequestMapping("/admin/dish")
@Slf4j
@Api(tags = "菜品管理")
public class DishController {

@Autowired
private DishService dishService;

@Autowired
private RedisTemplate redisTemplate;

/**
* 新增菜品
*/
@PostMapping
@ApiOperation("新增菜品")
public Result save(@RequestBody DishDTO dishDTO) {
log.info("新增菜品:{}", dishDTO);
dishService.saveWithFlavor(dishDTO);

//清理缓存数据
String key = "dish_" + dishDTO.getCategoryId();
redisTemplate.delete(key);
return Result.success();
}

/**
* 分页查询菜品
*/
@GetMapping("/page")
@ApiOperation("分页查询菜品")
public Result<PageResult> page(DishPageQueryDTO dishPageQueryDTO) {
log.info("分页查询菜品:{}", dishPageQueryDTO);
PageResult pageResult = dishService.pageQuery(dishPageQueryDTO);
return Result.success(pageResult);
}

/**
* 删除菜品
*/
@DeleteMapping
@ApiOperation("删除菜品")
public Result delete(@RequestParam List<Long> ids) {//@RequestParam接收请求参数
log.info("删除菜品:{}", ids);
dishService.deleteBatch(ids);

//清理缓存数据
cleanCache("dish_*");
return Result.success();
}

/**
* 根据id查询菜品
*/
@GetMapping("/{id}")
@ApiOperation("根据id查询菜品")
public Result<DishVO> getById(@PathVariable Long id) {//@PathVariable接收请求路径中的参数
log.info("根据id查询菜品:{}", id);
DishVO dishVO = dishService.getByIdWithFlavor(id);
return Result.success(dishVO);
}

/**
* 修改菜品
*/
@PutMapping
@ApiOperation("修改菜品")
public Result update(@RequestBody DishDTO dishDTO) {
log.info("修改菜品:{}", dishDTO);
dishService.updateWithFlavor(dishDTO);

//清理缓存数据
cleanCache("dish_*");
return Result.success();
}

/**
* 修改菜品状态
*/
@PostMapping("/status/{status}")
@ApiOperation("修改菜品状态")
public Result updateStatus(@RequestParam Long id, @PathVariable Integer status) {//RequestParam接收请求参数,PathVariable接收请求路径中的参数
log.info("修改菜品状态:{}", id);
dishService.updateStatus(id, status);

//清理缓存数据
cleanCache("dish_*");
return Result.success();
}

/**
* 根据分类id查询菜品
*/
@GetMapping("/list")
@ApiOperation("根据分类id查询菜品")
public Result<List<Dish>> listResult(@RequestParam Long categoryId) {
log.info("根据分类id查询菜品:{}", categoryId);
List<Dish> list = dishService.listByCategoryId(categoryId);
return Result.success(list);
}

//清理缓存
private void cleanCache(String pattern) {
Set keys = redisTemplate.keys(pattern);
redisTemplate.delete(keys);
}
}

缓存套餐

Spring Cache

Spring Cache 是一个框架,实现了基于<span style="color:red">注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能

Spring Cache 提供了一层抽象,底层可以切换不同的缓存实现,例如:

  1. EHCache
  2. Caffeine
  3. Redis

maven 坐标

1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
<version>2.7.3</version>
</dependency>

常用注解

注解说明
@EnableCaching开启缓存注解功能,通常加在启动类上
@Cacheable在方法执行前先查询缓存中是否有数据,如果有数据,则直接返回缓存数据;如果没有缓存数据,调用方法并将方法返回值放到缓存中
@CachePut将方法的返回值放到缓存中
@CacheEvict将一条或多条数据从缓存中删除

20241004152341

入门案例

springcachedemo.sql

1
2
3
4
5
6
7
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
`age` int DEFAULT NULL,
PRIMARY KEY (`id`)
);

pom.xml

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
<?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 http://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/>
</parent>
<groupId>com.itheima</groupId>
<artifactId>springcache-demo</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>

<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.1</version>
</dependency>

<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.7.3</version>
</plugin>
</plugins>
</build>
</project>

application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
server:
port: 8888
spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/spring_cache_demo?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: 123456
redis:
host: localhost
port: 6379
database: 1
logging:
level:
com:
itheima:
mapper: debug
service: info
controller: info

CacheDemoApplication.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.itheima;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@Slf4j
@SpringBootApplication
@EnableCaching // 开启缓存
public class CacheDemoApplication {
public static void main(String[] args) {
SpringApplication.run(CacheDemoApplication.class,args);
log.info("项目启动成功...");
}
}

WebMvcConfiguration.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
package com.itheima.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {

/**
* 生成接口文档配置
* @return
*/
@Bean
public Docket docket(){
log.info("准备生成接口文档...");

ApiInfo apiInfo = new ApiInfoBuilder()
.title("接口文档")
.version("2.0")
.description("接口文档")
.build();

Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo)
.select()
//指定生成接口需要扫描的包
.apis(RequestHandlerSelectors.basePackage("com.itheima.controller"))
.paths(PathSelectors.any())
.build();

return docket;
}

/**
* 设置静态资源映射
* @param registry
*/
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
log.info("开始设置静态资源映射...");
registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}

UserController.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
package com.itheima.controller;

import com.itheima.entity.User;
import com.itheima.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {

@Autowired
private UserMapper userMapper;

@PostMapping
@CachePut(cacheNames = "userCache", key = "#user.id")
public User save(@RequestBody User user){
userMapper.insert(user);
return user;
}

@GetMapping
@Cacheable(cacheNames = "userCache", key = "#id")
public User getById(Long id){
User user = userMapper.getById(id);
return user;
}

@DeleteMapping
@CacheEvict(cacheNames = "userCache", key = "#id")
public void deleteById(Long id){
userMapper.deleteById(id);
}

@DeleteMapping("/delAll")
@CacheEvict(cacheNames = "userCache", allEntries = true)
public void deleteAll(){
userMapper.deleteAll();
}
}

User.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.itheima.entity;

import lombok.Data;
import java.io.Serializable;

@Data
public class User implements Serializable {

private static final long serialVersionUID = 1L;

private Long id;

private String name;

private int age;

}

UserMapper.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.itheima.mapper;

import com.itheima.entity.User;
import org.apache.ibatis.annotations.*;

@Mapper
public interface UserMapper{

@Insert("insert into user(name,age) values (#{name},#{age})")
@Options(useGeneratedKeys = true,keyProperty = "id")
void insert(User user);

@Delete("delete from user where id = #{id}")
void deleteById(Long id);

@Delete("delete from user")
void deleteAll();

@Select("select * from user where id = #{id}")
User getById(Long id);
}

套餐管理

  1. 导入 Spring Cache 和 Redis 相关的 Maven 坐标
  2. 在启动类上加入@EnableCaching 注解,开启缓存注解功能
  3. 在用户端接口 SetmealController 的<span style="color:red">list方法上加入@Cacheable 注解
  4. 在管理端接口 SetmealController 的<span style="color:red">save、delete、update、updateStatus等方法上加入@CacheEvict 注解

SkyApplication

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.sky;

import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@SpringBootApplication
@EnableTransactionManagement // 开启注解方式的事务管理
@Slf4j // 自动生成日志记录器
@EnableCaching // 开启缓存
public class SkyApplication {
public static void main(String[] args) {
SpringApplication.run(SkyApplication.class, args);
log.info("server started");
}
}

User 的 SetmealController

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
package com.sky.controller.user;

import com.sky.constant.StatusConstant;
import com.sky.entity.Setmeal;
import com.sky.result.Result;
import com.sky.service.SetmealService;
import com.sky.vo.DishItemVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
* @author Jie.
* @description: TODO
* @date 2024/9/25
* @version: 1.0
*/
@RestController("userSetmealController")
@RequestMapping("/user/setmeal")
@Api(tags = "套餐管理")
@Slf4j
public class SetmealController {

@Autowired
private SetmealService setmealService;

/**
* 根据分类id查询套餐
*/
@GetMapping("/list")
@ApiOperation("套餐列表")
@Cacheable(cacheNames = "setmealCache", key = "#categoryId")
public Result<List<Setmeal>> list(Long categoryId) {
Setmeal setmeal = new Setmeal();
setmeal.setCategoryId(categoryId);
setmeal.setStatus(StatusConstant.ENABLE);

List<Setmeal> list = setmealService.list(setmeal);
return Result.success(list);
}

/**
* 根据套餐id查询包含的菜品
*/
@GetMapping("/dish/{id}")
@ApiOperation("根据套餐id查询包含的菜品")
public Result<List<DishItemVO>> dishList(@PathVariable Long id) {
List<DishItemVO> list = setmealService.getDishItemById(id);
return Result.success(list);
}
}

admin 的 SetmealController

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
package com.sky.controller.admin;

import com.sky.dto.SetmealDTO;
import com.sky.dto.SetmealPageQueryDTO;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.SetmealService;
import com.sky.vo.SetmealVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
* @author Jie.
* @description: TODO
* @date 2024/9/16
* @version: 1.0
*/
@RestController("adminSetmealController")
@RequestMapping("/admin/setmeal")
@Api(tags = "套餐管理")
@Slf4j
public class SetmealController {

@Autowired
private SetmealService setmealService;

/**
* 新增套餐
*/
@PostMapping
@ApiOperation("新增套餐")
@CacheEvict(cacheNames = "setmealCache", key = "#setmealDTO.categoryId")
public Result save(@RequestBody SetmealDTO setmealDTO) {
log.info("新增套餐");
setmealService.saveWithDishes(setmealDTO);
return Result.success();
}

/**
* 分页查询套餐
*/
@GetMapping("/page")
@ApiOperation("分页查询套餐")
public Result<PageResult> page(SetmealPageQueryDTO setmealPageQueryDTO) {
log.info("分页查询套餐:{}", setmealPageQueryDTO);
PageResult pageResult = setmealService.pageQuery(setmealPageQueryDTO);
return Result.success(pageResult);
}

/**
* 删除套餐
*/
@DeleteMapping
@ApiOperation("删除套餐")
@CacheEvict(cacheNames = "setmealCache", allEntries = true)
public Result delete(@RequestParam List<Long> ids) {
log.info("删除套餐:{}", ids);
setmealService.deleteBatch(ids);
return Result.success();
}

/**
* 根据id查询套餐
*/
@GetMapping("/{id}")
@ApiOperation("根据id查询套餐")
public Result<SetmealVO> getById(@PathVariable Long id) {
log.info("根据id查询套餐:{}", id);
SetmealVO setmealVO = setmealService.getByIdWithDish(id);
return Result.success(setmealVO);
}

/**
* 修改套餐
*/
@PutMapping
@ApiOperation("修改套餐")
@CacheEvict(cacheNames = "setmealCache", allEntries = true)
public Result update(@RequestBody SetmealDTO setmealDTO) {
log.info("修改套餐:{}", setmealDTO);
setmealService.updateWithDishes(setmealDTO);
return Result.success();
}

/**
* 修改套餐状态
*/
@PostMapping("/status/{status}")
@ApiOperation("修改套餐状态")
@CacheEvict(cacheNames = "setmealCache", allEntries = true)
public Result updateStatus(@PathVariable Integer status, Long id) {
log.info("修改套餐状态:{}", id);
setmealService.updateStatus(status, id);
return Result.success();
}
}

二. 购物车功能

添加购物车

ShoppingCartController

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
package com.sky.controller.user;

import com.sky.dto.ShoppingCartDTO;
import com.sky.result.Result;
import com.sky.service.ShoppingCartService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* @author Jie.
* @description: TODO
* @date 2024/10/7
* @version: 1.0
*/
@RestController
@RequestMapping("/user/shoppingCart")
@Api(tags = "购物车")
@Slf4j
public class ShoppingCartController {

@Autowired
private ShoppingCartService shoppingCartService;

/**
* 添加购物车
*/
@PostMapping("add")
@ApiOperation(value = "添加购物车")
public Result add(@RequestBody ShoppingCartDTO shoppingCartDTO) {
log.info("添加购物车:{}", shoppingCartDTO);
shoppingCartService.addShoppingCart(shoppingCartDTO);
return Result.success();
}
}

ShoppingCartService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.sky.service;

import com.sky.dto.ShoppingCartDTO;

/**
* @author Jie.
* @description: TODO
* @date 2024/10/7
* @version: 1.0
*/
public interface ShoppingCartService {

/**
* 添加购物车
*/
void addShoppingCart(ShoppingCartDTO shoppingCartDTO);
}

ShoppingCartServiceImpl

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
package com.sky.service.impl;

import com.sky.context.BaseContext;
import com.sky.dto.ShoppingCartDTO;
import com.sky.entity.Dish;
import com.sky.entity.Setmeal;
import com.sky.entity.ShoppingCart;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealMapper;
import com.sky.mapper.ShoppingCartMapper;
import com.sky.service.ShoppingCartService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

/**
* @author Jie.
* @description: TODO
* @date 2024/10/7
* @version: 1.0
*/
@Service
@Slf4j
public class ShoppingCartServiceImpl implements ShoppingCartService {

@Autowired
private ShoppingCartMapper shoppingCartMapper;

@Autowired
private DishMapper dishMapper;

@Autowired
private SetmealMapper setmealMapper;

/**
* 添加购物车
*/
@Override
public void addShoppingCart(ShoppingCartDTO shoppingCartDTO) {
//判断加入购物车的商品是否已经存在
ShoppingCart shoppingCart = new ShoppingCart();
BeanUtils.copyProperties(shoppingCartDTO, shoppingCart);
Long currentId = BaseContext.getCurrentId();
shoppingCart.setUserId(currentId);
//查询购物车列表
List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);
//如果存在,修改商品数量
if (list != null && !list.isEmpty()) {
ShoppingCart cart = list.get(0);
cart.setNumber(cart.getNumber() + 1);//数量加1
shoppingCartMapper.updateById(cart);
}
//如果不存在,添加商品
else {
//判断是菜品还是套餐
Long dishId = shoppingCartDTO.getDishId();
if (dishId != null) {
//菜品
Dish dish = dishMapper.selectById(dishId);
shoppingCart.setName(dish.getName());
shoppingCart.setImage(dish.getImage());
shoppingCart.setAmount(dish.getPrice());
} else {
//套餐
Long setmealId = shoppingCartDTO.getSetmealId();
Setmeal setmeal = setmealMapper.selectById(setmealId);
shoppingCart.setName(setmeal.getName());
shoppingCart.setImage(setmeal.getImage());
shoppingCart.setAmount(setmeal.getPrice());
}
shoppingCart.setNumber(1);
shoppingCart.setCreateTime(LocalDateTime.now());
shoppingCartMapper.insert(shoppingCart);
}
}
}

ShoppingCartMapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.sky.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.sky.entity.ShoppingCart;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

/**
* @author Jie.
* @description: TODO
* @date 2024/10/7
* @version: 1.0
*/
@Mapper
public interface ShoppingCartMapper extends BaseMapper<ShoppingCart> {

/**
* 查询购物车列表
*/
List<ShoppingCart> list(ShoppingCart shoppingCart);
}

ShoppingCartMapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?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.sky.mapper.ShoppingCartMapper">

<select id="list" resultType="com.sky.entity.ShoppingCart">
SELECT * FROM shopping_cart
<where>
<if test="userId != null">
AND user_id = #{userId}
</if>
<if test="setmealId != null">
AND setmeal_id = #{setmealId}
</if>
<if test="dishId != null">
AND dish_id = #{dishId}
</if>
<if test="dishFlavor != null">
AND dish_flavor = #{dishFlavor}
</if>
</where>
</select>
</mapper>

application

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
server:
port: 8080

spring:
profiles:
active: dev
main:
allow-circular-references: true
datasource:
druid:
driver-class-name: ${sky.datasource.driver-class-name}
url: jdbc:mysql://${sky.datasource.host}:${sky.datasource.port}/${sky.datasource.database}?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
username: ${sky.datasource.username}
password: ${sky.datasource.password}
redis:
host: ${sky.redis.host}
post: ${sky.redis.post}
database: ${sky.redis.database}

# mybatis-plus配置
mybatis-plus:
configuration:
# 驼峰命名
map-underscore-to-camel-case: true
# 日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
id-type: auto
mapper-locations: classpath:mapper/*.xml

# 日志配置
logging:
level:
com:
sky:
mapper: debug
service: info
controller: info

sky:
jwt:
# 设置jwt签名加密时使用的秘钥
admin-secret-key: itcast
# 设置jwt过期时间
admin-ttl: 720000000
# 设置前端传递过来的令牌名称
admin-token-name: token
# 设置jwt签名加密时使用的秘钥
user-secret-key: itheima
# 设置jwt过期时间
user-ttl: 720000000
# 设置前端传递过来的令牌名称
user-token-name: authentication
alioss:
endpoint: ${sky.alioss.endpoint}
access-key-id: ${sky.alioss.access-key-id}
access-key-secret: ${sky.alioss.access-key-secret}
bucket-name: ${sky.alioss.bucket-name}
wechat:
appid: ${sky.wechat.appid}
secret: ${sky.wechat.secret}

查看购物车

ShoppingCartController

1
2
3
4
5
6
7
8
9
/**
* 查看购物车
*/
@GetMapping("list")
@ApiOperation(value = "查看购物车")
public Result<List<ShoppingCart>> list() {
List<ShoppingCart> list = shoppingCartService.showShoppingCart();
return Result.success(list);
}

ShoppingCartService

1
2
3
4
/**
* 查看购物车
*/
List<ShoppingCart> showShoppingCart();

ShoppingCartServiceImpl

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 查看购物车
*/
@Override
public List<ShoppingCart> showShoppingCart() {
Long currentId = BaseContext.getCurrentId();
ShoppingCart shoppingCart = ShoppingCart.builder()
.userId(currentId)
.build();
List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);
return list;
}

清空购物车

ShoppingCartController

1
2
3
4
5
6
7
8
9
/**
* 清空购物车
*/
@DeleteMapping("clean")
@ApiOperation(value = "清空购物车")
public Result clean() {
shoppingCartService.cleanShoppingCart();
return Result.success();
}

ShoppingCartService

1
2
3
4
/**
* 清空购物车
*/
void cleanShoppingCart();

ShoppingCartServiceImpl

1
2
3
4
5
6
7
8
9
10
/**
* 清空购物车
*/
@Override
public void cleanShoppingCart() {
Long currentId = BaseContext.getCurrentId();
LambdaQueryWrapper<ShoppingCart> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(ShoppingCart::getUserId, currentId);
shoppingCartMapper.delete(wrapper);
}

删除购物车中一个商品

ShoppingCartController

1
2
3
4
5
6
7
8
9
/**
* 删除购物车中一个商品
*/
@PostMapping("/sub")
public Result sub(@RequestBody ShoppingCartDTO shoppingCartDTO) {
log.info("删除购物车中一个商品:{}", shoppingCartDTO);
shoppingCartService.subShoppingCart(shoppingCartDTO);
return Result.success();
}

ShoppingCartService

1
2
3
4
/**
* 删除购物车商品
*/
void subShoppingCart(ShoppingCartDTO shoppingCartDTO);

ShoppingCartServiceImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 删除购物车商品
*/
@Override
public void subShoppingCart(ShoppingCartDTO shoppingCartDTO) {
ShoppingCart shoppingCart = new ShoppingCart();
BeanUtils.copyProperties(shoppingCartDTO, shoppingCart);
Long currentId = BaseContext.getCurrentId();
shoppingCart.setUserId(currentId);
List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);
if (list != null && !list.isEmpty()) {
ShoppingCart cart = list.get(0);
if (cart.getNumber() > 1) {
cart.setNumber(cart.getNumber() - 1);
shoppingCartMapper.updateById(cart);
} else {
shoppingCartMapper.deleteById(cart.getId());
}
}
}