springboot第28集:springboot一些概念

news2024/12/24 21:24:55
DataScopeAspect 
数据过滤处理

此切面在执行带有@ControllerDataScope注解的方法之前进行数据权限过滤。首先获取当前登录用户,然后判断当前用户是否为超级管理员。如果不是超级管理员,则获取权限字符,默认使用上下文中的权限字符。接下来,根据用户的角色和数据范围类型进行数据权限过滤。根据不同的数据范围类型,生成相应的SQL条件,并将其加入到参数中。最后,在拼接权限SQL之前,先清空参数中的params.dataScope参数,以防止注入。

注意:以上代码中涉及的StringUtilsSysUserSysRoleSysDept等类和方法是示例中的自定义类和方法,实际使用时需要根据项目的具体情况进行替换或实现。

  • @RestController: 表示这是一个控制器类,并且处理的请求返回的是 JSON 数据。

  • @Resource(name = "captchaProducer")@Resource(name = "captchaProducerMath"): 注入名为 "captchaProducer" 和 "captchaProducerMath" 的 Producer 对象。这里使用了 @Resource 注解,表示通过名称来注入对应的 Bean。

  • @Autowired: 注入 RedisCacheISysConfigService 对象。

  • @GetMapping("/captchaImage"): 处理 GET 请求路径为 "/captchaImage" 的请求。

  • AjaxResult: 一个自定义的结果封装类,用于返回响应结果。

用于表示路由的元数据。包括路由的标题(title)、图标(icon)、是否缓存(noCache)和内链地址(link)。

  1. @Service: 将类声明为一个服务类,由Spring进行管理。

  2. @Autowired: 自动装配依赖关系,将SysConfigMapperRedisCache注入到当前类中。

  3. @PostConstruct: 在构造函数执行完成后,执行init方法。用于在项目启动时初始化参数到缓存。

  4. @Override: 表示重写或实现了父类或接口的方法。

  5. @DataSource(DataSourceType.MASTER): 指定数据源为主数据源,用于数据库访问。

  6. config.setConfigId(configId): 设置SysConfig对象的configId属性值为configId

  7. return configMapper.selectConfig(config): 调用configMapperselectConfig方法查询参数配置信息并返回。

  8. String configValue = Convert.toStr(redisCache.getCacheObject(getCacheKey(configKey))): 从缓存中获取参数键对应的参数值。

  9. if (StringUtils.isNotEmpty(configValue)) { return configValue; }: 如果参数值不为空,则直接返回参数值。

  10. config.setConfigKey(configKey): 设置SysConfig对象的configKey属性值为configKey

  11. SysConfig retConfig = configMapper.selectConfig(config): 调用configMapperselectConfig方法查询参数配置信息并赋值给retConfig

  12. if (StringUtils.isNotNull(retConfig)) { redisCache.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue()); return retConfig.getConfigValue(); }: 如果查询到参数配置信息,将其存入缓存,并返回参数值。

  13. return StringUtils.EMPTY;: 返回空字符串。

  14. String captchaEnabled = selectConfigByKey("sys.account.captchaEnabled"): 调用selectConfigByKey方法获取验证码开关的参数值。

  15. if (StringUtils.isEmpty(captchaEnabled)) { return true; }: 如果参数值为空,则返回true,表示开启验证码。

  16. return Convert.toBool(captchaEnabled): 将参数值转为布尔型并返回。

  17. return configMapper.selectConfigList(config): 调用configMapperselectConfigList方法查询参数配置列表并返回。

  18. int row = configMapper.insertConfig(config): 调用configMapperinsertConfig方法插入参数配置信息并将受影响的行数赋值给row

  19. if (row > 0) { redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); }: 如果插入成功,则将参数配置信息存入缓存。

  20. SysConfig temp = configMapper.selectConfigById(config.getConfigId()): 调用configMapperselectConfigById方法查询旧的参数配置信息并赋值给temp

  21. if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey())) { redisCache.deleteObject(getCacheKey(temp.getConfigKey())); }: 如果参数键发生变化,则从缓存中删除旧的参数配置信息。

  22. int row = configMapper.updateConfig(config): 调用configMapperupdateConfig方法更新参数配置信息并将受影响的行数赋值给row

  23. if (row > 0) { redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); }: 如果更新成功,则将新的参数配置信息存入缓存。

  24. for (Long configId : configIds) { SysConfig config = selectConfigById(configId); ... }: 遍历要删除的参数ID,调用selectConfigById方法查询参数配置信息并判断是否允许删除内置参数,然后调用deleteConfigById方法删除参数配置信息,并从缓存中删除。

  25. List<SysConfig> configsList = configMapper.selectConfigList(new SysConfig()): 调用configMapperselectConfigList方法查询参数配置列表并赋值给configsList

  26. redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()): 将参数配置信息存入缓存。

  27. Collection<String> keys = redisCache.keys(CacheConstants.SYS_CONFIG_KEY + "*"): 获取所有参数配置的缓存键。

  28. redisCache.deleteObject(keys): 清空缓存。

  29. clearConfigCache(): 清空参数缓存数据。

  30. loadingConfigCache(): 加载参数缓存数据。

  31. Long configId = StringUtils.isNull(config.getConfigId()) ? -1L : config.getConfigId(): 获取参数配置ID,如果为空则设置为-1。

  32. SysConfig info = configMapper.checkConfigKeyUnique(config.getConfigKey()): 调用configMappercheckConfigKeyUnique方法查询是否存在相同的参数键名。

  33. if (StringUtils.isNotNull(info) && info.getConfigId().longValue() != configId.longValue()) { return UserConstants.NOT_UNIQUE; }: 如果存在相同的参数键名且不是当前配置的参数键名,则返回false

  34. return UserConstants.UNIQUE;: 参数键名唯一,返回true

  35. return CacheConstants.SYS_CONFIG_KEY + configKey: 返回缓存键。

  36. private String getCacheKey(String configKey): 私有方法,用于获取缓存键。

