springboot的自定义注解

1.首先在pom文件里添加

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.定义注解

package com.mzd.ces.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;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogAnno {
	
	//日志类型 0:登录
	String type() default "0";
	
	//介绍
	String title() default "我的说明例子";

}

@Target——定义注解使用范围
1.TYPE——用于描述类、接口(包括注解类型) 或enum声明
2.FIELD——用于字段声明(包括枚举常量)
3.METHOD——用于方法声明
4.PARAMETER——用于参数声明
5.CONSTRUCTOR——用于构造函数声明
6.LOCAL_VARIABLE——用于本地变量声明
7.ANNOTATION_TYPE——用于注解类型声明
8.PACKAGE——用于包声明
9.TYPE_PARAMETER—— 用于类型参数声明,JavaSE8引进,可以应用于类的泛型声明之处
10.TYPE_USE——JavaSE8引进,此类型包括类型声明和类型参数声明,是为了方便设计者进行类型检查,例如,如果使用@Target(ElementType.TYPE_USE)对@NonNull进行标记,则类型检查器可以将@NonNull class C {…} C类的所有变量都视为非null

@Retention——定义注解保留阶段
1.RetentionPolicy.SOURCE —— 这种类型的Annotations只在源代码级别保留,编译时就会被忽略
2.RetentionPolicy.CLASS —— 这种类型的Annotations编译时被保留,在class文件中存在,但JVM将会忽略
3.RetentionPolicy.RUNTIME —— 这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用

@Documented
注解标记的元素,Javadoc工具会将此注解标记元素的注解信息包含在javadoc中。默认,注解信息不会包含在Javadoc中。

3.切点声明

package com.mzd.ces.annotation;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

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.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.mzd.ces.bo.SysOperLogBo;

import lombok.extern.slf4j.Slf4j;

@Aspect
@Component
@Slf4j
public class LogAspect {
	
	 /**
     * 定义切点 @Pointcut
     * 在注解的位置切入代码
     */
    @Pointcut("@annotation(com.mzd.ces.annotation.LogAnno)")
    public void logPointCut() {
    }
    
    /**
     * 环绕通知,获取接口调用前后入参及返回值数据
     * @param proceedingJoinPoint
     * @return
     */
    @Around("logPointCut()")
    public void saveSysLog(ProceedingJoinPoint proceedingJoinPoint) {
        try {
        	SysOperLogBo operLog = new SysOperLogBo();
            //从切面织入点处通过反射机制获取织入点处的方法
            MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
            //获取切入点所在的方法
            Method method = signature.getMethod();
            //获取操作
            LogAnno myLog = method.getAnnotation(LogAnno.class);
            if (myLog != null) {
            	operLog.setType(myLog.type());
                operLog.setTitle(myLog.title());
            }
            //获取请求的类名
            String className = proceedingJoinPoint.getTarget().getClass().getName();
            //获取请求的方法名
            String methodName = method.getName();
            operLog.setMethod(className + "." + methodName+"()");

            //请求的参数
            Object[] args = proceedingJoinPoint.getArgs();
            String params = JSON.toJSONString(args);
            JSONArray jsonArray = JSON.parseArray(params);
            operLog.setParams(params);
//            UserInfo user = JSON.toJavaObject(jsonArray.getJSONObject(0),UserInfo.class);
//            operLog.setOperName(user != null ? user.getUserName() != null ? user.getUserName() : user.getMobile() : "");
//            operLog.setOperTime(new Date());
            //获取用户名
            //获取用户ip地址
            // 接收到请求,记录请求内容
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            // 记录下请求内容
//            operLog.setOperIp(IpUtils.getIpAddr(request));
            operLog.setUrl(request.getRequestURI());
            //调用service保存SysLog实体类到数据库
            // 异步保存日志数据到数据库
//            AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
            //实际方法运行
            Object result = proceedingJoinPoint.proceed();
            System.out.println(result);
        } catch (Throwable e) {
            log.error(e.getMessage());
        }
    }

}

4.调用

	@GetMapping("/test")
	@LogAnno(title="title",type="#tpye")
	public ResponseResult<String> test(String type){
		String url = "hellow ces"+type;
		return ResponseResult.success(url);
	}

5.补充一个获取客户端ip的方法

package com.mzd.ces.util;

import java.net.InetAddress;
import java.net.UnknownHostException;

import javax.servlet.http.HttpServletRequest;

public class IpUtils {
	
	public static String getIpAddr(HttpServletRequest request) {
		String ipAddress = request.getHeader("x-forwarded-for");  
        if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {  
            ipAddress = request.getHeader("Proxy-Client-IP");  
        }  
        if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {  
            ipAddress = request.getHeader("WL-Proxy-Client-IP");  
        }  
        if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {  
            ipAddress = request.getRemoteAddr();  
            if(ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")){  
                //根据网卡取本机配置的IP  
                InetAddress inet=null;  
                try {  
                    inet = InetAddress.getLocalHost();  
                } catch (UnknownHostException e) {  
                    e.printStackTrace();  
                }  
                ipAddress= inet.getHostAddress();  
            }  
        }  
        //对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割  
        if(ipAddress!=null && ipAddress.length()>15){ //"***.***.***.***".length() = 15  
            if(ipAddress.indexOf(",")>0){  
                ipAddress = ipAddress.substring(0,ipAddress.indexOf(","));  
            }  
        }  
        return ipAddress; 
	}

}

SpringBoot中可以自定义注解来实现特定的功能。自定义注解的步骤如下: 1. 使用`@interface`关键字来定义注解,可以在注解中设置属性。 2. 可以通过注解的属性来传递参数,比如设置注解中的属性值。 3. 可以通过判断某个类是否有特定注解来进行相应的操作。 在SpringBoot中,自定义注解可以用于实现日志记录、定时器等功能。通过使用注解,可以简化代码,并提高开发效率。同时,自定义注解也是Spring框架中广泛应用的一种方式,可以在SpringMVC框架中使用注解来配置各种功能。而在SpringBoot框架中,更是将注解的使用推向了极致,几乎将传统的XML配置都替换为了注解。因此,对于SpringBoot来说,自定义注解是非常重要的一部分。123 #### 引用[.reference_title] - *1* *3* [springboot 自定义注解(含源码)](https://blog.csdn.net/yb546822612/article/details/88116654)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}} ] [.reference_item] - *2* [SpringBoot-自定义注解](https://blog.csdn.net/weixin_44809337/article/details/124366325)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值