苍穹外卖[操作步骤+讲解]

苍穹外卖操作详解

资料下载:

https://gitee.com/a-fish-v/sky-take-out

day1:

1. 初始环境导入

先创建一个主文件夹xxx,放到非中文目录下, 

从提供的资料中,找到管理端的前端工程文件夹,将这个文件夹导入到你创建的主文件夹中

双击nginx.exe启动前端工程,再将后端的初始工程文件夹导入到你创建的这个主文件夹中,

2. 运行项目

双击nginx.exe启动前端工程,在idea中打开后端的初始工程文件夹,jdk版本可以设置成17,防止出现jdk版本过低的警告。

在sky-take-out主模块下会有三个子模块

分别是sky-common(存放一些工具类) ; sky-pojo(实体类, DTO, VO) ; sky-server(配置类, Controller, Mapper, Service),  在里面找到项目的启动类SkyApplication, 点击运行,然后访问

http://localhost:80, 初始密码是123456,然后就点击登录进入到管理端

3. 创建数据库

然后在资料中找到sky.sql文件,执行sql的话,你可选择sqlyang或者DataGrip,也可以idea内置的(前提是你装了mysql),然后执行一次就可以,

一共有11张表,像employee【员工表】category【分类表】dish【菜品表】dish_flavor【菜品口味表】setmeal【套餐表】... 都是管理端的数据库表

​​​​​​

管理端登录模块

就是管理员登录一次后生成JWT令牌,返回给前端 ,然后每次登录时, 携带这个码跟后端进行校验,来判断登录成功或失败  

login方法中 生成令牌, 返回给前端

生成Jwt令牌:jwt - > 签名算法+密钥+自定义内容+有效期 

解析 - > 密钥

jwt 的 自定义内容【clamis对象, 必须是Map类型】中包含了当前登录的员工信息 

表现层(Controller)

    /**
     * 登录
     *
     * @param employeeLoginDTO
     * @return
     */
    @PostMapping("/login")
    @ApiOperation(value = "员工登录")
    public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) {
        log.info("员工登录:{}", employeeLoginDTO);

        Employee employee = employeeService.login(employeeLoginDTO);

        //登录成功后,生成jwt令牌
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.EMP_ID, employee.getId());
        String token = JwtUtil.createJWT(
                jwtProperties.getAdminSecretKey(),
                jwtProperties.getAdminTtl(),
                claims);

        EmployeeLoginVO employeeLoginVO = EmployeeLoginVO.builder()
                .id(employee.getId())
                .userName(employee.getUsername())
                .name(employee.getName())
                .token(token)
                .build();

        return Result.success(employeeLoginVO);
    }

JwtUtil工具类

createJWT方法中指定了   密钥+有效期+自定义内容

parseJWT 方法中指定了 密钥 和 生成的token , 都是固定写法

public class JwtUtil {
    /**
     * 生成jwt
     * 使用Hs256算法, 私匙使用固定秘钥
     *
     * @param secretKey jwt秘钥
     * @param ttlMillis jwt过期时间(毫秒)
     * @param claims    设置的信息
     * @return
     */
    public static String createJWT(String secretKey, long ttlMillis, Map<String, Object> claims) {
        // 指定签名的时候使用的签名算法,也就是header那部分
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        // 生成JWT的时间
        long expMillis = System.currentTimeMillis() + ttlMillis;
        Date exp = new Date(expMillis);

        // 设置jwt的body
        JwtBuilder builder = Jwts.builder()
                // 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的
                .setClaims(claims)
                // 设置签名使用的签名算法和签名使用的秘钥
                .signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))
                // 设置过期时间
                .setExpiration(exp);

        return builder.compact();
    }

    /**
     * Token解密
     *
     * @param secretKey jwt秘钥 此秘钥一定要保留好在服务端, 不能暴露出去, 否则sign就可以被伪造, 如果对接多个客户端建议改造成多个
     * @param token     加密后的token
     * @return
     */
    public static Claims parseJWT(String secretKey, String token) {
        // 得到DefaultJwtParser
        Claims claims = Jwts.parser()
                // 设置签名的秘钥
                .setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))
                // 设置需要解析的jwt, .getBody()方法可以得到jwt中的第二个部分[自定义部分]
                .parseClaimsJws(token).getBody();
        return claims;
    }

}
@Component
//指定从配置文件中加载以sky.jwt开头的属性
@ConfigurationProperties(prefix = "sky.jwt")
@Data
public class JwtProperties {

