日志切面接口和方法demo,切面内重新抛出异常
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,切面内重新抛出异常的更多相关文章
- Spring 运用 pointcut 和 advisor 对特定的方法进行切面编程
上一个例子演示了对特定的bean中的所有的方法进行面向切面编程,包括了 before , after , after throwing, around 几种形式: 如果想对一个bean中的特定方法进行 ...
- Spring AOP基于配置文件的面向方法的切面
Spring AOP基于配置文件的面向方法的切面 Spring AOP根据执行的时间点可以分为around.before和after几种方式. around为方法前后均执行 before为方法前执行 ...
- Java基础学习笔记十二 类、抽象类、接口作为方法参数和返回值以及常用API
不同修饰符使用细节 常用来修饰类.方法.变量的修饰符 public 权限修饰符,公共访问, 类,方法,成员变量 protected 权限修饰符,受保护访问, 方法,成员变量 默认什么也不写 也是一种权 ...
- MyBatis的接口式编程Demo
很久没细看过MyBatis了,时间一长就容易忘记. 下面是一个接口式编程的例子. 这里的例子一共分为4步: 1 首先要有一个namespace为接口的全类名的映射文件,该例中是 IMyUser.xml ...
- 从线上日志统计接口访问量QPS
这一阵子在面试,连续遇到好几家(大小厂都有)问我的项目线上qps的情况了,说实话,我作为一个大头兵,本来没关注过这个数据,只能含混地给个"大概.也许"的回答. 回来之后,我决定对业 ...
- Lambda函数接口和方法构造器应用
函数式接口 什么是函数式接口? 在java中'有且仅有一个抽象方法的接口',就称为函数式接口. 可以通过Lambda表达式来创建该接口的对象.(若Lambda表达式抛出一个受检异常,那么该异常需要在目 ...
- java中获取接口(方法)中的参数名字(eclipse设置编译参数)(java8 javac -parameters)
interface接口参数 jdk1.7及以前使用spring功能实现的: 注意: 1.该功能只能获取类的方法的参数名,不能获取接口的方法的参数名. public static void test() ...
- Mybatis Generator的model生成中文注释,支持oracle和mysql(通过实现CommentGenerator接口的方法来实现)
自己手动实现的前提,对maven项目有基本的了解,在本地成功搭建了maven环境,可以参考我之前的文章:maven环境搭建 项目里新建表时model,mapper以及mapper.xml基本都是用My ...
- 009-jdk1.8版本新特性一-展方法,Lambda表达式,函数式接口、方法引用构造引用
一.JDK1.8 名称:Spider(蜘蛛) 发布日期:2014-03-18 新特性: 1.1.扩展方法[接口的默认方法] Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 defaul ...
- 用ladon框架封装Python为Webservice接口以及调用接口的方法
一.用ladon框架封装Python为Webservice接口 功能实现的同时,希望将接口开放给别人,而封装python接口的一个再简单不过的框架Ladon,而且提供不同的协议,包括SOAP和Json ...
随机推荐
- 殷浩详解DDD:如何避免写流水账代码?
简介: 在日常工作中我观察到,面对老系统重构和迁移场景,有大量代码属于流水账代码,通常能看到开发在对外的API接口里直接写业务逻辑代码,或者在一个服务里大量的堆接口,导致业务逻辑实际无法收敛,接口复用 ...
- 庖丁解InnoDB之REDO LOG
简介: 数据库故障恢复机制的前世今生一文中提到,今生磁盘数据库为了在保证数据库的原子性(A, Atomic) 和持久性(D, Durability)的同时,还能以灵活的刷盘策略来充分利用磁盘顺序写的 ...
- github 解决推拉代码提示 REMOTE HOST IDENTIFICATION HAS CHANGED 失败
本文记录最近 github 推送或拉取代码时提示 WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! 而失败的解决方法 报错提示如下 @@@@@@@@@@ ...
- k8s自动扩缩容方案-HPA-VPA-KPA(18)
一.自动(弹性)扩缩容背景分析 背景: 弹性伸缩是根据用户的业务需求和策略,自动"调整"其"弹性资源"的管理服务.通过弹 性伸缩功能,用户可设置定时.周期或监控 ...
- 一键启动的AI离线知识库,无需复杂环境依赖,小白都能上手了
简介 在人工智能技术飞速发展的今天,我们经常面临一个挑战:如何快速.简便地部署和使用AI技术?AntSK项目,一个开源的AI知识库和智能体,就是为了解决这一问题而诞生的.现在,我们自豪地宣布,AntS ...
- rails 之下载
控制器 def index #传给前端展示层当前的id @id = 6 end # http://127.0.0.1:3000/admin/category_statistics/export_tab ...
- elementui 时间戳和后台配合
保存时间 思路: 前端传时间戳, 后台表里的时间类型为timestamp, model结构体tag设置为 *time.Time json:"activationTime" gorm ...
- WEB服务与NGINX(1)-HTTP协议基础
WEB服务与NGINX(1) 目录 WEB服务与NGINX(1) 1. HTTP协议 1.1 WEB资源 1.2 URI简介 1.3 WEB服务请求处理过程 1.4 HTTP报文结构 1.4.1 re ...
- 怎么样给Oracle数据库中的表添加列?
首发微信公众号:SQL数据库运维 原文链接:https://mp.weixin.qq.com/s?__biz=MzI1NTQyNzg3MQ==&mid=2247485212&idx=1 ...
- vscode插件安装和配置支持vue3
一.常用插件介绍 1.插件Vue 3 Snippets 作用:用于vue3的智能代码提示,语法高亮.智能感知.Emmet等.替代Vetur插件,Vetur在vue2时期比较流行. 常用命令:vuein ...