元注解:
元注解就是可以加在注解上的注解,元注解不可以自定义。下面我来一一说明一下这四个元注解的作用。
@Documented
如果添加了@Documented,注解将能够在JavaDoc中展现。
@Retention
描述注解的生命周期,即什么时候注解是有效
类型 | 说明 |
---|---|
RetentionPolicy.SOURCE | 在源文件中有效 |
RetentionPolicy.CLASS | 在 class 文件中有效 |
RetentionPolicy.RUNTIME | 在运行时有效 |
@Inherited
是否允许子类继承该注解。即@Spongebob 如果修饰了类A,那么类A的子类类B也会默认被@Spongebob 修饰。
@Target
表示该注解用于什么地方。默认值为任何元素,表示该注解可以用于任何地方。注解值可以多选,如果建注解用到了未定义的地方,编译会报错。
类型 | 说明 |
---|---|
CONSTRUCTOR | 可用于描述构造器 |
FIELD | 用于描述域(属性) |
LOCAL_VARIABLE | 用于描述局部变量 |
METHOD | 用于描述方法 |
PACKAGE | 用于描述包 |
PARAMETER | 用于描述参数 |
TYPE | 用于描述类或接口(甚至 enum ) |
接下来都是干货,新建自定义注解Log
ackage com.gpdi.operatingunit.common.annotation;
import java.lang.annotation.*;
/**
* @Description: 系统日志注解
* @Author: Lxq
* @Date: 2019/10/21 11:20
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
String value() default "";
}
新建LogAspect 日志切面出来类
package com.gpdi.operatingunit.common.aspect;
import com.google.gson.Gson;
import com.gpdi.operatingunit.common.annotation.Log;
import com.gpdi.operatingunit.entity.system.SysLog;
import com.gpdi.operatingunit.entity.system.SysUser;
import com.gpdi.operatingunit.service.system.SysLogService;
import com.gpdi.operatingunit.utils.HttpContextUtils;
import com.gpdi.operatingunit.utils.IPUtils;
import com.gpdi.operatingunit.utils.ShiroUtils;
import org.apache.ibatis.session.SqlSessionFactory;
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.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
/**
* @Description:系统日志,切面处理类
* @Author: Lxq
* @Date: 2019/10/21 11:31
*/
@Aspect
@Component
public class LogAspect {
@Autowired
private SysLogService sysLogService;
// 自定义注解的位置
@Pointcut("@annotation(com.gpdi.operatingunit.common.annotation.Log)")
public void logPointCut() {
}
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis();
//执行方法
Object result = point.proceed();
//执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
//保存日志
saveSysLog(point, time);
return result;
}
private void saveSysLog(ProceedingJoinPoint joinPoint, long time) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
SysLog sysLog = new SysLog();
Log log = method.getAnnotation(Log.class);
if (log != null) {
//注解上的描述
sysLog.setOperType(log.value());
}
//请求的方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
sysLog.setMethod(className + "." + methodName + "()");
//请求的参数
Object[] args = joinPoint.getArgs();
try {
if ("用户登录".equals(log.value())) {
//只保存第一个参数
String params = new Gson().toJson(args[0]);
sysLog.setParams(params);
} else {
//保存全部参数
String params = new Gson().toJson(args);
sysLog.setParams(params);
}
} catch (Exception e) {
}
//获取request
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
//设置IP地址
sysLog.setIp(IPUtils.getIpAddr(request));
//用户名
SysUser sysUser = ShiroUtils.getUser();
sysLog.setUserId(sysUser.getId());
sysLog.setExecuteTime(time);
sysLog.setOperTime(new Date());
//保存系统日志
sysLogService.insert(sysLog);
}
}
在方法中使用
@Log("修改密码")
@PostMapping("/updatePass")
public R updateUserInfo(String pass){
SysUser user = ShiroUtils.getUser();
user.setSalt(getSalt());
user.setPassword(new Sha256Hash(pass, user.getSalt(), 3).toString());
user.setUpdateTime(new Date());
sysUserMapper.updateById(user);
return R.ok();
}