该篇是一刷黑马程序员的苍穹外卖项目记录的笔记,参考了Purse Wind这个博主的博客(写的真心不错我觉得)
Day1开发环境搭建


nginx反向代理-网关
①提高访问速度、②进行负载均衡、③保证后端服务的安全
反向代理配置方式(在nginx软件的配置文件中进行设置),请求路径中含有api

通过proxy_pass指令进行配置http://localhost/api/employee/login--\>http://localhost:8080/admin/employee/login
负载均衡方式


MD5加密(单向的)

Swagger
帮助后端生成接口文档,可以进行在线接口测试

①导入knife4j坐标,②在配置类中加入knife4j相关配置,③设置静态资源映射,否则接口文档页面无法访问
Yapi是设计阶段使用的工具,管理和维护接口。Swagger在开发阶段使用的框架,帮助后端开发人员做后端的接口测试。
常用注解

通过注解影响原始参数的生成,使文档有更好的可读性。
代码模块说明

|--------|--------------|--------------------------------------------|
| 序号 | 名称 | 说明 |
| 1 | sky-take-out | meaven父工程,统一管理依赖版本,聚合其他子模块 |
| 2 | sky-common | 子模块,存放公共类,例如:工具类、常量类、异常类等 |
| 3 | sky-pojo | 子模块,存放实体类、VO、DTO等 |
| 4 | sky-server | 子模块,后端服务,存放配置文件、Controller、Service、Mapper等 |
sky-common:存放公共类,供其他模块使用

每个包的作用:
| 名称 | 说明 |
|---|---|
| constant | 存放相关常量类 |
| context | 存放上下文类 |
| enumeration | 项目的枚举类存储 |
| exception | 存放自定义异常类 |
| json | 处理json转换的类 |
| properties | 存放SpringBoot相关的配置属性类 |
| result | 返回结果类的封装 |
| utils | 常用工具类 |
sky-pojo:模块里存放的是entity、DTO、VO

| 名称 | 说明 |
|---|---|
| Entity | 实体,通常和数据库中的表对应 |
| DTO | 数据传输对象,通常用于程序中各层之间传递数据 |
| VO | 视图对象,为前端展示数据提供的对象 |
| POJO | 普通Java对象,只有属性和对应的getter和setter |
sky-server:模块中存放配置文件、配置类、拦截器、controller、service、mapper、启动类

| 名称 | 说明 |
|---|---|
| config | 存放配置类 |
| controller | 存放controller类 |
| interceptor | 存放拦截器类 |
| mapper | 存放mapper接口 |
| service | 存放service类 |
| SkyApplication | 启动类 |
版权声明:本文为CSDN博主「Purse Wind」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/chan12345678910/article/details/147051485
Day2员工管理和分类操作

Day02-03配置好token之后如果出现401可以修改一下token(有时效性),换一个再运行。或者检查sql语句,下面的要是驼峰。代码修改完之后要再Debug才会生效
ThreadLocal并不是一个Thread,而是Thread的局部变量,为每一个线程提供单独一份的存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。
Page中的limit是通过TreadLocal传到Mapper层的。
新增员工
1 需求分析和设计

注意事项:
-
账号必须是唯一的
-
手机号为合法的11位手机号码
-
身份证号为合法的18位身份证号码
-
密码默认为123456
2 接口设计

3 代码开发
根据新增员工接口设计对应的DTO

3.1 controller层
进入到sky-server模块中,在com.sky.controller.admin包下,在EmployeeController中创建新增员工方法,接收前端提交的参数。
java
/**
* 新增员工
* @param employeeDTO
* @return
*/
@PostMapping
@ApiOperation("新增员工")
public Result save(@RequestBody EmployeeDTO employeeDTO){
log.info("新增员工:{}",employeeDTO);
employeeService.save(employeeDTO);//该方法后续步骤会定义
return Result.success();
}
**注:**Result类定义了后端统一返回结果格式。
进入sky-common模块,在com.sky.result包下定义了Result.java
java
package com.sky.result;
import lombok.Data;
import java.io.Serializable;
/**
* 后端统一返回结果
* @param <T>
*/
@Data
public class Result<T> implements Serializable {
private Integer code; //编码:1成功,0和其它数字为失败
private String msg; //错误信息
private T data; //数据
public static <T> Result<T> success() {
Result<T> result = new Result<T>();
result.code = 1;
return result;
}
public static <T> Result<T> success(T object) {
Result<T> result = new Result<T>();
result.data = object;
result.code = 1;
return result;
}
public static <T> Result<T> error(String msg) {
Result result = new Result();
result.msg = msg;
result.code = 0;
return result;
}
}
3.2 Servicer层接口
在EmployeeService接口中声明新增员工方法
进入到sky-server模块中,com.sky.server.EmployeeService
java
/**
* 新增员工
* @param employeeDTO
*/
void save(EmployeeDTO employeeDTO);
3.3 Servicer层实现类
在EmployeeServiceImpl中实现新增员工方法
com.sky.server.impl.EmployeeServiceImpl中创建方法
java
/**
* 新增员工
*
* @param employeeDTO
*/
public void save(EmployeeDTO employeeDTO) {
Employee employee = new Employee();
//对象属性拷贝
BeanUtils.copyProperties(employeeDTO, employee);
//设置账号的状态,默认正常状态 1表示正常 0表示锁定
employee.setStatus(StatusConstant.ENABLE);
//设置密码,默认密码123456
employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));
//设置当前记录的创建时间和修改时间
employee.setCreateTime(LocalDateTime.now());
employee.setUpdateTime(LocalDateTime.now());
//设置当前记录创建人id和修改人id
employee.setCreateUser(10L);//目前写个假数据,后期修改
employee.setUpdateUser(10L);
employeeMapper.insert(employee);//后续步骤定义
}
3.4 Mapper层
在EmployeeMapper中声明insert方法
com.sky.EmployeeMapper中添加方法
java
/**
* 插入员工数据
* @param employee
*/
@Insert("insert into employee (name, username, password, phone, sex, id_number, create_time, update_time, create_user, update_user,status) " +
"values " +
"(#{name},#{username},#{password},#{phone},#{sex},#{idNumber},#{createTime},#{updateTime},#{createUser},#{updateUser},#{status})")
void insert(Employee employee);
在application.yml中已开启驼峰命名,故id_number和idNumber可对应。
java
mybatis:
configuration:
#开启驼峰命名
map-underscore-to-camel-case: true
Day3菜品管理分类
公共字段填充