roleMapper.selectRolePermissionByUserId(userId)查询角色权限列表。然后,创建一个空的权限集合permsSet。接下来,遍历角色权限列表,对每个角色进行处理。如果角色对象perm不为空,则将其角色权限的roleKey字段按逗号分隔后转换为列表,并将列表中的权限添加到permsSet集合中。最后,返回权限集合permsSet,该集合包含了用户拥有的所有角色权限。

adb4eda0640653fed8a69e627399427b.png
image.png
7ac743792aef457471242559291d694a.png
image.png
ISysConfigService
ISysMenuService

定义完ISysDictDataService接口后,您需要创建一个实现类来继承该接口。在Java中,接口定义了一组方法的契约或规范,但它们并不提供这些方法的实际实现。实现类负责为接口中声明的每个方法提供具体的实现。

如果不编写实现类,那么ISysDictDataService接口将仅仅是一个接口的定义,没有具体的实现逻辑。在这种情况下,其他部分的代码将无法直接调用接口中定义的方法,因为没有实现提供实际的方法实现。

接口本身是一种规范或契约,它定义了一组方法的签名,用于指导实现类的开发。实现类负责提供方法的实际逻辑和功能。

如果您不编写实现类,那么接口只是一个接口声明,它可能会在代码中的其他地方作为类型或约定使用,但不能直接调用其方法。

通常情况下,我们会编写实现类来实现接口中定义的方法,以便在需要时可以实际调用这些方法并执行相应的逻辑。如果没有实现类,接口的定义将没有具体的实际用途。

因此,为了能够使用接口中定义的方法,您需要编写一个实现类来提供具体的方法实现。这样,其他部分的代码可以通过实例化实现类并调用接口中的方法来使用这些功能

在Java中,接口(interface)是一种抽象类型,它定义了一组方法的签名但没有具体的实现。当您编写完ISysDictDataService接口后,并不需要强制编写一个实现类去继承它。

编写实现类的目的是为了提供接口中定义的方法的具体实现逻辑。如果不编写实现类,编译过程不会报错,因为接口本身不需要被实例化或直接调用。

然而,如果其他部分的代码(如其他类或方法)试图调用ISysDictDataService接口中的方法,而没有相应的实现类提供具体实现,那么在运行时会抛出java.lang.UnsupportedOperationException异常。