    /**
     * 管理端员工生成jwt令牌相关配置
     */
    private String adminSecretKey;
    private long adminTtl;
    private String adminTokenName;

    /**
     * 用户端微信用户生成jwt令牌相关配置
     */
    private String userSecretKey;
    private long userTtl;
    private String userTokenName;

}

yml文件中密钥,有效期.....

sky:
  jwt:
    # 设置jwt签名加密时使用的秘钥
    admin-secret-key: itcast
    # 设置jwt过期时间
    admin-ttl: 7200000
    # 设置前端传递过来的令牌名称
    admin-token-name: token
    user-secret-key: itheima
    user-ttl: 7200000
    user-token-name: authentication

表现层调用   Employee employee = employeeService.login(employeeLoginDTO);

    public Employee login(EmployeeLoginDTO employeeLoginDTO) {
        String username = employeeLoginDTO.getUsername();
        String password = employeeLoginDTO.getPassword();

        //1、根据用户名查询数据库中的数据
        Employee employee = employeeMapper.getByUsername(username);

        //2、处理各种异常情况(用户名不存在、密码不对、账号被锁定)
        if (employee == null) {
            //账号不存在, 下面所有的异常都继承自  BaseException 方法, 由全局异常处理器 
            //GlobalExceptionHandler 统一进行处理
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }

        //密码比对
        //对前端传过来的明文密码进行md5加密处理
        password = DigestUtils.md5DigestAsHex(password.getBytes());
        if (!password.equals(employee.getPassword())) {
            //密码错误
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }
        //  StatusConstant.DISABLE = 0
        if (employee.getStatus() == StatusConstant.DISABLE) {
            //账号被锁定
            throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);
        }

        //3、返回实体对象
        return employee;
    }

调用Mapper 层的接口Employee employee = employeeMapper.getByUsername(username);

查询员工表

nginx反向代理

进到nginx-1.20.2\conf,打开nginx配置

# 反向代理,处理管理端发送的请求
location /api/ {
	proxy_pass   http://localhost:8080/admin/;
    #proxy_pass   http://webservers/admin/;
}

当在访问http://localhost/api/employee/login,nginx接收到请求后转到http://localhost:8080/admin/,故最终的请求地址为http://localhost:8080/admin/employee/login,和后台服务的访问地址一致。

对登录密码进行MD5加密

将MD5加密后的密码更新到数据库employee表中

password = DigestUtils.md5DigestAsHex(password.getBytes());

使用DigestUtils这个工具类

代码逻辑就是将password加密后的和数据库employee表中的进行对比

Swagger【后端【表现层】接口测试, 类似于potman】

1. 导入 knife4j 的maven坐标, 在pom.xml中添加依赖

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

2. 在配置类WebMvcConfiguration中加入 knife4j 相关配置

/**
     * 通过knife4j生成接口文档
     * @return
*/
    @Bean
    public Docket docket() {
        ApiInfo apiInfo = new ApiInfoBuilder()
                // 指定文档的标题, 版本, 描述
                .title("苍穹外卖项目接口文档")
                .version("2.0")
                .description("苍穹外卖项目接口文档")
                .build();
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo)
                .select()
                // 可自定义:扫描包路径 
                .apis(RequestHandlerSelectors.basePackage("com.sky.controller"))
                // 所有路径[路径过滤]
                .paths(PathSelectors.any())
                .build();
        return docket;
    }

3. 静态资源过滤【ssm里面提到的addResourceHandlers】

在配置类WebMvcConfiguration中添加

/**
     * 设置静态资源映射
     * @param registry
*/
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
// 添加静态资源的访问路径 /webjars/** 中的两个星号 ** 表示匹配 /webjars/ 目录下的所有文件和子目录

使用 http://localhost:8080/doc.html 访问

上面很多都是资料中提供好的

day2:

新增员工

员工分页查询

启用禁用员工账号

编辑员工

导入分类模块功能代码

1. 新增员工

根据产品原型分析/资料中的接口文档, 员工id , 账号, 姓名, 手机号, 性别, 身份证号, 将这些字段封装成一个DTO类由管理端提交到服务端

@Data
public class EmployeeDTO implements Serializable {

    private Long id;

    private String username;

    private String name;

    private String phone;