技术点:枚举、注解、AOP、反射
自定义AutoFill,用于标识需要进行公共字段自动填充的方法
自定义切面类AutoFillAspect,统一拦截加入了AutoFill注解的方法,通过反射为公共字段复制
在Mapper的方法上加入AutoFill注解
前端登录不进去有可能是8080端口被占用了,终止当前进程或者开始另一个端口就行。
# 只查看 LISTENING(监听)状态
netstat -ano | findstr :8080 | findstr LISTENING
# 或者查看所有 8080 相关连接
netstat -ano | findstr :8080
如果显示
TCP 192.168.1.109:50763 157.148.59.148:8080 ESTABLISHED 3300
# 结束使用该连接的进程
taskkill /F /PID 3300
# 或者根据进程名判断
tasklist | findstr 3300
新增菜品
产品原型

业务规则:
- 菜品名称是唯一的
- 菜品必须属于某个分类下,不能单独存在
- 新增菜品时可以根据情况选择菜品的口味
- 每个菜品必须对应一张图片
接口设计
- 根据类型查询分类
- 文件上传
- 新增菜品
接口设计



数据库设计

浏览器->后端服务->阿里云,参考下面这篇博客配置阿里云服务
苍穹外卖项目实战(日记九)-新增菜品文件上传(使用阿里云OSS对象存储服务的方法)-记录实战教程及问题的解决方法-CSDN博客
Day5 店铺营业设置状态
Redis技术
Redis是一个基于内存的key-value结构数据库,基于内存存储,读写性高,适合存储热点数据(是对于MySQL的补充)。
key是字符串类型,value有5种常用的数据类型(字符串string,哈希hash,列表list,集合set,有序集合sorted set/zset)
字符串操作命令

哈希操作命令

列表操作命令

集合操作命令

有序集合操作命令

通用命令

店铺营业状态设置
产品原型

接口设计


Day6-微信登陆、商品浏览
HttpClient:客户端编程的工具包,是Apache Jakarta Common下的子项目,可以用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议,只需要导入http坐标就可以在JAVA中使用。
微信小程序开发
电脑重启需要重新连接数据库和redis
①win+R输入services.msc找到mysql和redis手动打开,cmd窗口输入"mysql.exe所在路径" -uroot -p输入密码即可,redis如果没在目录中找到说明安装了绿色版,则在redis目录里
redis-server.exe redis.windows.conf
再打开一个输入
redis-cli.exe -h 127.0.0.1 -p 6379 -a 你的密码
127.0.0.1:6379> ping
PONG
然后把mysql和前端打开即可
exit退出数据可和mysql
这里有些代码可能是课程作业然后出现了一些问题,我也是调了好久终于调通了。

sky-common.src.main.java.com.sky.contant.messageConstant里面新加一个常量类
public static final String SETMEAL_NOT_FOUND = "套餐不存在";
完整代码如下
java
package com.sky.constant;
/**
* 信息提示常量类
*/
public class MessageConstant {
public static final String PASSWORD_ERROR = "密码错误";
public static final String ACCOUNT_NOT_FOUND = "账号不存在";
public static final String ACCOUNT_LOCKED = "账号被锁定";
public static final String UNKNOWN_ERROR = "未知错误";
public static final String ALREADY_EXISTS = "已存在";
public static final String USER_NOT_LOGIN = "用户未登录";
public static final String CATEGORY_BE_RELATED_BY_SETMEAL = "当前分类关联了套餐,不能删除";
public static final String CATEGORY_BE_RELATED_BY_DISH = "当前分类关联了菜品,不能删除";
public static final String SHOPPING_CART_IS_NULL = "购物车数据为空,不能下单";
public static final String ADDRESS_BOOK_IS_NULL = "用户地址为空,不能下单";
public static final String LOGIN_FAILED = "登录失败";
public static final String UPLOAD_FAILED = "文件上传失败";
public static final String SETMEAL_ENABLE_FAILED = "套餐内包含未启售菜品,无法启售";
public static final String PASSWORD_EDIT_FAILED = "密码修改失败";
public static final String DISH_ON_SALE = "起售中的菜品不能删除";
public static final String SETMEAL_ON_SALE = "起售中的套餐不能删除";
public static final String DISH_BE_RELATED_BY_SETMEAL = "当前菜品关联了套餐,不能删除";
public static final String ORDER_STATUS_ERROR = "订单状态错误";
public static final String ORDER_NOT_FOUND = "订单不存在";
public static final String SETMEAL_NOT_FOUND = "套餐不存在";
}

