责任链模式消除多个if
原来的代码
String tenantId = getTenantId(request);
// 判断租户是否存在
SysTenant sysTenant = sysTenantService.getById(tenantId);
if (Objects.isNull(sysTenant)) {
throw new AppException(ResultCodeEnum.TENANT_NOT_NULL);
}
// 获取域名
if (!StringUtils.equals(request.getDomainName(), sysTenant.getDomainName())) {
throw new AppException(ResultCodeEnum.NO_AUTH);
}
// 判断版本是否存在
Version version = versionService.lambdaQuery().eq(Version::getNumber, request.getVersionId()).one();
if (Objects.isNull(version)) {
throw new AppException(VERSION_NOT_EXIST);
}
// 判断当前用户权限
Boolean admin = sysRoleMapper.isAdmin(Utils.getAccount().getExternalAccountId());
if (admin) {
return getVersionModel(version);
}
Product product = productService.getById(version.getProductId());
List<SysUserProd> sysUserProds = getSysRoleUserProds(product);
if (CollectionUtils.isEmpty(sysUserProds)) {
throw new AppException(ResultCodeEnum.NO_AUTH);
}
return getVersionModel(version);
修改后
post 代码 文字描述
基类
public interface Request { }
public interface Response { }
@Data
public class RequestFilterChain {
private RequestFilter requestFilter;
private RequestFilterChain nextFilterChain;
public void doFilter(Request request, Response response) {
if (requestFilter != null) {
if (nextFilterChain == null) {
nextFilterChain = new RequestFilterChain();
}
requestFilter.doFilter(request, response, nextFilterChain);
}
}
}
public interface RequestFilter {
void doFilter(Request request, Response response, RequestFilterChain filterChain);
default int sort() {
return 1;
}
}
这里用到了模板方法模式,里面的抽象方法是获取责任链的节点列表
public abstract class FilterHandlerAbstract {
private List<RequestFilterChain> chains;
private void init() {
if (Objects.nonNull(chains)) {
return;
}
List<RequestFilter> filterBeans = getRequestFilters();
if (CollectionUtil.isEmpty(filterBeans)) {
chains = Collections.emptyList();
return;
}
List<RequestFilter> sortedFilter = filterBeans.stream()
.sorted(Comparator.comparing(RequestFilter::sort))
.collect(Collectors.toList());
int index = sortedFilter.size() - 1;
List<RequestFilterChain> list = new ArrayList<>();
for (int i = index; i >= 0; i--) {
RequestFilter requestFilter = sortedFilter.get(i);
RequestFilterChain chain = new RequestFilterChain();
chain.setRequestFilter(requestFilter);
if (list.size() > 0) {
chain.setNextFilterChain(list.get(0));
}
list.add(0, chain);
}
chains = list;
}
protected abstract List<RequestFilter> getRequestFilters();
private RequestFilterChain getLastChain() {
if (Objects.nonNull(chains)) {
if (chains.size() > 0) {
return chains.get(chains.size() - 1);
}
}
init();
if (Objects.nonNull(chains)) {
if (chains.size() > 0) {
return chains.get(chains.size() - 1);
}
}
return null;
}
private RequestFilterChain getFirstChain() {
if (Objects.nonNull(chains)) {
if (chains.size() > 0) {
return chains.get(0);
}
}
init();
if (Objects.nonNull(chains)) {
if (chains.size() > 0) {
return chains.get(0);
}
}
return null;
}
public void doFilter(Request request, Response response) {
RequestFilterChain firstChain = getFirstChain();
if (Objects.nonNull(firstChain) && Objects.nonNull(firstChain.getRequestFilter())) {
firstChain.doFilter(request, response);
}
}
}
鉴权相关业务代码
鉴权 请求 响应
@Data
public class AuthResponse implements Response {
private VersionModel versionModel;
}
鉴权handler
@Configuration
public class InterfaceImplementationFinder {
private final ApplicationContext applicationContext;
@Autowired
public InterfaceImplementationFinder(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
public <T> Map<String, T> getImplementations(Class<T> interfaceClass) {
return applicationContext.getBeansOfType(interfaceClass);
}
}
@Component
public class AuthenticationFilterHandler extends FilterHandlerAbstract {
@Resource
private InterfaceImplementationFinder interfaceImplementationFinder;
@Override
protected List<RequestFilter> getRequestFilters() {
Collection<AuthenticationRequestFilter> values = interfaceImplementationFinder.getImplementations(
AuthenticationRequestFilter.class).values();
return new ArrayList<>(values);
}
}
鉴权校验
@Component
public class TenantFilter implements AuthenticationRequestFilter {
@Resource
private SysTenantService sysTenantService;
@Override
public void doFilter(Request request, Response response, RequestFilterChain filterChain) {
RuleEngineAuthorizationRequest authorizationRequest = (RuleEngineAuthorizationRequest) request;
// 获取token
String tenantId = Utils.getTenantId(authorizationRequest);
// 判断租户是否存在
SysTenant sysTenant = sysTenantService.getById(tenantId);
if (Objects.isNull(sysTenant)) {
throw new AppException(ResultCodeEnum.TENANT_NOT_NULL);
}
// 下一步校验
filterChain.doFilter(request, response);
}
@Override
public int sort() {
return 1;
}
}
@Component
public class DomainNameFilter implements AuthenticationRequestFilter {
@Resource
private SysTenantService sysTenantService;
@Override
public void doFilter(Request request, Response response, RequestFilterChain filterChain) {
RuleEngineAuthorizationRequest authorizationRequest = (RuleEngineAuthorizationRequest) request;
SysTenant sysTenant = sysTenantService.getById(Utils.getTenantId(authorizationRequest));
// 获取域名
if (!StringUtils.equals(authorizationRequest.getDomainName(), sysTenant.getDomainName())) {
throw new AppException(ResultCodeEnum.NO_AUTH);
}
// 下一步校验
filterChain.doFilter(request, response);
}
@Override
public int sort() {
return 2;
}
}
总结
总的来说,个人觉得 上面的责任链运用有点牵强,但是也比多个if这样的代码好维护,这个接口还在完善,上面的if也不是最终的接口代码,复杂圈数和方法代码行数也会很容易增多
蓝天和白云是标配。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端