因此,虽然不是强制要求编写实现类,但通常情况下,为了能够使用接口中定义的方法

  • @Override:注解表示该方法是对父类或接口的重写。

  • public boolean checkRoleNameUnique(SysRole role):方法签名,指定了该方法的访问修饰符、返回类型和参数。

  • Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId();:使用三元运算符判断角色ID是否为空,如果为空,则将roleId赋值为-1,否则为角色的实际ID。

  • SysRole info = roleMapper.checkRoleNameUnique(role.getRoleName());:调用roleMapper对象的checkRoleNameUnique方法,根据角色名查找角色信息,并将结果赋值给info变量。

  • if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue()):判断info对象不为空且角色ID与roleId不相等。

    • StringUtils.isNotNull(info):调用StringUtils类的isNotNull方法判断info是否不为空。

    • info.getRoleId().longValue() != roleId.longValue():将info对象的角色ID与roleId进行比较,判断是否相等。

  • return UserConstants.NOT_UNIQUE;:如果角色名不唯一,则返回UserConstants.NOT_UNIQUE,表示角色名不唯一。

  • return UserConstants.UNIQUE;:如果角色名唯一,则返回UserConstants.UNIQUE,表示角色名唯一。

该方法用于检查角色键值是否唯一。

  • @Override:注解表示该方法是对父类或接口的重写。

  • public boolean checkRoleKeyUnique(SysRole role):方法签名,指定了该方法的访问修饰符、返回类型和参数。

  • Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId();:使用三元运算符判断角色ID是否为空,如果为空,则将roleId赋值为-1,否则为角色的实际ID。

  • SysRole info = roleMapper.checkRoleKeyUnique(role.getRoleKey());:调用roleMapper对象的checkRoleKeyUnique方法,根据角色键值查找角色信息,并将结果赋值给info变量。

  • if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue()):判断info对象不为空且角色ID与roleId不相等。

    • StringUtils.isNotNull(info):调用StringUtils类的isNotNull方法判断info是否不为空。

    • info.getRoleId().longValue() != roleId.longValue():将info对象的角色ID与roleId进行比较,判断是否相等。

  • return UserConstants.NOT_UNIQUE;:如果角色键值不唯一,则返回UserConstants.NOT_UNIQUE,表示角色键值不唯一。

  • return UserConstants.UNIQUE;:如果角色键值唯一,则返回UserConstants.UNIQUE,表示角色键值唯一。

  • @Override:注解表示该方法是对父类或接口的重写。

  • public void checkRoleAllowed(SysRole role):方法签名,指定了该方法的访问修饰符、返回类型和参数。

  • if (StringUtils.isNotNull(role.getRoleId()) && role.isAdmin()):判断角色的ID不为空且角色为超级管理员。

    • StringUtils.isNotNull(role.getRoleId()):调用StringUtils类的isNotNull方法判断角色的ID是否不为空。

    • role.isAdmin():调用role对象的isAdmin方法判断角色是否为超级管理员。

  • throw new ServiceException("不允许操作超级管理员角色");:抛出ServiceException异常,提示不允许操作超级管理员角色。

  • @Service: 标识这是一个服务类,用于处理业务逻辑。

  • public class SysMenuServiceImpl implements ISysMenuService: 定义了一个名为 SysMenuServiceImpl 的类,该类实现了 ISysMenuService 接口。

  • public static final String PREMISSION_STRING = "perms["{0}"]";: 声明了一个名为 PREMISSION_STRING 的常量,用于定义权限字符串的格式。

  • @Autowired: 自动注入依赖对象。

  • private SysMenuMapper menuMapper;: 声明了一个私有字段 menuMapper,用于访问菜单数据的对象。

  • private SysRoleMapper roleMapper;: 声明了一个私有字段 roleMapper,用于访问角色数据的对象。

  • private SysRoleMenuMapper roleMenuMapper;: 声明了一个私有字段 roleMenuMapper,用于访问角色菜单关系数据的对象。

  • @Override: 表示该方法是对父类或接口中同名方法的重写。

  • public List<SysMenu> selectMenuList(Long userId): 声明了一个公共方法 selectMenuList,接受一个 Long 类型的参数 userId,返回一个 SysMenu 类型的列表。

  • return selectMenuList(new SysMenu(), userId);: 调用另一个名为 selectMenuList 的方法,并传递一个新创建的 SysMenu 对象和 userId 参数作为参数。

  • @Override: 表示该方法是对父类或接口中同名方法的重写。

  • public List<SysMenu> selectMenuList(SysMenu menu, Long userId): 声明了一个公共方法 selectMenuList,接受一个 SysMenu 类型的参数 menu 和一个 Long 类型的参数 userId,返回一个 SysMenu 类型的列表。

  • List<SysMenu> menuList = null;: 声明了一个名为 menuList 的变量,类型为 List<SysMenu>,初始值为 null

  • if (SysUser.isAdmin(userId)): 判断当前用户是否是管理员。

  • menuList = menuMapper.selectMenuList(menu);: 如果当前用户是管理员,则调用 menuMapper 对象的 selectMenuList 方法来获取所有菜单信息。

  • menu.getParams().put("userId", userId);: 如果当前用户不是管理员,则将用户ID存储到 menu 对象的参数中。

  • menuList = menuMapper.selectMenuListByUserId(menu);: 调用 menuMapper 对象的 selectMenuListByUserId 方法来根据用户ID获取菜单列表。

  • return menuList;: 返回菜单列表。

  • @Override: 表示该方法是对父类或接口中同名方法的重写。

  • public List<Long> selectMenuListByRoleId(Long roleId): 声明了一个公共方法 selectMenuListByRoleId,接受一个 Long 类型的参数 roleId,返回一个 List<Long> 类型的结果。

  • SysRole role = roleMapper.selectRoleById(roleId);: 调用 roleMapper 对象的 selectRoleById 方法,根据角色ID获取对应的角色信息,并将结果存储在 role 变量中。

  • return menuMapper.selectMenuListByRoleId(roleId, role.isMenuCheckStrictly());: 调用 menuMapper 对象的 selectMenuListByRoleId 方法,根据角色ID和角色的菜单严格检查属性获取对应的菜单列表,并作为方法的返回值。

  • @Override: 表示该方法是对父类或接口中同名方法的重写。

  • public List<RouterVo> buildMenus(List<SysMenu> menus): 声明了一个公共方法 buildMenus,接受一个 List<SysMenu> 类型的参数 menus,返回一个 List<RouterVo> 类型的结果。

  • List<RouterVo> routers = new LinkedList<RouterVo>();: 声明了一个名为 routers 的变量,类型为 List<RouterVo>,使用 LinkedList 初始化。

  • for (SysMenu menu : menus) { ... }: 遍历 menus 列表中的每个 SysMenu 对象,使用变量 menu 进行迭代。

  • RouterVo router = new RouterVo();: 创建一个新的 RouterVo 对象,用于存储路由信息。

  • router.setHidden("1".equals(menu.getVisible()));: 根据 menu 对象的 visible 属性设置路由是否隐藏。

  • router.setName(getRouteName(menu));: 调用 getRouteName 方法获取路由名称,并设置到 router 对象中。

  • router.setPath(getRouterPath(menu));: 调用 getRouterPath 方法获取路由路径,并设置到 router 对象中。

  • router.setComponent(getComponent(menu));: 调用 getComponent 方法获取路由组件,并设置到 router 对象中。

  • router.setQuery(menu.getQuery());: 设置路由的查询参数为 menu 对象的 query 属性。

  • router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));: 创建一个新的 MetaVo 对象,设置其属性值为 menu 对象的相关属性,并将其设置为 router 对象的元数据。

  • List<SysMenu> cMenus = menu.getChildren();: 获取当前菜单的子菜单列表。

  • if (StringUtils.isNotEmpty(cMenus) && UserConstants.TYPE_DIR.equals(menu.getMenuType())) { ... }: 如果子菜单列表不为空且当前菜单类型为目录类型。

  • router.setAlwaysShow(true);: 设置路由是否总是显示为 true

  • router.setRedirect("noRedirect");: 设置路由的重定向为 "noRedirect"

  • router.setChildren(buildMenus(cMenus));: 递归调用 buildMenus 方法构建子菜单的路由,并将结果设置为当前路由的子路由。

  • else if (isMenuFrame(menu)) { ... }: 否则,如果当前菜单为菜单框架。

  • router.setMeta(null);: 清空路由的元数据。

  • List<RouterVo> childrenList = new ArrayList<RouterVo>();: 声明一个新的 ArrayList<RouterVo> 对象,用于存储子路由列表。

  • RouterVo children = new RouterVo();: 创建一个新的 RouterVo 对象,用于存储子路由信息。

  • children.setPath(menu.getPath());: 设置子路由的路径为当前菜单的路径。

  • children.setComponent(menu.getComponent());: 设置子路由的组件为当前菜单的组件。

  • children.setName(StringUtils.capitalize(menu.getPath()));: 设置子路由的名称为当前菜单路径的首字母大写形式。

  • children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));: 创建一个新的 MetaVo 对象,设置其属性值为当前菜单的相关属性,并将其设置为子路由的元数据。

  • children.setQuery(menu.getQuery());: 设置子路由的查询参数为当前菜单的查询参数。

  • childrenList.add(children);: 将子路由添加到子路由列表中。

  • router.setChildren(childrenList);: 设置子路由列表为当前路由的子路由列表。

  • else if (menu.getParentId().intValue() == 0 && isInnerLink(menu)) { ... }: 否则,如果当前菜单的父菜单ID为0且是内部链接。

  • router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon()));: 创建一个新的 MetaVo 对象,设置其属性值为当前菜单的名称和图标,并将其设置为当前路由的元数据。

  • router.setPath("/");: 设置当前路由的路径为根路径。

  • List<RouterVo> childrenList = new ArrayList<RouterVo>();: 声明一个新的 ArrayList<RouterVo> 对象,用于存储子路由列表。

  • RouterVo children = new RouterVo();: 创建一个新的 RouterVo 对象,用于存储子路由信息。

  • String routerPath = innerLinkReplaceEach(menu.getPath());: 调用 innerLinkReplaceEach 方法替换内部链接的路径。

  • children.setPath(routerPath);: 设置子路由的路径为替换后的路径。

  • children.setComponent(UserConstants.INNER_LINK);: 设置子路由的组件为内部链接组件。

  • children.setName(StringUtils.capitalize(routerPath));: 设置子路由的名称为替换后的路径的首字母大写形式。

  • children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath()));: 创建一个新的 MetaVo 对象,设置其属性值为当前菜单的相关属性,并将其设置为子路由的元数据。

  • childrenList.add(children);: 将子路由添加到子路由列表中。

  • router.setChildren(childrenList);: 设置子路由列表为当前路由的子路由列表。

  • routers.add(router);: 将当前路由添加到路由列表中。

  • return routers;: 返回路由列表作为方法的结果。

  • Long menuId = StringUtils.isNull(menu.getMenuId()) ? -1L : menu.getMenuId();:获取菜单ID,若菜单ID为空,则将其设为-1。

  • SysMenu info = menuMapper.checkMenuNameUnique(menu.getMenuName(), menu.getParentId());:调用菜单Mapper的checkMenuNameUnique方法,查询具有相同菜单名称和父菜单ID的菜单信息。

    • menu.getMenuName():获取菜单的名称。

    • menu.getParentId():获取菜单的父菜单ID。

  • if (StringUtils.isNotNull(info) && info.getMenuId().longValue() != menuId.longValue()) {...}:判断查询到的菜单信息是否存在且菜单ID与当前菜单ID不相同。

    • StringUtils.isNotNull(info):判断菜单信息是否不为空。

    • info.getMenuId().longValue() != menuId.longValue():判断查询到的菜单ID与当前菜单ID是否不相同。

  • return UserConstants.NOT_UNIQUE;:菜单名称不唯一,返回不唯一标识。

  • return UserConstants.UNIQUE;:菜单名称唯一,返回唯一标识。

  • @Service:用于标识该类为服务类,由Spring进行管理和注入。

  • public class SysConfigServiceImpl implements ISysConfigService:定义了类SysConfigServiceImpl,实现了接口ISysConfigService

  • @Autowired:自动注入依赖的对象。

  • private SysConfigMapper configMapper;:声明一个私有成员变量configMapper,用于访问SysConfigMapper对象。

  • private RedisCache redisCache;:声明一个私有成员变量redisCache,用于访问RedisCache对象。

  • @PostConstruct:在对象创建后,调用init方法进行初始化操作。

  • public void init():初始化方法,用于在项目启动时将参数加载到缓存中。

  • loadingConfigCache():自定义的方法,用于加载参数到缓存中。

  • @Override:表示该方法覆盖了父类或接口的同名方法。

  • @DataSource(DataSourceType.MASTER):指定数据源为主数据库,用于读取配置信息。

  • public SysConfig selectConfigById(Long configId):方法签名,指定了该方法的访问修饰符、返回类型和参数。

  • SysConfig config = new SysConfig();:创建一个SysConfig对象,用于设置查询条件。

  • config.setConfigId(configId);:将传入的configId设置为config对象的configId属性值。

  • return configMapper.selectConfig(config);:调用configMapperselectConfig方法,传入config对象作为参数,查询并返回匹配的配置信息对象。

