当前位置: 首页 > news >正文

苍穹外卖-day04:项目实战-套餐管理(新增套餐,分页查询套餐,删除套餐,修改套餐,起售停售套餐)业务类似于菜品模块

苍穹外卖-day04

课程内容

  • 新增套餐
  • 套餐分页查询
  • 删除套餐
  • 修改套餐
  • 起售停售套餐

要求:

  1. 根据产品原型进行需求分析,分析出业务规则
  2. 设计接口
  3. 梳理表之间的关系(分类表、菜品表、套餐表、口味表、套餐菜品关系表)
  4. 根据接口设计进行代码实现
  5. 分别通过swagger接口文档和前后端联调进行功能测试

1. 新增套餐

1.1 需求分析和设计

产品原型:

在这里插入图片描述

在这里插入图片描述

业务规则:

  • 套餐名称唯一
  • 套餐必须属于某个分类
  • 套餐必须包含菜品
  • 名称、分类、价格、图片为必填项
  • 添加菜品窗口需要根据分类类型来展示菜品
  • 新增的套餐默认为停售状态

接口设计(共涉及到4个接口):

  • 根据类型查询分类(已完成)
  • 根据分类id查询菜品
  • 图片上传(已完成)
  • 新增套餐

在这里插入图片描述

在这里插入图片描述

数据库设计:

setmeal表为套餐表,用于存储套餐的信息。具体表结构如下:

字段名数据类型说明备注
idbigint主键自增
namevarchar(32)套餐名称唯一
category_idbigint分类id逻辑外键
pricedecimal(10,2)套餐价格
imagevarchar(255)图片路径
descriptionvarchar(255)套餐描述
statusint售卖状态1起售 0停售
create_timedatetime创建时间
update_timedatetime最后修改时间
create_userbigint创建人id
update_userbigint最后修改人id

setmeal_dish表为套餐菜品关系表,用于存储套餐和菜品的关联关系。具体表结构如下:

字段名数据类型说明备注
idbigint主键自增
setmeal_idbigint套餐id逻辑外键
dish_idbigint菜品id逻辑外键
namevarchar(32)菜品名称冗余字段
pricedecimal(10,2)菜品单价冗余字段
copiesint菜品份数

1.2 代码实现

1.2.1 DishController(根据分类id查询菜品)

在这里插入图片描述

/*** 根据分类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);
}
1.2.2 DishService
/*** 根据分类id查询菜品* @param categoryId* @return
*/
List<Dish> list(Long categoryId);
1.2.3 DishServiceImpl(请求参数封装的不同情况)
/*** 根据分类id查询菜品* @param categoryId* @return
*/
public List<Dish> list(Long categoryId) {Dish dish = Dish.builder().categoryId(categoryId).status(StatusConstant.ENABLE).build();return dishMapper.list(dish);
}
1.2.4 DishMapper
/*** 动态条件查询菜品* @param dish* @return
*/
List<Dish> list(Dish dish);
1.2.5 DishMapper.xml
<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>

前后端联调:

在这里插入图片描述

在这里插入图片描述

1.2.6 SetmealController(新增套餐)

在这里插入图片描述