sky-server.src.main.java.com.sky.config.WebMvcConfiguration
java
package com.sky.config;
import com.sky.interceptor.JwtTokenAdminInterceptor;
import com.sky.interceptor.JwtTokenUserInterceptor;
import com.sky.json.JacksonObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.cbor.MappingJackson2CborHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
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;
import java.util.List;
/**
* 配置类,注册web层相关组件
*/
@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
@Autowired
private JwtTokenAdminInterceptor jwtTokenAdminInterceptor;
@Autowired
private JwtTokenUserInterceptor jwtTokenUserInterceptor;
/**
* 注册自定义拦截器
*
* @param registry
*/
protected void addInterceptors(InterceptorRegistry registry) {
log.info("开始注册自定义拦截器...");
registry.addInterceptor(jwtTokenAdminInterceptor)
.addPathPatterns("/admin/**")
.excludePathPatterns("/admin/employee/login");
registry.addInterceptor(jwtTokenUserInterceptor)
.addPathPatterns("/user/**")
.excludePathPatterns("/user/user/login")
.excludePathPatterns("/user/shop/status");
}
/**
* 通过knife4j生成接口文档
* @return
*/
@Bean
public Docket docket1() {
log.info("准备生成接口文档...");
ApiInfo apiInfo = new ApiInfoBuilder()
.title("苍穹外卖项目接口文档")
.version("2.0")
.description("苍穹外卖项目接口文档")
.build();
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.groupName("管理端接口")
.apiInfo(apiInfo)
.select()
.apis(RequestHandlerSelectors.basePackage("com.sky.controller.admin"))
.paths(PathSelectors.any())
.build();
return docket;
}
@Bean
public Docket docket2() {
log.info("准备生成接口文档...");
ApiInfo apiInfo = new ApiInfoBuilder()
.title("苍穹外卖项目接口文档")
.version("2.0")
.description("苍穹外卖项目接口文档")
.build();
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.groupName("用户端接口")
.apiInfo(apiInfo)
.select()
.apis(RequestHandlerSelectors.basePackage("com.sky.controller.user"))
.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/");
}
/**
* 扩展Spring MVC框架的消息转化器
* @param converters
*/
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
log.info("扩展消息转换器");
//创建一个消息转换器
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
//需要为消息转换器设置一个对象转化器,对象转换器可以将JAVA对象序列化为json数据
converter.setObjectMapper(new JacksonObjectMapper());
//将自己的消息转化器加入到自己的容器中
converters.add(0,converter);
}
}
sky-server.src.main.java.com.sky.controller.admin.DishController完整代码
java
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.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/admin/dish")
@Api(tags = "后台菜品管理")
@Slf4j
public class DishController {
@Autowired
private DishService dishService;
/**
* 新增菜品
* @param dishDTO
* @return
*/
@PostMapping
@ApiOperation(value = "新增菜品")
public Result save(@RequestBody DishDTO dishDTO){
log.info("新增菜品:{}", dishDTO);
dishService.saveWithFlavors(dishDTO);
return Result.success();
}
/**
* 分页查询菜品
* @param dishPageQueryDTO
* @return
*/
@GetMapping("/page")
@ApiOperation("分页查询菜品")
public Result<PageResult> page(DishPageQueryDTO dishPageQueryDTO){
log.info("分页查询菜品:{}", dishPageQueryDTO);
PageResult pageResult = dishService.pageQuery(dishPageQueryDTO);
return Result.success(pageResult);
}
/**
* 删除菜品
* @param ids
* @return
*/
@DeleteMapping
@ApiOperation("批量删除菜品")
public Result delete(@RequestParam List<Long> ids){
log.info("删除菜品:{}", ids);
dishService.deleteBatch(ids);
return Result.success();
}
/**
* 根据ID查询菜品详情
* @param id
* @return
*/
@GetMapping("/{id}")
@ApiOperation("根据ID查询菜品详情")
public Result<DishVO> getById(@PathVariable Long id){
log.info("查询菜品:{}", id);
DishVO dishVO = dishService.getByIdWithFlavors(id);
return Result.success(dishVO);
}
@PutMapping
@ApiOperation("更新菜品")
public Result update(@RequestBody DishDTO dishDTO){
log.info("更新菜品:{}", dishDTO);
dishService.updateWithFlavors(dishDTO);
return Result.success();
}
/**
* 根据分类id查询菜品
* @param categoryId
* @return
*/
@GetMapping("/list")
@ApiOperation("根据分类id查询菜品")
public Result<List<Dish>> list(Long categoryId){
List<Dish> list = dishService.list(categoryId);
return Result.success(list);
}
/**
* 菜品起售停售
* @param status
* @param id
* @return
*/
@PostMapping("/status/{status}")
@ApiOperation("菜品起售停售")
public Result<String> startOrStop(@PathVariable Integer status, Long id){
dishService.startOrStop(status,id);
return Result.success();
}
}
sky-server.src.main.java.com.sky.controller.admin.SetmealController完整代码
java
package com.sky.controller.admin;
import com.sky.constant.StatusConstant;
import com.sky.dto.SetmealDTO;
import com.sky.dto.SetmealPageQueryDTO;
import com.sky.entity.Setmeal;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.SetmealService;
import com.sky.vo.DishItemVO;
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.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/admin/setmeal")
@Api(tags = "套餐相关接口")
@Slf4j
public class SetmealController {
@Autowired
private SetmealService setmealService;
/**
* 新增套餐
* @param setmealDTO
* @return
*/
@PostMapping
@ApiOperation("新增套餐")
public Result save(@RequestBody SetmealDTO setmealDTO) {
log.info("新增套餐:{}", setmealDTO);
setmealService.saveWithDish(setmealDTO);
return Result.success();
}
/**
* 条件查询
*
* @param categoryId
* @return
*/
@GetMapping("/list")
@ApiOperation("根据分类id查询套餐")
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查询包含的菜品列表
*
* @param id
* @return
*/
@GetMapping("/dish/{id}")
@ApiOperation("根据套餐id查询包含的菜品列表")
public Result<List<DishItemVO>> dishList(@PathVariable("id") Long id) {
List<DishItemVO> list = setmealService.getDishItemById(id);
return Result.success(list);
}
/**
* 分页查询
* @param setmealPageQueryDTO
* @return
*/
@GetMapping("/page")
@ApiOperation("分页查询")
public Result<PageResult> page(SetmealPageQueryDTO setmealPageQueryDTO) {
PageResult pageResult = setmealService.pageQuery(setmealPageQueryDTO);
return Result.success(pageResult);
}
/**
* 批量删除套餐
* @param ids
* @return
*/
@DeleteMapping
@ApiOperation("批量删除套餐")
public Result delete(@RequestParam List<Long> ids){
log.info("批量删除套餐:{}", ids);
setmealService.delete(ids);
return Result.success();
}
/**
* 根据id获取套餐
* @param id
* @return
*/
@GetMapping("/{id}")
@ApiOperation("根据id获取套餐")
public Result<SetmealVO> getById(@PathVariable("id") Long id){
log.info("根据id获取套餐:{}", id);
SetmealVO setmealVO = setmealService.getById(id);
return Result.success(setmealVO);
}
// /**
// * 修改套餐
// *
// * @param setmealDTO
// * @return
// */
// @PutMapping
// @ApiOperation("修改套餐")
// public Result update(@RequestBody SetmealDTO setmealDTO) {
// setmealService.update(setmealDTO);
// return Result.success();
// }
/**
* 更新套餐
* @param setmealDTO
* @return
*/
@PutMapping
@ApiOperation("更新套餐")
public Result Update(@RequestBody SetmealDTO setmealDTO) {
log.info("更新套餐:{}", setmealDTO);
setmealService.update(setmealDTO);
return Result.success();
}
/**
* 套餐起售停售
* @param status
* @param id
* @return
*/
@PostMapping("/status/{status}")
@ApiOperation("套餐起售停售")
public Result startOrStop(@PathVariable Integer status, Long id) {
setmealService.startOrStop(status, id);
return Result.success();
}
}
sky-server.src.main.java.com.sky.controller.user.CategoryController完整代码
java
package com.sky.controller.user;
import com.sky.entity.Category;
import com.sky.result.Result;
import com.sky.service.CategoryService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
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;
@RestController("userCategoryController")
@RequestMapping("/user/category")
@Api(tags = "C端-分类接口")
public class CategoryController {
@Autowired
private CategoryService categoryService;
/**
* 查询分类
* @param type
* @return
*/
@GetMapping("/list")
@ApiOperation("查询分类")
public Result<List<Category>> list(Integer type) {
List<Category> list = categoryService.list(type);
return Result.success(list);
}
}
sky-server.src.main.java.com.sky.controller.user.DishController完整代码
java
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.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController("userDishController")
@RequestMapping("/user/dish")
@Slf4j
@Api(tags = "C端-菜品浏览接口")
public class DishController {
@Autowired
private DishService dishService;
/**
* 根据分类id查询菜品
*
* @param categoryId
* @return
*/
@GetMapping("/list")
@ApiOperation("根据分类id查询菜品")
public Result<List<DishVO>> list(Long categoryId) {
Dish dish = new Dish();
dish.setCategoryId(categoryId);
dish.setStatus(StatusConstant.ENABLE);//查询起售中的菜品
List<DishVO> list = dishService.listWithFlavor(dish);
return Result.success(list);
}
}

