【java】【项目实战】[外卖四]分类管理业务开发
前言:公共字段自动填充实现,删除业务逻辑实现
一、公共字段自动填充
1.1 问题分析
1.2 代码实现
1.2.1 修改实体类Employee
package com.runa.reggie.entity;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;@Data
public class Employee implements Serializable {private static final long serialVersionUID = 1L;private Long id;private String username;private String name;private String password;private String phone;private String sex;private String idNumber;private Integer status;@TableField(fill = FieldFill.INSERT) //插入时更新字段private LocalDateTime createTime;@TableField(fill = FieldFill.INSERT_UPDATE) //插入和更新时更新字段private LocalDateTime updateTime;@TableField(fill = FieldFill.INSERT)private Long createUser;@TableField(fill = FieldFill.INSERT_UPDATE)private Long updateUser;}
1.2.2 MyMetaObjectHandler
package com.runa.reggie.common;import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;import java.time.LocalDateTime;@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {/*** 插入操作,自动填充* @param metaObject*/@Overridepublic void insertFill(MetaObject metaObject) {log.info("公共字段自动填充[insert]...");log.info(metaObject.toString());metaObject.setValue("createTime", LocalDateTime.now());metaObject.setValue("updateTime", LocalDateTime.now());metaObject.setValue("createUser", new Long(1) );metaObject.setValue("updateUser", new Long(1));}/*** 更新操作,自动填充* @param metaObject*/@Overridepublic void updateFill(MetaObject metaObject) {log.info("公共字段自动填充[update]...");log.info(metaObject.toString());metaObject.setValue("updateTime", LocalDateTime.now());metaObject.setValue("updateUser", new Long(1));}
}
1.2.3 EmployeeController将新增、修改方法当中的公共字段赋值注释掉
package com.runa.reggie.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.runa.reggie.common.R;
import com.runa.reggie.entity.Employee;
import com.runa.reggie.service.impl.EmployeeServcie;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;@Slf4j
@RestController
@RequestMapping("/employee")
public class EmployeeController {@Autowiredprivate EmployeeServcie employeeServcie;/*** 员工登录* @param request* @param employee* @return*///HttpServletRequest request 是为了将登录对象塞入session@PostMapping("/login")public R<Employee> login(HttpServletRequest request, @RequestBody Employee employee){//1、将页面提交的密码password进行md5加密处理String password = employee.getPassword();password = DigestUtils.md5DigestAsHex(password.getBytes());//2、根据页面提交的用户名username查询数据库LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(Employee::getUsername,employee.getUsername());Employee emp = employeeServcie.getOne(queryWrapper);//3、如果没有查询到则返回登录失败结果if(emp == null){return R.error("登录失败");}//4、密码比对,如果不一致则返回登录失败结果if(!emp.getPassword().equals(password)){return R.error("登录失败");}//5、查看员工状态,如果为已禁用状态,则返回员工已禁用结果if(emp.getStatus() == 0){return R.error("账号已禁用");}//6、登录成功,将员工id存入Session并返回登录成功结果request.getSession().setAttribute("employee",emp.getId());return R.success(emp);}@PostMapping("/logout")public R<String> logout(HttpServletRequest request){// 清理Session 中保存的当前员工的idrequest.getSession().removeAttribute("emplyee");return R.success("退出成功!");}@PostMappingpublic R<String> save(HttpServletRequest request, @RequestBody Employee employee){log.info("新增员工,员工信息为:{}",employee.toString());// 设置初始密码123456,需要进行md5加密处理employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));// employee.setCreateTime(LocalDateTime.now());
// employee.setUpdateTime(LocalDateTime.now());
// //获得当前用户的id
// Long empId = (Long) request.getSession().getAttribute("employee");
// employee.setCreateUser(empId);
// employee.setUpdateUser(empId);employeeServcie.save(employee);return R.success("新增员工成功");}/*** 员工信息分页查询* @param page* @param pageSize* @param name* @return*/@GetMapping("/page")public R<Page> page(int page, int pageSize,String name){log.info("page= {}, pageSize= {}, name = {}",page, pageSize, name);// 构造分页构造器Page pageInfo = new Page(page, pageSize);//构造条件构造器LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper();// 添加过滤条件//当传入的name不为空的时候才会添加条件queryWrapper.like(StringUtils.isNotEmpty(name),Employee::getName,name);// 添加排序条件queryWrapper.orderByDesc(Employee::getUpdateTime);//执行查询employeeServcie.page(pageInfo, queryWrapper);return R.success(pageInfo);}/*** 根据ID修改员工信息* @param employee* @return*/@PutMappingpublic R<String> update(HttpServletRequest request, @RequestBody Employee employee){log.info(employee.toString());// Long empId = (Long) request.getSession().getAttribute("employee");
// employee.setUpdateUser(empId);
// employee.setUpdateTime(LocalDateTime.now());employeeServcie.updateById(employee);return R.success("员工信息修改成功");}@GetMapping("/{id}")public R<Employee> GetById(@PathVariable Long id){log.info("根据id查询员工:{}",id);Employee employee = employeeServcie.getById(id);if(employee != null){return R.success(employee);}return R.error("没有查询到对应员工信息");}}
1.3 功能测试
1.4 功能完善
1.4.1 BaseContext
package com.runa.reggie.common;public class BaseContext {private static ThreadLocal<Long> threadLocal = new ThreadLocal<>();public static void setCurrentId(Long id){threadLocal.set(id);}public static Long getCurrent(){return threadLocal.get();}
}
1.4.2 LoginCheckFilter优化将用户id塞进线程
package com.runa.reggie.filter;import com.alibaba.fastjson.JSON;
import com.runa.reggie.common.BaseContext;
import com.runa.reggie.common.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@Slf4j
@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*")
public class LoginCheckFilter implements Filter {// 路径匹配器public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;// 1 获取本次请求的URI// request.getRequestURL()返回的是全路径。// request.getRequestURI()返回的是除去协议,域名(IP+端口号)之后的路由部分。String requestURI = request.getRequestURI();log.info("拦截到请求:【{}】",requestURI);// 定义一些不需要处理的路径String[] urls = new String[]{"/employee/login", // 登录不需要"/employee/logout","/backend/**","/front/**"};// 2 判断本次请求是否需要处理boolean check = check(urls, requestURI);// 3 如果不需要处理,则直接放行if(check){log.info("本次请求【 {} 】 不需要处理",requestURI);filterChain.doFilter(request,response);return;}// 4 判断登录状态,如果已登录,则直接放行if(request.getSession().getAttribute("employee") != null){log.info("用户已登录,请求url为:【{}】, 用户id为:【 {} 】 ",requestURI,request.getSession().getAttribute("employee"));// 获取ID 塞进线程Long empId = (Long) request.getSession().getAttribute("employee");BaseContext.setCurrentId(empId);filterChain.doFilter(request,response);return;}log.info("用户未登录");// 5 如果未登录则返回未登录结果,通过输出流方式向客户端页面响应数据response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));return;}/*** 路径匹配,检查本次请求是否需要放行* @param urls* @param requestURI* @return*/public boolean check(String[] urls, String requestURI){for (String url : urls) {boolean match = PATH_MATCHER.match(url, requestURI);if(match){return true;}}// 循环都匹配不上就返回falsereturn false;}
}
1.4.3 MyMetaObjectHandler
package com.runa.reggie.common;import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;import java.time.LocalDateTime;@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {/*** 插入操作,自动填充* @param metaObject*/@Overridepublic void insertFill(MetaObject metaObject) {log.info("公共字段自动填充[insert]...");log.info(metaObject.toString());metaObject.setValue("createTime", LocalDateTime.now());metaObject.setValue("updateTime", LocalDateTime.now());metaObject.setValue("createUser", BaseContext.getCurrent());metaObject.setValue("updateUser", BaseContext.getCurrent());}/*** 更新操作,自动填充* @param metaObject*/@Overridepublic void updateFill(MetaObject metaObject) {log.info("公共字段自动填充[update]...");log.info(metaObject.toString());metaObject.setValue("updateTime", LocalDateTime.now());metaObject.setValue("updateUser", BaseContext.getCurrent());}
}
二、新增分类
2.1 需求分析
2.2 数据模型
2.3 代码实现
2.3.1 实体类Category
package com.runa.reggie.entity;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.time.LocalDateTime;/*** 分类*/
@Data
public class Category implements Serializable {private static final long serialVersionUID = 1L;private Long id;//类型 1 菜品分类 2 套餐分类private Integer type;//分类名称private String name;//顺序private Integer sort;//创建时间@TableField(fill = FieldFill.INSERT)private LocalDateTime createTime;//更新时间@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime updateTime;//创建人@TableField(fill = FieldFill.INSERT)private Long createUser;//修改人@TableField(fill = FieldFill.INSERT_UPDATE)private Long updateUser;//是否删除private Integer isDeleted;}
2.3.2 CategoryMapper
package com.runa.reggie.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.runa.reggie.entity.Category;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface CategoryMapper extends BaseMapper<Category> {
}
2.3.3 CategoryService
package com.runa.reggie.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.runa.reggie.entity.Category;public interface CategoryService extends IService<Category> {
}
2.3.4 CategoryServiceImpl
package com.runa.reggie.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.runa.reggie.entity.Category;
import com.runa.reggie.mapper.CategoryMapper;
import com.runa.reggie.service.CategoryService;
import org.springframework.stereotype.Service;@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {
}
2.3.5 CategoryController
package com.runa.reggie.controller;import com.runa.reggie.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** 分类管理*/
@Slf4j
@RestController
@RequestMapping("/category")
public class CategoryController {@Autowiredprivate CategoryService categoryService;
}
2.3.6 CategoryController新增save方法
package com.runa.reggie.controller;import com.runa.reggie.common.R;
import com.runa.reggie.entity.Category;
import com.runa.reggie.service.CategoryService;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** 分类管理*/
@Slf4j
@RestController
@RequestMapping("/category")
public class CategoryController {@Autowiredprivate CategoryService categoryService;/*** 新增分类* @param category* @return*/@PostMappingpublic R<String> save(@RequestBody Category category){log.info("新增分类:{}", category);categoryService.save(category);return R.success("新增分类成功");}
}
2.4 功能测试
三、分类信息分页查询
3.1 需求分析
3.2 代码实现
3.2.1 CategoryController
package com.runa.reggie.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.runa.reggie.common.R;
import com.runa.reggie.entity.Category;
import com.runa.reggie.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;/*** 分类管理*/
@Slf4j
@RestController
@RequestMapping("/category")
public class CategoryController {@Autowiredprivate CategoryService categoryService;/*** 新增分类* @param category* @return*/@PostMappingpublic R<String> save(@RequestBody Category category){log.info("新增分类:{}", category);categoryService.save(category);return R.success("新增分类成功");}/*** 分页查询* @param page* @param pageSize* @return*/@GetMapping("/page")public R<Page> page(int page, int pageSize){log.info("page= {}, pageSize= {}, name = {}",page, pageSize);//分页构造器Page pageInfo = new Page(page, pageSize);// 条件构造器LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();//添加排序条件,根据sort排序queryWrapper.orderByAsc(Category::getSort);//进行分页查询categoryService.page(pageInfo, queryWrapper);return R.success(pageInfo);}
}
3.2.1 Category注释是否删除字段
package com.runa.reggie.entity;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.time.LocalDateTime;/*** 分类*/
@Data
public class Category implements Serializable {private static final long serialVersionUID = 1L;private Long id;//类型 1 菜品分类 2 套餐分类private Integer type;//分类名称private String name;//顺序private Integer sort;//创建时间@TableField(fill = FieldFill.INSERT)private LocalDateTime createTime;//更新时间@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime updateTime;//创建人@TableField(fill = FieldFill.INSERT)private Long createUser;//修改人@TableField(fill = FieldFill.INSERT_UPDATE)private Long updateUser;//是否删除
// private Integer isDeleted;}
3.3 功能测试
四、删除分类
4.1 需求分析
4.2 代码实现
4.2.1 CategoryController
注意传参是ids
package com.runa.reggie.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.runa.reggie.common.R;
import com.runa.reggie.entity.Category;
import com.runa.reggie.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;/*** 分类管理*/
@Slf4j
@RestController
@RequestMapping("/category")
public class CategoryController {@Autowiredprivate CategoryService categoryService;/*** 新增分类* @param category* @return*/@PostMappingpublic R<String> save(@RequestBody Category category){log.info("新增分类:{}", category);categoryService.save(category);return R.success("新增分类成功");}/*** 分页查询* @param page* @param pageSize* @return*/@GetMapping("/page")public R<Page> page(int page, int pageSize){log.info("page= {}, pageSize= {}, name = {}",page, pageSize);//分页构造器Page pageInfo = new Page(page, pageSize);// 条件构造器LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();//添加排序条件,根据sort排序queryWrapper.orderByAsc(Category::getSort);//进行分页查询categoryService.page(pageInfo, queryWrapper);return R.success(pageInfo);}/*** 根据id删除分类* @param ids* @return*/@DeleteMappingpublic R<String> delete(Long ids){log.info("根据ID删除分类:{}",ids);categoryService.removeById(ids);return R.success("分类信息删除成功");}
}
4.3 功能测试
4.4 功能完善
4.4.1 菜品实体类Dish
package com.runa.reggie.entity;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;/**菜品*/
@Data
public class Dish implements Serializable {private static final long serialVersionUID = 1L;private Long id;//菜品名称private String name;//菜品分类idprivate Long categoryId;//菜品价格private BigDecimal price;//商品码private String code;//图片private String image;//描述信息private String description;//0 停售 1 起售private Integer status;//顺序private Integer sort;@TableField(fill = FieldFill.INSERT)private LocalDateTime createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime updateTime;@TableField(fill = FieldFill.INSERT)private Long createUser;@TableField(fill = FieldFill.INSERT_UPDATE)private Long updateUser;//是否删除private Integer isDeleted;}
4.4.2 套餐实体类Setmeal
package com.runa.reggie.entity;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;/*** 套餐*/
@Data
public class Setmeal implements Serializable {private static final long serialVersionUID = 1L;private Long id;//分类idprivate Long categoryId;//套餐名称private String name;//套餐价格private BigDecimal price;//状态 0:停用 1:启用private Integer status;//编码private String code;//描述信息private String description;//图片private String image;@TableField(fill = FieldFill.INSERT)private LocalDateTime createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime updateTime;@TableField(fill = FieldFill.INSERT)private Long createUser;@TableField(fill = FieldFill.INSERT_UPDATE)private Long updateUser;//是否删除private Integer isDeleted;
}
4.4.3 DishMapper
package com.runa.reggie.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.runa.reggie.entity.Dish;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface DishMapper extends BaseMapper<Dish> {
}
4.4.4 SetmealMapper
package com.runa.reggie.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.runa.reggie.entity.Setmeal;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface SetmealMapper extends BaseMapper<Setmeal> {
}
4.4.5 DishService
package com.runa.reggie.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.runa.reggie.entity.Dish;public interface DishService extends IService<Dish> {
}
4.4.6 SetmealService
package com.runa.reggie.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.runa.reggie.entity.Setmeal;public interface SetmealService extends IService<Setmeal> {
}
4.4.7 DishServiceImpl
package com.runa.reggie.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.runa.reggie.entity.Dish;
import com.runa.reggie.mapper.DishMapper;
import com.runa.reggie.service.DishService;
import org.springframework.stereotype.Service;@Service
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {
}
4.4.8 SetmealServiceImpl
package com.runa.reggie.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.runa.reggie.entity.Setmeal;
import com.runa.reggie.mapper.SetmealMapper;
import com.runa.reggie.service.SetmealService;
import org.springframework.stereotype.Service;@Service
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper, Setmeal> implements SetmealService {
}
4.4.9 修改CategoryService
package com.runa.reggie.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.runa.reggie.entity.Category;public interface CategoryService extends IService<Category> {public void remove(Long ids);
}
4.4.10 自定义业务异常类CustomException
package com.runa.reggie.common;/*** 自定义业务异常类*/
public class CustomException extends RuntimeException {public CustomException(String message){super(message);}
}
4.4.11 CategoryServiceImpl
package com.runa.reggie.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.runa.reggie.common.CustomException;
import com.runa.reggie.entity.Category;
import com.runa.reggie.entity.Dish;
import com.runa.reggie.entity.Setmeal;
import com.runa.reggie.mapper.CategoryMapper;
import com.runa.reggie.service.CategoryService;
import com.runa.reggie.service.DishService;
import com.runa.reggie.service.SetmealService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {@Autowiredprivate DishService dishService;@Autowiredprivate SetmealService setmealService;@Overridepublic void remove(Long ids) {LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();//添加查询条件,根据分类id查询dishLambdaQueryWrapper.eq(Dish::getCategoryId,ids);int count1 = dishService.count(dishLambdaQueryWrapper);// 查询分类是否关联了菜品,如果关联了,抛出一个业务异常if(count1 > 0){// 关联了 抛出异常throw new CustomException("当前分类下关联了菜品,不能删除");}LambdaQueryWrapper<Setmeal> setmealLambdaQueryWrapper = new LambdaQueryWrapper<>();//添加查询条件,根据分类id查询setmealLambdaQueryWrapper.eq(Setmeal::getCategoryId,ids);int count2 = setmealService.count(setmealLambdaQueryWrapper);// 查询分类是否关联了套餐,如果关联了,抛出一个业务异常if(count2 > 0){// 关联了 抛出异常throw new CustomException("当前分类下关联了套餐,不能删除");}//执行删除super.removeById(ids);}
}
4.4.12 GlobaExceptionHandler
package com.runa.reggie.common;import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;import java.sql.SQLIntegrityConstraintViolationException;/*** 全局异常处理*/
@ControllerAdvice(annotations = {RestController.class, Controller.class}) // 加了RestController Controller 注解的
@ResponseBody
@Slf4j
public class GlobaExceptionHandler {/*** 异常处理方法* @return*/@ExceptionHandler(SQLIntegrityConstraintViolationException.class)public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex){String msg = ex.getMessage();log.error(msg);if(msg.contains("Duplicate entry")){String[] split = msg.split(" "); //空分割String resultMsg = split[2] + " 已存在 ";return R.error(resultMsg);}return R.error("未知错误!");}/*** 异常处理方法(处理自定义的)* @return*/@ExceptionHandler(CustomException.class)public R<String> exceptionHandler(CustomException ex){String msg = ex.getMessage();log.error(msg);return R.error(msg);}}
4.4.13 CategoryController
package com.runa.reggie.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.runa.reggie.common.R;
import com.runa.reggie.entity.Category;
import com.runa.reggie.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;/*** 分类管理*/
@Slf4j
@RestController
@RequestMapping("/category")
public class CategoryController {@Autowiredprivate CategoryService categoryService;/*** 新增分类* @param category* @return*/@PostMappingpublic R<String> save(@RequestBody Category category){log.info("新增分类:{}", category);categoryService.save(category);return R.success("新增分类成功");}/*** 分页查询* @param page* @param pageSize* @return*/@GetMapping("/page")public R<Page> page(int page, int pageSize){log.info("page= {}, pageSize= {}, name = {}",page, pageSize);//分页构造器Page pageInfo = new Page(page, pageSize);// 条件构造器LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();//添加排序条件,根据sort排序queryWrapper.orderByAsc(Category::getSort);//进行分页查询categoryService.page(pageInfo, queryWrapper);return R.success(pageInfo);}/*** 根据id删除分类* @param ids* @return*/@DeleteMappingpublic R<String> delete(Long ids){log.info("根据ID删除分类:{}",ids);
// categoryService.removeById(ids);categoryService.remove(ids);return R.success("分类信息删除成功");}
}
五、修改分类
5.1 需求分析
5.2 代码实现
5.2.1 CategoryController
package com.runa.reggie.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.runa.reggie.common.R;
import com.runa.reggie.entity.Category;
import com.runa.reggie.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;/*** 分类管理*/
@Slf4j
@RestController
@RequestMapping("/category")
public class CategoryController {@Autowiredprivate CategoryService categoryService;/*** 新增分类* @param category* @return*/@PostMappingpublic R<String> save(@RequestBody Category category){log.info("新增分类:{}", category);categoryService.save(category);return R.success("新增分类成功");}/*** 分页查询* @param page* @param pageSize* @return*/@GetMapping("/page")public R<Page> page(int page, int pageSize){log.info("page= {}, pageSize= {}, name = {}",page, pageSize);//分页构造器Page pageInfo = new Page(page, pageSize);// 条件构造器LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();//添加排序条件,根据sort排序queryWrapper.orderByAsc(Category::getSort);//进行分页查询categoryService.page(pageInfo, queryWrapper);return R.success(pageInfo);}/*** 根据id删除分类* @param ids* @return*/@DeleteMappingpublic R<String> delete(Long ids){log.info("根据ID删除分类:{}",ids);
// categoryService.removeById(ids);categoryService.remove(ids);return R.success("分类信息删除成功");}@PutMappingpublic R<String> update(@RequestBody Category category){log.info("根据id更新分类信息:{}",category);categoryService.updateById(category);return R.success("修改分类信息成功");}
}
5.3 功能测试
相关文章:
【java】【项目实战】[外卖四]分类管理业务开发
前言:公共字段自动填充实现,删除业务逻辑实现 一、公共字段自动填充 1.1 问题分析 1.2 代码实现 1.2.1 修改实体类Employee package com.runa.reggie.entity;import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.…...
【Go 基础篇】Go语言包详解:模块化开发与代码复用
介绍 在Go语言中,包(Package) 是一种用于组织代码的机制,用于将相关的函数、类型和变量等组织在一起,以便于模块化开发和代码复用。包的使用能够使程序结构更加清晰、可维护性更高,同时也是Go语言强调的一…...
【业务功能篇82】微服务SpringCloud-ElasticSearch-Kibanan-docke安装-进阶实战
四、ElasticSearch进阶 https://www.elastic.co/guide/en/elasticsearch/reference/7.4/getting-started-search.html 1.ES中的检索方式 在ElasticSearch中支持两种检索方式 通过使用REST request URL 发送检索参数(uri检索参数)通过使用 REST request body 来发送检索参数…...
【工具】XML和JSON互相转换
1、JSON解析为XML function parseJSONToXML(json) {let xmlDoc document.implementation.createDocument(null, );function parseValue(value, parentElement) {if (Array.isArray(value)) {for (let item of value) {let arrayElement xmlDoc.createElement(parentElement.…...
前端面试:【浏览器与渲染引擎】Web APIs - DOM、XHR、Fetch、Canvas
嗨,亲爱的读者!当我们在浏览器中浏览网页时,我们常常会与各种Web API打交道。这些API允许我们与网页内容、服务器资源和图形进行交互。本文将深入探讨一些常见的Web API,包括DOM、XHR、Fetch和Canvas,以帮助你了解它们…...
编码基础一:侵入式链表
一、简介概述 1、普通链表数据结构 每个节点的next指针指向下一个节点的首地址。这样会有如下的限制: 一条链表上的所有节点的数据类型需要完全一致。对某条链表的操作如插入,删除等只能对这种类型的链表进行操作,如果链表的类型换了&#…...
深圳IT行业供需:蓬勃发展的科技中心
深圳作为中国的科技中心之一,IT行业在这座城市蓬勃发展。本文将探讨深圳IT行业的供需状况,包括就业机会、技能需求以及行业前景展望。 近年来,深圳IT行业迅速发展,成为全球科技创新的重要枢纽之一。随着大量的科技企业和初创公司在…...
LeetCode 面试题 02.01. 移除重复节点
文章目录 一、题目二、C# 题解 一、题目 编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。 点击此处跳转题目。 示例1: 输入:[1, 2, 3, 3, 2, 1] 输出:[1, 2, 3] 示例2: 输入:[1, 1, 1, 1, 2] 输出:[1, …...
【Java8特性】——Stream API
一、概述 <1> 是什么 是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。 Stream 不会存储数据Stream 不会改变数据源,相反,会返回一个持有结果的新Stream。Stream 操作是延迟执行的,这意…...
grep命令的用法
文章目录 前言一、使用说明二、应用举例 前言 grep 命令用于查找文件里符合条件的字符串。 一、使用说明 -r: 如果需要搜索目录中的文件内容, 需要进行递归操作, 必须指定该参数 -i: 对应要搜索的关键字, 忽略字符大小写的差别 -n: 在显示符合样式的那一行之前,标…...
【无标题】jenkins消息模板(飞书)
这里写目录标题 Jenkins 安装的插件 发送消息到飞书预览 1 (单Job)预览 2 (多Job,概览) Jenkins 安装的插件 插件名称作用Rebuilder Rebuilder。 官方地址:https://plugins.jenkins.io/rebuild 安装方式&a…...
2023年国赛 高教社杯数学建模思路 - 案例:随机森林
文章目录 1 什么是随机森林?2 随机深林构造流程3 随机森林的优缺点3.1 优点3.2 缺点 4 随机深林算法实现 建模资料 ## 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 什么是随机森林ÿ…...
element Collapse 折叠面板 绑定事件
1. 点击面板触发事件 change <el-collapse accordion v-model"activeNames" change"handleChange"><el-collapse-item title"一致性 Consistency"><div>与现实生活一致:与现实生活的流程、逻辑保持一致,…...
CSS :mix-blend-mode、aspect-ratio
mix-blend-mode 元素的内容应该与元素的直系父元素的内容和元素的背景如何混合。 mix-blend-mode: normal; // 正常mix-blend-mode: multiply; // 正片叠底mix-blend-mode: screen; // 滤色mix-blend-mode: overlay; // 叠加mix-blend-mode: darken; // 变暗mix-blend-mode: …...
Module not found: Error: Can‘t resolve ‘less-loader‘解决办法
前言: 主要是在自我提升方面,感觉自己做后端还是需要继续努力,争取炮筒前后端,作为一个全栈软阿金开发人员,所以还是需要努力下,找个方面,目前是计划学会Vue,这样后端有java和pytho…...
量化QAT QLoRA GPTQ
模型量化的思路可以分为PTQ(Post-Training Quantization,训练后量化)和QAT(Quantization Aware Training,在量化过程中进行梯度反传更新权重,例如QLoRA),GPTQ是一种PTQ的思路。 QAT…...
CentOS下查看 ssd 寿命
SSD写入量达到设计极限,颗粒擦写寿命耗尽后会导致磁盘写入速度非常缓慢,读取正常。 使用smartctl及raid卡管理软件查看硬盘smart信息可以发现Media_Wearout_Indicator值降为1,表明寿命完全耗尽。 涉及范围 所有SSD处理方案 查看SSD smart信…...
Node基础--npm相关内容
下面,我们一起来看看Node中的至关重要的一个知识点-----npm 1.npm概述 npm(Node Package Manager),CommonJS包规范是理论,npm是其中一种实践。 对于Node而言,NPM帮助其完成了第三方模块的发布、安装和依赖等。借助npm,Node与第三方模块之间形成了很好的一个 生态系统。(类…...
Python图片爬虫工具
不废话了,直接上代码: import re import os import requests import tqdmheader{User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36}def getImg(url,idx,path):imgre…...
制造执行系统(MES)在汽车行业中的应用
汽车行业在不断发展中仍然面临一些挑战和痛点。以下是一些当前汽车行业可能面临的问题: 1.电动化和可持续性转型:汽车行业正逐渐向电动化和可持续性转型,但这需要投入大量资金和资源,包括电池技术、充电基础设施等,同时…...
Spring与Mybatis集成且Aop整合
目录 一、集成 1.1 集成的概述 1.2 集成的优点 1.3 代码示例 二、整合 2.1 整合概述 2.2 整合进行分页 一、集成 1.1 集成的概述 集成是指将不同的组件、部分或系统组合在一起,以形成一个整体功能完整的解决方案。它是通过连接、交互和协调组件之间的关系来实…...
【nonebot-plugin-mystool】快速安装使用nonebot-plugin-mystool
快速安装使用nonebot-plugin-mystool,以qq为主 前期准备:注册一个QQ号,python3.9以上的版本安装,go-cqhttp下载 用管理员模式打开powershell,并输入以下命令 #先排查是否有安装过的nonebot,若有则删除 pip uninstal…...
js实现数据关联查找更新。数据求和验证
为了实现这个功能我们和后端定义了数据结构 data:{id:‘’,formInfo:,formInfo2:,formInfo3:,formInfo4:, ......deailData:[ // 明细数据 // saleData 查询带出的对应明细序列号数据{ id:, ocopyId:, copyId:, odoId:, ......, saleData:[ { id:, oc…...
区块链上地址与银行账户有什么区别?
在区块链世界中,除了交易还有另一个基础要素:地址。在日前推出的Onchain AML合规技术方案,也有一个与区块链地址密切相关的概念:KYA(Know Your Address,了解你的地址)。 那问题来了,区块链地址究竟有什么用…...
CF 148 D Bag of mice(概率dp求概率)
CF 148 D. Bag of mice(概率dp求概率) Problem - 148D - Codeforces 大意:袋子里有 w 只白鼠和 b 只黑鼠 ,A和B轮流从袋子里抓,谁先抓到白色谁就赢。A每次随机抓一只,B每次随机抓完一只之后会有另一只随机老鼠跑出来。如果两个人…...
引入本地 jar 包教程
将本地 jar 包,放到 resource 目录下,在 pom.xml 文件中加入如下依赖: <dependency><groupId>com.hk</groupId><artifactId>examples</artifactId><version>1.0</version><scope>system<…...
优维产品最佳实践第5期:什么是持续集成?
谈到到DevOps,持续交付流水线是绕不开的一个话题,相对于其他实践,通过流水线来实现快速高质量的交付价值是相对能快速见效的,特别对于开发测试人员,能够获得实实在在的收益。 本期EasyOps产品使用最佳实践,…...
空时自适应处理用于机载雷达——元素空间空时自适应处理(Matla代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
聚观早报 | 青瓷游戏上半年营收3.34亿元;如祺出行冲击IPO
【聚观365】8月26日消息 青瓷游戏上半年营收3.34亿元 如祺出行冲击IPO 索尼互动娱乐将收购Audeze 昆仑万维上半年净利润3.6亿元 T-Mobile计划在未来五周内裁员5000人 青瓷游戏上半年营收3.34亿元 青瓷游戏发布截至2023年6月30日止的中期业绩,财报显示…...
硅谷的魔法:如何塑造了全球技术的未来
硅谷的创新文化简介 硅谷,位于美国加利福尼亚州的圣克拉拉谷,已经从一个半导体产业的中心发展成为全球技术创新的代名词。这里集结了全球最顶尖的技术公司、创业者和投资者,共同创造了一个技术创新的奇迹。 起源与发展 硅谷的起源与斯坦福大…...
(三)行为模式:4、迭代器模式(Iterator Pattern)(C++示例)
目录 1、迭代器模式(Iterator Pattern)含义 2、迭代器模式的UML图学习 3、迭代器模式的应用场景 4、迭代器模式的优缺点 (1)优点 (2)缺点 5、C实现迭代器模式的实例 1、迭代器模式(Itera…...
React Antd form.getFieldsValue() 和 form.getFieldsValue(true) 有区别吗?
背景 突然发现 antd 的 getFieldsValue()是可以传一个 true 参数的,如题,React Antd form.getFieldsValue() 和 form.getFieldsValue(true) 有区别吗? 验证 确实不一样 结论 getFieldsValue 提供了多种重载方法: getFieldsValue(name…...
浅谈Java中的观察者模式
观察者模式是软件开发中常用的一种设计模式,它通过定义一对多的依赖关系,使得一个对象(主题)的状态变化可以通知多个其他对象(观察者)。 这种模式的优点是解耦和增加扩展性,用于实现对象之间的…...
C++:命名空间,缺省参数,函数重载,引用,内联函数
个人主页 : 个人主页 个人专栏 : 《数据结构》 《C语言》《C》 文章目录 前言一、命名空间命名空间的定义命名空间的使用 二、缺省参数缺省参数概念缺省参数分类 三、函数重载函数重载的概念 四、引用引用的概念引用特性引用的使用场景引用与指针的区别 …...
2.Vue报错Cannot read properties of undefined (reading ‘then‘)
1.出现报错 Cannot read properties of undefined (reading ‘then’), 代码为 uploadFile(e.target.files[0]).then((res) > {alert(JSON.stringify(res));});2.原因 是因为uploadFile方法没有返回值,于是我又检查了一遍代码,发现我的r…...
【LeetCode 】数组简介
集合列表和数组 本文中介绍的概念为适用于所有编程语言的抽象理论,具体实现会由编程语言的不同而稍有差别。 具体介绍数组之前,我们先来了解一下集合、列表和数组的概念之间的差别。 集合 集合一般被定义为:由一个或多个确定的元素所构成的…...
一文解析block io生命历程
作为存储业务的一个重要组成部分,block IO是非易失存储的唯一路径,它的生命历程每个阶段都直接关乎我们手机的性能、功耗、甚至寿命。本文试图通过block IO的产生、调度、下发、返回的4个阶段,阐述一个block IO的生命历程。 一、什么是块设备…...
Python爬虫学习之旅:从入门到精通,要学多久?
导语: 随着信息时代的发展,大量的数据和信息储存在互联网上,这为我们提供了获取和利用这些数据的机会。而Python爬虫作为一种强大的工具,可以帮助我们从网页中提取数据,并进行进一步的分析和挖掘。然而,对…...
HarmonyOS/OpenHarmony(Stage模型)卡片开发应用上下文Context使用场景一
1.获取应用文件路径 基类Context提供了获取应用文件路径的能力,ApplicationContext、AbilityStageContext、UIAbilityContext和ExtensionContext均继承该能力。应用文件路径属于应用沙箱路径。上述各类Context获取的应用文件路径有所不同。 通过ApplicationContext…...
MAE 论文精读 | 在CV领域自监督的Bert思想
1. 背景 之前我们了解了VIT和transformer MAE 是基于VIT的,不过像BERT探索了自监督学习在NLP领域的transformer架构的应用,MAE探索了自监督学习在CV的transformer的应用 论文标题中的Auto就是说标号来自于图片本身,暗示了这种无监督的学习 …...
C++中内存的分配
一个由C/C编译的程序占用的内存分为以下几个部分 1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。 2、堆区(heap) — 一般由程序员分配释放, 若程序…...
Qt中的垂直布局QVBoxLayout和水平布局QHBoxLayout
文章目录 QVBoxLayoutQHBoxLayout QVBoxLayout Qt中的垂直布局(Vertical Layout)是用来将控件按垂直方向进行排列的布局管理器。下面是一些常用的Qt Vertical Layout的函数及其用法示例: QVBoxLayout类的构造函数: QVBoxLayout…...
【C#学习笔记】委托和事件
文章目录 委托委托的定义委托实例化委托的调用多播委托 为什么使用委托?官方委托泛型方法和泛型委托 事件为什么要有事件?事件和委托的区别: 题外话——委托与观察者模式 委托 在 .NET 中委托提供后期绑定机制。 后期绑定意味着调用方在你所…...
堆排序简介
概念: 堆排序是一种基于二叉堆数据结构的排序算法。它的概念是通过将待排序的元素构建成一个二叉堆,然后通过不断地取出堆顶元素并重新调整堆的结构来实现排序。 算法步骤: 构建最大堆(或最小堆):将待排…...
React Diff算法
文章目录 React Diff算法一、它的作用是什么?二、React的Diff算法1.了解一下什么是调和?2.react的diff算法3.React Diff的三大策略4.tree diff:1、如果DOM节点出现了跨层级操作,Diff会怎么办? 5. component diff:6. e…...
07 mysql5.6.x docker 启动, 无 config 目录导致客户端连接认证需要 10s
前言 呵呵 最近再一次 环境部署的过程中碰到了这样的一个问题 我基于 docker 启动了一个 mysql 服务, 然后 挂载出了 数据目录 和 配置目录, 没有手动复制配置目录出来, 所以配置目录是空的 然后 我基于 docker 启动了一个 nacos, 配置数据库设置为上面的这个 mysql 然后 启…...
GO GC
GO GC 垃圾回收(Garbage Collection,简称GC)是编程语言中提供的自动的内存管理机制,自动释放不需要的对象,让出存储器资源,无需程序员手动执行。 Golang中的垃圾回收主要应用三色标记法,GC过程和其他用户goroutine可…...
ECharts配合Node.js爬虫实现数据可视化
数据可视化简介 可视化技术是将数据和信息以图形化的方式展示出来,以便更好地理解和分析。可视化技术通常使用各种图表、图形、动画和交互式效果来呈现数据。可视化技术有以下几个基本概念: 数据:可视化技术的基础是数据。数据可以是数字、文…...
[Linux] C获取键盘,鼠标数据
键盘检测指令:cat /dev/input/event1 | hexdump 鼠标检测指令:cat /dev/input/event2 | hexdump 当键盘/鼠标有输入时,会有对应的一堆16进制输出。它其实对应着input_event结构体【24字节】。 struct input_event {struct timeval time;_…...
户外跑步用什么耳机、户外运动耳机推荐
跑步是一项简单的运动,只需要交替迈左右腿就可以进行。然而,跑步有时可能变得单调乏味。即使是意志坚定、热爱跑步的人,在这个漫长的过程中也会感到乏味,更不用说像你我这样的普通跑者了。音乐能够让跑步变得更加有趣,…...