1. 定义切面

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
String value() default "";
}

2.切面类

package aspect;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Objects; @Aspect
@Component
public class LogAspect {
private Logger logger = LoggerFactory.getLogger(this.getClass()); @Pointcut("@annotation(Log)") //定义切面的类路径
public void pointcut() {
} @Around("pointcut()")
public Object around(ProceedingJoinPoint point) throws Throwable{
long beginTime = System.currentTimeMillis();
//增加返回值
Object proceed = null;
try {
// 执行方法
proceed = point.proceed();
} catch (Throwable e) {
logger.error("切面异常:",e);
       throw e;
} // 执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
// 保存日志
saveLog(point, time,proceed);
//关键,同时该参数作为入参存储在数据库中。
return proceed;
} private void saveLog(ProceedingJoinPoint joinPoint, long time, Object proceed) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
//TODO存入日志表中 Log logAnnotation = method.getAnnotation(Log.class);
if (logAnnotation != null) {
// 注解上的描述
//Operation = (logAnnotation.value()); //TODO 操作名称
}
// 请求的方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
//简称类名
String classNameSimple = joinPoint.getTarget().getClass().getSimpleName(); //Method = (classNameSimple + "." + methodName + "()"); //TODO 执行类和方法 // 请求的方法参数值
Object[] args = joinPoint.getArgs();
// 请求的方法参数名称
LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
String[] paramNames = u.getParameterNames(method);
if (args != null && paramNames != null) {
String params = "";
for (int i = 0; i < args.length; i++) {
logger.info(i+" paramNames[i]="+paramNames[i]+",args[i]="+GsonUtils.toJson(args[i]));
params += " " + paramNames[i] + ": " + GsonUtils.toJson(args[i]);
}
//Params = (params); //TODO 方法参数
} //获取关键参数,比如外部订单号
Object argument = args[0];
//从参数中获取out_order_no
String jsonString = JSON.toJSONString(args[0]);
String outOrderNo = StringUtils.EMPTY;
if (argument instanceof String) {
outOrderNo = argument.toString();
jsonString = JSON.toJSONString(args);
} else if (isJSONObj(jsonString)) {
JSONObject jsonObject = JSON.parseObject(jsonString);
if (jsonObject.containsKey("out_order_no")) {
outOrderNo = jsonObject.getString("out_order_no");
}
} else if (isJSONArr(jsonString)) {
JSONArray jsonArray = JSON.parseArray(jsonString);
if (CollectionUtils.isNotEmpty(jsonArray) && Objects.nonNull(jsonArray.getJSONObject(0))) {
JSONObject jsonObject = jsonArray.getJSONObject(0);
if (jsonObject.containsKey("out_order_no")) {
outOrderNo = jsonObject.getString("out_order_no");
}
}
}
//OutOrderNo = (outOrderNo); //TODO 关键索引参数 //ReqTime = ((int) time); //TODO 请求时长 //查询返回值
logger.info("target=" + joinPoint.getTarget());
logger.info("kind=" + joinPoint.getKind());
logger.info("proceed=" + proceed.toString()); //返回结果
//Resp = (GsonUtils.toJson(proceed)); //TODO 接口返回结果 // 保存系统日志
//saveSysLog(); //TODO save to database
} public static boolean isJSONObj(String jsonStr){ if(StringUtils.isNotBlank(jsonStr) && jsonStr.startsWith("{") && jsonStr.endsWith("}")){
return true;
}
return false;
} public static boolean isJSONArr(String jsonStr){ if(StringUtils.isNotBlank(jsonStr) && jsonStr.startsWith("[") && jsonStr.endsWith("]")){
return true;
}
return false;
} }

3.测试类

@Log(value = "测试日志切面接口")
@GetMapping("/hello")
public String hello(@RequestParam("out_order_no") String name){
logger.info("request param is [{name}]",name);
LogEntity entity = new LogEntity();
entity.setOut_order_no("TB123456789");
String resp = log(entity);
logger.info("request resp is [{resp}]",resp);
return "hello"+name+",resp="+resp;
} @Log("测试日志切面方法")
@Override
public String log(LogEntity entity) {
return "success-log:" + GsonUtils.toJson(entity);
} public class LogEntity {
private String out_order_no; public String getOut_order_no() {
return out_order_no;
} public void setOut_order_no(String out_order_no) {
this.out_order_no = out_order_no;
}
}

