瑞吉外卖笔记


项目源码地址:https://gitee.com/sjd75/takeaway

1. 准备阶段

角色

  • 后台系统管理员:登录后台管理系统,拥有后台管理系统中的所有操作权限。
  • 后台系统普通员工:登录后台管理系统,仅能对菜品、套餐、订单等模块进行操作。
  • C 端用户:登录移动端应用,浏览菜品、添加菜品到购物车、设置地址、在线下单等。

1.1 数据库准备

员工表 employee

-- 员工信息
employee:
    + columns
        id: bigint NN
            --  主键(USING BTREE)
        name: varchar(32) NN
            --  姓名
        username: varchar(32) NN
            --  用户名(UNIQUE KEY)
        password: varchar(64) NN
            --  密码
        phone: varchar(11) NN
            --  手机号
        sex: varchar(2) NN
            --  性别
        id_number: varchar(18) NN
            --  身份证号
        status: int NN default 1
            --  状态(0 禁用,1 正常)
        create_time: datetime NN
            --  创建时间
        update_time: datetime NN
            --  更新时间
        create_user: bigint NN
            --  创建人
        update_user: bigint NN
            --  修改人

菜品及套餐分类表 category

--  菜品及套餐分类
category:
    + columns
        id: bigint NN
            --  主键(USING BTREE)
        type: int
            --  类型(1 菜品分类,2 套餐分类)
        name: varchar(64) NN
            --  分类名称(UNIQUE KEY)
        sort: int NN default 0
            --  顺序
        create_time: datetime NN
            --  创建时间
        update_time: datetime NN
            --  更新时间
        create_user: bigint NN
            --  创建人
        update_user: bigint NN
            --  修改人

菜品表 dish

--  菜品管理
dish:
    + columns
        id: bigint NN
            --  主键(USING BTREE)
        name: varchar(64) NN
            --  菜品名称(UNIQUE KEY)
        category_id: bigint NN
            --  菜品分类id
        price: decimal(10,2)
            --  菜品价格
        code: varchar(64) NN
            --  商品码
        image: varchar(200) NN
            --  图片
        description: varchar(400)
            --  描述信息
        status: int NN default 1
            --  0 停售 1 起售
        sort: int NN default 0
            --  顺序
        create_time: datetime NN
            --  创建时间
        update_time: datetime NN
            --  更新时间
        create_user: bigint NN
            --  创建人
        update_user: bigint NN
            --  修改人
        is_deleted: int NN default 0
            --  是否删除

套餐表 setmeal

--  套餐
setmeal:
    + columns
        id: bigint NN
            --  主键(USING BTREE)
        category_id: bigint NN
            --  菜品分类id
        name: varchar(64) NN
            --  套餐名称(UNIQUE KEY)
        price: decimal(10,2) NN
            --  套餐价格
        status: int
            --  状态 0:停用 1:启用
        code: varchar(32)
            --  编码
        description: varchar(512)
            --  描述信息
        image: varchar(255)
            --  图片
        create_time: datetime NN
            --  创建时间
        update_time: datetime NN
            --  更新时间
        create_user: bigint NN
            --  创建人
        update_user: bigint NN
            --  修改人
        is_deleted: int NN default 0
            --  是否删除

套餐菜品关系表 setmeal_dish

--  套餐菜品关系
setmeal_dish:
    + columns
        id: bigint NN
            --  主键(USING BTREE)
        setmeal_id: varchar(32) NN
            --  套餐id 
        dish_id: varchar(32) NN
            --  菜品id
        name: varchar(32)
            --  菜品名称 (冗余字段)
        price: decimal(10,2)
            --  菜品原价(冗余字段)
        copies: int NN
            --  份数
        sort: int NN default 0
            --  排序
        create_time: datetime NN
            --  创建时间
        update_time: datetime NN
            --  更新时间
        create_user: bigint NN
            --  创建人
        update_user: bigint NN
            --  修改人
        is_deleted: int NN default 0
            --  是否删除

菜品口味关系表 dish_flavor

--  菜品口味关系表
dish_flavor:
    + columns
        id: bigint NN
            --  主键(USING BTREE)
        dish_id: bigint NN
            --  菜品
        name: varchar(64) NN
            --  口味名称
        value: varchar(500)
            --  口味数据list
        create_time: datetime NN
            --  创建时间
        update_time: datetime NN
            --  更新时间
        create_user: bigint NN
            --  创建人
        update_user: bigint NN
            --  修改人
        is_deleted: int NN default 0
            --  是否删除

C 端用户表 user

--  用户信息
user:
    + columns
        id: bigint NN
            --  主键(USING BTREE)
        name: varchar(50)
            --  姓名
        phone: varchar(100) NN
            --  手机号
        sex: varchar(2)
            --  性别
        id_number: varchar(18)
            --  身份证号
        avatar: varchar(500)
            --  头像
        status: int default 0
            --  状态 0:禁用,1:正常

