实现Web层的日志切面(方便清晰查看日志)
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层的日志切面(方便清晰查看日志)的更多相关文章
- web部署启动或者运行报错查看日志寻找问题方法
今天运行一个项目,启动报错,查看日志,只看到了前半段错误日志,根据前半段错误日志差查找原因,找了两个小时,也没有解决掉,最后根据后半段错误日志十分钟定位错误,给解决了,以后出现问题不能急躁,查看完成的 ...
- 【docker】docker限制日志文件大小的方法+查看日志文件的方法
一.docker日志文件的方法 除了 docker logs -f 容器ID/容器名 这个方法以外. 在linux上,一般docker的日志文件存储在/var/lib/docker/container ...
- Web层后端权限模块
从零开始编写自己的C#框架(19)——Web层后端权限模块 不知不觉本系统写了快三个月了,最近写页面的具体功能时感觉到有点吃力,很多地方如果张嘴来讲的话可以说得很细,很全面,可写成文字的话,就不太 ...
- Django websocket之web端实时查看日志实践案例
这是Django Channels系列文章的第二篇,以web端实现tailf的案例讲解Channels的具体使用以及跟Celery的结合 通过上一篇<Django使用Channels实现WebS ...
- 从零开始编写自己的C#框架(16)——Web层后端父类
本章节讲述的各个类是后端系统的核心之一,涉及到系统安全验证.操作日志记录.页面与按键权限控制.后端页面功能封装等内容,希望学习本系列的朋友认真查看新增的类与函数,这对以后使用本框架进行开发时非常重要. ...
- Spring Boot 2.0 教程 | AOP 切面统一打印请求日志
欢迎关注微信公众号: 小哈学Java 文章首发于个人网站 https://www.exception.site/springboot/spring-boot-aop-web-request 本节中,您 ...
- 状态维持在web层 每层都可以Cache
API网关的开源解决方案那么多,为什么我们却还要选择自研? - SDK.CN - 中国领先的开发者服务平台 https://sdk.cn/news/8001 技术细节Microservice+SOA状 ...
- Web 层由 Web,Web-MVC,Web-Socket 和 Web-Portlet 组成
Web 层由 Web,Web-MVC,Web-Socket 和 Web-Portlet 组成,它们的细节如下: Web 模块提供面向web的基本功能和面向web的应用上下文,比如多部分(multipa ...
- SpringBoot2.0 基础案例(11):配置AOP切面编程,解决日志记录业务
本文源码 GitHub地址:知了一笑 https://github.com/cicadasmile/spring-boot-base 一.AOP切面编程 1.什么是AOP编程 在软件业,AOP为Asp ...
随机推荐
- Kotlin 数据类型(数值类型)
Kotlin 的常见数据类型: 类型 范围 byte -128~127 short 32767-32768 int -2147483648~2147483647 long 92233720368547 ...
- laravel安装[转https://laravelacademy.org/post/9528.html]
Laravel 框架对PHP版本和扩展有一定要求,不过这些要求 Laravel Homestead 都已经满足了,不过如果你没有使用 Homestead 的话(那真是一件很遗憾的事情),有必要了解下这 ...
- DP【洛谷P4290】 [HAOI2008]玩具取名
P4290 [HAOI2008]玩具取名 某人有一套玩具,并想法给玩具命名.首先他选择WING四个字母中的任意一个字母作为玩具的基本名字.然后他会根据自己的喜好,将名字中任意一个字母用"WI ...
- luogu4449 于神之怒加强版(莫比乌斯反演)
link 给定n,m,k,计算\(\sum_{i=1}^n\sum_{j=1}^m\gcd(i,j)^k\)对1000000007取模的结果 多组数据,T<=2000,1<=N,M,K&l ...
- 基础线程机制--Executor线程池框架
基础线程机制 Executor线程池框架 1.引入Executor的原因 (1)new Thread()的缺点 每次new Thread()耗费性能 调用new Thread()创建的线程 ...
- Alpha冲刺(6/10)——2019.4.28
作业描述 课程 软件工程1916|W(福州大学) 团队名称 修!咻咻! 作业要求 项目Alpha冲刺(团队) 团队目标 切实可行的计算机协会维修预约平台 开发工具 Eclipse 团队信息 队员学号 ...
- C++的一种业务分发方案(另类的工厂模式)
在C++中,传统的业务分发.总要写一大串的switch-case,并且每次添加新业务时.都要在原有的switch-case里加一个分支,这就违反了设计模式中的开放封闭原则. 下面这样的方案,就全然去除 ...
- 07. 如何实现移动端rem适配
如何实现移动端rem适配 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...
- Xshell连接不上Ubuntu解决方式
1—— 首先检查一下自己的网络是否正常,如果是插上网线就能用的,就很好:如果是校园网拨号方式上网的,请检查自己是否建立拨号连接. [编辑连接] [添加] PPPOE上网方式选择[DSL] 2—— ...
- 74th LeetCode Weekly Contest Number of Subarrays with Bounded Maximum
We are given an array A of positive integers, and two positive integers L and R (L <= R). Return ...