    private String sex;

    private String idNumber;

}

进入到sky-server模块中,在com.sky.controller.admin包下,在EmployeeController中创建新增员工方法,接收前端提交的参数

    @PostMapping
    @ApiOperation(value = "新增员工")
    public Result save(@RequestBody EmployeeDTO employeeDTO){
        log.info("新增员工:{}", employeeDTO);
        employeeService.save(employeeDTO);
        return Result.success();
    }

Result<T> 类 是返回给管理端的json数据,其中包含code, msg, data

Result.success(); 操作成功, 返回状态码:1成功

/**
 * 后端统一返回结果
 * @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;
    }

}

进入到sky-server模块中,com.sky.server.EmployeeService

在service业务层定义接口, 然后在serviceImp写具体的业务代码

public interface EmployeeService {

    /**
     * 员工登录
     * @param employeeLoginDTO
     * @return
     */
    Employee login(EmployeeLoginDTO employeeLoginDTO);

    void save(EmployeeDTO employeeDTO);
}

在serviceImp 包中实现刚定义的save接口

你可以对比employee实体类和employeeDTO,完善DTO中缺失的属性,调用Mapper层接口中的方法【记得要在当前类的上面声明employeeMapper对象】,

    //新增员工
    public void save(EmployeeDTO employeeDTO) {
        Employee employee = new Employee();
        // 将EmployeeDTO(属性少)对象转换为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
        // TODO 后期需要修改为登录用户的id
        // employee.setCreateUser(BaseContext.getCurrentId());
        // employee.setUpdateUser(BaseContext.getCurrentId());
        employeeMapper.insert(employee);
    }

employeeMapper.insert(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})")
    @AutoFill(value = OperationType.INSERT)
    void insert(Employee employee);

employee实体类中的属性和数据库字段不同的情况

在application.yml中已开启驼峰命名,故id_number和idNumber可对应

注:在初始学mybatis时, 使用的是.xml文件进行配置, 但是spring-boot中做出了改变

mybatis:
  configuration:
    #开启驼峰命名
    map-underscore-to-camel-case: true

在swagger中测试这个接口

调用员工登录接口获得一个合法的JWT令牌,【初次登录会返回给管理端的令牌】

添加令牌:

将合法的JWT令牌添加到全局参数中

文档管理-->全局参数设置-->添加参数

否则会报错

2. 员工分页查询

系统中的员工很多的时候,如果在一个页面中全部展示出来会显得比较乱,不便于查看,所以一般的系统中都会以分页的方式来展示列表数据。而在我们的分页查询页面中, 除了分页条件以外,还有一个查询条件 "员工姓名"。

根据接口文档/原型图,请求参数有name, page【页码】pageSize 【每页记录数】

请求参数类型为Query,不是json格式提交,在路径后直接拼接。/admin/employee/page?name=zhangsan

返回数据中records数组中使用Employee实体类对属性进行封装。

@Data
public class EmployeePageQueryDTO implements Serializable {

    //员工姓名
    private String name;

    //页码
    private int page;

    //每页显示记录数
    private int pageSize;

}

后面所有的分页查询,统一都封装为PageResult对象【返回给管理端中的 data】

@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult implements Serializable {

    private long total; //总记录数

    private List records; //当前页数据集合, employee数组

}

员工信息分页查询后端返回的对象类型为: Result<PageResult>

查询成功:

data: PageResult

code : 1

在sky-server模块中,com.sky.controller.admin.EmployeeController中添加分页查询方法。

    //员工分页查询
    @GetMapping("/page")
    @ApiOperation(value = "员工分页查询")
    public Result<PageResult> page(EmployeePageQueryDTO employeePageQueryDTO){
        log.info("员工分页查询:{}", employeePageQueryDTO);
        PageResult pageResult = employeeService.pageQuery(employeePageQueryDTO);
        return Result.success(pageResult);
    }

在EmployeeService接口中声明pageQuery方法:

public interface EmployeeService {

    /**
     * 员工登录
     * @param employeeLoginDTO
     * @return
     */
    Employee login(EmployeeLoginDTO employeeLoginDTO);

    void save(EmployeeDTO employeeDTO);

    PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO);
}

在EmployeeServiceImpl中实现pageQuery方法:

注:此处使用 mybatis 的分页插件 PageHelper 来简化分页代码的开发。底层基于 mybatis 的拦截器实现。