地址簿表 address_book

--  地址管理
address_book:
    + columns
        id: bigint NN
            --  主键(USING BTREE)
        user_id: bigint NN
            --  用户id
        consignee: varchar(50) NN
            --  收货人
        sex: tinyint NN
            --  性别 0 女 1 男
        phone: varchar(11) NN
            --  手机号
        province_code: varchar(12) collate utf8mb4_0900_ai_ci
            --  省级区划编号
        province_name: varchar(32) collate utf8mb4_0900_ai_ci
            --  省级名称
        city_code: varchar(12) collate utf8mb4_0900_ai_ci
            --  市级区划编号
        city_name: varchar(32) collate utf8mb4_0900_ai_ci
            --  市级名称
        district_code: varchar(12) collate utf8mb4_0900_ai_ci
            --  区级区划编号
        district_name: varchar(32) collate utf8mb4_0900_ai_ci
            --  区级名称
        detail: varchar(200) collate utf8mb4_0900_ai_ci
            --  详细地址
        label: varchar(100) collate utf8mb4_0900_ai_ci
            --  标签
        is_default: tinyint(1) NN default 0
            --  默认 0 否 1是
        create_time: datetime NN
            --  创建时间
        update_time: datetime NN
            --  更新时间
        create_user: bigint NN
            --  创建人
        update_user: bigint NN
            --  修改人
        is_deleted: int NN default 0
            --  是否删除

购物车表 shopping_cart

--  购物车
shopping_cart:
    + columns
        id: bigint NN
            --  主键(USING BTREE)
        name: varchar(50)
            --  名称
        image: varchar(100)
            --  图片
        user_id: bigint NN
            --  主键
        dish_id: bigint
            --  菜品id
        setmeal_id: bigint
            --  套餐id
        dish_flavor: varchar(50)
            --  口味
        number: int NN default 1
            --  数量
        amount: decimal(10,2) NN
            --  金额
        create_time: datetime
            --  创建时间

订单表 order

--  订单表
orders:
    + columns
        id: bigint NN
            --  主键(USING BTREE)
        number: varchar(50)
            --  订单号
        status: int NN default 1
            --  订单状态 1待付款,2待派送,3已派送,4已完成,5已取消
        user_id: bigint NN
            --  下单用户
        address_book_id: bigint NN
            --  地址id
        order_time: datetime NN
            --  下单时间
        checkout_time: datetime NN
            --  结账时间
        pay_method: int NN default 1
            --  支付方式 1微信,2支付宝
        amount: decimal(10,2) NN
            --  实收金额
        remark: varchar(100)
            --  备注
        phone: varchar(255)
        address: varchar(255)
        user_name: varchar(255)
        consignee: varchar(255)

订单明细表 order_detail

--  订单明细表
order_detail:
    + columns
        id: bigint NN
            --  主键(USING BTREE)
        name: varchar(50)
            --  名字
        image: varchar(100)
            --  图片
        order_id: bigint NN
            --  订单id
        dish_id: bigint
            --  菜品id
        setmeal_id: bigint
            --  套餐id
        dish_flavor: varchar(50)
            --  口味
        number: int NN default 1
            --  数量
        amount: decimal(10,2) NN
            --  金额

1.2 POM 文件

<?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.4.5</version>
        <relativePath/>
    </parent>

    <groupId>com.sun.takeaway</groupId>
    <artifactId>takeaway</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!-- Boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <scope>compile</scope>
        </dependency>
      	<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- Database -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.15</version>
        </dependency>

        <!-- Tools -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.15</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.4.5</version>
            </plugin>
        </plugins>
    </build>
</project>

1.3 application.yml

server:
  port: 8080
spring:
  application:
    name: takeaway
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/takeaway?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
      username: root
      password: root
mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      id-type: ASSIGN_ID
      logic-delete-field: is_delete
      logic-delete-value: 1
      logic-not-delete-value: 0

1.4 前端项目导入

