This commit is contained in:
yidao620
2018-02-26 19:05:53 +08:00
commit 4d57c022c6
534 changed files with 96924 additions and 0 deletions

View File

@ -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");
}
}

View File

@ -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();
}
}

View File

@ -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() {
}
}

View File

@ -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;
}
}

View File

@ -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 + "]";
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}

View File

@ -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();
}
}

View File

@ -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
}
}

View File

@ -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);
}
}

View File

@ -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);
// }
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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.1https://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);
// }
// }
}

View File

@ -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";
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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";
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}