一、背景
有这样一个业务场景,用户要申请一个功能,但是这个功能需要有校验多种资格。如果有些资格不满足需要给用户提示。
下面给出一个简单的通用方案。
这个方案的优势是,加新的校验非常容易,只需要写一个新的校验函数,添加校验条件即可,不至于把所有校验写在一大串代码里,导致可读性,可维护性都不好。
其实还可以更强大一些,可以在应用启动后获取某个注解或者继承自某个类或接口的所有校验类,然后校验时自动调用。
二、方法
2.1 项目结构
2.2 pom文件<?xml version="1.0" encoding="UTF-8"?>
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">
4.0.0
com.chujianyun
lambdacheck
1.0-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
2.1.6.RELEASE
org.springframework.boot
spring-boot-starter-web
org.projectlombok
lombok
1.18.8
org.apache.commons
commons-lang3
3.9
1.8
org.springframework.boot
spring-boot-maven-plugin
2.3 实体
import lombok.Data;@Datapublic class UserParam { /**
* 用户ID
*/
private Long userId;
}
结果package com.chujianyun.entity.dto;import lombok.Data;import java.util.List;@Datapublic class UserCheckResultDTO { /**
* 是否有效
*/
private Boolean isValidUser; /**
* 是否白名单
*/
private Boolean isInWhiteList; /**
* 是否等级高
*/
private Boolean isHighLevel; /**
* 失败原因
*/
private List failedMessages;
}
上下文import com.chujianyun.entity.dto.UserCheckResultDTO;import lombok.Data;@Datapublic class UserCheckContext { private UserCheckResultDTO userCheckResultDTO = new UserCheckResultDTO(); // 可以携带其他结果}
2.4 核心封装import com.chujianyun.entity.context.UserCheckContext;import com.chujianyun.entity.dto.UserCheckResultDTO;import com.chujianyun.entity.param.UserParam;import org.apache.commons.lang3.RandomUtils;import org.springframework.stereotype.Component;import java.util.ArrayList;import java.util.List;import java.util.function.Consumer;import java.util.function.Function;@Componentpublic class UserCheckFuntions { // 注入校验所需的各种Bean
public Function checkIsValid(UserParam userParam) { return buildCheck(userCheckContext -> {
UserCheckResultDTO userCheckResultDTO = userCheckContext.getUserCheckResultDTO(); // 模拟调用服务A,检查有效性
boolean result = (userParam.getUserId() > 50); if (result) {
userCheckResultDTO.setIsValidUser(true);
} else {
userCheckResultDTO.setIsValidUser(false);
addFailedMessage(userCheckResultDTO, "无效");
}
});
} public Function checkIsInWhiteList(UserParam userParam) { return buildCheck(userCheckContext -> {
UserCheckResultDTO userCheckResultDTO = userCheckContext.getUserCheckResultDTO(); // 模拟调用服务B,检查是否在白名单
boolean result = (userParam.getUserId() > 500); if (result) {
userCheckResultDTO.setIsInWhiteList(true);
} else {
userCheckResultDTO.setIsInWhiteList(false);
addFailedMessage(userCheckResultDTO, "不在白名单");
}
});
} public Function checkIsHighLevel(UserParam userParam) { return buildCheck(userCheckContext -> {
UserCheckResultDTO userCheckResultDTO = userCheckContext.getUserCheckResultDTO(); // 模拟调用服务C,检查是否高级用户
boolean result = (userParam.getUserId() > 30); if (result) {
userCheckResultDTO.setIsHighLevel(true);
} else {
userCheckResultDTO.setIsHighLevel(false);
addFailedMessage(userCheckResultDTO, "等级不够");
}
});
} public Function buildCheck(Consumer userCheckContextConsumer) { return (userCheckContext) -> {
userCheckContextConsumer.accept(userCheckContext); return userCheckContext;
};
} /**
* 添加失败的信息
*/
public void addFailedMessage(UserCheckResultDTO userCheckResultDTO, String message) {
List failMessages = userCheckResultDTO.getFailedMessages(); if (failMessages == null) {
failMessages = new ArrayList<>();
userCheckResultDTO.setFailedMessages(failMessages);
}
failMessages.add(message);
}
}
2.5 服务类import com.chujianyun.entity.dto.UserCheckResultDTO;import com.chujianyun.entity.param.UserParam;public interface UserService { UserCheckResultDTO checkUser(UserParam userParam);
}
实现import com.chujianyun.component.UserCheckFuntions;import com.chujianyun.entity.context.UserCheckContext;import com.chujianyun.entity.dto.UserCheckResultDTO;import com.chujianyun.entity.param.UserParam;import com.chujianyun.service.UserService;import org.springframework.stereotype.Service;import javax.annotation.Resource;@Servicepublic class UserServiceImpl implements UserService { @Resource
private UserCheckFuntions userCheckFuntions; @Override
public UserCheckResultDTO checkUser(UserParam userParam) {
UserCheckContext userCheckContext = new UserCheckContext(); return userCheckFuntions.checkIsValid(userParam)
.andThen(userCheckFuntions.checkIsInWhiteList(userParam))
.andThen(userCheckFuntions.checkIsHighLevel(userParam))
.apply(userCheckContext)
.getUserCheckResultDTO();
}
}
如果需要新增一个校验,则结果对象里加一个boolean属性,在Function里加一个校验函数,然后再实现类里加一个andThen的校验即可。
2.6 控制器
import com.chujianyun.entity.dto.UserCheckResultDTO;import com.chujianyun.entity.param.UserParam;import com.chujianyun.service.UserService;import org.springframework.http.HttpStatus;import org.springframework.http.ResponseEntity;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestMapping;import javax.annotation.Resource;@Controller@RequestMapping("/user")public class HelloController { @Resource
private UserService userService; @PostMapping("/check") public ResponseEntity checkUser(UserParam userParam) { return new ResponseEntity<>(userService.checkUser(userParam), HttpStatus.OK);
}
}
2.7 测试
三、总结
本文主要演示Lambda表达式在参数校验的特殊场景下的一个很有趣的应用,可读性,可拓展性更强。
给我们的启发是要灵活运用Java8提供的新的函数式类。
创作不易,如果觉得本文对你有帮助,欢迎点赞,欢迎关注我,如果有补充欢迎评论交流,我将努力创作更多更好的文章。