结构性模式-门面模式/外观模式

结合SpringBoot中的自定义starter中间件开发的方式,统一处理所有需要白名单的地方

对接口的包装提供出接口服务的门面模式后面补充

在这里插入图片描述

设计知识点

自定义注解的使用

  1. @Retention(RetentionPolicy.RUNTIME)
    @Retention 注解用于指定自定义注解的保留策略。RetentionPolicy.RUNTIME 表示该注解在运行时也可见,因此可以通过反射机制读取。
  2. @Target(ElementType.METHOD)
    @Target 注解用于指定自定义注解可以应用的 Java 元素类型。ElementType.METHOD 表示这个注解只能应用于方法上。
  3. key() default “”:当在方法上使用 @DoDoor 注解时,可以选择性地提供 key 的值,如果不提供,则默认为空字符串
  4. returnJson() default “”::当在方法上使用 @DoDoor 注解时,可以选择性地提供 key 的值,如果不提供,则默认为空字符串
    总结:@DoDoor 是一个自定义注解,可以应用于方法上,并提供两个可选的元素 key 和 returnJson。使用此注解可以为方法添加额外的元数据,这些元数据可以在运行时通过反射被读取和使用
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DoDoor {

    String key() default "";

    String returnJson() default "";

}

SpringBoot的starter中间件开发方式
流程:StarterServiceProperties读取application.yml配置文件中配置内容,并将配置文件内容的值设置给StarterServiceProperties类的属性,StarterAutoConfigure类引入StarterServiceProperties类型的属性并在方法中获取StarterServiceProperties从配置文件获取的值设置给starterService类的属性
在这里插入图片描述

StarterServiceProperties 类使用了 @ConfigurationProperties(“itstack.door”) 注解,spring Boot 会查找配置文件(如 application.properties 或 application.yml)中前缀为 itstack.door 的属性,并将它们自动绑定到 StarterServiceProperties 类的字段上。StarterServiceProperties 类中,定义了一个 userStr 字段,以及对应的 getter 和 setter 方法, Spring Boot 通过反射调用这些方法来设置字段的值。

@ConfigurationProperties("itstack.door")
public class StarterServiceProperties {

    private String userStr;

    public String getUserStr() {
        return userStr;
    }

    public void setUserStr(String userStr) {
        this.userStr = userStr;
    }

}

@Configuration 注解表明该类是一个配置类,它定义了一个或多个 @Bean 方法,这些方法会被 Spring 容器处理,生成 Spring 管理的 bean。在自动配置类中,通常不直接定义 @Bean 方法,而是使用其他机制(如条件注解)来间接地配置 beans。
@ConditionalOnClass 是一个条件注解,它表明只有在指定的类存在于类路径上时,才会应用配置。@ConditionalOnClass(StarterService.class) 表示只有当 StarterService 类在类路径上可用时,StarterAutoConfigure 类的配置才会被激活。
@EnableConfigurationProperties(StarterServiceProperties.class) 表示 Spring Boot 会将 StarterServiceProperties 类中的属性绑定到配置文件中的属性,并将 StarterServiceProperties 的实例作为 bean 注册到 Spring 容器中,以便在其他地方注入使用
@Bean: 这个注解告诉 Spring 容器这个方法会返回一个StarterService 对象,并且这个对象会被 Spring 管理。
@ConditionalOnMissingBean: 这个注解表示只有当 Spring 容器中不存在指定类型的 bean 时,当前带有 @Bean 注解的方法才会被执行
@ConditionalOnProperty:据配置文件中的属性值来决定是否创建 bean,只有当 itstack.door.enabled 的值为 true 时,starterService 方法才会被执行,进而创建 StarterService 类型的 bean

@Configuration
@ConditionalOnClass(StarterService.class)
@EnableConfigurationProperties(StarterServiceProperties.class)
public class StarterAutoConfigure {

    @Autowired
    private StarterServiceProperties properties;

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = "itstack.door", value = "enabled", havingValue = "true")
    StarterService starterService() {
        return new StarterService(properties.getUserStr());
    }

}

StarterService

public class StarterService {

    private String userStr;

    public StarterService(String userStr) {
        this.userStr = userStr;
    }

