国内有哪些比较好的做定制旅游网站,北京网络营销技术培训,旅游网站建设的目的及功能定位,网站维护费计入什么科目菜品管理 1 新增菜品1.1 需求分析与设计1.2 代码开发文件上传新增菜品实现 1.3 功能测试 2 菜品分页查询2.1 需求分析和设计2.2 代码开发设计DTO类设计VO类Controller层Service层Mapper层 2.3 功能测试 3 删除菜品3.1 需求分析和设计3.2 代码开发Controller层Service层Mapper层… 菜品管理 1 新增菜品1.1 需求分析与设计1.2 代码开发文件上传新增菜品实现 1.3 功能测试 2 菜品分页查询2.1 需求分析和设计2.2 代码开发设计DTO类设计VO类Controller层Service层Mapper层 2.3 功能测试 3 删除菜品3.1 需求分析和设计3.2 代码开发Controller层Service层Mapper层 3.3 功能测试 4 修改菜品4.1 需求分析和设计4.2 根据id查询菜品代码开发Controller层Service层 4.3 修改菜品代码开发Controller层Service层接口Mapper层 4.4 功能测试 5 菜品起售或停售状态5.1 需求分析和设计5.1.1 页面原型5.1.2 接口设计 5.2 代码开发ControllerServiceMapper层 5.3 功能测试 1 新增菜品
1.1 需求分析与设计
详见资料中的产品原型和业务规则。HTML的静态网页已经包含所有信息。 产品原型 业务规则 接口设计 接口设计
根据类型查询分类已完成文件上传新增菜品 表设计
新增菜品其实就是将新增页面录入的菜品信息插入到dish表如果添加了口味做法还需要向dish_flavor表插入数据。所以在新增菜品时涉及到两个表
表名说明dish菜品表dish_flavor菜品口味表
1). 菜品表:dish
字段名数据类型说明备注idbigint主键自增namevarchar(32)菜品名称唯一category_idbigint分类id逻辑外键pricedecimal(10,2)菜品价格imagevarchar(255)图片路径descriptionvarchar(255)菜品描述statusint售卖状态1起售 0停售create_timedatetime创建时间update_timedatetime最后修改时间create_userbigint创建人idupdate_userbigint最后修改人id 2). 菜品口味表:dish_flavor
字段名数据类型说明备注idbigint主键自增dish_idbigint菜品id逻辑外键namevarchar(32)口味名称valuevarchar(255)口味值 1.2 代码开发
文件上传
直接将图片保存到服务的硬盘springmvc中的文件上传 优点开发便捷成本低缺点扩容困难 使用分布式文件系统进行存储 优点容易实现扩容缺点开发复杂度稍大有成熟的产品可以使用比如FastDFS,MinIO 使用第三方的存储服务例如OSS 优点开发简单拥有强大功能免维护缺点付费
我们使用OSS服务进行文件存储 实现步骤
1). 定义OSS相关配置
在sky-server模块
application-dev.yml
sky:alioss:endpoint: yoursaccess-key-id: yoursaccess-key-secret: yoursbucket-name: yoursapplication.yml
spring:profiles:active: dev #设置环境
sky: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}
以下是我使用阿里云OSS存储的文件。 rescources中添加
2). 读取OSS配置
在sky-common模块中已定义
package com.sky.properties;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;Component
ConfigurationProperties(prefix sky.alioss)
Data
public class AliOssProperties {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketName;}3). 生成OSS工具类对象
在sky-server模块
package com.sky.config;import com.sky.properties.AliOssProperties;
import com.sky.utils.AliOssUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** 配置类用于创建AliOssUtil对象*/
Configuration
Slf4j
public class OssConfiguration {BeanConditionalOnMissingBeanpublic AliOssUtil aliOssUtil(AliOssProperties aliOssProperties){log.info(开始创建阿里云文件上传工具类对象{},aliOssProperties);return new AliOssUtil(aliOssProperties.getEndpoint(),aliOssProperties.getAccessKeyId(),aliOssProperties.getAccessKeySecret(),aliOssProperties.getBucketName());}
}其中AliOssUtil.java已在sky-common模块中定义 定义了一个名为AliOssUtil的工具类用于与阿里云OSSObject Storage Service交互实现文件的上传。以下是关键点的解释
类属性
endpoint: 阿里云OSS服务的访问域名。accessKeyId: 阿里云账号的Access Key ID用于身份验证。accessKeySecret: 阿里云账号的Access Key Secret用于身份验证。bucketName: 存储空间名称。
上传方法
upload(byte[] bytes, String objectName)接收一个字节数组代表文件内容和一个对象名称然后将文件上传到OSS。 使用OSSClientBuilder创建OSSClient实例这是与OSS服务交互的主要对象。putObject方法用于上传文件传入存储空间名称、对象名称和ByteArrayInputStream后者由字节数组创建。异常处理捕获OSSException和ClientException分别处理服务端和客户端可能出现的问题。 最后关闭OSSClient以释放资源。
URL构建
方法返回一个字符串表示上传文件后的访问URL。URL由bucketName、endpoint和objectName拼接而成。
数据库连接字符串未完的代码片段
提供了一个JDBC数据库连接字符串用于连接MySQL数据库。包含了数据库的主机、端口、数据库名以及相关连接参数。 请注意暴露accessKeyId和accessKeySecret这样的敏感信息在生产环境中是不安全的。通常这些信息应存储在环境变量或配置服务器中并在运行时注入到应用程序中。
package com.sky.utils;import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.io.ByteArrayInputStream;Data
AllArgsConstructor
Slf4j
public class AliOssUtil {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketName;/*** 文件上传** param bytes* param objectName* return*/public String upload(byte[] bytes, String objectName) {// 创建OSSClient实例。OSS ossClient new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);try {// 创建PutObject请求。ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));} catch (OSSException oe) {System.out.println(Caught an OSSException, which means your request made it to OSS, but was rejected with an error response for some reason.);System.out.println(Error Message: oe.getErrorMessage());System.out.println(Error Code: oe.getErrorCode());System.out.println(Request ID: oe.getRequestId());System.out.println(Host ID: oe.getHostId());} catch (ClientException ce) {System.out.println(Caught an ClientException, which means the client encountered a serious internal problem while trying to communicate with OSS, such as not being able to access the network.);System.out.println(Error Message: ce.getMessage());} finally {if (ossClient ! null) {ossClient.shutdown();}}//文件访问路径规则 https://BucketName.Endpoint/ObjectNameStringBuilder stringBuilder new StringBuilder(https://);stringBuilder.append(bucketName).append(.).append(endpoint).append(/).append(objectName);log.info(文件上传到:{}, stringBuilder.toString());return stringBuilder.toString();}
}4). 定义文件上传接口
在sky-server模块中定义接口
package com.sky.controller.admin;import com.sky.constant.MessageConstant;
import com.sky.result.Result;
import com.sky.utils.AliOssUtil;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.UUID;/*** 通用接口*/
RestController
RequestMapping(/admin/common)
Api(tags 通用接口)
Slf4j
public class CommonController {Autowiredprivate AliOssUtil aliOssUtil;/*** 文件上传* param file* return*/PostMapping(/upload)ApiOperation(文件上传)public ResultString upload(MultipartFile file){log.info(文件上传{},file);try {//原始文件名String originalFilename file.getOriginalFilename();//截取原始文件名的后缀 dfdfdf.pngString extension originalFilename.substring(originalFilename.lastIndexOf(.));//构造新文件名称String objectName UUID.randomUUID().toString() extension;//文件的请求路径String filePath aliOssUtil.upload(file.getBytes(), objectName);return Result.success(filePath);} catch (IOException e) {log.error(文件上传失败{}, e);}return Result.error(MessageConstant.UPLOAD_FAILED);}
}其中AliOssUtil.java已在sky-common模块中定义
package com.sky.utils;import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.io.ByteArrayInputStream;Data
AllArgsConstructor
Slf4j
public class AliOssUtil {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketName;/*** 文件上传** param bytes* param objectName* return*/public String upload(byte[] bytes, String objectName) {// 创建OSSClient实例。OSS ossClient new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);try {// 创建PutObject请求。ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));} catch (OSSException oe) {System.out.println(Caught an OSSException, which means your request made it to OSS, but was rejected with an error response for some reason.);System.out.println(Error Message: oe.getErrorMessage());System.out.println(Error Code: oe.getErrorCode());System.out.println(Request ID: oe.getRequestId());System.out.println(Host ID: oe.getHostId());} catch (ClientException ce) {System.out.println(Caught an ClientException, which means the client encountered a serious internal problem while trying to communicate with OSS, such as not being able to access the network.);System.out.println(Error Message: ce.getMessage());} finally {if (ossClient ! null) {ossClient.shutdown();}}//文件访问路径规则 https://BucketName.Endpoint/ObjectNameStringBuilder stringBuilder new StringBuilder(https://);stringBuilder.append(bucketName).append(.).append(endpoint).append(/).append(objectName);log.info(文件上传到:{}, stringBuilder.toString());return stringBuilder.toString();}
}4). 定义文件上传接口
在sky-server模块中的controller.admin定义接口 CommonController
package com.sky.controller.admin;import com.sky.constant.MessageConstant;
import com.sky.result.Result;
import com.sky.utils.AliOssUtil;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.UUID;/*** 通用接口*/
RestController
RequestMapping(/admin/common)
Api(tags 通用接口)
Slf4j
public class CommonController {Autowiredprivate AliOssUtil aliOssUtil;/*** 文件上传* param file* return*/PostMapping(/upload)ApiOperation(文件上传)public ResultString upload(MultipartFile file){log.info(文件上传{},file);try {//原始文件名String originalFilename file.getOriginalFilename();//截取原始文件名的后缀 dfdfdf.pngString extension originalFilename.substring(originalFilename.lastIndexOf(.));//构造新文件名称String objectName UUID.randomUUID().toString() extension;//文件的请求路径String filePath aliOssUtil.upload(file.getBytes(), objectName);return Result.success(filePath);} catch (IOException e) {log.error(文件上传失败{}, e);}return Result.error(MessageConstant.UPLOAD_FAILED);}
}新增菜品实现
设计DTO类
在sky-pojo模块中
package com.sky.dto;import com.sky.entity.DishFlavor;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;Data
public class DishDTO implements Serializable {private Long id;//菜品名称private String name;//菜品分类idprivate Long categoryId;//菜品价格private BigDecimal price;//图片private String image;//描述信息private String description;//0 停售 1 起售private Integer status;//口味private ListDishFlavor flavors new ArrayList();
}2). Controller层
进入到sky-server模块
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;
import java.util.Set;/*** 菜品管理*/
RestController
RequestMapping(/admin/dish)
Api(tags 菜品相关接口)
Slf4j
public class DishController {Autowiredprivate DishService dishService;/*** 新增菜品** param dishDTO* return*/PostMappingApiOperation(新增菜品)public Result save(RequestBody DishDTO dishDTO) {log.info(新增菜品{}, dishDTO);dishService.saveWithFlavor(dishDTO);//后绪步骤开发return Result.success();}
}3). Service层接口
package com.sky.service;import com.sky.dto.DishDTO;
import com.sky.entity.Dish;public interface DishService {/*** 新增菜品和对应的口味** param dishDTO*/public void saveWithFlavor(DishDTO dishDTO);}4). Service层实现类
package com.sky.service.impl;Service
Slf4j
public class DishServiceImpl implements DishService {Autowiredprivate DishMapper dishMapper;Autowiredprivate DishFlavorMapper dishFlavorMapper;/*** 新增菜品和对应的口味** param dishDTO*/Transactionalpublic void saveWithFlavor(DishDTO dishDTO) {Dish dish new Dish();BeanUtils.copyProperties(dishDTO, dish);//向菜品表插入1条数据dishMapper.insert(dish);//后绪步骤实现//获取insert语句生成的主键值Long dishId dish.getId();ListDishFlavor flavors dishDTO.getFlavors();if (flavors ! null flavors.size() 0) {flavors.forEach(dishFlavor - {dishFlavor.setDishId(dishId);});//向口味表插入n条数据dishFlavorMapper.insertBatch(flavors);//后绪步骤实现}}}5). Mapper层
DishMapper.java中添加 /*** 插入菜品数据** param dish*/AutoFill(value OperationType.INSERT)void insert(Dish dish);在/resources/mapper中创建DishMapper.xml
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.sky.mapper.DishMapperinsert idinsert useGeneratedKeystrue keyPropertyidinsert into dish (name, category_id, price, image, description, create_time, update_time, create_user,update_user, status)values (#{name}, #{categoryId}, #{price}, #{image}, #{description}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser}, #{status})/insert
/mapper
DishFlavorMapper.java
package com.sky.mapper;import com.sky.entity.DishFlavor;
import java.util.List;Mapper
public interface DishFlavorMapper {/*** 批量插入口味数据* param flavors*/void insertBatch(ListDishFlavor flavors);}在/resources/mapper中创建DishFlavorMapper.xml
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.sky.mapper.DishFlavorMapperinsert idinsertBatchinsert into dish_flavor (dish_id, name, value) VALUESforeach collectionflavors itemdf separator,(#{df.dishId},#{df.name},#{df.value})/foreach/insert
/mapper1.3 功能测试
不管是接口测试还是前后端测试
最后看控制台信息添加成功 2 菜品分页查询
2.1 需求分析和设计
产品原型 业务规则 见资料静态HTML网页 接口设计 见ApiFox网站
2.2 代码开发
设计DTO类
根据菜品分页查询接口定义设计对应的DTO
在sky-pojo模块中已定义
package com.sky.dto;import lombok.Data;
import java.io.Serializable;Data
public class DishPageQueryDTO implements Serializable {private int page;private int pageSize;private String name;private Integer categoryId; //分类idprivate Integer status; //状态 0表示禁用 1表示启用}设计VO类
根据菜品分页查询接口定义设计对应的VO
在sky-pojo模块中已定义
package com.sky.vo;import com.sky.entity.DishFlavor;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;Data
Builder
NoArgsConstructor
AllArgsConstructor
public class DishVO implements Serializable {private Long id;//菜品名称private String name;//菜品分类idprivate Long categoryId;//菜品价格private BigDecimal price;//图片private String image;//描述信息private String description;//0 停售 1 起售private Integer status;//更新时间private LocalDateTime updateTime;//分类名称private String categoryName;//菜品关联的口味private ListDishFlavor flavors new ArrayList();
}Controller层
根据接口定义创建DishController的page分页查询方法 /*** 菜品分页查询** param dishPageQueryDTO* return*/GetMapping(/page)ApiOperation(菜品分页查询)public ResultPageResult page(DishPageQueryDTO dishPageQueryDTO) {log.info(菜品分页查询:{}, dishPageQueryDTO);PageResult pageResult dishService.pageQuery(dishPageQueryDTO);//后绪步骤定义return Result.success(pageResult);}Service层
在 DishService 中扩展分页查询方法 /*** 菜品分页查询** param dishPageQueryDTO* return*/PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO);在 DishServiceImpl 中实现分页查询方法 /*** 菜品分页查询** param dishPageQueryDTO* return*/public PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO) {PageHelper.startPage(dishPageQueryDTO.getPage(), dishPageQueryDTO.getPageSize());PageDishVO page dishMapper.pageQuery(dishPageQueryDTO);//后绪步骤实现return new PageResult(page.getTotal(), page.getResult());}Mapper层
在 DishMapper 接口中声明 pageQuery 方法 /*** 菜品分页查询** param dishPageQueryDTO* return*/PageDishVO pageQuery(DishPageQueryDTO dishPageQueryDTO);在 DishMapper.xml 中编写SQL
select idpageQuery resultTypecom.sky.vo.DishVOselect d.* , c.name as categoryName from dish d left outer join category c on d.category_id c.idwhereif testname ! nulland d.name like concat(%,#{name},%)/ifif testcategoryId ! nulland d.category_id #{categoryId}/ifif teststatus ! nulland d.status #{status}/if/whereorder by d.create_time desc
/select2.3 功能测试 3 删除菜品
3.1 需求分析和设计
菜品原型和业务规则 详见资料中的页面原型
接口设计 详见Apifox
表设计 注意事项
在dish表中删除菜品基本数据时同时也要把关联在dish_flavor表中的数据一块删除。setmeal_dish表为菜品和套餐关联的中间表。若删除的菜品数据关联着某个套餐此时删除失败。若要删除套餐关联的菜品数据先解除两者关联再对菜品进行删除。
3.2 代码开发
Controller层
根据删除菜品的接口定义在DishController中创建方法 /*** 菜品批量删除** param ids* return*/DeleteMappingApiOperation(菜品批量删除)public Result delete(RequestParam ListLong ids) {log.info(菜品批量删除{}, ids);dishService.deleteBatch(ids);//后绪步骤实现return Result.success();}Service层
在DishService接口中声明deleteBatch方法 /*** 菜品批量删除** param ids*/void deleteBatch(ListLong ids);在DishServiceImpl中实现deleteBatch方法 Autowiredprivate SetmealDishMapper setmealDishMapper;/*** 菜品批量删除** param ids*/Transactional//事务public void deleteBatch(ListLong ids) {//判断当前菜品是否能够删除---是否存在起售中的菜品for (Long id : ids) {Dish dish dishMapper.getById(id);//后绪步骤实现if (dish.getStatus() StatusConstant.ENABLE) {//当前菜品处于起售中不能删除throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);}}//判断当前菜品是否能够删除---是否被套餐关联了ListLong 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);//后绪步骤实现}}Mapper层
在DishMapper中声明getById方法并配置SQL /*** 根据主键查询菜品** param id* return*/Select(select * from dish where id #{id})Dish getById(Long id);创建SetmealDishMapper声明getSetmealIdsByDishIds方法并在xml文件中编写SQL
package com.sky.mapper;import com.sky.entity.SetmealDish;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
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)ListLong getSetmealIdsByDishIds(ListLong dishIds);
}
SetmealDishMapper.xml
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.sky.mapper.SetmealDishMapperselect idgetSetmealIdsByDishIds resultTypejava.lang.Longselect setmeal_id from setmeal_dish where dish_id inforeach collectiondishIds itemdishId separator, open( close)#{dishId}/foreach/select
/mapper在DishMapper.java中声明deleteById方法并配置SQL /*** 根据主键删除菜品数据** param id*/Delete(delete from dish where id #{id})void deleteById(Long id);在DishFlavorMapper中声明deleteByDishId方法并配置SQL /*** 根据菜品id删除对应的口味数据* param dishId*/Delete(delete from dish_flavor where dish_id #{dishId})void deleteByDishId(Long dishId);3.3 功能测试
详略得当
4 修改菜品
4.1 需求分析和设计
产品原型和接口设计 详见资料中的页面原型和ApiFox中的接口设计
接口
根据id查询菜品根据类型查询分类(已实现)文件上传(已实现)修改菜品
我们只需要实现根据id查询菜品和修改菜品两个接口接下来我们来重点分析这两个接口。
4.2 根据id查询菜品代码开发
Controller层
根据id查询菜品的接口定义在DishController中创建方法 /*** 根据id查询菜品** param id* return*/GetMapping(/{id})ApiOperation(根据id查询菜品)public ResultDishVO getById(PathVariable Long id) {log.info(根据id查询菜品{}, id);DishVO dishVO dishService.getByIdWithFlavor(id);//后绪步骤实现return Result.success(dishVO);}Service层
在DishService接口中声明getByIdWithFlavor方法 /*** 根据id查询菜品和对应的口味数据** param id* return*/DishVO getByIdWithFlavor(Long id);在DishServiceImpl中实现getByIdWithFlavor方法 /*** 根据id查询菜品和对应的口味数据** param id* return*/public DishVO getByIdWithFlavor(Long id) {//根据id查询菜品数据Dish dish dishMapper.getById(id);//根据菜品id查询口味数据ListDishFlavor dishFlavors dishFlavorMapper.getByDishId(id);//后绪步骤实现//将查询到的数据封装到VODishVO dishVO new DishVO();BeanUtils.copyProperties(dish, dishVO);dishVO.setFlavors(dishFlavors);return dishVO;}Mapper层 在DishFlavorMapper中声明getByDishId方法并配置SQL /*** 根据菜品id查询对应的口味数据* param dishId* return*/Select(select * from dish_flavor where dish_id #{dishId})ListDishFlavor getByDishId(Long dishId);4.3 修改菜品代码开发
Controller层
根据修改菜品的接口定义在DishController中创建方法 /*** 修改菜品** param dishDTO* return*/PutMappingApiOperation(修改菜品)public Result update(RequestBody DishDTO dishDTO) {log.info(修改菜品{}, dishDTO);dishService.updateWithFlavor(dishDTO);return Result.success();}Service层接口
在DishService接口中声明updateWithFlavor方法 /*** 根据id修改菜品基本信息和对应的口味信息** param dishDTO*/void updateWithFlavor(DishDTO dishDTO);在DishServiceImpl中实现updateWithFlavor方法 /*** 根据id修改菜品基本信息和对应的口味信息** param dishDTO*/public void updateWithFlavor(DishDTO dishDTO) {Dish dish new Dish();BeanUtils.copyProperties(dishDTO, dish);//修改菜品表基本信息dishMapper.update(dish);//删除原有的口味数据dishFlavorMapper.deleteByDishId(dishDTO.getId());//重新插入口味数据ListDishFlavor flavors dishDTO.getFlavors();if (flavors ! null flavors.size() 0) {flavors.forEach(dishFlavor - {dishFlavor.setDishId(dishDTO.getId());});//向口味表插入n条数据dishFlavorMapper.insertBatch(flavors);}}Mapper层
在DishMapper中声明update方法 /*** 根据id动态修改菜品数据** param dish*/AutoFill(value OperationType.UPDATE)void update(Dish dish);并在DishMapper.xml文件中编写SQL:
update idupdateupdate dishsetif testname ! nullname #{name},/ifif testcategoryId ! nullcategory_id #{categoryId},/ifif testprice ! nullprice #{price},/ifif testimage ! nullimage #{image},/ifif testdescription ! nulldescription #{description},/ifif teststatus ! nullstatus #{status},/ifif testupdateTime ! nullupdate_time #{updateTime},/ifif testupdateUser ! nullupdate_user #{updateUser},/if/setwhere id #{id}
/update4.4 功能测试 5 菜品起售或停售状态
5.1 需求分析和设计
5.1.1 页面原型
在菜品管理列表页面可以对某个菜品进行启售或者售操作。停售的菜品不能售卖启售的菜品可以售卖。如果某个菜品状态为正常则按钮显示为 “停售”如果菜品状态为停售则按钮显示为起售。 业务规则 启售/停售 菜品停售则包含菜品的套餐同时停售。 菜品停售则包含菜品的套餐同时停售。 菜品停售则包含菜品的套餐同时停售。 【启售/停售】菜品被停售后前台不展示 点【启售/停售】弹出确认弹窗操作成功提示 操作成功失败提示 操作失败。
5.1.2 接口设计 1). 路径参数携带状态值。
2). 同时把id传递过去明确对哪个菜品进行操作。
3). 返回数据code状态是必须其它是非必须。
5.2 代码开发
Controller
在sky-server模块中根据接口设计中的请求参数形式对应的在 DishController 中创建启用禁用员工账号的方法
/*** 菜品起售停售* param status* param id* return
*/
PostMapping(/status/{status})
ApiOperation(菜品起售停售)
public ResultString startOrStop(PathVariable Integer status, Long id){dishService.startOrStop(status,id);return Result.success();
}Service
DishService接口中声明startOrStop方法
/*** 菜品起售停售* param status* param id
*/
void startOrStop(Integer status, Long id);DishServiceImpl中实现startOrStop方法。
/*** 菜品起售停售** param status* param id
*/
Transactional
public void startOrStop(Integer status, Long id) {Dish dish Dish.builder().id(id).status(status).build();dishMapper.update(dish);if (status StatusConstant.DISABLE) {// 如果是停售操作还需要将包含当前菜品的套餐也停售ListLong dishIds new ArrayList();dishIds.add(id);// select setmeal_id from setmeal_dish where dish_id in (?,?,?)ListLong 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);}}}
}Mapper层
SetmealMapper已经实现了对根据id修改
/*** 根据id修改菜品** param setmeal*/
AutoFill(OperationType.UPDATE)
void update(Setmeal setmeal);SetmealMapper.xml中添加一条对categoryId的判断。
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.sky.mapper.SetmealMapperupdate idupdate parameterTypeSetmealupdate setmealsetif testname ! nullname #{name},/ifif testcategoryId ! nullcategory_id #{categoryId},/ifif testprice ! nullprice #{price},/ifif teststatus ! nullstatus #{status},/ifif testdescription ! nulldescription #{description},/ifif testimage ! nullimage #{image},/ifif testupdateTime ! nullupdate_time #{updateTime},/ifif testupdateUser ! nullupdate_user #{updateUser}/if/setwhere id #{id}/update/mapper5.3 功能测试