wordpress 批量文章/手机网站怎么优化
概览
日志服务是项目中必不可少的的一个,通过面向切面的编程,我们可以统一处理日志逻辑,现在市面上有很多优秀的日志框架,但是者不妨碍我们通过自己编写的日志框架了解其底层原理。
思路
- aop采集日志
- 把日志存入一个有序的、堵塞的队列中
- 单独开一个线程通过异步方式,把队列中的日志写入到文件中。
核心代码
- pom配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>log-manager</artifactId><version>0.0.1-SNAPSHOT</version><name>log-manager</name><description>log-manager</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 引入aop插件包 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>2.7.2</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.7</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
- 日志写入处理类
package com.example.logmanager.utils;import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;@Component
public class LogManager {private static BlockingQueue<String> blockingQueue = new LinkedBlockingQueue<>();private static final String filePath = "C:\\Users\\Administrator\\Desktop\\123.log";public LogManager() {new LogThread().start();}public static void addLog(String msg){blockingQueue.add(msg);}class LogThread extends Thread {@Overridepublic void run() {while (true) {String log = blockingQueue.poll();if(StringUtils.hasLength(log)) {// 写入本地FileUtils.writeText(filePath, log, true);}}}}
}
- 切面逻辑
package com.example.logmanager.aop;import com.example.logmanager.utils.LogManager;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;@Component
@Aspect
public class AopLog {@Pointcut("execution(public * com.example.logmanager.controller..*(..))")public void log(){};@Before("log()")public void before(JoinPoint joinPoint){ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = Objects.requireNonNull(requestAttributes).getRequest();LogManager.addLog("[请求的url]:" + request.getRequestURL());LogManager.addLog("[请求的Ip]:" + request.getRemoteAddr());LogManager.addLog("[类名 Class]:" + joinPoint.getSignature().getDeclaringTypeName());}
}
- 文件操作工具类
package com.example.logmanager.utils;import java.io.*;
import java.nio.channels.FileChannel;public class FileUtils {/*判断文件是否存在*/public static boolean isExists(String filePath) {File file = new File(filePath);return file.exists();}/*判断是否是文件夹*/public static boolean isDir(String path) {File file = new File(path);if (file.exists()) {return file.isDirectory();} else {return false;}}/*** 文件或者目录重命名** @param oldFilePath 旧文件路径* @param newName 新的文件名,可以是单个文件名和绝对路径* @return*/public static boolean renameTo(String oldFilePath, String newName) {try {File oldFile = new File(oldFilePath);//若文件存在if (oldFile.exists()) {//判断是全路径还是文件名if (newName.indexOf("/") < 0 && newName.indexOf("\\") < 0) {//单文件名,判断是windows还是Linux系统String absolutePath = oldFile.getAbsolutePath();if (newName.indexOf("/") > 0) {//Linux系统newName = absolutePath.substring(0, absolutePath.lastIndexOf("/") + 1) + newName;} else {newName = absolutePath.substring(0, absolutePath.lastIndexOf("\\") + 1) + newName;}}File file = new File(newName);//判断重命名后的文件是否存在if (file.exists()) {System.out.println("该文件已存在,不能重命名");} else {//不存在,重命名return oldFile.renameTo(file);}} else {System.out.println("原该文件不存在,不能重命名");}} catch (Exception e) {e.printStackTrace();}return false;}/*文件拷贝操作*/public static void copy(String sourceFile, String targetFile) {File source = new File(sourceFile);File target = new File(targetFile);target.getParentFile().mkdirs();FileInputStream fis = null;FileOutputStream fos = null;FileChannel in = null;FileChannel out = null;try {fis = new FileInputStream(source);fos = new FileOutputStream(target);in = fis.getChannel();//得到对应的文件通道out = fos.getChannel();//得到对应的文件通道in.transferTo(0, in.size(), out);//连接两个通道,并且从in通道读取,然后写入out通道} catch (IOException e) {e.printStackTrace();} finally {try {if (out != null) {out.close();}if (in != null) {in.close();}if (fos != null) {fos.close();}if (fis != null) {fis.close();}} catch (IOException e) {e.printStackTrace();}}}/*读取Text文件操作*/public static String readText(String filePath) {String lines = "";try {FileReader fileReader = new FileReader(filePath);BufferedReader bufferedReader = new BufferedReader(fileReader);String line = null;while ((line = bufferedReader.readLine()) != null) {lines += line + "\n";}} catch (Exception e) {e.printStackTrace();}return lines;}/*写入Text文件操作*/public static void writeText(String filePath, String content, boolean isAppend) {FileOutputStream outputStream = null;OutputStreamWriter outputStreamWriter = null;BufferedWriter bufferedWriter = null;try {outputStream = new FileOutputStream(filePath, isAppend);outputStreamWriter = new OutputStreamWriter(outputStream);bufferedWriter = new BufferedWriter(outputStreamWriter);bufferedWriter.write(content);bufferedWriter.newLine();} catch (IOException e) {e.printStackTrace();} finally {try {if (bufferedWriter != null) {bufferedWriter.close();}if (outputStreamWriter != null) {outputStreamWriter.close();}if (outputStream != null) {outputStream.close();}} catch (Exception e) {e.printStackTrace();}}}}
- 测试controller
package com.example.logmanager.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/test")
public class TestController {@GetMappingpublic String test(){return "succ";}
}