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

本文主要是介绍苍穹外卖-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:项目实战-套餐管理(新增套餐,分页查询套餐,删除套餐,修改套餐,起售停售套餐)业务类似于菜品模块的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/824223

相关文章

Python中模块graphviz使用入门

《Python中模块graphviz使用入门》graphviz是一个用于创建和操作图形的Python库,本文主要介绍了Python中模块graphviz使用入门,具有一定的参考价值,感兴趣的可以了解一... 目录1.安装2. 基本用法2.1 输出图像格式2.2 图像style设置2.3 属性2.4 子图和聚

gradle第三方Jar包依赖统一管理方式

《gradle第三方Jar包依赖统一管理方式》:本文主要介绍gradle第三方Jar包依赖统一管理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录背景实现1.顶层模块build.gradle添加依赖管理插件2.顶层模块build.gradle添加所有管理依赖包

基于Python打造一个智能单词管理神器

《基于Python打造一个智能单词管理神器》这篇文章主要为大家详细介绍了如何使用Python打造一个智能单词管理神器,从查询到导出的一站式解决,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 项目概述:为什么需要这个工具2. 环境搭建与快速入门2.1 环境要求2.2 首次运行配置3. 核心功能使用指

MyBatis模糊查询报错:ParserException: not supported.pos 问题解决

《MyBatis模糊查询报错:ParserException:notsupported.pos问题解决》本文主要介绍了MyBatis模糊查询报错:ParserException:notsuppo... 目录问题描述问题根源错误SQL解析逻辑深层原因分析三种解决方案方案一:使用CONCAT函数(推荐)方案二:

MySQL 中的 JSON 查询案例详解

《MySQL中的JSON查询案例详解》:本文主要介绍MySQL的JSON查询的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录mysql 的 jsON 路径格式基本结构路径组件详解特殊语法元素实际示例简单路径复杂路径简写操作符注意MySQL 的 J

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

Python的time模块一些常用功能(各种与时间相关的函数)

《Python的time模块一些常用功能(各种与时间相关的函数)》Python的time模块提供了各种与时间相关的函数,包括获取当前时间、处理时间间隔、执行时间测量等,:本文主要介绍Python的... 目录1. 获取当前时间2. 时间格式化3. 延时执行4. 时间戳运算5. 计算代码执行时间6. 转换为指

SpringBoot项目中报错The field screenShot exceeds its maximum permitted size of 1048576 bytes.的问题及解决

《SpringBoot项目中报错ThefieldscreenShotexceedsitsmaximumpermittedsizeof1048576bytes.的问题及解决》这篇文章... 目录项目场景问题描述原因分析解决方案总结项目场景javascript提示:项目相关背景:项目场景:基于Spring

解决Maven项目idea找不到本地仓库jar包问题以及使用mvn install:install-file

《解决Maven项目idea找不到本地仓库jar包问题以及使用mvninstall:install-file》:本文主要介绍解决Maven项目idea找不到本地仓库jar包问题以及使用mvnin... 目录Maven项目idea找不到本地仓库jar包以及使用mvn install:install-file基

Python正则表达式语法及re模块中的常用函数详解

《Python正则表达式语法及re模块中的常用函数详解》这篇文章主要给大家介绍了关于Python正则表达式语法及re模块中常用函数的相关资料,正则表达式是一种强大的字符串处理工具,可以用于匹配、切分、... 目录概念、作用和步骤语法re模块中的常用函数总结 概念、作用和步骤概念: 本身也是一个字符串,其中