日志切面接口和方法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 ...
随机推荐
- 【阿里云 CDP 公开课】 第二讲:CDH/HDP 何去何从
简介:Hadoop社区版CDH/HDP已经不再更新,也将终止服务.后续的平台路线图怎么规划?Cloudera CDP整合了CDH和HDP,有哪些性能提升和功能增强?如何平滑的进行迁移?本文结合CDH ...
- [FAQ] 如何从 svg 字符串创建 SVGElement
HTML 部分: <div style="display: none" id="svgCon"></div> JS 部分: cons ...
- Servlet注解的使用,简化配置 以及,使用模板方法设计模式优化oa项目
Servlet注解的使用,简化配置 以及,使用模板方法设计模式优化oa项目 每博一文案 有句谚语说:"一怒之下踢石头,只有痛着脚趾头." 比一件糟糕的事情更可拍的,是你用糟糕的态度 ...
- Lua 学习笔记(自用)
Lua 学习笔记 1 语言基础 运行方式类似Python,可以直接在交互行运行,也可以通过解释器运行某个脚本.也可以在交互行运行某个lua脚本 dofile("hello.lua" ...
- 三、Doris数据模型
DorisDB根据摄入数据和实际存储数据之间的映射关系, 将数据表的明细表, 聚合表和更新表, 分别对应有明细模型, 聚合模型和更新模型. Aggregate (聚合模型) : 将表中的列分为了Key ...
- laravel-cms学习笔记
学习地址: https://www.houdunren.com/edu/video/12045 laravel 文档地址: https://gitee.com/houdunren/code/blob/ ...
- Splashtop和 TiFlux 宣布建立合作伙伴关系
2020年9月21日,远程访问解决方案的全球领导者 Splashtop Inc. 和面向 IT 服务提供商的 IT 解决方案公司 TiFlux 宣布建立合作伙伴关系,以整合 Splashtop 远程访 ...
- C语言:将文件中所得到的单词表保存到一个顺序表中--使用动态分配数组。
在很多时候我们想要在程序中存储想要的信息,但是又不知道该信息的大小或者说不知道需要多长的数组来存放.动态分配空间这个很好的解决了这个问题,动态分配不仅只可以用在链表中分配节点空间,其实更多时候用来分配 ...
- AIRIOT物联网低代码平台如何配置交通部JT-808协议?
属性配置可配置终端ID和SIM卡号,数据点配置决定设备传上来的哪些数据可以存储展示. 驱动配置可配置采集周期和通讯超时时间. AIRIOT物联网低代码平台如何配置交通部JT-808协议?具体操作如下: ...
- Linux之kill命令
1.kill命令的使用格式 kill [参数] [进程号] 2.kill命令的功能 发送指定的信号到相应进程.不指定型号将发送SIGTERM(15)终止指定进程.如果任然无法终止该程序可用" ...