项目总结--04

1.之前在进行项目开发的过程中,主要的功能开发其实是基于需求文档进行开发的,其实之前在对开发的过程了解中,没有整体掌握对原型的概念,基于原型图的概念开发,其实可以更直观的看出数据的流转,有些事基于需求文档的开发,会吧一些文字用抽象的语言描述出来,在进行开发的过程中需要对抽象语言进行概括和升级,在进行相关的开发过程中,需要将人类语言转为编程语言。

但是基于原型图的开发,后续开发的过程中,主要是针对具体的原型图中某些系统的概念和对应的具体的按钮,整体来说这种开发模式还是非常不错的,在进行这种开发的时候,需要了解原型的整体的概念和整体的逻辑。

2.原型图和基于需求文档的开发是编程人员对于产品功能设计的一种方式,整体的方式需要通过自己结合抽象的数据理念去理解对应的数据的流转才可以,一般情况下来说,基于原型的开发更符合我现在的模式和开发基础

3.下面来理一下对应的预约配置的相关的逻辑,其实要根据原型去写逻辑,相对操作还是比较难的,要理解原型图的抽象概念才能继续下去,否则没办法写;                                                          

1. 分析这个预约配置可以得出的结论有第一个分了一个全天,和时间段的概念,可以增加时间段

可以输入对应的预约日期,第一点需要分析的就是一个预约的功能选项卡就是一个对应的Controllere相关的RequestController对应的URI路径,通过分析对应的页面中对应的元素,可以得到的信息有,两个单选的按钮,一个时间段的输入框,一个输入框,两个额按钮,然后进行保存操作,在进行保存操作的时候通常需要开启事务相关的注解,

@Transactional(rollbackFor = Exception.class)

可以看到这个里面有多条信息进行保存的操作即就是可以添加多条的信息操作,这个里面就涉及和上次一样也涉及到了内部类的 操作,所以在这个额里面就是需要配置一个list去接受对应的子列表的集合信息;

@Data
@NoArgsConstructor
@ApiModel(description = "采样点预约时间配置")
public class AppointTimeConfigInCheckPointDTO {

    @ApiModelProperty("采样点 id")
    @NotBlank(message = "check_point_id 不能为空")
    private String checkPointId;

    @ApiModelProperty("预约时间类型")
    @NotNull(message = "appoint_time_type 不能为 null")
    private AppointTimeType appointTimeType;

    @ApiModelProperty("预约时间段配置,需要按照开始时间正序排序,时间段不能交叠")
    private List<AppointTimePeriodConfig> appointTimePeriodConfigList;

    @ApiModelProperty("可预约日期")
    @NotNull(message = "days 不能为 null")
    private Integer days;

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class AppointTimePeriodConfig {

        @ApiModelProperty("开始时间,格式为 HHmmss")
        @JsonFormat(pattern = "HHmmss", timezone = "GMT+8")
        private LocalTime startTime;

        @ApiModelProperty("结束时间,格式为 HHmmss")
        @JsonFormat(pattern = "HHmmss", timezone = "GMT+8")
        private LocalTime endTime;

    }

    public AppointTimeConfigInCheckPointDTO(List<AppointTimeConfig> appointTimeConfigList) {
        if (!CollectionUtils.isEmpty(appointTimeConfigList)) {
            AppointTimeConfig appointTimeConfig = appointTimeConfigList.get(0);
            BeanUtils.copyProperties(appointTimeConfig, this);
            if (AppointTimeType.TIME_PERIOD.equals(appointTimeConfig.getAppointTimeType())) {
                List<AppointTimePeriodConfig> timePeriodConfigList = new ArrayList<>(appointTimeConfigList.size());
                appointTimeConfigList.forEach(atc -> timePeriodConfigList.add(
                        new AppointTimePeriodConfig(atc.getStartTime(), atc.getEndTime())
                ));
                this.appointTimePeriodConfigList = timePeriodConfigList;
            }
        }
    }

上面这个DTO的配置写的也是很神奇的一种操作,在进行操作的时候需要进行相关的设置和相关的列表的集合的配置,如果对应的dto设置的type是时间段类型才可以进行操作,如果不是时间段类型就不能进行存储时间段范围信息的操作,

这个时候通常来说进行保存操作的时候,则需要进行相关的先要获取UI用那个的配置列表信息,如果配置列表信息中的内容不为空,则直接将删除标志设置我true,然后再进行保存吃操作,就可以将对应的设置信息保存到对应的预约时间列表内容中了,通常来说对应的保存操作都是先查在保存