该方法将给定的配置对象 config 插入到数据库中,使用 configMapperinsertConfig 方法执行插入操作,并返回受影响的行数。

如果插入成功(受影响的行数大于0),则将配置信息存储到 Redis 缓存中,使用 redisCachesetCacheObject 方法。

最后,返回插入结果(受影响的行数)。

注解中的 @param 表示方法的参数,@return 表示方法的返回值。

加群联系作者vx:xiaoda0423

仓库地址:https://github.com/webVueBlog/JavaGuideInterview

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/674572.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【计算机组成原理】2、二进制和十六进制转换,进制相减、内存地址偏移计算与容量计算

文章目录 一、进制转换1.1 二进制转十六进制1.2 十六进制转二进制 二、进制相减2.1 十六进制 三、内存地址偏移计算3.1 根据首末地址&#xff0c;求存储容量3.2 根据末地址 和 存储容量&#xff0c;求首地址 一、进制转换 1.1 二进制转十六进制 因 2 4 16 2^416 2416&#…

leetcode300. 最长递增子序列(动态规划-java)

最长递增子序列 leetcode300. 最长递增子序列题目描述解题思路代码演示: 二分法改进(N * logN)动态规划专题 leetcode300. 最长递增子序列 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/longest-increasing-subsequenc…

C++标准输出