/*** 套餐管理*/
@RestController
@RequestMapping("/admin/setmeal")
@Api(tags = "套餐相关接口")
@Slf4j
public class SetmealController {@Autowiredprivate SetmealService setmealService;/*** 新增套餐* @param setmealDTO* @return*/@PostMapping@ApiOperation("新增套餐")public Result save(@RequestBody SetmealDTO setmealDTO) {setmealService.saveWithDish(setmealDTO);return Result.success();}
}
1.2.7 SetmealService
public interface SetmealService {/*** 新增套餐,同时需要保存套餐和菜品的关联关系* @param setmealDTO*/void saveWithDish(SetmealDTO setmealDTO);
}
1.2.8 SetmealServiceImpl(新增业务逻辑 类似新增菜品逻辑)
/*** 套餐业务实现*/
@Service
@Slf4j
public class SetmealServiceImpl implements SetmealService {@Autowiredprivate SetmealMapper setmealMapper;@Autowiredprivate SetmealDishMapper setmealDishMapper;@Autowiredprivate DishMapper dishMapper;/*** 新增套餐,同时需要保存套餐和菜品的关联关系* @param setmealDTO*/@Transactional@Overridepublic void saveWithDish(SetmealDTO setmealDTO) {//请求参数用的是SetmealDTO类封装的,包含套餐数据以及套餐菜品关系表数据,//   这个地方只需要插入套餐的基本信息,所以进行属性拷贝。Setmeal setmeal = new Setmeal();BeanUtils.copyProperties(setmealDTO, setmeal);//向套餐表插入数据setmealMapper.insert(setmeal);//获取生成的套餐id   通过sql中的useGeneratedKeys="true" keyProperty="id"获取插入后生成的主键值//套餐菜品关系表的setmealId页面不能传递,它是向套餐表插入数据之后生成的主键值,也就是套餐菜品关系表的逻辑外键setmealIdLong setmealId = setmeal.getId();//获取页面传来的套餐和菜品关系表数据List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();//遍历关系表数据,为关系表中的每一条数据(每一个对象)的setmealId赋值,//   这个地方不需要像之前写新增菜品时多写个if判断,因为之前的口味数据是非必须的,//   这个地方要求套餐必须包含菜品是必须的,所以不需要if判断,不存在套餐不包含菜品得情况setmealDishes.forEach(setmealDish -> {//将Setmeal套餐类的id属性赋值给SetmealDish套餐关系类的setmealId//套餐表的id保存在套餐关系表充当外键为setmealIdsetmealDish.setSetmealId(setmealId);});//保存套餐和菜品的关联关系  动态sql批量插入setmealDishMapper.insertBatch(setmealDishes);}
}
1.2.9 SetmealMapper
/*** 新增套餐* @param setmeal
*/
@AutoFill(OperationType.INSERT)
void insert(Setmeal setmeal);
1.2.10 SetmealMapper.xml
<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>
1.2.11 SetmealDishMapper
/*** 批量保存套餐和菜品的关联关系* @param setmealDishes
*/
void insertBatch(List<SetmealDish> setmealDishes);
1.2.12 SetmealDishMapper.xml
<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>

1.3 功能测试

略,还没有写分页查询,所以暂时不进行前后端联调。

2. 套餐分页查询(字段和属性不一致问题)

2.1 需求分析和设计

产品原型:

在这里插入图片描述

业务规则:

