微信开放平台可以做网站么,网站开发开题报告范文,51我们一起做网站,八度填写icp备案网站 接入信息作者 | 阿Q来源 | 阿Q说代码背景在开发过程中我遇到这么一个问题#xff1a;表结构#xff1a;一张主表A #xff0c;一张关联表B #xff0c;表 A 中存储着表 B 记录的状态。场景#xff1a;第一步创建主表数据#xff0c;插入A表#xff1b;第二步调用第三方接口插入B… 作者 | 阿Q来源 | 阿Q说代码背景在开发过程中我遇到这么一个问题表结构一张主表A 一张关联表B 表 A 中存储着表 B 记录的状态。场景第一步创建主表数据插入A表第二步调用第三方接口插入B表同时更新A表的状态。此时大家应该都会想到在进行第二步的时候需要做好数据的幂等性。这样的话就会存在以下几种情况一、B表中不存在与A表关联的数据此时需要调用第三方接口插入B表同时更新A表的状态二、B表中存在与A表关联的数据A表中的状态为处理中直接返回处理中字样A表中的状态为处理成功直接返回成功的字样A表中的状态为处理失败此时需要调用第三方接口更新B表同时更新A表的状态代码实现首先我是这样编写的伪代码B b this.baseMapper.selectOne(queryWrapper);
if (b ! null) {String status b.getStatus();if (Objects.equals(Constants.STATUS_ING, status)){return 处理中;} else if (Objects.equals(Constants.STATUS_SUCCESS, status)){return 处理成功;}//失败的操作//请求第三方接口并解析响应结果......if (ReturnInfoEnum.SUCCESS.getCode().equals(parse.getCode())) {......//更新B表操作bb.setStatus(Constants.STATUS_ING);mapper.updateById(bb);//更新A表的状态a.setStatus(Constants.STATUS_ING);aMapper.updateById(a);}} else {//请求第三方接口并解析响应结果......if (ReturnInfoEnum.SUCCESS.getCode().equals(parse.getCode())) {......//插入B表操作bb.setStatus(Constants.STATUS_ING);mapper.insert(bb);//更新A表的状态a.setStatus(Constants.STATUS_ING);aMapper.updateById(a);}
}不知道细心的小伙伴是否发现存在B表记录并且状态为“失败”的情况和不存在B表的情况除了插入B表或者更新B表的操作之外其余的操作都是相同的。如果我们想要将公共的部分抽取出来发现都比较零散还不如不抽取但是不抽取代码又存在大量重复的代码不符合我的风格。于是我便将手伸向了 Consumer 接口。更改之后的伪代码B b this.baseMapper.selectOne(queryWrapper);
if (b ! null) {String status b.getStatus();if (Objects.equals(Constants.STATUS_ING, status)){return 处理中;} else if (Objects.equals(Constants.STATUS_SUCCESS, status)){return 处理成功;}//失败的操作getResponse(dto, response, s - mapper.updateById(s));
} else {getResponse(dto, response, s - mapper.updateById(s));
}public void getResponse(DTO dto, Response response, ConsumerB consumer){//请求第三方接口并解析响应结果......if (ReturnInfoEnum.SUCCESS.getCode().equals(parse.getCode())) {......bb.setStatus(Constants.STATUS_ING);consumer.accept(bb);//更新A表的状态a.setStatus(Constants.STATUS_ING);aMapper.updateById(a);}
}看到这如果大家都已经看懂了那么恭喜你说明你对 Consumer 的使用已经全部掌握了。如果你还存在一丝丝的疑虑那么就接着往下看我们将介绍一下四种常见的函数式接口。函数式接口那什么是函数式接口呢函数式接口是只有一个抽象方法Object的方法除外但是可以有多个非抽象方法的接口它表达的是一种逻辑上的单一功能。FunctionalInterfaceFunctionalInterface 注解用来表示该接口是函数式接口。它有助于及早发现函数式接口中出现的或接口继承的不适当的方法声明。如果接口用该注解来注释但实际上不是函数式接口则会在编译时报错。Consumer我们一般称之为“消费者”它表示接受单个输入参数但不返回结果的操作。不同于其它函数式接口Consumer 预期通过副作用进行操作。那什么又是副作用呢说一下我所理解的副作用副作用其实就是一个函数是否会修改它范围之外的资源如果有就叫有副作用反之为没有副作用。比如修改全局变量修改输入参数所引用的对象等。FunctionalInterface
public interface ConsumerT {/*** 对给定的参数执行此操作。*/void accept(T t);/*** * 返回一个组合的 Consumer 依次执行此操作然后执行after操作。* 如果执行任一操作会抛出异常它将被转发到组合操作的调用者。* 如果执行此操作会引发异常则不会执行after操作。*/default ConsumerT andThen(Consumer? super T after) {Objects.requireNonNull(after);return (T t) - { accept(t); after.accept(t); };}
}正如我们案例中遇到的场景我们只需要将要执行的逻辑方法当作参数传入 getResponse() 中然后在该方法中执行 accept() 方法进行消费即可。如果还不理解我们可以把它转换为匿名内部类的调用方式。getResponse(dto, response, new ConsumerB() {Overridepublic void accept(B bb) {mapper.insert(bb);}
});当调用accept() 方法的时候就会去调用匿名内部类的方法了也就是我们传入 getResponse() 的逻辑方法。Supplier我们一般称之为“生产者”没有参数输入但是能返回结果为结果的提供者。FunctionalInterface
public interface SupplierT {/*** 获取一个结果*/T get();
}可以举个简单的例子感受下OptionalDouble optional Optional.empty();
optional.orElseGet(()-Math.random() );//orElseGet 方法的源码里边用到了 get 方法
public T orElseGet(Supplier? extends T other) { return value ! null ? value : other.get();
}Function我把它称为“转换者”表示接收一个参数通过处理之后返回一个结果的函数。FunctionalInterface
public interface FunctionT, R {/*** 将 T 类型的参数传入经过函数表达式的计算返回 R 类型的结果*/R apply(T t);/*** 返回一个组合函数先将参数应用于 before 函数然后将结果应用于当前函数返回最终结果。* 如果对任一函数的求值引发异常则会将其转发给组合函数的调用方。*/default V FunctionV, R compose(Function? super V, ? extends T before) {Objects.requireNonNull(before);return (V v) - apply(before.apply(v));}/*** 返回一个组合函数先将参数应用与当前函数然后将结果应用于 after 函数返回最终的结果。* 如果对任一函数的求值引发异常则会将其转发给组合函数的调用方。 */default V FunctionT, V andThen(Function? super R, ? extends V after) {Objects.requireNonNull(after);return (T t) - after.apply(apply(t));}/*** 返回始终返回其输入参数的函数。*/static T FunctionT, T identity() {return t - t;}
}我们在 lambda 表达式中应用比较多所以我们来简单演示下Data
AllArgsConstructor
public class Teacher {private String name;private int age;
}public class TeacherTest {public static void main(String[] args) {ListTeacher list Arrays.asList(new Teacher(张三,25),new Teacher(李四,28),new Teacher(王五,18));ListString collect list.stream().map(item - item.getName()).collect(Collectors.toList());System.out.println(collect);}
}其中 map 接收的参数就是 Function 类型 item 为传入参数item.getName() 为返回处理的结果最后输出结果为[张三, 李四, 王五]Predicate我们称之为“判断者”通过接收参数 T 来返回 boolean 的结果。FunctionalInterface
public interface PredicateT {/*** 接收一个参数, 判断这个参数是否匹配某种规则, 匹配成功返回true, 匹配失败则返回false*/boolean test(T t);/*** 接收一个 Predicate 类型的参数用当前函数和 other 函数逻辑与判断参数 t 是否匹配规则成功返回true失败返回 false * 如果当前函数返回 false则 other 函数不进行计算* 在评估 Predicate 期间引发的任何异常都会转发给调用方*/default PredicateT and(Predicate? super T other) {Objects.requireNonNull(other);return (t) - test(t) other.test(t);}/*** 返回当前Predicate取反操作之后的Predicate*/default PredicateT negate() {return (t) - !test(t);}/*** 接收一个 Predicate 类型的参数用当前函数和 other 函数 逻辑或 判断参数 t 是否匹配规则成功返回true失败返回 false * 如果当前函数返回 true则 other 函数不进行计算* 在评估 Predicate 期间引发的任何异常都会转发给调用方*/default PredicateT or(Predicate? super T other) {Objects.requireNonNull(other);return (t) - test(t) || other.test(t);}/*** 静态方法传入一个参数用来生成一个 Predicate调用test() 方法时调的 object - targetRef.equals(object) 函数式**/static T PredicateT isEqual(Object targetRef) {return (null targetRef)? Objects::isNull: object - targetRef.equals(object);}
}相信大家在编码过程中经常会遇到该函数式接口我们举个例子来说一下public static void main(String[] args) {ListTeacher list Arrays.asList(new Teacher(张三,25),new Teacher(李四,28),new Teacher(王五,18));list list.stream().filter(item - item.getAge()25).collect(Collectors.toList());list.stream().forEach(item-System.out.println(item.getName()));
}其中 filter() 的参数为 Predicate 类型的返回结果为李四看到这儿我们常见的四种函数式接口就已经介绍完了。说实话函数式接口我已经看过好几遍了尤其是 Consumer 和 Supplier。当时只是脑子里学会了没有应用到具体的项目中下次再遇到的时候还是一脸懵逼不知道大家有没有这种感受。往期推荐虚幻引擎5上的《黑客帝国》全新体验爱了爱了元宇宙真的是割韭菜吗Log4j 第三次发布漏洞补丁漏洞或将长存低代码发展专访系列之六低代码平台能解决业务重构的问题吗点分享点收藏点点赞点在看