在区域人员端写任务管理时,需要获取登录人员管理的居民。这时候,一个问题就出现了——如何在后台实现这些功能呢?我们可以发现,前台并没有将当前登录的用户传递给后台,所以理论上应该直接从后台获取当前登录的用户。之前在住户管理的项目中也是如此,所以先总结一下。将相应的分页查询数据传递给后台C层后,后台直接调用residentService.page方法。publicPagepage(Stringname,...Pageablepageable){Districtdistrict=this.filterDistrictOfCurrentUserAccess(districtId);Specificationspecification=this.getSpec(name,...beVaccinated);Pageresidents=this.residentRepository.findAll(specification,pageable);返乡居民;}我们可以发现,通过filterDistrictOfCurrentUserAccess方法获取到当前登录人员的区域ID,并添加到综合查询条件中。其中,综合查询中属于某个区域的居民的查询就是这样进行的。publicstaticSpecificationbelongDistrict(District区){if(district==null||district.getId()==null||district.getType()==null||TYPE_COUNTY.equals(district.getType())){logger.debug("未传入region信息或regionID为null或传入的region为根region,忽略查询条件");返回Specification.where(null);}return(root,criteriaQuery,criteriaBuilder)->{logger.debug("按楼、区、社区、镇查询(默认)");JoinbuildingJoin=root.join("houses").join("building",JoinType.LEFT);LongdistrictId=district.getId();switch(district.getType()){caseTYPE_BUILDING:returncriteriaBuilder.equal(buildingJoin.get("id").as(Long.class),districtId);caseTYPE_VILLAGE:returncriteriaBuilder.equal(buildingJoin.join("parent").get("id").as(Long.class),districtId);caseTYPE_COMMUNITY:returncriteriaBuilder.equal(buildingJoin.join("parent",JoinType.LEFT).join("parent",JoinType.LEFT).get("id").as(Long.class),districtId);默认值:返回criteriaBuilder.equal(buildingJoin.join("parent",JoinType.LEFT).join("parent",JoinType.LEFT).join("parent",JoinType.LEFT).get("id").as(Long.class),districtId);}};}看起来很多,其实逻辑很简单。首先判断传入的区域信息是否完整。建筑的起始Join对象JoinbuildingJoin=root.join("houses").join("building",JoinType.LEFT);其中根代表居民,然后输入房屋的属性,然后输入建筑物的属性。criteriaBuilder.equal(buildingJoin.get("id").as(Long.class),districtId);然后根据传入的districtId查询等于buildingId的居民;接下来我们要做的就是根据传入的district.getType()进行分类讨论,即如果是社区,则在这个building的基础上获取parent,然后进行查询。那么我们就来看看在实际项目中如何获取当前登录的用户,获取其区域ID。首先,过滤传入的分区。如果传入的是districtId,则检查当前登录的用户是否具有传入小区ID的管理权限。经许可,归还相应区域;未经许可,返回当前登录用户所在区域;如果没有传入districtId,则直接返回登录用户所在的区域。在这种情况下,我们首先讨论如何获取当前登录的用户。publicOptionalgetCurrentLoginWebUser(){returnthis.webUserRepository.findById(this.getCurrentLoginWebUserId().orElseThrow(()->newAccessDeniedException("当前登录类型不正确或未登录")));}/**获取当前登录用户ID**/publicOptionalgetCurrentLoginWebUserId(){AuthUserDetailsauthUserDetails=this.userService.getAuthUserDetailWithoutTransaction().orElseThrow(()->newAccessDeniedException("当前登录类型是否错误登录”));如果(authUserDetailsinstanceofWebUser){returnOptional.of(((WebUser)authUserDetails).getId());}else{returnOptional.empty();}}publicOptionalgetAuthUserDetailWithoutTransaction(){logger.debug("根据Authentication获取当前登录用户名,并获取用户");身份验证authentication=SecurityContextHolder.getContext().getAuthentication();if(authentication!=null){AuthUserDetailsuserDetail;if(authenticationinstanceofUsernamePasswordAuthenticationToken){userDetail=(AuthUserDetails)authentication.getPrincipal();}elseif(authenticationinstanceofAuthUserDetails){userDetail=(AuthUserDetails)authentication;}elseif(authenticationinstanceofAnonymousAuthenticationToken){al.prowse){al.prowse)(newRuntimeException("获取类型不正确");}returnOptional.of(userDetail);}logger.debug("已认证用户不正确notexistinthedatabase");returnOptional.empty();}根据上面的代码,我们可以发现SpringBoot已经封装了部分登录,登录后我们只需要下面这部分代码就可以获取信息当前登录用户的Authenticationauthentication=SecurityContextHolder.getContext().getAuthentication();分类讨论类型,转换为AuthUserDetails问题2使用前后端登录后,菜单界面消失,但可以手动输入地址进入想要的页面。所以首先要了解菜单是如何获取的,先用前端测试一下,发现可以正常显示菜单。然后去前端代码里找,发现每个菜单都配了一个对应用户的角色选项。{name:'EmployedPersons',url:'employed-persons',icon:'fafa-user',roles:[ROLE_TYPE.volunteer.value,ROLE_TYPE.admin.value]}以下是获取菜单的方法:this.userService.currentLoginUser$.subscribe(user=>{console.log(user);constroleKeys=user?user.roles.map(role=>role.value):[];subscribe.next(MenuService.menus.filter(menu=>{constmenuRoleKeys=menu.roles;letfound=false;menuRoleKeys.forEach(roleKey=>{if(!found&&(roleKeys.indexOf(roleKey)!==-1)){found=true;}});返回找到;}));});先获取当前登录用户的角色数组,然后判断是否在菜单中匹配角色数组返回搜索结果,于是尝试打印获取到的role:,发现roles确实为空,并且然后去数据库查,发现role_user的关系联表确实是空的,再次添加上面的关系后就恢复正常了。