美文网首页
Base4Cloud基类使用

Base4Cloud基类使用

作者: 勤的空间 | 来源:发表于2023-01-19 19:38 被阅读0次

    一、BaseCloud概述

    Base4Cloud主要用于数据库的操作,引用最新base4cloud依赖

            <dependency>
                <groupId>com.zdetech.base4cloud</groupId>
                <artifactId>base4cloud</artifactId>
                <version>1.0.0</version>
                <classifier>small</classifier>
            </dependency>
    

    本次使用的Base4Cloud与之前的BaseDao主要不同:

    特点 Base4Cloud BaseDao
    编程方式 Reactor3非阻塞响应式编程 阻塞式编程
    Web框架 Spring WebFlux Spring Web MVC
    数据框架 Spring Data R2DBC Spring Data JPA

    非阻塞响应式编程与传统的阻塞式编程有很大不同,下面以BaseDao与BaseCloud比较。

    现需要给部门ID为1的人员添加角色ID2,因此需要批量插入用户-角色表。

    用户表(sys_user):

    字段名 类型 说明
    user_id bigint 用户ID
    username varchar(64) 用户名
    password varchar(255) 密码
    birthday Date 出生日期
    salary decimal 工资
    dept_id bigint 部门ID

    用户-角色表(sys_user_role):

    字段名 类型 说明
    user_id bigint 用户ID
    role_id bigint 角色ID

    使用BaseDao传统阻塞式编程:

    SysUser where = new SysUser();
    where.setDeptId(1L);
    List<SysUser> list = baseDao.findByFields(where);  // 1
    for (int i=0;  i < list.size(); i++) { // 2
      SysUser user = list.get(i); // 3
      SysUserRole sysUserRole = new SysUserRole(); // 4
      sysUserRole.setUserId(user.getId());
      sysUserRole.setRoleId(2L);
      baseDao.save(sysUserRole); 
    }
    
    1. 设置查询条件dept_id=1, 根据查询条件查询出用户实体列表
    2. 遍历查询出的用户
    3. 得到一个查询出的用户
    4. 根据用户ID创建用户-角色实体,设置用户ID为查询出的用户ID, 设置角色ID为2, 保存用户-角色实体

    使用Base4Cloud非阻塞响应式编程

    SysUser where = new SysUser(); 
    where.setDeptId(1L);
    return baseDAO.findByFields(where)  // 1
                    .flatMap(user -> { // 2
                        SysUserRole userRole = new SysUserRole(); 
                        userRole.setUserId(user.getUserId());
                        userRole.setRoleId(2L);
                        return baseDAO.save(userRole); // 3
                    });
    
    1. 设置查询条件dept_id=1, 根据查询条件查询出用户实体
    2. flatMap操作符依次遍历上一步的结果, 参数user是SysUser实体对象
    3. 根据用户ID创建用户-角色实体,设置角色ID为2, 保存用户-角色实体, 一定要return, 否则不能执行任何SQL语句

    非阻塞响应式编程与传统阻塞式编程不同的是, 所有操作返回的是一个Mono(单值)或Flux(多值), 后续操作是使用Mono或Flux的操作符如:map flatMap filter then reduce zipWith switchIfEmpty等来实现编程逻辑, 而这些操作符调用的返回依然是Mono或Flux, 所以会一直调用不同的操作符, 直到 return。需要熟悉这些操作符才能完成编程逻辑。

    下面对一些常用操作符举例说明:

    • flatMap

    对上一步操作的数据进行迭代(循环)操作,前面已有flatMap的例子。

    • then thenMany thenReturn

    thenthenRetutnthenMany都表示等上一步完成后,忽略上一步的操作结果,直接进行其他操作。

    比如上面代码,如果后续还有其他操作,比如保存了用户-角色后,再删除用户ID为1,2,3的用户,可这样写:

            SysUser where = new SysUser();
            where.setDeptId(1L);
            return baseDAO.findByFields(where)
                    .flatMap(user -> {
                        SysUserRole userRole = new SysUserRole();
                        userRole.setUserId(user.getUserId());
                        userRole.setRoleId(2L);
                        return baseDAO.save(userRole);
                    })
                    .thenMany(baseDAO.findByListIn(SysUser.class, "user_id", Arrays.asList(1, 2, 3))) // 1
                    .flatMap(baseDAO::delete); // 2
                    
    
    1. thenMany操作符忽略上一步的数据,直接执行一次查询ID为1,2,3的用户。
      此处findByListIn方法返回是Flux(多值),所以用thenMany操作符,如果是返回Mono(单值),则应该使用then操作符。
      注意:这儿不能用flatMap操作符,因为flatMap是对上一步return baseDAO.save(userRole)的结果Flux<SysUserRole>进行迭代,假设插入的用户-角色记录有3条(因为部门ID为1的的用户有3个),则会执行三次baseDAO.findByListIn(SysUser.class, "user_id", Arrays.asList(1, 2, 3)),这显然是不对的。
    2. 遍历删除查询出来的用户,此处双冒号::写法baseDAO::deleteuser -> baseDAO.delete(user)的简写。
    • collectList map

    如果后面确实要使用上一步return baseDAO.save(userRole)的结果数据,但只想执行一次操作而不是迭代,可用collectList()操作符,把上一步结果Flux转为Mono<List>再继续调用flatMap操作符。代码如下:

            SysUser where = new SysUser();
            where.setDeptId(1L);
            return baseDAO.findByFields(where)
                    .flatMap(user -> {
                        SysUserRole userRole = new SysUserRole();
                        userRole.setUserId(user.getUserId());
                        userRole.setRoleId(2L);
                        return baseDAO.save(userRole);
                    })
                    .map(userRole -> userRole.getUserid()) // 1
                    .collectList() // 2
                    .flatMap(ids -> // 3
                           baseDAO.deleteByListIn(SysUser.class,"user_id", ids)) // 4
    
    1. 遍历上一步结果将SysUserRole对象map为userId,mapflatMap类似都是迭代操作。这儿没用flatMap,是因为flatMap要求返回Mono或Flux,就要冗余的写成flatMap(userRole -> Mono.just(userRole.getUserid()))。如果是调用baseDAO方法,它返回的是Mono或Flux,就要用flatMap
    2. 使用collectList把上一步的Flux转为Mono<List>,后面使用flatMap就只执行一次,而不是遍历多次
    3. 此处是List对象,就是插入的SysUserRole的userid列表List<Long>
    4. baseDAO.deleteByListIn方法根据ids用IN条件批量删除用户

    上面代码只是演示操作符用法,实际不可能这么干。实现的逻辑是:查询部门ID1下的用户,分别给每个用户新增用户-角色表记录,角色ID为2,最后根据新增的用户-角色记录的用户ID在用户表中删除用户记录。

    • zip zipWith reduce cache

    前面例子都是从上一步获取一个数据进行处理的情况,如果有一个操作需要多个数据合并起来处理怎么办呢?这时就用到了zipzipWith操作符了,zip操作符能把多个Flux或Mono合并在成Tuple类型,比如2个合并成Tuple2,3个合并成Tuple3,n个合并成TupleNTupleNgetT1,getT2,getT3...getTn等方法分别获取各个数据。

    比如,我们想要从用户表中统计出用户数、平均工资、平均年龄,代码如下:

            Flux<User> result = baseDAO.findAll(User.class).cache(); // 1
            Mono<Double> totalSalary = result.reduce(0.0, (sum, user) -> sum + user.getSalary()); // 2
            Mono<Integer> totalAge = result.reduce(0, (sum, user) -> sum + user.getBrithday().until(LocalDate.now()).getYears()); // 3
            Mono<Long> count = result.count(); // 4
            return Mono.zip(totalSalary, totalAge, count) // 5
                    .map(data -> { // 6
                        JSONObject res = new JSONObject();
                        res.put("cnt", data.getT3());
                        res.put("avgSalary", data.getT1() / data.getT3());
                        res.put("avgAge", data.getT2() / data.getT3());
                        return res;
                    })
    
    1. 查询所有用户,保存结果到result。这儿用到了cache缓存方法,因为后面会3次用到result,如果不加上cache,每次引用result会再次执行findAll查询,就会执行3次findAll查询。所以如果有一个操作结果后面会多次使用,要加上cache是必须的。
    2. 使用reduce 操作符汇总用户工资总额。
    3. 使用redeuce操作符汇总用户年龄总数。
    4. 使用count操作符获取用户数。
    5. zip操作符合并前面三个结果(工资总额(T1)、年龄总数(T2)、用户数(T3))数据成Tuple3对象。
    6. 计算平均工资、平均年龄、用户数建立JSONObject对象。
      返回结果如下:
            {
                "cnt": 4,
                "avgAge": 34,
                "avgSalary": 275.0
            }
    

    上面只是为了说明操作符用法,其实可以在sys_sqlds表配置SQL调用baseDAO.getData方法更简单。

    • groupBy reduce

    上例是统计全体人员,如果要按部门分组统计平均工资、平均年龄、部门人数呢?需要用到groupBy操作符,代码如下:

            Flux<GroupedFlux<Long, User>> group = baseDAO.findAll(User.class)
                    .groupBy(User::getDepId); // 1
            return group.flatMap(groupedFlux -> groupedFlux.reduce(new JSONObject(), (result, user) -> { // 2
                        result.put("dept_id", groupedFlux.key());
                        result.put("cnt", result.getIntValue("cnt") + 1);
                        result.put("salary", result.getDoubleValue("salary") + user.getSalary());
                        result.put("age", result.getIntValue("age") + user.getBrithday().until(LocalDate.now()).getYears());
                        return result;
                    }))
                    .map(data -> { // 3
                        JSONObject obj = new JSONObject();
                        obj.put("dept_id", data.getIntValue("dept_id"));
                        obj.put("cnt", data.getIntValue("cnt"));
                        obj.put("avgSalary", data.getDoubleValue("salary") / data.getIntValue("cnt"));
                        obj.put("avgAge", data.getIntValue("age") / data.getIntValue("cnt"));
                        return obj;
                    })
                    .collectList();
    
    1. 使用groupBy操作符,按员工的dept_id分组,注意分组后的结果类型是Flux<Flux<User>>,即结果本身是一个Flux(多值),而它的每一项也是一个Flux(多值),这个Flux每一项目是User对象,表示同一部门的员工。即数据如下:
        [
           { // 部门1
             [ 
               {id: 1, username : 'li', birthday: '1979-08-05', salary: 500},
               {id: 2, username : 'wang', birthday: '1992-08-25', salary: 200}
             ],
             key: 1 // dept_id=1
           },
           { // 部门2
              [ 
                {id: 3, username : 'zhang', birthday: '1990-04-25', salary: 300},
                {id: 4, username : 'liu', birthday: '1991-03-25', salary: 100}      
              ],
              key: 2// dept_id=2
            }
        ]
    
    1. 上一步groupBy生成的是Flux<Flux<User>>类型,使用flatMap操作符遍历Flux<Flux<User>>每一项,每一项目数据类型是Flux<User>,所以这儿groupedFlux数据类型就是Flux<User>。使用groupedFlux的reduce操作符,也就是对它的每一项User做汇总操作,得到员工数cnt,工资总额salary,年龄总数age,组成一个JSONObject对象。
    2. 计算平均工资、平均年龄,生成JSONObject对象
      执行结果:
    [
      {"cnt":2,"avgAge":36,"avgSalary":350.0,"dept_id":1}, 
      {"cnt":2,"avgAge":31,"avgSalary":200.0,"dept_id":2}
    ]
    

    上面只是为了说明操作符用法,其实可以在sys_sqlds表配置SQL调用baseDAO.getData方法更简单。

    总结:非阻塞响应式编程会用到Mono或Flux的各种操作符实现编程逻辑,请熟悉各种操作符。操作符详情说明可参考Reactor3开发参考文档Reactor3的API文档

    二、生成实体类, 一个实体类对应一张表

    1. 添加数据源,根据你的需要选择你使用的数据库,如MySQL或Oracle。


      image
    2. 第一次生成需要修改Generated POJOs.groovy脚本, 脚本会给passwordkzzf kzsz kzsj kzid开头的字段加上@JsonIgnore注解,接口将忽略这些字段,如需要指定字段,请去掉此注解
      右键在数据源中选择要生成的实体表, Tools -> Scripted Extensions -> Go To Scripts Directory, 打开脚本修改如下:
    import com.intellij.database.model.DasTable
    import com.intellij.database.util.Case
    import com.intellij.database.util.DasUtil
    
    /*
     * Available context bindings:
     *   SELECTION   Iterable<DasObject>
     *   PROJECT     project
     *   FILES       files helper
     */
    
    packageName = ""
    typeMapping = [
            (~/(?i)int/)                      : "Long",
            (~/(?i)float|double|decimal|real/): "Double",
            (~/(?i)datetime|timestamp/)       : "java.time.LocalDateTime",
            (~/(?i)date/)                     : "java.time.LocalDate",
            (~/(?i)time/)                     : "java.time.LocalTime",
            (~/(?i)/)                         : "String"
    ]
    
    FILES.chooseDirectoryAndSave("Choose directory", "Choose where to store generated files") { dir ->
        SELECTION.filter { it instanceof DasTable }.each { generate(it, dir) }
    }
    
    def generate(table, dir) {
        def className = javaName(table.getName(), true)
        def fields = calcFields(table)
        packageName = getPackageName(dir)
        new File(dir, className + ".java").withPrintWriter("utf-8") { out -> generate(out, className, fields, table) }
    }
    
    // 获取包所在文件夹路径
    def getPackageName(dir) {
        return dir.toString().replaceAll("\\\\", ".").replaceAll("/", ".").replaceAll("^.*src(\\.main\\.java\\.)?", "") + ";"
    }
    
    def isNotEmpty(content) {
        return content != null && content.toString().trim().length() > 0
    }
    
    def generate(out, className, fields, table) {
        out.println "package $packageName"
        out.println ""
        out.println "import com.fasterxml.jackson.annotation.JsonIgnore;"
        out.println "import org.springframework.data.annotation.Version;"
        out.println "import io.swagger.v3.oas.annotations.media.Schema;"
        out.println "import org.springframework.data.relational.core.mapping.Table;"
        out.println "import org.springframework.data.annotation.Id;"
        out.println "import org.springframework.data.relational.core.mapping.Column;"
        out.println "import lombok.Data;"
        out.println ""
        out.println "@Data"
        out.println "@Table(\"" + table.getName() + "\")"
        out.println "public class $className {"
        fields.each() {
            out.println ""
            if (isNotEmpty(it.comment)) {
                out.println "\t@Schema(description = \"${it.comment.toString()}\")"
            }
    
            if (it.annos != "") out.println "\t${it.annos}"
            out.println "\t@Column(\"${it.columnName}\")"
            out.println "\tprivate ${it.type} ${it.name};"
        }
        out.println ""
        out.println "}"
    }
    
    def calcFields(table) {
        def pkCnt = 0
        DasUtil.getColumns(table).reduce([]) { fields, col ->
            def spec = Case.LOWER.apply(col.getDataType().getSpecification())
            def typeStr = typeMapping.find { p, t -> p.matcher(spec).find() }.value
            if (DasUtil.isPrimary(col)) {
                pkCnt++
            }
            def annos = "";
            if (col.getName() == "password" || col.getName().startsWith("kzzf") || col.getName().startsWith("kzsz") || col.getName().startsWith("kzsj") || col.getName().startsWith("kzid")) {
                annos = "@JsonIgnore"
            } else if (col.getName() == "version") {
                annos = "@Version"
            } else if (DasUtil.isPrimary(col)) {
                if (pkCnt < 2) {
                    annos = "@Id"
                } else {
                    annos = "@javax.persistence.Id"
                }
            }
            fields += [[
                               name      : javaName(col.getName(), false),
                               type      : typeStr,
                               comment   : col.getComment(),
                               columnName: col.getName(),
                               annos     : annos
                       ]]
        }
    }
    
    def javaName(str, capitalize) {
        def s = com.intellij.psi.codeStyle.NameUtil.splitNameIntoWords(str)
                .collect { Case.LOWER.apply(it).capitalize() }
                .join("")
                .replaceAll(/[^\p{javaJavaIdentifierPart}[_]]/, "_")
        capitalize || s.length() == 1 ? s : Case.LOWER.apply(s[0]) + s[1..-1]
    }
    
    image.png
    1. 右键在数据源中选择要生成实体类的表, Tools -> Scripted Extensions -> Generated POJOs.groovy


      image.png

    三、baseDAO方法

    一、查询方法
    <T> Flux<T> findAll(Class<T> clazz)

    查询clazz实体类型的所有记录,比如查询所有用户表记录:

            return baseDAO.findAll(SysUser.class)
                    . map(user -> {
                        System.out.println(user);
                        return user;
                    });
    
    <T> Flux<T> findByFields(T where)

    根据where条件查询, 如: 查询部门ID为1,用户名为leonine的用户

            SysUser where = new SysUser();
            where.setDeptId(1L);
            where.setUsername("leonine");
            return baseDAO.findByFields(where)
                    . map(user -> {
                        System.out.println(user);
                        return user;
                    });
    
    <T> Mono<T> findByIds(T entity)

    用于查询联合主键的表, entity为主键对象, 所有主键都要赋值, 否则报错。比如查询:user_id=1 role_id=2 的用户-角色。

            SysUserRole pk = new SysUserRole();
            pk.setUserId(1L);
            pk.setRoleId(2L);
            return baseDAO.findByIds(pk)
                    .map(userRole -> {
                        System.out.println(userRole);
                        return userRole;
                    });
    
    <T> Mono<T> findById(Class<T> clazz, ID id)

    根据唯一主键查询实体,如查询用户ID为1的SysUser实体:

            return baseDAO.findById(SysUser.class, 1L)
                    .map(user -> {
                        System.out.println(user);
                        return user;
                    });
    
    <T> Flux<T> findByListIn(Class<T> clazz, String fieldName, List list)

    根据IN条件查询实体,如查询用户ID为1,2,3的SysUser:

            baseDAO.findByListIn(SysUser.class, "user_id", Arrays.asList(1, 2, 3))
                    .map(user -> {
                        System.out.println(user);
                        return user;
                    });
    
    
    Mono<JSONObject> getTreeData(String sqlId, JSONObject params)

    返回树结构对象,sqlIdsys_sqlds表中配置的查询,params为查询参数,查询参数必传rootId,返回结果必带parenteidid字段,其他字段随意,SQL如:

    WITH RECURSIVE ctetable as (
      SELECT dept_id id , parent_id parentid ,name as label from sys_dept where 1 = :rootId
      UNION ALL
      SELECT dept_id id , parent_id parentid , name  as label from sys_dept a join ctetable t2 
    WHERE a.dept_id =t2.parentid
    )
    SELECT DISTINCT * FROM ctetable a
    
            JSONObject params = new JSONObject();
            params.put("rootId",1);
            baseDAO.getTreeData("getdepttree",params)
                    .map(tree->{
                        System.out.println(tree);
                        return tree;
                    });
    
    <T> Flux<T> getData(String sqlId, Class<T> clazz, JSONObject params)

    根据配置的SQL返回查询结果,sqlIdsys_sqlds表中配置的查询,clazz为返回的结果实体类型,如果传null,返回的结果为JSONObject类型,params为查询参数,SQL如:
    select * from sys_user where username = :username

            JSONObject params = new JSONObject();
            params.put("username","leonine");
            baseDAO.getData("getsysuser", SysUser.class, params)
                    .map(user->{
                        System.out.println(user);
                        return user;
                    });
    
    Flux<JSONObject> getData(String sqlId, JSONObject params)

    根据配置的SQL返回查询结果,sqlIdsys_sqlds表中配置的查询,返回的结果为JSONObject类型,params为查询参数,SQL如:
    select * from sys_user where username = :username

            JSONObject params = new JSONObject();
            params.put("username","leonine");
            baseDAO.getData("getsysuser", params)
                    .map(user->{
                        System.out.println(user);
                        return user;
                    });
    
    二、修改方法
    <T> Mono<T> save(T entity)

    保存实体对象,如果主键有赋值且有记录就修改,否则就插入,自增长的主键在下一个操作符如map flatMap filter等中获取。

            SysUser newUser = new SysUser();
            newUser.setUsername("leonine");
            PasswordEncoder ENCODER = new BCryptPasswordEncoder();
            newUser.setPassword(ENCODER.encode("123456"));
            newUser.setPhone("17712345678");
            return baseDAO.save(newUser)
                    .map(user -> {
                        System.out.println("新增用户ID:" + user.getUserId());
                        return user;
                    });
    
    <T> Mono<Integer> updateByFields(T entity, T where)

    根据where条件批量修改记录,entity为包含新值的对象。

            SysUser where = new SysUser();
            where.setUsername("leonine");
            where.setPhone("17712345678");
    
            SysUser updater = new SysUser();
            updater.setUsername("leonine updated");
            updater.setMail("mail updated");
    
            return baseDAO.updateByFields(updater,where)
                    .map(cnt -> {
                        System.out.println("修改了" + cnt  + "条记录");
                        return cnt;
                    });
    
    <T> Mono<Integer> updateByListIn(T entity, String fieldName, List list)

    fieldName字段名,list字段值列表,entity修改的值对象,下面代码批量修改ID为1,2,3的记录,设置username值为leonine:

            SysUser entity = new SysUser();
            entity.setUsername("leonine");
            return baseDAO.updateByListIn(entity, "user_id", Arrays.asList(1, 2, 3))
                    .map(cnt -> {
                        System.out.println("修改了" + cnt  + "条记录");
                        return cnt;
                    });
    
    <T> Mono<T> delete(T entity)

    删除对象,entity对象主键必须赋值

            SysUser entity = new SysUser();
            entity.setUserId(1L);
            return baseDAO.delete(entity)
                    .map(user -> {
                        System.out.println(user);
                        return user;
                    });
    
    <T> Mono<Integer> deleteByFields(T where)

    根据where条件批量删除记录。

            SysUser where = new SysUser();
            where.setDeptId(1L);
            return baseDAO.deleteByFields(where)
                    .map(cnt -> {
                        System.out.println("删除了" + cnt  + "条记录");
                        return cnt;
                    });
    
    <T> Mono<Integer> deleteByListIn(Class<T> clazz, String fieldName, List list)

    fieldName字段名,list字段值列表,clazz删除的对象,下面代码批量删除ID为1,2,3的记录:

            return baseDAO.deleteByListIn(SysUser.class, "user_id" , Arrays.asList(1, 2, 3))
                    .map(cnt -> {
                        System.out.println("删除了" + cnt  + "条记录");
                        return cnt;
                    });
    

    四、查询getData.do编写

    与BaseDao基类编写方式相同,请参考BaseDAO基类使用
    简述如下:
    sys_sqlds表中插入记录,数据如下:
    sql_id: 查询唯一id
    sql_ds: 查询语句说明
    sql_server: 查询语句
    查询语句编写与原生写法类似,其中参数用 :<参数名>代替,如
    select * from user_password where username = :username and password = :password

    五、setData.do业务类编写

    业务类接口:
    public interface AppService {
        Mono<Result> addUser(JSONObject jsonObject, BaseDAO baseDAO);
    }
    

    业务类接口方法两个参数:前端请求参数jsonObject、数据操作对象baseDAO可调用前面介绍的savefindByIddelete等方法,返回类型统一为Mono<Result>。前端如果传的参数是包含多个jsonObject的数组如[ { username:'leonine', phone:'123' }, { userid: 5 , username:'leo', phone:'456' }, { userid: 1, delete: true } ]包含3个jsonObject对象,setData.do会每次取一个jsonObject调用,总共执行3次这个方法。

    业务类实现:
    @Service("appService")
    public class AppServiceImpl implements AppService {
    
        @Override
        @SuppressWarnings("unchecked")
        public Mono<Result> addUser(JSONObject jsonObject, BaseDAO baseDAO) {
    
            SysUser sysUser = jsonObject.toJavaObject(SysUser.class); // 1
    
            boolean delete = jsonObject.getBooleanValue("delete"); // 2
            if (delete) {
                return baseDAO.delete(sysUser)
                        .flatMap(BaseResult::ok); // 3
            } else {
                if (sysUser.getUsername() == null) { // 4
                    return BaseResult.failed("用户名不能为空");
                }
                return baseDAO.save(sysUser)  // 5
                        .flatMap(user -> { 
                            SysUserRole userRole = new SysUserRole();
                            userRole.setUserId(user.getUserId());
                            userRole.setRoleId(2L);
                            return baseDAO.save(userRole) // 6
                                    .thenReturn(user); // 7
                        })
                        .flatMap(BaseResult::ok); // 8
            }
        }
    }
    
    1. 把jsonObject转为实体对象
    2. 获取前端的其他实体对象中没包含的参数如delete
    3. 删除用户,调用BaseResul::ok,返回成功
    4. 如果用户名为空,调用BaseResult.failed方法返回失败提示:用户名不能为空
    5. 新增或修改用户
    6. 新增或修改用户-角色记录,用户ID为新增或修改的用户ID,角色ID为2
    7. thenReturn方法用于直接传递用户信息到下一步,如果没有这一句,传递到下一步的将是baseDAO.save(userRole)的返回结果,就是保存的SysUserRole对象(用户-角色)记录信息
    8. 调用BaseResul::ok,返回成功到前端,也就是json: {code: 0 , msg :'处理成功', data: <用户信息>}

    所有操作最后以BaseResult.ok方法或BaseResult.failed结束。成功调用BaseResult.ok,失败调用BaseResult.failed,有多种参数形式,具体看代码提示。
    比如返回失败BaseResult.failed(5, "用户不存在")表示错误码5,错误描述:用户不存在
    .flatMap(BaseResult::ok)实际上是.flatMap(result -> BaseResult.ok(result)的简写,返回json:{code: 0 , msg :'处理成功', data: <result的值>}

    相关文章

      网友评论

          本文标题:Base4Cloud基类使用

          本文链接:https://www.haomeiwen.com/subject/etyqhdtx.html