其他分享
首页 > 其他分享> > 桥梁模式加反射查找服务类的实践

桥梁模式加反射查找服务类的实践

作者:互联网

前言

需求

笔者所实践的需求如下:

如上,报表类型一共九种。每种报表的数据要分四个数据源,包括后端数据:(实时数据、离线数据)、前端数据:(客户端数据)、排除其他数据的:真实数据

后端实现

服务框架:springboot、springcloudAlibaba、mybatis

数据源配置

离线数据源

在这里插入图片描述

实时数据源在这里插入图片描述

客户端数据源

在这里插入图片描述

真实报表数据源

在这里插入图片描述

桥梁定义如下

桥梁中定义固定的realMapper用于指定查看实时报表,offMapper用于指定查看离线报表,baseMapper则是通过输入参数判断出当前所请求的数据源,reportParam是当前请求的参数、queryReport()为请求报表数据的方法。

@Component
public abstract class Report {
    @Setter
    protected BaseMapper realMapper;
    @Setter
    protected BaseMapper offMapper;
    @Setter
    protected BaseMapper baseMapper;
    @Setter
    protected ReportParam reportParam;

    public abstract BaseResult queryReport();
}

桥梁上下文ReportContext 定义如下

主要通过reportFactory方法对桥梁中的各个维度属性进行设置,其中 report.setBaseMapper()、report.setRealMapper()、report.setOffMapper()三个方法通过 getReport()方法中的SpringContextUtil.getBean(ConstantTypes.getT())从枚举类中获取对应的类名,再从spring容器中获取对应的bean。

@Component
@Slf4j
public class ReportContext {

    /**
     * 报表上下文工厂
     *
     * @param reportType  报表类型
     * @param reportParam 报表参数
     * @return 生成好的报表类
     */
    public Report reportFactory(String reportType, ReportParam reportParam) {
        reportParam.setShowType(StringUtils.isEmpty(reportParam.getShowType()) ? account : reportParam.getShowType());
        boolean isUser = accountClient.equals(reportParam.getDataType()) || deviceClient.equals(reportParam.getDataType());
        boolean isWhite = account.equals(reportParam.getIsContainWhite());
        Boolean shiftDataSource = (Objects.nonNull(reportParam.getShiftDataSource()) && reportParam.getShiftDataSource()) || isWhite;
        reportParam.setShiftDataSource(shiftDataSource);

        Report report = getReport(reportParam.getDataType(), reportType);
        report.setBaseMapper(getBaseMapper(reportType, isUser, isWhite, shiftDataSource));
        report.setRealMapper(getBaseMapper(reportType, isUser, isWhite, true));
        report.setOffMapper(getBaseMapper(reportType, isUser, false, false));
        report.setReportParam(reportParam);

        return report;
    }

    /**
     * 获取mapper类型
     *
     * @param reportType      报表类型
     * @param isUser          是否为前端报表
     * @param isWhite         是否为白名单报表
     * @param shiftDataSource 是否切换数据源
     * @return
     */
    private BaseMapper getBaseMapper(String reportType, Boolean isUser, Boolean isWhite, Boolean shiftDataSource) {
        return SpringContextUtil.getBean(ConstantTypes.getT(reportType, isUser, isWhite, shiftDataSource).getClassName(), BaseMapper.class);
    }

    /**
     * 选择报表类型
     *
     * @param dateType   数据维度
     * @param reportType 报表类型
     * @return 报表服务类
     */
    private Report getReport(String dateType, String reportType) {
        return SpringContextUtil.getBean(ConstantTypes.getT(reportType, dateType).getClassName(), Report.class);
    }


}

枚举类ConstantTypes 定义如下

public class ConstantTypes {

    @AllArgsConstructor
    @Getter
    public enum Service_type {

        NULL("未知", null, null, null),

        roleCom("角色综合报表", ReportConstant.com, ReportConstant.role, "Boss2RoleReportService"),
        roleLtv("角色ltv报表", ReportConstant.ltv, ReportConstant.role, "Boss2RoleLtvService"),
        roleCreateRetain("角色创建留存报表", ReportConstant.createRetain, ReportConstant.role, "Boss2RoleCreateKeepService"),
        roleRechargeRetain("角色充值留存报表", ReportConstant.rechargeRetain, ReportConstant.role, "Boss2RoleRechargeKeepService"),