C将输入和输出看作字节流&#xff0c;输入时&#xff0c;程序从输入流中抽取字节&#xff0c;输出时&#xff0c;程序将自己插入到输出流中&#xff0c;流充当了程序与流源或流目标之间的桥梁&#xff0c;也就是说C通过流与硬件&#xff0c;文件相关联&#xff0c;流赋予了C程序…

[数字图像处理]第六章 彩色图像处理

第六章 彩色图像处理 引言 ​ 彩色图像处理可分为两个主要领域&#xff1a;全彩色处理和伪彩色处理。在第一类中&#xff0c; 通常要求图像用全彩色传感器获取&#xff0c;如彩色电视摄像机或彩色扫描仪。在第二类中&#xff0c;问题是对一种特定的单色灰度或灰度范围赋予一种…

设计模式之装饰者模式笔记

设计模式之装饰者模式笔记 说明Decorator(装饰)目录装饰者模式示例类图快餐类炒饭类炒面类装饰者类鸡蛋类培根类测试类 说明 记录下学习设计模式-装饰者模式的写法。JDK使用版本为1.8版本。 Decorator(装饰) 意图:动态地给一个对象添加一些额外的职责。 结构: 其中&#x…

【Neo4j教程之CQL命令基本使用】

&#x1f680; Neo4j &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;C…

