责任链模式消除多个if

发布时间 2023-11-02 14:35:15作者: linzm14

原来的代码

        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

@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也不是最终的接口代码,复杂圈数和方法代码行数也会很容易增多