解决Activiti在linux环境下中文不显示问题

Activiti提供DefaultProcessDiagramGenerator用于生成流程InputStream流,可用于生成图片,并且可高亮某些节点、连线等,使用方法如下:

String processDefinitionId = "xxx";
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
ProcessDiagramGenerator pdg = new DefaultProcessDiagramGenerator();
InputStream inputStream = pdg.generateDiagram(bpmnModel, "png", 
					highLightedActivitiesList,highLightedFlowsList,
					processEngine.getProcessEngineConfiguration().getActivityFontName(),
					processEngine.getProcessEngineConfiguration().getLabelFontName(), 
					processEngine.getProcessEngineConfiguration().getAnnotationFontName(),
					null, 1);

"generateDiagram"方法的具体参数可参考API。

其中有三个字体名称ActivityFontNameLabelFontNameAnnotationFontName可在XML配置文件中进行声明,当前项目使用微软雅黑

问题:

在window环境下生成的图片可正常显示,但是部署到linux环境下中文字体无法显示。

原因:

该问题是由于linux环境下没有中文字体文件。

解决方案:

1.在linux环境下安装需要的字体文件,具体步骤网上可查询。
2.将字体文件放入项目中,在生成流程图的时候进行加载,从而实现不依赖服务器系统字体。

--------------------本文主要介绍如何实现解决方案2。----------------------------

查看DefaultProcessDiagramGenerator.generateDiagram()方法源码可以看到生成图片主要涉及的类和方法如下:

方法说明
DefaultProcessDiagramGeneratorgenerateProcessDiagram()
DefaultProcessDiagramGeneratorinitProcessDiagramCanvas()计算X、Y等变量,并调用canvas
DefaultProcessDiagramCanvasinitialize()字体创建的核心

根据上述表格得知,如果需要加载项目中的字体文件,则需要重写DefaultProcessDiagramCanvas类的核心方法initialize

  1. 创建自定义Canvas类CustomizedProcessDiagramCanvas继承DefaultProcessDiagramCanvas并重写initialize方法,如下:
package com.fangjie.activiti.config;

import org.activiti.image.impl.DefaultProcessDiagramCanvas;
import org.activiti.image.util.ReflectUtil;
import org.springframework.util.StringUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;

/**
 * @author fangjie
 * @Description: ${todo}
 */
public class CustomizedProcessDiagramCanvas extends DefaultProcessDiagramCanvas {

    public CustomizedProcessDiagramCanvas(int width, int height, int minX, int minY, String imageType, String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) {
        super(width, height, minX, minY, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader);
    }

    public CustomizedProcessDiagramCanvas(int width, int height, int minX, int minY, String imageType) {
        super(width, height, minX, minY, imageType);
    }