Python基础篇(二):入门基础必备知识

Python基础篇(一)&#xff1a;如何使用PyCharm创建第一个Python项目(包含tools) 入门基础必备知识 1. 标识符2. 关键字2.1 关键字字典 3. 引号3.1 表示字符串3.2 在字符串中使用引号3.3 创建多行字符串3.4 在注释中使用引号 4. 编码5. 输入输出5.1 输入示例5.2 输出示例5.3 格…

王道计算机网络学习笔记(3)——数据链路层

前言 文章中的内容来自B站王道考研计算机网络课程&#xff0c;想要完整学习的可以到B站官方看完整版。 三&#xff1a;数据链路层 3.1&#xff1a;数据链路层功能概述 结点&#xff1a;主机、路由器 链路&#xff1a;网络中两个结点之间的物理通道&#xff0c;链路的传输介…

PolarFormer:Multi-camera 3D Object Detection with Polar Transformer——论文笔记

参考代码&#xff1a;PolarFormer 1. 概述 介绍&#xff1a;在仓库RoboBEV中总结了现有的一些bev感知算法在不同输入情况下的鲁棒性&#xff0c;在这些感知算法中PolarFormer拥有较为不错的泛化性能。这个算法的思想是将之前由直角坐标系栅格化构建bev网格&#xff0c;转换到由…