sky-server.src.main.java.com.sky.controller.user.UserController完整代码
java
package com.sky.controller.user;
import com.sky.constant.JwtClaimsConstant;
import com.sky.dto.UserLoginDTO;
import com.sky.entity.User;
import com.sky.properties.JwtProperties;
import com.sky.result.Result;
import com.sky.service.UserService;
import com.sky.utils.JwtUtil;
import com.sky.vo.UserLoginVO;
import io.jsonwebtoken.Claims;
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;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@RestController
@RequestMapping("/user/user")
@Api(tags = "C端用户相关接口")
@Slf4j
public class UserController {
@Autowired
private UserService userService;
@Autowired
private JwtProperties jwtProperties;
/**
* 微信登录
* @param userLoginDTO
* @return
*/
@PostMapping("/login")
@ApiOperation("微信登录")
public Result<UserLoginVO> login(@RequestBody UserLoginDTO userLoginDTO){
log.info("微信用户登录:{}",userLoginDTO.getCode());
//微信登录
User user = userService.wxLogin(userLoginDTO);
//为微信用户生成jwt令牌
Map<String, Object> claims = new HashMap<>();
claims.put(JwtClaimsConstant.USER_ID,user.getId());
String token = JwtUtil.createJWT(jwtProperties.getUserSecretKey(),jwtProperties.getUserTtl(), claims);
UserLoginVO userLoginVO = UserLoginVO.builder()
.id(user.getId())
.openid(user.getOpenid())
.token(token)
.build();
return Result.success(userLoginVO);
}
}
sky-server.src.main.java.com.sky.interceptor.JwtTokenUserInterceptor完整代码
java
package com.sky.interceptor;
import com.sky.constant.JwtClaimsConstant;
import com.sky.context.BaseContext;
import com.sky.properties.JwtProperties;
import com.sky.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* jwt令牌校验的拦截器
*/
@Component
@Slf4j
public class JwtTokenUserInterceptor implements HandlerInterceptor {
@Autowired
private JwtProperties jwtProperties;
/**
* 校验jwt
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//判断当前拦截到的是Controller的方法还是其他资源
if (!(handler instanceof HandlerMethod)) {
//当前拦截到的不是动态方法,直接放行
return true;
}
//1、从请求头中获取令牌
String token = request.getHeader(jwtProperties.getUserTokenName());
//2、校验令牌
try {
log.info("jwt校验:{}", token);
Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);
Long userId = Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString());
log.info("当前用户的id:", userId);
BaseContext.setCurrentId(userId);
//3、通过,放行
return true;
} catch (Exception ex) {
//4、不通过,响应401状态码
response.setStatus(401);
return false;
}
}
}
sky-server.src.main.java.com.sky.mapper.DishMapper完整代码
java
package com.sky.mapper;
import com.github.pagehelper.Page;
import com.sky.annotation.Autofill;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.enumeration.OperationType;
import com.sky.vo.DishVO;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
@Mapper
public interface DishMapper {
/**
* 动态条件查询菜品
* @param dish
* @return
*/
List<Dish> list(Dish dish);
/**
* 根据分类id查询菜品数量
* @param categoryId
* @return
*/
@Select("select count(id) from dish where category_id = #{categoryId}")
Integer countByCategoryId(Long categoryId);
/**
* 插入菜品数据
* @param dish
*/
@Autofill(value = OperationType.INSERT)
void insert(Dish dish);
/**
* 菜品分页查询
* @param dishPageQueryDTO
* @return
*/
Page<DishVO> pageQuery(DishPageQueryDTO dishPageQueryDTO);
/**
* 根据主键查询菜品
* @param id
* @return
*/
@Select("select * from dish where id = #{id}")
Dish getById(Long id);
/**
* 根据主键来删除菜品数据
* @param id
*/
@Delete("delete from dish where id = #{id}")
void deleteById(Long id);
/**
* 根据菜品ID集合批量删除菜品
* @param ids
*/
void deleteByIds(List<Long> ids);
/*
根据ID动态修改菜品
*/
@Autofill(value = OperationType.UPDATE)
void update(Dish dish);
/**
* 根据套餐id查询菜品
* sql语句的意思为根据传进来的id找到对应的套餐,
* 然后再根据该套餐表的dish_id找到对应菜品,最后找到套餐中菜品
* @param id
* @return
*/
@Select("select a.* from dish a, setmeal_dish b where a.id = b.dish_id and b.setmeal_id = #{id}")
List<Dish> getBySetmealId(Long id);
}
sky-server.src.main.java.com.sky.mapper.SetmealDishMapper完整代码
java
package com.sky.mapper;
import com.sky.entity.SetmealDish;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface SetmealDishMapper {
/**
* 根据菜品ID查询对应的套餐ID
* @param dishIds
* @return
*/
//select setmeal_id from setmeal_dish where dish_id in (1,2,3,4)
List<Long> getSetmealIdsByDishIds(List<Long> dishIds);
/**
* 批量保存套餐和菜品的关联关系
* @param setmealDishes
*/
void insertBatch(List<SetmealDish> setmealDishes);
/**
* 根据套餐id删除套餐和菜品的关联关系
* @param setmealId
*/
@Delete("delete from setmeal_dish where setmeal_id = #{setmealId}")
void deleteBySetmealId(Long setmealId);
/**
* 根据套餐id删除套餐菜品
* @param ids
*/
void deleteBySetmealIds(List<Long> ids);
/**
* 根据套餐id获取菜品id
* @param ids
* @return
*/
List<Long> getDishIdsBySetmealIds(List<Long> ids);
/**
* 根据id获取套餐及菜品关联关系
* @param id
* @return
*/
@Select("SELECT * FROM setmeal_dish WHERE id = #{id}")
List<SetmealDish> getBySetmealId(Long id);
}
sky-server.src.main.java.com.sky.mapper.SetmealMapper完整代码
java
package com.sky.mapper;
import com.github.pagehelper.Page;
import com.sky.annotation.Autofill;
import com.sky.annotation.Autofill;
import com.sky.dto.SetmealPageQueryDTO;
import com.sky.entity.Setmeal;
import com.sky.enumeration.OperationType;
import com.sky.vo.DishItemVO;
import com.sky.vo.SetmealVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface SetmealMapper {
/**
* 新增套餐
* @param setmeal
*/
@Autofill(value = OperationType.INSERT)
void insert(Setmeal setmeal);
/**
* 根据分类id查询套餐的数量
* @param id
* @return
*/
@Select("select count(id) from setmeal where category_id = #{categoryId}")
Integer countByCategoryId(Long id);
/**
* 根据id修改套餐
*
* @param setmeal
*/
@Autofill(OperationType.UPDATE)
void update(Setmeal setmeal);
/**
* 分页查询
* @param setmealPageQueryDTO
* @return
*/
Page<SetmealVO> pageQuery(SetmealPageQueryDTO setmealPageQueryDTO);
/**
* 根据id删除套餐
* @param ids
*/
void deleteByIDs(List<Long> ids);
/**
* 根据id查询套餐1
* @param id
* @return
*/
@Select("select * from setmeal where id = #{id}")
Setmeal getByID(Long id);
/**
* 动态条件查询套餐
* @param setmeal
* @return
*/
List<Setmeal> list(Setmeal setmeal);
/**
* 根据套餐id查询菜品选项
* @param setmealId
* @return
*/
@Select("select sd.name, sd.copies, d.image, d.description " +
"from setmeal_dish sd left join dish d on sd.dish_id = d.id " +
"where sd.setmeal_id = #{setmealId}")
List<DishItemVO> getDishItemBySetmealId(Long setmealId);
}
sky-server.src.main.java.com.sky.mapper.UserMapper完整代码
java
package com.sky.mapper;
import com.sky.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface UserMapper {
/**
* 根据openid查询用户
* @param openid
* @return
*/
@Select("select * from user where openid = #{openid}")
User getByOpenid(String openid);
/**
* 插入数据
* @param user
*/
void insert(User user);
}
sky-server.src.main.java.com.sky.service.impl.DishServiceimpl完整代码
java
package com.sky.service.impl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.entity.Setmeal;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.mapper.DishFlavorMapper;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealDishMapper;
import com.sky.mapper.SetmealMapper;
import com.sky.result.PageResult;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
@Service
@Slf4j
public class DishServiceimpl implements DishService {
@Autowired
private DishMapper dishMapper;
@Autowired
private DishFlavorMapper dishFlavorMapper;
@Autowired
private SetmealDishMapper setmealDishMapper;
@Autowired
private SetmealMapper setmealMapper;
/**
* 保存菜品及其配料信息
*@Transactional:由于涉及到多个表的操作,需要使用事务注解,保证操作的原子性
* 事务指一组数据库操作要么全部成功,要么全部失败,如果失败,则回滚到事务开始前的状态
* BeanUtils:用于将dto对象中的属性的值复制到entity对象(dish对象)中
* @param dishDTO
*/
@Transactional
public void saveWithFlavors(DishDTO dishDTO) {
//创建新的dish对象,用于向dish表中插入菜品信息
Dish dish = new Dish();
//将dto对象中的属性复制到dish对象中
BeanUtils.copyProperties(dishDTO, dish);
//向dish表中插入1条菜品信息
dishMapper.insert(dish);
//获取刚插入的菜品的id,id由数据库生成
//这个id将用于向dish_flavor表中插入配料信息
Long dishId = dish.getId();
//向dish_flavor表中插入N个配料信息
List<DishFlavor> flavors = dishDTO.getFlavors();
//判断是否有配料信息
//flavors != null && flavors.size() > :意义是防止空指针异常
if (flavors != null && flavors.size() > 0) {
//给配料信息设置dish_id
flavors.forEach(dishflavor -> {
dishflavor.setDishId(dishId);
});
//向dish_flavor表中插入N条配料信息
dishFlavorMapper.insertBatch(flavors);
}
}
/**
* 分页查询菜品信息
*
* @param dishPageQueryDTO
* @return
*/
public PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO) {
PageHelper.startPage(dishPageQueryDTO.getPage(), dishPageQueryDTO.getPageSize());
Page<DishVO> page = dishMapper.pageQuery(dishPageQueryDTO);
return new PageResult(page.getTotal(), page.getResult());
}
/**
* 根据ID批量删除菜品信息
*
* @param ids
*/
@Transactional//由于涉及到多个表的操作,需要使用事务注解,保证删除操作的原子性
public void deleteBatch(List<Long> ids) {
//判断当前菜品是否能够被删除-是否存在起售中的菜品
for (Long id : ids) {
Dish dish = dishMapper.getById(id);
if (dish.getStatus() == StatusConstant.ENABLE) {
//抛出异常,提示菜品已上架,不能删除
throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
}
}
//是否被关联
List<Long> setmealIds = setmealDishMapper.getSetmealIdsByDishIds(ids);
if (setmealIds != null && setmealIds.size() > 0) {
//抛出异常,提示菜品已关联套餐,不能删除
throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
}
// 方法一:
// 删除菜品信息
// for (Long id : ids) {
// dishMapper.deleteByID(id);
// //删除菜品口味信息
// dishFlavorMapper.deleteByDishId(id);
// }
//方法二:
//sql:delete from dish where id in (?,?,?)
//批量删除菜品信息
dishMapper.deleteByIds(ids);
//sql:delete from dishFlavor where dish_id in (?,?,?)
//批量删除菜品口味信息
dishFlavorMapper.deleteByDishIds(ids);
}
/**
* 根据ID查询菜品及其配料信息
* @param id
* @return
*/
public DishVO getByIdWithFlavors(Long id) {
//根据ID查询菜品
Dish dish = dishMapper.getById(id);
//根据id查询菜品口味信息
List<DishFlavor> dishflavors = dishFlavorMapper.getByDishId(id);
//将菜品和菜品口味信息封装到DishVO对象中
DishVO dishVo = new DishVO();
BeanUtils.copyProperties(dish, dishVo);//将dish对象中的属性复制到dishVo对象中
dishVo.setFlavors(dishflavors);//将dishflavors列表复制到dishVo对象中
return dishVo;
}
/**
* 更新菜品及其配料信息
* @param dishDTO
*/
public void updateWithFlavors(DishDTO dishDTO) {
//创建新的dish对象
Dish dish = new Dish();
//将dto对象中的属性复制到dish对象中
BeanUtils.copyProperties(dishDTO, dish);//将dto对象中的属性复制到dish对象中
//更新菜品信息
dishMapper.update(dish);
//删除原有的菜品口味信息
dishFlavorMapper.deleteByDishId(dishDTO.getId());
//插入新的菜品口味信息
List<DishFlavor> flavors = dishDTO.getFlavors();
//判断是否有配料信息
if (flavors != null && flavors.size() > 0) {
//给配料信息设置dish_id
flavors.forEach(dishflavor -> {
dishflavor.setDishId(dishDTO.getId());
});
//向dish_flavor表中插入N条配料信息
dishFlavorMapper.insertBatch(flavors);
}
}
/**
* 根据分类ID查询菜品列表
* @param categoryId
* @return
*/
public List<Dish> list(Long categoryId) {
Dish dish = Dish.builder()
.categoryId(categoryId)
.status(StatusConstant.ENABLE)
.build();
return dishMapper.list(dish);
}
/**
* 菜品起售停售
*
* @param status
* @param id
*/
@Transactional//由于涉及到多个表的操作,需要使用事务注解,保证操作的原子性
public void startOrStop(Integer status, Long id) {
//更新菜品状态,调用builder模式构建对象
//为什么只使用id和status,而不使用其他属性呢?因为其他属性可能是有值的,
// 比如name、categoryId等,但id和status是必须的,所以只使用这两个属性
Dish dish = Dish.builder()
.id(id)
.status(status)
.build();
dishMapper.update(dish);
if (status == StatusConstant.DISABLE) {
// 如果是停售操作,还需要将包含当前菜品的套餐也停售
List<Long> dishIds = new ArrayList<>();
dishIds.add(id);
// select setmeal_id from setmeal_dish where dish_id in (?,?,?)
List<Long> setmealIds = setmealDishMapper.getSetmealIdsByDishIds(dishIds);
if (setmealIds != null && setmealIds.size() > 0) {
for (Long setmealId : setmealIds) {
Setmeal setmeal = Setmeal.builder()
.id(setmealId)
.status(StatusConstant.DISABLE)
.build();
setmealMapper.update(setmeal);
}
}
}
}
/**
* 条件查询菜品和口味
* @param dish
* @return
*/
public List<DishVO> listWithFlavor(Dish dish) {
List<Dish> dishList = dishMapper.list(dish);
List<DishVO> dishVOList = new ArrayList<>();
for (Dish d : dishList) {
DishVO dishVO = new DishVO();
BeanUtils.copyProperties(d,dishVO);
//根据菜品id查询对应的口味
List<DishFlavor> flavors = dishFlavorMapper.getByDishId(d.getId());
dishVO.setFlavors(flavors);
dishVOList.add(dishVO);
}
return dishVOList;
}
}
sky-server.src.main.java.com.sky.service.impl.SetmealServiceimpl完整代码
java
package com.sky.service.impl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.SetmealDTO;
import com.sky.dto.SetmealPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.entity.Setmeal;
import com.sky.entity.SetmealDish;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.exception.SetmealEnableFailedException;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealDishMapper;
import com.sky.mapper.SetmealMapper;
import com.sky.result.PageResult;
import com.sky.service.SetmealService;
import com.sky.vo.DishItemVO;
import com.sky.vo.SetmealVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.xml.datatype.DatatypeConfigurationException;
import java.util.List;
@Service//声明当前类是一个Service类,由Spring来管理
@Slf4j//声明当前类使用Slf4j日志,这样可以打印日志
public class SetmealServiceImpl implements SetmealService {
@Autowired
private SetmealMapper setmealMapper;
@Autowired
private SetmealDishMapper setmealDishMapper;
@Autowired
private DishMapper dishMapper;
/**
* 新增套餐,同时需要保存套餐和菜品的关联关系
* @param setmealDTO
*/
@Transactional//由于涉及到两个表的操作,需要事务控制
public void saveWithDish(SetmealDTO setmealDTO) {
//复制套餐dto到套餐实体
Setmeal setmeal = new Setmeal();
BeanUtils.copyProperties(setmealDTO, setmeal);
//向套餐表插入数据
setmealMapper.insert(setmeal);
//获取生成的套餐id,id由数据库自动生成
Long setmealId = setmeal.getId();
//复制套餐菜品dto到套餐菜品实体,因为有套餐id,所以需要设置套餐id,然后保存到数据库,作用为保存套餐菜品的关联关系
List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();//获取套餐菜品dto列表
setmealDishes.forEach(setmealDish -> {
setmealDish.setSetmealId(setmealId);//设置套餐id
});
//保存套餐和菜品的关联关系
setmealDishMapper.insertBatch(setmealDishes);
}
/**
* 分页查询
* @param setmealPageQueryDTO
* @return
*/
public PageResult pageQuery(SetmealPageQueryDTO setmealPageQueryDTO) {
int pageNum = setmealPageQueryDTO.getPage();
int pageSize = setmealPageQueryDTO.getPageSize();
PageHelper.startPage(pageNum, pageSize);
Page<SetmealVO> page = setmealMapper.pageQuery(setmealPageQueryDTO);
return new PageResult(page.getTotal(), page.getResult());
}
/**
* 批量删除套餐
* 1.删除套餐表数据
* 2.删除套餐菜品表数据
* 3.删除菜品表数据
* @param ids
*/
@Transactional//由于涉及到三个表的操作,需要事务控制
public void delete(List<Long> ids) {
//判断起售状态是否为0,如果为0,则不能删除
ids.forEach(id -> {
Setmeal setmeal = setmealMapper.getByID(id);
if (setmeal.getStatus() == StatusConstant.ENABLE) {
throw new DeletionNotAllowedException(MessageConstant.SETMEAL_ON_SALE);
}
});
//判断是否有菜品关联了套餐,如果有,则不能删除
ids.forEach(id -> {
setmealMapper.deleteByIDs(ids);//删除套餐表数据
setmealDishMapper.deleteBySetmealIds(ids);//删除套餐菜品表数据
});
}
/**
* 根据id查询套餐详情和菜品信息
* @param id
* @return
*/
public SetmealVO getById(Long id) {
//查询套餐信息,如果没有该菜品,则抛出异常
Setmeal setmeal = setmealMapper.getByID(id);
if (setmeal == null) {
throw new SetmealEnableFailedException(MessageConstant.SETMEAL_NOT_FOUND);
}
//查询套餐菜品信息
List<SetmealDish> setmealDishes = setmealDishMapper.getBySetmealId(id);
//创建套餐vo对象
SetmealVO setmealVO = new SetmealVO();
BeanUtils.copyProperties(setmeal, setmealVO);
//设置套餐菜品信息
setmealVO.setSetmealDishes(setmealDishes);
return setmealVO;
}
/**
* 修改套餐
* @param setmealDTO
*/
@Transactional
public void update(SetmealDTO setmealDTO) {
Setmeal setmeal = new Setmeal();
BeanUtils.copyProperties(setmealDTO, setmeal);
//1、修改套餐表,执行update
setmealMapper.update(setmeal);
//套餐id
Long setmealId = setmealDTO.getId();
//2、删除套餐和菜品的关联关系,操作setmeal_dish表,执行delete
setmealDishMapper.deleteBySetmealId(setmealId);
//获取套餐菜品dto列表
List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();
//执行循环,给每个dto对象设置套餐id,然后保存到数据库,作用为保存套餐菜品的关联关系
setmealDishes.forEach(setmealDish -> {
setmealDish.setSetmealId(setmealId);
});
//3、重新插入套餐和菜品的关联关系,操作setmeal_dish表,执行insert
setmealDishMapper.insertBatch(setmealDishes);
}
/**
* 套餐起售、停售
* @param status
* @param id
*/
public void startOrStop(Integer status, Long id) {
//起售套餐时,判断套餐内是否有停售菜品,有停售菜品提示"套餐内包含未启售菜品,无法启售"
if(status == StatusConstant.ENABLE){
//如果有停售菜品,则抛出异常
List<Dish> dishList = dishMapper.getBySetmealId(id);
//判断是否有菜品关联了套餐,如果有,则不能删除
//套餐菜品为空,就不需要判断菜品状态了
if(dishList != null && dishList.size() > 0){
dishList.forEach(dish -> {
//判断菜品状态是否为0,如果为0,则不能启用
if(StatusConstant.DISABLE == dish.getStatus()){
//抛出异常
throw new SetmealEnableFailedException(MessageConstant.SETMEAL_ENABLE_FAILED);
}
});
}
}
//修改套餐状态
Setmeal setmeal = Setmeal.builder()
.id(id)
.status(status)
.build();
setmealMapper.update(setmeal);
}
/**
* 条件查询
* @param setmeal
* @return
*/
public List<Setmeal> list(Setmeal setmeal) {
List<Setmeal> list = setmealMapper.list(setmeal);
return list;
}
/**
* 根据id查询菜品选项
* @param id
* @return
*/
public List<DishItemVO> getDishItemById(Long id) {
return setmealMapper.getDishItemBySetmealId(id);
}
}
sky-server.src.main.java.com.sky.service.impl.UserServiceimpl完整代码
java
package com.sky.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sky.constant.MessageConstant;
import com.sky.dto.UserLoginDTO;
import com.sky.entity.User;
import com.sky.exception.LoginFailedException;
import com.sky.mapper.UserMapper;
import com.sky.properties.WeChatProperties;
import com.sky.service.UserService;
import com.sky.utils.HttpClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@Service
@Slf4j
public class UserServiceImpl implements UserService {
//微信服务接口地址
public static final String WX_LOGIN = "https://api.weixin.qq.com/sns/jscode2session";
@Autowired
private WeChatProperties weChatProperties;
@Autowired
private UserMapper userMapper;
/**
* 微信登录
* @param userLoginDTO
* @return
*/
public User wxLogin(UserLoginDTO userLoginDTO) {
String openid = getOpenid(userLoginDTO.getCode());
//判断openid是否为空,如果为空表示登录失败,抛出业务异常
if(openid == null){
throw new LoginFailedException(MessageConstant.LOGIN_FAILED);
}
//判断当前用户是否为新用户
User user = userMapper.getByOpenid(openid);
//如果是新用户,自动完成注册
if(user == null){
user = User.builder()
.openid(openid)
.createTime(LocalDateTime.now())
.build();
userMapper.insert(user);//后绪步骤实现
}
//返回这个用户对象
return user;
}
/**
* 调用微信接口服务,获取微信用户的openid
* @param code
* @return
*/
private String getOpenid(String code){
//调用微信接口服务,获得当前微信用户的openid
Map<String, String> map = new HashMap<>();
map.put("appid",weChatProperties.getAppid());
map.put("secret",weChatProperties.getSecret());
map.put("js_code",code);
map.put("grant_type","authorization_code");
String json = HttpClientUtil.doGet(WX_LOGIN, map);
JSONObject jsonObject = JSON.parseObject(json);
String openid = jsonObject.getString("openid");
return openid;
}
}

