springboot-自定义注解拦截ip aop和ioc

简介: springboot-自定义注解拦截ip aop和ioc
定义LimitIp
package com.blove.ityustudy.annotation;

import java.lang.annotation.*;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LimitIp {
    String ip() default "";
}

定义IpAspect
package com.blove.ityustudy.aop;


import com.blove.ityustudy.annotation.LimitIp;
import com.blove.util.IPUtils;
import com.blove.util.RUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;


@Aspect
@Component
@Slf4j
public class IpAspect {

    @Pointcut("@annotation(com.blove.ityustudy.annotation.LimitIp)")
    public void annotationPointcut() {

    }

    @Before("annotationPointcut()")
    public void beforePointcut(JoinPoint joinPoint) {
        log.info("beforePointcut");
    }

    @After("annotationPointcut()")
    public void afterPointcut(JoinPoint joinPoint) {
        log.info("afterPointcut");
    }

    /**
     * 拦截器具体实现
     * @param pjp
     * @return JsonResult(被拦截方法的执行结果,或需要登录的错误提示。)
     */
    @Around("annotationPointcut()") //指定拦截器规则;也可以直接把“execution(* com.xjj.........)”写进这里
    public Object Interceptor(ProceedingJoinPoint pjp) {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod(); //获取被拦截的方法
        String methodName = method.getName(); //获取被拦截的方法名
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();

        LimitIp annotation = method.getAnnotation(LimitIp.class);
        String value = annotation.ip();
        String ip = IPUtils.getRealIP(request);
        if(value.equals(ip)){
            try {
                return pjp.proceed();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
                return RUtil.error(throwable.getMessage());
            }
        }else{
            return RUtil.error("调用失败");
        }
    }

}

使用
 @ApiOperation(value = "获取用户信息")
    @ApiImplicitParams({ // 参数说明
            @ApiImplicitParam(name = "name", paramType = "query", value = "用户名字", dataType = "string", required = true),
            @ApiImplicitParam(name = "sex", paramType = "query", value = "性别", dataType = "Integer"),
            @ApiImplicitParam(name = "city", paramType = "query", value = "城市", dataType = "string"),
    })
    @PostMapping(value = "/getUser")
    @LimitIp(ip = "127.0.0.1")
    public R<UserModel> getUser(@RequestParam(value = "name") String name, @RequestParam(value = "sex", required = false) Integer sex, @RequestParam(value = "city", required = false) String city) {
        if (!StringUtils.isBlank(city)) {
            return RUtil.ok(new UserModel().setName(name).setAge(sex).setCity(city));
        }
        throw new CommonException("城市不能为空");
    }
学习
1. @Target 这个注解可以放到那个位置,例如类上,方法上,属性上等
public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE,

    /** Field declaration (includes enum constants) */
    FIELD,

    /** Method declaration */
    METHOD,

    /** Formal parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    ANNOTATION_TYPE,

    /** Package declaration */
    PACKAGE,

    /**
     * Type parameter declaration
     *
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * Use of a type
     *
     * @since 1.8
     */
    TYPE_USE,

    /**
     * Module declaration.
     *
     * @since 9
     */
    MODULE
}
2. @Retention
public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     */
    SOURCE,

    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     */
    CLASS,

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}
3. @Documented
AOP
满足 pointcut 规则的 joinpoint 会被添加相应的 advice 操作.
方法的生命周期:1,调用前,调用中,调用后(不关注结果),调用成功(调用返回异常),

Before-> After-> Around-> AfterReturning(AfterThrowing)

知道了生命周期就可以在任何地方切入了。


IOC

早期: 你需要啥,new一个就行了

ioc: 你需要啥,你先通过注解的方式告诉容器,让容器给你创建出来,当你需要的地方直接导入就行了

标注需求(@Component)
//读取classpath配置信息
@Data
@Component
@PropertySource(value = {"classpath:config.yml"},encoding = "utf-8")
public class FileConfig {
    @Value("${staticAccessPath}")
    private String staticAccessPath;
    @Value("${uploadFolder}")
    private String uploadFolder;
    @Value("${min}")
    private int min;
    @Value("${max}")
    private int max;