故在pom.xml文中添加依赖(初始工程已添加)

    // 员工分页查询
    public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO){
          PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());
/*
    PageHelper:MyBatis分页插件
    startPage():设置分页参数,后续的第一个MyBatis查询会自动分页
    getPage():当前页码
    getPageSize():每页记录数

*/
        Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);
/*
    调用Mapper层的分页查询方法
    返回Page<Employee>对象(PageHelper提供的分页对象)
    这个查询会自动应用前面设置的分页参数
*/
        long total = page.getTotal();  // 总记录数
        List<Employee> result = page.getResult();  // 当前页的数据列表
        return new PageResult(total,result); // 将数据封装到自定义的PageResult对象中
    }

在 EmployeeMapper 中声明 pageQuery 方法:

    // 分页查询 -> 不再使用注解, 而采用动态的sql
    Page<Employee> pageQuery(EmployeePageQueryDTO employeePageQueryDTO);

xml: 

<?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.EmployeeMapper">
    <select id="pageQuery" resultType="com.sky.entity.Employee">
        select * from employee
        <where>
            <if test="name!= null and name!= ''">
                and name like concat('%', #{name}, '%')
            </if>
        </where>
        order by create_time desc
    </select>
</mapper>
// spring-boot, xml文件中的几个常见属性 namespace: 和你mapper层的对应接口进行绑定
// id:指定接口中对象的方法名 resultType : 你查询的数据的类型

时间格式问题:可以在每个时间属性上添加@JsonFormat指定日期格式

也可以 

在WebMvcConfiguration中扩展SpringMVC的消息转换器,统一对日期类型进行格式处理

就是配置类WebMvcConfiguration 继承 WebMvcConfigurationSupport类,然后重写WebMvcConfigurationSupport类中的extendMessageConverters方法, 方法形参都是固定的

	/**
     * 扩展Spring MVC框架的消息转化器
     * @param converters
     */
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        log.info("扩展消息转换器...");
        //创建一个消息转换器对象
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        //需要为消息转换器设置一个对象转换器,对象转换器可以将Java对象序列化为json数据
        // 用自定义的JacksonObjectMapper替换默认的ObjectMapper
        converter.setObjectMapper(new JacksonObjectMapper());
        //将自己的消息转化器加入容器中
        // add(0, converter):插入到列表的第一个位置(最高优先级)
        //Spring会按顺序使用第一个能够处理当前类型的转换器
        converters.add(0,converter);
    }

时间格式定义,sky-common模块中

package com.sky.json;

public class JacksonObjectMapper extends ObjectMapper {

	//.......
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";
    //.......

    }
}

3. 启用禁用员工账号

在员工管理列表页面,可以对某个员工账号进行启用或者禁用操作。账号禁用的员工不能登录系统,启用后的员工可以正常登录。如果某个员工账号状态为正常,则按钮显示为 "禁用",如果员工账号状态为已禁用,则按钮显示为"启用"。

1). 路径参数携带状态值。

2). 同时,把id传递过去,明确对哪个用户进行操作。

3). 返回数据code状态是必须,其它是非必须。

在url中进行拼接status和员工id,分别填充到EmployeeController的形参中

在sky-server模块中,根据接口设计中的请求参数形式对应的在 EmployeeController 中创建启用禁用员工账号的方法:

    @PostMapping("/status/{status}")
    @ApiOperation(value = "启用禁用员工账号")
    public Result startOrStop(@PathVariable Integer status, Long id){
        log.info("启用禁用员工账号:{},{}",status,id);
        employeeService.startOrStop(status, id);
        return Result.success();
    }

在 EmployeeService 接口中声明启用禁用员工账号的业务方法:

public interface EmployeeService {

    /**
     * 员工登录
     * @param employeeLoginDTO
     * @return
     */
    Employee login(EmployeeLoginDTO employeeLoginDTO);

    void save(EmployeeDTO employeeDTO);

    PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO);

    void startOrStop(Integer status, Long id);
}

在 EmployeeServiceImpl 中实现启用禁用员工账号的业务方法:

    //启用禁用员工账号
    public void startOrStop(Integer status, Long id) {
        // 还是类似于写一个sql : update employee set status = ? where id = ?
        // 扩展这个方法
        Employee employee = Employee.builder().status(status).id(id).build();
        employeeMapper.update(employee);
    }

