首页 > 其他分享 >spring 常见注解记录+ 使用自定义注解与aop 记录接口请求参数

spring 常见注解记录+ 使用自定义注解与aop 记录接口请求参数

时间:2024-09-29 16:04:06浏览次数:8  
标签:lang java 自定义 记录 public import 注解 annotation

注解定义:

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Controller;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
    @AliasFor(
        annotation = Controller.class
    )
    String value() default "";
}

ElementType 配置介绍:

TYPE
描述:类、接口(包括注解类型)、或枚举声明。
示例:@MyAnnotation public class MyClass {}
FIELD
描述:字段声明(包括枚举常量)。
示例:@MyAnnotation private int myField;
METHOD
描述:方法声明。
示例:@MyAnnotation public void myMethod() {}
PARAMETER
描述:形式参数声明。
示例:public void myMethod(@MyAnnotation String param) {}
CONSTRUCTOR
描述:构造器声明。
示例:@MyAnnotation public MyClass(int value) {}
LOCAL_VARIABLE
描述:局部变量声明(但注意,Java 注解在 Java 8 之前不能用于局部变量)。
示例(Java 8 及以上):void myMethod() { @MyAnnotation int localVar; }
ANNOTATION_TYPE
描述:注解类型声明。
示例:@MyAnnotation public @interface MyOtherAnnotation {}
PACKAGE
描述:包声明。从 Java 9 开始,注解可以应用于包声明。
示例(Java 9 及以上):@MyAnnotation package com.example;
TYPE_PARAMETER
描述:类型参数声明(Java 8 引入)。
示例:public class MyClass<@MyAnnotation T> {}
TYPE_USE
描述:类型的使用(Java 8 引入)。这允许注解应用于任何类型的使用,如泛型、强制类型转换等。
示例:public void myMethod(List<@MyAnnotation String> list) {}
// 注解的生命周期
@Retention(RetentionPolicy.RUNTIME)

/**
 * Annotation retention policy.  The constants of this enumerated type
 * describe the various policies for retaining annotations.  They are used
 * in conjunction with the {@link Retention} meta-annotation type to specify
 * how long annotations are to be retained.
 *
 * @author  Joshua Bloch
 * @since 1.5
 */
public enum RetentionPolicy {
    /**
     * 源码阶段存在
     */
    SOURCE,

    /**
     * 编译阶段存在
     */
    CLASS,

    /**
     * 运行阶段存在
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}
// 生成java doc文档 时是否增加该注解显示
@Documented
// 别名
@AliasFor 属性可互换, 如 attribute 和 value 写那个配置都一样
可参考:https://www.jb51.net/program/3149973yk.htm

public @interface AliasFor {
    @AliasFor("attribute")
    String value() default "";

    @AliasFor("value")
    String attribute() default "";

    Class<? extends Annotation> annotation() default Annotation.class;
}

常见注解解介绍:

@RestController = @ResponseBody + @Controller
该注解等同于 @ResponseBody + @Controller, 可以在controller 上使用,等同这两个注解。
@Controller
标注该类为控制器
@PostMapping
@GetMapping
标志请求的类型,请求路径
@RequestMapping
标注在类上,为该类所有方法增加请求路径
标注在方法上,指定方法请求路径,可配置请求类型 如 GET POST
@RequestMapping(value = "/test", method = RequestMethod.GET)
@RequestBody
指定在方法入参上,标识该参数通过 请求体传递,一般是json 串 POST请求传
@ResponseBody
指定返回数据为 web返回实体类型
@ControllerAdvice
统一的报错拦截处理,结合 @ExceptionHandler 可以对异常进行统一处理 如包装异常,日志打印等
@ComponentScan
	用在spring boot 启动类上,用于标注spring 扫描路径,如果没有被包含进去的bean,不会被spring 管理与创建,自动注入会报错
@Configuration
	用在类上,标注该类为配置类,在spring 启动时,会取读该类的配置,例如自定义webmvc 配置增加拦截器时会用到
@EnableConfigurationProperties
    @EnableConfigurationProperties注解的作用是:使 使用 @ConfigurationProperties 注解的类生效。
    如果一个配置类只配置@ConfigurationProperties注解,而没有使用@Component或者实现了@Component的其他注解,那么在IOC容器中是获取不到properties 	  配置文件转化的bean。
	说白了 @EnableConfigurationProperties 相当于把使用 @ConfigurationProperties 的类进行了一次注入。

@Import
    导入一个或多个Bean(可以实现不在 componentScan 标注路径下的bean包进行扫描)
	导入@Configuration类
    导入ImportSelector的实现类
    导入ImportBeanDefinitionRegistrar的实现类
@Primary
	当存在多个相同类型的Bean注入时,加上@Primary注解,指定更高的优先级。
@Qualifier
    存在多个相同类型的Bean注入时,加上@Qualifier注解,指定注入名称。
@Bean
    标注方法上,返回的结果指定为 bean, 被spring 容器管理
@Value
    标注在变量从上,从配置文件设置变量值,启动时未设置值,会报错
@Service
    标注该类为 service 类,能够会spring 容器管理 在 controller 中可以被自动注入 
@Component
    标注该类为组件类,可以能够会spring 容器管理 在 service等被自动注入
@RequestParam
    写在cotroller 的方法中,变量名默认为通过路径传参的参数名称
@Autowired
    对指定的对象进行自动注入,如果ioc 容器中不存在,则会报错 
@Deprecated
    标注该类/方法被废弃,使用时会有提示,无实际影响

使用spring 自定义注解 + aop 实现接口出入参记录:

注解定义:

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 日志记录注解
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
    /**
     * 模块名称
     */
    String modelName() default "";

}