 @Transactional(rollbackFor = Exception.class)
    public void save(AppointTimeConfigInCheckPointDTO appointTimeConfig) {
        List<AppointTimeConfig> oldAppointTimeConfigList = getAppointTimeConfigList(appointTimeConfig.getCheckPointId());
        if (!CollectionUtils.isEmpty(oldAppointTimeConfigList)) {
            oldAppointTimeConfigList.forEach(atc -> atc.setDelFlag(true));
        }
        oldAppointTimeConfigList.addAll(AppointTimeConfig.build(appointTimeConfig));
        appointTimeConfigRepository.saveAll(oldAppointTimeConfigList);
    }

2.下面看相关的时间段的对应的配置信息,可以根据时间段的配置信息来进行相关的选择配置。

保存时间段对应的配置的时候,因为上面是可以多条添加的时间信息,在进行相关的配置的时候,需要进行时间段的信息的获取和相关的配置,这个时候,需要将对应的添加的多段的时间段配置信息转换为对应的DTO配置信息,先根据对应的ID 集合,获取对应的配置信息列表集合,判断当前的配置信息列表是否是空,如果不为空,则直接进行判断循环将当前遍历出来的这些时间段信息设置为不可访问,然后再进行buid将对应的时间段信息转换为config,信息,

因为传过来的config会是有未来时间和多条的时间配置信息,所以在将对应的时间配置信息在进行相关的配置的时候会有时候可以将对应的多条信息进行批量处理的操作,在操作的时候需要对多条信息进行处理,下面多条处理操作,则需要进行转换,将对应的DTO进行处理。这个处理其实就是将对应的entity转换为DTO,因为对应的repository也是将对应的entity转换为DTO在去进行添加的;

整个判断的逻辑执行,这个里面有一个Collections.singltoList,这个是会返回一个List里面的当前的元素的集合,在进行判断的时候需要进行这个工具类之前没有遇到过这个工具类的singletoList是只会返回当前List中的受个元素的位置的第一个元素,如下例子所示:

import java.util.*;
public class CollectionsSingletonListExample2 {
    public static void main(String[] args) {             
        //Create an array of string objects
          String str[] = { "One", "Two", "Three", "One", "Two", "Three", "lidihuo" };         
          //Create one list
          List<String> list = new ArrayList<String>(Arrays.asList(str));       
          System.out.println("List value before: "+list);          
          //Create singleton list
          list = Collections.singletonList("One");      
          System.out.println("List value after: "+list);
          }
}
List value before: [One, Two, Three, One, Two, Three, lidihuo]
List value after: [One]

判断就是当前的如果dto中的类型是全天的类型,那么返回的时间段其实就可以忽略了,任意返回一条就可以了,这种写法是比较规范和整洁的,另一种情况就是返回的不是全天的时间段,那么当前需要进行整理的就是要进行相关的设置和取数的逻辑了,在进行取数的时候,进行操作。

首先获取对应的多个时间段的配置信息和相关的设置,设置完之后在拿到对应的时间段对应的设置和配置设置,在进行配置设置的时候,先遍历对应的时间段配置设置,去获取对应的开始时间和对应的结束时间的设置,在将对应的多条时间段开始时间和结束时间,设置到dto里面,因为遍历的是dto里面的list,所以每一条的时间段配置都可以获取到,在将对应的时间段配置条件到时间段配置list中,这个转换其实是dto转换成list,操作的时候还是需要注意一下的。

在进行Buid完之后就可以将对应的时间段信息存储到数据库中了,在进行存储的时候需要注意地方就是内部类转换为entity中的设置相关的内容,其他地方没有需要进行过多的处理;

3.在关联这个采样点数量的时候,这个地方需要进行相关的判断和设置,因为这个关联采样点数量的字段,不是从库里面直接得出来的,而是一个医院下属的采样点,然后根据一个医院有多少个采样点进行设置的,这个count数是关联出来的,而不是直接从库里面取出来的,这个地方就需要进行相关的配置设置,部分代码截图