        userCom("账号综合报表", ReportConstant.com, ReportConstant.account, "Boss2UserReportService"),
        userLtv("账号ltv报表", ReportConstant.ltv, ReportConstant.account, "Boss2UserLtvService"),
        userCreateRetain("账号创建留存报表", ReportConstant.createRetain, ReportConstant.account, "Boss2UserCreateKeepService"),
        userRechargeRetain("账号充值留存报表", ReportConstant.rechargeRetain, ReportConstant.account, "Boss2UserRechargeKeepService"),

        deviceCom("设备综合报表", ReportConstant.com, ReportConstant.device, "Boss2DeviceReportService"),
        deviceLtv("设备ltv报表", ReportConstant.ltv, ReportConstant.device, "Boss2DeviceLtvService"),
        deviceCreateRetain("设备创建留存报表", ReportConstant.createRetain, ReportConstant.device, "Boss2DeviceCreateKeepService"),
        deviceRechargeRetain("设备充值留存报表", ReportConstant.rechargeRetain, ReportConstant.device, "Boss2DeviceRechargeKeepService"),


        clientUserCom("客户端账号综合报表", ReportConstant.com, ReportConstant.accountClient, "Boss2UserReportService"),
        clientUserLtv("客户端账号ltv报表", ReportConstant.ltv, ReportConstant.accountClient, "Boss2UserLtvService"),
        clientUserCreateRetain("客户端账号创建留存报表", ReportConstant.createRetain, ReportConstant.accountClient, "Boss2UserCreateKeepService"),
        clientUserRechargeRetain("客户端账号充值留存报表", ReportConstant.rechargeRetain, ReportConstant.accountClient, "Boss2UserRechargeKeepService"),


        clientDeviceCom("客户端设备综合报表", ReportConstant.com, ReportConstant.deviceClient, "Boss2DeviceReportService"),
        clientDeviceLtv("客户端设备ltv报表", ReportConstant.ltv, ReportConstant.deviceClient, "Boss2DeviceLtvService"),
        clientDeviceCreateRetain("客户端设备创建留存报表", ReportConstant.createRetain, ReportConstant.deviceClient, "Boss2DeviceCreateKeepService"),
        clientDeviceRechargeRetain("客户端设备充值留存报表", ReportConstant.rechargeRetain, ReportConstant.deviceClient, "Boss2DeviceRechargeKeepService");

        public final String reportTypeName;
        public final String reportType;
        public final String dateType;
        public final String className;
    }


    @AllArgsConstructor
    @Getter
    public enum BaseMapper_type {

        NULL("未知", null, false, false, false, null),

        WhiteOnLineCom("白名单综合报表", ReportConstant.com, false, true, true, "Boss2RealWhiteComReportMapper"),
        WhiteOnLineLtv("白名单ltv报表", ReportConstant.ltv, false, true, true, "Boss2RealWhiteLtvReportMapper"),
        WhiteOnLineCreateRetain("白名单创建留存报表", ReportConstant.createRetain, false, true, true, "Boss2RealWhiteRetainReportMapper"),
        WhiteOnLineRechargeRetain("白名单充值留存报表", ReportConstant.rechargeRetain, false, true, true, "Boss2RealWhiteRechargeRetainReportMapper"),


        ClientOnLineCom("前端在线实时综合报表", ReportConstant.com, true, false, true, "Boss2RealUserComMapper"),
        ClientOnLineLtv("前端在线实时ltv报表", ReportConstant.ltv, true, false, true, "Boss2RealUserLtvMapper"),
        ClientOnLineCreateRetain("前端在线实时创建留存报表", ReportConstant.createRetain, true, false, true, "Boss2RealUserRetainMapper"),
        ClientOnLineRechargeRetain("前端在线实时充值留存报表", ReportConstant.rechargeRetain, true, false, true, "Boss2RealUserRechargeRetainMapper"),


        OnLineCom("实时综合报表", ReportConstant.com, false, false, true, "Boss2RealComReportMapper"),
        OnLineLtv("实时ltv报表", ReportConstant.ltv, false, false, true, "Boss2RealLtvReportMapper"),
        OnLineCreateRetain("实时创建留存报表", ReportConstant.createRetain, false, false, true, "Boss2RealRetainReportMapper"),
        OnLineRechargeRetain("实时充值留存报表", ReportConstant.rechargeRetain, false, false, true, "Boss2RealRechargeRetainReportMapper"),


