日志切面接口和方法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 ...
随机推荐
- 数据分析之pyecharts v1版本
维护人员,感谢他们 https://github.com/chenjiandongx https://github.com/chfw https://github.com/kinegratii中文文档 ...
- 二进制安装多master节点的k8s集群(2)
1.环境准备 k8s集群角色 IP 主机名 安装的组件 控制节点 192.168.1.10 master apiserver.controller-manager.scheduler.etcd.doc ...
- visual studio 2008的试用版评估期已结束(附无法使用产品密钥)的解决方法
visual studio 2008过了试用期后再次启动提示对话框:visual studio的试用版评估期已结束. 解决办法: 第一步,在"控制面板"中启动"添加删除程 ...
- vue使用echart(地图,弹窗展示多条数据,option定义)
第二次用echart,第一次做地图, <template> <div class="echarts" style="background:#3bafde ...
- 【项目学习】Timeswap:第一个完全去中心化的基于 AMM 的货币市场协议
总览 Timeswap 是世界上第一个完全去中心化的基于 AMM 的货币市场协议,无需预言机或清算人即可工作. Timeswap 采用 3 变量来维持 AMM 的运作.它通过允许用户决定他们的风险状况 ...
- fastposter v2.8.0 发布 电商海报编辑器
fastposter v2.8.0 发布 电商海报编辑器 fastposter海报生成器,电商海报编辑器,电商海报设计器,fast快速生成海报 海报制作 海报开发.二维码海报,图片海报,分享海报,二维 ...
- 《最新出炉》系列入门篇-Python+Playwright自动化测试-46-鼠标滚轮操作
1.简介 有些网站为了节省流量和资源,提高加载效率,采用的是动态加载(懒加载)的,也就是当拖动页面右侧滚动条后会自动加载网页下面的内容,不拖动就不会加载的或者通过鼠标滚轮操作. 2.wheel模拟鼠标 ...
- android中Room数据库的基本使用
简介: 还在使用原生的sqllite?有这么清爽且稳如狗的room为啥不用呢? Room是Google官方推荐使用的数据库,相比较某些优秀数据库框架来说,不用过于担心某天库会停止维护,且访问数据库非常 ...
- 高性能远程控制软件,完美替代Anydesk
Anydesk是一款来自德国的远程软件,据悉是Teamviewer团队成员出来独立门户做的.Anydesk给人一种小而美的感觉,软件体积小,性能高,被视为Teamviewer的替代产品.现在,AnyD ...
- mybatis-puls解决多数据源事务的问题
直接上代码: pom: <!--JTA组件核心依赖--> <dependency> <groupId>org.springframework.boot</gr ...