 List<String> ids = hospitalPage.stream().map(Hospital::getId).collect(Collectors.toList());
        Map<String, Integer> checkpointCountMap = findAllByHospitalIds(ids);
        List<HospitalOutputDTO> collect = hospitalPage.stream().map(hospital -> {
            HospitalOutputDTO hospitalOutputDTO = new HospitalOutputDTO(hospital);
            if (checkpointCountMap.containsKey(hospital.getId())) {
                hospitalOutputDTO.setCheckpointSum(checkpointCountMap.get(hospital.getId()));
            }
            return hospitalOutputDTO;
        }).collect(Collectors.toList());

public Map<String, Integer> findAllByHospitalIds(List<String> hospitalIds) {
        List<HospitalCheckpoint> relations = hospitalCheckpointRepository.findAllByDelFlagIsFalseAndHospitalIdIn(hospitalIds);
        if (CollectionUtils.isEmpty(relations)) {
            return new HashMap<>(0);
        }
        Map<String, Integer> countMap = new HashMap<>(32);
        for (HospitalCheckpoint relation : relations) {
            if (countMap.containsKey(relation.getHospitalId())) {
                countMap.put(relation.getHospitalId(), countMap.get(relation.getHospitalId()) + 1);
                continue;
            }
            countMap.put(relation.getHospitalId(), 1);
        }
        return countMap;
    }

在进行设置和相关判断的时候,我可以获取到对应的医院的IDS的集合,统一有ID组成的列表信息,然后根据对应的ids的集合信息去找对应的countMap信息,在进行统计汇算的时候,这个地方需要进行特殊的处理,首先是医院的IDS集合,进行查找的时候,回去拿医院ID去中间表查询对应的医院的记录条数,如果,不为空,就要遍历每一条关联关系,这个需要用对应的countMap进行相关的处理了

========================================================================

这个地方需要插一下就是注解的作用,在进行相关的设置的时候,注解的作用不可谓不大,在进行相关的一开始不太明白系统中的注解如何使用;

  1. @interface 用来定义一个自定义注解

在Java中,定义注解其实和定义接口差多不,只需要在interface前添加一个@符号就可以,即 @interface Zhujie{ },这就表明我们定义了一个名为 @Zhujie 的注解。

注解中的方法即为注解的元素,元素中不能包含参数,返回值只能为简单数据类型、String、Class、emnus、注释 和这些类型的数组

//自定义注解 @Zhujie ,该注解有两个元素 personId、company
public @interface Zhujie(){
    int personId(); //元素1
    String company() default "[unassigned]"; //元素2
}

 注解定义完之后就可以使用了,注解是一种特殊的修饰符,在其他修饰符(例如,public、static 或者 final 等)使用地方都可以使用注解。按照惯例,注解应该放在其他修饰符的前面。注解的声明用@符号后面跟上这个注解类型的名字,再后面加上括号,括号中列出这个注释中元素的key-value对,其中,元素名为key ,值必须是常量。例如:

@Zhujie(personId=20151120,company="YeePay")

如果注解中只有一个元素且元素名字为 value,那么在使用这个注解的时候,元素的名字和等号都可以省略,例如: 

public @interface Zhujie(){
    String value();
}
//使用方式

@Zhujie(value="hello")
或
@Zhujie("hello")

2.当我们使用@interface定义一个注解时,需要确定这个注解的生命周期和需要用到哪些地方。这就用到了注解的注解--元注解,其中@Retention 用来确定这个注解的生命周期;@Target 指定注解使用的目标范围(类、方法、字段等) 

 在系统中的注解的使用其实,主要还是起到了标识的作用,在进行标识的时候,需要进行特殊的处理

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ClientAuthorize {

    ClientId[] value();
}
@ApiOperation("保存居委会")
    @PostMapping("/community")
    @SiteTypeAuthorize(SiteType.ADMIN)
    public ObjectResponse<Void> saveCommunitySite(@ApiIgnore Session session,
                                                  @Valid @RequestBody CommunitySiteDTO communitySiteDTO) {
        siteService.saveCommunity(session.getSiteId(), session.getSiteType(), communitySiteDTO, null);
        return new ObjectResponse<>();
    }

可以由图中看到的设置,在使用自定义注解的地方在进行设置的时候直接使用,他就会判断当前的方法的类型,是什么情况下才会去调用,其实注解的作用还是非常的明显的,这样写会让代码显的更加的规范,

注解的作用 1.生成文档 2.编译检测 3.编译时动态处理 4.运行时动态处理

=========================================================================

在进行相关的文件上传的时候,需要进行校验判断的是相关设置,其实之前在进行核酸的扫码的时候,一直会有一个采样端,采样端是干什么用的呢,采样端就是负责采取当前用户的居民的信息的

扫码的时候,会读取里面的二维码的内容然后再进行相关的内容的解析配置

这个直接使用系统中自由的FileController就可以进行相关的配置设置,可以读取里面的设置内容的信息就可以解析相关额图片里面的内容了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值