add:添加示教接口
This commit is contained in:
34
src/main/java/org/nl/apt15e/Apt15EApplication.java
Normal file
34
src/main/java/org/nl/apt15e/Apt15EApplication.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package org.nl.apt15e;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@EnableAsync
|
||||
@EnableScheduling
|
||||
@SpringBootApplication
|
||||
@EnableTransactionManagement
|
||||
@RestController
|
||||
@MapperScan("org.nl.apt15e.**.config")
|
||||
public class Apt15EApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Apt15EApplication.class, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 访问首页提示
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
@GetMapping("/")
|
||||
public String index() {
|
||||
return "Backend service started successfully";
|
||||
}
|
||||
|
||||
}
|
||||
26
src/main/java/org/nl/apt15e/apt/dao/VehicleException.java
Normal file
26
src/main/java/org/nl/apt15e/apt/dao/VehicleException.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package org.nl.apt15e.apt.dao;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/7/2
|
||||
*/
|
||||
@Data
|
||||
public class VehicleException implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 错误信息
|
||||
*/
|
||||
private List<String> exception;
|
||||
|
||||
/**
|
||||
* 错误码
|
||||
*/
|
||||
private List<Long> exceptionCodes;
|
||||
|
||||
}
|
||||
65
src/main/java/org/nl/apt15e/apt/dao/VehicleInfo.java
Normal file
65
src/main/java/org/nl/apt15e/apt/dao/VehicleInfo.java
Normal file
@@ -0,0 +1,65 @@
|
||||
package org.nl.apt15e.apt.dao;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/7/2
|
||||
*/
|
||||
@Data
|
||||
public class VehicleInfo implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 车辆 ID
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 车辆名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 车辆 IP
|
||||
*/
|
||||
private String ip;
|
||||
|
||||
/**
|
||||
* 车辆所在地图 ID
|
||||
*/
|
||||
private Long mapId;
|
||||
|
||||
/**
|
||||
* 车辆所在地图 名称
|
||||
*/
|
||||
private String mapName;
|
||||
|
||||
/**
|
||||
* 车辆状态 ID
|
||||
*/
|
||||
private Long stateId;
|
||||
|
||||
/**
|
||||
* 车辆状态名称
|
||||
*/
|
||||
private String state;
|
||||
|
||||
/**
|
||||
* 区域 ID
|
||||
*/
|
||||
private Long areaId;
|
||||
|
||||
/**
|
||||
* 电量
|
||||
*/
|
||||
private Long batteryPower;
|
||||
|
||||
/**
|
||||
* 异常信息
|
||||
*/
|
||||
private VehicleException exceptionInfo;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.nl.apt15e.apt.rest;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nl.apt15e.apt.dao.VehicleInfo;
|
||||
import org.nl.apt15e.apt.service.VehicleInfoService;
|
||||
import org.nl.apt15e.common.logging.annotation.Log;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/7/3
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/vehicle")
|
||||
public class VehicleInfoController {
|
||||
|
||||
@Resource
|
||||
private VehicleInfoService vehicleInfoService;
|
||||
|
||||
@GetMapping("/getVehicleInfo")
|
||||
// @Log("获取车辆信息")
|
||||
public VehicleInfo getVehicleInfo() {
|
||||
return vehicleInfoService.getVehicleInfo();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.nl.apt15e.apt.service;
|
||||
|
||||
import org.nl.apt15e.apt.dao.VehicleInfo;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/7/2
|
||||
*/
|
||||
public interface VehicleInfoService {
|
||||
|
||||
VehicleInfo getVehicleInfo();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package org.nl.apt15e.apt.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nl.apt15e.apt.dao.VehicleException;
|
||||
import org.nl.apt15e.apt.dao.VehicleInfo;
|
||||
import org.nl.apt15e.apt.service.VehicleInfoService;
|
||||
import org.nl.apt15e.apt.websocket.WebSocketVehicleServer;
|
||||
import org.nl.apt15e.util.HTTPUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/7/2
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class VehicleInfoServiceImpl implements VehicleInfoService {
|
||||
|
||||
@Resource
|
||||
private TaskScheduler scheduler;
|
||||
|
||||
public static VehicleInfo vehicleInfo = new VehicleInfo();
|
||||
|
||||
@Override
|
||||
public VehicleInfo getVehicleInfo() {
|
||||
return vehicleInfo;
|
||||
}
|
||||
|
||||
@Async("asynchronousTasks")
|
||||
public void queryVehicleInfo() {
|
||||
HttpResponse response = null;
|
||||
try {
|
||||
response = HTTPUtil.get("http://192.168.100.82:8081","/amr/onlineAmr",null);
|
||||
// 检查响应状态码
|
||||
if (response!=null && response.isOk()) {
|
||||
// 获取响应体内容
|
||||
String body = response.body();
|
||||
JSONArray jsonArray = JSONObject.parseObject(body).getJSONArray("data");
|
||||
if (jsonArray.isEmpty()) {
|
||||
log.info("车辆数据为空");
|
||||
}
|
||||
for (int i = 0; i < jsonArray.size(); i++) {
|
||||
JSONObject data = jsonArray.getJSONObject(i);
|
||||
vehicleInfo = JSONObject.toJavaObject(data, VehicleInfo.class);
|
||||
//电量
|
||||
vehicleInfo.setBatteryPower(data.getLong("batteryPercentile"));
|
||||
//上报的异常信息
|
||||
VehicleException vehicleException = JSONObject.toJavaObject(data.getJSONObject("amrException"), VehicleException.class);
|
||||
vehicleInfo.setExceptionInfo(vehicleException);
|
||||
System.out.println("Response Body: " + data);
|
||||
System.out.println("vehicleInfo: " + vehicleInfo);
|
||||
}
|
||||
} else {
|
||||
log.info("查询调度车辆信息失败:{}",response);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.info("访问调度报错{}", e.getMessage());
|
||||
}
|
||||
if (response != null) {
|
||||
response.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Async("asynchronousTasks")
|
||||
public void sendVehicleInfo() {
|
||||
CopyOnWriteArraySet<WebSocketVehicleServer> webSocketSet =
|
||||
WebSocketVehicleServer.getWebSocketSet();
|
||||
if (webSocketSet.size() > 0) {
|
||||
webSocketSet.forEach(c -> {
|
||||
Map<String, Object> vehicleInfoMap = new HashMap<>();
|
||||
vehicleInfoMap.put("data", vehicleInfo);
|
||||
c.sendDataToClient(vehicleInfoMap);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
scheduler.scheduleAtFixedRate(this::queryVehicleInfo,4000);
|
||||
scheduler.scheduleAtFixedRate(this::sendVehicleInfo, 4000);
|
||||
}
|
||||
}
|
||||
50
src/main/java/org/nl/apt15e/apt/station/dao/Station.java
Normal file
50
src/main/java/org/nl/apt15e/apt/station/dao/Station.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package org.nl.apt15e.apt.station.dao;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/7/4
|
||||
*/
|
||||
@Data
|
||||
public class Station implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 站点标识
|
||||
*/
|
||||
private String station_id;
|
||||
|
||||
/**
|
||||
* 站点编码 对应地图上站点
|
||||
*/
|
||||
private String station_code;
|
||||
|
||||
/**
|
||||
* 站点别名
|
||||
*/
|
||||
private String station_name;
|
||||
|
||||
/**
|
||||
* 动作类型
|
||||
*/
|
||||
private String action_type;
|
||||
|
||||
/**
|
||||
* x坐标
|
||||
*/
|
||||
private Double x;
|
||||
|
||||
/**
|
||||
* y坐标
|
||||
*/
|
||||
private Double y;
|
||||
|
||||
/**
|
||||
* 角度
|
||||
*/
|
||||
private Double angle;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package org.nl.apt15e.apt.teaching.rest;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.nl.apt15e.apt.teaching.service.TeachingService;
|
||||
import org.nl.apt15e.common.logging.annotation.Log;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/7/3
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/teaching")
|
||||
public class TeachingController {
|
||||
|
||||
@Resource
|
||||
private TeachingService teachingService;
|
||||
|
||||
|
||||
@PostMapping("/startMapping")
|
||||
// @Log("开始建图")
|
||||
private ResponseEntity<Object> startMapping(@RequestParam("mapName") String mapName) {
|
||||
return new ResponseEntity<>(teachingService.startMapping(mapName), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/stopMapping")
|
||||
private ResponseEntity<Object> stopMapping() {
|
||||
return new ResponseEntity<>(teachingService.stopMapping(), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/setStation")
|
||||
private ResponseEntity<Object> setStation(@RequestParam("stationName") String stationName) {
|
||||
return new ResponseEntity<>(teachingService.setStation(stationName), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/deployRunMap")
|
||||
private ResponseEntity<Object> deployRunMap(@RequestParam("mapName") String mapName) {
|
||||
return new ResponseEntity<>(teachingService.deployRunMap(mapName), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/changeCurrentRunMap")
|
||||
private ResponseEntity<Object> changeCurrentRunMap(@RequestParam("mapName") String mapName) {
|
||||
return new ResponseEntity<>(teachingService.changeCurrentRunMap(mapName), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/getLocalMaps")
|
||||
private ResponseEntity<Object> getLocalMaps() {
|
||||
return new ResponseEntity<>(teachingService.getLocalMaps(), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/getRunMapZip")
|
||||
private ResponseEntity<Object> getRunMapZip(@RequestParam("mapName") String mapName) {
|
||||
return new ResponseEntity<>(teachingService.getRunMapZip(mapName), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/synchronizeMap")
|
||||
private ResponseEntity<Object> synchronizeMap(@RequestParam("mapName") String mapName) {
|
||||
return new ResponseEntity<>(teachingService.synchronizeMap(mapName), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/restart")
|
||||
private ResponseEntity<Object> restart() {
|
||||
return new ResponseEntity<>(teachingService.restart(), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/relocate")
|
||||
private ResponseEntity<Object> relocate(@RequestParam("x") Double x, @RequestParam("y") Double y, @RequestParam("angle") Double angle) {
|
||||
return new ResponseEntity<>(teachingService.relocate(x, y, angle), HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package org.nl.apt15e.apt.teaching.service;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/7/3
|
||||
*/
|
||||
public interface TeachingService {
|
||||
|
||||
/**
|
||||
* 开始建图
|
||||
*/
|
||||
Map<String, Object> startMapping(String mapName);
|
||||
|
||||
/**
|
||||
* 切手动
|
||||
*/
|
||||
Map<String, Object> startManual();
|
||||
|
||||
/**
|
||||
* 切自动
|
||||
*/
|
||||
Map<String, Object> stopManual();
|
||||
|
||||
/**
|
||||
* 结束建图
|
||||
*/
|
||||
Map<String, Object> stopMapping();
|
||||
|
||||
/**
|
||||
* 建图过程中设置站点
|
||||
*/
|
||||
Map<String, Object> setStation(String stationName);
|
||||
|
||||
/**
|
||||
* 获取后台地图列表
|
||||
*/
|
||||
Map<String, Object> getLocalMaps();
|
||||
|
||||
/**
|
||||
* 部署地图
|
||||
* @param mapName
|
||||
* @return
|
||||
*/
|
||||
Map<String, Object> deployRunMap(String mapName);
|
||||
|
||||
/**
|
||||
* 应用地图
|
||||
* @param mapName
|
||||
* @return
|
||||
*/
|
||||
Map<String, Object> changeCurrentRunMap(String mapName);
|
||||
|
||||
/**
|
||||
* 获取主机地图包
|
||||
* @param mapName
|
||||
* @return
|
||||
*/
|
||||
File getRunMapZip(String mapName);
|
||||
|
||||
/**
|
||||
* 同步地图到调度
|
||||
*/
|
||||
Map<String, Object> synchronizeMap(String mapName);
|
||||
|
||||
/**
|
||||
* 重定位
|
||||
* @param x
|
||||
* @param y
|
||||
* @param angle
|
||||
* @return
|
||||
*/
|
||||
Map<String, Object> relocate(Double x,Double y,Double angle);
|
||||
|
||||
/**
|
||||
* 重启车辆后台程序
|
||||
*/
|
||||
Map<String, Object> restart();
|
||||
}
|
||||
@@ -0,0 +1,350 @@
|
||||
package org.nl.apt15e.apt.teaching.service.impl;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.ZipUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nl.apt15e.apt.dao.VehicleException;
|
||||
import org.nl.apt15e.apt.dao.VehicleInfo;
|
||||
import org.nl.apt15e.apt.teaching.service.TeachingService;
|
||||
import org.nl.apt15e.common.BadRequestException;
|
||||
import org.nl.apt15e.util.HTTPUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/7/3
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class TeachingServiceImpl implements TeachingService {
|
||||
|
||||
@Override
|
||||
public Map<String, Object> startMapping(String mapName) {
|
||||
if ("".equals(mapName)){
|
||||
throw new BadRequestException("mapName is empty");
|
||||
}
|
||||
JSONObject params = new JSONObject();
|
||||
params.put("name", mapName);
|
||||
HttpResponse response = null;
|
||||
try {
|
||||
response = HTTPUtil.post("http://192.168.100.82:9998","/tool/rob/startMapping", params);
|
||||
} catch (Exception e) {
|
||||
log.info("访问车体开始建图接口报错:{}",e.getMessage());
|
||||
throw new BadRequestException("开始建图失败");
|
||||
}
|
||||
// 检查响应状态码
|
||||
if (response.isOk()) {
|
||||
// 获取响应体内容
|
||||
JSONObject body = JSON.parseObject(response.body());
|
||||
log.info("开始建图:{}",body);
|
||||
if ("200".equals(body.getString("code"))){
|
||||
body =(JSONObject) this.startManual();
|
||||
}
|
||||
return body;
|
||||
}
|
||||
log.info("开始建图失败");
|
||||
throw new BadRequestException("开始建图失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> startManual() {
|
||||
HttpResponse response = null;
|
||||
try {
|
||||
response = HTTPUtil.post("http://192.168.100.82:9998","/tool/rob/startManual", new JSONObject());
|
||||
} catch (Exception e) {
|
||||
log.info("访问车体切手动接口报错:{}",e.getMessage());
|
||||
throw new BadRequestException("切手动失败");
|
||||
}
|
||||
// 检查响应状态码
|
||||
if (response.isOk()) {
|
||||
// 获取响应体内容
|
||||
JSONObject body = JSON.parseObject(response.body());
|
||||
log.info("切手动:{}",body);
|
||||
return body;
|
||||
}
|
||||
log.info("切手动失败");
|
||||
throw new BadRequestException("切手动失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> stopManual() {
|
||||
HttpResponse response = null;
|
||||
try {
|
||||
response = HTTPUtil.post("http://192.168.100.82:9998","/tool/rob/stopManual", new JSONObject());
|
||||
} catch (Exception e) {
|
||||
log.info("访问车体切自动接口报错:{}",e.getMessage());
|
||||
throw new BadRequestException("切自动失败");
|
||||
}
|
||||
// 检查响应状态码
|
||||
if (response.isOk()) {
|
||||
// 获取响应体内容
|
||||
JSONObject body = JSON.parseObject(response.body());
|
||||
log.info("切自动:{}",body);
|
||||
return body;
|
||||
}
|
||||
log.info("切自动失败");
|
||||
throw new BadRequestException("切自动失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> stopMapping() {
|
||||
HttpResponse response = null;
|
||||
try {
|
||||
response = HTTPUtil.post("http://192.168.100.82:9998","/tool/rob/stopMapping", new JSONObject());
|
||||
} catch (Exception e) {
|
||||
log.info("访问车体结束建图接口报错:{}",e.getMessage());
|
||||
throw new BadRequestException("结束建图失败");
|
||||
}
|
||||
// 检查响应状态码
|
||||
if (response.isOk()) {
|
||||
// 获取响应体内容
|
||||
JSONObject body = JSON.parseObject(response.body());
|
||||
log.info("结束建图:{}",body);
|
||||
if ("200".equals(body.getString("code"))){
|
||||
body =(JSONObject) this.stopManual();
|
||||
}
|
||||
return body;
|
||||
}
|
||||
log.info("结束建图失败");
|
||||
throw new BadRequestException("结束建图失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> setStation(String stationName) {
|
||||
if ("".equals(stationName)){
|
||||
throw new BadRequestException("spotCode is empty");
|
||||
}
|
||||
JSONObject params = new JSONObject();
|
||||
params.put("spotCode", stationName);
|
||||
HttpResponse response = null;
|
||||
try {
|
||||
response = HTTPUtil.post("http://192.168.100.82:9998","/tool/rob/setStates", params);
|
||||
} catch (Exception e) {
|
||||
log.info("访问车体设置站点接口报错:{}",e.getMessage());
|
||||
throw new BadRequestException("设置站点失败");
|
||||
}
|
||||
// 检查响应状态码
|
||||
if (response.isOk()) {
|
||||
// 获取响应体内容
|
||||
JSONObject body = JSON.parseObject(response.body());
|
||||
log.info("设置站点:{}",body);
|
||||
return body;
|
||||
}
|
||||
log.info("设置站点失败");
|
||||
throw new BadRequestException("设置站点失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getLocalMaps() {
|
||||
HttpResponse response = null;
|
||||
try {
|
||||
response = HTTPUtil.get("http://192.168.100.82:9998","/tool/editor/getLocalMaps", new JSONObject());
|
||||
} catch (Exception e) {
|
||||
log.info("访问车体地图列表接口报错:{}",e.getMessage());
|
||||
throw new BadRequestException("获取地图列表失败");
|
||||
}
|
||||
// 检查响应状态码
|
||||
if (response.isOk()) {
|
||||
// 获取响应体内容
|
||||
JSONObject body = JSON.parseObject(response.body());
|
||||
log.info("获取地图列表:{}",body);
|
||||
return body;
|
||||
}
|
||||
log.info("获取地图列表失败");
|
||||
throw new BadRequestException("获取地图列表失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> deployRunMap(String mapName) {
|
||||
if ("".equals(mapName)){
|
||||
throw new BadRequestException("mapName is empty");
|
||||
}
|
||||
JSONObject params = new JSONObject();
|
||||
params.put("id", mapName);
|
||||
HttpResponse response = null;
|
||||
try {
|
||||
response = HTTPUtil.post("http://192.168.100.82:9998","/tool/rob/deployRunMap", params);
|
||||
} catch (Exception e) {
|
||||
log.info("访问车体部署地图接口报错:{}",e.getMessage());
|
||||
throw new BadRequestException("部署地图失败");
|
||||
}
|
||||
// 检查响应状态码
|
||||
if (response.isOk()) {
|
||||
// 获取响应体内容
|
||||
JSONObject body = JSON.parseObject(response.body());
|
||||
log.info("部署地图:{}",body);
|
||||
return body;
|
||||
}
|
||||
log.info("部署地图失败");
|
||||
throw new BadRequestException("部署地图失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> changeCurrentRunMap(String mapName) {
|
||||
if ("".equals(mapName)){
|
||||
throw new BadRequestException("mapName is empty");
|
||||
}
|
||||
JSONObject params = new JSONObject();
|
||||
params.put("name", mapName);
|
||||
HttpResponse response = null;
|
||||
try {
|
||||
response = HTTPUtil.post("http://192.168.100.82:9998","/tool/rob/changeCurrentRunMap", params);
|
||||
} catch (Exception e) {
|
||||
log.info("访问车体应用地图接口报错:{}",e.getMessage());
|
||||
throw new BadRequestException("应用地图失败");
|
||||
}
|
||||
// 检查响应状态码
|
||||
if (response.isOk()) {
|
||||
// 获取响应体内容
|
||||
JSONObject body = JSON.parseObject(response.body());
|
||||
log.info("应用地图:{}",body);
|
||||
return body;
|
||||
}
|
||||
log.info("应用地图失败");
|
||||
throw new BadRequestException("应用地图失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getRunMapZip(String mapName) {
|
||||
if ("".equals(mapName)){
|
||||
throw new BadRequestException("mapName is empty");
|
||||
}
|
||||
JSONObject params = new JSONObject();
|
||||
params.put("name", mapName);
|
||||
HttpResponse response = null;
|
||||
try {
|
||||
response = HTTPUtil.post("http://192.168.100.82:9998","/tool/rob/getRunMapZip", params);
|
||||
} catch (Exception e) {
|
||||
log.info("访问车体地图包接口报错:{}",e.getMessage());
|
||||
throw new BadRequestException("获取地图包失败");
|
||||
}
|
||||
// 检查响应状态码
|
||||
if (response.isOk()) {
|
||||
// 获取响应体内容
|
||||
// JSONObject body = JSON.parseObject(response.body());
|
||||
// 3. 将响应体写入临时ZIP文件
|
||||
byte[] zipBytes = response.bodyBytes();
|
||||
File fileName = new File(mapName);
|
||||
File tempZipFile = FileUtil.writeBytes(zipBytes, FileUtil.createTempFile(fileName));
|
||||
|
||||
// 4. 解压ZIP文件
|
||||
// File unzipDir = ZipUtil.unzip(tempZipFile, Charset.defaultCharset());
|
||||
|
||||
// 5. 处理解压后的文件
|
||||
// File[] files = unzipDir.listFiles();
|
||||
// if (files != null) {
|
||||
// for (File file : files) {
|
||||
// System.out.println("文件名: " + file.getName());
|
||||
// System.out.println("文件内容: ");
|
||||
// System.out.println(FileUtil.readUtf8String(file)); // 读取文本内容
|
||||
// // 如果是二进制文件,使用:FileUtil.readBytes(file)
|
||||
// }
|
||||
// }
|
||||
|
||||
// 6. 清理临时文件(可选)
|
||||
// FileUtil.del(tempZipFile);
|
||||
// FileUtil.del(unzipDir);
|
||||
log.info("获取地图包");
|
||||
return tempZipFile;
|
||||
}
|
||||
log.info("获取地图包失败");
|
||||
throw new BadRequestException("获取地图包失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> synchronizeMap(String mapName) {
|
||||
File zipFile = this.getRunMapZip(mapName);
|
||||
HttpResponse response = null;
|
||||
try {
|
||||
response = HttpRequest.post("http://192.168.100.82:8081/map/uploadFile")
|
||||
.setConnectionTimeout(3000)
|
||||
.setReadTimeout(3000)
|
||||
.header("token", "admin123")
|
||||
.header("name", "lx-script")
|
||||
.header("Content-Type", "multipart/form-data;charset=UTF-8")
|
||||
.form("areaId",1)
|
||||
.form("areaName","")
|
||||
.form("data",zipFile)
|
||||
.execute();
|
||||
} catch (Exception e) {
|
||||
log.info("同步地图到调度接口报错:{}",e.getMessage());
|
||||
throw new BadRequestException("同步地图失败");
|
||||
}
|
||||
// 检查响应状态码
|
||||
if (response.isOk()) {
|
||||
// 获取响应体内容
|
||||
JSONObject body = JSON.parseObject(response.body());
|
||||
log.info("同步地图:{}",body);
|
||||
return body;
|
||||
}
|
||||
log.info("同步地图失败");
|
||||
throw new BadRequestException("同步地图失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> relocate(Double x, Double y, Double angle) {
|
||||
if (ObjectUtil.isEmpty(x) || ObjectUtil.isEmpty(y) || ObjectUtil.isEmpty(angle)){
|
||||
throw new BadRequestException("params is empty");
|
||||
}
|
||||
JSONObject params = new JSONObject();
|
||||
params.put("x", x);
|
||||
params.put("y", y);
|
||||
params.put("angle", angle / 180.0 * Math.PI);
|
||||
params.put("noisyX", 0.5);
|
||||
params.put("noisyY", 0.5);
|
||||
params.put("noisyAngle", Math.PI);
|
||||
HttpResponse response = null;
|
||||
try {
|
||||
response = HTTPUtil.post("http://192.168.100.82:9998","/tool/rob/relocate", params);
|
||||
} catch (Exception e) {
|
||||
log.info("访问车体重定位接口报错:{}",e.getMessage());
|
||||
throw new BadRequestException("重定位失败");
|
||||
}
|
||||
// 检查响应状态码
|
||||
if (response.isOk()) {
|
||||
// 获取响应体内容
|
||||
JSONObject body = JSON.parseObject(response.body());
|
||||
log.info("重定位:{}",body);
|
||||
return body;
|
||||
}
|
||||
log.info("重定位失败");
|
||||
throw new BadRequestException("重定位失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> restart() {
|
||||
HttpResponse response = null;
|
||||
try {
|
||||
response = HTTPUtil.post("http://192.168.100.82:9998","/tool/rob/restart", new JSONObject());
|
||||
} catch (Exception e) {
|
||||
log.info("访问车体程序重启接口报错:{}",e.getMessage());
|
||||
throw new BadRequestException("车体程序重启失败");
|
||||
}
|
||||
// 检查响应状态码
|
||||
if (response.isOk()) {
|
||||
// 获取响应体内容
|
||||
JSONObject body = JSON.parseObject(response.body());
|
||||
log.info("车体程序重启:{}",body);
|
||||
return body;
|
||||
}
|
||||
log.info("车体程序重启失败");
|
||||
throw new BadRequestException("车体程序重启失败");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package org.nl.apt15e.apt.websocket;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.websocket.*;
|
||||
import javax.websocket.server.PathParam;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/7/3
|
||||
*/
|
||||
@Slf4j
|
||||
@ServerEndpoint("/webSocket/VehicleInfo/{sid}")
|
||||
@Component
|
||||
public class WebSocketVehicleServer {
|
||||
|
||||
/**
|
||||
* concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
|
||||
*/
|
||||
private static CopyOnWriteArraySet<WebSocketVehicleServer> webSocketSet = new CopyOnWriteArraySet<>();
|
||||
|
||||
/**
|
||||
* 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
|
||||
*/
|
||||
private static int onlineCount = 0;
|
||||
|
||||
|
||||
/**
|
||||
* 与某个客户端的连接会话,需要通过它来给客户端发送数据
|
||||
*/
|
||||
private Session session;
|
||||
/**
|
||||
* 接收userId
|
||||
*/
|
||||
private String sid = "";
|
||||
|
||||
/**
|
||||
* 连接建立成功调用的方法
|
||||
*/
|
||||
@OnOpen
|
||||
public void onOpen(Session session, @PathParam("sid") String sid) {
|
||||
this.session = session;
|
||||
//如果存在就先删除一个,防止重复推送消息
|
||||
webSocketSet.removeIf(webSocket -> webSocket.sid.equals(sid));
|
||||
webSocketSet.add(this);
|
||||
//在线数加1
|
||||
addOnlineCount();
|
||||
log.info("VehicleWS:sid{}连接成功,当前在线人数为{}", sid, getOnlineCount());
|
||||
this.sid = sid;
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接关闭调用的方法
|
||||
*/
|
||||
@OnClose
|
||||
public void onClose() {
|
||||
webSocketSet.remove(this);
|
||||
//在线数减1
|
||||
subOnlineCount();
|
||||
log.info("VehicleWS:sid{}关闭连接!当前在线人数为{}", sid, getOnlineCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* 收到客户端消息后调用的方法
|
||||
*
|
||||
* @param message 客户端发送过来的消息
|
||||
*/
|
||||
@OnMessage
|
||||
public void onMessage(String message, Session session) {
|
||||
//System.out.println(webSocketSet.size() + "_接收到消息_" + session.getId());
|
||||
}
|
||||
|
||||
@OnError
|
||||
public void onError(Session session, Throwable error) {
|
||||
//log.error("发生错误");
|
||||
webSocketSet.remove(session);
|
||||
error.printStackTrace();
|
||||
}
|
||||
|
||||
public Session getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
// 发送消息,在定时任务中会调用此方法
|
||||
public void sendMessage(String message) throws IOException {
|
||||
this.session.getBasicRemote().sendText(message);
|
||||
}
|
||||
|
||||
|
||||
public void sendDataToClient(Map<String, Object> data) {
|
||||
try {
|
||||
if (this.session != null&& MapUtil.isNotEmpty(data)) {
|
||||
this.session.getBasicRemote().sendText(JSON.toJSONString(data));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("发送消息给客户端失败", e);
|
||||
}
|
||||
}
|
||||
public static synchronized int getOnlineCount() {
|
||||
return onlineCount;
|
||||
}
|
||||
|
||||
public static CopyOnWriteArraySet<WebSocketVehicleServer> getWebSocketSet() {
|
||||
return webSocketSet;
|
||||
}
|
||||
|
||||
|
||||
public void setSession(Session session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
public static synchronized void addOnlineCount() {
|
||||
WebSocketVehicleServer.onlineCount++;
|
||||
}
|
||||
|
||||
public static synchronized void subOnlineCount() {
|
||||
WebSocketVehicleServer.onlineCount--;
|
||||
}
|
||||
}
|
||||
25
src/main/java/org/nl/apt15e/common/BadRequestException.java
Normal file
25
src/main/java/org/nl/apt15e/common/BadRequestException.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package org.nl.apt15e.common;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/7/3
|
||||
*/
|
||||
@Getter
|
||||
public class BadRequestException extends RuntimeException{
|
||||
|
||||
private Integer status = BAD_REQUEST.value();
|
||||
|
||||
public BadRequestException(String msg){
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public BadRequestException(HttpStatus status, String msg){
|
||||
super(msg);
|
||||
this.status = status.value();
|
||||
}
|
||||
}
|
||||
49
src/main/java/org/nl/apt15e/common/exception/ApiError.java
Normal file
49
src/main/java/org/nl/apt15e/common/exception/ApiError.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.nl.apt15e.common.exception;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
class ApiError {
|
||||
|
||||
private Integer code = 400;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime Date;
|
||||
private String message;
|
||||
|
||||
private ApiError() {
|
||||
Date = LocalDateTime.now();
|
||||
}
|
||||
|
||||
public static ApiError error(String message){
|
||||
ApiError apiError = new ApiError();
|
||||
apiError.setMessage(message);
|
||||
return apiError;
|
||||
}
|
||||
|
||||
public static ApiError error(Integer status, String message){
|
||||
ApiError apiError = new ApiError();
|
||||
apiError.setCode(status);
|
||||
apiError.setMessage(message);
|
||||
return apiError;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package org.nl.apt15e.common.exception;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nl.apt15e.common.BadRequestException;
|
||||
import org.nl.apt15e.util.ThrowableUtil;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
/**
|
||||
* @author liejiu
|
||||
*/
|
||||
@Slf4j
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
/**
|
||||
* 处理所有不可知的异常
|
||||
*/
|
||||
@ExceptionHandler(Throwable.class)
|
||||
public ResponseEntity<ApiError> handleException(Throwable e){
|
||||
// 打印堆栈信息
|
||||
log.error(ThrowableUtil.getStackTrace(e));
|
||||
return buildResponseEntity(ApiError.error(e.getMessage()));
|
||||
}
|
||||
|
||||
/**
|
||||
* token 无效的异常拦截
|
||||
* @param e
|
||||
* @return
|
||||
*/
|
||||
// @ExceptionHandler(value = NotLoginException.class)
|
||||
// public ResponseEntity<ApiError> notLoginException(Exception e) {
|
||||
//// log.error(ThrowableUtil.getStackTrace(e));
|
||||
// return buildResponseEntity(ApiError.error(401,"token 失效"));
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* 处理自定义异常
|
||||
*/
|
||||
@ExceptionHandler(value = BadRequestException.class)
|
||||
public ResponseEntity<ApiError> badRequestException(BadRequestException e) {
|
||||
// 打印堆栈信息
|
||||
log.error(ThrowableUtil.getStackTrace(e));
|
||||
log.info(e.getMessage());
|
||||
return buildResponseEntity(ApiError.error(e.getStatus(),e.getMessage()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 处理所有接口数据验证异常
|
||||
*/
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public ResponseEntity<ApiError> handleMethodArgumentNotValidException(MethodArgumentNotValidException e){
|
||||
// 打印堆栈信息
|
||||
log.error(ThrowableUtil.getStackTrace(e));
|
||||
String[] str = Objects.requireNonNull(e.getBindingResult().getAllErrors().get(0).getCodes())[1].split("\\.");
|
||||
String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
|
||||
String msg = "不能为空";
|
||||
if(msg.equals(message)){
|
||||
message = str[1] + ":" + message;
|
||||
}
|
||||
return buildResponseEntity(ApiError.error(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一返回
|
||||
*/
|
||||
private ResponseEntity<ApiError> buildResponseEntity(ApiError apiError) {
|
||||
return new ResponseEntity<>(apiError, HttpStatus.valueOf(apiError.getCode()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.nl.apt15e.common.logging.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/7/3
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Log {
|
||||
String value() default "";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package org.nl.apt15e.common.logging.aspect;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.Signature;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/7/3
|
||||
*/
|
||||
@Slf4j
|
||||
@Aspect
|
||||
@Component
|
||||
public class LogAspect {
|
||||
|
||||
/**
|
||||
* 配置切入点
|
||||
*/
|
||||
@Pointcut("@annotation(org.nl.apt15e.common.logging.annotation.Log)")
|
||||
public void logPointCut(){}
|
||||
|
||||
/**
|
||||
* 环绕通知
|
||||
* @param joinPoint
|
||||
* @return
|
||||
* @throws Throwable
|
||||
*/
|
||||
@Around("logPointCut()")
|
||||
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
// MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||
// Method method = signature.getMethod();
|
||||
// String className = joinPoint.getTarget().getClass().getName();
|
||||
// 方法路径
|
||||
// String methodName = joinPoint.getTarget().getClass().getName() + "." + signature.getName() + "()";
|
||||
// String params = JSONObject.toJSONString(joinPoint.getArgs());
|
||||
|
||||
|
||||
Object result;
|
||||
// log.info("【日志注解】开始执行 -- {}:{} {}", className, "111", params);
|
||||
result = joinPoint.proceed();
|
||||
// log.info("返回参数:{}" ,JSONObject.toJSONString(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.nl.apt15e.config.thread;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.AsyncConfigurer;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
/**
|
||||
* 异步任务线程池装配类
|
||||
*
|
||||
* @author https://juejin.im/entry/5abb8f6951882555677e9da2
|
||||
* @date 2019年10月31日15:06:18
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@EnableAsync
|
||||
public class AsyncTaskExecutePool implements AsyncConfigurer{
|
||||
|
||||
@Override
|
||||
public Executor getAsyncExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
//核心线程池大小
|
||||
executor.setCorePoolSize(20);
|
||||
//最大线程数
|
||||
executor.setMaxPoolSize(50);
|
||||
//队列容量
|
||||
executor.setQueueCapacity(50);
|
||||
//活跃时间
|
||||
executor.setKeepAliveSeconds(60);
|
||||
//线程名字前缀
|
||||
executor.setThreadNamePrefix("Async-");
|
||||
// setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务
|
||||
// CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
|
||||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 线程池配置
|
||||
*/
|
||||
@Bean(name = "asynchronousTasks")
|
||||
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
|
||||
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
|
||||
// 核心线程池大小
|
||||
threadPoolTaskExecutor.setCorePoolSize(20);
|
||||
// 最大线程数
|
||||
threadPoolTaskExecutor.setMaxPoolSize(50);
|
||||
// 队列容量
|
||||
threadPoolTaskExecutor.setQueueCapacity(50);
|
||||
// 活跃时间
|
||||
threadPoolTaskExecutor.setKeepAliveSeconds(60);
|
||||
// 主线程等待子线程执行时间
|
||||
threadPoolTaskExecutor.setAwaitTerminationSeconds(50);
|
||||
// threadPoolTaskExecutor.setAwaitTerminationSeconds(30);
|
||||
// 线程名字前缀
|
||||
threadPoolTaskExecutor.setThreadNamePrefix("apt-thread-");
|
||||
// RejectedExecutionHandler:当pool已经达到max-size的时候,如何处理新任务
|
||||
// CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
|
||||
threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||
// 初始化
|
||||
threadPoolTaskExecutor.initialize();
|
||||
return threadPoolTaskExecutor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.nl.apt15e.config.thread;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/7/3
|
||||
*/
|
||||
@Configuration
|
||||
public class WebSocketConfig {
|
||||
|
||||
@Bean
|
||||
public ServerEndpointExporter serverEndpointExporter() {
|
||||
return new ServerEndpointExporter();
|
||||
}
|
||||
|
||||
}
|
||||
40
src/main/java/org/nl/apt15e/util/HTTPUtil.java
Normal file
40
src/main/java/org/nl/apt15e/util/HTTPUtil.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package org.nl.apt15e.util;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/7/2
|
||||
*/
|
||||
@Slf4j
|
||||
public class HTTPUtil {
|
||||
|
||||
public static HttpResponse post(String url, String method, JSONObject params)throws Exception{
|
||||
String sendUrl = url + method;
|
||||
return HttpRequest.post(sendUrl)
|
||||
.setConnectionTimeout(3000)
|
||||
.setReadTimeout(3000)
|
||||
.header("token", "admin123")
|
||||
.header("name", "lx-script")
|
||||
.header("Content-Type", "application/json")
|
||||
.body(String.valueOf(params))
|
||||
.execute();
|
||||
|
||||
}
|
||||
|
||||
public static HttpResponse get(String url, String method, JSONObject params)throws Exception{
|
||||
String sendUrl = url + method;
|
||||
return HttpRequest.get(sendUrl)
|
||||
.setConnectionTimeout(3000)
|
||||
.setReadTimeout(3000)
|
||||
.header("token", "admin123")
|
||||
.header("name", "lx-script")
|
||||
.header("Content-Type", "application/json")
|
||||
.form(params)
|
||||
.execute();
|
||||
|
||||
}
|
||||
}
|
||||
22
src/main/java/org/nl/apt15e/util/ThrowableUtil.java
Normal file
22
src/main/java/org/nl/apt15e/util/ThrowableUtil.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package org.nl.apt15e.util;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
|
||||
/**
|
||||
* @author liejiu
|
||||
*/
|
||||
public class ThrowableUtil {
|
||||
|
||||
/**
|
||||
* 获取堆栈信息
|
||||
*/
|
||||
public static String getStackTrace(Throwable throwable){
|
||||
StringWriter sw = new StringWriter();
|
||||
try (PrintWriter pw = new PrintWriter(sw)) {
|
||||
throwable.printStackTrace(pw);
|
||||
return sw.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
8
src/main/resources/banner.txt
Normal file
8
src/main/resources/banner.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
_ _ ___________ _ _____ _ ___________ _____
|
||||
| \ | | _ | ___ \ | | ___| | | ___| ___|_ _|
|
||||
| \| | | | | |_/ / | | |__ | | | |__ | |_ | |
|
||||
| . ` | | | | ___ \ | | __|| | | __|| _| | |
|
||||
| |\ \ \_/ / |_/ / |____| |___| |____| |___| | | |
|
||||
\_| \_/\___/\____/\_____/\____/\_____/\____/\_| \_/
|
||||
|
||||
:: Spring Boot :: (v2.6.13.RELEASE)
|
||||
52
src/main/resources/config/application-dev.yml
Normal file
52
src/main/resources/config/application-dev.yml
Normal file
@@ -0,0 +1,52 @@
|
||||
server:
|
||||
# 端口
|
||||
port: 8081
|
||||
spring:
|
||||
datasource:
|
||||
druid:
|
||||
db-type: com.alibaba.druid.pool.DruidDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://localhost:3306/apt_data?serverTimezone=GMT%2B8&characterEncoding=utf-8&userSSL=false
|
||||
username: root
|
||||
password: 123456
|
||||
# 初始连接数
|
||||
initial-size: 5
|
||||
# 最小连接数
|
||||
min-idle: 15
|
||||
# 最大连接数
|
||||
max-active: 30
|
||||
# 超时时间(以秒数为单位)
|
||||
remove-abandoned-timeout: 180
|
||||
# 获取连接超时时间
|
||||
max-wait: 3000
|
||||
# 连接有效性检测时间
|
||||
time-between-eviction-runs-millis: 60000
|
||||
# 连接在池中最小生存的时间
|
||||
min-evictable-idle-time-millis: 300000
|
||||
# 连接在池中最大生存的时间
|
||||
max-evictable-idle-time-millis: 900000
|
||||
# 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除
|
||||
test-while-idle: true
|
||||
# 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个
|
||||
test-on-borrow: true
|
||||
# 是否在归还到池中前进行检验
|
||||
test-on-return: false
|
||||
# 检测连接是否有效
|
||||
validation-query: select 1
|
||||
# 配置监控统计
|
||||
webStatFilter:
|
||||
enabled: true
|
||||
stat-view-servlet:
|
||||
enabled: true
|
||||
url-pattern: /druid/*
|
||||
reset-enable: false
|
||||
filter:
|
||||
stat:
|
||||
enabled: true
|
||||
# 记录慢SQL
|
||||
log-slow-sql: true
|
||||
slow-sql-millis: 1000
|
||||
merge-sql: true
|
||||
wall:
|
||||
config:
|
||||
multi-statement-allow: true
|
||||
52
src/main/resources/config/application-pro.yml
Normal file
52
src/main/resources/config/application-pro.yml
Normal file
@@ -0,0 +1,52 @@
|
||||
server:
|
||||
# 端口
|
||||
port: 8081
|
||||
spring:
|
||||
datasource:
|
||||
druid:
|
||||
db-type: com.alibaba.druid.pool.DruidDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://localhost:3306/apt_data?serverTimezone=GMT%2B8&characterEncoding=utf-8&userSSL=false
|
||||
username: root
|
||||
password: 123456
|
||||
# 初始连接数
|
||||
initial-size: 5
|
||||
# 最小连接数
|
||||
min-idle: 15
|
||||
# 最大连接数
|
||||
max-active: 30
|
||||
# 超时时间(以秒数为单位)
|
||||
remove-abandoned-timeout: 180
|
||||
# 获取连接超时时间
|
||||
max-wait: 3000
|
||||
# 连接有效性检测时间
|
||||
time-between-eviction-runs-millis: 60000
|
||||
# 连接在池中最小生存的时间
|
||||
min-evictable-idle-time-millis: 300000
|
||||
# 连接在池中最大生存的时间
|
||||
max-evictable-idle-time-millis: 900000
|
||||
# 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除
|
||||
test-while-idle: true
|
||||
# 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个
|
||||
test-on-borrow: true
|
||||
# 是否在归还到池中前进行检验
|
||||
test-on-return: false
|
||||
# 检测连接是否有效
|
||||
validation-query: select 1
|
||||
# 配置监控统计
|
||||
webStatFilter:
|
||||
enabled: true
|
||||
stat-view-servlet:
|
||||
enabled: true
|
||||
url-pattern: /druid/*
|
||||
reset-enable: false
|
||||
filter:
|
||||
stat:
|
||||
enabled: true
|
||||
# 记录慢SQL
|
||||
log-slow-sql: true
|
||||
slow-sql-millis: 1000
|
||||
merge-sql: true
|
||||
wall:
|
||||
config:
|
||||
multi-statement-allow: true
|
||||
18
src/main/resources/config/application.yml
Normal file
18
src/main/resources/config/application.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
spring:
|
||||
profiles:
|
||||
active: dev
|
||||
jackson:
|
||||
time-zone: GMT+8
|
||||
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
map-underscore-to-camel-case: false
|
||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
mapper-locations: classpath*:/mapper/**/*.xml
|
||||
global-config:
|
||||
banner: false
|
||||
|
||||
logging:
|
||||
file:
|
||||
path: logs
|
||||
config: classpath:logback-spring.xml
|
||||
69
src/main/resources/logback-spring.xml
Normal file
69
src/main/resources/logback-spring.xml
Normal file
@@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!-- 级别[ALL< Trace < DEBUG < INFO < WARN < ERROR < FATAL < OFF] -->
|
||||
<!-- monitorInterval(单位s)指定log4j自动重新配置的监测间隔时间-->
|
||||
<configuration scan="true" scanPeriod="30 seconds" debug="false">
|
||||
<property name="log.charset" value="utf-8"/>
|
||||
<property name="log.pattern" value="%black(nlAdmin-) %red(%d{yyyy-MM-dd HH:mm:ss.SSS}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36} - %method) - %white(%msg%n)"/>
|
||||
<SpringProperty scope="context" name="logPath" source="logging.file.path" defaultValue="logs"/>
|
||||
<property name="LOG_HOME" value="${logPath}"/>
|
||||
|
||||
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<level>INFO</level>
|
||||
</filter>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
<charset>${log.charset}</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 系统日志输出 appender class 中的log.pattern 表示日志滚动输出 -->
|
||||
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!-- 日志首次输出的文件地址 -->
|
||||
<!-- <file>${LOG_HOME}/info.log</file>-->
|
||||
<!-- 滚动输出策略:基于时间创建日志文件 ,这样第二天输出的日志,就会按照 fileNamePattern 新建日志文件 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${LOG_HOME}/root/info.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>30</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<!-- 日志内容输出格式设置为定义好的 log.pattern-->
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
|
||||
<charset>${log.charset}</charset>
|
||||
</encoder>
|
||||
<!-- 日志内容输出过滤器 -->
|
||||
<!-- <filter class="ch.qos.logback.classic.filter.LevelFilter">-->
|
||||
<!-- <!– 过滤的级别 –>-->
|
||||
<!-- <level>INFO</level>-->
|
||||
<!-- <!– 匹配时的操作:接收(记录) –>-->
|
||||
<!-- <onMatch>ACCEPT</onMatch>-->
|
||||
<!-- <!– 不匹配时的操作:拒绝(不记录) –>-->
|
||||
<!-- <onMismatch>DENY</onMismatch>-->
|
||||
<!-- </filter>-->
|
||||
</appender>
|
||||
|
||||
<!-- <appender name="async" class="ch.qos.logback.classic.AsyncAppender">-->
|
||||
<!-- <!– 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 –>-->
|
||||
<!-- <discardingThreshold>0</discardingThreshold>-->
|
||||
<!-- <queueSize>256</queueSize>-->
|
||||
<!-- <appender-ref ref="console"/>-->
|
||||
<!-- </appender>-->
|
||||
|
||||
<!-- <appender name="async_file_info" class="ch.qos.logback.classic.AsyncAppender">-->
|
||||
<!-- <discardingThreshold>0</discardingThreshold>-->
|
||||
<!-- <queueSize>256</queueSize>-->
|
||||
<!-- <appender-ref ref="file_info"/>-->
|
||||
<!-- </appender>-->
|
||||
|
||||
<!--系统操作日志 root 根路径的日志级别 info -->
|
||||
<root level="info">
|
||||
<!-- 将定义好的几个日志输出 追加到 root 上 -->
|
||||
<!-- <appender-ref ref="console"/>-->
|
||||
<appender-ref ref="console" />
|
||||
<!-- <appender-ref ref="async_file_info" />-->
|
||||
</root>
|
||||
</configuration>
|
||||
13
src/test/java/org/nl/apt15e/Apt15EApplicationTests.java
Normal file
13
src/test/java/org/nl/apt15e/Apt15EApplicationTests.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package org.nl.apt15e;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
@SpringBootTest
|
||||
class Apt15EApplicationTests {
|
||||
|
||||
@Test
|
||||
void contextLoads() {
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user