import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder; /**
* 实现Web层的日志切面
* @author lpf
*/
@Component
@Aspect
@Order(1)
public class WebLogAspect {
private Logger log = LoggerFactory.getLogger(getClass());
private ThreadLocal<Long> startTime = new ThreadLocal<>(); /**
* 定义一个切入点.
* 解释下:
* <p>
* ~ 第一个 * 代表任意修饰符及任意返回值.
* ~ 第二个 * 任意包名
* ~ 第三个 * 定义在web包或者子包
* ~ 第四个 * 任意方法
* ~ .. 匹配任意数量的参数.
*/
// @Pointcut("execution(public * com.kfit.*.web..*.*(..))")
// use
// @Pointcut("execution(public * org.zhilan..*Controller.*(..))") // @Pointcut("(execution(public * org.zhilan.timer.*Service.*(..)))")
@Pointcut("(execution(public * com.haoyun..*Controller.*(..))) "
// + "|| execution(public * com.haoyun.timer.*Service.*(..)) "
+ "&& !execution(* com.haoyun.login.LoginController.getSystemState())"
)
public void webLog() {
} @Before("webLog()")
public void doBefore(JoinPoint joinPoint) throws UnsupportedEncodingException {
startTime.set(System.currentTimeMillis()); // 接收到请求,记录请求内容
log.info("========================= before start =========================");
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature; log.info("CLASS_METHOD : " + methodSignature.getDeclaringTypeName() + "." + methodSignature.getName()); // 记录下请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if(attributes != null){
HttpServletRequest request = attributes.getRequest();
log.info("IP : " + request.getRemoteAddr());
} log.info("请求参数: 名称 值");
String[] argsNameArray = methodSignature.getParameterNames();
Object[] argsValueArray = joinPoint.getArgs();
for (int i = 0; i < argsNameArray.length; i++) {
log.info("args_name: " + argsNameArray[i]); String argValue = argsValueArray[i] != null ? argsValueArray[i].toString() : "";
if (argsNameArray[i].contains("encode")) {
String str = URLDecoder.decode(argValue, "utf-8");
log.info("args_value: " + (str.length() > 200 ? str.substring(0, 200) + "..." : str));
} else {
log.info("args_value: " + (argValue.length() > 200 ? argValue.substring(0, 200) + "..." : argValue));
}
} log.info("========================= before end =========================");
} @AfterReturning(returning="rvt", pointcut="webLog()")
public void doAfterReturning(JoinPoint joinPoint, Object rvt) {
// 处理完请求, 返回内容
log.info("========================= after returning start =========================");
Signature signature = joinPoint.getSignature();
log.info("CLASS_METHOD : " + signature.getDeclaringTypeName() + "." + signature.getName()); if(rvt != null){
String str = rvt.toString();
if (str.length() > 200) {
str = str.substring(0, 200) + "...";
} log.info("return 返回值:");
log.info(str);
} log.info("耗时(毫秒) : " + (System.currentTimeMillis() - startTime.get())); log.info("========================= after returning end =========================");
}
}

