网站首页 > 精选教程 正文
一、业务场景
web 项目开发中,经常会有的一个操作是记录请求日志,比如记录请求的 IP 地址,记录请求的路径,记录请求的参数等等。
每个系统都会根据自己的需要来记录一些请求相关的日志。一般会将记录的日志信息保存到数据库中,以便于查看,如出现异常
高频率的访问请求,或者是遇到其他一些问题都可以查看记录的日志来进行排查问题。如果系统的请求比较少的话,直接记录日志
则没什么问题,可是如果请求量比较大的时候,如何来优化日志记录的操作呢?
二、需求分析
本篇文章所说的这种方式是使用异步的方式来记录日志。 Java 代码一般都是同步执行,所谓同步执行,简单理解
就是从上往下执行, 必须要等待上一行代码执行完之后,才会执行下一行代码。了解前端的同学应该对异步操作并不
陌生,页面中的很多 ajaxx 请求大多都是 异步执行的,并不一定要等前面一行的代码执行完,后面一行的代码也可以执
行。可是在 Java 中如何来进行异步操作呢?
三、解决方案
从当前项目中 学习到的方式如下:
大致的思路是,在 web 项目中使用拦截器来拦截需要记录日志的请求,在这个拦截器的拦截方法中,获取一个记录日志的任务对象,
对象是多实例的。然后使用 这个对象设置一些指定的值,比如请求路径,请求 IP ,请求求时间信息等等。将这些值设置好之后,在使用
一个工具类来调用方法,传入的参数 为这个任务处理类。之后就可以使用异步线程的方式来记录请求的日志数据。自己模仿项目中的方
式写的代码如下 :
拦截器中的代码 :
@Slf4j
public classLogRecordInterceptor **implements** HandlerInterceptor{
@Autowired
privateLogRecordRunnableTask **logRecordRunnableTask** ;
@Override
public booleanpreHandle(HttpServletRequest request, HttpServletResponse response, Object handler) **throws** Exception {
try{
String requestURL = request.getRequestURL().toString();
logRecordRunnableTask.setUrl(requestURL);
logRecordRunnableTask.setRequestTime(CommonUtil. *getCurrentDateTime* ());
RecordLogRunnableUtils. *submit* ( **logRecordRunnableTask** );
} **catch** (Exception ex) {
*log* .error( **"日志记录异常--->{}"** , ex);
}
return true;
}
}
注册拦截器bean对象的代码 :
@Configuration
public classWebMvcConfig **extends** WebMvcConfigurerAdapter {
*/**** * Function: addInterceptors** * Author : kaye0110,** * Version : 1.0** * Description : 注册拦截器 ** * Param and Description : ** * ****@param* *****registry*****/* @Override
public voidaddInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(logRecordInterceptor()).addPathPatterns( **"/**"** );
super.addInterceptors(registry);
}
@Bean
publicLogRecordInterceptor logRecordInterceptor(){
return newLogRecordInterceptor();
}
}
日志任务处理类的代码
@Data
@Component
@Scope( **"prototype"** )
public classLogRecordRunnableTask **implements** Runnable{
@Autowired
privateLogRecordService **logRecordService** ;
*/*** * 请求地址** */* **private** String **url** ;
*/*** * 请求时间** */* **private** String **requestTime** ;
@Override
public voidrun() {
logRecordService.createLogRecord( **url** , **requestTime** );
}
}
注意:这个类是多实例的,类中实现 Runnable 接口,重写 Run 方法,就在这个方法中执行记录日志的操作。
Service 接口实现类的代码 .
@Slf4j
@Service
public classLogRecordServiceImpl **implements** LogRecordService {
@Override
public voidcreateLogRecord(String url, String recordTime) {
*log* .info( **"url-->{}, recordTime--->{}"** , url, recordTime);
}
}
日志记录工具类的代码
@Slf4j
public classRecordLogRunnableUtils {
privateRecordLogRunnableUtils(){}
private staticExecutorService *executor* = Executors. *newFixedThreadPool* (20);
*/* @Description: 执行日志记录操作** * @author: yilang** * @date: 2022/7/27 13:03** * @param: runnable** * @return: void** */* **public static void** submit(Runnable runnable) {
try{
*executor* .submit(runnable);
} **catch** (Exception ex) {
*log* .error( **"执行日志操作异常:{}"** , ex);
}
}
}
简单测试了一下,使用 postman 一次性发 30 个请求 .
测试结果如下结果符合预期,程序正常执行,后台记录日志的时候是使用多线程的方式来进行处理的。
以后有需要的同学完全可以采用这种方式,来优化日志记录的操作,当访问量越来越大时,这种方式的优点也会提现得更加明显。
以前也有同事使用过其他方式来优化日志记录,首先将请求的日志信息保存在的 redis 中,然后另外跑一个定时任务定时去取
这些日志信息, 如果日志信息大于 100 条则将其存储在数据库中,并且删除已保存的 数据。这样在一定程度上也可以提高日志
猜你喜欢
- 2024-11-27 多线程技术(同步异步,并发并行)守护线程(java垃圾回收机制)
- 2024-11-27 Java 爬虫遇上数据异步加载,试试这两种办法
- 2024-11-27 Java 17 多线程的同步和异步synchronized关键字
- 2024-11-27 java异步编程产生的原因
- 2024-11-27 Java:了解Java中的异步套接字通道
- 2024-11-27 Java面试常见问题:阻塞与非阻塞,同步与异步
- 2024-11-27 parseq-让java异步并发编程更简单
- 2024-11-27 Java异步编程实战:基于JDK中的Future实现异步编程
- 2024-11-27 Java8异步编程就是拽的不行
- 2024-11-27 Java异步任务优化CompletionService
你 发表评论:
欢迎- 04-11Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- 04-11Java中你知道几种从字符串中找指定的字符的数量
- 04-11探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- 04-11Python字符串详解与示例(python字符串的常见操作)
- 04-11java正则-取出指定字符串之间的内容
- 04-11String s1 = new String("abc");这句话创建了几个字符串对象?
- 04-11java判断字符串中是否包含某个字符
- 04-11关于java开发中正确的发牌逻辑编写规范
- 最近发表
-
- Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- Java中你知道几种从字符串中找指定的字符的数量
- 探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- Python字符串详解与示例(python字符串的常见操作)
- java正则-取出指定字符串之间的内容
- String s1 = new String("abc");这句话创建了几个字符串对象?
- java判断字符串中是否包含某个字符
- 关于java开发中正确的发牌逻辑编写规范
- windows、linux如何后台运行jar(并且显示进程名)
- 腾讯大佬私人收藏,GitHub上最受欢迎的100个JAVA库,值得学习
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)