JSP老旧项目迁移过来的代码,生成海报,会读取图片,读取字体文件,绘制图片,会生成大量临时文件,内存泄漏。
方案一,服务器定时删除temp临时文件夹
方案二,图片、字体改用静态类读取文件,并且释放相关资源文件。
导致原因
java
package com.huida.train.utils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
@Component
public class ResourceUtil {
// 使用volatile保证多线程环境下的可见性,防止指令重排
private static volatile BufferedImage activityShareBannerImage;
private static volatile Font sourceHanSansFont;
private static volatile BufferedImage backgroundImage;
private static volatile Font rdFont;
/**
* 方正小标宋字体
*/
private static volatile Font fzxbsjwFont;
/**
* 方正黑体
*/
private static volatile Font htFont;
/**
* 仿宋
*/
private static volatile Font fsFont;
private static volatile BufferedImage bottomTextImg;
private ResourceUtil() {
// 私有构造函数,防止外部实例化
}
public static BufferedImage getBottomTextImg() {
if (bottomTextImg == null) {
synchronized (ResourceUtil.class) {
if (bottomTextImg == null) {
try {
ClassPathResource resource = new ClassPathResource("static/qr/bottomText.png");
bottomTextImg = ImageIO.read(resource.getInputStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
return bottomTextImg;
}
public static Font getFsFont() {
if (fsFont == null) {
synchronized (ResourceUtil.class) {
if (fsFont == null) {
try {
ClassPathResource fsFontResource = new ClassPathResource("static/font/fs_gbk.TTF");
fsFont = Font.createFont(Font.TRUETYPE_FONT, fsFontResource.getInputStream());
} catch (IOException | FontFormatException e) {
throw new RuntimeException(e);
}
}
}
}
return fsFont;
}
public static Font getHtFont() {
if (htFont == null) {
synchronized (ResourceUtil.class) {
if (htFont == null) {
try {
ClassPathResource fsFontResource = new ClassPathResource("static/font/ht.TTF");
htFont = Font.createFont(Font.TRUETYPE_FONT, fsFontResource.getInputStream());
} catch (IOException | FontFormatException e) {
throw new RuntimeException(e);
}
}
}
}
return htFont;
}
public static Font getFzxbsjwFont() {
if (fzxbsjwFont == null) {
synchronized (ResourceUtil.class) {
if (fzxbsjwFont == null) {
try {
ClassPathResource fsFontResource = new ClassPathResource("static/font/FZXBSJW.TTF");
fzxbsjwFont = Font.createFont(Font.TRUETYPE_FONT, fsFontResource.getInputStream());
} catch (IOException | FontFormatException e) {
throw new RuntimeException(e);
}
}
}
}
return fzxbsjwFont;
}
public static Font getSimsunFont() {
if (rdFont == null) {
synchronized (ResourceUtil.class) {
if (rdFont == null) {
try {
ClassPathResource fsFontResource = new ClassPathResource("static/font/simsun.ttf");
rdFont = Font.createFont(Font.TRUETYPE_FONT, fsFontResource.getInputStream());
} catch (IOException | FontFormatException e) {
throw new RuntimeException(e);
}
}
}
}
return rdFont;
}
public static BufferedImage getBackgroundImage() {
if (backgroundImage == null) {
synchronized (ResourceUtil.class) {
if (backgroundImage == null) {
try {
ClassPathResource resource = new ClassPathResource("static/qr/backgroundImage.png");
backgroundImage = ImageIO.read(resource.getInputStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
return backgroundImage;
}
public static BufferedImage getActivityShareBannerImage() {
if (activityShareBannerImage == null) {
synchronized (ResourceUtil.class) {
if (activityShareBannerImage == null) {
try {
ClassPathResource resource = new ClassPathResource("static/qr/activity_share_banner.png");
activityShareBannerImage = ImageIO.read(resource.getInputStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
return activityShareBannerImage;
}
public static Font getSourceHanSansFont() {
if (sourceHanSansFont == null) {
synchronized (ResourceUtil.class) {
if (sourceHanSansFont == null) {
try {
ClassPathResource fsFontResource = new ClassPathResource("static/font/SourceHanSans-Regular.otf");
sourceHanSansFont = Font.createFont(Font.TRUETYPE_FONT, fsFontResource.getInputStream());
} catch (IOException | FontFormatException e) {
throw new RuntimeException(e);
}
}
}
}
return sourceHanSansFont;
}
}
java
@Override
public String getStrainingShareCode2(Map<String, String> map) throws IOException, FontFormatException {
String trainingCourseId = map.get("trainingCourseId");
TrainingCourse trainingCoursePo = trainingCourseMapper.select(trainingCourseId);
if (trainingCoursePo == null) {
throw new TipUserException("活动-培训已被删除或不可见");
}
BufferedImage activityShareBannerImage = ResourceUtil.getActivityShareBannerImage();
// 开启画图
Graphics2D graphics = activityShareBannerImage.createGraphics();
//字体样式
Font font = ResourceUtil.getSourceHanSansFont().deriveFont(Font.BOLD, 27);
//字体颜色
float[] color = Color.RGBtoHSB(58, 58, 58, null);
graphics.setColor(Color.getHSBColor(color[0], color[1], color[2]));
graphics.setFont(font);
String address = "";
//地点
if (trainingCoursePo.getAddress().length() >= 16) {
address = trainingCoursePo.getAddress().subSequence(0, 14) + "...";
} else {
address = trainingCoursePo.getAddress();
}
drawWrapString(graphics, address, 50, 220, activityShareBannerImage.getWidth() - 100, null, null);
//时间
drawWrapString(graphics, DateUtils.dateTime(trainingCoursePo.getStartTime()) + " ~ " + DateUtils.dateTime(trainingCoursePo.getEndTime()), 50, 275, activityShareBannerImage.getWidth() - 100, null, null);
//报名人数
Long enrollNum = trainingCoursePo.getEnrollNum();
if (ObjectUtils.isNull(enrollNum)) {
enrollNum = 0L;
}
drawWrapString(graphics, enrollNum.toString() + "人报名", 50, 330, activityShareBannerImage.getWidth() - 100, null, null);
// String base64 = ImgUtil.toBase64DataUri(activityShareBannerImage, "png");
// return base64;
// 指定文件路径
String filePath = HuiDaConfig.getTrainUploadPath() + "/shareCode/" + trainingCoursePo.getRecordId() + "/" + trainingCoursePo.getRecordId() + "_" + enrollNum + ".png";
File outputfile = new File(filePath);
if (!outputfile.exists()) {
String deleteFilePath = HuiDaConfig.getTrainUploadPath() + "/shareCode/" + trainingCoursePo.getRecordId();
File deleteFileFile = new File(deleteFilePath);
FileUtils.deleteDirectory(deleteFileFile);
File parentDir = outputfile.getParentFile();
if (!parentDir.exists()) {
parentDir.mkdirs();
}
ImageIO.write(activityShareBannerImage, "png", outputfile);
}
activityShareBannerImage.flush();
graphics.dispose();
return filePath;
}