        ClientOffLineCom("前端离线综合报表", ReportConstant.com, true, false, false, "Boss2UserComMapper"),
        ClientOffLineLtv("前端离线ltv报表", ReportConstant.ltv, true, false, false, "Boss2UserLtvMapper"),
        ClientOffLineCreateRetain("前端离线创建留存报表", ReportConstant.createRetain, true, false, false, "Boss2UserRetainMapper"),
        ClientOffLineRechargeRetain("前端离线充值留存报表", ReportConstant.rechargeRetain, true, false, false, "Boss2UserRechargeRetainMapper"),


        OffLineCom("离线综合报表", ReportConstant.com, false, false, false, "Boss2ComMapper"),
        OffLineLtv("离线ltv报表", ReportConstant.ltv, false, false, false, "Boss2LtvMapper"),
        OffLineCreateRetain("离线创建留存报表", ReportConstant.createRetain, false, false, false, "Boss2CreateKeepMapper"),
        OffLineRechargeRetain("离线充值留存报表", ReportConstant.rechargeRetain, false, false, false, "Boss2RechargeKeepMapper");

        public final String reportTypeName;
        public final String reportType;
        public final Boolean isUser;
        public final Boolean isWhite;
        public final Boolean shiftDataSource;
        public final String className;

    }


    /**
     * @param reportType 报表类型
     * @param dateType   数据维度
     * @return Service_type
     */
    public static Service_type getT(String reportType, String dateType) {
        return Arrays.stream(Service_type.values()).parallel()
                .filter(p -> Objects.equals(reportType, p.reportType) && Objects.equals(dateType, p.dateType))
                .findAny()
                .orElse(Service_type.NULL);
    }


    /**
     * @param reportType 报表类型
     * @param isUser     是否为用户报表
     * @param isWhite    是否为白名单报表
     * @return BaseMapper_type
     */
    public static BaseMapper_type getT(String reportType, Boolean isUser, Boolean isWhite, Boolean shiftDataSource) {
        return Arrays.stream(BaseMapper_type.values()).parallel()
                .filter(p -> Objects.equals(reportType, p.reportType) && Objects.equals(isUser, p.isUser)
                        && Objects.equals(isWhite, p.isWhite) && Objects.equals(shiftDataSource, p.shiftDataSource))
                .findAny()
                .orElse(BaseMapper_type.NULL);
    }


}

桥梁数据维度BaseMapper 定义如下

@Component
public interface BaseMapper {
    List getUserReport(Map<String, Object> params);

    List getRoleReport(Map<String, Object> params);

    List getDeviceReport(Map<String, Object> params);

    @Deprecated
    List getUserTotalMaxDay(Map<String, Object> params);
    @Deprecated
    List getRoleTotalMaxDay(Map<String, Object> params);
    @Deprecated
    List getDeviceTotalMaxDay(Map<String, Object> params);
}

dao层的方法直接继承于此类即可使用接口中定义好的多种维度数据
在这里插入图片描述
在这里插入图片描述

服务类@Service定义

服务类继承桥梁Report,实现其中的queryReport()方法。
在这里插入图片描述

接口@Controller定义

接口中通过reportContext.reportFactory()方法获取设定好所有维度属性的Report类,再通过report.queryReport()方法获取需要的数据

@Controller
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class Boss2ComReportController {

    private final ReportContext reportContext;

    @ResponseBody
    @RequestMapping(value = "/queryComReport", method = RequestMethod.POST)
    public Boss2CommonReportModel queryComReport(@RequestBody ReportParam reportParam) {
        Boss2CommonReportModel boss2CommonReportModel = null;
        try {
            Report report = reportContext.reportFactory(ReportConstant.com, reportParam);
            boss2CommonReportModel = (Boss2CommonReportModel) report.queryReport();
            boss2CommonReportModel.ok();
        } catch (Exception e) {
            boss2CommonReportModel.builder().build().fail(e.getMessage());
            log.error("query ComReport fail", e);
        }
        return boss2CommonReportModel;
    }


}

通过以上方法我们将原本九张报表*四个维度 = 36个逻辑简化为 九张报表+四个维度 ,极大的降低了代码量,增加了可读性,毫不客气的说,妈妈再也不用担心产品要改需求了!

标签:反射,false,报表,桥梁,ReportConstant,reportType,true,public,查找服务
来源: https://blog.csdn.net/w4187402/article/details/118764242