    @Override
    public String toString() {
        return "FileConfig{" +
                "staticAccessPath='" + staticAccessPath + '\'' +
                ", uploadFolder='" + uploadFolder + '\'' +
                ", min='" + min + '\'' +
                ", max='" + max + '\'' +
                '}';
    }
}
导入需求( @Autowired)
@Autowired
    FileConfig fileConfig;
疑问
我定义了注解,为啥注解到类上不起作用是哪里错了?求指点。
相关文章
|
17天前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
228 0
|
23天前
|
Java 测试技术 API
将 Spring 的 @Embedded 和 @Embeddable 注解与 JPA 结合使用的指南
Spring的@Embedded和@Embeddable注解简化了JPA中复杂对象的管理,允许将对象直接嵌入实体,减少冗余表与连接操作,提升数据库设计效率。本文详解其用法、优势及适用场景。
200 126
|
1月前
|
XML JSON Java
Spring框架中常见注解的使用规则与最佳实践
本文介绍了Spring框架中常见注解的使用规则与最佳实践,重点对比了URL参数与表单参数的区别,并详细说明了@RequestParam、@PathVariable、@RequestBody等注解的应用场景。同时通过表格和案例分析,帮助开发者正确选择参数绑定方式,避免常见误区,提升代码的可读性与安全性。
|
3天前
|
XML Java 数据格式
常用SpringBoot注解汇总与用法说明
这些注解的使用和组合是Spring Boot快速开发和微服务实现的基础,通过它们,可以有效地指导Spring容器进行类发现、自动装配、配置、代理和管理等核心功能。开发者应当根据项目实际需求,运用这些注解来优化代码结构和服务逻辑。
65 12
|
16天前
|
Java 测试技术 数据库
使用Spring的@Retryable注解进行自动重试
在现代软件开发中,容错性和弹性至关重要。Spring框架提供的`@Retryable`注解为处理瞬时故障提供了一种声明式、可配置的重试机制,使开发者能够以简洁的方式增强应用的自我恢复能力。本文深入解析了`@Retryable`的使用方法及其参数配置,并结合`@Recover`实现失败回退策略,帮助构建更健壮、可靠的应用程序。
使用Spring的@Retryable注解进行自动重试
|
16天前
|
传感器 Java 数据库
探索Spring Boot的@Conditional注解的上下文配置
Spring Boot 的 `@Conditional` 注解可根据不同条件动态控制 Bean 的加载,提升应用的灵活性与可配置性。本文深入解析其用法与优势,并结合实例展示如何通过自定义条件类实现环境适配的智能配置。
探索Spring Boot的@Conditional注解的上下文配置
|
16天前
|
智能设计 Java 测试技术
Spring中最大化@Lazy注解,实现资源高效利用
本文深入探讨了 Spring 框架中的 `@Lazy` 注解,介绍了其在资源管理和性能优化中的作用。通过延迟初始化 Bean,`@Lazy` 可显著提升应用启动速度,合理利用系统资源,并增强对 Bean 生命周期的控制。文章还分析了 `@Lazy` 的工作机制、使用场景、最佳实践以及常见陷阱与解决方案,帮助开发者更高效地构建可扩展、高性能的 Spring 应用程序。
Spring中最大化@Lazy注解,实现资源高效利用
|
17天前
|
安全 IDE Java
Spring 的@FieldDefaults和@Data:Lombok 注解以实现更简洁的代码
本文介绍了如何在 Spring 应用程序中使用 Project Lombok 的 `@Data` 和 `@FieldDefaults` 注解来减少样板代码,提升代码可读性和可维护性,并探讨了其适用场景与限制。
Spring 的@FieldDefaults和@Data:Lombok 注解以实现更简洁的代码
|
17天前
|
缓存 监控 安全
Spring Boot 的执行器注解:@Endpoint、@ReadOperation 等
Spring Boot Actuator 提供多种生产就绪功能,帮助开发者监控和管理应用。通过注解如 `@Endpoint`、`@ReadOperation` 等,可轻松创建自定义端点,实现健康检查、指标收集、环境信息查看等功能,提升应用的可观测性与可管理性。
Spring Boot 的执行器注解:@Endpoint、@ReadOperation 等