栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

AllBlue项目

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

AllBlue项目

一、项目介绍

1、项目简介

项目是专门为餐饮企业(餐厅、饭店)定制的一款软件产品,包括系统管理后台和移动端应用两部分。其中系统管理后台主要提供给餐饮企业内部员工使用,可以对餐厅的分类、菜品、套餐、订单、员工等进行管理维护。移动端应用主要提供给消费者使用,可以在线浏览菜品、添加购物车、下单等。

2、技术选用

前端:H5、vue、ElementUl

后端:SpringBoot、SpringMVC、Spring、Spring Session

数据库:Mysql、Mybatis、Mybatis Plus

二、项目配置 1、数据库搭建

创建数据库和数据库表

2、创建maven项目

1、创建普通maven项目

 

 2、检测maven和Runner配置

 3、检测jdk

 三、导入相关依赖和配置文件

1、pom文件



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.4.5
         
    
    net.lzzy
    all_bule_take_out
    1.0-SNAPSHOT
    
        1.8
    

    
        
            org.springframework.boot
            spring-boot-starter
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        

        
            org.springframework.boot
            spring-boot-starter-web
            compile
        

        
            com.baomidou
            mybatis-plus-boot-starter
            3.4.2
        

        
            org.projectlombok
            lombok
            1.18.20
        

        
            com.alibaba
            fastjson
            1.2.76
        

        
            commons-lang
            commons-lang
            2.6
        

        
            mysql
            mysql-connector-java
            runtime
        

        
            com.alibaba
            druid-spring-boot-starter
            1.1.23
        

    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                2.4.5
            
        
    

2、在resources文件夹下新建application.yml文件

 输入配置

server:
  port: 8080
spring:
  application:
    #应用的名称,可选
    name: all_bule_take_out
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/all_bule?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
      username: root
      password: 123456
mybatis-plus:
  configuration:
    #在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射
    #比如数据库的表:address_book=>实体类的类名AdderssBook
    #字段也一样,例如数据库的列:user_name=>类的属性userName
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      id-type: ASSIGN_ID
四、创建启动类

1、在java目录下新建net.lzzy.allbule目录和AllBuleApplication启动类

AllBuleApplication启动类配置:

@Slf4j
@SpringBootApplication
public class AllBuleApplication {
    public static void main(String[] args) {
        SpringApplication.run(AllBuleApplication.class,args);
        log.info("项目启动成功");
    }
}

@SpringBootApplication是SpringBoot启动类的注解

@Slf4j:在类前面添加注解@Slf4j,就可以使用info的方法在控制台输出日志,或者可以说是可直接使用log日志的功能了

 五、设置静态资源的映射

把前端的页面放在resources下,发现访问不了

 

1、配置MVC静态支援的映射

 创建config包,然后再新建WebMvcConfig类:

1、@Configuration注解表示当前类是配置类,声明当前类为Spring配置类

2、继承WebMvcConfigurationSupport类,重写静态资源映射的方法:addResourceHandlers方法,使用registry参数来设置要映射的访问路径

@Slf4j
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
    
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        log.info("开始静态资源映射...");
        registry.addResourceHandler("/backend
@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;

    private LocalDateTime createTime;

    private LocalDateTime updateTime;

    @TableField(fill = FieldFill.INSERT)
    private Long createUser;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;

}

2、在net.lzzy.allbule创建controller包(Controler负责请求转发,接受页面过来的参数,传给Service处理,接到返回值,再传给页面)、mapper包(数据层进行crud的实现方式),server包( 封装通用的业务逻辑,操作),在server下再建一个impl包(service的impl是把mapper和service进行整合的文件)

3、在mapper包下创建EmployeeMapper接口(员工数据操作接口)操作数据,继承MyBatis-Plus提供的BaseMapper类,继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能,BaseMapper泛型是指定要操作的实体类@Mapper的作用是可以给mapper接口自动生成一个实现类,让spring对mapper接口的bean进行管理,并且可以省略去写复杂的xml文件。

