SpringCloud+Feign微服务拆分最佳实践

71 阅读32分钟

技术选型

JDK:17

Mysql:8.0.4

Maven:3.9.10

SpringBoot:3.3.13

Mybatis-Plus:3.5.7

Spring-Data-Redis:3.3.13

Spring-Cache:3.3.13

Spring-Cloud:2023.0.1

Nacos:3.0.2

安装Nacos

Nacos官网:Nacos官网| Nacos 配置中心 | Nacos 下载| Nacos 官方社区 | Nacos 官网Nacos 提供动态服务发现、配置和管理,助力用户在私有云、混合云、公有云等环境中快速构建和交付微服务平台,提升业务复用和创新交付速度,为用户赢得市场竞争力。https://nacos.io/

​编辑

启动服务器:

​编辑

创建微服务项目

编辑

编辑

创建emp-service模块

编辑

编辑

创建dept-service模块

编辑

编辑

创建common-pojo模块(存放实体类)

编辑

创建common-utils模块(存放工具类)

编辑

编辑

修改父工程pom文件

引入父依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.he</groupId>
    <artifactId>kawa-cloud</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>emp-service</module>
        <module>dept-service</module>
        <module>common-pojo</module>
    </modules>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.13</version>
        <relativePath/>
    </parent>

    <properties>
        <java.version>17</java.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

编辑

引入共同依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.he</groupId>
    <artifactId>kawa-cloud</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>emp-service</module>
        <module>dept-service</module>
        <module>common-pojo</module>
    </modules>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.13</version>
        <relativePath/>
    </parent>

    <properties>
        <java.version>17</java.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-boot-starter-web.version>3.3.13</spring-boot-starter-web.version>
    </properties>

    <!--  引入共有的依赖  -->
    <dependencies>
        <!--springboot-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot-starter-web.version}</version>
        </dependency>
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>
    </dependencies>

</project>

编辑

管理版本依赖(并不会直接引入依赖)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.he</groupId>
    <artifactId>kawa-cloud</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>emp-service</module>
        <module>dept-service</module>
        <module>common-pojo</module>
    </modules>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.13</version>
        <relativePath/>
    </parent>

    <properties>
        <java.version>17</java.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-boot-starter-web.version>3.3.13</spring-boot-starter-web.version>
        <mysql.version>8.0.33</mysql.version>
        <lombok.version>1.18.22</lombok.version>
    </properties>

    <!--  引入共有的依赖  -->
    <dependencies>
        <!--springboot-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot-starter-web.version}</version>
        </dependency>
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>
    </dependencies>

    <!-- 管理依赖版本  -->
    <dependencyManagement>
        <dependencies>
            <!--mysql-->
            <dependency>
                <groupId>com.mysql</groupId>
                <artifactId>mysql-connector-j</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <!--lombok-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

编辑

操作common-pojo模块

修改pom文件引入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.he</groupId>
        <artifactId>kawa-cloud</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>common-pojo</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>

编辑

创建包引入实体类

编辑

package com.he.pojo.Dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.time.LocalDateTime;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class DeptSimpleDto implements Serializable {
    // 版本控制
    private static final long serialVersionUID = 1L;
    private Integer id;
    private String name;
    private LocalDateTime createTime;
}

package com.he.pojo.Dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.time.LocalDate;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class EmpSimpleDto implements Serializable {
    // 版本控制
    private static final long serialVersionUID = 1L;
    private Integer id;
    private String name;
    private Short gender;
    private LocalDate entryDate;
    private Integer deptId;
}

package com.he.pojo.Dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDate;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class EmpSearchDto {
    private String name;
    private Short gender;
    private LocalDate begin;
    private LocalDate end;
    private Integer page;
    private Integer pageSize;
}

package com.he.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.he.pojo.Dto.EmpSimpleDto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Dept implements Serializable {
    // 版本控制
    @TableField(exist = false)
    private static final long serialVersionUID = 1L;
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    private String name;
    private LocalDateTime createTime;
    private LocalDateTime updateTime;
    @TableField(exist = false)
    private List<EmpSimpleDto> empsSimple;
}

编辑

package com.he.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.he.pojo.Dto.DeptSimpleDto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;

@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("emp")
public class Emp implements Serializable {
    // 版本控制
    @TableField(exist = false)
    private static final long serialVersionUID = 1L;
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    private String username;
    private String password;
    private String name;
    private Short gender;
    private String phone;
    private Short job;
    private Integer salary;
    private String image;
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate entryDate;
    private Integer deptId;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;
    @TableField(exist = false)
    private DeptSimpleDto deptSimple;
}

package com.he.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.List;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageBean implements Serializable {
    // 版本控制
    private static final long serialVersionUID = 1L;
    private Long total; // 总记录数
    private List rows; // 当前页数据列表
}

package com.he.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result{
    // 成员变量
    private Integer code; // 响应码:1:成功,0:失败
    private String msg; // success:成功,error:失败
    private Object data; // 要封装的对象

    // 成功:根据不同的情况返回相对应的结果 无数据返回
    public static Result success(){
        // 创建Result对象
        Result result = new Result();
        // 封装数据
       result.code = 1;
       result.msg = "success";
        // 返回结果
        return result;
    }
    // 成功:根据不同的情况返回相对应的结果 有数据返回
    public static Result success(Object data){
        // 创建Result对象
        Result result = new Result();
        // 封装数据
        result.code = 1;
        result.msg = "success";
        result.data = data;
        // 返回结果
        return result;
    }
    // 失败:根据不同情况返回相对应的结果
    public static Result error(){
        // 创建Result对象
        Result result = new Result();
        // 封装数据
        result.code = 0;
        result.msg = "error";
        return result;
    }
    // 失败:根据不同情况返回相对应的结果
    public static Result error(String msg){
        // 创建Result对象
        Result result = new Result();
        // 封装数据
        result.code = 0;
        result.msg = msg;
        return result;
    }
}

操作common-utils模块

创建包,创建MybatisPlusConfig配置类