Unity之透明度混合与ps的透明度混合计算结果不一致

一、问题 前段时间学习shader时发现了一个问题&#xff0c;一张纯红色透明度为128的图片叠加在一张纯绿色的图片上得出的结果与ps中的结果不一致。网上查找了ps中的透明混合的公式为 color A.rgb*A.alpha B.rgb*(1-A.alpha)。自己使用代码在unity中计算了一下结果总是不对。…

Python--异常处理

Python--异常处理 <font colorblue>一、异常<font colorblue>二、异常处理语句<font colorblue>1、try...except语句<font colorblue>2、try...except...else语句<font colorblue>3、try...except...finally语句<font colorblue>4、raise语…

leetcode354. 俄罗斯套娃信封问题(动态规划-java)

俄罗斯套娃信封问题 leetcode354. 俄罗斯套娃信封问题题目描述:解题思路代码演示 动态规划专题 leetcode354. 俄罗斯套娃信封问题 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/russian-doll-envelopes 题目描述: 给你…

c++学习之模板

目录 一&#xff0c;模板的概述 二&#xff0c;函数模板 1.函数模板的定义 2.函数模板的注意事项 3.函数模板的重载 4.函数模板的局限性 三&#xff0c;类模板 1.类模板的概念 2.类模板定义方式 3.类模板的成员函数在类外实现 4.函数模板作为类模板的友元 5.在写程…

《大学英语4》期末考试复习(一)听力原文+答案速记

目录 Unit 1 Long conversation Passage 1 Unit 2 Long conversation Passage 1 Unit 3 Long conversation Passage 1 Unit 4 Long conversation Passage 1 Unit 5 Long conversation Passage 1 Unit 6 Long conversation Passage 1 Unit 7 Long conversat…

Java线程池小结

目录 一.什么是线程池 二.线程池的好处是什么 三.四种基本线程池及其使用 newCachedThreadPool newFixedThreadPool newScheduledThreadPool newSingleThreadExecutor 线程池的四种拒绝策略 选择一:AbortPolicy 选择二:CallerRunsPolicy 选择三:DiscardPolicy 选择四…

【Java】Java核心要点总结70

文章目录 1. volatile 如何保证变量的可⻅性&#xff1f;2. volatile 可以保证原⼦性么&#xff1f;3. synchronized 关键字4. synchronized 和 volatile 的区别5. synchronized 和 ReentrantLock 的区别 1. volatile 如何保证变量的可⻅性&#xff1f; 在Java中&#xff0c;使…

html实现多种风格的时间轴(附源码)

文章目录 1.设计来源1.1 对称风格时间轴1.2 横向风格时间轴1.3 回忆风格时间轴1.4 记事风格时间轴1.5 简易风格时间轴1.6 科技风格时间轴1.7 列表风格时间轴1.8 跑道风格时间轴1.9 人物风格时间轴1.10 容器风格时间轴1.11 沙滩风格时间轴1.12 双边风格时间轴1.13 图文风格时间轴…

【verilog基础】时钟无毛刺切换电路 Clock Glitch Free

文章目录 一、时钟切换电路:容易产生毛刺二、时钟无毛刺切换电路:在S端增加一些控制通路三、异步时钟无毛刺切换电路:使用同步电路解决亚稳态问题四、真题题目解答一、时钟切换电路:容易产生毛刺 1、在芯片运行时经常需要切换时钟源,通常的实现方式是:通过mux来选择不同的…

用试题这把“剑“帮你破除指针与数组之间的那些猫腻

作者主页&#xff1a;paper jie的博客_CSDN博客-C语言,算法详解领域博主 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文录入于《系统解析C语言》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白…

【linux】在Linux系统开机的时候卡在/dev/nvme0n1p1:clean / files / blocks界面进不去

一、问题背景 开机的时候没办法开机&#xff0c;一直停留在下面这个界面。 x86/cpu: SGX disabled by BIOS dev/nvme0n1p3:clean, 21118/30523392 fies, 122066176/122070272 blocks dev/nvme0n1p4:clean, 486125/61038592 fies,21657184/244140544b1ocks 试过网上的一些方法…