在 EmployeeMapper 接口中声明 update 方法:

    @AutoFill(value = OperationType.UPDATE)
    void update(Employee employee);

在 EmployeeMapper.xml 中编写SQL:

<update id="update" parameterType="Employee">
        update employee
        <set>
            <if test="name != null">name = #{name},</if>
            <if test="username != null">username = #{username},</if>
            <if test="password != null">password = #{password},</if>
            <if test="phone != null">phone = #{phone},</if>
            <if test="sex != null">sex = #{sex},</if>
            <if test="idNumber != null">id_Number = #{idNumber},</if>
            <if test="updateTime != null">update_Time = #{updateTime},</if>
            <if test="updateUser != null">update_User = #{updateUser},</if>
            <if test="status != null">status = #{status},</if>
        </set>
        where id = #{id}
    </update>

4. 编辑员工

在员工管理列表页面点击 "编辑" 按钮,跳转到编辑页面,在编辑页面回显员工信息并进行修改,最后点击 "保存" 按钮完成编辑操作。

设计两个接口:

1. 根据id就进行回显员工信息 ----> 路径参数,请求方式对应rest风格中的GET

2. 对回显的员工信息进行修改    ----> 提交json数据到后台 ,请求方式对应rest风格中的PUT

1. 根据id就进行回显员工信息

在 EmployeeController 中创建 getById 方法:

    @GetMapping("/{id}")
    @ApiOperation(value = "查询员工信息")
    public Result<Employee> getById(@PathVariable Long id){
        Employee employee = employeeService.getById(id);
        return Result.success(employee);
    }

在 EmployeeService 接口中声明 getById 方法:

    Employee getById(Long id);

在 EmployeeServiceImpl 中实现 getById 方法:

    //根据id查询员工信息

    @Override
    public Employee getById(Long id) {
        Employee employee = employeeMapper.getById(id);
        employee.setPassword("******");
        return employee;
    }

在 EmployeeMapper 接口中声明 getById 方法:

    // 根据id查询员工信息
    @Select("select * from employee where id = #{id}")
    Employee getById(Long id);

2. 对回显的员工信息进行修改

在 EmployeeController 中创建 update 方法:

    //更新/修改员工信息
    @PutMapping
    @ApiOperation(value = "更新员工信息")
    public Result update(@RequestBody EmployeeDTO employeeDTO){
        log.info("更新员工信息:{}", employeeDTO);
        employeeService.update(employeeDTO);
        return Result.success();
    }

在 EmployeeService 接口中声明 update 方法:

public interface EmployeeService {

    /**
     * 员工登录
     * @param employeeLoginDTO
     * @return
     */
    Employee login(EmployeeLoginDTO employeeLoginDTO);

    void save(EmployeeDTO employeeDTO);

    PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO);

    void startOrStop(Integer status, Long id);

    Employee getById(Long id);

    void update(EmployeeDTO employeeDTO);
}

在 EmployeeServiceImpl 中实现 update 方法:

    // 编辑员工信息
    @Override
    public void update(EmployeeDTO employeeDTO) {
       // 实体属性不等 -> 对象的属性拷贝
       Employee employee = new Employee();
       BeanUtils.copyProperties(employeeDTO, employee);


       // 时间和id
        // employee.setUpdateTime(LocalDateTime.now());
        //employee.setUpdateUser(BaseContext.getCurrentId());

        employeeMapper.update(employee);
    }

在实现启用禁用员工账号功能时,已实现employeeMapper.update(employee),在此不需写Mapper层代码,你业务代码写的再多,最后也肯定是落脚到操作数据库中对应的表。

接口测试和前后端联调

5. 导入分类模块功能代码

后台系统中可以管理分类信息,分类包括两种类型,分别是 菜品分类 和 套餐分类 。

先来分析菜品分类相关功能。

新增菜品分类:当我们在后台系统中添加菜品时需要选择一个菜品分类,在移动端也会按照菜品分类来展示对应的菜品。

菜品分类分页查询:系统中的分类很多的时候,如果在一个页面中全部展示出来会显得比较乱,不便于查看,所以一般的系统中都会以分页的方式来展示列表数据。

根据id删除菜品分类:在分类管理列表页面,可以对某个分类进行删除操作。需要注意的是当分类关联了菜品或者套餐时,此分类不允许删除。

