Java 操作二维码的开源项目很多,如 SwetakeQRCode、BarCode4j、Zxing 等,这边以Zxing 为例进行介绍。
选择需要生成QR原始文件,支持 “清除空白行及空格” 以减少二维码图片大小。
代码结构
QrCodeUI: 完整版本代码
SimpleQrCodeUI:简化版本代码
如何使用下面的备份文件恢复成原始的项目代码,请移步查阅:神奇代码恢复工具
//goto pom.xml
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.fly</groupId>
<artifactId>file-to-qrcode</artifactId>
<version>0.0.1</version>
<name>file-to-qrcode</name>
<url>http://maven.apache.org</url>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<log4j.version>2.12.1</log4j.version>
</properties>
<dependencies>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
//goto src\main\java\com\fly\MainRun.java
package com.fly;
import javax.swing.SwingUtilities;
import org.apache.commons.lang3.RandomUtils;
import com.fly.ui.QrCodeUI;
import com.fly.ui.SimpleQrCodeUI;
/**
*
* MainRun
*
* @author 00fly
* @version [版本号, 2023年3月5日]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public class MainRun
{
public static void main(String[] args)
{
// 随机运行
boolean input = RandomUtils.nextBoolean();
if (input)
{
SwingUtilities.invokeLater(() -> new QrCodeUI());
return;
}
SwingUtilities.invokeLater(() -> new SimpleQrCodeUI());
}
}
//goto src\main\java\com\fly\ui\QrCodeUI.java
package com.fly.ui;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.filechooser.FileFilter;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import com.fly.utils.QRCodeUtil;
/*****
* 界面操作展示类
*/
public class QrCodeUI extends JFrame
{
private static final long serialVersionUID = -9154321945329564644L;
// 界面组件
JPanel panel = new JPanel();
JTextArea textArea = new JTextArea();
JTextField fileText = new JTextField(null, 40);
JButton fileDirBrowse = new JButton("请选择");
JButton removeButton = new JButton("清除空白行及空格");
JButton qrButton = new JButton(" 生 成 二 维 码 ");
JButton clearButton = new JButton(" 清 除 内 容 ");
// 构造函数
public QrCodeUI()
{
// 加载图标
URL imgURL = getClass().getResource("/img/icon.gif");
if (imgURL != null)
{
Image image = getToolkit().createImage(imgURL);
setIconImage(image);
}
setTitle("二维码应用工具 V1.0");
setSize(900, 550);
Dimension screenSize = getToolkit().getScreenSize();
Dimension frameSize = this.getSize();
frameSize.height = Math.min(screenSize.height, frameSize.height);
frameSize.width = Math.min(screenSize.width, frameSize.width);
setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);
addMenu();
addButton();
try
{
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
SwingUtilities.updateComponentTreeUI(this);
}
catch (Exception e)
{
}
setResizable(false);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
fileText.setFocusable(false);
}
// Menu set
private void addMenu()
{
JMenuBar mb = new JMenuBar();
// 一级菜单
JMenu conf = new JMenu(" 系 统 ");
// 子菜单
JMenuItem exit = new JMenuItem("退出");
exit.addActionListener(event -> System.exit(0));
conf.add(exit);
mb.add(conf);
JMenu help = new JMenu(" 帮 助 ");
JMenuItem about = new JMenuItem("关于工具");
about.addActionListener((ActionEvent event) -> JOptionPane.showMessageDialog(null, "二维码应用工具 V1.0,00fly 于2023年3月。\n", "关于本工具", JOptionPane.INFORMATION_MESSAGE));
help.add(about);
mb.add(help);
setJMenuBar(mb);
}
// JButton set
private void addButton()
{
panel.setLayout(null);
getContentPane().add(panel);
JLabel textLabel = new JLabel("文件内容");
textLabel.setBounds(20, 10, 120, 18);
panel.add(textLabel);
JLabel fileLabel = new JLabel(" 待生成QR原始文件");
fileLabel.setBounds(30, 410, 240, 18);
panel.add(fileLabel);
textArea.setEditable(false);
JScrollPane scroll = new JScrollPane(textArea);
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scroll.setBounds(20, 30, 850, 360);
panel.add(scroll);
fileText.setBounds(150, 410, 450, 24);
fileText.setText(new File(" ").getAbsolutePath().trim());
fileText.setToolTipText("选择需要生成二维码图片的原始文本文件,包含xml、java、yaml、md等");
panel.add(fileText);
fileDirBrowse.setBounds(610, 410, 80, 25);
fileDirBrowse.setToolTipText("选择需要生成二维码图片的原始文本文件,包含xml、java、yaml、md等");
fileDirBrowse.addActionListener(event -> {
String path = fileText.getText();
File xmlfile = new File(path);
if (new File(fileText.getText()).exists())
{
xmlfile = new File(path).getParentFile();
}
JFileChooser fc = new JFileChooser(xmlfile);
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
fc.setDialogTitle("原始文件选择");
if (fc.showOpenDialog(null) == JFileChooser.CANCEL_OPTION)
{
return;
}
fc.setFileFilter(new FileFilter()
{
@Override
public boolean accept(File file)
{
String name = file.getName().toLowerCase();
return name.endsWith(".xml") || name.endsWith(".java") || name.endsWith(".yml") || name.endsWith(".yaml") || name.endsWith(".md") || name.endsWith(".txt");
}
@Override
public String getDescription()
{
return "";
}
});
File f = fc.getSelectedFile();
if (f != null && f.isFile())
{
fileText.setText(f.getAbsolutePath());
try
{
textArea.setText(FileUtils.readFileToString(f, StandardCharsets.UTF_8));
qrButton.setEnabled(true);
}
catch (IOException e)
{
}
}
});
panel.add(fileDirBrowse);
removeButton.addMouseListener(new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
String content = textArea.getText();
if (StringUtils.isNotBlank(content))
{
content = content.replaceAll("\t", " ").replaceAll("((\r\n)|\n)[\\s\t ]*(\\1)+", "$1");
textArea.setText(content);
}
}
});
removeButton.setBounds(100, 450, 160, 30);
removeButton.add(qrButton);
panel.add(removeButton);
qrButton.addMouseListener(new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
if (!qrButton.isEnabled())
{
return;
}
try
{
String content = textArea.getText();
BufferedImage image = QRCodeUtil.createImage(content, "", false);
new ShowDialog(image);
}
catch (Exception e1)
{
JOptionPane.showMessageDialog(null, "失败原因: " + e1.getMessage(), "二维码生成失败", JOptionPane.ERROR_MESSAGE);
}
}
});
qrButton.setBounds(350, 450, 160, 30);
qrButton.setEnabled(false);
panel.add(qrButton);
clearButton.addMouseListener(new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
textArea.setText(null);
qrButton.setEnabled(false);
}
});
clearButton.setBounds(600, 450, 160, 30);
panel.add(clearButton);
}
// Run
public static void main(String[] args)
{
SwingUtilities.invokeLater(() -> new QrCodeUI());
}
}
//goto src\main\java\com\fly\ui\ShowDialog.java
package com.fly.ui;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JLabel;
/**
*
* qr显示弹出窗口
*
* @author 00fly
* @version [版本号, 2023年3月3日]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public class ShowDialog extends JDialog
{
private static final long serialVersionUID = 8010838747205419843L;
public ShowDialog(BufferedImage image)
{
super();
// 加载图标
URL imgURL = getClass().getResource("/img/icon.gif");
if (imgURL != null)
{
setIconImage(getToolkit().createImage(imgURL));
}
setTitle("请扫描二维码");
setSize(510, 530);
// 自适应居中处理
Dimension screenSize = getToolkit().getScreenSize();
Dimension dialogSize = getSize();
dialogSize.height = Math.min(screenSize.height, dialogSize.height);
dialogSize.width = Math.min(screenSize.width, dialogSize.width);
setLocation((screenSize.width - dialogSize.width) / 2, (screenSize.height - dialogSize.height) / 2);
// 生成二维码图片
add(new JLabel(new ImageIcon(image)));
setVisible(true);
setResizable(false);
setAlwaysOnTop(true);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
}
}
//goto src\main\java\com\fly\ui\SimpleQrCodeUI.java
package com.fly.ui;
import java.awt.BorderLayout;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import org.apache.commons.lang3.StringUtils;
import com.fly.utils.QRCodeUtil;
/**
*
* 文本二维码生成简化版本
*
* @author 00fly
* @version [版本号, 2023年3月3日]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public class SimpleQrCodeUI extends JFrame
{
private static final long serialVersionUID = -708209618541039567L;
JTextArea textArea = new JTextArea();
JButton qrButton = new JButton("生 成 二 维 码");
public SimpleQrCodeUI()
throws HeadlessException
{
initComponent();
// 设定用户界面的外观
try
{
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
SwingUtilities.updateComponentTreeUI(this);
}
catch (Exception e)
{
}
// 加载图标
URL imgURL = getClass().getResource("/img/icon.gif");
if (imgURL != null)
{
Image image = getToolkit().createImage(imgURL);
setIconImage(image);
}
this.setTitle("二维码应用工具 V1.0");
this.setBounds(400, 200, 1200, 550);
this.setResizable(true);
this.setVisible(true);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
/**
* 组件初始化
*
* @see [类、类#方法、类#成员]
*/
private void initComponent()
{
textArea.setToolTipText("输入需要生成二维码图片的原始文本内容");
// JTextArea不自带滚动条,因此就需要把文本区放到一个滚动窗格中
JScrollPane scroll = new JScrollPane(textArea);
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
this.add(scroll, BorderLayout.CENTER);
this.add(qrButton, BorderLayout.SOUTH);
qrButton.addMouseListener(new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
try
{
String content = textArea.getText();
if (StringUtils.isNotBlank(content))
{
content = content.replaceAll("\t", " ").replaceAll("((\r\n)|\n)[\\s\t ]*(\\1)+", "$1");
BufferedImage image = QRCodeUtil.createImage(content, "", false);
new ShowDialog(image);
}
}
catch (Exception e1)
{
JOptionPane.showMessageDialog(null, e1.getMessage(), "二维码生成失败", JOptionPane.ERROR_MESSAGE);
}
}
});
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(() -> new SimpleQrCodeUI());
}
}
//goto src\main\java\com\fly\utils\BufferedImageLuminanceSource.java
package com.fly.utils;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import com.google.zxing.LuminanceSource;
public class BufferedImageLuminanceSource extends LuminanceSource
{
private final BufferedImage image;
private final int left;
private final int top;
public BufferedImageLuminanceSource(BufferedImage image)
{
this(image, 0, 0, image.getWidth(), image.getHeight());
}
public BufferedImageLuminanceSource(BufferedImage image, int left, int top, int width, int height)
{
super(width, height);
int sourceWidth = image.getWidth();
int sourceHeight = image.getHeight();
if (left + width > sourceWidth || top + height > sourceHeight)
{
throw new IllegalArgumentException("Crop rectangle does not fit within image data.");
}
for (int y = top; y < top + height; y++)
{
for (int x = left; x < left + width; x++)
{
if ((image.getRGB(x, y) & 0xFF000000) == 0)
{
image.setRGB(x, y, 0xFFFFFFFF); // = white
}
}
}
this.image = new BufferedImage(sourceWidth, sourceHeight, BufferedImage.TYPE_BYTE_GRAY);
this.image.getGraphics().drawImage(image, 0, 0, null);
this.left = left;
this.top = top;
}
@Override
public byte[] getRow(int y, byte[] row)
{
if (y < 0 || y >= getHeight())
{
throw new IllegalArgumentException("Requested row is outside the image: " + y);
}
int width = getWidth();
if (row == null || row.length < width)
{
row = new byte[width];
}
image.getRaster().getDataElements(left, top + y, width, 1, row);
return row;
}
@Override
public byte[] getMatrix()
{
int width = getWidth();
int height = getHeight();
int area = width * height;
byte[] matrix = new byte[area];
image.getRaster().getDataElements(left, top, width, height, matrix);
return matrix;
}
@Override
public boolean isCropSupported()
{
return true;
}
@Override
public LuminanceSource crop(int left, int top, int width, int height)
{
return new BufferedImageLuminanceSource(image, this.left + left, this.top + top, width, height);
}
@Override
public boolean isRotateSupported()
{
return true;
}
@Override
public LuminanceSource rotateCounterClockwise()
{
int sourceWidth = image.getWidth();
int sourceHeight = image.getHeight();
AffineTransform transform = new AffineTransform(0.0, -1.0, 1.0, 0.0, 0.0, sourceWidth);
BufferedImage rotatedImage = new BufferedImage(sourceHeight, sourceWidth, BufferedImage.TYPE_BYTE_GRAY);
Graphics2D g = rotatedImage.createGraphics();
g.drawImage(image, transform, null);
g.dispose();
int width = getWidth();
return new BufferedImageLuminanceSource(rotatedImage, top, sourceWidth - (left + width), getHeight(), width);
}
}
//goto src\main\java\com\fly\utils\QRCodeUtil.java
package com.fly.utils;
import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Shape;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Hashtable;
import javax.imageio.ImageIO;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.Result;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
public class QRCodeUtil
{
private static final String FORMAT_NAME = "JPG";
// 二维码尺寸
private static final int QRCODE_SIZE = 500;
// LOGO宽度
private static final int WIDTH = 60;
// LOGO高度
private static final int HEIGHT = 60;
public static BufferedImage createImage(String content, String imgPath, boolean needCompress)
throws Exception
{
Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, StandardCharsets.UTF_8);
hints.put(EncodeHintType.MARGIN, 1);
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
}
}
if (imgPath == null || "".equals(imgPath))
{
return image;
}
// 插入图片
insertImage(image, imgPath, needCompress);
return image;
}
private static void insertImage(BufferedImage source, String imgPath, boolean needCompress)
throws Exception
{
File file = new File(imgPath);
if (!file.exists())
{
System.err.println(imgPath + " 该文件不存在!");
return;
}
Image src = ImageIO.read(new File(imgPath));
int width = src.getWidth(null);
int height = src.getHeight(null);
if (needCompress)
{
// 压缩LOGO
width = Math.min(width, WIDTH);
height = Math.min(height, HEIGHT);
Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
g.drawImage(image, 0, 0, null); // 绘制缩小后的图
g.dispose();
src = image;
}
// 插入LOGO
Graphics2D graph = source.createGraphics();
int x = (QRCODE_SIZE - width) / 2;
int y = (QRCODE_SIZE - height) / 2;
graph.drawImage(src, x, y, width, height, null);
Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
graph.setStroke(new BasicStroke(3f));
graph.draw(shape);
graph.dispose();
}
public static void encode(String content, String imgPath, String destPath, boolean needCompress)
throws Exception
{
BufferedImage image = createImage(content, imgPath, needCompress);
mkdirs(destPath);
ImageIO.write(image, FORMAT_NAME, new File(destPath));
}
public static BufferedImage encode(String content, String imgPath, boolean needCompress)
throws Exception
{
BufferedImage image = createImage(content, imgPath, needCompress);
return image;
}
public static void mkdirs(String destPath)
{
File file = new File(destPath);
if (!file.exists() && !file.isDirectory())
{
file.mkdirs();
}
}
public static void encode(String content, String imgPath, String destPath)
throws Exception
{
encode(content, imgPath, destPath, false);
}
public static void encode(String content, String destPath)
throws Exception
{
encode(content, null, destPath, false);
}
public static void encode(String content, String imgPath, OutputStream output, boolean needCompress)
throws Exception
{
BufferedImage image = createImage(content, imgPath, needCompress);
ImageIO.write(image, FORMAT_NAME, output);
}
public static void encode(String content, OutputStream output)
throws Exception
{
encode(content, null, output, false);
}
public static String decode(File file)
throws Exception
{
BufferedImage image = ImageIO.read(file);
if (image == null)
{
return null;
}
BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Hashtable<DecodeHintType, String> hints = new Hashtable<>();
hints.put(DecodeHintType.CHARACTER_SET, StandardCharsets.UTF_8.name());
Result result = new MultiFormatReader().decode(bitmap, hints);
return result.getText();
}
public static String decode(String path)
throws Exception
{
return decode(new File(path));
}
}
//goto src\main\resources\log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="off" monitorInterval="0">
<!-- 常量引用 -->
<properties>
<property name="LOG_HOME">logs</property>
<property name="PROJECT">qrcode</property>
<property name="FORMAT">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</property>
</properties>
<!-- appender用于接收各种日志 -->
<appenders>
<!-- 常见的输出到console,常用于开发环境中,默认是system_err,还有一个system_out -->
<console name="Console" target="system_out">
<!-- appender级别的日志过滤 -->
<!-- <thresholdFilter level="info" onMatch="accept" onMismatch="deny"/> -->
<patternLayout pattern="${FORMAT}" />
</console>
<RollingRandomAccessFile name="RollingFileInfo" fileName="${LOG_HOME}/${PROJECT}/info.log" filePattern="${LOG_HOME}/${PROJECT}/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log.gz">
<Filters>
<ThresholdFilter level="error" onMatch="deny" onMismatch="neutral" />
<ThresholdFilter level="warn" onMatch="deny" onMismatch="neutral" />
<ThresholdFilter level="info" onMatch="accept" onMismatch="deny" />
</Filters>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n" />
<Policies>
<TimeBasedTriggeringPolicy modulate="true" interval="1" />
<SizeBasedTriggeringPolicy size="20 MB" />
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件 -->
<DefaultRolloverStrategy max="20">
<Delete basePath="${LOG_HOME}/${PROJECT}/" maxDepth="2">
<IfFileName glob="*/info-*.log.gz" />
<IfLastModified age="60d" />
</Delete>
</DefaultRolloverStrategy>
</RollingRandomAccessFile>
<RollingRandomAccessFile name="RollingFileWarn" fileName="${LOG_HOME}/${PROJECT}/warn.log" filePattern="${LOG_HOME}/${PROJECT}/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log.gz">
<Filters>
<ThresholdFilter level="error" onMatch="deny" onMismatch="neutral" />
<ThresholdFilter level="warn" onMatch="accept" onMismatch="deny" />
</Filters>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n" />
<Policies>
<TimeBasedTriggeringPolicy modulate="true" interval="1" />
<SizeBasedTriggeringPolicy size="20 MB" />
</Policies>
<DefaultRolloverStrategy max="20">
<Delete basePath="${LOG_HOME}/${PROJECT}/" maxDepth="2">
<IfFileName glob="*/warn-*.log.gz" />
<IfLastModified age="60d" />
</Delete>
</DefaultRolloverStrategy>
</RollingRandomAccessFile>
<RollingRandomAccessFile name="RollingFileError" fileName="${LOG_HOME}/${PROJECT}/error.log" filePattern="${LOG_HOME}/${PROJECT}/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log.gz">
<ThresholdFilter level="error" onMatch="accept" onMismatch="deny" />
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n" />
<Policies>
<TimeBasedTriggeringPolicy modulate="true" interval="1" />
<SizeBasedTriggeringPolicy size="20 MB" />
</Policies>
<DefaultRolloverStrategy max="20">
<Delete basePath="${LOG_HOME}/${PROJECT}/" maxDepth="2">
<IfFileName glob="*/error-*.log.gz" />
<IfLastModified age="60d" />
</Delete>
</DefaultRolloverStrategy>
</RollingRandomAccessFile>
</appenders>
<!-- 接收appender -->
<loggers>
<!-- Spring -->
<logger name="org.springframework" level="INFO" />
<!-- root logger,一般用于放置所有的appender -->
<root level="INFO">
<appender-ref ref="Console" />
<appender-ref ref="RollingFileInfo" />
<appender-ref ref="RollingFileWarn" />
<appender-ref ref="RollingFileError" />
</root>
</loggers>
</configuration>
有任何问题和建议,都可以向我提问讨论,大家一起进步,谢谢!
-over-