package net.lzzy.allbule.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import net.lzzy.allbule.entity.Employee;
import org.apache.ibatis.annotations.Mapper;


@Mapper
public interface EmployeeMapper extends BaseMapper {
}

4.1、在service包下创建EmployeeService业务层。继承MyBatis-Puls提供的IService类

package net.lzzy.allbule.service;

import com.baomidou.mybatisplus.extension.service.IService;
import net.lzzy.allbule.entity.Employee;


public interface EmployeeService extends IService {
}

4.2、在service包下的Impl包新建一个实现类EmployeeServiceImpl,

Spring提供@Component注解的三个衍生注解:功能一样,使用原因:方便理解

1、@Controller :用于表现层bean定义

2、@Service :用于业务层bean定义

3、@Repository :用于数据层bean定义

package net.lzzy.allbule.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.lzzy.allbule.entity.Employee;

import net.lzzy.allbule.mapper.EmployeeMapper;
import net.lzzy.allbule.service.EmployeeService;
import org.springframework.stereotype.Service;

@Service
public class EmployeeServiceImpl extends ServiceImpl implements EmployeeService {
}

5、在controller包下创建EmployeeController类

@RequestMapping用来映射URL

@RestController = @Controller + @ResponseBody组成

  • @Controller 将当前修饰的类注入SpringBoot IOC容器,使得从该类所在的项目跑起来的过程中,这个类就被实例化。当然也有语义化的作用,即代表该类是充当Controller的作用
  • @ResponseBody 它的作用简短截说就是指该类中所有的API接口返回的数据,甭管你对应的方法返回Map或是其他Object,它会以Json字符串的形式返回给客户端
package net.lzzy.allbule.controller;

import lombok.extern.slf4j.Slf4j;
import net.lzzy.allbule.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@Slf4j
@RestController
@RequestMapping("/employee")
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;
}
2、创建common包,用于放通用的的类

5、创建通用返回类R类

package net.lzzy.allbule.common;

import lombok.Data;
import java.util.HashMap;
import java.util.Map;


@Data
public class R {

    private Integer code; //编码:1成功,0和其它数字为失败

    private String msg; //错误信息

    private T data; //数据

    private Map map = new HashMap(); //动态数据

    
    public static  R success(T object) {
        R r = new R();
        r.data = object;
        r.code = 1;
        return r;
    }

    
    public static  R error(String msg) {
        R r = new R();
        r.msg = msg;
        r.code = 0;
        return r;
    }

    public R add(String key, Object value) {
        this.map.put(key, value);
        return this;
    }

}
3、登录方法

登录处理逻辑:
1、将页面提交的密码password进行md5加密处理

2、根据页面提交的用户名username查询数据库

3、如果没有查询到则返回登录失败结果

4、密码比对,如果不一致则返回登录失败结果

5、查看员工状态,如果为已禁用状态,则返回员工已禁用结果

6、登录成功,将员工id存入Session并返回登录成功结果

 
    @PostMapping("/login")
    public R login(HttpServletRequest request,@RequestBody Employee employee){
        String password = employee.getPassword();
        //将前端提交的密码进行md5加密
        DigestUtils.md5DigestAsHex(password.getBytes());

        //根据页面提交的用户名username查询数据库
        LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
        //使用Mybatis-plus的等值查询进行查询
        queryWrapper.eq(Employee::getUsername,employee.getUsername());
        //数据库中表的username设置了唯一索引,不能重复,调用getOne方法查出唯一的一个数据,查出来后封装成一个对象,emp是查出来的对象
        Employee emp = employeeService.getOne(queryWrapper);
        //如果没有查询到就返回登录失败的结果
        if(emp==null){
            return R.error("登陆失败");
        }
        //密码对比,不对返回失败
//        if(!emp.getPassword().equals(password)){
//            return R.error("登陆失败");
//        }
        //查看状态,是否被禁用,禁用就返回已经禁用的结果
        if(emp.getStatus()==0){
            return R.error("账号已经禁用");
        }
        //登录成功,将id存入Session中
        request.getSession().setAttribute("employee",emp.getId());
        //返回登录成功的结果
        return R.success(emp);
    }