将 backend、frontend 导入到 Maven 项目中的 resource 目录下,并设置静态资源映射。

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
   
    /**
     * 设置静态资源映射
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
   
        // 访问 /backend、/frontend 开头的任意路径,都会被映射到类路径下的 backend 和 frontend 目录
        registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
        registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
    }
}

1.5 COMMON

统一返回

public enum ErrorCode {
   
    SUCCESS(0, "ok"),
    PARAMS_ERROR(40000, "请求参数错误"),
    NOT_LOGIN_ERROR(40100, "未登录"),
    NO_AUTH_ERROR(40101, "无权限"),
    NOT_FOUND_ERROR(40400, "请求数据不存在"),
    FORBIDDEN_ERROR(40300, "禁止访问"),
    SYSTEM_ERROR(50000, "系统内部异常"),
    OPERATION_ERROR(50001, "操作失败");

    private final int code;
    private final String message;

    ErrorCode(int code, String message) {
   
        this.code = code;
        this.message = message;
    }

    public int getCode() {
   
        return code;
    }

    public String getMessage() {
   
        return message;
    }
}
@Data
public class CommonResult<T> implements Serializable {
   
    private int code;
    private T data;
    private String message;

    public CommonResult(int code, T data, String message) {
   
        this.code = code;
        this.data = data;
        this.message = message;
    }

    public static <T> CommonResult<T> success(T data) {
   
        return new CommonResult<>(1, data, "ok");
    }

    public static <T> CommonResult<T> error(ErrorCode errorCode) {
   
        return new CommonResult<>(errorCode.getCode(), null, errorCode.getMessage());
    }

    public static <T> CommonResult<T> error(int code, String message) {
   
        return new CommonResult<>(code, null, message);
    }

    public static <T> CommonResult<T> error(ErrorCode errorCode, String message) {
   
        return new CommonResult<>(errorCode.getCode(), null, message);
    }
}

EXCEPTION

public class BusinessException extends RuntimeException {
   
    private final int code;

    public BusinessException(String message, int code) {
   
        super(message);
        this.code = code;
    }

    public BusinessException(ErrorCode errorCode) {
   
        super(errorCode.getMessage());
        this.code = errorCode.getCode();
    }

    public BusinessException(ErrorCode errorCode, String message) {
   
        super(message);
        this.code = errorCode.getCode();
    }

    public int getCode() {
   
        return code;
    }
}
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
   
    @ExceptionHandler(BusinessException.class)
    public CommonResult<?> businessExceptionHandler(BusinessException e) {
   
        log.error("BusinessException", e);
        return CommonResult.error(e.getCode(), e.getMessage());
    }

    @ExceptionHandler(RuntimeException.class)
    public CommonResult<?> runtimeExceptionHandler(RuntimeException e) {
   
        log.error("RuntimeException", e);
        return CommonResult.error(ErrorCode.SYSTEM_ERROR, "系统错误");
    }
}
public class ThrowUtils {
   
    public static void throwIf(boolean condition, RuntimeException runtimeException) {
   
        if (condition) {
   
            throw runtimeException;
        }
    }
    public static void throwIf(boolean condition, ErrorCode errorCode) {
   
        throwIf(condition, new BusinessException(errorCode));
    }
    public static void throwIf(boolean condition, ErrorCode errorCode, String message) {
   
        throwIf(condition, new BusinessException(errorCode, message));
    }
}

CONSTANT

public interface LOGINConstant {
   
    /**
     * 员工登录态的 Key
     */
    String EMPLOYEE_LOGIN_STATE = "employee_login";

    /**
     * 用户登录态的 Key
     */
    String USER_LOGIN_STATE = "user_login";
}
public interface CommonConstant {
   
    /**
     * 可用
     */
    int AVAILABLE = 1;
    
    /**
     * 禁用
     */
    int BAN = 0;

    /**
     * 1
     */
    int ONE = 1;
    
    /**
     * 0
     */
    int ZERO = 0;
}

MODEL

@Data
public class EmployeeLoginRequest implements Serializable {
   

    private static final long serialVersionUID = 1L;

    private String username;

    private String password;
}

@Data
public class LoginEmployeeVO implements Serializable {
   
    private static final long serialVersionUID = 1L;

    private Long id;

    // 用户名(Unique)
    private String username;

    // 姓名
    private String name;

    // 手机号
    private String phone;

    // 性别
    private String sex;

    // 身份证号
    private String idNumber;

    // 状态 (0 禁用,1 正常)
    private Integer status;

    // 创建时间
    private LocalDateTime createTime;

    // 更新时间
    private LocalDateTime updateTime;

    // 创建人
    @TableField(fill = FieldFill.INSERT)
    private Long createUser;

    // 修改人
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;
}

1.6 新增消息转换器

/**
 * 对象映射器:基于 Jackson 将 Java 对象序列化为 JSON,或者将 JSON 反序列化为 Java 对象
 */
public class JacksonObjectMapper extends ObjectMapper {
   
    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";

    public JacksonObjectMapper() {
   
        super();
        // 收到未知属性时不报异常
        this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 反序列化时,属性不存在的兼容处理
        this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        SimpleModule simpleModule = new SimpleModule()
                .addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))
                .addSerializer(BigInteger.class, ToStringSerializer.instance)
                .addSerializer(Long.class, ToStringSerializer.instance)
                .addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
        // 注册功能模块(可以添加自定义序列化器和反序列化器)
        this.registerModule(simpleModule);
    }
}
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
   
    /**
     * 设置静态资源映射
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
   
        // 访问 /backend、/frontend 开头的任意路径,都会被映射到类路径下的 backend 和 frontend 目录
        registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
        registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
    }

    /**
     * 添加自定义的消息转换器
     */
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
   
        // 创建消息转换器对象
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        // 设置消息转换器
        converter.setObjectMapper(new JacksonObjectMapper());
        //
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值