sky-server.src.main.java.com.sky.service.DishService完整代码
java
package com.sky.service;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.result.PageResult;
import com.sky.vo.DishVO;
import java.util.List;
public interface DishService {
/**
* 保存菜品及其配料信息
* @param dishDTO
*/
void saveWithFlavors(DishDTO dishDTO);
/**
* 分页查询菜品信息
* @param dishPageQueryDTO
* @return
*/
PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO);
/**
* 根据ID删除菜品信息
* @param ids
*/
void deleteBatch(List<Long> ids);
/**
*
* 根据ID查询菜品详情及其配料信息
* @param id
* @return
*/
DishVO getByIdWithFlavors(Long id);
/**
* 更新菜品及其配料信息
* @param dishDTO
*/
void updateWithFlavors(DishDTO dishDTO);
/**
* 根据分类ID查询菜品列表
* @param categoryId
* @return
*/
List<Dish> list(Long categoryId);
/**
* 根据ID更新菜品状态
* @param status
* @param id
*/
void startOrStop(Integer status, Long id);
/**
* 条件查询菜品和口味
* @param dish
* @return
*/
List<DishVO> listWithFlavor(Dish dish);
}
sky-server.src.main.java.com.sky.service.SetmealService完整代码
java
package com.sky.service;
import com.sky.dto.SetmealDTO;
import com.sky.dto.SetmealPageQueryDTO;
import com.sky.entity.Setmeal;
import com.sky.result.PageResult;
import com.sky.vo.DishItemVO;
import com.sky.vo.SetmealVO;
import java.util.List;
public interface SetmealService {
/**
* 保存套餐及其菜品
* @param setmealDTO
*/
void saveWithDish(SetmealDTO setmealDTO);
/**
* 分页查询套餐
* @param setmealPageQueryDTO
* @return
*/
PageResult pageQuery(SetmealPageQueryDTO setmealPageQueryDTO);
/**
* 根据id删除套餐
* @param ids
*/
void delete(List<Long> ids);
/**
* 根据id获取套餐详情
* @param id
* @return
*/
SetmealVO getById(Long id);
/**
* 更新套餐
* @param setmealDTO
*/
void update(SetmealDTO setmealDTO);
/**
* 套餐起售、停售
* @param status
* @param id
*/
void startOrStop(Integer status, Long id);
/**
* 条件查询
* @param setmeal
* @return
*/
List<Setmeal> list(Setmeal setmeal);
/**
* 根据id查询菜品选项
* @param id
* @return
*/
List<DishItemVO> getDishItemById(Long id);
}
sky-server.src.main.java.com.sky.service.UserService完整代码
java
package com.sky.service;
import com.sky.dto.UserLoginDTO;
import com.sky.entity.User;
public interface UserService {
/**
* 微信登录
* @param userLoginDTO
* @return
*/
User wxLogin(UserLoginDTO userLoginDTO);
}
sky-server.src.main.resources.mapper.DishMapper.xml完整代码
java
<?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.DishMapper">
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
insert into dish (name, category_id, price, image, description, status, create_time, update_time, create_user, update_user)
values
(#{name},#{categoryId},#{price},#{image},#{description},#{status},#{createTime},#{updateTime},#{createUser},#{updateUser})
</insert>
<delete id="deleteByIds">
delete from dish where id in
<foreach collection="ids" open="(" close=")" separator="," item="id">
#{id}
</foreach>
</delete>
<select id="pageQuery" resultType="com.sky.vo.DishVO">
select d.* , c.name as categoryName from dish d left outer join category c on d.category_id = c.id
<where>
<if test="name != null">
and d.name like concat('%',#{name},'%')
</if>
<if test="categoryId != null">
and d.category_id like concat('%',#{categoryId},'%')
</if>
<if test="status != null">
and d.status like concat('%',#{status},'%')
</if>
</where>
order by d.create_time desc
</select>
<select id="list" resultType="Dish" parameterType="Dish">
select * from dish
<where>
<if test="name != null">
and name like concat('%',#{name},'%')
</if>
<if test="categoryId != null">
and category_id = #{categoryId}
</if>
<if test="status != null">
and status = #{status}
</if>
</where>
order by create_time desc
</select>
<update id="update">
update dish
<set>
<if test="name != null">name = #{name},</if>
<if test="categoryId != null">category_id = #{categoryId},</if>
<if test="price != null">price = #{price},</if>
<if test="image != null">image = #{image},</if>
<if test="description != null">description = #{description},</if>
<if test="status != null">status = #{status},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="updateUser != null">update_user = #{updateUser},</if>
</set>
where id = #{id}
</update>
</mapper>
sky-server.src.main.resources.mapper.SetmealDishMapper.xml完整代码
java
<?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.SetmealDishMapper">
<select id="getSetmealIdsByDishId" resultType="java.lang.Long">
SELECT setmeal_id FROM setmeal_dish WHERE dish_id IN
<foreach collection="dishIds" item="dishId" open="(" separator="," close=")">
#{dishId}
</foreach>
</select>
<select id="getSetmealIdsByDishIds" resultType="java.lang.Long">
select setmeal_id from setmeal_dish where dish_id in
<foreach collection="dishIds" item="dishId" separator="," open="(" close=")">
#{dishId}
</foreach>
</select>
<insert id="insertBatch" parameterType="list">
insert into setmeal_dish
(setmeal_id,dish_id,name,price,copies)
values
<foreach collection="setmealDishes" item="sd" separator=",">
(#{sd.setmealId},#{sd.dishId},#{sd.name},#{sd.price},#{sd.copies})
</foreach>
</insert>
<delete id="deleteBySetmealIds" parameterType="list">
DELETE FROM setmeal_dish
WHERE setmeal_id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<select id="getDishIdsBySetmealIds" resultType="java.lang.Long">
SELECT DISTINCT dish_id
FROM setmeal_dish
WHERE setmeal_id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
</mapper>
sky-server.src.main.resources.mapper.SetmealMapper.xml完整代码
java
<?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.SetmealMapper">
<insert id="insert" parameterType="Setmeal" useGeneratedKeys="true" keyProperty="id">
insert into setmeal
(category_id, name, price, status, description, image, create_time, update_time, create_user, update_user)
values (#{categoryId}, #{name}, #{price}, #{status}, #{description}, #{image}, #{createTime}, #{updateTime},
#{createUser}, #{updateUser})
</insert>
<update id="update" parameterType="Setmeal">
update setmeal
<set>
<if test="name != null">
name = #{name},
</if>
<if test="categoryId != null">
category_id = #{categoryId},
</if>
<if test="price != null">
price = #{price},
</if>
<if test="status != null">
status = #{status},
</if>
<if test="description != null">
description = #{description},
</if>
<if test="image != null">
image = #{image},
</if>
<if test="updateTime != null">
update_time = #{updateTime},
</if>
<if test="updateUser != null">
update_user = #{updateUser}
</if>
</set>
where id = #{id}
</update>
<select id="pageQuery" resultType="com.sky.vo.SetmealVO">
select
s.*,c.name categoryName
from
setmeal s
left join
category c
on
s.category_id = c.id
<where>
<if test="name != null">
and s.name like concat('%',#{name},'%')
</if>
<if test="status != null">
and s.status = #{status}
</if>
<if test="categoryId != null">
and s.category_id = #{categoryId}
</if>
</where>
order by s.create_time desc
</select>
<delete id="deleteByIDs">
delete from setmeal
where id in
<foreach collection = "ids" item="id" index="index" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<select id="list" parameterType="Setmeal" resultType="Setmeal">
select * from setmeal
<where>
<if test="name != null">
and name like concat('%',#{name},'%')
</if>
<if test="categoryId != null">
and category_id = #{categoryId}
</if>
<if test="status != null">
and status = #{status}
</if>
</where>
</select>
</mapper>
sky-server.src.main.resources.mapper.UserMapper.xml完整代码
java
<?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.UserMapper">
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
insert into user (openid, name, phone, sex, id_number, avatar, create_time)
values (#{openid}, #{name}, #{phone}, #{sex}, #{idNumber}, #{avatar}, #{createTime})
</insert>
</mapper>
sky-server.src.main.resources.application.xml和sky-server.src.main.resources.application-dev.xml按照自己的账号和密码进行修改就行了