4、退出登录

清除缓存id

  
    @PostMapping("/logout")
    public Rlogout(HttpServletRequest request){
        request.getSession().removeAttribute("employee");
        return R.success("退出成功");
    }
}
5、拦截器

防止没登录就直接访问系统

新建filter包,创建LoginCheckFilter类

package net.lzzy.allbule.filter;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import net.lzzy.allbule.common.R;
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 Boolean check(String[]urls,String requestURI){
        for (String url : urls) {
            boolean match = PATH_MATCHER.match( url,requestURI);
            if(match){
                return true;
            }
        }
        return false;
    }
}

@WebFilter 用于将一个类声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为过滤器。注解默认是不被扫描的,需要在项目启动类上添加 @ServletComponentScan 注解, 表示对 Servlet 组件扫描。

 七、员工信息操作 1、添加员工
    
    @PostMapping
    public Rsave(HttpServletRequest request,@RequestBody Employee employee){
        log.info("添加员工,信息:{}",employee.toString());

        //设置初始密码,需要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);

        employeeService.save(employee);

        return  R.success("添加员工成功");
    }

2、分页查询  1、配置MP(mabatisPlus)的分页插件

在config包下添加 MybatisPlusConfig配置类

package net.lzzy.allbule.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor=new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}
2、分页处理方法
    
    @GetMapping("/page")
    public Rpage(int page,int pageSize,String name){
        log.info("page={},pageSize={},name={}",page,pageSize,name);

        Page pageInfo=new Page(page,pageSize);

        //构造条件构造器
        LambdaQueryWrapper queryWrapper=new LambdaQueryWrapper();
        //当name不等于空的时候,添加过滤条件
        queryWrapper.like(StringUtils.isNotEmpty(name),Employee::getName,name);
        //添加排序条件
        queryWrapper.orderByDesc(Employee::getUpdateTime);
        //执行查询
        employeeService.page(pageInfo,queryWrapper);
        return R.success(pageInfo);
    }
3、员工状态启用/禁用
 
    @PutMapping
    public Rupdate(HttpServletRequest request,@RequestBody Employee employee){
        log.info(employee.toString());

        Long empId = (Long) request.getSession().getAttribute("employee");
        employee.setUpdateTime(LocalDateTime.now());
        employee.setUpdateUser(empId);

        employeeService.updateById(employee);
        return  R.success("员工信息修改成功");
    }
状态更新失败

 

 原因:js对long型数据进行处理时丢失精度,导致提交的id和数据库中的id不一致。

 如何解决这个问题?
我们可以在服务端给页面响应json数据时进行处理,将long型数据统一转为String字符串

具体实现步骤:

  1. 提供对象转换器JacksonobjectMapper,基于Jackson进行Java对象到json数据的转换
  2. 在WebMvcConfig配置类中扩展Spring mvc的消息转换器,在此消息转换器中使用提供的对象转换器进行Java对象到json数据的转换

添加对象映射器

package net.lzzy.allbule.common;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;


public class JacksonObjectMapper extends ObjectMapper {

    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";

    public JacksonObjectMapper() {
        super();
        //收到未知属性时不报异常
        this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);

        //反序列化时,属性不存在的兼容处理
        this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);


        SimpleModule simpleModule = new SimpleModule()
                .addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))

                .addSerializer(BigInteger.class, ToStringSerializer.instance)
                .addSerializer(Long.class, ToStringSerializer.instance)
                .addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));

        //注册功能模块 例如,可以添加自定义序列化器和反序列化器
        this.registerModule(simpleModule);
    }
}