日志切面接口和方法demo,切面内重新抛出异常的更多相关文章

  1. Spring 运用 pointcut 和 advisor 对特定的方法进行切面编程

    上一个例子演示了对特定的bean中的所有的方法进行面向切面编程,包括了 before , after , after throwing, around 几种形式: 如果想对一个bean中的特定方法进行 ...

  2. Spring AOP基于配置文件的面向方法的切面

    Spring AOP基于配置文件的面向方法的切面 Spring AOP根据执行的时间点可以分为around.before和after几种方式. around为方法前后均执行 before为方法前执行 ...

  3. Java基础学习笔记十二 类、抽象类、接口作为方法参数和返回值以及常用API

    不同修饰符使用细节 常用来修饰类.方法.变量的修饰符 public 权限修饰符,公共访问, 类,方法,成员变量 protected 权限修饰符,受保护访问, 方法,成员变量 默认什么也不写 也是一种权 ...

  4. MyBatis的接口式编程Demo

    很久没细看过MyBatis了,时间一长就容易忘记. 下面是一个接口式编程的例子. 这里的例子一共分为4步: 1 首先要有一个namespace为接口的全类名的映射文件,该例中是 IMyUser.xml ...

  5. 从线上日志统计接口访问量QPS

    这一阵子在面试,连续遇到好几家(大小厂都有)问我的项目线上qps的情况了,说实话,我作为一个大头兵,本来没关注过这个数据,只能含混地给个"大概.也许"的回答. 回来之后,我决定对业 ...

  6. Lambda函数接口和方法构造器应用

    函数式接口 什么是函数式接口? 在java中'有且仅有一个抽象方法的接口',就称为函数式接口. 可以通过Lambda表达式来创建该接口的对象.(若Lambda表达式抛出一个受检异常,那么该异常需要在目 ...

  7. java中获取接口(方法)中的参数名字(eclipse设置编译参数)(java8 javac -parameters)

    interface接口参数 jdk1.7及以前使用spring功能实现的: 注意: 1.该功能只能获取类的方法的参数名,不能获取接口的方法的参数名. public static void test() ...

  8. Mybatis Generator的model生成中文注释,支持oracle和mysql(通过实现CommentGenerator接口的方法来实现)

    自己手动实现的前提,对maven项目有基本的了解,在本地成功搭建了maven环境,可以参考我之前的文章:maven环境搭建 项目里新建表时model,mapper以及mapper.xml基本都是用My ...

  9. 009-jdk1.8版本新特性一-展方法,Lambda表达式,函数式接口、方法引用构造引用

    一.JDK1.8 名称:Spider(蜘蛛) 发布日期:2014-03-18 新特性: 1.1.扩展方法[接口的默认方法] Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 defaul ...

  10. 用ladon框架封装Python为Webservice接口以及调用接口的方法

    一.用ladon框架封装Python为Webservice接口 功能实现的同时,希望将接口开放给别人,而封装python接口的一个再简单不过的框架Ladon,而且提供不同的协议,包括SOAP和Json ...

随机推荐

  1. 数仓架构的持续演进与发展 — 云原生、湖仓一体、离线实时一体、SaaS模式

    简介: 数据仓库概念从1990年提出,经过了四个主要阶段.从最初的数据库演进到数据仓库,到MPP架构,到大数据时代的数据仓库,再到今天的云原生的数据仓库.在不断的演进过程中,数据仓库面临着不同的挑战. ...

  2. Dubbo-go v3.0 正式发布 ——打造国内一流开源 Go 服务框架

    ​简介:Dubbo-go 是常新的,每年都在不断进化.介绍 Dubbo-go 3.0 工作之前,先回顾其过往 6 年的发展历程,以明晰未来的方向. ​ 作者 | 李志信 来源 | 阿里技术公众号 作者 ...

  3. [Blockchain] Cosmos Starport 101 - 为你的新数据类型 生成代码

    # 项目模板 $ starport app github.com/hello/planet --address-prefix your_new_prefix 项目目录结构的说明看这里: https:/ ...

  4. [FAQ] Python list 的值是带有小括号的是什么意思 ?

    python 中的 list 即列表,是用中括号 [ ] 表示的数组列表: dict 即字典,是用花括号 { } 表示的 json 对象: tuple 即元祖,是用小括号表示的序列: 见到它们之间的组 ...

  5. dotnet SemanticKernel 入门 将技能导入框架

    在上一篇博客中和大家简单介绍了 SemanticKernel 里的技能概念,接下来咱准备将 技能 导入到 SemanticKernel 框架里面,进行一个管道式调用 本文属于 SemanticKern ...

  6. K8s控制器---DaemonSet控制器(12)

    一.DaemonSet控制器:概念.原理解读 1.1 DaemonSet概述 DaemonSet 控制器能够确保 k8s 集群所有的节点都运行一个相同的 pod 副本,当向 k8s 集群中增加 nod ...

  7. SpringBoot的@Resource和@Autowired+@Qualifier使用

    1.区别 参考: https://blog.csdn.net/xhbzl/article/details/126765893 https://blog.csdn.net/qq_40263124/art ...

  8. Radius 现在是云原生计算基金会(CNCF)的沙箱项目

    在数字化时代,云原生计算技术逐渐成为企业转型的关键.2024-04-25,备受瞩目的开源项目 Radius 已正式加入云原生计算基金会(CNCF)的沙箱项目![Sandbox] Radius · Is ...

  9. 羽夏闲谈—— Kdenlive flatpak 版本解决语音识别找不到 pip3

    简述   Kdenlive是在 Linux 上一款比较优秀的剪辑软件,功能比较强大.操作相对容易,能够满足日常剪辑的需要. 解决方案   找到对应的安装目录/var/lib/flatpak/app/o ...

  10. Ubuntu开启root账户登陆

    Ubuntu开启root账户登陆 设置 root 密码:sudo passwd root sudo chmod 777 /usr/share/lightdm/lightdm.conf.d/50-xx ...