注解切面逻辑:

import com.alibaba.fastjson.JSON;
import com.datadriver.log.annoations.Log;
import com.datadriver.log.dao.LogMapper;
import com.datadriver.log.entity.SystemLog;
import com.datadriver.spring.boot.security.SecurityUserDetails;
import com.datadriver.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;

/**
 * @ClassName LogAspect
 * @Description 日志切面
 * @Author lvhui7
 * @Date 2024/8/29
 */
@Slf4j
@Aspect
@Component
public class LogAspect {

    @Autowired
    private LogMapper logMapper;
    @Autowired
    private HttpServletRequest request;

    /**
     * 切入点
     */
    @Pointcut("@annotation(com.test.log.annoations.Log)")
    public void logPointCut() {
        // do nothing
    }
	// 环绕
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        Date date = new Date();
        Object result = point.proceed();
        long time = System.currentTimeMillis() - beginTime;
        this.saveLog(point, time, date);
        return result;
    }

    /**
     * 记录日志信息。
     * @param joinPoint 切点,用于获取方法签名和目标对象。
     * @param time 执行时间。
     */
    private void saveLog(ProceedingJoinPoint joinPoint, long time, Date beginTime) {
        try {
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            SystemLog systemLog = new SystemLog();
            systemLog.setId(StringUtil.getUUID());
            Log logAnnotation = method.getAnnotation(Log.class);
            if (logAnnotation != null) {
                systemLog.setModule(logAnnotation.modelName());
            }
            systemLog.setTime(time);
            // 获取类名
            String className = joinPoint.getTarget().getClass().getName();
            systemLog.setClassName(className);
            // 获取方法名
            String methodName = signature.getName();
            systemLog.setMethodName(methodName);
            // 从 SecurityContextHolder 中获取当前登录人的相关信息
            SecurityContext context = SecurityContextHolder.getContext();
            Authentication authentication = context.getAuthentication();
            SecurityUserDetails details = (SecurityUserDetails) authentication.getPrincipal();
            String username = details.getUsername();
            systemLog.setNotesId(username);
            Map<String, String[]> parameterMap = request.getParameterMap();
            systemLog.setIp(request.getRemoteAddr());
            systemLog.setParams(JSON.toJSONString(parameterMap));
            systemLog.setRequestedOn(beginTime);
            // 写入数据库
            logMapper.insertLog(systemLog);
        } catch (Exception e) {
            // 出现异常不抛出,避免回滚事务
            log.warn("日志记录异常:", e);
        }
    }
}