    public String[] split(String separatorChar) {
        return StringUtils.split(this.userStr, separatorChar);
    }

}

面向切面编程和反射
@Aspect 注解用于标识一个类作为切面(Aspect),而 @Component 注解则用于将类声明为 Spring 容器管理的组件。由于 DoJoinPoint 类被标记为 @Component,Spring 会在启动时自动扫描并创建这个类的实例,并将其作为切面注册到 AOP 代理中。这样,当应用运行时,任何匹配 doorPointcut 切点的方法调用都会触发相应的通知逻辑。
在 Spring AOP(Aspect-Oriented Programming,面向切面编程)中,@Pointcut 注解用于定义一个切点(pointcut),即一个或多个连接点(joinpoint)的集合,这些连接点通常对应于方法执行异常抛出等程序执行过程中的特定点。
定义了一个切点 aopPoint,它匹配所有标注有 cn.bugstack.design.door.annotation.DoDoor 注解的方法,也就是说所有标注DoDoor注解的方法都会被拦截,切点aopPoint() 方法本身不需要任何逻辑,因为 @Pointcut 注解只是声明了一个切点,具体的通知(advice)逻辑将在其他地方定义

@Aspect
@Component
public class DoJoinPoint {

    private Logger logger = LoggerFactory.getLogger(DoJoinPoint.class);

    @Autowired
    private StarterService starterService;

    @Pointcut("@annotation(cn.bugstack.design.door.annotation.DoDoor)")
    public void aopPoint() {

    }

    @Around("aopPoint()")
    public Object doRouter(ProceedingJoinPoint jp) throws Throwable {
        Method method = getMethod(jp);
        DoDoor door = method.getAnnotation(DoDoor.class);

        String keyValue = getFiledValue(door.key(), jp.getArgs());
        logger.info("itstack door handler method:{} value:{}", method.getName(), keyValue);
        if (null == keyValue || "".equals(keyValue)) return jp.proceed();

        String[] split = starterService.split(",");

        // 白名单过滤
        for (String str : split) {
            if (keyValue.equals(str)) {
                return jp.proceed();
            }
        }
        // 拦截
        return returnObject(door, method);
    }
}

controller定义
@RestController 注解用于标识一个类为控制器(Controller),并且这个控制器返回的数据将自动转换为 JSON 或 XML 等格式,直接作为 HTTP 响应体返回给客户端,而不是视图名称。这意味着你不需要为返回的数据添加 @ResponseBody 注解,因为 @RestController 已经隐含了 @ResponseBody 的功能。当访问/api/queryUserInfo请求时,queryUserInfo方法会被调用,并且返回UserInfo对象 会自动转换为 JSON 或 XML(取决于客户端的请求头)并作为 HTTP 响应返回。在普通的 Spring MVC 项目中,也可以使用 @Controller@ResponseBody 来达到类似的效果,但 @RestController 提供了更简洁的语法。

@RestController
public class HelloWorldController {

    @Value("${server.port}")
    private int port;

    @DoDoor(key = "userId", returnJson = "{\"code\":\"1111\",\"info\":\"非白名单可访问用户拦截!\"}")
    @RequestMapping(path = "/api/queryUserInfo", method = RequestMethod.GET)
    public UserInfo queryUserInfo(@RequestParam String userId) {
        return new UserInfo("虫虫:" + userId, 19, "天津市南开区旮旯胡同100号");
    }

}

SpringApplication
@SpringBootApplication是一个组合注解,它包括了@Configuration、@EnableAutoConfiguration和@ComponentScan三个注解的功能。
@Configuration:表明该类是一个配置类,用于定义bean。
@EnableAutoConfiguration:让Spring Boot根据添加的jar依赖自动配置应用。比如添加了spring-boot-starter-web,则自动配置成web应用。
@ComponentScan:让Spring扫描到Configuration类并把它加入到程序上下文。

@SpringBootApplication
@Configuration
public class HelloWorldApplication {

    public static void main(String[] args) {
        SpringApplication.run(HelloWorldApplication.class, args);
    }

}

白名单效果
在这里插入图片描述
非白名单效果
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值