  • 根据页码进行分页展示
  • 每页展示10条数据
  • 可以根据需要,按照套餐名称、分类、售卖状态进行查询

接口设计:

在这里插入图片描述

2.2 代码实现

2.2.1 SetmealController

在这里插入图片描述

/*** 分页查询* @param setmealPageQueryDTO* @return
*/
@GetMapping("/page")
@ApiOperation("分页查询")
public Result<PageResult> page(SetmealPageQueryDTO setmealPageQueryDTO) {PageResult pageResult = setmealService.pageQuery(setmealPageQueryDTO);return Result.success(pageResult);
}
2.2.2 SetmealService
/*** 分页查询* @param setmealPageQueryDTO* @return
*/
PageResult pageQuery(SetmealPageQueryDTO setmealPageQueryDTO);
2.2.3 SetmealServiceImpl
    /*** 分页查询* @param setmealPageQueryDTO* @return*/@Overridepublic PageResult pageQuery(SetmealPageQueryDTO setmealPageQueryDTO) {int pageNum = setmealPageQueryDTO.getPage();int pageSize = setmealPageQueryDTO.getPageSize();//需要在查询功能之前开启分页功能:当前页的页码   每页显示的条数PageHelper.startPage(pageNum, pageSize);//这个方法有返回值为Page对象,里面保存的是分页之后的相关数据Page<SetmealVO> page = setmealMapper.pageQuery(setmealPageQueryDTO);//封装到PageResult中:总记录数  当前页数据集合return new PageResult(page.getTotal(), page.getResult());}
2.2.4 SetmealMapper
/*** 分页查询* @param setmealPageQueryDTO* @return
*/
Page<SetmealVO> pageQuery(SetmealPageQueryDTO setmealPageQueryDTO);
2.2.5 SetmealMapper.xml
  • 问题:类似于菜品分页查询,在套餐分页查询中,套餐表setmeal保存的字段是category_id分类id,而接口文档要求返回的数据是分类名称。

  • 解决:使用左外连接查询。查询套餐表以及套餐对应的分类名称。

  • 注意:此时查询出套餐表中的字段 套餐名称为name,分类表中的字段分类名称也是name,那这样的话我们在封装数据的时候就会出现问题,通过mybatis框架去封装数据的时候由于这2个字段名相同,封装VO这个数据的时候就会对应错,分类表中的字段分类名称是name字段,SetmealVO是categoryName属性,字段名和属性名不一致所以封装不了数据。------------通过起字段别名方式解决c.name as categoryName

  • 名称习惯使用模糊查询而不是等号。

<select id="pageQuery" resultType="com.sky.vo.SetmealVO">selects.*,c.name categoryNamefromsetmeal sleft joincategory cons.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>

2.3 功能测试

测试:分页查询
在这里插入图片描述

测试:新增套餐

在这里插入图片描述
在这里插入图片描述

3. 删除套餐(删除的业务逻辑)

3.1 需求分析和设计

产品原型:

在这里插入图片描述

业务规则:

  • 可以一次删除一个套餐,也可以批量删除套餐
  • 起售中的套餐不能删除

接口设计:

在这里插入图片描述

3.2 代码实现

3.2.1 SetmealController

在这里插入图片描述

/*** 批量删除套餐* @param ids* @return
*/
@DeleteMapping
@ApiOperation("批量删除套餐")
public Result delete(@RequestParam List<Long> ids){setmealService.deleteBatch(ids);return Result.success();
}
3.2.2 SetmealService
/*** 批量删除套餐* @param ids
*/
void deleteBatch(List<Long> ids);
3.2.3 SetmealServiceImpl
    /*** 批量删除套餐* @param ids*/@Transactional@Overridepublic void deleteBatch(List<Long> ids) {//判断当前套餐是否能够删除---是否存在起售中的套餐??//思路:遍历获取传入的id,根据id查询套餐setmeal中的status字段,0 停售 1 起售,//    如果是1代表是起售状态不能删除ids.forEach(id -> {Setmeal setmeal = setmealMapper.getById(id);if(StatusConstant.ENABLE == setmeal.getStatus()){//起售中的套餐不能删除throw new DeletionNotAllowedException(MessageConstant.SETMEAL_ON_SALE);}});//思路:套餐表和菜品表是多对多关系,把整个套餐都删除了,那么关系表中保存的套餐对应//     的菜品关系就没有意义了,所以此时也应该删除关系表中的数据。ids.forEach(setmealId -> {//删除套餐表中的数据setmealMapper.deleteById(setmealId);//删除套餐菜品关系表中的数据setmealDishMapper.deleteBySetmealId(setmealId);});}

类似于删除菜品,删除套餐的sql存在缺点:

  • 上述代码每一次for循环遍历都会发生2条sql(删除套餐、删除套餐菜品关系表数据),如果遍历的次数比较多,那么发出的sql数量也很多,可能会引发性能一些方面的问题。
  • 解决:减少sql语句的数量,使用动态sql批量删除,只需要1条sql就可以把需要删除的菜品删除掉,同样1条sql删除口味表的数据
  • 这里不在演示,详情查看day03-删除菜品。这里使用的是有缺点的方式做的删除。
3.2.4 SetmealMapper
/*** 根据id查询套餐* @param id* @return
*/
@Select("select * from setmeal where id = #{id}")
Setmeal getById(Long id);/*** 根据id删除套餐* @param setmealId
*/
@Delete("delete from setmeal where id = #{id}")
void deleteById(Long setmealId);
3.2.5 SetmealDishMapper
/*** 根据套餐id删除套餐和菜品的关联关系* @param setmealId
*/
@Delete("delete from setmeal_dish where setmeal_id = #{setmealId}")
void deleteBySetmealId(Long setmealId);

3.3 功能测试

在这里插入图片描述

在这里插入图片描述

4. 修改套餐(修改的业务逻辑)

4.1 需求分析和设计

产品原型:

在这里插入图片描述

接口设计(共涉及到5个接口):

  • 根据id查询套餐
  • 根据类型查询分类(已完成)
  • 根据分类id查询菜品(已完成)
  • 图片上传(已完成)
  • 修改套餐

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4.2 代码实现

4.2.1 SetmealController

在这里插入图片描述

/*** 根据id查询套餐,用于修改页面回显数据** @param id* @return
*/
@GetMapping("/{id}")
@ApiOperation("根据id查询套餐")
public Result<SetmealVO> getById(@PathVariable Long id) {SetmealVO setmealVO = setmealService.getByIdWithDish(id);return Result.success(setmealVO);
}/*** 修改套餐** @param setmealDTO* @return
*/
@PutMapping
@ApiOperation("修改套餐")
public Result update(@RequestBody SetmealDTO setmealDTO) {setmealService.update(setmealDTO);return Result.success();
}
4.2.2 SetmealService
    /*** 根据id查询套餐和关联的菜品数据* @param id* @return*/SetmealVO getByIdWithDish(Long id);/*** 修改套餐* @param setmealDTO*/void update(SetmealDTO setmealDTO);
4.2.3 SetmealServiceImpl
    /*** 根据id查询套餐和套餐菜品关系** @param id* @return*/@Overridepublic SetmealVO getByIdWithDish(Long id) {//根据id查询套餐表数据Setmeal setmeal = setmealMapper.getById(id);//删除菜品时写过了//根据id查询餐菜品关系表数据List<SetmealDish> setmealDishes = setmealDishMapper.getBySetmealId(id);//封装返回结果SetmealVO setmealVO = new SetmealVO();BeanUtils.copyProperties(setmeal, setmealVO);setmealVO.setSetmealDishes(setmealDishes);return setmealVO;}/*** 修改套餐** 思路分析:套餐表修改直接使用update语句即可,对于这个套餐菜品关系表,*         套餐和菜品关系的修改比较复杂,因为它的情况有很多 有可能关系没有修改 有可能*         关系是追加的 也有可能关系是删除了,那么这个地方我们有没有一种比较*         简单的处理方式呢???*         可以先把你当前这个套餐菜品关系数据全都统一删掉,然后在按照你当前*         传过来的这个套餐菜品关系,重新再来插入一遍这个数据就可以了。** @param setmealDTO*/@Transactionalpublic void update(SetmealDTO setmealDTO) {//说明:SetmealDTO含有套餐菜品关系表数据,当前只是修改套餐的基本信息,所以直接传递SetmealDTO不合适,//     可以把SetmealDTO的数据拷贝到套餐的基本信息类Setmeal中更合适。Setmeal setmeal = new Setmeal();BeanUtils.copyProperties(setmealDTO, setmeal);//1、修改套餐表,执行updatesetmealMapper.update(setmeal);//获取生成的套餐id   通过sql中的useGeneratedKeys="true" keyProperty="id"获取插入后生成的主键值//套餐菜品关系表的setmealId页面不能传递,它是向套餐表插入数据之后生成的主键值,也就是套餐菜品关系表的逻辑外键setmealIdLong setmealId = setmealDTO.getId();//新增套餐时的sql获取主键值//2、删除套餐和菜品的关联关系,操作setmeal_dish表,执行deletesetmealDishMapper.deleteBySetmealId(setmealId); //删除套餐时已经实现了//获取页面传来的套餐和菜品关系表数据List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();//遍历关系表数据,为关系表中的每一条数据(每一个对象)的setmealId赋值,//   这个地方不需要像之前写新增菜品时多写个if判断,因为之前的口味数据是非必须的,//   这个地方要求套餐必须包含菜品是必须的,所以不需要if判断,不存在套餐不包含菜品得情况setmealDishes.forEach(setmealDish -> {setmealDish.setSetmealId(setmealId);});//3、重新插入套餐和菜品的关联关系,操作setmeal_dish表,执行insert//   动态sql批量插入setmealDishMapper.insertBatch(setmealDishes);//新增套餐时已经实现了}
4.2.4 SetmealMapper
    /*** 根据id查询套餐* @param id* @return*/@Select("select * from setmeal where id = #{id}")Setmeal getById(Long id);//修改套餐表,执行update@AutoFill(OperationType.UPDATE)void update(Setmeal setmeal);
4.2.5 SetmealMapper.xml
    <update id="update">update setmeal<set><if test="categoryId != null">category_id = #{categoryId},</if><if test="name != null">name = #{name},</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>
4.2.6 SetmealDishMapper
    /*** 根据套餐id查询套餐和菜品的关联关系* @param setmealId* @return*/@Select("select * from setmeal_dish where setmeal_id = #{setmealId}")List<SetmealDish> getBySetmealId(Long setmealId);/*** 根据套餐id删除套餐和菜品的关联关系* @param setmealId*/@Delete("delete from setmeal_dish where setmeal_id = #{setmealId}")void deleteBySetmealId(Long setmealId);/*** 批量保存套餐和菜品的关联关系* @param setmealDishes*/void insertBatch(List<SetmealDish> setmealDishes);
4.2.7 SetmealDishMapper
    <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>

4.3 功能测试

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

5. 起售停售套餐(业务逻辑)

5.1 需求分析和设计

产品原型:

在这里插入图片描述

业务规则:

  • 可以对状态为起售的套餐进行停售操作,可以对状态为停售的套餐进行起售操作
  • 起售的套餐可以展示在用户端,停售的套餐不能展示在用户端
  • 起售套餐时,如果套餐内包含停售的菜品,则不能起售

接口设计:

在这里插入图片描述

5.2 代码实现

5.2.1 SetmealController

在这里插入图片描述

/*** 套餐起售停售* @param status* @param id* @return
*/
@PostMapping("/status/{status}")
@ApiOperation("套餐起售停售")
public Result startOrStop(@PathVariable Integer status, Long id) {setmealService.startOrStop(status, id);return Result.success();
}
5.2.2 SetmealService
/*** 套餐起售、停售* @param status* @param id
*/
void startOrStop(Integer status, Long id);
5.2.3 SetmealServiceImpl
    /*** 套餐起售、停售* @param status* @param id*/@Overridepublic void startOrStop(Integer status, Long id) {//起售套餐时,判断套餐内是否有停售菜品,有停售菜品提示"套餐内包含未启售菜品,无法启售"if(status.equals(StatusConstant.ENABLE)){  //1  启用//select a.* from dish a left join setmeal_dish b on a.id = b.dish_id where b.setmeal_id = ?//左外连接查询,根据套餐id查询菜品以及对应的菜品套餐关系数据,a.*所以返回所有菜品数据List<Dish> dishList = dishMapper.getBySetmealId(id);if(dishList != null && dishList.size() > 0){//判断套餐中是否包含的有菜品,有才走if判断dishList.forEach(dish -> {//套餐中包含菜品,如果这个菜品的状态为禁用,则抛出异常if(StatusConstant.DISABLE.equals(dish.getStatus())){throw new SetmealEnableFailedException(MessageConstant.SETMEAL_ENABLE_FAILED);}});}}//执行流程: 如果是起售套餐,套餐内有停售菜品,则抛出异常 不能起售//         如果是起售套餐,套餐内没有停售菜品,if执行完后跳出继续向下执行,执行更新//         如果是停售套餐,不走上面的if,直接进行更新状态。Setmeal setmeal = Setmeal.builder().id(id).status(status).build();setmealMapper.update(setmeal);//修改套餐时写了通用的修改sql}
5.2.4 DishMapper
/*** 根据套餐id查询菜品* @param setmealId* @return
*/
@Select("select a.* from dish a left join setmeal_dish b on a.id = b.dish_id where b.setmeal_id = #{setmealId}")
List<Dish> getBySetmealId(Long setmealId);
5.2.5 SetmealMapper
    //修改套餐表,执行update@AutoFill(OperationType.UPDATE)void update(Setmeal setmeal);
5.2.6 SetmealMapper.xml
    <update id="update">update setmeal<set><if test="categoryId != null">category_id = #{categoryId},</if><if test="name != null">name = #{name},</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>

5.3 功能测试

在这里插入图片描述
在这里插入图片描述

相关文章:

苍穹外卖-day04:项目实战-套餐管理(新增套餐,分页查询套餐,删除套餐,修改套餐,起售停售套餐)业务类似于菜品模块

苍穹外卖-day04 课程内容 新增套餐套餐分页查询删除套餐修改套餐起售停售套餐 要求&#xff1a; 根据产品原型进行需求分析&#xff0c;分析出业务规则设计接口梳理表之间的关系&#xff08;分类表、菜品表、套餐表、口味表、套餐菜品关系表&#xff09;根据接口设计进行代…...

深入探索C与C++的混合编程

实现混合编程的技术细节 混合使用C和C可能由多种原因驱动。一方面&#xff0c;现有的大量优秀C语言库为特定任务提供了高效的解决方案&#xff0c;将这些库直接应用于C项目中可以节省大量的开发时间和成本。另一方面&#xff0c;C的高级特性如类、模板和异常处理等&#xff0c;…...

数组中的flat方法如何实现

数组的成员有时还是数组&#xff0c;Array.prototype.flat()用于将嵌套的数组“拉平”&#xff0c;变成一维的数组。该方法返回一个新数组&#xff0c;对原数据没有影响。 [1, 2, [3, 4]].flat() // [1, 2, 3, 4]那flat怎么来实现呢&#xff1f; 1、使用while循环 实现的代码…...

计算机考研|北航北理北邮怎么选?

北航985&#xff0c;北理985&#xff0c;北邮211 虽然北邮事211&#xff0c;但是北邮的计算机实力一点也不弱&#xff0c;学科评级&#xff0c;计算机是A 北航计算机评级也是A&#xff0c;北理的计算机评级是A- 所以&#xff0c;这三所学校在实力上来说&#xff0c;真的大差…...

面试算法-52-对称二叉树

题目 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true 解 class Solution {public boolean isSymmetric(TreeNode root) {return dfs(root, root);}public boolean dfs(Tr…...

独立维基和验收测试框架 Fitnesse 入门介绍

拓展阅读 junit5 系列教程 基于 junit5 实现 junitperf 源码分析 Auto generate mock data for java test.(便于 Java 测试自动生成对象信息) Junit performance rely on junit5 and jdk8.(java 性能测试框架。压测测试报告生成。) Fitnesse 完全集成的独立维基和验收测试…...

AI 初创公司趋势:Y Combinator 最新批次的见解

总部位于硅谷的著名创业加速器 Y Combinator (YC) 最近宣布了其 2023 年冬季队列&#xff0c;不出所料&#xff0c;约 31% 的初创公司&#xff08;269 家中有 80 家&#xff09;拥有自我报告的 AI 标签。在这篇文章中&#xff0c;我分析了这批 20-25 家初创公司&#xff0c;以了…...

tts语音合成原理

TTS&#xff08;Text-to-Speech&#xff0c;文本到语音&#xff09;语音合成技术是一种将文本数据转换为可听见的语音输出的技术。它允许计算机和其他电子设备读出文字信息&#xff0c;使得用户可以通过听的方式接收信息。TTS技术在无障碍服务、智能助手、语音导航、有声读物等…...

轮转数组题解

链接&#xff1a;189. 轮转数组 - 力扣&#xff08;LeetCode&#xff09; 这个题目很简单&#xff0c;因为说到了 k 是一个非负数&#xff0c;那么我们就可以 求模的时候就不用考虑的下标还会越界了&#xff0c;往右边 移动 其实就是当前下标 ik ,为了保证它能头尾相接并且不越…...

sqllab第二十四关通关笔记

知识点&#xff1a; 二次注入 先埋一个炸弹&#xff0c;然后通过其他路径引爆它 查看界面发现是一个登录框&#xff0c;尝试进行登录框的注入发现这里不存在注入点 那么就注册一个新的账户吧 通过点击注册&#xff0c;进入注册面板&#xff0c;注册一个新的账户 用户名为 re…...

web前端之多行文本擦除效果、文本逐个显示或展示、创建元素标签、querySelector、createElement、appendChild、requestAnimationFrame

MENU 版本一(requestAnimationFrame)版本二(setTimeout)版本三(css) 版本一(requestAnimationFrame) 前言 window.requestAnimationFrame()告诉浏览器——你希望执行一个动画&#xff0c;并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数…...

一文解读ISO26262安全标准:功能安全管理

一文解读ISO26262安全标准&#xff1a;功能安全管理 1 安全生命周期1.1 概念阶段1.2 产品开发阶段1.3 生产发布后续阶段 2 安全管理的角色和职责3 安全活动的裁剪4 安全活动的评审5 安全活动的评估6 交付物 下文的表中&#xff0c;一些方法的推荐等级说明&#xff1a; “”表示…...

【华为OD机试】找座位【C卷|100分】

【华为OD机试】-真题 !!点这里!! 【华为OD机试】真题考点分类 !!点这里 !! 题目描述 在一个大型体育场内举办了一场大型活动,由于疫情防控的需要, 要求每位观众的必须间隔至少一个空位才允许落座。 现在给出一排观众座位分布图,座位中存在已落座的观众,请计算出, 在不移…...

LarkXR上新了 | Apollo多终端与XR体验的优化创新

作为领先的数字平行世界产品技术提供方&#xff0c;「Paraverse平行云」一直致力于为企业和开发者提供企业级实时云渲染解决方案。其多终端接入产品LarkXR Apollo&#xff0c;基于底层Runtime技术&#xff0c;实现了在Windows、Linux、MacOS、Android、iOS等多种操作系统下&…...

车载电子电器架构 - 网络拓扑

车载电子电器架构 - 网络拓扑 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师 (Wechat:gongkenan2013)。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 本就是小人物,输了就是输了,不要在意别人怎么看自己。江湖一碗茶,喝完再挣扎,出门靠…...

2024蓝桥杯每日一题(DFS)

备战2024年蓝桥杯 -- 每日一题 Python大学A组 试题一&#xff1a;奶牛选美 试题二&#xff1a;树的重心 试题三&#xff1a;大臣的差旅费 试题四&#xff1a;扫雷 试题一&#xff1a;奶牛选美 【题目描述】 听说最近两斑点的奶牛最受欢迎&#xff0c;…...

Docker 笔记(五)--链接

这篇笔记记录了Docker 的Link。 官方文档&#xff1a; Legacy container links - Communication across links 目录 参考Legacy container linksConnect using network port mappingConnect with the linking systemThe importance of naming Communication across linksEnviro…...

如何处理Android悬浮弹窗双击返回事件?

目录 1 前言 1.1 准备知识 1.2 问题概述 2 解决方案 3 代码部分 3.1 动态更新窗口焦点 3.2 窗口监听返回事件 3.3 判断焦点是否在窗口内部 3.4 窗口监听焦点移入/移出 4 注意事项 4.1 窗口范围 4.2 空隙处的返回事件处理 1 前言 1.1 准备知识 1&#xff09;开发环…...

高可用篇_A Docker容器化技术_II Docker环境搭建和常见命令

原创作者&#xff1a;田超凡&#xff08;程序员田宝宝&#xff09; 版权所有&#xff0c;引用请注明原作者&#xff0c;严禁复制转载 Docker安装 Docker 要求 CentOS7 系统的内核版本在 3.10以上 &#xff0c;查看本页面的前提条件来验证你的CentOS 版本是否支持 Docker 。 …...

Vue.js+SpringBoot开发食品生产管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 加工厂管理模块2.2 客户管理模块2.3 食品管理模块2.4 生产销售订单管理模块2.5 系统管理模块2.6 其他管理模块 三、系统展示四、核心代码4.1 查询食品4.2 查询加工厂4.3 新增生产订单4.4 新增销售订单4.5 查询客户 五、…...

Python面试笔记

Python面试笔记 PythonQ. Python中可变数据类型与不可变数据类型&#xff0c;浅拷贝与深拷贝详解Q. 解释什么是lambda函数&#xff1f;它有什么好处&#xff1f;Q. 什么是装饰器&#xff1f;Q. 什么是Python的垃圾回收机制&#xff1f;Q. Python内置函数dir的用法&#xff1f;Q…...

springboot 查看和修改内置 tomcat 版本

解析Spring Boot父级依赖 去到项目的根pom文件中&#xff0c;找到parent依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>${springboot.version}…...

003——移植鸿蒙

目录 一、顶层Make分析 二、添加一个新的单板 2.1 Kconfig 2.2 Makefile 2.2.1 顶层Makefile 2.2.2 platform下的Makefile 2.2.3 platform下的bsp.mk文件 2.3 编译与调试 2.4 解决链接错误 三、内核启动流程的学习 3.1 韦东山老师总结的启动四步 3.2 启动文件分析…...

罗马数字转整数-力扣通过自己编译器编译

学会将力扣题目用自己自带的编译软件编译---纯自己想的本题解法 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如&#xff0c; 罗马数字 2 写做 II &#xff0c;即为两…...

深入解析JVM加载机制

一、背景 Java代码被编译器变成生成Class字节码&#xff0c;但字节码仅是一个特殊的二进制文件&#xff0c;无法直接使用。因此&#xff0c;都需要放到JVM系统中执行&#xff0c;将Class字节码文件放入到JVM的过程&#xff0c;简称类加载。 二、整体流程 三、阶段逻辑分析 3…...

python redis中blpop和lpop的区别

python redis中lpop()方法是获取并删除左边第一个对象。 def lpop(self,name: str,count: Optional[int] None,) -> Union[Awaitable[Union[str, List, None]], Union[str, List, None]]:"""Removes and returns the first elements of the list name.By de…...

第四百一十回

文章目录 1. 概念介绍2. 方法与细节2.1 获取方法2.2 使用细节 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何获取当前系统语言"相关的内容&#xff0c;本章回中将介绍如何获取时间戳.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在本章…...

程序员的README——编写可维护的代码(一)

用户行为不可预测&#xff0c;网络不可靠&#xff0c;事情总会出错。生产环境下的软件必须一直保持可用状态。 编写可维护的代码有助于你应对不可预见的情况&#xff0c;可维护的代码有内置的保护、诊断和控制。 切记通过安全和有弹性的编码实践进行防御式编程来保护你的系统&a…...

数据库管理-第160期 Oracle Vector DB AI-11(20240312)

数据库管理160期 2024-03-12 数据库管理-第160期 Oracle Vector DB & AI-11&#xff08;20240312&#xff09;1 向量的函数操作to_vector()将vector转换为标准值vector_norm()vector_dimension_count()vector_dimension_format() 2 将向量转换为字符串或CLOBvector_seriali…...

(C++进阶)boost库笔记

目录 1、boost::function 1.1 概述 1.2 boost包装器和C11包装器对比 1.2、代码示例 1、boost::function 1.1 概述 boost::function 是 Boost 库中提供的一个通用函数对象包装器&#xff0c;它可以存储指向任何可调用对象的指针&#xff0c;并且可以在任何时候通过 operat…...

网站改版活动/营销型网站建设运营

转载&#xff1a;python文件操作&#xff08;with关键字&#xff09; - wangshanglinju - 博客园 with关键字的使用 with&#xff1a;我们称之为上下文管理器&#xff0c;很多需要手动关闭的连接比如文件连接、socket连接、数据库连接等都能使用with关键字自动关闭连接。 wit…...

十大设计网站排名/灰色关键词排名优化

近日&#xff0c;墨天轮社区发布了《2022年中国数据库行业年度分析报告》,在公众号回复&#xff1a;下载 可以找到链接。以下是关于报告中的简要摘录&#xff0c;供参考。1. 国产数据库持续丰富&#xff1a;墨天轮中国数据库流行度排行榜于 2019 年 6 月推出&#xff0c;2022 年…...

网站名称和网址/拼多多关键词排名在哪里看

AbstractFactory模式用来解决这类问题&#xff1a;要创建一组相关或者相互依赖的对象。 AbstractFactory Pattern结构图 实现&#xff1a; 1 #ifndef _PRODUCT_H_ 2 #define _PRODUCT_H_3 class AbstractProductA 4 { 5 public: 6 virtual ~AbstractProductA();7 protected…...

深圳网站建设的客户在哪里/做一套二级域名网站怎么做

PHP1 1994年&#xff0c;一位名叫Rasmus lerdorf的兄台为了在网上展示自己的履历和网页流量的统计&#xff0c;用Perl开发了一套脚本&#xff0c;后来因与日俱增的需求无法得到满足&#xff0c;lerdorf便使用c语言进行了重写&#xff0c;重写后的程序支持数据库的访问&#xff…...

威海市环翠区建设局网站/网络促销方案

2019独角兽企业重金招聘Python工程师标准>>> 概述 Group by 既将数据分组后处理 一般结合sum、count等使用 Group By用法 SELECT column_name, aggregate_function(column_name) FROM table_name WHERE column_name operator value GROUP BY column_name 注意&#…...

网站建设经费放哪个经济科目/网站seo分析

学校使用的是Inode客户端认证上网的。而且还只能使用iNodeSetup3.60-6210版本进行连接&#xff0c;之前使用Ubuntu 32位版本&#xff0c;可以完美地安装并能够连接到网站。由于我的机子是64位的机子&#xff0c;所以使用wubi的方式安装了Ubuntu desktop 12.10 amd64版本。安装系…...