在WebMvcConfig添加扩展mvc框架的消息转换器

 
    @Override
    protected void extendMessageConverters(List> converters) {
        log.info("扩展消息转换器...");
        //创建消息转换器对象
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
        //设置对象转换器,底层使用Jackson将Java对象转为json
        messageConverter.setObjectMapper(new JacksonObjectMapper());
        //将上面的消息转换器对象追加到mvc框架的转换器集合中
        converters.add(0, messageConverter);
    }
四、根据Id编辑员工信息
    
    @GetMapping("{id}")
    public RgetById(@PathVariable Long id){
        log.info("根据id查询");
        Employee employee = employeeService.getById(id);
        if(employee!=null){
            return R.success(employee);
        }
        return R.error("没有查询到对应的员工信息");

    }
八、全局异常捕获

在common包下添加GlobalExceptionHandler类

@ControllerAdvice是在类上声明的注解,其用法主要有三点::

  1. @ExceptionHandler注解标注的方法:用于捕获Controller中抛出的不同类型的异常,从而达到异常全局处理的目的;
  2. @InitBinder注解标注的方法:用于请求中注册自定义参数的解析,从而达到自定义请求参数格式的目的;
  3. @ModelAttribute注解标注的方法:表示此方法会在执行目标Controller方法之前执行 。
  4. @ControllerAdvice(annotations = {RestController.class, Controller.class})表示只要哪个类上加了@RestController和@Controller都会被当前处理器处理
  • @ExceptionHandler:统一处理某一类异常,从而能够减少代码重复率和复杂度
  • @ControllerAdvice:异常集中处理,更好的使业务逻辑与异常处理剥离开;其是对Controller层进行拦截
  • @ResponseStatus:可以将某种异常映射为HTTP状态码
package net.lzzy.allbule.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})
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {
    
    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    public R exceptionHandler(SQLIntegrityConstraintViolationException ex){
        log.error(ex.getMessage());

        if(ex.getMessage().contains("Duplicate entry")){
            String[] split = ex.getMessage().split(" ");
          String msg=  split[2]+"已经存在";
            return R.error(msg);
        }
        return R.error("未知错误");
    }
}
九、公共字段自动填充

Mybatis Plus公共字段自动填充,也就是在插入或者更新的时候为指定字段赋予指定的值,使用它的好处就是可以统一对这些字段进行处理,避免了重复代码。

实现步骤:

1、在实体类的属性上加入@TableField注解,指定自动填充的策略

2、按照框架要求编写元数据对象处理器,在此类中统一为公共字段赋值,此类需要实现MetaObjectHandler接口

ThreadLocal:

ThreadLocal为每个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。

 ThreadLocal常用方法:
  1. public void set(T value)设置当前线程的线程局部变量的值
  2. public T get() 返回当前线程所对应的线程局部变量的值
使用ThreadLocal存储当前用户的id

1、编写BaseContext工具类,基于ThreadLocal封装的工具类

package net.lzzy.allbule.common;


public class BaseContext {
// 用于保存当前登录用户id
    private static ThreadLocal threadLocal = new ThreadLocal<>();

    
    public static void setCurrentId(Long id){
        threadLocal.set(id);
    }

    
    public static Long getCurrentId(){
        return threadLocal.get();
    }
}

2、在LogincheckFilter的doFilter方法中调用BaseContext来设置当前登录用户的id

  Long empId = (Long) request.getSession().getAttribute("employee");
           BaseContext.setCurrentId(empId);
           long id = Thread.currentThread().getId();

3、新建MyMetaobjectHandler类,方法中调用BaseContext获取登录用户的id

package net.lzzy.allbule.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;


@Component
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {
    
    @Override
    public 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.getCurrentId());
        metaObject.setValue("updateUser",BaseContext.getCurrentId());
    }

    
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("公共字段自动填充[update]...");
        log.info(metaObject.toString());

        long id = Thread.currentThread().getId();
        log.info("线程id为:{}",id);

        metaObject.setValue("updateTime",LocalDateTime.now());
        metaObject.setValue("updateUser",BaseContext.getCurrentId());
    }
}