实现Web层的日志切面(方便清晰查看日志)的更多相关文章

  1. web部署启动或者运行报错查看日志寻找问题方法

    今天运行一个项目,启动报错,查看日志,只看到了前半段错误日志,根据前半段错误日志差查找原因,找了两个小时,也没有解决掉,最后根据后半段错误日志十分钟定位错误,给解决了,以后出现问题不能急躁,查看完成的 ...

  2. 【docker】docker限制日志文件大小的方法+查看日志文件的方法

    一.docker日志文件的方法 除了 docker logs -f 容器ID/容器名 这个方法以外. 在linux上,一般docker的日志文件存储在/var/lib/docker/container ...

  3. Web层后端权限模块

    从零开始编写自己的C#框架(19)——Web层后端权限模块   不知不觉本系统写了快三个月了,最近写页面的具体功能时感觉到有点吃力,很多地方如果张嘴来讲的话可以说得很细,很全面,可写成文字的话,就不太 ...

  4. Django websocket之web端实时查看日志实践案例

    这是Django Channels系列文章的第二篇,以web端实现tailf的案例讲解Channels的具体使用以及跟Celery的结合 通过上一篇<Django使用Channels实现WebS ...

  5. 从零开始编写自己的C#框架(16)——Web层后端父类

    本章节讲述的各个类是后端系统的核心之一,涉及到系统安全验证.操作日志记录.页面与按键权限控制.后端页面功能封装等内容,希望学习本系列的朋友认真查看新增的类与函数,这对以后使用本框架进行开发时非常重要. ...

  6. Spring Boot 2.0 教程 | AOP 切面统一打印请求日志

    欢迎关注微信公众号: 小哈学Java 文章首发于个人网站 https://www.exception.site/springboot/spring-boot-aop-web-request 本节中,您 ...

  7. 状态维持在web层 每层都可以Cache

    API网关的开源解决方案那么多,为什么我们却还要选择自研? - SDK.CN - 中国领先的开发者服务平台 https://sdk.cn/news/8001 技术细节Microservice+SOA状 ...

  8. Web 层由 Web,Web-MVC,Web-Socket 和 Web-Portlet 组成

    Web 层由 Web,Web-MVC,Web-Socket 和 Web-Portlet 组成,它们的细节如下: Web 模块提供面向web的基本功能和面向web的应用上下文,比如多部分(multipa ...

  9. SpringBoot2.0 基础案例(11):配置AOP切面编程,解决日志记录业务

    本文源码 GitHub地址:知了一笑 https://github.com/cicadasmile/spring-boot-base 一.AOP切面编程 1.什么是AOP编程 在软件业,AOP为Asp ...

随机推荐

  1. 502. IPO

    Suppose LeetCode will start its IPO soon. In order to sell a good price of its shares to Venture Cap ...

  2. SQL事务对并发处理的支持

    前言 继上次技术分享后,学到了关于mysql事务的许多新知识,感觉还是蛮有收获的.后来反过来想想,这些东西其实我们都接触过,最起码在自学考试的数据库系统原理那本书里面对事务的讲解,在里面就提到了事务的 ...

  3. laravel5.2总结--返回值

    基本概念和概述 1>StdClass 对象=>基础的对象 2>Eloquent 模型对象(Model 对象)=>和模型相关的类对象 3>Eloquent 集合=>可 ...

  4. 开窗函数Over用法

    比如我们有这个表: 销售记录表 日期 姓名 产品 销售额 201601 A 电脑 12560 201601 A 手机 6501 201601 A 平板 8510 201602 A 手机 1560 20 ...

  5. Java内存区域与内存溢出异常---运行时数据区域

    运行时数据区域 Java虚拟机所管理的内存将会包括以下几个运行时数据区域 线程私有区域 1.程序计数器   程序计数器记录的是当前正在执行的虚拟机字节码指令所在的地址.在虚拟机的概念模型中,字节码解释 ...

  6. 禁止百度转码和百度快照缓存的META声明

    今天手机 site 中国博客联盟时,发现网被转码了,虽然这个网站没做移动站,但是我也不希望被百度转码,因为这相当于拦截了所有来自手机的流量.下面说一下禁止百度转码和禁止百度快照缓存的方法. 一.禁止百 ...

  7. VS2010 简单ATL COM开发

    http://blog.csdn.net/wangwenjing90/article/details/8771934#reply http://blog.csdn.net/wangwenjing90/ ...

  8. 存储过程中的select into from是干什么的

    select into  赋值: select 0 into @starttimeselect @starttime from DUAL into后边应该还有个变量名,into前面也还要带上筛选字段, ...

  9. 2-28 switch

  10. linux系统安全加固--账号相关

    linux系统安全加固 一.账号相关 1.禁用或删除无用账号 减少系统无用账号,降低安全风险. 当我们的系统安装完毕后,系统默认自带了一些虚拟账户,比如bin.adm.lp.games.postfix ...