关于java:总结一下本周遇到的问题

在写区域工作人员端工作治理时须要获取登陆人员所治理的居民,这时就呈现了一个问题——后盾要怎么实现这些性能呢?
咱们能够发现前台并没有把以后登录用户传给后盾,所以实践上应该是间接从后盾获取以后登录用户。
之前我的项目中在居民治理中也是这种状况,所以就先总结了一下。
把相应的分页查问数据传给后盾C层后,后盾就间接调用了residentService.page办法。

  public Page<Resident> page(String name,
                           . . .
                             Pageable pageable) {
    District district = this.filterDistrictOfCurrentUserAccess(districtId);
    Specification<Resident> specification = this.getSpec(name,
       . . .
        beVaccinated);
    Page<Resident> residents = this.residentRepository.findAll(specification, pageable);

    return residents;
  }

咱们能够发现这里通过了filterDistrictOfCurrentUserAccess办法获取了以后登陆人员的区域ID,并把它退出到综合查问条件中。
其中对于综合查问中查问属于某个地区的居民是这样做的。

  public static Specification<Resident> belongDistrict(District district) {
    if (district == null ||
        district.getId() == null ||
        district.getType() == null ||
        TYPE_COUNTY.equals(district.getType())) {
      logger.debug("未传入区域信息或区域ID为null或传入了区域为根区域,疏忽查问条件");
      return Specification.where(null);
    }

    return (root, criteriaQuery, criteriaBuilder) -> {
      logger.debug("别离按楼、小区、社区、乡镇(默认)进行查问");
      Join<Resident, Building> buildingJoin = root.join("houses")
          .join("building", JoinType.LEFT);
      Long districtId = district.getId();
      switch (district.getType()) {
        case TYPE_BUILDING:
          return criteriaBuilder.equal(buildingJoin.get("id").as(Long.class), districtId);
        case TYPE_VILLAGE:
          return criteriaBuilder.equal(buildingJoin.join("parent").get("id").as(Long.class),
              districtId);
        case TYPE_COMMUNITY:
          return criteriaBuilder.equal(buildingJoin
                  .join("parent", JoinType.LEFT)
                  .join("parent", JoinType.LEFT)
                  .get("id").as(Long.class),
              districtId);
        default:
          return criteriaBuilder.equal(buildingJoin
                  .join("parent", JoinType.LEFT)
                  .join("parent", JoinType.LEFT)
                  .join("parent", JoinType.LEFT)
                  .get("id").as(Long.class),
              districtId);
      }
    };
  }

看起来很多其实逻辑很简略,先是判断传入的区域信息是否残缺,若不残缺则返回null。
之后因为查问的最小单位是楼所以间接结构了一个从building起始的Join对象

Join<Resident, Building> buildingJoin = root.join("houses")
          .join("building", JoinType.LEFT);

其中的root代表的就是resident,之后进入houses属性再进入building属性。

criteriaBuilder.equal(buildingJoin.get("id").as(Long.class), districtId);

再依据传入的districtId查问等于buildingId的resident;
之后咱们要做的就是依据传入的district.getType()进行分类探讨即如果是小区的话那么就在此building根底上获取parent再进行查问。

之后咱们再来看一下在理论我的项目中是如何获取以后登陆用户并获取其区域ID的。
先是过滤一下传入的district,如果传入了districtId,则看以后登录用户是否领有传入的区域ID的管理权限。有权限,返回对应区域;无权限,返回以后登录用户所在区域;如果未传入districtId间接返回登录用户所在区域。

在此状况下咱们先探讨如何获取以后登陆用户。

public Optional<WebUser> getCurrentLoginWebUser() {
    return this.webUserRepository.findById(this.getCurrentLoginWebUserId()
        .orElseThrow(() -> new AccessDeniedException("以后登录类型不正确或未登录")));
  }

/**
获取以后登陆用户ID
**/
public Optional<Long> getCurrentLoginWebUserId() {
    AuthUserDetails authUserDetails = this.userService.getAuthUserDetailWithoutTransaction()
        .orElseThrow(() -> new AccessDeniedException("以后登录类型不正确或未登录"));
    if (authUserDetails instanceof WebUser) {
      return Optional.of(((WebUser) authUserDetails).getId());
    } else {
      return Optional.empty();
    }
  }
  public Optional<AuthUserDetails> getAuthUserDetailWithoutTransaction() {
    logger.debug("依据认证获取以后登录用户名,并获取该用户");
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    if (authentication != null) {
      AuthUserDetails userDetail;
      if (authentication instanceof UsernamePasswordAuthenticationToken) {
        userDetail = (AuthUserDetails) authentication.getPrincipal();
      } else if (authentication instanceof AuthUserDetails) {
        userDetail = (AuthUserDetails) authentication;
      } else if (authentication instanceof AnonymousAuthenticationToken) {
        return Optional.empty();
      } else {
        throw new RuntimeException("获取类型不正确");
      }
      return Optional.of(userDetail);
    }

    logger.debug("认证用户在数据库中不存在");
    return Optional.empty();
  }

根据上述代码咱们能够发现SpringBoot曾经对登陆进行了一部分的封装,咱们在登陆后只需上面这部分代码就可获取以后登陆用户的信息

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

之后咱们在再依据返回的对象的类型进行分类探讨并把它转化为AuthUserDetails即可。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理