JSP老旧项目迁移过来的代码,生成海报,会读取图片,读取字体文件,绘制图片,会生成大量临时文件,内存泄漏。
方案一,服务器定时删除temp临时文件夹
方案二,图片、字体改用静态类读取文件,并且释放相关资源文件。
导致原因
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;}
}
@Overridepublic 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;}