    @Override
    public void initialize(String imageType) {
        if ("png".equalsIgnoreCase(imageType)) {
            this.processDiagram = new BufferedImage(canvasWidth, canvasHeight, BufferedImage.TYPE_INT_ARGB);
        } else {
            this.processDiagram = new BufferedImage(canvasWidth, canvasHeight, BufferedImage.TYPE_INT_RGB);
        }

        this.g = processDiagram.createGraphics();
        if ("png".equalsIgnoreCase(imageType) == false) {
            this.g.setBackground(new Color(255, 255, 255, 0));
            this.g.clearRect(0, 0, canvasWidth, canvasHeight);
        }

        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setPaint(Color.black);
        //activityFontName字体加载
        Font font = this.loadFontFromResources(this.activityFontName, Font.BOLD, FONT_SIZE);
        g.setFont(font);
        this.fontMetrics = g.getFontMetrics();
        //labelFontName字体加载
        LABEL_FONT = this.loadFontFromResources(this.labelFontName, Font.ITALIC, 10);
        //annotationFontName字体加载
        ANNOTATION_FONT = this.loadFontFromResources(this.annotationFontName, Font.PLAIN, FONT_SIZE);

        try {
            USERTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/userTask.png", customClassLoader));
            SCRIPTTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/scriptTask.png", customClassLoader));
            SERVICETASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/serviceTask.png", customClassLoader));
            RECEIVETASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/receiveTask.png", customClassLoader));
            SENDTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/sendTask.png", customClassLoader));
            MANUALTASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/manualTask.png", customClassLoader));
            BUSINESS_RULE_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/businessRuleTask.png", customClassLoader));
            SHELL_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/shellTask.png", customClassLoader));
            CAMEL_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/camelTask.png", customClassLoader));
            MULE_TASK_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/muleTask.png", customClassLoader));

            TIMER_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/timer.png", customClassLoader));
            COMPENSATE_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/compensate-throw.png", customClassLoader));
            COMPENSATE_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/compensate.png", customClassLoader));
            ERROR_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/error-throw.png", customClassLoader));
            ERROR_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/error.png", customClassLoader));
            MESSAGE_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/message-throw.png", customClassLoader));
            MESSAGE_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/message.png", customClassLoader));
            SIGNAL_THROW_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/signal-throw.png", customClassLoader));
            SIGNAL_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResource("org/activiti/icons/signal.png", customClassLoader));
        } catch (IOException e) {
            LOGGER.warn("Could not load image for process diagram creation: {}", e.getMessage());
        }
    }

    /**
     * 根据名称从resources中加载字体
     *
     * @param fontName
     * @param fontStyle
     * @param fontSize
     * @return
     */
    public Font loadFontFromResources(String fontName, int fontStyle, float fontSize) {
        Font font = null;
        if (StringUtils.isEmpty(fontName)) {
            return font;
        }
        try {
            //加载resources下的字体文件,文件命名与设置的字体名称一一对应
            InputStream fontInputStream = this.getClass().getResourceAsStream("/fonts/" + fontName + ".ttc");
            //未找到项目中相应的字体文件,则使用系统的字体
            if (fontInputStream == null) {
                return new Font(fontName, fontStyle, (int) fontSize);
            }
            font = Font.createFont(Font.TRUETYPE_FONT, fontInputStream);
            //设置字体类型
            if (fontStyle > -1) {
                font = font.deriveFont(fontStyle);
            }
            //设置字体大小
            if (fontSize > -1) {
                font = font.deriveFont(fontSize);
            }
        } catch (FontFormatException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return font;
    }
}

2.创建自定义Generator类CustomizedProcessDiagramGenerator继承DefaultProcessDiagramGenerator并重写相关方法,如下:

package com.fangjie.activiti.config;

import org.activiti.bpmn.model.*;
import org.activiti.bpmn.model.Process;
import org.activiti.image.impl.DefaultProcessDiagramCanvas;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;

import java.util.List;

/**
 * @author fangjie
 * @Description: ${todo}
 */
public class CustomizedProcessDiagramGenerator extends DefaultProcessDiagramGenerator {


    @Override
    protected DefaultProcessDiagramCanvas generateProcessDiagram(BpmnModel bpmnModel, String imageType, List<String> highLightedActivities, List<String> highLightedFlows, String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader, double scaleFactor) {

        prepareBpmnModel(bpmnModel);

        DefaultProcessDiagramCanvas processDiagramCanvas = initProcessDiagramCanvas(bpmnModel, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader);
        /**
         * 此处省略源码剩余部分代码
         */
    }

    protected static DefaultProcessDiagramCanvas initProcessDiagramCanvas(BpmnModel bpmnModel, String imageType, String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) {
        /**
         * 此处省略源码前部分代码
         */

        //返回上面自定义的canvas类
        return new CustomizedProcessDiagramCanvas((int) maxX + 10, (int) maxY + 10, (int) minX, (int) minY,
                imageType, activityFontName, labelFontName, annotationFontName, customClassLoader);
    }
}

3.将文章开头部分代码进行修改如下:

String processDefinitionId = "xxx";
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
//创建自定义的Generator类
ProcessDiagramGenerator pdg = new CustomizedProcessDiagramGenerator();
InputStream inputStream = pdg.generateDiagram(bpmnModel, "png", 
					highLightedActivitiesList,highLightedFlowsList,
					processEngine.getProcessEngineConfiguration().getActivityFontName(),
					processEngine.getProcessEngineConfiguration().getLabelFontName(), 
					processEngine.getProcessEngineConfiguration().getAnnotationFontName(),
					null, 1);

转载于:https://my.oschina.net/u/1161660/blog/3010360

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值