启动类增加aspectj 注解@EnableAspectJAutoProxypom 文件,增加相关依赖

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
        </dependency>

在需要记录接口出入参的方法上加上注解即可:

    @Log(modelName =  "测试记录日志")
    @RequestMapping(value = "test", method = RequestMethod.POST)
    public ApiResult testMethod(Model model, 
    HttpServletRequest request, 
    @RequestParam("name") String name,
    @RequestParam("type") String type) {
    	// 省略业务逻辑
        return ApiResult.success();
    }

起始还有个地方可以优化一下,记录的请求,可以改成异步的,避免接口请求时间被加长了,不过项目请求量小,就不做处理了~

标签:lang,java,自定义,记录,public,import,注解,annotation
From: https://www.cnblogs.com/charler/p/18440189

相关文章

  • Springboot自定义Prometheus采集指标
    添加依赖<!--增加Prometheus依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>io.micrometer&l......
  • Python基于自定义方法的排序
    Python基于自定义方法的排序在Python中,排序是一个常见的任务,它可以帮助我们根据特定的规则对数据结构(如列表)中的元素进行排序。Python的内置排序方法,如列表的sort()函数和内置函数sorted(),提供了非常灵活的排序机制,特别是通过key参数,我们可以指定一个自定义的函数来决定排序的顺......
  • 基于qwen2.5 手把手实战 自定义数据集 微调(llama-factory)
    基于qwen2.5手把手实战自定义数据集微调(llama-factory)准备工作1.数据集准备(例:民法典.txt)2.服务器准备(阿里云DSW白嫖)3.环境配置pip升级模型下载微调助手4.数据集处理脚本文件4.1文本分割(bert-base-chinese)4.2数据集生成4.3.1数据集转换(只有一个数据集)alpaca格式......
  • SpringBoot常用注解(超级详细,快快收藏)
    目录(1)@SpringBootApplication(2)@RestController(3)@RequestMapping(4)@GetMapping(5)@PostMapping(6)@PutMapping(7)@DeleteMapping(8)@RequestParam(9)@PathVariable(10)@RequestBody(11)@ResponseBody(12)@Autowired(13)@Component(14)@Service(15)@Reposit......
  • 论文速读记录 - 202409
    这次是KDD2024专场。目录:DeepBag-of-WordsModel:AnEfficientandInterpretableRelevanceArchitectureforChineseE-Commerce【词袋模型和语言模型结合,构建可解释的相关性计算方法】UnderstandingtheRankingLossforRecommendationwithSparseUserFeedba......
  • PbootCMS自定义前台404错误页面
    以下是一个简单的404错误页面示例代码:<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>......
  • plt注解相关介绍及应用
    目录plt.annotate()plt.text()实战plt.annotate()plt.annotate()是Matplotlib中用于在图形中添加注释的函数。与plt.text()类似,plt.annotate()可以在指定的位置添加文本注释,并可以指定箭头和文本的样式、颜色、字体大小等属性。plt.annotate()函数的常用参数......
  • mybatis基于注解、XML配置文件的形式来定义SQL语句
    一、mybatis基于注解定义SQL语句员工类@Data@NoArgsConstructor//无参@AllArgsConstructor//有参publicclassEmp{privateIntegerid;//idprivateStringusername;//用户名privateStringpassword;//密码privateStringname;//姓名privat......
  • 小主机虚拟化平台搭建记录
    小主机搭建虚拟化的一些记录:1,如果主机是Intel平台,目前建议还是使用VMwareEsxi6.7,如果你的主机网卡驱动没有包含在ESXI官方安装包内,去恩山找封装了网卡驱动的版本https://www.right.com.cn/FORUM/thread-7881507-1-1.html 2,如果你的主机是AMD平台,并且是ZEN系列,那么优先选......
  • 【Mybatis】Mybatis拦截器+注解,实现敏感数据自动加解密
    一:背景     今天,公司新要求对数据库的敏感数据进行加密,对手机号、身份证号、姓名等一些敏感数据进行加密处理,要求:    1.通过程序实现数据加密解密(快速便捷,尽量减少对原先代码的修改)    2.可以通过sql查询对数据进行解密(通过密钥直接对数据库......