开发需求:
java语言与数据源结合,生成可视化图片,结合echarts 框架 将生成的图片写入到word 文档中,不采用前台生成等操作。
难点:
后台如何生成图片,这是这个需求的难点,通过调研,有许多技术,比如Graphics2D、jfreechart、PhantomJS等等,Graphics2D 生成一些简单的图片比如二维码,海报等等,jfreechart 生成图片比较硬,需要各种调试,当然也可以生成好看的图片,对于懒的我来说,已经不在考虑了。最后决定使用PhantomJS技术来解决这个需求。
开发过程:
实现这个技术,需要对这个技术有个初步的了解,在网上各种搜索,其实最后明白就是搭建个服务,我们后台直接请求这个服务生成图片,返回给我们, PhantomJS是一个无界面的,可脚本编程的WebKit浏览器引擎,供我们请求进行各种操作。
安装环境:
下载对应系统地址: http://phantomjs.org/download 一. window系统:
1.配置环境变量:
系统 – 高级系统设置 – 环境变量 --系统变量 设置PATH
2.进入我们的cmd 窗口,phantomjs 即可看到效果。
3.使用一下它们提供的例子:
phantomjs e:\phantomjs-2.1.1-windows\examples\hello.js
Hello,world!
4.说明安装成功。
二. linux 系统:
1.解压压缩包:
tar xjf phantomjs-2.1.1-linux-x86_64.tar.bz2
2.设置环境变量,并使得配置文件生效:
export PATH=${PATH}:/opt/phantomjs/bin
source /etc/profile
3.phantomjs 即可看到生效
注意:phantomjs: error while loading shared libraries: libfontconfig.so.1: cannot open shared object file: No such file or directory
解决办法:
yum install fontconfig freetype2 (yum安装)
3.使用一下它们提供的例子:
phantomjs opt\phantomjs\examples\hello.js
Hello,world!
4.说明安装成功!
实现需求:
java通过连接 phantomjs 来实现后端生成echarts .生成效果如下:
首先 后端封装参数,生成option 通过http 请求得到对应的 图片 base64;
主要代码:
option.ftl:
{
xAxis: {
type: 'value',
show: false
},
yAxis: {
type: 'category',
data: ${categories},
splitLine:{
show: false
},
axisLine: {
show: false
},
axisTick:{
show: false
},
axisLabel:{
fontSize: 14,
fontFamily:'黑体'
}
},
grid:{
left: '110px',
top: '0px',
right: '60px',
bottom: '12px'
},
color: ${colorValue},
series: [{
data: ${values},
type: 'bar',
barWidth: '20px',
label: {
show: true,
position: 'right',
formatter: '{b}',
color: '#000',
fontFamily:'黑体'
}
}]
}
EchartsUtils工具类:
public class EchartsUtil {
private static Properties configProperties;
private static String url;
private static final String SUCCESS_CODE = "1";
/**
*
* @param option
* @param width
* @param height
* @return
* @throws ClientProtocolException
* @throws IOException
*/
public static String generateEchartsBase64(String option,String width,String height) throws ClientProtocolException, IOException {
if(StringUtils.isBlank(url)){
configProperties = SpringContextHolder.getBean("configProperties");
url = MapUtils.getString(configProperties, "phantomjs.url");
}
String base64 = "";
if (option == null) {
return base64;
}
option = option.replaceAll("\\s+", "").replaceAll("\"", "'");
// 将option字符串作为参数发送给echartsConvert服务器
Map<String, String> params = new HashMap();
params.put("opt", option);
params.put("width",width);
params.put("height",height);
String response = httpRequestUtils.post(url, params, "utf-8");
// 解析echartsConvert响应
JSONObject responseJson = JSON.parseObject(response);
String code = responseJson.getString("code");
// 如果echartsConvert正常返回
if (SUCCESS_CODE.equals(code)) {
base64 = responseJson.getString("data");
}
// 未正常返回
else {
String string = responseJson.getString("msg");
throw new RuntimeException(string);
}
return base64;
}
}
FreemarkerUtil 工具类:
public class FreemarkerUtil {
public static String generateString(HttpServletRequest httpRequest, String templateFileName, String templateDirectory, Map<String, Object> datas)
throws IOException, TemplateException {
Configuration configuration = new Configuration();
configuration.setDefaultEncoding("UTF-8");
// 设置模板所在文件夹
String separator = File.separator;
//如何区分是window 还是 liunx 系统
String filedownload = "";
if ("\\".equals(separator)) {
System.out.println("windows下");
filedownload = httpRequest.getSession().getServletContext().getRealPath("/WEB-INF/resources/file") + "/";
filedownload = filedownload.replace("/", "\\");
}
// liunx 下
if ("/".equals(separator)) {
System.out.println("linux下");
filedownload = httpRequest.getSession().getServletContext().getRealPath("/WEB-INF/resources/file") + "/" ;
filedownload = filedownload.replace("\\", "/");
}
configuration.setDirectoryForTemplateLoading(new File(filedownload));
// 生成模板对象
Template template = configuration.getTemplate(templateFileName);
// 将datas写入模板并返回
try (StringWriter stringWriter = new StringWriter()) {
template.process(datas, stringWriter);
stringWriter.flush();
return stringWriter.getBuffer().toString();
}
}
测试代码块:
public void getphantomjs(){
// 变量
String[] categories = new String[] { "苹果", "香蕉", "西瓜" };
String[] color= new String[] {"#008000"};
Map <String,Object> dataMap=new HashMap<>();
List dataList = new ArrayList<>();
dataMap.put("name","B");
dataMap.put("value",40);
dataList.add(dataMap);
dataMap=new HashMap<>();
dataMap.put("name","AA");
dataMap.put("value",60);
dataList.add(dataMap);
dataMap=new HashMap<>();
dataMap.put("name","AAA");
dataMap.put("value",100);
dataList.add(dataMap);
Object[] values = dataList.toArray();
HashMap<String, Object> datas = new HashMap<>();
//对应option.ftl 变量
datas.put("categories", JSON.toJSONString(categories));
datas.put("values", JSON.toJSONString(values));
datas.put("colorValue",JSON.toJSONString(color));
String option = null;
try {
option = FreemarkerUtil.generateString(getHttpRequest(),"option.ftl", "", datas);
String base64 = EchartsUtil.generateEchartsBase64(option,"555","96");
generateImage(base64, "D:\\test.png");
} catch (IOException e) {
e.printStackTrace();
} catch (TemplateException e) {
e.printStackTrace();
}
}
public static void generateImage(String base64, String path) throws IOException {
BASE64Decoder decoder = new BASE64Decoder();
try (OutputStream out = new FileOutputStream(path)){
// 解密
byte[] b = decoder.decodeBuffer(base64);
for (int i = 0; i < b.length; ++i) {
if (b[i] < 0) {
b[i] += 256;
}
}
out.write(b);
out.flush();
}
}
``
2019/04/28 新增
遗留2个问题:
1. 关于启动 phantomjs
2. linux 字体安装 生成与window一样的图片
第一个问题:
打开js 查看
其目的就是启动时加载这个 别人封装好的js插件,传入参数生成想要的结果。
(默认端口号9090)
window 启动:
phantomjs C:\Users\LENOVO\Desktop\安装phantomjs\echartsconvert\echarts-convert.js -s
linux 后台启动:
nohup phantomjs /opt/phantomjs/echartsconvert/echarts-convert.js -s &
附件echarts-convert.js 下载路径:
第二个问题:
Linux系统安装windos字体步骤如下:
1、复制字体
在“C:\Windows\Fonts”目录下找到所要安装字体,这里以“SIMHEI.TTF”为例。
2、上传字体至CentOS系统
在/usr/share/fonts目录下建立一个子目录,比如/HEITIFONTS. 上传“SIMHEI.TTF”字体至此目录。
3、进入此目录安装
cd /usr/share/fonts/HEITIFONTS
运行以下命令建立字体索引信息,更新字体缓存:
sudo mkfontscale
sudo mkfontdir
sudo fc-cache -fv
执行以下命令让字体生效
source /etc/profile
安装可能遇到的问题与解决办法
1.权限问题:
cd /usr/share/fonts/HEITIFONTS
chmod 755 *.ttf
2.提示 “ mkfontscale: command not found”,用yum安装: yum install mkfontscale
提示 “ fc-cache: command not found” yum install fontconfig
若需要重启服务器: reboot
查看已安装的字体: fc-list
总结:
在开发过程中,还需要进一步更改,封装等等操作,如有疑问,请留言。。。