@Configuration
public class MybatisPlusConfig {
    /**
     * 添加分页插件
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

编辑

操作dept-service模块

修改pom文件引入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.he</groupId>
        <artifactId>kawa-cloud</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>dept-service</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!--mysql-->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--common-pojo-->
        <dependency>
            <groupId>com.he</groupId>
            <artifactId>common-pojo</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
         <!--common-utils-->
        <dependency>
            <groupId>com.he</groupId>
            <artifactId>common-utils</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

编辑

创建包,创建DeptMapper接口

package com.he.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.he.pojo.Dept;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface DeptMapper extends BaseMapper<Dept> {

}

编辑

创建包,创建DeptService接口

package com.he.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.he.pojo.Dept;

import java.util.List;

public interface DeptService extends IService<Dept> {
    // 根据部门ID查询部门信息
    Dept queryById(Integer id);
}

编辑

创建包,创建DeptServiceImpl类

@Service
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements DeptService {

    @Autowired
    DeptMapper deptMapper;


    // 根据部门Id获取部门信息
    @Override
    public Dept queryById(Integer id) {
        Dept dept = deptMapper.selectById(id);
        return dept;
    }

}

编辑

创建包,创建DeptController类

@Slf4j
@RestController
@RequestMapping("/depts")
public class DeptController {
    @Autowired
    DeptService deptService;


    // 根据部门ID获取部门信息
    @GetMapping("/{id}")
    public Result queryById(@PathVariable Integer id) {
        log.info("根据部门ID:{}查询部门信息", id);
        Dept dept = deptService.queryById(id);
        return dept != null ? Result.success(dept): Result.error();
    }

}

编辑

创建application.yml配置文件

server:
  port: 8091
spring:
  application:
    name: deptservice
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/deptdatabase
    username: root
    password: 123456
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true # 开启驼峰命名
logging:
  level:
    com.he: debug
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS

编辑

创建DeptApplication启动类

package com.he;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DeptApplication {
    public static void main(String[] args) {
        SpringApplication.run(DeptApplication.class, args);
    }
}

编辑

操作emp-service模块

修改pom文件引入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.he</groupId>
        <artifactId>kawa-cloud-demo</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>emp-service</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!--mysql-->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--common-pojo-->
        <dependency>
            <groupId>com.he</groupId>
            <artifactId>common-pojo</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
         <!--common-utils-->
        <dependency>
            <groupId>com.he</groupId>
            <artifactId>common-utils</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>

编辑

创建包,创建EmpMapper接口

package com.he.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.he.pojo.Emp;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface EmpMapper extends BaseMapper<Emp> {

}

编辑

创建包,创建EmpService接口

public interface EmpService extends IService<Emp> {
    // 根据信息分页查询
    PageBean queryByInfo(EmpSearchDto empSearchDto);
}

编辑

创建包,创建EmpServiceImpl类

@Service
public class EmpServiceImpl extends ServiceImpl<EmpMapper, Emp> implements EmpService {

    @Autowired
    EmpMapper empMapper;

    // 根据信息分页查询
    public PageBean queryByInfo(EmpSearchDto empSearchDto) {
        // 创建查询条件
        LambdaQueryWrapper<Emp> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.like(StringUtils.hasLength(empSearchDto.getName()),Emp::getName, empSearchDto.getName())
                .eq(empSearchDto.getGender()!=null,Emp::getGender, empSearchDto.getGender())
                .ge(empSearchDto.getBegin()!=null,Emp::getEntryDate, empSearchDto.getBegin())
                .le(empSearchDto.getEnd()!=null,Emp::getEntryDate, empSearchDto.getEnd());
        // 创建分页条件
        if (empSearchDto.getPage() == null) {
            empSearchDto.setPage(1);
        }
        if (empSearchDto.getPageSize() == null) {
            empSearchDto.setPageSize(5);
        }
        Page<Emp> pageInfo = new Page<>(empSearchDto.getPage(), empSearchDto.getPageSize());
        // 执行查询
        Page<Emp> empPage = empMapper.selectPage(pageInfo, queryWrapper);
        // 封装数据
        PageBean pageBean = new PageBean(empPage.getTotal(), empPage.getRecords());
        // 返回数据
        return pageBean;
    }
}

编辑

创建包,创建EmpController类

@Slf4j
@RestController
@RequestMapping("/emps")
public class EmpController {
    @Autowired
    EmpService empService;

    @GetMapping
    public Result queryByInfo(@ModelAttribute EmpSearchDto empSearchDto){
        log.info("查询员工信息,参数:empDto={}", empSearchDto);
        PageBean pageBean = empService.queryByInfo(empSearchDto);
        return pageBean!=null?Result.success(pageBean):Result.error("查询失败!");
    }
}

编辑

创建application.yml配置文件

server:
  port: 8081
spring:
  application:
    name: empservice
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/empdatabase
    username: root
    password: 123456
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true # 开启驼峰命名
logging:
  level:
    com.he: debug
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS

编辑

创建EmpApplication启动类

@SpringBootApplication
public class EmpApplication {
    public static void main(String[] args) {
        SpringApplication.run(EmpApplication.class, args);
    }
}

编辑

修改父工程pom文件

管理版本依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.he</groupId>
    <artifactId>kawa-cloud</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>emp-service</module>
        <module>dept-service</module>
        <module>common-pojo</module>
        <module>fegin-api</module>
        <module>common-utils</module>
    </modules>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.13</version>
        <relativePath/>
    </parent>

    <properties>
        <java.version>17</java.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-boot-starter-web.version>3.3.13</spring-boot-starter-web.version>
        <mybatis-plus.version>3.5.7</mybatis-plus.version>
        <mysql.version>8.0.33</mysql.version>
        <lombok.version>1.18.22</lombok.version>
        <spring-cloud.version>2023.0.1</spring-cloud.version>
        <spring-cloud-alibaba-version>2023.0.1.0</spring-cloud-alibaba-version>
    </properties>

    <!--  引入共有的依赖  -->
    <dependencies>
        <!--springboot-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot-starter-web.version}</version>
        </dependency>
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>
    </dependencies>

    <!-- 管理依赖版本  -->
    <dependencyManagement>
        <dependencies>
            <!--mysql-->
            <dependency>
                <groupId>com.mysql</groupId>
                <artifactId>mysql-connector-j</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <!--lombok-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>
            <!-- springCloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--nacos-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba-version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

编辑

遇到问题:只引入SpringCloudAlibaba不引入SpringCloud就无法引入Feign依赖

原因:Spring Cloud Alibaba是对Spring Cloud生态的扩展,并非独立替代品;它需与Spring Cloud基础组件协同工作,Feign的注解解析、HTTP请求模板化等核心能力需通过spring-cloud-starter-openfeign提供,如果仅引入Spring Cloud Alibaba而不添加Spring Cloud相关依赖,会导致Feign无法被正确加载或调用。

创建feign-api模块

编辑

编辑

修改pom文件引入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.he</groupId>
        <artifactId>kawa-cloud</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>fegin-api</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!--feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!-- 负载均衡器 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
        <!--httpClient的依赖 -->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>
        <!--common-pojo-->
        <dependency>
            <groupId>com.he</groupId>
            <artifactId>common-pojo</artifactId>
            <version>1.0-SNAPSHOT</version>
            <!-- 模块内部使用,不会传递给其他依赖 -->
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

遇到问题:只引入spring-cloud-starter-openfeign,不引入spring-cloud-starter-loadbalancer,测试时控制台报错

原因:在Spring Cloud项目中仅引入spring-cloud-starter-openfeign而未添加spring-cloud-starter-loadbalancer时,控制台会报错No Feign Client for loadBalancing defined,这是因为自Spring Cloud Hoxton.M2版本后,Feign默认移除了Ribbon依赖,转而使用spring-cloud-loadbalancer实现客户端负载均衡。

创建包,创建DeptClient接口

package com.he.client;

import com.he.pojo.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient("deptservice")
public interface DeptClient {
    @GetMapping("/depts/{id}")
    Result queryDeptSimpleById(@PathVariable Integer id);
}

编辑

操作dept-service模块

修改pom文件引入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.he</groupId>
        <artifactId>kawa-cloud</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>dept-service</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!--mysql-->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--common-pojo-->
        <dependency>
            <groupId>com.he</groupId>
            <artifactId>common-pojo</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--common-utils-->
        <dependency>
            <groupId>com.he</groupId>
            <artifactId>common-utils</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--nacos客户端-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--feign-api-->
        <dependency>
            <groupId>com.he</groupId>
            <artifactId>feign-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

编辑

修改application.yml配置文件

server:
  port: 8091
spring:
  application:
    name: deptservice
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/deptdatabase
    username: root
    password: 123456
  cloud:
    nacos:
      server-addr: localhost:8848
      # Nacos 服务器启用了认证
      username: nacos  # 默认用户名
      password: nacos  # 默认密码
      discovery:
        cluster-name: SZ # 集群名称
        ephemeral: true # 配置是否注册为临时服务,默认是true即临时服务
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true # 开启驼峰命名
logging:
  level:
    com.he: debug
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS

编辑

操作emp-service模块

修改pom文件引入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.he</groupId>
        <artifactId>kawa-cloud</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>emp-service</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!--mysql-->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--common-pojo-->
        <dependency>
            <groupId>com.he</groupId>
            <artifactId>common-pojo</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--common-utils-->
        <dependency>
            <groupId>com.he</groupId>
            <artifactId>common-utils</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--nacos客户端-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--feign-api-->
        <dependency>
            <groupId>com.he</groupId>
            <artifactId>feign-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

编辑

修改application.yml配置文件

server:
  port: 8081
spring:
  application:
    name: empservice
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/empdatabase
    username: root
    password: 123456
  cloud:
    nacos:
      server-addr: localhost:8848
      # Nacos 服务器启用了认证
      username: nacos  # 默认用户名
      password: nacos  # 默认密码
      discovery:
        cluster-name: SZ # 集群名称
        ephemeral: true # 配置是否注册为临时服务,默认是true即临时服务
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true # 开启驼峰命名
logging:
  level:
    com.he: debug
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS
feign:
  client:
    config:
      default: # default全局的配置
        loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
  httpclient:
    enabled: true # 开启feign对HttpClient的支持
    max-connections: 200 # 最大的连接数
    max-connections-per-route: 50 # 每个路径的最大连接数
deptservice:
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则
ribbon:
  eager-load:
    enabled: true # 开启饥饿加载,默认是false即懒加载
    clients: deptservice

编辑

修改EmpApplication启动类

@SpringBootApplication
@EnableFeignClients(clients = {DeptClient.class})
public class EmpApplication {
    public static void main(String[] args) {
        SpringApplication.run(EmpApplication.class, args);
    }
}

编辑

修改EmpServiceImpl类

@Service
public class EmpServiceImpl extends ServiceImpl<EmpMapper, Emp> implements EmpService {
    @Autowired
    ObjectMapper objectMapper;

    @Autowired
    EmpMapper empMapper;

    @Autowired
    private DeptClient deptClient;

    // 根据信息分页查询
    @Cacheable(cacheNames = "empsList",key = "#empSearchDto.hashCode()" )
    public PageBean queryByInfo(EmpSearchDto empSearchDto) {
        // 创建查询条件
        LambdaQueryWrapper<Emp> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.like(StringUtils.hasLength(empSearchDto.getName()),Emp::getName, empSearchDto.getName())
                .eq(empSearchDto.getGender()!=null,Emp::getGender, empSearchDto.getGender())
                .ge(empSearchDto.getBegin()!=null,Emp::getEntryDate, empSearchDto.getBegin())
                .le(empSearchDto.getEnd()!=null,Emp::getEntryDate, empSearchDto.getEnd());
        // 创建分页条件
        if (empSearchDto.getPage() == null) {
            empSearchDto.setPage(1);
        }
        if (empSearchDto.getPageSize() == null) {
            empSearchDto.setPageSize(5);
        }
        Page<Emp> pageInfo = new Page<>(empSearchDto.getPage(), empSearchDto.getPageSize());
        // 执行查询
        Page<Emp> empPage = empMapper.selectPage(pageInfo, queryWrapper);
        // 为每个员工获取对应的部门信息
        List<Emp> empList = empPage.getRecords().stream().map(emp -> {
            // 调用Feign客户端获取部门信息
            Result deptResult = deptClient.queryDeptSimpleById(emp.getDeptId());
            if (deptResult.getCode() == 1) {
                // 假设员工实体中有部门名称字段 手动转换为部门实体
                Object data = deptResult.getData();
                DeptSimpleDto dept = objectMapper.convertValue(data, DeptSimpleDto.class);
                emp.setDeptSimple(dept);
            }
            return emp;
        }).collect(Collectors.toList());
        // 封装数据
        PageBean pageBean = new PageBean(empPage.getTotal(), empList);
        // 返回数据
        return pageBean;
    }
}

编辑

启动测试

启动nacos

编辑

startup.cmd -m standalone

编辑

编辑

访问nacos

编辑

编辑

启动dept-service

编辑

启动emp-service

编辑

访问nacos

编辑

测试分页查询员工

编辑

编辑

编辑

操作emp-service模块

修改EmpService接口

public interface EmpService extends IService<Emp> {
    // 根据信息分页查询
    PageBean queryByInfo(EmpSearchDto empSearchDto);
    // 根据部门ID获取所有符合的员工信息
    List<Emp> queryByDeptId(Integer deptId);
}

编辑

修改EmpServiceImpl类

@Service
public class EmpServiceImpl extends ServiceImpl<EmpMapper, Emp> implements EmpService {
    @Autowired
    ObjectMapper objectMapper;

    @Autowired
    EmpMapper empMapper;

    @Autowired
    private DeptClient deptClient;

    // 根据信息分页查询
    @Cacheable(cacheNames = "empsList",key = "#empSearchDto.hashCode()" )
    public PageBean queryByInfo(EmpSearchDto empSearchDto) {
        // 创建查询条件
        LambdaQueryWrapper<Emp> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.like(StringUtils.hasLength(empSearchDto.getName()),Emp::getName, empSearchDto.getName())
                .eq(empSearchDto.getGender()!=null,Emp::getGender, empSearchDto.getGender())
                .ge(empSearchDto.getBegin()!=null,Emp::getEntryDate, empSearchDto.getBegin())
                .le(empSearchDto.getEnd()!=null,Emp::getEntryDate, empSearchDto.getEnd());
        // 创建分页条件
        if (empSearchDto.getPage() == null) {
            empSearchDto.setPage(1);
        }
        if (empSearchDto.getPageSize() == null) {
            empSearchDto.setPageSize(5);
        }
        Page<Emp> pageInfo = new Page<>(empSearchDto.getPage(), empSearchDto.getPageSize());
        // 执行查询
        Page<Emp> empPage = empMapper.selectPage(pageInfo, queryWrapper);
        // 为每个员工获取对应的部门信息
        List<Emp> empList = empPage.getRecords().stream().map(emp -> {
            // 调用Feign客户端获取部门信息
            Result deptResult = deptClient.queryDeptSimpleById(emp.getDeptId());
            if (deptResult.getCode() == 1) {
                // 假设员工实体中有部门名称字段 手动转换为部门实体
                Object data = deptResult.getData();
                DeptSimpleDto dept = objectMapper.convertValue(data, DeptSimpleDto.class);
                emp.setDeptSimple(dept);
            }
            return emp;
        }).collect(Collectors.toList());
        // 封装数据
        PageBean pageBean = new PageBean(empPage.getTotal(), empList);
        // 返回数据
        return pageBean;
    }

    // 根据部门ID获取所有符合的员工信息
    @Override
    public List<Emp> queryByDeptId(Integer deptId) {
        // 创建查询条件
        LambdaQueryWrapper<Emp> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(Emp::getDeptId, deptId);
        // 执行查询
        List<Emp> empList = empMapper.selectList(queryWrapper);
        // 返回数据
        return empList;
    }
}

编辑

修改EmpController类

@Slf4j
@RestController
@RequestMapping("/emps")
public class EmpController {
    @Autowired
    EmpService empService;

    @GetMapping
    public Result queryByInfo(@ModelAttribute EmpSearchDto empSearchDto){
        log.info("查询员工信息,参数:empDto={}", empSearchDto);
        PageBean pageBean = empService.queryByInfo(empSearchDto);
        return pageBean!=null?Result.success(pageBean):Result.error("查询失败!");
    }

    @GetMapping("/dept/{id}")
    public Result queryByDeptId(@PathVariable Integer id){
        log.info("根据部门ID:{}查询员工信息",id);
        List<Emp> empList = empService.queryByDeptId(id);
        return empList!=null?Result.success(empList):Result.error("查询失败!");
    }
}

编辑

操作feign-api模块

创建EmpClient接口

@FeignClient("empservice")
public interface EmpClient {
    @GetMapping("/emps/dept/{id}")
    Result querySimpleByDeptId(@PathVariable Integer id);
}

编辑

操作dept-service模块

修改application.yml配置文件

server:
  port: 8091
spring:
  application:
    name: deptservice
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/deptdatabase
    username: root
    password: 123456
  cloud:
    nacos:
      server-addr: localhost:8848
      # Nacos 服务器启用了认证
      username: nacos  # 默认用户名
      password: nacos  # 默认密码
      discovery:
        cluster-name: SZ # 集群名称
        ephemeral: true # 配置是否注册为临时服务,默认是true即临时服务
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true # 开启驼峰命名
logging:
  level:
    com.he: debug
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS
feign:
  client:
    config:
      default: # default全局的配置
        loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
  httpclient:
    enabled: true # 开启feign对HttpClient的支持
    max-connections: 200 # 最大的连接数
    max-connections-per-route: 50 # 每个路径的最大连接数
empservice:
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则
ribbon:
  eager-load:
    enabled: true # 开启饥饿加载,默认是false即懒加载
    clients: empservice

编辑

修改DeptApplication启动类

@SpringBootApplication
@EnableFeignClients(clients = {EmpClient.class})
public class DeptApplication {
    public static void main(String[] args) {
        SpringApplication.run(DeptApplication.class, args);
    }
}

编辑

修改DeptServiceImpl类

@Service
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements DeptService {
    @Autowired
    ObjectMapper objectMapper;

    @Autowired
    DeptMapper deptMapper;

    @Autowired
    EmpClient empClient;

    // 根据部门Id获取部门信息
    @Override
    public Dept queryById(Integer id) {
        Dept dept = deptMapper.selectById(id);
        Result result = empClient.querySimpleByDeptId(id);
        if (result.getCode()==1){
            Object data = result.getData();
            List<EmpSimpleDto> list = objectMapper.convertValue(data, new TypeReference<List<EmpSimpleDto>>() {});
            dept.setEmpsSimple(list); // 设置简单员工列表
        }
        return dept;
    }
}

启动测试

启动dept-service

编辑

启动emp-service

编辑

测试根据ID查询部门信息

编辑

完善emp-service模块增删改查功能

修改EmpService接口

public interface EmpService extends IService<Emp> {
    // 根据信息分页查询
    PageBean queryByInfo(EmpSearchDto empSearchDto);
    // 根据部门ID获取所有符合的员工信息
    List<Emp> queryByDeptId(Integer deptId);
    // 根据员工ID获取员工信息
    Emp queryById(Integer id);
    // 添加员工信息
    Integer addEmp(Emp emp);
    // 修改员工信息
    Integer updateEmp(Emp emp);
    // 删除员工信息
    Integer deleteEmp(Integer id);
}

编辑

修改EmpServiceImpl类

@Service
public class EmpServiceImpl extends ServiceImpl<EmpMapper, Emp> implements EmpService {
    @Autowired
    ObjectMapper objectMapper;

    @Autowired
    EmpMapper empMapper;

    @Autowired
    private DeptClient deptClient;

    // 根据信息分页查询
    public PageBean queryByInfo(EmpSearchDto empSearchDto) {
        // 创建查询条件
        LambdaQueryWrapper<Emp> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.like(StringUtils.hasLength(empSearchDto.getName()),Emp::getName, empSearchDto.getName())
                .eq(empSearchDto.getGender()!=null,Emp::getGender, empSearchDto.getGender())
                .ge(empSearchDto.getBegin()!=null,Emp::getEntryDate, empSearchDto.getBegin())
                .le(empSearchDto.getEnd()!=null,Emp::getEntryDate, empSearchDto.getEnd());
        // 创建分页条件
        if (empSearchDto.getPage() == null) {
            empSearchDto.setPage(1);
        }
        if (empSearchDto.getPageSize() == null) {
            empSearchDto.setPageSize(5);
        }
        Page<Emp> pageInfo = new Page<>(empSearchDto.getPage(), empSearchDto.getPageSize());
        // 执行查询
        Page<Emp> empPage = empMapper.selectPage(pageInfo, queryWrapper);
        // 为每个员工获取对应的部门信息
        List<Emp> empList = empPage.getRecords().stream().map(emp -> {
            // 调用Feign客户端获取部门信息
            Result deptResult = deptClient.queryDeptSimpleById(emp.getDeptId());
            if (deptResult.getCode() == 1) {
                // 假设员工实体中有部门名称字段 手动转换为部门实体
                Object data = deptResult.getData();
                DeptSimpleDto dept = objectMapper.convertValue(data, DeptSimpleDto.class);
                emp.setDeptSimple(dept);
            }
            return emp;
        }).collect(Collectors.toList());
        // 封装数据
        PageBean pageBean = new PageBean(empPage.getTotal(), empList);
        // 返回数据
        return pageBean;
    }

    // 根据部门ID获取所有符合的员工信息
    @Override
    public List<Emp> queryByDeptId(Integer deptId) {
        // 创建查询条件
        LambdaQueryWrapper<Emp> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(Emp::getDeptId, deptId);
        // 执行查询
        List<Emp> empList = empMapper.selectList(queryWrapper);
        // 返回数据
        return empList;
    }

    // 根据员工ID获取员工信息
    @Override
    public Emp queryById(Integer id) {
        Emp emp = empMapper.selectById(id);
        return emp;
    }

    // 添加员工
    @Override
    public Integer addEmp(Emp emp) {
        if (emp.getName() == null || emp.getUsername() == null|| emp.getGender() == null){
            return 0;
        }
        emp.setCreateTime(LocalDateTime.now());
        emp.setUpdateTime(LocalDateTime.now());
        emp.setEntryDate(LocalDate.now());
        emp.setPassword("123456");
        int i = empMapper.insert(emp);
        return i;
    }

    // 修改员工
    @Override
    public Integer updateEmp(Emp emp) {
        if (emp.getId() == null){
            return 0;
        }
        emp.setUpdateTime(LocalDateTime.now());
        int i = empMapper.updateById(emp);
        return i;
    }

    // 删除员工
    @Override
    public Integer deleteEmp(Integer id) {
        int i = empMapper.deleteById(id);
        return i;
    }

}

编辑

修改EmpController类

@Slf4j
@RestController
@RequestMapping("/emps")
public class EmpController {
    @Autowired
    EmpService empService;

    @GetMapping
    public Result queryByInfo(@ModelAttribute EmpSearchDto empSearchDto){
        log.info("查询员工信息,参数:empDto={}", empSearchDto);
        PageBean pageBean = empService.queryByInfo(empSearchDto);
        return pageBean!=null?Result.success(pageBean):Result.error("查询失败!");
    }

    @GetMapping("/dept/{id}")
    public Result queryByDeptId(@PathVariable Integer id){
        log.info("根据部门ID:{}查询员工信息",id);
        List<Emp> empList = empService.queryByDeptId(id);
        return empList!=null?Result.success(empList):Result.error("查询失败!");
    }

    @GetMapping("/{id}")
    public Result queryById(@PathVariable Integer id){
        log.info("根据员工ID:{}查询员工信息",id);
        Emp emp = empService.queryById(id);
        return emp!=null?Result.success(emp):Result.error("查询失败!");
    }

    @PostMapping
    public Result addEmp(@RequestBody Emp emp){
        log.info("添加员工,参数:emp={}", emp);
        Integer addEmp = empService.addEmp(emp);
        return addEmp>0?Result.success("添加成功!"):Result.error("添加失败!");
    }

    @PutMapping
    public Result updateEmp(@RequestBody Emp emp){
        log.info("修改员工,参数:emp={}", emp);
        Integer updateEmp = empService.updateEmp(emp);
        return updateEmp>0?Result.success("修改成功!"):Result.error("修改失败!");
    }

    @DeleteMapping("/{id}")
    public Result deleteEmp(@PathVariable Integer id){
        log.info("删除员工,参数:id={}", id);
        Integer deleteEmp = empService.deleteEmp(id);
        return deleteEmp>0?Result.success("删除成功!"):Result.error("删除失败!");
    }
}

编辑

完善dept-service模块增删改查功能

修改DeptServicze接口

package com.he.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.he.pojo.Dept;

import java.util.List;

public interface DeptService extends IService<Dept> {
    // 查询所有部门信息
    List<Dept> queryAll();
    // 根据部门ID查询部门信息
    Dept queryById(Integer id);
    // 添加部门
    Integer addDept(Dept dept);
    // 修改部门信息
    Integer updateDept(Dept dept);
    // 删除部门
    Integer deleteDept(Integer id);
}

编辑

修改DeptServiczeImpl类

@Service
public class DeptServiczeImpl extends ServiceImpl<DeptMapper, Dept> implements DeptService {
    @Autowired
    ObjectMapper objectMapper;

    @Autowired
    DeptMapper deptMapper;

    @Autowired
    EmpClient empClient;

    // 查询所有部门
    @Override
    public List<Dept> queryAll() {
        List<Dept> depts = deptMapper.selectList(null);
        return depts;
    }

    // 根据部门Id获取部门信息
    @Override
    public Dept queryById(Integer id) {
        Dept dept = deptMapper.selectById(id);
        Result result = empClient.querySimpleByDeptId(id);
        if (result.getCode()==1){
            Object data = result.getData();
            List<EmpSimpleDto> list = objectMapper.convertValue(data, new TypeReference<List<EmpSimpleDto>>() {});
            dept.setEmpsSimple(list); // 设置简单员工列表
        }
        return dept;
    }

    // 添加部门
    @Override
    public Integer addDept(Dept dept) {
        dept.setCreateTime(LocalDateTime.now());
        dept.setUpdateTime(LocalDateTime.now());
        int i = deptMapper.insert(dept);
        return i;
    }

    // 修改部门
    @Override
    public Integer updateDept(Dept dept) {
        if (dept.getId()==null){
            return 0;
        }
        dept.setUpdateTime(LocalDateTime.now());
        int i = deptMapper.updateById(dept);
        return i;
    }

    // 删除部门
    @Override
    public Integer deleteDept(Integer id) {
        Result result = empClient.querySimpleByDeptId(id);
        if (result.getCode()==1){
            Object data = result.getData();
            List<EmpSimpleDto> list = objectMapper.convertValue(data, new TypeReference<List<EmpSimpleDto>>() {});
            if (list.size()>0){
                throw new RuntimeException("该部门下有员工,不能删除");
            }
        }
        int i = deptMapper.deleteById(id);
        return i;
    }
}

编辑

修改DeptController类

@Slf4j
@RestController
@RequestMapping("/depts")
public class DeptController {
    @Autowired
    DeptService deptService;

    // 查询所有部门信息
    @GetMapping
    public Result queryAll() {
        log.info("查询所有部门信息");
        List<Dept> list = deptService.queryAll();
        return list != null ? Result.success(list) : Result.error();
    }

    // 根据部门ID获取部门信息
    @GetMapping("/{id}")
    public Result queryById(@PathVariable Integer id) {
        log.info("根据部门ID:{}查询部门信息", id);
        Dept dept = deptService.queryById(id);
        return dept != null ? Result.success(dept): Result.error();
    }

    // 添加部门
    @PostMapping
    public Result addDept(@RequestBody Dept dept) {
        log.info("添加部门:{}", dept);
        Integer i = deptService.addDept(dept);
        return i>0 ? Result.success() : Result.error();
    }

    // 修改部门
    @PutMapping
    public Result updateDept(@RequestBody Dept dept) {
        log.info("修改部门:{}", dept);
        Integer i = deptService.updateDept(dept);
        return i>0 ? Result.success() : Result.error();
    }

    // 删除部门
    @DeleteMapping("/{id}")
    public Result deleteDept(@PathVariable Integer id) {
        log.info("删除部门ID:{}", id);
        Integer i = deptService.deleteDept(id);
        return i>0 ? Result.success() : Result.error();
    }
}

编辑

配置全局异常处理

修改common-utils模块pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.he</groupId>
        <artifactId>kawa-cloud</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>common-utils</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!--common-pojo-->
        <dependency>
            <groupId>com.he</groupId>
            <artifactId>common-pojo</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

编辑

创建包,创建GlobalExceptionHandle类

package com.he.exception;

import com.he.pojo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandle {
    @ExceptionHandler(Exception.class)
    public Result handleException(Exception e) {
        // 收到异常之后,做的事?
        e.printStackTrace(); // 打印异常信息
        log.error("全局异常处理:{}",e.getMessage());
        return Result.error(e.getMessage());
    }
}

编辑

配置Redis缓存

修改父工程pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.he</groupId>
    <artifactId>kawa-cloud</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>emp-service</module>
        <module>dept-service</module>
        <module>common-pojo</module>
        <module>feign-api</module>
        <module>common-utils</module>
    </modules>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.13</version>
        <relativePath/>
    </parent>

    <properties>
        <java.version>17</java.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-boot-starter-web.version>3.3.13</spring-boot-starter-web.version>
        <mybatis-plus.version>3.5.7</mybatis-plus.version>
        <mysql.version>8.0.33</mysql.version>
        <lombok.version>1.18.22</lombok.version>
        <spring-cloud.version>2023.0.1</spring-cloud.version>
        <spring-cloud-alibaba-version>2023.0.1.0</spring-cloud-alibaba-version>
        <spring-boot-starter-data-redis.version>3.3.13</spring-boot-starter-data-redis.version>
        <spring-boot-starter-cache.version>3.3.13</spring-boot-starter-cache.version>
    </properties>

    <!--  引入共有的依赖  -->
    <dependencies>
        <!--springboot-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot-starter-web.version}</version>
        </dependency>
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>
    </dependencies>

    <!-- 管理依赖版本  -->
    <dependencyManagement>
        <dependencies>
            <!--mysql-->
            <dependency>
                <groupId>com.mysql</groupId>
                <artifactId>mysql-connector-j</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <!--lombok-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>
            <!-- springCloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--nacos-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba-version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--redis-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
                <version>${spring-boot-starter-data-redis.version}</version>
            </dependency>
            <!--spring-cache-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-cache</artifactId>
                <version>${spring-boot-starter-cache.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

编辑

遇到问题:只引入spring-boot-starter-cache,不引入spring-boot-starter-data-redis,数据不会存在redis中

原因:Spring Boot会默认使用基于内存的ConcurrentMapCacheManager作为缓存管理器,数据不会存储到Redis中,必须显式引入spring-boot-starter-data-redis依赖,并配置Redis连接信息时Spring Boot会自动检测到Redis依赖,并将缓存管理器替换为RedisCacheManager

修改common-utils模块pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.he</groupId>
        <artifactId>kawa-cloud</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>common-utils</artifactId>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!--common-pojo-->
        <dependency>
            <groupId>com.he</groupId>
            <artifactId>common-pojo</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--spring-cache-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
    </dependencies>
</project>

编辑

common-utils模块创建RedisConfiguration配置类

@Configuration
public class RedisConfiguration {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
        // 使用StringRedisSerializer
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // 使用Jackson序列化器
        GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer();
        // 创建RedisTemplate对象
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        // 设置连接工厂
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // 设置redis的key序列化器
        redisTemplate.setKeySerializer(stringRedisSerializer);
        // 设置redis的value序列化器
        redisTemplate.setValueSerializer(serializer);
        // 设置redis的hashKey序列化器
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        // 添加redis的hashValue序列化器
        redisTemplate.setHashValueSerializer(serializer);
        // 返回
        return redisTemplate;
    }
}

编辑

完善emp-service模块redis缓存

修改application.yml配置文件
server:
  port: 8081
spring:
  application:
    name: empservice
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/empdatabase
    username: root
    password: 123456
  cloud:
    nacos:
      server-addr: localhost:8848
      # Nacos 服务器启用了认证
      username: nacos  # 默认用户名
      password: nacos  # 默认密码
      discovery:
        cluster-name: SZ # 集群名称
        ephemeral: true # 配置是否注册为临时服务,默认是true即临时服务
  data:
    redis:
      host: localhost
      port: 6379
      password: ""
      database: 0
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true # 开启驼峰命名
logging:
  level:
    com.he: debug
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS
feign:
  client:
    config:
      default: # default全局的配置
        loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
  httpclient:
    enabled: true # 开启feign对HttpClient的支持
    max-connections: 200 # 最大的连接数
    max-connections-per-route: 50 # 每个路径的最大连接数
deptservice:
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则
ribbon:
  eager-load:
    enabled: true # 开启饥饿加载,默认是false即懒加载
    clients: deptservice

编辑

修改EmpApplication启动类
@SpringBootApplication
@EnableCaching
@EnableFeignClients(clients = {DeptClient.class})
public class EmpApplication {
    public static void main(String[] args) {
        SpringApplication.run(EmpApplication.class, args);
    }
}

编辑

修改EmpServiceImpl类
@Service
public class EmpServiceImpl extends ServiceImpl<EmpMapper, Emp> implements EmpService {
    @Autowired
    ObjectMapper objectMapper;

    @Autowired
    EmpMapper empMapper;

    @Autowired
    private DeptClient deptClient;

    // 根据信息分页查询
    @Cacheable(cacheNames = "empsList",key = "#empSearchDto.hashCode()" )
    public PageBean queryByInfo(EmpSearchDto empSearchDto) {
        // 创建查询条件
        LambdaQueryWrapper<Emp> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.like(StringUtils.hasLength(empSearchDto.getName()),Emp::getName, empSearchDto.getName())
                .eq(empSearchDto.getGender()!=null,Emp::getGender, empSearchDto.getGender())
                .ge(empSearchDto.getBegin()!=null,Emp::getEntryDate, empSearchDto.getBegin())
                .le(empSearchDto.getEnd()!=null,Emp::getEntryDate, empSearchDto.getEnd());
        // 创建分页条件
        if (empSearchDto.getPage() == null) {
            empSearchDto.setPage(1);
        }
        if (empSearchDto.getPageSize() == null) {
            empSearchDto.setPageSize(5);
        }
        Page<Emp> pageInfo = new Page<>(empSearchDto.getPage(), empSearchDto.getPageSize());
        // 执行查询
        Page<Emp> empPage = empMapper.selectPage(pageInfo, queryWrapper);
        // 为每个员工获取对应的部门信息
        List<Emp> empList = empPage.getRecords().stream().map(emp -> {
            // 调用Feign客户端获取部门信息
            Result deptResult = deptClient.queryDeptSimpleById(emp.getDeptId());
            if (deptResult.getCode() == 1) {
                // 假设员工实体中有部门名称字段 手动转换为部门实体
                Object data = deptResult.getData();
                DeptSimpleDto dept = objectMapper.convertValue(data, DeptSimpleDto.class);
                emp.setDeptSimple(dept);
            }
            return emp;
        }).collect(Collectors.toList());
        // 封装数据
        PageBean pageBean = new PageBean(empPage.getTotal(), empList);
        // 返回数据
        return pageBean;
    }

    // 根据部门ID获取所有符合的员工信息
    @Override
    public List<Emp> queryByDeptId(Integer deptId) {
        // 创建查询条件
        LambdaQueryWrapper<Emp> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(Emp::getDeptId, deptId);
        // 执行查询
        List<Emp> empList = empMapper.selectList(queryWrapper);
        // 返回数据
        return empList;
    }

    // 根据员工ID获取员工信息
    @Override
    @Cacheable(cacheNames = "emps",key = "#id")
    public Emp queryById(Integer id) {
        Emp emp = empMapper.selectById(id);
        return emp;
    }

    // 添加员工
    @Override
    @CacheEvict(cacheNames = "empsList",allEntries = true)
    public Integer addEmp(Emp emp) {
        if (emp.getName() == null || emp.getUsername() == null|| emp.getGender() == null){
            return 0;
        }
        emp.setCreateTime(LocalDateTime.now());
        emp.setUpdateTime(LocalDateTime.now());
        emp.setEntryDate(LocalDate.now());
        emp.setPassword("123456");
        int i = empMapper.insert(emp);
        return i;
    }

    // 修改员工
    @Override
    @Caching(evict = {@CacheEvict(cacheNames = "emps", key = "#emp.id"),@CacheEvict(cacheNames = "empsList",allEntries = true)})
    public Integer updateEmp(Emp emp) {
        if (emp.getId() == null){
            return 0;
        }
        emp.setUpdateTime(LocalDateTime.now());
        int i = empMapper.updateById(emp);
        return i;
    }

    // 删除员工
    @Override
    @Caching(evict = {@CacheEvict(cacheNames = "emps", key = "#id"),@CacheEvict(cacheNames = "empsList",allEntries = true)})
    public Integer deleteEmp(Integer id) {
        int i = empMapper.deleteById(id);
        return i;
    }

}

编辑

完善dept-service模块redis缓存

修改application.yml配置文件
server:
  port: 8091
spring:
  application:
    name: deptservice
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/deptdatabase
    username: root
    password: 123456
  cloud:
    nacos:
      server-addr: localhost:8848
      # Nacos 服务器启用了认证
      username: nacos  # 默认用户名
      password: nacos  # 默认密码
      discovery:
        cluster-name: SZ # 集群名称
        ephemeral: true # 配置是否注册为临时服务,默认是true即临时服务
  data:
    redis:
      host: localhost
      port: 6379
      password: ""
      database: 0
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true # 开启驼峰命名
logging:
  level:
    com.he: debug
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS
feign:
  client:
    config:
      default: # default全局的配置
        loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
  httpclient:
    enabled: true # 开启feign对HttpClient的支持
    max-connections: 200 # 最大的连接数
    max-connections-per-route: 50 # 每个路径的最大连接数
empservice:
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则
ribbon:
  eager-load:
    enabled: true # 开启饥饿加载,默认是false即懒加载
    clients: empservice

编辑

修改DeptApplication启动类
@SpringBootApplication
@EnableCaching
@EnableFeignClients(clients = {EmpClient.class})
public class DeptApplication {
    public static void main(String[] args) {
        SpringApplication.run(DeptApplication.class, args);
    }
}

编辑

修改DeptServiceImpl类
@Service
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements DeptService {
    @Autowired
    ObjectMapper objectMapper;

    @Autowired
    DeptMapper deptMapper;

    @Autowired
    EmpClient empClient;

    // 查询所有部门
    @Override
    @Cacheable(cacheNames = "depts", key = "'deptsList'")
    public List<Dept> queryAll() {
        List<Dept> depts = deptMapper.selectList(null);
        return depts;
    }

    // 根据部门Id获取部门信息
    @Override
    @Cacheable(cacheNames = "depts", key = "#id")
    public Dept queryById(Integer id) {
        Dept dept = deptMapper.selectById(id);
        Result result = empClient.querySimpleByDeptId(id);
        if (result.getCode()==1){
            Object data = result.getData();
            List<EmpSimpleDto> list = objectMapper.convertValue(data, new TypeReference<List<EmpSimpleDto>>() {});
            dept.setEmpsSimple(list); // 设置简单员工列表
        }
        return dept;
    }

    // 添加部门
    @Override
    @CacheEvict(cacheNames = "depts",key = "'deptsList'")
    public Integer addDept(Dept dept) {
        dept.setCreateTime(LocalDateTime.now());
        dept.setUpdateTime(LocalDateTime.now());
        int i = deptMapper.insert(dept);
        return i;
    }

    // 修改部门
    @Override
    @Caching(evict = {@CacheEvict(cacheNames = "depts", key = "#dept.id"),@CacheEvict(cacheNames = "depts",key = "'deptsList'")})
    public Integer updateDept(Dept dept) {
        if (dept.getId()==null){
            return 0;
        }
        dept.setUpdateTime(LocalDateTime.now());
        int i = deptMapper.updateById(dept);
        return i;
    }

    // 删除部门
    @Override
    @Caching(evict = {@CacheEvict(cacheNames = "depts", key = "#id"),@CacheEvict(cacheNames = "depts",key = "'deptsList'")})
    public Integer deleteDept(Integer id) {
        Result result = empClient.querySimpleByDeptId(id);
        if (result.getCode()==1){
            Object data = result.getData();
            List<EmpSimpleDto> list = objectMapper.convertValue(data, new TypeReference<List<EmpSimpleDto>>() {});
            if (list.size()>0){
                throw new RuntimeException("该部门下有员工,不能删除");
            }
        }
        int i = deptMapper.deleteById(id);
        return i;
    }
}

编辑

提交至Gitee

初始化本地仓库

编辑

添加远程仓库

编辑

编辑

本地提交

编辑

推送至远端仓库

编辑

编辑

源码:gitee.com/banana911/k… 

数据库sql:

drop table if EXISTS dept;
CREATE TABLE dept (
  id int unsigned PRIMARY KEY AUTO_INCREMENT COMMENT 'ID, 主键',
  name varchar(10) NOT NULL UNIQUE COMMENT '部门名称',
  create_time datetime DEFAULT NULL COMMENT '创建时间',
  update_time datetime DEFAULT NULL COMMENT '修改时间'
) COMMENT '部门表';

INSERT INTO dept VALUES (1,'学工部','2023-09-25 09:47:40','2023-09-25 09:47:40'),
						  (2,'教研部','2023-09-25 09:47:40','2023-10-09 15:17:04'),
						  (3,'咨询部','2023-09-25 09:47:40','2023-11-30 21:26:24'),
						  (4,'就业部','2023-09-25 09:47:40','2023-09-25 09:47:40'),
						  (5,'人事部','2023-09-25 09:47:40','2023-09-25 09:47:40'),
						  (15,'行政部','2023-11-30 20:56:37','2023-11-30 20:56:37'),
              (6,'财务部','2023-12-01 08:30:15','2023-12-01 08:30:15'),
              (7,'市场部','2023-12-05 14:22:10','2024-01-10 11:05:33'),
              (8,'技术部','2023-12-10 09:15:45','2024-02-15 16:40:22'),
              (9,'客服部','2023-12-15 10:20:30','2023-12-15 10:20:30'),
              (10,'采购部','2023-12-20 13:45:00','2024-03-05 09:30:18'),
              (11,'法务部','2024-01-05 15:10:25','2024-01-05 15:10:25'),
              (12,'品牌部','2024-01-10 11:35:40','2024-04-20 14:25:10'),
              (13,'国际部','2024-01-15 16:50:55','2024-01-15 16:50:55'),
              (14,'研发中心','2024-02-01 09:25:30','2024-05-15 10:45:12'),
              (16,'质量部','2024-02-10 14:15:20','2024-02-10 14:15:20');


drop table if EXISTS emp;
create table emp(
    id int unsigned primary key auto_increment comment 'ID,主键',
    username varchar(20) not null unique comment '用户名',
    password varchar(50) default '123456' comment '密码',
    name varchar(10) not null comment '姓名',
    gender tinyint unsigned not null comment '性别, 1:男, 2:女',
    phone char(11) not null unique comment '手机号',
    job tinyint unsigned comment '职位, 1 班主任, 2 讲师 , 3 学工主管, 4 教研主管, 5 咨询师',
    salary int unsigned comment '薪资',
    image varchar(300) comment '头像',
    entry_date date comment '入职日期',
    dept_id int unsigned comment '部门ID',
    create_time datetime comment '创建时间',
    update_time datetime comment '修改时间'
) comment '员工表';
INSERT INTO emp VALUES 
(1,'shinaian','123456','施耐庵',1,'13309090001',4,15000,'5.png','2000-01-01',2,'2023-10-20 16:35:33','2023-11-16 16:11:26'),
(2,'songjiang','123456','宋江',1,'13309090002',2,8600,'01.png','2015-01-01',2,'2023-10-20 16:35:33','2023-10-20 16:35:37'),
(3,'lujunyi','123456','卢俊义',1,'13309090003',2,8900,'01.png','2008-05-01',2,'2023-10-20 16:35:33','2023-10-20 16:35:39'),
(4,'wuyong','123456','吴用',1,'13309090004',2,9200,'01.png','2007-01-01',2,'2023-10-20 16:35:33','2023-10-20 16:35:41'),
(5,'gongsunsheng','123456','公孙胜',1,'13309090005',2,9500,'01.png','2012-12-05',2,'2023-10-20 16:35:33','2023-10-20 16:35:43'),
(6,'huosanniang','123456','扈三娘',2,'13309090006',3,6500,'01.png','2013-09-05',1,'2023-10-20 16:35:33','2023-10-20 16:35:45'),
(7,'chaijin','123456','柴进',1,'13309090007',1,4700,'01.png','2005-08-01',1,'2023-10-20 16:35:33','2023-10-20 16:35:47'),
(8,'likui','123456','李逵',1,'13309090008',1,4800,'01.png','2014-11-09',1,'2023-10-20 16:35:33','2023-10-20 16:35:49'),
(9,'wusong','123456','武松',1,'13309090009',1,4900,'01.png','2011-03-11',1,'2023-10-20 16:35:33','2023-10-20 16:35:51'),
(10,'linchong','123456','林冲',1,'13309090010',1,5000,'01.png','2013-09-05',1,'2023-10-20 16:35:33','2023-10-20 16:35:53'),
(11,'huyanzhuo','123456','呼延灼',1,'13309090011',2,9700,'01.png','2007-02-01',2,'2023-10-20 16:35:33','2023-10-20 16:35:55'),
(12,'xiaoliguang','123456','小李广',1,'13309090012',2,10000,'01.png','2008-08-18',2,'2023-10-20 16:35:33','2023-10-20 16:35:57'),
(13,'yangzhi','123456','杨志',1,'13309090013',1,5300,'01.png','2012-11-01',1,'2023-10-20 16:35:33','2023-10-20 16:35:59'),
(14,'shijin','123456','史进',1,'13309090014',2,10600,'01.png','2002-08-01',2,'2023-10-20 16:35:33','2023-10-20 16:36:01'),
(15,'sunerniang','123456','孙二娘',2,'13309090015',2,10900,'01.png','2011-05-01',2,'2023-10-20 16:35:33','2023-10-20 16:36:03'),
(16,'luzhishen','123456','鲁智深',1,'13309090016',2,9600,'01.png','2010-01-01',2,'2023-10-20 16:35:33','2023-10-20 16:36:05'),
(17,'liying','12345678','李应',1,'13309090017',1,5800,'01.png','2015-03-21',1,'2023-10-20 16:35:33','2023-10-20 16:36:07'),
(18,'shiqian','123456','时迁',1,'13309090018',2,10200,'01.png','2015-01-01',2,'2023-10-20 16:35:33','2023-10-20 16:36:09'),
(19,'gudasao','123456','顾大嫂',2,'13309090019',2,10500,'01.png','2008-01-01',2,'2023-10-20 16:35:33','2023-10-20 16:36:11'),
(20,'ruanxiaoer','123456','阮小二',1,'13309090020',2,10800,'01.png','2018-01-01',2,'2023-10-20 16:35:33','2023-10-20 16:36:13'),
(21,'ruanxiaowu','123456','阮小五',1,'13309090021',5,5200,'01.png','2015-01-01',3,'2023-10-20 16:35:33','2023-10-20 16:36:15'),
(22,'ruanxiaoqi','123456','阮小七',1,'13309090022',5,5500,'01.png','2016-01-01',3,'2023-10-20 16:35:33','2023-10-20 16:36:17'),
(23,'ruanji','123456','阮籍',1,'13309090023',5,5800,'01.png','2012-01-01',3,'2023-10-20 16:35:33','2023-10-20 16:36:19'),
(24,'tongwei','123456','童威',1,'13309090024',5,5000,'01.png','2006-01-01',3,'2023-10-20 16:35:33','2023-10-20 16:36:21'),
(25,'tongmeng','123456','童猛',1,'13309090025',5,4800,'01.png','2002-01-01',3,'2023-10-20 16:35:33','2023-10-20 16:36:23'),
(26,'yanshun','123456','燕顺',1,'13309090026',5,5400,'01.png','2011-01-01',3,'2023-10-20 16:35:33','2023-11-08 22:12:46'),
(27,'lijun','123456','李俊',1,'13309090027',2,6600,'8.png','2004-01-01',2,'2023-10-20 16:35:33','2023-11-16 17:56:59'),
(28,'lizhong','123456','李忠',1,'13309090028',5,5000,'6.png','2007-01-01',3,'2023-10-20 16:35:33','2023-11-17 16:34:22'),
(30,'liyun','123456','李云',1,'13309090030',NULL,NULL,'01.png','2020-03-01',NULL,'2023-10-20 16:35:33','2023-10-20 16:36:31'),
(36,'linghuchong','123456','令狐冲',1,'18809091212',2,6800,'1.png','2023-10-19',2,'2023-10-20 20:44:54','2023-11-09 09:41:04');