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. 殷浩详解DDD:领域层设计规范

    简介: 在一个DDD架构设计中,领域层的设计合理性会直接影响整个架构的代码结构以及应用层.基础设施层的设计.但是领域层设计又是有挑战的任务,特别是在一个业务逻辑相对复杂应用中,每一个业务规则是应该放在 ...

  2. [FE] Quasar BEX 所有位置类型 types

    科普:[FE] Quasar BEX 预览版指南 New Tab Quasar BEX 的默认类型是 New Tab,在新 tab 栏里打开内容. Dev Tools 也就是在开发者栏里面的内容. O ...

  3. 1.权限控制RBAC

    官方参考地址:https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/rbac/#privilege-escalation-prev ...

  4. github只下载某个文件或文件夹(使用GitZip插件)

    安装GitZip插件 (此安装过程需要梯子(不懂"梯子",百度一下就明白)) 1. 打开插件管理页面 方法一:打开Chrome浏览器(Edge浏览器同理),在Chrom地址栏输入c ...

  5. async 与 promise 的区别

    async函数会引式返回一个promise,而promise的resolve值就是函数return的值 使用async和await明显节约了不少代码,不需要.then,不需要写匿名函数处理promis ...

  6. 在Linux下想要删除一个目录需要怎样的权限

    场景一 在Home目录下创建一个目录dirtest,然后使用chmod 333 dirtest修改目录权限.这时候dirtest的权限为d-wx-wx-wx,如果执行rm -r dirtest可以进行 ...

  7. ansible(11)--ansible的user和group模块

    1. group模块 功能:管理被控端用户组: 主要参数如下: 参数 说明 name 指定创建的组名 gid 为组设置gid state 是否将组创建在远程主机上,创建:present(Default ...

  8. WEB服务与NGINX(11)-NGINX状态页

    nginx状态页 nginx的状态页功能用于输出nginx的基本状态信息,基于ngx_http_stub_status_module模块实现. 默认情况下不生成此模块,应使用--with-http_s ...

  9. 读写可编程 SIM/USIM 卡

    目录 文章目录 目录 SIM 卡 USIM 卡 USIM 卡的关键参数 pySim 读写软件与 ADM key SIM 卡 SIM 卡,用户身份模块(Subscriber Identity Modul ...

  10. docker flannel网络

    部署etcd github部署访问链接:https://github.com/etcd-io/etcd/releases/ ETCD_VER=v3.5.1 # choose either URL GO ...