十、新增分类 1、搭建操作工作 1、创建实体类
@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;

}
@Data
public class Dish implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;


    //菜品名称
    private String name;


    //菜品分类id
    private 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;

}

@Data
public class Setmeal implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;


    //分类id
    private 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;
}

2、创建Mapper
@Mapper
public interface CategoryMapper extends BaseMapper {
}
@Mapper
public interface DishMapper extends BaseMapper {
}
@Mapper
public interface SetmealMapper extends BaseMapper {
}
3、创建service接口和实现类
public interface CategoryService extends IService {
        public void remove(Long id);
}
@Service
public class CategoryServiceImpl extends ServiceImpl implements CategoryService {
}
public interface DishService extends IService {
}
@Service
@Slf4j
public class DishServiceImpl extends ServiceImpl implements DishService {
}
public interface SetmealService extends IService {
}
@Service
public class SetmealServiceImpl extends ServiceImplimplements SetmealService {
}
4、创建控制层类
@RestController
@RequestMapping("/category")
@Slf4j
public class CategoryController {
    @Autowired
    private CategoryService categoryService;
}
2、业务开发 1、添加分类

在CategoryController类添加新增分类的方法

    
    @PostMapping
    public Rsave(@RequestBody Category category){
        log.info("新增参数:{}"+category);
        categoryService.save(category);
        return R.success("新增成功");
    }
2、分页查询
  
    @GetMapping("/page")
    public Rpage(int page,int pageSize){
        //创建分页构造器
        PagepageInfo=new Page<>();
        //创建条件构造器对象,根据sort进行排序
        LambdaQueryWrapperqueryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.orderByAsc(Category::getSort);

        //进行查询
        categoryService.page(pageInfo,queryWrapper);


        return R.success(pageInfo);
    }

为了提高查询性能,表与表之间的联系需要人工去维护,不推荐使用外键维护数据的安全性

3、删除

因为分类中可能关联了一下菜品跟套餐,所以不能直接删除,需要自定义判断处理

自定义删除方法,抛出异常

@Service
public class CategoryServiceImpl extends ServiceImpl implements CategoryService {

    @Autowired
    private DishService dishService;
    @Autowired
    private SetmealService setmealService;

    
    @Override
    public void remove(Long id) {
        LambdaQueryWrapperdishLambdaQueryWrapper=new LambdaQueryWrapper<>();
        //添加查询条件,根据Id查询
        dishLambdaQueryWrapper.eq(Dish::getCategoryId,id);
        int count=dishService.count(dishLambdaQueryWrapper);

        //查询当前分类是否关联了菜品,如果已经关联,抛出一个异常
        if(count>0){
            //已经关联菜品,抛出异常
            throw new CustomException("当前分类关联了菜品,不能删除");

        }
        //查询当前分类是否关联了套餐,如果已经关联,抛出一个业务异常
        LambdaQueryWrappersetmealLambdaQueryWrapper=new LambdaQueryWrapper<>();
        setmealLambdaQueryWrapper.eq(Setmeal::getCategoryId,id);
        int count1 = setmealService.count(setmealLambdaQueryWrapper);
        if(count1>0){
            //已经关联套餐,抛出异常
            throw new CustomException("当前分类关联了菜品,不能删除");
        }
        //删除
        super.removeById(id);
    }
}
在common包中定义接收自定义业务异常类
public class CustomException extends RuntimeException {
    public CustomException(String message){
        super(message);
    }
}

在GlobalExceptionHandler类中添加异常处理方法

  
    @ExceptionHandler(CustomException.class)
    public R exceptionHandler(CustomException ex){
        log.error(ex.getMessage());

        return R.error(ex.getMessage());
    }

