ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2021-07-15 18:02:29  阅读:183  来源: 互联网

标签:反射 false 报表 桥梁 ReportConstant reportType true public 查找服务


前言

  • 桥梁模式的用意是“将抽象化与实现化脱耦,使得二者可以独立地变化。
  • 通常我们使用桥梁模式是为了将两个维度的控制分离开来,通过桥梁模式连接起来,使两个维度通过桥梁轻松的做出多种组合。
  • 通过使用桥梁模式,我们不必为每种组合写一套逻辑代码,只需要将每个维度中每种逻辑作为一个实现类实现一次,之后使用桥梁对其进行桥接。

需求

笔者所实践的需求如下:

  • 服务类型:报表展示服务
  • 报表类型:
  •  		综合报表
    
  •  		创建留存报表
    
  •  		ltv报表
    
  •  		充值留存报表
    
  •  		在线监控报表
    
  •  		资源报表
    
  •  		设备激活监控
    
  •  		充值礼包报表
    
  •  		在线统计报表
    

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

后端实现

服务框架: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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有