first
This commit is contained in:
17
springboot-echarts/.gitignore
vendored
Normal file
17
springboot-echarts/.gitignore
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
# 此为注释– 将被Git 忽略
|
||||
# /结尾表示是目录,忽略目录和目录下的所有件
|
||||
# /开头表示根目录,否则是.gitignore的相对目录
|
||||
# !开头表示反选
|
||||
.idea/
|
||||
target/
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
*.log
|
||||
.svn/
|
||||
.project
|
||||
rebel.xml
|
||||
.rebel-remote.xml.*
|
||||
swagger.json
|
||||
swagger.adoc
|
||||
|
||||
20
springboot-echarts/LICENSE
Normal file
20
springboot-echarts/LICENSE
Normal file
@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018 Xiong Neng
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
32
springboot-echarts/README.md
Normal file
32
springboot-echarts/README.md
Normal file
@ -0,0 +1,32 @@
|
||||
## Echarts + WebSocket实现图片生成
|
||||
|
||||
大致的过程是这样
|
||||
|
||||
对于每一种图表类型,开放一个数据请求接口,通过POST请求接受图表数据,然后push到客户端去,
|
||||
客户端接受到请求后渲染echarts图表,并且会将BASE64格式图片数据再次提交给另外一个图片保存接口进行实际的保存。
|
||||
|
||||
对于需要生成图片形式的客户端,先打开一个浏览器连上服务器,另外写一个HTTPClient程序通过POST调用图片保存接口即可。
|
||||
|
||||
## 使用案例
|
||||
|
||||
使用JMH做微基准测试的时候,通常需要可视化显示测试结果,这时候可将文本形式的测试结果上传,自动生成非常漂亮的性能测试报告图表。
|
||||
|
||||
其他想要可视化数据保存图片的场景,都可以这样实现。
|
||||
|
||||
## 改进方案
|
||||
|
||||
通过配合PhantomJS来实现无浏览器的自动图片生成。
|
||||
|
||||
经过测试PhantomJS打开页面后可以连上socket服务器,但是10秒后自动关闭了。
|
||||
|
||||
尝试采用页面js轮询方式,1秒轮询一次,有数据的时候就导出图片。
|
||||
|
||||
结果导出图片太大了,不知道怎么回事,另外轮询方案始终不是很好。
|
||||
|
||||
最后还是老老实实使用websocket方案,自己手动打开这个网页吧。<http://localhost:9075/>
|
||||
|
||||
## 许可证
|
||||
|
||||
Copyright (c) 2018 Xiong Neng
|
||||
|
||||
基于 MIT 协议发布: <http://www.opensource.org/licenses/MIT>
|
||||
218
springboot-echarts/pom.xml
Normal file
218
springboot-echarts/pom.xml
Normal file
@ -0,0 +1,218 @@
|
||||
<?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.enzhico</groupId>
|
||||
<artifactId>springboot-echarts</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>springboot-echarts</name>
|
||||
<description>通过接口实现Echarts图片保存</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>1.5.9.RELEASE</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<netty.version>4.1.19.Final</netty.version>
|
||||
<thymeleaf.version>3.0.7.RELEASE</thymeleaf.version>
|
||||
<thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version>
|
||||
<jmh.version>1.20</jmh.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jetty</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>1.11</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-all</artifactId>
|
||||
<version>1.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- netty-socketio-->
|
||||
<dependency>
|
||||
<groupId>com.corundumstudio.socketio</groupId>
|
||||
<artifactId>netty-socketio</artifactId>
|
||||
<version>1.7.13</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-buffer</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-codec</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-codec-http</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-common</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-handler</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-resolver</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-transport</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-transport-native-epoll</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-transport-native-unix-common</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.socket</groupId>
|
||||
<artifactId>socket.io-client</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JMH-->
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-core</artifactId>
|
||||
<version>${jmh.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-generator-annprocess</artifactId>
|
||||
<version>${jmh.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Json libs-->
|
||||
<dependency>
|
||||
<groupId>net.sf.json-lib</groupId>
|
||||
<artifactId>json-lib</artifactId>
|
||||
<version>2.4</version>
|
||||
<classifier>jdk15</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.46</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.9.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<version>2.9.4</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.6.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.20</version>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/java</directory>
|
||||
<includes>
|
||||
<include>**/*.xml</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
72
springboot-echarts/run.sh
Normal file
72
springboot-echarts/run.sh
Normal file
@ -0,0 +1,72 @@
|
||||
#!/bin/bash
|
||||
# 项目自动更新脚本
|
||||
# 先clone相应的分支下来:
|
||||
# git clone ssh://git@120.24.173.142:7999/xxx.git
|
||||
# 远程调试启动:
|
||||
# nohup java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -Xms512m -Xmx1024m -jar -Dspring.profiles.active=${profile} ${jarfile} >/dev/null 2>&1 &
|
||||
|
||||
function start {
|
||||
profile="$1"
|
||||
echo "启动环境profile=${profile}"
|
||||
jarfile=$(ls target/*.jar)
|
||||
if [[ "$?" == "0" ]]; then
|
||||
stop $profile $jarfile
|
||||
fi
|
||||
branch=$(git branch |awk '{print $2}')
|
||||
git pull origin ${branch}
|
||||
echo "更新完代码开始重新打包"
|
||||
mvn clean && mvn clean && mvn package -DskipTests=true
|
||||
if [[ "$?" != "0" ]]; then
|
||||
echo "编译出错,退出!"
|
||||
exit 1
|
||||
fi
|
||||
echo "nohup java -Xms512m -Xmx1024m -jar -Dspring.profiles.active=${profile} ${jarfile} >/dev/null 2>&1 &"
|
||||
nohup java -Xms512m -Xmx1024m -jar -Dspring.profiles.active=${profile} ${jarfile} >/dev/null 2>&1 &
|
||||
echo "启动应用中,请查看日志文件..."
|
||||
}
|
||||
|
||||
function stop {
|
||||
profile="$1"
|
||||
jarfile="$2"
|
||||
ps aux | grep "${jarfile}" | grep "spring.profiles.active=${profile}" | grep -v grep > /dev/null
|
||||
if [[ "$?" == "0" ]]; then
|
||||
echo "该应用还在跑,我先停了它"
|
||||
pid=$(ps aux | grep "${jarfile}" | grep "spring.profiles.active=${profile}" | grep -v grep |awk '{print $2}')
|
||||
if [[ "$pid" != "" ]]; then
|
||||
kill -9 $pid
|
||||
fi
|
||||
echo "停止应用成功..."
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ "$1" == "start" ]]; then
|
||||
if [[ "$#" < 2 ]]; then
|
||||
echo "请输入正确参数:./epay.sh start {profile}"
|
||||
exit 1
|
||||
fi
|
||||
profile="$2"
|
||||
if [[ "$profile" != "dev" && "$profile" != "test" && "$profile" != "show" && "$profile" != "production" ]]; then
|
||||
echo "参数错误,请输入正确的profile参数,使用方法:"
|
||||
echo "./epay.sh start {profile} ==> 启动应用,{profile}取值:dev|test|show|production"
|
||||
exit 1
|
||||
fi
|
||||
start "${profile}"
|
||||
elif [[ "$1" == "stop" ]]; then
|
||||
if [[ "$#" < 2 ]]; then
|
||||
echo "请输入正确参数:./epay.sh stop {profile}"
|
||||
exit 1
|
||||
fi
|
||||
profile="$2"
|
||||
if [[ "$profile" != "dev" && "$profile" != "test" && "$profile" != "show" && "$profile" != "production" ]]; then
|
||||
echo "参数错误,请输入正确的profile参数,使用方法:"
|
||||
echo "./epay.sh stop {profile} ==> 停止应用,{profile}取值:dev|test|show|production"
|
||||
exit 1
|
||||
fi
|
||||
jarfile=$(ls target/*.jar)
|
||||
stop $profile $jarfile
|
||||
else
|
||||
echo "参数错误,使用方法:{}参数是必填的,[]参数可选"
|
||||
echo "./epay.sh start {profile} ==> 启动应用,{profile}取值:dev|test|show|production"
|
||||
echo "./epay.sh stop {profile} ==> 停止应用,{profile}取值:dev|test|show|production"
|
||||
exit 1
|
||||
fi
|
||||
@ -0,0 +1,57 @@
|
||||
package com.enzhico.benchmark.common;
|
||||
|
||||
import org.openjdk.jmh.infra.BenchmarkParams;
|
||||
import org.openjdk.jmh.results.BenchmarkResult;
|
||||
import org.openjdk.jmh.results.Result;
|
||||
import org.openjdk.jmh.results.RunResult;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static com.enzhico.echarts.common.util.ExportPngUtil.generateOption;
|
||||
import static com.enzhico.echarts.common.util.ExportPngUtil.postOption;
|
||||
|
||||
/**
|
||||
* 将基准测试结果导出图片
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/24
|
||||
*/
|
||||
public class ResultExporter {
|
||||
|
||||
public static void exportResult(String titleStr, Collection<RunResult> results,
|
||||
String paramKey, String xunit) throws Exception {
|
||||
// 几个测试对象
|
||||
List<String> objects = new ArrayList<>();
|
||||
// 测试维度,输入值n
|
||||
List<String> dimensions = new ArrayList<>();
|
||||
// 有几个测试对象,就有几组测试数据,每组测试数据中对应几个维度的结果
|
||||
List<List<Double>> allData = new ArrayList<>();
|
||||
List<Double> temp = new ArrayList<>();
|
||||
for (RunResult runResult : results) {
|
||||
BenchmarkResult benchmarkResult = runResult.getAggregatedResult();
|
||||
Result r = benchmarkResult.getPrimaryResult();
|
||||
BenchmarkParams params = runResult.getParams();
|
||||
if (!objects.contains(r.getLabel())) {
|
||||
objects.add(r.getLabel());
|
||||
if (!temp.isEmpty()) {
|
||||
allData.add(temp);
|
||||
temp = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
temp.add(Double.parseDouble(String.format("%.2f", r.getScore())));
|
||||
// 测试维度
|
||||
if (!dimensions.contains("n=" + params.getParam(paramKey))) {
|
||||
dimensions.add("n=" + params.getParam(paramKey));
|
||||
}
|
||||
}
|
||||
// 最后一组测试数据别忘记加进去了
|
||||
allData.add(temp);
|
||||
|
||||
String optionStr = generateOption(titleStr, objects, dimensions, allData, xunit);
|
||||
// POST到接口上
|
||||
postOption(optionStr, "http://localhost:9075/api/v1/data");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.enzhico.benchmark.first;
|
||||
|
||||
import org.openjdk.jmh.annotations.*;
|
||||
import org.openjdk.jmh.runner.Runner;
|
||||
import org.openjdk.jmh.runner.RunnerException;
|
||||
import org.openjdk.jmh.runner.options.Options;
|
||||
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
/**
|
||||
* FirstBenchmark
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/24
|
||||
*/
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@OutputTimeUnit(TimeUnit.MICROSECONDS)
|
||||
@State(Scope.Thread)
|
||||
public class FirstBenchmark {
|
||||
|
||||
@Benchmark
|
||||
public int sleepAWhile() {
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
// ignore
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws RunnerException {
|
||||
Options opt = new OptionsBuilder()
|
||||
.include(FirstBenchmark.class.getSimpleName())
|
||||
.forks(1)
|
||||
.warmupIterations(5)
|
||||
.measurementIterations(5)
|
||||
.build();
|
||||
new Runner(opt).run();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,84 @@
|
||||
package com.enzhico.benchmark.json;
|
||||
|
||||
import com.enzhico.benchmark.common.ResultExporter;
|
||||
import com.enzhico.benchmark.json.model.FullName;
|
||||
import com.enzhico.benchmark.json.model.Person;
|
||||
import com.enzhico.benchmark.json.util.FastJsonUtil;
|
||||
import com.enzhico.benchmark.json.util.GsonUtil;
|
||||
import com.enzhico.benchmark.json.util.JacksonUtil;
|
||||
import com.enzhico.benchmark.json.util.JsonLibUtil;
|
||||
import org.openjdk.jmh.annotations.*;
|
||||
import org.openjdk.jmh.results.RunResult;
|
||||
import org.openjdk.jmh.runner.Runner;
|
||||
import org.openjdk.jmh.runner.options.Options;
|
||||
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Json反序列化基准测试
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/24
|
||||
*/
|
||||
@BenchmarkMode(Mode.SingleShotTime)
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
@State(Scope.Benchmark)
|
||||
public class JsonDeserializeBenchmark {
|
||||
/**
|
||||
* 反序列化次数参数
|
||||
*/
|
||||
@Param({"1000", "10000", "100000"})
|
||||
private int count;
|
||||
|
||||
private String jsonStr;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Options opt = new OptionsBuilder()
|
||||
.include(JsonDeserializeBenchmark.class.getSimpleName())
|
||||
.forks(1)
|
||||
.warmupIterations(0)
|
||||
.build();
|
||||
Collection<RunResult> results = new Runner(opt).run();
|
||||
ResultExporter.exportResult("JSON反序列化性能", results, "count", "秒");
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void JsonLib() {
|
||||
for (int i = 0; i < count; i++) {
|
||||
JsonLibUtil.json2Bean(jsonStr, Person.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void Gson() {
|
||||
for (int i = 0; i < count; i++) {
|
||||
GsonUtil.json2Bean(jsonStr, Person.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void FastJson() {
|
||||
for (int i = 0; i < count; i++) {
|
||||
FastJsonUtil.json2Bean(jsonStr, Person.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void Jackson() {
|
||||
for (int i = 0; i < count; i++) {
|
||||
JacksonUtil.json2Bean(jsonStr, Person.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Setup
|
||||
public void prepare() {
|
||||
jsonStr="{\"name\":\"邵同学\",\"fullName\":{\"firstName\":\"zjj_first\",\"middleName\":\"zjj_middle\",\"lastName\":\"zjj_last\"},\"age\":24,\"birthday\":null,\"hobbies\":[\"篮球\",\"游泳\",\"coding\"],\"clothes\":{\"shoes\":\"安踏\",\"trousers\":\"adidas\",\"coat\":\"Nike\"},\"friends\":[{\"name\":\"小明\",\"fullName\":{\"firstName\":\"xxx_first\",\"middleName\":\"xxx_middle\",\"lastName\":\"xxx_last\"},\"age\":24,\"birthday\":null,\"hobbies\":[\"篮球\",\"游泳\",\"coding\"],\"clothes\":{\"shoes\":\"安踏\",\"trousers\":\"adidas\",\"coat\":\"Nike\"},\"friends\":null},{\"name\":\"Tony\",\"fullName\":{\"firstName\":\"xxx_first\",\"middleName\":\"xxx_middle\",\"lastName\":\"xxx_last\"},\"age\":24,\"birthday\":null,\"hobbies\":[\"篮球\",\"游泳\",\"coding\"],\"clothes\":{\"shoes\":\"安踏\",\"trousers\":\"adidas\",\"coat\":\"Nike\"},\"friends\":null},{\"name\":\"陈小二\",\"fullName\":{\"firstName\":\"xxx_first\",\"middleName\":\"xxx_middle\",\"lastName\":\"xxx_last\"},\"age\":24,\"birthday\":null,\"hobbies\":[\"篮球\",\"游泳\",\"coding\"],\"clothes\":{\"shoes\":\"安踏\",\"trousers\":\"adidas\",\"coat\":\"Nike\"},\"friends\":null}]}";
|
||||
}
|
||||
|
||||
@TearDown
|
||||
public void shutdown() {
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,116 @@
|
||||
package com.enzhico.benchmark.json;
|
||||
|
||||
import com.enzhico.benchmark.common.ResultExporter;
|
||||
import com.enzhico.benchmark.json.model.FullName;
|
||||
import com.enzhico.benchmark.json.model.Person;
|
||||
import com.enzhico.benchmark.json.util.FastJsonUtil;
|
||||
import com.enzhico.benchmark.json.util.GsonUtil;
|
||||
import com.enzhico.benchmark.json.util.JacksonUtil;
|
||||
import com.enzhico.benchmark.json.util.JsonLibUtil;
|
||||
import com.enzhico.benchmark.sum.calc.impl.MultithreadCalculator;
|
||||
import com.enzhico.benchmark.sum.calc.impl.SinglethreadCalculator;
|
||||
import org.openjdk.jmh.annotations.*;
|
||||
import org.openjdk.jmh.infra.BenchmarkParams;
|
||||
import org.openjdk.jmh.results.BenchmarkResult;
|
||||
import org.openjdk.jmh.results.Result;
|
||||
import org.openjdk.jmh.results.RunResult;
|
||||
import org.openjdk.jmh.runner.Runner;
|
||||
import org.openjdk.jmh.runner.options.Options;
|
||||
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static com.enzhico.echarts.common.util.ExportPngUtil.generateOption;
|
||||
import static com.enzhico.echarts.common.util.ExportPngUtil.postOption;
|
||||
|
||||
/**
|
||||
* Json序列化基准测试
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/24
|
||||
*/
|
||||
@BenchmarkMode(Mode.SingleShotTime)
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
@State(Scope.Benchmark)
|
||||
public class JsonSerializeBenchmark {
|
||||
/**
|
||||
* 序列化次数参数
|
||||
*/
|
||||
@Param({"1000", "10000", "100000"})
|
||||
private int count;
|
||||
|
||||
private Person p;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Options opt = new OptionsBuilder()
|
||||
.include(JsonSerializeBenchmark.class.getSimpleName())
|
||||
.forks(1)
|
||||
.warmupIterations(0)
|
||||
.build();
|
||||
Collection<RunResult> results = new Runner(opt).run();
|
||||
ResultExporter.exportResult("JSON序列化性能", results, "count", "秒");
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void JsonLib() {
|
||||
for (int i = 0; i < count; i++) {
|
||||
JsonLibUtil.bean2Json(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void Gson() {
|
||||
for (int i = 0; i < count; i++) {
|
||||
GsonUtil.bean2Json(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void FastJson() {
|
||||
for (int i = 0; i < count; i++) {
|
||||
FastJsonUtil.bean2Json(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void Jackson() {
|
||||
for (int i = 0; i < count; i++) {
|
||||
JacksonUtil.bean2Json(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Setup
|
||||
public void prepare() {
|
||||
List<Person> friends=new ArrayList<Person>();
|
||||
friends.add(createAPerson("小明",null));
|
||||
friends.add(createAPerson("Tony",null));
|
||||
friends.add(createAPerson("陈小二",null));
|
||||
p=createAPerson("邵同学",friends);
|
||||
}
|
||||
|
||||
@TearDown
|
||||
public void shutdown() {
|
||||
}
|
||||
|
||||
private Person createAPerson(String name,List<Person> friends) {
|
||||
Person newPerson=new Person();
|
||||
newPerson.setName(name);
|
||||
newPerson.setFullName(new FullName("zjj_first", "zjj_middle", "zjj_last"));
|
||||
newPerson.setAge(24);
|
||||
List<String> hobbies=new ArrayList<String>();
|
||||
hobbies.add("篮球");
|
||||
hobbies.add("游泳");
|
||||
hobbies.add("coding");
|
||||
newPerson.setHobbies(hobbies);
|
||||
Map<String,String> clothes=new HashMap<String, String>();
|
||||
clothes.put("coat", "Nike");
|
||||
clothes.put("trousers", "adidas");
|
||||
clothes.put("shoes", "安踏");
|
||||
newPerson.setClothes(clothes);
|
||||
newPerson.setFriends(friends);
|
||||
return newPerson;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
package com.enzhico.benchmark.json.model;
|
||||
|
||||
/**
|
||||
* FullName
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/24
|
||||
*/
|
||||
public class FullName {
|
||||
private String firstName;
|
||||
private String middleName;
|
||||
private String lastName;
|
||||
|
||||
public FullName() {
|
||||
}
|
||||
|
||||
public FullName(String firstName, String middleName, String lastName) {
|
||||
this.firstName = firstName;
|
||||
this.middleName = middleName;
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getMiddleName() {
|
||||
return middleName;
|
||||
}
|
||||
|
||||
public void setMiddleName(String middleName) {
|
||||
this.middleName = middleName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[firstName=" + firstName + ", middleName="
|
||||
+ middleName + ", lastName=" + lastName + "]";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,93 @@
|
||||
package com.enzhico.benchmark.json.model;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Person
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/24
|
||||
*/
|
||||
public class Person {
|
||||
private String name;
|
||||
private FullName fullName;
|
||||
private int age;
|
||||
private Date birthday;
|
||||
private List<String> hobbies;
|
||||
private Map<String, String> clothes;
|
||||
private List<Person> friends;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public FullName getFullName() {
|
||||
return fullName;
|
||||
}
|
||||
|
||||
public void setFullName(FullName fullName) {
|
||||
this.fullName = fullName;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public Date getBirthday() {
|
||||
return birthday;
|
||||
}
|
||||
|
||||
public void setBirthday(Date birthday) {
|
||||
this.birthday = birthday;
|
||||
}
|
||||
|
||||
public List<String> getHobbies() {
|
||||
return hobbies;
|
||||
}
|
||||
|
||||
public void setHobbies(List<String> hobbies) {
|
||||
this.hobbies = hobbies;
|
||||
}
|
||||
|
||||
public Map<String, String> getClothes() {
|
||||
return clothes;
|
||||
}
|
||||
|
||||
public void setClothes(Map<String, String> clothes) {
|
||||
this.clothes = clothes;
|
||||
}
|
||||
|
||||
public List<Person> getFriends() {
|
||||
return friends;
|
||||
}
|
||||
|
||||
public void setFriends(List<Person> friends) {
|
||||
this.friends = friends;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder str = new StringBuilder("Person [name=" + name + ", fullName=" + fullName + ", age="
|
||||
+ age + ", birthday=" + birthday + ", hobbies=" + hobbies
|
||||
+ ", clothes=" + clothes + "]\n");
|
||||
if (friends != null) {
|
||||
str.append("Friends:\n");
|
||||
for (Person f : friends) {
|
||||
str.append("\t").append(f);
|
||||
}
|
||||
}
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.enzhico.benchmark.json.util;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
|
||||
/**
|
||||
* FastJsonUtil
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/24
|
||||
*/
|
||||
public class FastJsonUtil {
|
||||
public static String bean2Json(Object obj) {
|
||||
return JSON.toJSONString(obj);
|
||||
}
|
||||
|
||||
public static <T> T json2Bean(String jsonStr, Class<T> objClass) {
|
||||
return JSON.parseObject(jsonStr, objClass);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package com.enzhico.benchmark.json.util;
|
||||
|
||||
/**
|
||||
* GsonUtil
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/24
|
||||
*/
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
public class GsonUtil {
|
||||
private static Gson gson = new GsonBuilder().create();
|
||||
|
||||
public static String bean2Json(Object obj) {
|
||||
return gson.toJson(obj);
|
||||
}
|
||||
|
||||
public static <T> T json2Bean(String jsonStr, Class<T> objClass) {
|
||||
return gson.fromJson(jsonStr, objClass);
|
||||
}
|
||||
|
||||
public static String jsonFormatter(String uglyJsonStr) {
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
JsonParser jp = new JsonParser();
|
||||
JsonElement je = jp.parse(uglyJsonStr);
|
||||
return gson.toJson(je);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package com.enzhico.benchmark.json.util;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* JacksonUtil
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/24
|
||||
*/
|
||||
public class JacksonUtil {
|
||||
private static ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
public static String bean2Json(Object obj) {
|
||||
try {
|
||||
return mapper.writeValueAsString(obj);
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T json2Bean(String jsonStr, Class<T> objClass) {
|
||||
try {
|
||||
return mapper.readValue(jsonStr, objClass);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package com.enzhico.benchmark.json.util;
|
||||
|
||||
import net.sf.json.JSONObject;
|
||||
|
||||
/**
|
||||
* JsonLibUtil
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/24
|
||||
*/
|
||||
|
||||
public class JsonLibUtil {
|
||||
|
||||
public static String bean2Json(Object obj) {
|
||||
JSONObject jsonObject = JSONObject.fromObject(obj);
|
||||
return jsonObject.toString();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T json2Bean(String jsonStr, Class<T> objClass) {
|
||||
return (T) JSONObject.toBean(JSONObject.fromObject(jsonStr), objClass);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package com.enzhico.benchmark.string;
|
||||
|
||||
import org.openjdk.jmh.annotations.*;
|
||||
import org.openjdk.jmh.runner.Runner;
|
||||
import org.openjdk.jmh.runner.RunnerException;
|
||||
import org.openjdk.jmh.runner.options.Options;
|
||||
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 比较字符串直接相加和StringBuilder的效率
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/25
|
||||
*/
|
||||
@BenchmarkMode(Mode.Throughput)
|
||||
@Warmup(iterations = 3)
|
||||
@Measurement(iterations = 10, time = 5, timeUnit = TimeUnit.SECONDS)
|
||||
@Threads(8)
|
||||
@Fork(2)
|
||||
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
||||
public class StringBuilderBenchmark {
|
||||
|
||||
@Benchmark
|
||||
public void testStringAdd() {
|
||||
String a = "";
|
||||
for (int i = 0; i < 10; i++) {
|
||||
a += i;
|
||||
}
|
||||
print(a);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void testStringBuilderAdd() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
sb.append(i);
|
||||
}
|
||||
print(sb.toString());
|
||||
}
|
||||
|
||||
private void print(String a) {
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) throws RunnerException {
|
||||
Options options = new OptionsBuilder()
|
||||
.include(StringBuilderBenchmark.class.getSimpleName())
|
||||
.output("E:/Benchmark.log")
|
||||
.build();
|
||||
new Runner(options).run();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
package com.enzhico.benchmark.sum;
|
||||
|
||||
import com.enzhico.benchmark.common.ResultExporter;
|
||||
import com.enzhico.benchmark.sum.calc.Calculator;
|
||||
import com.enzhico.benchmark.sum.calc.impl.MultithreadCalculator;
|
||||
import com.enzhico.benchmark.sum.calc.impl.SinglethreadCalculator;
|
||||
import org.openjdk.jmh.annotations.*;
|
||||
import org.openjdk.jmh.results.RunResult;
|
||||
import org.openjdk.jmh.runner.Runner;
|
||||
import org.openjdk.jmh.runner.options.Options;
|
||||
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* SecondBenchmark
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/24
|
||||
*/
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@OutputTimeUnit(TimeUnit.MICROSECONDS)
|
||||
@State(Scope.Benchmark)
|
||||
public class SecondBenchmark {
|
||||
@Param({"10000", "100000", "1000000"})
|
||||
private int length;
|
||||
|
||||
private int[] numbers;
|
||||
private Calculator singleThreadCalc;
|
||||
private Calculator multiThreadCalc;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Options opt = new OptionsBuilder()
|
||||
.include(SecondBenchmark.class.getSimpleName())
|
||||
.forks(1)
|
||||
.warmupIterations(5)
|
||||
.measurementIterations(2)
|
||||
.build();
|
||||
Collection<RunResult> results = new Runner(opt).run();
|
||||
ResultExporter.exportResult("单线程与多线程求和性能", results, "length", "微秒");
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public long singleThreadBench() {
|
||||
return singleThreadCalc.sum(numbers);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public long multiThreadBench() {
|
||||
return multiThreadCalc.sum(numbers);
|
||||
}
|
||||
|
||||
@Setup
|
||||
public void prepare() {
|
||||
numbers = IntStream.rangeClosed(1, length).toArray();
|
||||
singleThreadCalc = new SinglethreadCalculator();
|
||||
multiThreadCalc = new MultithreadCalculator(Runtime.getRuntime().availableProcessors());
|
||||
}
|
||||
|
||||
@TearDown
|
||||
public void shutdown() {
|
||||
singleThreadCalc.shutdown();
|
||||
multiThreadCalc.shutdown();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package com.enzhico.benchmark.sum.calc;
|
||||
|
||||
/**
|
||||
* Calculator
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/24
|
||||
*/
|
||||
public interface Calculator {
|
||||
/**
|
||||
* calculate sum of an integer array
|
||||
*
|
||||
* @param numbers
|
||||
* @return
|
||||
*/
|
||||
public long sum(int[] numbers);
|
||||
|
||||
/**
|
||||
* shutdown pool or reclaim any related resources
|
||||
*/
|
||||
public void shutdown();
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
package com.enzhico.benchmark.sum.calc.impl;
|
||||
|
||||
import com.enzhico.benchmark.sum.calc.Calculator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* MultithreadCalculator
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/24
|
||||
*/
|
||||
public class MultithreadCalculator implements Calculator {
|
||||
private final int nThreads;
|
||||
private final ExecutorService pool;
|
||||
|
||||
public MultithreadCalculator(int nThreads) {
|
||||
this.nThreads = nThreads;
|
||||
this.pool = Executors.newFixedThreadPool(nThreads);
|
||||
}
|
||||
|
||||
private class SumTask implements Callable<Long> {
|
||||
private int[] numbers;
|
||||
private int from;
|
||||
private int to;
|
||||
|
||||
public SumTask(int[] numbers, int from, int to) {
|
||||
this.numbers = numbers;
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
public Long call() throws Exception {
|
||||
long total = 0L;
|
||||
for (int i = from; i < to; i++) {
|
||||
total += numbers[i];
|
||||
}
|
||||
return total;
|
||||
}
|
||||
}
|
||||
|
||||
public long sum(int[] numbers) {
|
||||
int chunk = numbers.length / nThreads;
|
||||
|
||||
int from, to;
|
||||
List<SumTask> tasks = new ArrayList<SumTask>();
|
||||
for (int i = 1; i <= nThreads; i++) {
|
||||
if (i == nThreads) {
|
||||
from = (i - 1) * chunk;
|
||||
to = numbers.length;
|
||||
} else {
|
||||
from = (i - 1) * chunk;
|
||||
to = i * chunk;
|
||||
}
|
||||
tasks.add(new SumTask(numbers, from, to));
|
||||
}
|
||||
|
||||
try {
|
||||
List<Future<Long>> futures = pool.invokeAll(tasks);
|
||||
long total = 0L;
|
||||
for (Future<Long> future : futures) {
|
||||
total += future.get();
|
||||
}
|
||||
return total;
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
pool.shutdown();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package com.enzhico.benchmark.sum.calc.impl;
|
||||
|
||||
import com.enzhico.benchmark.sum.calc.Calculator;
|
||||
|
||||
/**
|
||||
* SinglethreadCalculator
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/24
|
||||
*/
|
||||
public class SinglethreadCalculator implements Calculator {
|
||||
public long sum(int[] numbers) {
|
||||
long total = 0L;
|
||||
for (int i : numbers) {
|
||||
total += i;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package com.enzhico.echarts;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,146 @@
|
||||
package com.enzhico.echarts.api;
|
||||
|
||||
import com.corundumstudio.socketio.AckRequest;
|
||||
import com.corundumstudio.socketio.SocketIOClient;
|
||||
import com.corundumstudio.socketio.annotation.OnEvent;
|
||||
import com.enzhico.echarts.api.model.BaseResponse;
|
||||
import com.enzhico.echarts.api.model.EchartsData;
|
||||
import com.enzhico.echarts.api.model.PicRequest;
|
||||
import com.enzhico.echarts.service.ApiService;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* 对外API接口类
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(value = "/api/v1")
|
||||
public class PublicController {
|
||||
|
||||
@Resource
|
||||
private ApiService apiService;
|
||||
|
||||
private static final Logger _logger = LoggerFactory.getLogger(PublicController.class);
|
||||
|
||||
/**
|
||||
* 数据上传接口,body直接接受字符串,不要转
|
||||
* @return 结果
|
||||
*
|
||||
{
|
||||
"title": {
|
||||
"text": "天气预报"
|
||||
},
|
||||
"tooltip": {
|
||||
"trigger": "axis",
|
||||
"axisPointer": {
|
||||
"type": "shadow"
|
||||
}
|
||||
},
|
||||
"legend": {
|
||||
"data": ["City Alpha", "City Beta", "City Gamma"]
|
||||
},
|
||||
"grid": {
|
||||
"left": 100
|
||||
},
|
||||
"toolbox": {
|
||||
"show": false,
|
||||
"feature": {
|
||||
"saveAsImage": {}
|
||||
}
|
||||
},
|
||||
"xAxis": {
|
||||
"type": "value",
|
||||
"name": "Days"
|
||||
},
|
||||
"yAxis": {
|
||||
"type": "category",
|
||||
"inverse": false,
|
||||
"data": ["Sunny", "Cloudy", "Showers"],
|
||||
"axisLabel": {
|
||||
"margin": 20
|
||||
}
|
||||
},
|
||||
"series": [
|
||||
{
|
||||
"name": "City Alpha",
|
||||
"type": "bar",
|
||||
"label": {
|
||||
"normal": {
|
||||
"show": true,
|
||||
"textBorderWidth": 2
|
||||
}
|
||||
},
|
||||
"data": [165, 170, 30]
|
||||
},
|
||||
{
|
||||
"name": "City Beta",
|
||||
"type": "bar",
|
||||
"label": {
|
||||
"normal": {
|
||||
"show": true,
|
||||
"textBorderWidth": 2
|
||||
}
|
||||
},
|
||||
"data": [150, 105, 110]
|
||||
},
|
||||
{
|
||||
"name": "City Gamma",
|
||||
"type": "bar",
|
||||
"label": {
|
||||
"normal": {
|
||||
"show": true,
|
||||
"textBorderWidth": 2
|
||||
}
|
||||
},
|
||||
"data": [220, 82, 63]
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
@RequestMapping(value = "/data", method = RequestMethod.POST)
|
||||
public ResponseEntity<BaseResponse> doJoin(HttpServletRequest request) throws Exception {
|
||||
_logger.info("数据上传消息push接口 start....");
|
||||
String jsonBody = IOUtils.toString(request.getInputStream(), Charset.forName("UTF-8"));
|
||||
EchartsData echartsData = new EchartsData("", jsonBody);
|
||||
String jsonString = new ObjectMapper().writeValueAsString(echartsData);
|
||||
apiService.pushMsg("notify", jsonString);
|
||||
BaseResponse result = new BaseResponse<>(true, "数据上传消息push成功", null);
|
||||
return new ResponseEntity<>(result, HttpStatus.OK);
|
||||
}
|
||||
|
||||
// @RequestMapping(value = "/ask", method = RequestMethod.POST)
|
||||
// public ResponseEntity<BaseResponse> doAsk() {
|
||||
// ResponseEntity<BaseResponse> result;
|
||||
// String jsonString = apiService.popJson();
|
||||
// if (jsonString == null) {
|
||||
// result = new ResponseEntity<>(new BaseResponse<>(false, "轮询没有查到数据", null), HttpStatus.OK);
|
||||
// } else {
|
||||
// _logger.info("轮询后查询到数据");
|
||||
// result = new ResponseEntity<>(new BaseResponse<>(true, "轮询后查询到数据", jsonString), HttpStatus.OK);
|
||||
// }
|
||||
// return result;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 保存客户端传来的图片数据
|
||||
// *
|
||||
// * @param picInfo 图片BASE64
|
||||
// */
|
||||
// @RequestMapping(value = "/savePic", method = RequestMethod.POST)
|
||||
// public ResponseEntity<BaseResponse> onSavePic(@RequestParam("picInfo") String picInfo) {
|
||||
// _logger.info("保存客户端传来的图片数据 start");
|
||||
// String r = apiService.saveBase64Pic(picInfo);
|
||||
// _logger.info("保存客户端传来的图片 = {}", r);
|
||||
// return new ResponseEntity<>(new BaseResponse<>(true, "图片保存成功", null), HttpStatus.OK);
|
||||
// }
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package com.enzhico.echarts.api.model;
|
||||
|
||||
/**
|
||||
* API接口的基础返回类
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/1/7
|
||||
*/
|
||||
public class BaseResponse<T> {
|
||||
/**
|
||||
* 是否成功
|
||||
*/
|
||||
private boolean success;
|
||||
|
||||
/**
|
||||
* 说明
|
||||
*/
|
||||
private String msg;
|
||||
|
||||
/**
|
||||
* 返回数据
|
||||
*/
|
||||
private T data;
|
||||
|
||||
public BaseResponse() {
|
||||
|
||||
}
|
||||
|
||||
public BaseResponse(boolean success, String msg, T data) {
|
||||
this.success = success;
|
||||
this.msg = msg;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
public void setSuccess(boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.enzhico.echarts.api.model;
|
||||
|
||||
/**
|
||||
* EchartsData
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/8
|
||||
*/
|
||||
public class EchartsData {
|
||||
/**
|
||||
* 图表类型
|
||||
*/
|
||||
private String msgType;
|
||||
/**
|
||||
* 图表数据
|
||||
*/
|
||||
private String option;
|
||||
|
||||
public EchartsData() {
|
||||
}
|
||||
|
||||
public EchartsData(String msgType, String option) {
|
||||
this.msgType = msgType;
|
||||
this.option = option;
|
||||
}
|
||||
|
||||
public String getMsgType() {
|
||||
return msgType;
|
||||
}
|
||||
|
||||
public void setMsgType(String msgType) {
|
||||
this.msgType = msgType;
|
||||
}
|
||||
|
||||
public String getOption() {
|
||||
return option;
|
||||
}
|
||||
|
||||
public void setOption(String option) {
|
||||
this.option = option;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package com.enzhico.echarts.api.model;
|
||||
|
||||
/**
|
||||
* PicRequest
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/8
|
||||
*/
|
||||
public class PicRequest {
|
||||
/**
|
||||
* Base64格式的图片
|
||||
*/
|
||||
private String picInfo;
|
||||
|
||||
public String getPicInfo() {
|
||||
return picInfo;
|
||||
}
|
||||
|
||||
public void setPicInfo(String picInfo) {
|
||||
this.picInfo = picInfo;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.enzhico.echarts.api.model.jmh;
|
||||
|
||||
/**
|
||||
* AxisPointer
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/9
|
||||
*/
|
||||
public class AxisPointer {
|
||||
public AxisPointer() {
|
||||
}
|
||||
|
||||
public AxisPointer(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
private String type;
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.enzhico.echarts.api.model.jmh;
|
||||
|
||||
/**
|
||||
* Feature
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/9
|
||||
*/
|
||||
public class Feature {
|
||||
private SaveAsImage saveAsImage;
|
||||
|
||||
public Feature() {
|
||||
}
|
||||
|
||||
public Feature(SaveAsImage saveAsImage) {
|
||||
this.saveAsImage = saveAsImage;
|
||||
}
|
||||
|
||||
public SaveAsImage getSaveAsImage() {
|
||||
return saveAsImage;
|
||||
}
|
||||
|
||||
public void setSaveAsImage(SaveAsImage saveAsImage) {
|
||||
this.saveAsImage = saveAsImage;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package com.enzhico.echarts.api.model.jmh;
|
||||
|
||||
/**
|
||||
* Grid
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/9
|
||||
*/
|
||||
public class Grid {
|
||||
|
||||
private Integer left;
|
||||
|
||||
public Grid(Integer left) {
|
||||
this.left = left;
|
||||
}
|
||||
|
||||
public Grid() {
|
||||
}
|
||||
|
||||
public Integer getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public void setLeft(Integer left) {
|
||||
this.left = left;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.enzhico.echarts.api.model.jmh;
|
||||
|
||||
/**
|
||||
* Label
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/9
|
||||
*/
|
||||
public class Label {
|
||||
private Normal normal;
|
||||
|
||||
public Label() {
|
||||
}
|
||||
|
||||
public Label(Normal normal) {
|
||||
this.normal = normal;
|
||||
}
|
||||
|
||||
public Normal getNormal() {
|
||||
return normal;
|
||||
}
|
||||
|
||||
public void setNormal(Normal normal) {
|
||||
this.normal = normal;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package com.enzhico.echarts.api.model.jmh;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Legend
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/9
|
||||
*/
|
||||
public class Legend {
|
||||
private List<String> data;
|
||||
|
||||
public Legend() {
|
||||
}
|
||||
|
||||
public Legend(List<String> data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public List<String> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(List<String> data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package com.enzhico.echarts.api.model.jmh;
|
||||
|
||||
/**
|
||||
* Normal
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/9
|
||||
*/
|
||||
public class Normal {
|
||||
private boolean show;
|
||||
private Integer textBorderWidth;
|
||||
|
||||
public Normal() {
|
||||
}
|
||||
|
||||
public Normal(boolean show, Integer textBorderWidth) {
|
||||
this.show = show;
|
||||
this.textBorderWidth = textBorderWidth;
|
||||
}
|
||||
|
||||
public boolean isShow() {
|
||||
return show;
|
||||
}
|
||||
|
||||
public void setShow(boolean show) {
|
||||
this.show = show;
|
||||
}
|
||||
|
||||
public Integer getTextBorderWidth() {
|
||||
return textBorderWidth;
|
||||
}
|
||||
|
||||
public void setTextBorderWidth(Integer textBorderWidth) {
|
||||
this.textBorderWidth = textBorderWidth;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,85 @@
|
||||
package com.enzhico.echarts.api.model.jmh;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 汇总Option
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/9
|
||||
*/
|
||||
public class Option {
|
||||
private Title title;
|
||||
private Tooltip tooltip;
|
||||
private Legend legend;
|
||||
private Grid grid;
|
||||
private Toolbox toolbox;
|
||||
private XAxis xAxis;
|
||||
private YAxis yAxis;
|
||||
private List<Serie> series;
|
||||
|
||||
public Title getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(Title title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public Tooltip getTooltip() {
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
public void setTooltip(Tooltip tooltip) {
|
||||
this.tooltip = tooltip;
|
||||
}
|
||||
|
||||
public Legend getLegend() {
|
||||
return legend;
|
||||
}
|
||||
|
||||
public void setLegend(Legend legend) {
|
||||
this.legend = legend;
|
||||
}
|
||||
|
||||
public Grid getGrid() {
|
||||
return grid;
|
||||
}
|
||||
|
||||
public void setGrid(Grid grid) {
|
||||
this.grid = grid;
|
||||
}
|
||||
|
||||
public Toolbox getToolbox() {
|
||||
return toolbox;
|
||||
}
|
||||
|
||||
public void setToolbox(Toolbox toolbox) {
|
||||
this.toolbox = toolbox;
|
||||
}
|
||||
|
||||
public XAxis getxAxis() {
|
||||
return xAxis;
|
||||
}
|
||||
|
||||
public void setxAxis(XAxis xAxis) {
|
||||
this.xAxis = xAxis;
|
||||
}
|
||||
|
||||
public YAxis getyAxis() {
|
||||
return yAxis;
|
||||
}
|
||||
|
||||
public void setyAxis(YAxis yAxis) {
|
||||
this.yAxis = yAxis;
|
||||
}
|
||||
|
||||
public List<Serie> getSeries() {
|
||||
return series;
|
||||
}
|
||||
|
||||
public void setSeries(List<Serie> series) {
|
||||
this.series = series;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.enzhico.echarts.api.model.jmh;
|
||||
|
||||
/**
|
||||
* SaveAsImage
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/10
|
||||
*/
|
||||
public class SaveAsImage {
|
||||
private String type;
|
||||
|
||||
public SaveAsImage() {
|
||||
}
|
||||
|
||||
public SaveAsImage(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
package com.enzhico.echarts.api.model.jmh;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Serie
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/9
|
||||
*/
|
||||
public class Serie {
|
||||
private String name;
|
||||
private String type;
|
||||
private List<Double> data;
|
||||
private Label label;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public List<Double> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(List<Double> data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Label getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public void setLabel(Label label) {
|
||||
this.label = label;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.enzhico.echarts.api.model.jmh;
|
||||
|
||||
/**
|
||||
* Title
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/9
|
||||
*/
|
||||
public class Title {
|
||||
private String text;
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package com.enzhico.echarts.api.model.jmh;
|
||||
|
||||
/**
|
||||
* Toolbox
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/9
|
||||
*/
|
||||
public class Toolbox {
|
||||
private boolean show;
|
||||
private Feature feature;
|
||||
|
||||
public Toolbox() {
|
||||
}
|
||||
|
||||
public Toolbox(boolean show, Feature feature) {
|
||||
this.show = show;
|
||||
this.feature = feature;
|
||||
}
|
||||
|
||||
public boolean isShow() {
|
||||
return show;
|
||||
}
|
||||
|
||||
public void setShow(boolean show) {
|
||||
this.show = show;
|
||||
}
|
||||
|
||||
public Feature getFeature() {
|
||||
return feature;
|
||||
}
|
||||
|
||||
public void setFeature(Feature feature) {
|
||||
this.feature = feature;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package com.enzhico.echarts.api.model.jmh;
|
||||
|
||||
/**
|
||||
* Tooltip
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/9
|
||||
*/
|
||||
public class Tooltip {
|
||||
private String trigger;
|
||||
private AxisPointer axisPointer;
|
||||
|
||||
public Tooltip() {
|
||||
}
|
||||
|
||||
public Tooltip(String trigger, AxisPointer axisPointer) {
|
||||
this.trigger = trigger;
|
||||
this.axisPointer = axisPointer;
|
||||
}
|
||||
|
||||
public String getTrigger() {
|
||||
return trigger;
|
||||
}
|
||||
|
||||
public void setTrigger(String trigger) {
|
||||
this.trigger = trigger;
|
||||
}
|
||||
|
||||
public AxisPointer getAxisPointer() {
|
||||
return axisPointer;
|
||||
}
|
||||
|
||||
public void setAxisPointer(AxisPointer axisPointer) {
|
||||
this.axisPointer = axisPointer;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package com.enzhico.echarts.api.model.jmh;
|
||||
|
||||
/**
|
||||
* XAxis
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/9
|
||||
*/
|
||||
public class XAxis {
|
||||
private String type;
|
||||
private String name;
|
||||
|
||||
public XAxis() {
|
||||
}
|
||||
|
||||
public XAxis(String type, String name) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package com.enzhico.echarts.api.model.jmh;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* YAxis
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/9
|
||||
*/
|
||||
public class YAxis {
|
||||
private String type;
|
||||
private boolean inverse;
|
||||
private List<String> data;
|
||||
private YAxisLabel axisLabel;
|
||||
|
||||
public YAxis() {
|
||||
}
|
||||
|
||||
public YAxis(String type, boolean inverse, List<String> data, YAxisLabel axisLabel) {
|
||||
this.type = type;
|
||||
this.inverse = inverse;
|
||||
this.data = data;
|
||||
this.axisLabel = axisLabel;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public boolean isInverse() {
|
||||
return inverse;
|
||||
}
|
||||
|
||||
public void setInverse(boolean inverse) {
|
||||
this.inverse = inverse;
|
||||
}
|
||||
|
||||
public List<String> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(List<String> data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public YAxisLabel getAxisLabel() {
|
||||
return axisLabel;
|
||||
}
|
||||
|
||||
public void setAxisLabel(YAxisLabel axisLabel) {
|
||||
this.axisLabel = axisLabel;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.enzhico.echarts.api.model.jmh;
|
||||
|
||||
/**
|
||||
* YAxisLabel
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/9
|
||||
*/
|
||||
public class YAxisLabel {
|
||||
private Integer margin;
|
||||
|
||||
public YAxisLabel() {
|
||||
}
|
||||
|
||||
public YAxisLabel(Integer margin) {
|
||||
this.margin = margin;
|
||||
}
|
||||
|
||||
public Integer getMargin() {
|
||||
return margin;
|
||||
}
|
||||
|
||||
public void setMargin(Integer margin) {
|
||||
this.margin = margin;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
package com.enzhico.echarts.common;
|
||||
|
||||
import com.corundumstudio.socketio.SocketIOServer;
|
||||
import com.enzhico.echarts.config.properties.MyProperties;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* SpringBoot启动之后执行
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2017/7/31
|
||||
*/
|
||||
@Component
|
||||
@Order(1)
|
||||
public class ServerRunner implements CommandLineRunner {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
private final SocketIOServer server;
|
||||
// 下载地址,版本2.1.1:https://bitbucket.org/ariya/phantomjs/downloads/
|
||||
private static final String PHANTOM_PATH = "phantomjs";
|
||||
@Resource
|
||||
private MyProperties p;
|
||||
|
||||
@Autowired
|
||||
public ServerRunner(SocketIOServer server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(String... args) {
|
||||
logger.info("ServerRunner 开始启动啦...");
|
||||
server.start();
|
||||
logger.info("SocketServer 启动成功!");
|
||||
logger.info("点击打开首页: http://localhost:9075");
|
||||
// 启动socker服务器后,通过phantomjs启动浏览器网页客户端
|
||||
// openHtml(p.getLoadJs());
|
||||
// logger.info("Phantomjs 启动成功!");
|
||||
}
|
||||
|
||||
// private void openHtml(String loadJs) {
|
||||
// String cmdStr = PHANTOM_PATH + " " + loadJs + " " + "http://localhost:9075";
|
||||
// logger.info("cmdStr=" + cmdStr);
|
||||
// Runtime rt = Runtime.getRuntime();
|
||||
// try {
|
||||
// rt.exec(cmdStr);
|
||||
// } catch (IOException e) {
|
||||
// logger.error("执行phantomjs的指令失败!PhantomJs详情参考这里:http://phantomjs.org", e);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package com.enzhico.echarts.common.constants;
|
||||
|
||||
/**
|
||||
* 消息类型
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/8
|
||||
*/
|
||||
public class MsgType {
|
||||
public static final String TYPE1 = "type1";
|
||||
public static final String TYPE2 = "type2";
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package com.enzhico.echarts.common.util;
|
||||
|
||||
/**
|
||||
* 常用工具类,字符串、数字相关
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/1/15
|
||||
*/
|
||||
public class CommonUtil {
|
||||
/**
|
||||
* 检查某版本是否比现在版本更大些
|
||||
*
|
||||
* @param version 某版本
|
||||
* @param nowVersion 现在使用的版本
|
||||
* @return 是否版本数更大
|
||||
*/
|
||||
public static boolean isNewer(String version, String nowVersion) {
|
||||
try {
|
||||
String[] versions = version.split("\\.");
|
||||
String[] nowVersions = nowVersion.split("\\.");
|
||||
|
||||
if (versions.length != nowVersions.length) {
|
||||
return false;
|
||||
}
|
||||
int sum = 0;
|
||||
for (String v : versions) {
|
||||
sum += sum * 10 + Integer.valueOf(v);
|
||||
}
|
||||
|
||||
int nowSum = 0;
|
||||
for (String nv : nowVersions) {
|
||||
nowSum += nowSum * 10 + Integer.valueOf(nv);
|
||||
}
|
||||
|
||||
return sum > nowSum;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,85 @@
|
||||
package com.enzhico.echarts.common.util;
|
||||
|
||||
import com.enzhico.echarts.api.model.jmh.*;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import okhttp3.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* ExportPngUtil
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/24
|
||||
*/
|
||||
public class ExportPngUtil {
|
||||
|
||||
public static void postOption(String optionStr, String url) throws Exception {
|
||||
final MediaType TEXT = MediaType.parse("application/text; charset=utf-8");
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
RequestBody body = RequestBody.create(TEXT, optionStr);
|
||||
Request request = new Request.Builder()
|
||||
.url(url)
|
||||
.post(body)
|
||||
.build();
|
||||
Response response = client.newCall(request).execute();
|
||||
if (response.isSuccessful()) {
|
||||
System.out.println(response.body().string());
|
||||
} else {
|
||||
throw new IOException("Unexpected code " + response);
|
||||
}
|
||||
}
|
||||
|
||||
public static String generateOption(String titleStr, List<String> objects, List<String> dimensions,
|
||||
List<List<Double>> allData, String xunit) {
|
||||
Option option = new Option();
|
||||
// "title"
|
||||
Title title = new Title();
|
||||
title.setText(titleStr);
|
||||
// "tooltip"
|
||||
Tooltip tooltip = new Tooltip("axis", new AxisPointer("shadow"));
|
||||
// "legend"
|
||||
Legend legend = new Legend(objects);
|
||||
// "grid"
|
||||
Grid grid = new Grid(100);
|
||||
// "toolbox"
|
||||
Toolbox toolbox = new Toolbox(false, new Feature(new SaveAsImage("png")));
|
||||
// "xAxis"
|
||||
XAxis xAxis = new XAxis("value", xunit);
|
||||
// "yAxis"
|
||||
YAxis yAxis = new YAxis("category", false, dimensions, new YAxisLabel(20));
|
||||
// "series"
|
||||
List<Serie> series = new ArrayList<>();
|
||||
for (int i = 0; i < allData.size(); i++) {
|
||||
Serie serie = new Serie();
|
||||
serie.setName(objects.get(i));
|
||||
serie.setType("bar");
|
||||
serie.setLabel(new Label(new Normal(true, 2)));
|
||||
serie.setData(allData.get(i));
|
||||
series.add(serie);
|
||||
}
|
||||
|
||||
// 开始设置option
|
||||
option.setTitle(title);
|
||||
option.setTooltip(tooltip);
|
||||
option.setLegend(legend);
|
||||
option.setGrid(grid);
|
||||
option.setToolbox(toolbox);
|
||||
option.setxAxis(xAxis);
|
||||
option.setyAxis(yAxis);
|
||||
option.setSeries(series);
|
||||
|
||||
String jsonString = null;
|
||||
try {
|
||||
jsonString = new ObjectMapper().writeValueAsString(option);
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return jsonString;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package com.enzhico.echarts.config;
|
||||
|
||||
import com.corundumstudio.socketio.SocketIOServer;
|
||||
import com.corundumstudio.socketio.annotation.SpringAnnotationScanner;
|
||||
import com.enzhico.echarts.config.properties.MyProperties;
|
||||
import com.enzhico.echarts.service.ApiService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* NettySocketConfig
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/1/19
|
||||
*/
|
||||
@Configuration
|
||||
public class NettySocketConfig {
|
||||
|
||||
@Resource
|
||||
private MyProperties myProperties;
|
||||
|
||||
@Resource
|
||||
private ApiService apiService;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(NettySocketConfig.class);
|
||||
|
||||
@Bean
|
||||
public SocketIOServer socketIOServer() {
|
||||
/*
|
||||
* 创建Socket,并设置监听端口
|
||||
*/
|
||||
com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();
|
||||
// 设置主机名,默认是0.0.0.0
|
||||
// config.setHostname("localhost");
|
||||
// 设置监听端口
|
||||
config.setPort(myProperties.getSocketPort());
|
||||
// 协议升级超时时间(毫秒),默认10000。HTTP握手升级为ws协议超时时间
|
||||
config.setUpgradeTimeout(10000);
|
||||
// Ping消息间隔(毫秒),默认25000。客户端向服务器发送一条心跳消息间隔
|
||||
config.setPingInterval(myProperties.getPingInterval());
|
||||
// Ping消息超时时间(毫秒),默认60000,这个时间间隔内没有接收到心跳消息就会发送超时事件
|
||||
config.setPingTimeout(myProperties.getPingTimeout());
|
||||
return new SocketIOServer(config);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SpringAnnotationScanner springAnnotationScanner(SocketIOServer socketServer) {
|
||||
return new SpringAnnotationScanner(socketServer);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
package com.enzhico.echarts.config.properties;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
/**
|
||||
* 本项目自定义配置
|
||||
*
|
||||
* @author xiongneng
|
||||
* @since 2018/01/06 21:09
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "enzhico")
|
||||
public class MyProperties {
|
||||
/**
|
||||
* socket端口
|
||||
*/
|
||||
private Integer socketPort;
|
||||
/**
|
||||
* Ping消息间隔(毫秒)
|
||||
*/
|
||||
private Integer pingInterval;
|
||||
/**
|
||||
* Ping消息超时时间(毫秒)
|
||||
*/
|
||||
private Integer pingTimeout;
|
||||
/**
|
||||
* 图片保存路径
|
||||
*/
|
||||
private String imageDir;
|
||||
/**
|
||||
* Phantomjs加载文件
|
||||
*/
|
||||
private String loadJs;
|
||||
/**
|
||||
* 打开的HTMl文件
|
||||
*/
|
||||
private String indexHtml;
|
||||
|
||||
public Integer getSocketPort() {
|
||||
return socketPort;
|
||||
}
|
||||
|
||||
public void setSocketPort(Integer socketPort) {
|
||||
this.socketPort = socketPort;
|
||||
}
|
||||
|
||||
public Integer getPingInterval() {
|
||||
return pingInterval;
|
||||
}
|
||||
|
||||
public void setPingInterval(Integer pingInterval) {
|
||||
this.pingInterval = pingInterval;
|
||||
}
|
||||
|
||||
public Integer getPingTimeout() {
|
||||
return pingTimeout;
|
||||
}
|
||||
|
||||
public void setPingTimeout(Integer pingTimeout) {
|
||||
this.pingTimeout = pingTimeout;
|
||||
}
|
||||
|
||||
public String getImageDir() {
|
||||
return imageDir;
|
||||
}
|
||||
|
||||
public void setImageDir(String imageDir) {
|
||||
this.imageDir = imageDir;
|
||||
}
|
||||
|
||||
public String getLoadJs() {
|
||||
return loadJs;
|
||||
}
|
||||
|
||||
public void setLoadJs(String loadJs) {
|
||||
this.loadJs = loadJs;
|
||||
}
|
||||
|
||||
public String getIndexHtml() {
|
||||
return indexHtml;
|
||||
}
|
||||
|
||||
public void setIndexHtml(String indexHtml) {
|
||||
this.indexHtml = indexHtml;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package com.enzhico.echarts.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
/**
|
||||
* IndexController
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/2/24
|
||||
*/
|
||||
@Controller
|
||||
public class IndexController {
|
||||
/**
|
||||
* 首页
|
||||
*/
|
||||
@RequestMapping(value = "/")
|
||||
public String index() {
|
||||
return "index";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,93 @@
|
||||
package com.enzhico.echarts.handler;
|
||||
|
||||
import com.corundumstudio.socketio.AckRequest;
|
||||
import com.corundumstudio.socketio.SocketIOClient;
|
||||
import com.corundumstudio.socketio.SocketIOServer;
|
||||
import com.corundumstudio.socketio.annotation.OnConnect;
|
||||
import com.corundumstudio.socketio.annotation.OnDisconnect;
|
||||
import com.corundumstudio.socketio.annotation.OnEvent;
|
||||
import com.enzhico.echarts.common.constants.MsgType;
|
||||
import com.enzhico.echarts.config.properties.MyProperties;
|
||||
import com.enzhico.echarts.service.ApiService;
|
||||
import io.socket.client.Socket;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.time.FastDateFormat;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 消息事件处理器
|
||||
*
|
||||
* @author XiongNeng
|
||||
* @version 1.0
|
||||
* @since 2018/1/19
|
||||
*/
|
||||
@Component
|
||||
public class MessageEventHandler {
|
||||
@Resource
|
||||
private MyProperties p;
|
||||
private final SocketIOServer server;
|
||||
private final ApiService apiService;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(MessageEventHandler.class);
|
||||
|
||||
@Autowired
|
||||
public MessageEventHandler(SocketIOServer server, ApiService apiService) {
|
||||
this.server = server;
|
||||
this.apiService = apiService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加connect事件,当客户端发起连接时调用
|
||||
*
|
||||
* @param client 客户端
|
||||
*/
|
||||
@OnConnect
|
||||
public void onConnect(SocketIOClient client) {
|
||||
if (client != null) {
|
||||
final String sessionId = client.getSessionId().toString();
|
||||
logger.info("连接成功, sessionId=" + sessionId);
|
||||
// 赶紧保存这个sessionID呀
|
||||
apiService.updateSessionId(sessionId);
|
||||
} else {
|
||||
logger.error("客户端为空");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加@OnDisconnect事件,客户端断开连接时调用,刷新客户端信息
|
||||
*
|
||||
* @param client 客户端
|
||||
*/
|
||||
@OnDisconnect
|
||||
public void onDisconnect(SocketIOClient client) {
|
||||
logger.info("客户端断开连接, sessionId=" + client.getSessionId().toString());
|
||||
client.disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存客户端传来的图片数据
|
||||
*
|
||||
* @param client 客户端
|
||||
* @param ackRequest 回执消息
|
||||
* @param imgData Base64的图形数据
|
||||
*/
|
||||
@OnEvent(value = "savePic")
|
||||
public void onSavePic(SocketIOClient client, AckRequest ackRequest, String imgData) {
|
||||
logger.info("保存客户端传来的图片数据 start, sessionId=" + client.getSessionId().toString());
|
||||
String r = apiService.saveBase64Pic(imgData);
|
||||
logger.info("保存客户端传来的图片 = {}", r);
|
||||
ackRequest.sendAckData("图片保存结果=" + r);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,105 @@
|
||||
package com.enzhico.echarts.service;
|
||||
|
||||
import com.corundumstudio.socketio.SocketIOClient;
|
||||
import com.corundumstudio.socketio.SocketIOServer;
|
||||
import com.enzhico.echarts.config.properties.MyProperties;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.time.FastDateFormat;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 专门用来服务对外接口用Service
|
||||
*/
|
||||
|
||||
@Service
|
||||
public class ApiService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ApiService.class);
|
||||
/**
|
||||
* 保存最后一个连接上来的sessionID
|
||||
*/
|
||||
private String sessionId;
|
||||
|
||||
@Resource
|
||||
private MyProperties p;
|
||||
|
||||
// private LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>();
|
||||
|
||||
@Resource
|
||||
private SocketIOServer server;
|
||||
|
||||
public synchronized void updateSessionId(String sid) {
|
||||
sessionId = sid;
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务器主动推送消息
|
||||
*
|
||||
* @param msgType 消息类型
|
||||
* @param jsonData echarts图表数据
|
||||
*/
|
||||
public void pushMsg(String msgType, String jsonData) {
|
||||
SocketIOClient targetClient = this.server.getClient(UUID.fromString(sessionId));
|
||||
if (targetClient == null) {
|
||||
logger.error("sessionId=" + sessionId + "在server中获取不到client");
|
||||
} else {
|
||||
targetClient.sendEvent(msgType, jsonData);
|
||||
}
|
||||
// queue.offer(jsonData);
|
||||
}
|
||||
|
||||
// public String popJson() {
|
||||
// try {
|
||||
// return queue.poll(100L, TimeUnit.MILLISECONDS);
|
||||
// } catch (InterruptedException e) {
|
||||
// e.printStackTrace();
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* 解析Base64位信息并输出到某个目录下面.
|
||||
*
|
||||
* @param base64Info base64串
|
||||
* @return 文件地址
|
||||
*/
|
||||
public String saveBase64Pic(String base64Info) {
|
||||
if (StringUtils.isEmpty(base64Info)) {
|
||||
return "";
|
||||
}
|
||||
// 数据中:data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABI4AAAEsCAYAAAClh/jbAAA ... 在"base64,"之后的才是图片信息
|
||||
String[] arr = base64Info.split("base64,");
|
||||
|
||||
// 将图片输出到系统某目录.
|
||||
OutputStream out = null;
|
||||
String now = FastDateFormat.getInstance("yyyyMMddHHmmss").format(new Date());
|
||||
String destFile = p.getImageDir() + now + ".png";
|
||||
try {
|
||||
// 使用了Apache commons codec的包来解析Base64
|
||||
byte[] buffer = Base64.decodeBase64(arr[1]);
|
||||
out = new FileOutputStream(destFile);
|
||||
out.write(buffer);
|
||||
} catch (IOException e) {
|
||||
logger.error("解析Base64图片信息并保存到某目录下出错!", e);
|
||||
return "";
|
||||
} finally {
|
||||
IOUtils.closeQuietly(out);
|
||||
}
|
||||
return destFile;
|
||||
}
|
||||
|
||||
}
|
||||
70
springboot-echarts/src/main/resources/application.yml
Normal file
70
springboot-echarts/src/main/resources/application.yml
Normal file
@ -0,0 +1,70 @@
|
||||
##########################################################
|
||||
################## 所有profile共有的配置 #################
|
||||
##########################################################
|
||||
|
||||
################### 自定义项目配置 ###################
|
||||
enzhico:
|
||||
socket-port: 9076 #socket端口
|
||||
ping-interval: 60000 #Ping消息间隔(毫秒)
|
||||
ping-timeout: 180000 #Ping消息超时时间(毫秒)
|
||||
|
||||
################### 项目启动端口 ###################
|
||||
server:
|
||||
port: 9075
|
||||
jetty:
|
||||
max-http-post-size: 20000000
|
||||
|
||||
################### spring配置 ###################
|
||||
spring:
|
||||
profiles:
|
||||
active: dev
|
||||
http:
|
||||
multipart:
|
||||
max-request-size: 100MB #最大请求大小
|
||||
max-file-size: 100MB #最大文件大小
|
||||
|
||||
logging:
|
||||
level:
|
||||
org.springframework.web.servlet: ERROR
|
||||
|
||||
---
|
||||
|
||||
#####################################################################
|
||||
######################## 开发环境profile ##########################
|
||||
#####################################################################
|
||||
spring:
|
||||
profiles: dev
|
||||
|
||||
enzhico:
|
||||
image-dir: E:/pics/
|
||||
load-js: E:/pics/html/js/echarts-load.js
|
||||
index-html: file:///E:/pics/html/index.html
|
||||
|
||||
logging:
|
||||
level:
|
||||
ROOT: INFO
|
||||
com:
|
||||
enzhico: DEBUG
|
||||
file: E:/logs/sb-ehcharts.log
|
||||
|
||||
---
|
||||
|
||||
#####################################################################
|
||||
######################## 测试环境profile ##########################
|
||||
#####################################################################
|
||||
|
||||
spring:
|
||||
profiles: test
|
||||
|
||||
enzhico:
|
||||
image-dir: /var/pics/echarts/
|
||||
load-js: /usr/share/nginx/html/echarts/js/echarts-load.js
|
||||
index-html: file:///usr/share/nginx/html/echarts/index.html
|
||||
|
||||
logging:
|
||||
level:
|
||||
ROOT: INFO
|
||||
com:
|
||||
enzhico: DEBUG
|
||||
file: /var/logs/sb-ehcharts.log
|
||||
|
||||
BIN
springboot-echarts/src/main/resources/public/favicon.ico
Normal file
BIN
springboot-echarts/src/main/resources/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
4983
springboot-echarts/src/main/resources/public/static/css/bootstrap.css
vendored
Normal file
4983
springboot-echarts/src/main/resources/public/static/css/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,43 @@
|
||||
var system = require('system');
|
||||
var page = require('webpage').create();
|
||||
|
||||
// 获取第二个参数(即请求地址url).
|
||||
var url = system.args[1];
|
||||
console.log('url:' + url);
|
||||
|
||||
// 显示控制台日志.
|
||||
page.onConsoleMessage = function (msg, lineNum, sourceId) {
|
||||
console.log('console message ----> ' + msg);
|
||||
};
|
||||
page.onLoadStarted = function () {
|
||||
console.log("load started");
|
||||
};
|
||||
|
||||
page.onLoadFinished = function () {
|
||||
console.log("load finished");
|
||||
};
|
||||
page.onUrlChanged = function () {
|
||||
console.log("onUrlChanged");
|
||||
};
|
||||
|
||||
//打开给定url的页面.
|
||||
var start = new Date().getTime();
|
||||
|
||||
page.open(url, function (status) {
|
||||
if (status === 'success') {
|
||||
console.log('echarts页面加载完成,加载耗时:' + (new Date().getTime() - start) + ' ms');
|
||||
// // 处理页面
|
||||
// var pic_url = page.evaluate(function() {
|
||||
// // DOM操作
|
||||
// return document.getElementById('cp_image').getAttribute('src');
|
||||
// });
|
||||
// 由于echarts动画效果,延迟500毫秒确保图片渲染完毕再调用下载图片方法.
|
||||
// setTimeout(function () {
|
||||
// page.evaluate(function () {
|
||||
// console.log("调用了echarts的下载图片功能.");
|
||||
// });
|
||||
// }, 500);
|
||||
} else {
|
||||
console.log("页面加载失败 Page failed to load!");
|
||||
}
|
||||
});
|
||||
1
springboot-echarts/src/main/resources/public/static/js/echarts.common.min.js
vendored
Normal file
1
springboot-echarts/src/main/resources/public/static/js/echarts.common.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
springboot-echarts/src/main/resources/public/static/js/jquery-1.10.1.min.js
vendored
Normal file
6
springboot-echarts/src/main/resources/public/static/js/jquery-1.10.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
springboot-echarts/src/main/resources/public/static/js/moment.min.js
vendored
Normal file
6
springboot-echarts/src/main/resources/public/static/js/moment.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
122
springboot-echarts/src/main/resources/templates/index.html
Normal file
122
springboot-echarts/src/main/resources/templates/index.html
Normal file
@ -0,0 +1,122 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="renderer" content="webkit">
|
||||
<title>Echarts Demo</title>
|
||||
<link rel="shortcut icon" th:href="@{/favicon.ico}"/>
|
||||
<link th:href="@{/static/css/bootstrap.css}" rel="stylesheet"/>
|
||||
<style>
|
||||
body {
|
||||
padding: 20px;
|
||||
}
|
||||
#console {
|
||||
height: 100px;
|
||||
overflow: auto;
|
||||
}
|
||||
.connect-msg {
|
||||
color: green;
|
||||
}
|
||||
.disconnect-msg {
|
||||
color: red;
|
||||
}
|
||||
.send-msg {
|
||||
color: #888
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Netty-socketio Demo Chat</h1>
|
||||
<br/>
|
||||
<div id="console" class="well"></div>
|
||||
|
||||
<!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
|
||||
<div id="main" style="width:860px; height:470px;"></div>
|
||||
|
||||
<form class="well form-inline" onsubmit="return false;">
|
||||
<input id="msg" class="input-xlarge" type="text" placeholder="Type something..."/>
|
||||
<button type="button" onClick="sendDisconnect()" class="btn">Disconnect</button>
|
||||
<button type="button" onClick="sendSavePic()" class="btn">Save Picture</button>
|
||||
</form>
|
||||
|
||||
<script th:src="@{/static/js/jquery-1.10.1.min.js}"></script>
|
||||
<script th:src="@{/static/js/socket.io.js}"></script>
|
||||
<script th:src="@{/static/js/moment.min.js}"></script>
|
||||
<script th:src="@{/static/js/echarts.common.min.js}" charset="utf-8"></script>
|
||||
|
||||
<script>
|
||||
var socket;
|
||||
var myChart;
|
||||
|
||||
function sendDisconnect() {
|
||||
socket.disconnect();
|
||||
}
|
||||
|
||||
function output(message) {
|
||||
var currentTime = "<span class='time'>" + moment().format('HH:mm:ss.SSS') + "</span>";
|
||||
var element = $("<div>" + currentTime + " " + message + "</div>");
|
||||
$('#console').prepend(element);
|
||||
}
|
||||
|
||||
function sendSavePic() {
|
||||
socket.emit('savePic', myChart.getDataURL(), function (result) {
|
||||
output('<span class="connect-msg">' + result + '</span>');
|
||||
});
|
||||
}
|
||||
|
||||
function initPage() {
|
||||
console.log('this is index.html log...');
|
||||
|
||||
var userName = 'user' + Math.floor((Math.random() * 1000) + 1);
|
||||
socket = io.connect('http://localhost:9076');
|
||||
|
||||
console.log('socket = ' + socket);
|
||||
|
||||
socket.on('connect', function () {
|
||||
console.log('connect successful');
|
||||
output('<span class="connect-msg">Client has connected to the server!</span>');
|
||||
});
|
||||
|
||||
socket.on('ping', function () {
|
||||
console.log('ping successful');
|
||||
output('<span class="connect-msg">Client Ping msg to the server!</span>');
|
||||
});
|
||||
|
||||
socket.on('pong', function () {
|
||||
console.log('pong successful');
|
||||
output('<span class="connect-msg">Client Pong msg from the server!</span>');
|
||||
});
|
||||
|
||||
socket.on('disconnect', function () {
|
||||
console.log('disconnect successful');
|
||||
output('<span class="disconnect-msg">The client has disconnected!</span>');
|
||||
});
|
||||
|
||||
socket.on('notify', function (jsonBody) {
|
||||
console.log('get notify message from server...');
|
||||
var msg = JSON.parse(jsonBody);
|
||||
output('<span class="connect-msg">接收到notify消息, 去给我保存图片</span>');
|
||||
var option = msg.option;
|
||||
// 使用刚指定的配置项和数据显示图表。
|
||||
myChart.setOption(JSON.parse(option));
|
||||
// 渲染完成之后再给服务器发送保存图片消息
|
||||
sendSavePic();
|
||||
});
|
||||
|
||||
/**************************************分割线***********************************/
|
||||
// 基于准备好的dom,初始化echarts实例
|
||||
myChart = echarts.init(document.getElementById('main'));
|
||||
console.log('index initPage finished!')
|
||||
}
|
||||
|
||||
$(function () {
|
||||
initPage();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@ -0,0 +1,53 @@
|
||||
package com.enzhico.echarts.common.util;
|
||||
|
||||
import com.enzhico.echarts.api.model.jmh.*;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.ObjectWriter;
|
||||
import okhttp3.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static com.enzhico.echarts.common.util.ExportPngUtil.generateOption;
|
||||
import static com.enzhico.echarts.common.util.ExportPngUtil.postOption;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class CommonUtilTest {
|
||||
|
||||
@Test
|
||||
public void isNewer() {
|
||||
assertThat(CommonUtil.isNewer("1.2.1", "1.2.0"), is(true));
|
||||
assertThat(CommonUtil.isNewer("1.2", "1.2.0"), is(false));
|
||||
assertThat(CommonUtil.isNewer("2.1.9", "1.2.0"), is(true));
|
||||
assertThat(CommonUtil.isNewer("adfa.1.3", "1.2.0"), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimestamp() {
|
||||
System.out.println(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOption() throws Exception {
|
||||
String titleStr = "对象序列化为JSON字符串";
|
||||
// 几个测试对象
|
||||
List<String> objects = Arrays.asList("FastJson", "Jackson", "Gson", "Json-lib");
|
||||
// 测试维度,输入值n
|
||||
List<String> dimensions = Arrays.asList("10000次", "100000次", "1000000次");
|
||||
// 有几个测试对象,就有几组测试数据,每组测试数据中对应几个维度的结果
|
||||
List<List<Double>> allData = new ArrayList<List<Double>>(){{
|
||||
add(Arrays.asList(2.17, 9.10, 21.70));
|
||||
add(Arrays.asList(1.94, 8.94, 19.43));
|
||||
add(Arrays.asList(4.88, 22.88, 48.89));
|
||||
add(Arrays.asList(9.11, 58.14, 108.44));
|
||||
}};
|
||||
String optionStr = generateOption(titleStr, objects, dimensions, allData, "秒");
|
||||
// POST到接口上
|
||||
postOption(optionStr, "http://localhost:9075/api/v1/data");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user