控制层调用方法

   
    @DeleteMapping
    public Rdelete(Long ids){
        log.info("删除分类,id为:{}",ids);
        categoryService.remove(ids);

        return R.success("分类删除成功");
    }
4、修改分类信息
  
    @PutMapping
    public Rupdate(@RequestBody Category category){
        categoryService.updateById(category);
        return R.success("修改成功");
    }

十一、文件上传、下载
import lombok.extern.slf4j.Slf4j;
import net.lzzy.allbule.common.R;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.UUID;



@RestController
@RequestMapping("/common")
@Slf4j
public class CommonController {

    @Value("${allBlue.path}")
    private String basePath;

    
    @PostMapping("/upload")
    public R upload(MultipartFile file) {
        log.info(file.toString());
        //原始文件名
        String originalFilename = file.getOriginalFilename();//abc.jpg
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));

        //使用UUID重新生成文件名,防止文件名称重复造成文件覆盖
        String fileName = UUID.randomUUID().toString() + suffix;

        //创建一个目录对象
        File dir = new File(basePath);
        //判断当前目录是否存在
        if (!dir.exists()) {
            //目录不存在,需要创建
            dir.mkdirs();
        }

        try {
            //将临时文件转存到指定位置
            file.transferTo(new File(basePath + fileName));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return R.success(fileName);
    }


    
    @GetMapping("/download")
    public void download(String name, HttpServletResponse response){

        try {
            //输入流,通过输入流读取文件内容
            FileInputStream fileInputStream = new FileInputStream(new File(basePath + name));

            //输出流,通过输出流将文件写回浏览器
            ServletOutputStream outputStream = response.getOutputStream();

            response.setContentType("image/jpeg");

            int len = 0;
            byte[] bytes = new byte[1024];
            while ((len = fileInputStream.read(bytes)) != -1){
                outputStream.write(bytes,0,len);
                outputStream.flush();
            }

            //关闭资源
            outputStream.close();
            fileInputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

十二、添加菜品 业务准备 1、创建DishFlavor实体类
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.time.LocalDateTime;


@Data
public class DishFlavor implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;


    //菜品id
    private Long dishId;


    //口味名称
    private String name;


    //口味数据list
    private String value;


    @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、创建DishFlavorMapper数据持久层
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import net.lzzy.allbule.entity.DishFlavor;
import org.apache.ibatis.annotations.Mapper;



@Mapper
public interface DishFlavorMapper extends BaseMapper {
}
3、创建DishFlavorService业务层,继承IService类
import com.baomidou.mybatisplus.extension.service.IService;
import net.lzzy.allbule.entity.DishFlavor;

public interface DishFlavorService extends IService {
}
4、创建DishFlavorServiceImpl业务实现类,继承ServiceImpl类
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.lzzy.allbule.entity.DishFlavor;
import net.lzzy.allbule.mapper.DishFlavorMapper;
import net.lzzy.allbule.service.DishFlavorService;
import org.springframework.stereotype.Service;

@Service
public class DishFlavorServiceImpl extends ServiceImpl implements DishFlavorService {
}
5、创建DishController类控制层
import net.lzzy.allbule.service.DishFlavorService;
import net.lzzy.allbule.service.DishService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("/dish")
public class DishController {

    @Autowired
    private DishFlavorService dishFlavorService;

    @Autowired
    private DishService dishService;
}
实现 1、菜品分类数据获取

在CategoryController添加查询分类数据的方法

    @GetMapping("/list")
    public  R>list(Category category){
        //条件构造器
        LambdaQueryWrapper queryWrapper=new LambdaQueryWrapper<>();
        //添加添加
        queryWrapper.eq(category.getType()!=null,Category::getType,category.getType());
        //添加排序条件
        queryWrapper.orderByAsc(Category::getSort).orderByDesc(Category::getUpdateTime);

        List list = categoryService.list(queryWrapper);

        return R.success(list);
    }

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/927329.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号