修改菜品分类:在分类管理列表页面点击修改按钮,弹出修改窗口,在修改窗口回显分类信息并进行修改,最后点击确定按钮完成修改操作。

启用禁用菜品分类:在分类管理列表页面,可以对某个分类进行启用或者禁用操作。

分类类型查询:当点击分类类型下拉框时,从数据库中查询所有的菜品分类数据进行展示。

和上面员工的接口类似,可能多修改菜品/套餐这个接口

这个模块资料里有可以导入的现成代码

接口文档中提供了下面这6个接口

新增分类

分类分页查询

根据id删除分类

修改分类

启用禁用分类

根据类型查询分类

1.  新增分类

菜品分类和套餐分类共用一个接口, 新增操作携带的参数有name, 排序所需数字, type: 区分共用接口,提供的category表【数据库表】字段比你前端提交过来的DTO字段多,应该还是要用工具类进行拷贝

就是使用Rest风格对表现层进行开发的时候,删除和修改都应该在路径参数中指定id,但是下面代码中写法直接就 @DeleteMapping @PutMapping 接口文档里面把id定义成了query, 这样也可以

2. 分类分页查询

请求方式为GET, query参数为page【页码】,pageSize【每页记录数】前面写过【新增员工】,使用PageHelper插件,具体参数看资料中的接口文档

3. 根据id删除分类

请求方式为DELETE, query参数为id, 返回的VO还是Result封装的

4. 修改分类

请求方式为PUT, query参数为id, name 排序数字,type区分分类类型

5.启用禁用分类

还是路径参数中携带status: 1【启用】,0【禁用】,query参数为id

6.  根据类型查询分类

请求方式为GET, 查询所有相同类型的数据

可按照mapper-->service-->controller依次导入,这样代码不会显示相应的报错。

进入到sky-server模块

DishMapper.java

package com.sky.mapper;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface DishMapper {

    /**
     * 根据分类id查询菜品数量
     * @param categoryId
     * @return
     */
    @Select("select count(id) from dish where category_id = #{categoryId}")
    Integer countByCategoryId(Long categoryId);

}

SetmealMapper.java

package com.sky.mapper;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface SetmealMapper {

    /**
     * 根据分类id查询套餐的数量
     * @param id
     * @return
     */
    @Select("select count(id) from setmeal where category_id = #{categoryId}")
    Integer countByCategoryId(Long id);

}

CategoryMapper.java

package com.sky.mapper;

import com.github.pagehelper.Page;
import com.sky.dto.CategoryPageQueryDTO;
import com.sky.entity.Category;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;

impor
### 苍穹外卖项目 IDEA 开发配置与使用教程 #### 1. 创建 Maven 项目 为了更好地管理和构建苍穹外卖项目,在 IntelliJ IDEA 中创建一个新的 Maven 项目。确保选择了合适的 Java 版本,并勾选 "Create from archetype" 来选择适合 Web 应用的模板[^2]。 #### 2. 导入现有代码库 如果已经有一个现成的 Git 仓库,则可以通过 `VCS -> Checkout from Version Control` 功能来克隆远程仓库到本地环境中。这一步骤能够帮助快速获取完整的源码文件夹结构以及依赖关系描述文件 pom.xml[^1]。 #### 3. 配置数据源连接 按照指导说明,打开数据库并将提供的 SQL 脚本导入至 MySQL 数据库实例中。接着回到 IDE 内部编辑 application-dev.yml 文件中的 datasource 属性项,将其设置为自己机器上的实际用户名、密码及 URL 地址[^3]: ```yaml spring: datasource: url: jdbc:mysql://localhost:3306/foodie?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC username: root password: your_password_here ``` #### 4. 设置运行参数 为了让应用程序能够在不同的环境下正常工作(比如开发模式 dev 或者生产模式 prod),可以在启动命令后面加上 `-Dspring.profiles.active=dev` 参数指定当前使用的 profile 是哪一个。这样做的好处是可以轻松切换不同场景下的特定配置而无需频繁更改主配置文件的内容: ```bash java -jar -Dspring.profiles.active=dev food-delivery.jar ``` #### 5. Nginx 反向代理配置 对于前端请求转发给后端服务的情况,通常会采用 Nginx 作为反向代理服务器来进行处理。通过调整 nginx.conf 文件内的 location 指令实现 API 请求路径映射规则设定,从而使得前后端分离架构更加清晰合理。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值