因为造轮子,我一个月就转正了
Java后端技术
共 16413字,需浏览 33分钟
·
2022-04-28 21:57
往期热门文章:
1、用了Stream后,代码反而越写越丑? 2、一不小心节约了 591 台机器! 3、你见过哪些目瞪口呆的 Java 代码技巧? 4、笑死!程序员延寿指南开源了 5、互联网黑话,被上海人翻译火了
作者 | Baldwin_KeepMind
责编 | 伍杏玲
出品 | CSDN博客
public interface Constants {
//等下要引入的配置文件名
String CONFIG_FILE_NAME = "yzlogconfig";
//配置文件中配置的日志路径
String CONFIG_LOG_PATH = "logpath";
//配置文件中配置的要扫描的,可能存在我们注解的路径
String CONFIG_SACN_PATH = "scanpath";
//若未声明某些信息,则使用以下默认值
//默认的我们的日志信息前缀,对日志信息做简单描述
String DEFAULT_CONTENT_PREFIX = "注入值:";
//默认的日志文件名(实际写入时会在日志文件名后加上日期标签)
String DEFAULT_FILE_NAME = "log";
//日志信息类型,处理消息时会用到
String MSG_TYPE_LOG = "log";
//默认的Linux系统下的日志路径
String LINUX_LOG_PATH = "/home/data/";
//默认的Windows系统下的日志路径
String WIN_LOG_PATH = "D:/winLog/data/";
}
import java.util.ResourceBundle;
public class ConfigurationUtil {
private static Object lock = new Object();
private static ConfigurationUtil config = null;
private static ResourceBundle rb = null;
private ConfigurationUtil(String filename) {
rb = ResourceBundle.getBundle(filename);
}
public static ConfigurationUtil getInstance(String filename) {
synchronized (lock) {
if (null == config) {
config = new ConfigurationUtil(filename);
}
}
return (config);
}
public String getValue(String key) {
String ret = "";
if (rb.containsKey(key)) {
ret = rb.getString(key);
}
return ret;
}
}
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtil {
public final static String DATE_A = "yyyy-MM-dd";
public final static String DATE_B = "yyyy-MM-dd HH:mm:ss";
public final static String DATE_C = "yyyyMMddHHmmss";
public final static String DATE_D = "yyyyMMdd-HHmmss-SS";
public final static String DATE_E = "M月d日";
public final static String DATE_F = "MM-dd";
public final static String DATE_G = "yyyyMMddHHmmss";
// 普通的当前时间转字符串方法,格式为yyyy-MM-dd
public static String getDate() {
SimpleDateFormat sdf = new SimpleDateFormat(DATE_A);
return sdf.format(new Date());
}
public static String getDateTime() {
Date date = new Date();
String datestr;
SimpleDateFormat sdf = new SimpleDateFormat(DATE_B);
datestr = sdf.format(date);
return datestr;
}
}
/**
*@描述 用于判断当前系统
*@参数
*@返回值
*@创建人 Baldwin
*@创建时间 2020/4/4
*@修改人和其它信息
*/
public class SystemUtil {
/**
* 判断系统时win还是linux
* @return
*/
public static boolean isLinux(){
String name = System.getProperty("os.name");
if(name.toLowerCase().startsWith("win"))
return false;
else
return true;
}
}
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
public class FileUtil {
// 在已经存在的文件后面追加写的方式
public static boolean write(String path, String str) {
File f = new File(path);
File fileParent = f.getParentFile();
BufferedWriter bw = null;
try {
if(!fileParent.exists()){
fileParent.mkdirs();
}
if(!f.exists()){
f.createNewFile();
}
// new FileWriter(name,true)设置文件为在尾部添加模式,参数为false和没有参数都代表覆写方式
bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path, true), "UTF-8"));
bw.write(str);
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
try {
if(bw!=null)bw.close();
} catch (Exception e) {
System.out.println("FileUtil.write colse bw wrong:" + e);
}
}
return true;
}
}
import cn.yzstu.support.Constants;
import cn.yzstu.support.DateUtil;
import cn.yzstu.support.FileUtil;
import cn.yzstu.support.SystemUtil;
public class LogUtil {
//日志写入操作
public static void write2file(String path, String fileName, String content) {
//获取当前日期,我们的日志保存的文件夹名是自定义path+日期
String date = DateUtil.getDate()+"/";
try {
//传了path,那我们直接用这个path
if (null != path && 0 != path.length()) {
//写入
FileUtil.write(path + date + fileName + ".txt",
DateUtil.getDateTime() + ":" + content + "\r\n");
} else {
//没有传path或错误使用默认的路径
if (SystemUtil.isLinux()) {
FileUtil.write(Constants.LINUX_LOG_PATH + date + fileName + ".txt",
DateUtil.getDateTime() + ":" + content + "\r\n");
} else {
FileUtil.write(Constants.WIN_LOG_PATH + date + fileName + ".txt",
DateUtil.getDateTime() + ":" + content + "\r\n");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
import cn.yzstu.core.MsgQueue;
import cn.yzstu.support.Constants;
public class LogMsg {
private String path;
private String content;
private String fileName;
private String msgType;
public LogMsg(String path, String content, String fileName) {
this.path = path;
this.content = content;
this.fileName = fileName;
this.msgType = "logmsg";
//在构造函数中就让这个消息入列
MsgQueue.push(this);
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getMsgType() {
return this.msgType;
}
public void setMsgType(String msgType) {
this.msgType = msgType;
}
@Override
public String toString() {
return "LogMsg{" +
"path='" + path + '\'' +
", content='" + content + '\'' +
", fileName='" + fileName + '\'' +
", msgType='" + msgType + '\'' +
'}';
}
}
import cn.yzstu.beans.LogMsg;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;
public class MsgQueue {
private static Queuequeue = new ConcurrentLinkedDeque<>();
//消息入列
public static boolean push(LogMsg logMsg){
return queue.offer(logMsg);
}
//消息出列
public static LogMsg poll(){
return queue.poll();
}
//消息队列是否已经处理完毕,处理完毕返回true
public static boolean isFinash(){
return !queue.isEmpty();
}
}
import java.lang.annotation.*;
//作用于字段
@Target({ElementType.FIELD})
//运行时生效
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface YzLogWrite {
//需要注解的值
int value() default -1;
//默认是Linux系统,默认记录文件夹如下
String path() default "";
//文件名
String fileName() default "";
//内容
String msgPrefix() default "";
}
import cn.yzstu.annotation.YzLogWrite;
import cn.yzstu.beans.LogMsg;
import cn.yzstu.support.Constants;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
public class DealAnnotation {
//配置文件中设置的log所在地址
private static String LOG_PATH = ConfigurationUtil.getInstance(Constants.CONFIG_FILE_NAME).getValue(Constants.CONFIG_LOG_PATH);
//保存那些存在注解的class的类名
private List<String> registyClasses = new ArrayList<>();
public void injectAndMakeMsg() {
//需要扫描的注解可能存在的位置
String scanPath = ConfigurationUtil.getInstance(Constants.CONFIG_FILE_NAME).getValue(Constants.CONFIG_SACN_PATH);
doScanner(scanPath);
for (String className : registyClasses) {
try {
Class clazz = Class.forName(className);
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
//获取类的所有注解
Annotation[] annotations = field.getAnnotations();
//没有注解或没有我们的注解,跳过
if (0 == annotations.length || !field.isAnnotationPresent(YzLogWrite.class)) {
continue;
}
//获取注解
YzLogWrite yzLogWrite = field.getAnnotation(YzLogWrite.class);
//提取注解中的值
//声明大于配置
String path = null == yzLogWrite.path() || yzLogWrite.path().isEmpty() ? LOG_PATH : yzLogWrite.path();
String content = null == yzLogWrite.msgPrefix() || yzLogWrite.msgPrefix().isEmpty() ? Constants.DEFAULT_CONTENT_PREFIX : yzLogWrite.msgPrefix();
String fileName = null == yzLogWrite.fileName() || yzLogWrite.fileName().isEmpty() ? Constants.DEFAULT_FILE_NAME : yzLogWrite.fileName();
int value = yzLogWrite.value();
//新建logMsg,在构造函数中已入列
new LogMsg(path, content + ":" + value, fileName);
//开始注入
//强制访问该成员变量
field.setAccessible(true);
//注入int值
field.setInt(Integer.class, value);
}
} catch (ClassNotFoundException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
private void doScanner(String scanPath) {
URL url = this.getClass().getClassLoader().getResource(scanPath.replaceAll("\\.", "/"));
File classPath = new File(url.getFile());
for (File file : classPath.listFiles()) {
if (file.isDirectory()) {
//如果是目录则递归调用,直到找到class
doScanner(scanPath + "." + file.getName());
} else {
if (!file.getName().endsWith(".class")) {
continue;
}
String className = (scanPath.replace("/", ".") + "." + file.getName().replace(".class", ""));
registyClasses.add(className);
}
}
}
}
import cn.yzstu.beans.LogMsg;
public class DealMsg extends Thread{
@Override
public void run() {
while (MsgQueue.isFinash()){
//多态
//实际中,我们可以定义很多中msg,用type来区分,并通过不同的方法来处理
//此处运用了这种思想,但是没有实现具体操作
LogMsg logMsg = MsgQueue.poll();
switch (logMsg.getMsgType()){
case "logmsg" :
//如果类型是logmsg,那就通过日志来处理
dealLogMsg(logMsg);
break;
default:defaultMethod(logMsg);
}
}
this.interrupt();
}
private void defaultMethod(LogMsg logMsg) {
System.out.println("no msg");
}
private void dealLogMsg(LogMsg logMsg) {
LogUtil.write2file(logMsg.getPath(),logMsg.getFileName(),logMsg.getContent());
}
@Override
public synchronized void start() {
this.run();
}
}
import cn.yzstu.annotation.YzLogWrite;
public class StartWork {
//程序入口
public static void doWork(){
//处理:扫描注解、注入、发送日志消息到队列
new DealAnnotation().injectAndMakeMsg();
//创建线程来处理消息
new DealMsg().start();
}
}
#logpath最后需要带/
logpath = /opt/
scanpath = cn/yzstu/tt
import cn.yzstu.annotation.YzLogWrite;
import cn.yzstu.core.StartWork;
public class Demo {
//因为测试用的main函数是static,所以此时将age设置为static
@YzLogWrite(value = 18,msgPrefix = "记录Baldwin的年龄:")
static int age;
public static void main(String[] args) {
StartWork.doWork();
System.out.println(age);
}
}
/opt/java/jdk1.8.0_241/bin/java -javaagent:/opt/jetbrains/idea-IU-193.6911.18/lib/idea_rt.jar=38115:/opt/jetbrains/idea-IU-193.6911.18/bin -Dfile.encoding=UTF-8 -classpath /opt/java/jdk1.8.0_241/jre/lib/charsets.jar:/opt/java/jdk1.8.0_241/jre/lib/deploy.jar:/opt/java/jdk1.8.0_241/jre/lib/ext/cldrdata.jar:/opt/java/jdk1.8.0_241/jre/lib/ext/dnsns.jar:/opt/java/jdk1.8.0_241/jre/lib/ext/jaccess.jar:/opt/java/jdk1.8.0_241/jre/lib/ext/jfxrt.jar:/opt/java/jdk1.8.0_241/jre/lib/ext/localedata.jar:/opt/java/jdk1.8.0_241/jre/lib/ext/nashorn.jar:/opt/java/jdk1.8.0_241/jre/lib/ext/sunec.jar:/opt/java/jdk1.8.0_241/jre/lib/ext/sunjce_provider.jar:/opt/java/jdk1.8.0_241/jre/lib/ext/sunpkcs11.jar:/opt/java/jdk1.8.0_241/jre/lib/ext/zipfs.jar:/opt/java/jdk1.8.0_241/jre/lib/javaws.jar:/opt/java/jdk1.8.0_241/jre/lib/jce.jar:/opt/java/jdk1.8.0_241/jre/lib/jfr.jar:/opt/java/jdk1.8.0_241/jre/lib/jfxswt.jar:/opt/java/jdk1.8.0_241/jre/lib/jsse.jar:/opt/java/jdk1.8.0_241/jre/lib/management-agent.jar:/opt/java/jdk1.8.0_241/jre/lib/plugin.jar:/opt/java/jdk1.8.0_241/jre/lib/resources.jar:/opt/java/jdk1.8.0_241/jre/lib/rt.jar:/root/IdeaProjects/LogUtil/target/classes cn.yzstu.tt.Demo
18
Process finished with exit code 0
2020-04-06 00:17:30:记录Baldwin的年龄::18
往期热门文章:
1、笑死!程序员延寿指南开源了 2、用 Dubbo 传输文件?被老板一顿揍! 3、45 个 Git 经典操作场景,专治不会合代码! 4、@Transactional 注解失效的3种原因及解决办法 5、小学生们在B站讲算法,网友:我只会阿巴阿巴 6、Spring爆出比Log4j2还大的漏洞? 7、Objects.equals 有坑!!! 8、Redis 官方可视化工具,功能真心强大! 8、xxl-job 和 ElasticJob比,谁牛? 10、推荐好用的 Spring Boot 内置工具类
评论