commit 2d5ce99c310b73bdcfad053c7c34d3f4b087a609
Author: 熟小柿 <15150590045@163.com>
Date: Wed Jan 17 16:21:36 2024 +0800
wcs回调项目 20240117-适配好工品项目
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7086a64
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,38 @@
+*.class
+
+# maven ignore
+target/
+*.jar
+*.war
+*.zip
+*.tar
+*.tar.gz
+
+# eclipse ignore
+.externalToolBuilders
+.springBeans
+
+# idea ignore
+.idea/
+*.ipr
+*.iml
+*.iws
+
+# temp ignore
+*.log
+*.cache
+*.diff
+*.patch
+*.tmp
+
+# system ignore
+.DS_Store
+Thumbs.db
+
+# custom lib
+!custom_lib/*
+/bin
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+/.factorypath
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..cfd7fe4
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,93 @@
+
+
+ 4.0.0
+
+ com.wcs.back
+ wcsBack
+ 1.0
+ jar
+
+
+ wcs回调服务
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.4
+
+
+
+
+ 1.8
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+ io.swagger
+ swagger-models
+ 1.6.2
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+ org.apache.commons
+ commons-lang3
+ 3.4
+
+
+
+ org.apache.httpcomponents
+ httpclient
+ 4.5.13
+
+
+ org.apache.httpcomponents
+ httpcore
+
+
+
+
+ com.alibaba.fastjson2
+ fastjson2
+ 2.0.25
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/wcs/back/WmsApplication.java b/src/main/java/com/wcs/back/WmsApplication.java
new file mode 100644
index 0000000..bb9ed27
--- /dev/null
+++ b/src/main/java/com/wcs/back/WmsApplication.java
@@ -0,0 +1,35 @@
+package com.wcs.back;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.env.Environment;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * 启动程序
+ *
+ * @author wms
+ */
+@Slf4j
+@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
+public class WmsApplication {
+ public static void main(String[] args) throws UnknownHostException {
+ // System.setProperty("spring.devtools.restart.enabled", "false");
+ ConfigurableApplicationContext application = SpringApplication.run(WmsApplication.class, args);
+ System.out.println("=====================wms启动成功=====================");
+ Environment env = application.getEnvironment();
+ String host = InetAddress.getLocalHost().getHostAddress();
+ String port = env.getProperty("server.port");
+ log.info("\n----------------------------------------------------------\n\t" +
+ "Application Declare is running! Access URLs:\n\t" +
+ "Local: \t\t\thttp://localhost:" + port + "\n\t" +
+ "External: \t\thttp://" + host + ":" + port + "\n\t" +
+ "Swagger-UI: \thttp://" + host + ":" + port + "/doc.html\n" +
+ "----------------------------------------------------------");
+ }
+}
diff --git a/src/main/java/com/wcs/back/constant/CacheConstants.java b/src/main/java/com/wcs/back/constant/CacheConstants.java
new file mode 100644
index 0000000..d319258
--- /dev/null
+++ b/src/main/java/com/wcs/back/constant/CacheConstants.java
@@ -0,0 +1,43 @@
+package com.wcs.back.constant;
+
+/**
+ * 缓存的key 常量
+ *
+ * @author wms
+ */
+public class CacheConstants {
+ /**
+ * 登录用户 redis key
+ */
+ public static final String LOGIN_TOKEN_KEY = "login_tokens:";
+
+ /**
+ * 验证码 redis key
+ */
+ public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
+
+ /**
+ * 参数管理 cache key
+ */
+ public static final String SYS_CONFIG_KEY = "sys_config:";
+
+ /**
+ * 字典管理 cache key
+ */
+ public static final String SYS_DICT_KEY = "sys_dict:";
+
+ /**
+ * 防重提交 redis key
+ */
+ public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
+
+ /**
+ * 限流 redis key
+ */
+ public static final String RATE_LIMIT_KEY = "rate_limit:";
+
+ /**
+ * 登录账户密码错误次数 redis key
+ */
+ public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
+}
diff --git a/src/main/java/com/wcs/back/constant/Constants.java b/src/main/java/com/wcs/back/constant/Constants.java
new file mode 100644
index 0000000..da6438a
--- /dev/null
+++ b/src/main/java/com/wcs/back/constant/Constants.java
@@ -0,0 +1,155 @@
+package com.wcs.back.constant;
+
+/**
+ * 通用常量信息
+ *
+ * @author wms
+ */
+public class Constants {
+ /**
+ * UTF-8 字符集
+ */
+ public static final String UTF8 = "UTF-8";
+
+ /**
+ * GBK 字符集
+ */
+ public static final String GBK = "GBK";
+
+ /**
+ * www主域
+ */
+ public static final String WWW = "www.";
+
+ /**
+ * http请求
+ */
+ public static final String HTTP = "http://";
+
+ /**
+ * https请求
+ */
+ public static final String HTTPS = "https://";
+
+ /**
+ * 通用成功标识
+ */
+ public static final String SUCCESS = "0";
+
+ /**
+ * 通用失败标识
+ */
+ public static final String FAIL = "1";
+
+ /**
+ * 登录成功
+ */
+ public static final String LOGIN_SUCCESS = "Success";
+
+ /**
+ * 注销
+ */
+ public static final String LOGOUT = "Logout";
+
+ /**
+ * 注册
+ */
+ public static final String REGISTER = "Register";
+
+ /**
+ * 登录失败
+ */
+ public static final String LOGIN_FAIL = "Error";
+
+ /**
+ * 验证码有效期(分钟)
+ */
+ public static final Integer CAPTCHA_EXPIRATION = 2;
+
+ /**
+ * 令牌
+ */
+ public static final String TOKEN = "token";
+
+ /**
+ * 令牌前缀
+ */
+ public static final String TOKEN_PREFIX = "Bearer ";
+
+ /**
+ * 令牌前缀
+ */
+ public static final String LOGIN_USER_KEY = "login_user_key";
+
+ /**
+ * 用户ID
+ */
+ public static final String JWT_USERID = "userid";
+
+ /**
+ * 用户名称
+ */
+ public static final String JWT_USERNAME = "userName";
+
+ /**
+ * 用户头像
+ */
+ public static final String JWT_AVATAR = "avatar";
+
+ /**
+ * 创建时间
+ */
+ public static final String JWT_CREATED = "created";
+
+ /**
+ * 用户权限
+ */
+ public static final String JWT_AUTHORITIES = "authorities";
+
+ /**
+ * 资源映射路径 前缀
+ */
+ public static final String RESOURCE_PREFIX = "/profile";
+
+ /**
+ * RMI 远程方法调用
+ */
+ public static final String LOOKUP_RMI = "rmi:";
+
+ /**
+ * LDAP 远程方法调用
+ */
+ public static final String LOOKUP_LDAP = "ldap:";
+
+ /**
+ * LDAPS 远程方法调用
+ */
+ public static final String LOOKUP_LDAPS = "ldaps:";
+
+ /**
+ * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
+ */
+ public static final String[] JOB_WHITELIST_STR = {"com.wms"};
+
+ /**
+ * 定时任务违规的字符
+ */
+ public static final String[] JOB_ERROR_STR = {"java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
+ "org.springframework", "org.apache", "com.wms.common.utils.file", "com.wms.common.config"};
+
+
+ /**
+ * 获取token失败
+ */
+ public static final String GET_TOKEN_FAIL = "getTokenError";
+
+ /**
+ * ERP token失效时间(小时)
+ */
+ public static final Integer ERP_TOKEN_EXPIRATION = 24;
+
+ /**
+ * erp令牌前缀
+ */
+ public static final String ERP_GET_TOKEN_KEY = "erp_get_token_key";
+}
diff --git a/src/main/java/com/wcs/back/constant/GenConstants.java b/src/main/java/com/wcs/back/constant/GenConstants.java
new file mode 100644
index 0000000..d7e0db2
--- /dev/null
+++ b/src/main/java/com/wcs/back/constant/GenConstants.java
@@ -0,0 +1,186 @@
+package com.wcs.back.constant;
+
+/**
+ * 代码生成通用常量
+ *
+ * @author wms
+ */
+public class GenConstants {
+ /**
+ * 单表(增删改查)
+ */
+ public static final String TPL_CRUD = "crud";
+
+ /**
+ * 树表(增删改查)
+ */
+ public static final String TPL_TREE = "tree";
+
+ /**
+ * 主子表(增删改查)
+ */
+ public static final String TPL_SUB = "sub";
+
+ /**
+ * 树编码字段
+ */
+ public static final String TREE_CODE = "treeCode";
+
+ /**
+ * 树父编码字段
+ */
+ public static final String TREE_PARENT_CODE = "treeParentCode";
+
+ /**
+ * 树名称字段
+ */
+ public static final String TREE_NAME = "treeName";
+
+ /**
+ * 上级菜单ID字段
+ */
+ public static final String PARENT_MENU_ID = "parentMenuId";
+
+ /**
+ * 上级菜单名称字段
+ */
+ public static final String PARENT_MENU_NAME = "parentMenuName";
+
+ /**
+ * 数据库字符串类型
+ */
+ public static final String[] COLUMNTYPE_STR = {"char", "varchar", "nvarchar", "varchar2"};
+
+ /**
+ * 数据库文本类型
+ */
+ public static final String[] COLUMNTYPE_TEXT = {"tinytext", "text", "mediumtext", "longtext"};
+
+ /**
+ * 数据库时间类型
+ */
+ public static final String[] COLUMNTYPE_TIME = {"datetime", "time", "date", "timestamp"};
+
+ /**
+ * 数据库数字类型
+ */
+ public static final String[] COLUMNTYPE_NUMBER = {"tinyint", "smallint", "mediumint", "int", "number", "integer",
+ "bit", "bigint", "float", "double", "decimal"};
+
+ /**
+ * 页面不需要编辑字段
+ */
+ public static final String[] COLUMNNAME_NOT_EDIT = {"id", "create_by", "create_time", "del_flag"};
+
+ /**
+ * 页面不需要显示的列表字段
+ */
+ public static final String[] COLUMNNAME_NOT_LIST = {"id", "create_by", "create_time", "del_flag", "update_by",
+ "update_time"};
+
+ /**
+ * 页面不需要查询字段
+ */
+ public static final String[] COLUMNNAME_NOT_QUERY = {"id", "create_by", "create_time", "del_flag", "update_by",
+ "update_time", "remark"};
+
+ /**
+ * Entity基类字段
+ */
+ public static final String[] BASE_ENTITY = {"createBy", "createTime", "updateBy", "updateTime", "remark"};
+
+ /**
+ * Tree基类字段
+ */
+ public static final String[] TREE_ENTITY = {"parentName", "parentId", "orderNum", "ancestors", "children"};
+
+ /**
+ * 文本框
+ */
+ public static final String HTML_INPUT = "input";
+
+ /**
+ * 文本域
+ */
+ public static final String HTML_TEXTAREA = "textarea";
+
+ /**
+ * 下拉框
+ */
+ public static final String HTML_SELECT = "select";
+
+ /**
+ * 单选框
+ */
+ public static final String HTML_RADIO = "radio";
+
+ /**
+ * 复选框
+ */
+ public static final String HTML_CHECKBOX = "checkbox";
+
+ /**
+ * 日期控件
+ */
+ public static final String HTML_DATETIME = "datetime";
+
+ /**
+ * 图片上传控件
+ */
+ public static final String HTML_IMAGE_UPLOAD = "imageUpload";
+
+ /**
+ * 文件上传控件
+ */
+ public static final String HTML_FILE_UPLOAD = "fileUpload";
+
+ /**
+ * 富文本控件
+ */
+ public static final String HTML_EDITOR = "editor";
+
+ /**
+ * 字符串类型
+ */
+ public static final String TYPE_STRING = "String";
+
+ /**
+ * 整型
+ */
+ public static final String TYPE_INTEGER = "Integer";
+
+ /**
+ * 长整型
+ */
+ public static final String TYPE_LONG = "Long";
+
+ /**
+ * 浮点型
+ */
+ public static final String TYPE_DOUBLE = "Double";
+
+ /**
+ * 高精度计算类型
+ */
+ public static final String TYPE_BIGDECIMAL = "BigDecimal";
+
+ /**
+ * 时间类型
+ */
+ public static final String TYPE_DATE = "Date";
+
+ /**
+ * 模糊查询
+ */
+ public static final String QUERY_LIKE = "LIKE";
+
+ /**
+ * 相等查询
+ */
+ public static final String QUERY_EQ = "EQ";
+
+ /**
+ * 需要
+ */
+ public static final String REQUIRE = "1";
+}
diff --git a/src/main/java/com/wcs/back/constant/HttpStatus.java b/src/main/java/com/wcs/back/constant/HttpStatus.java
new file mode 100644
index 0000000..bfa98d4
--- /dev/null
+++ b/src/main/java/com/wcs/back/constant/HttpStatus.java
@@ -0,0 +1,93 @@
+package com.wcs.back.constant;
+
+/**
+ * 返回状态码
+ *
+ * @author wms
+ */
+public class HttpStatus {
+ /**
+ * 操作成功
+ */
+ public static final int SUCCESS = 200;
+
+ /**
+ * 对象创建成功
+ */
+ public static final int CREATED = 201;
+
+ /**
+ * 请求已经被接受
+ */
+ public static final int ACCEPTED = 202;
+
+ /**
+ * 操作已经执行成功,但是没有返回数据
+ */
+ public static final int NO_CONTENT = 204;
+
+ /**
+ * 资源已被移除
+ */
+ public static final int MOVED_PERM = 301;
+
+ /**
+ * 重定向
+ */
+ public static final int SEE_OTHER = 303;
+
+ /**
+ * 资源没有被修改
+ */
+ public static final int NOT_MODIFIED = 304;
+
+ /**
+ * 参数列表错误(缺少,格式不匹配)
+ */
+ public static final int BAD_REQUEST = 400;
+
+ /**
+ * 未授权
+ */
+ public static final int UNAUTHORIZED = 401;
+
+ /**
+ * 访问受限,授权过期
+ */
+ public static final int FORBIDDEN = 403;
+
+ /**
+ * 资源,服务未找到
+ */
+ public static final int NOT_FOUND = 404;
+
+ /**
+ * 不允许的http方法
+ */
+ public static final int BAD_METHOD = 405;
+
+ /**
+ * 资源冲突,或者资源被锁
+ */
+ public static final int CONFLICT = 409;
+
+ /**
+ * 不支持的数据,媒体类型
+ */
+ public static final int UNSUPPORTED_TYPE = 415;
+
+ /**
+ * 系统内部错误
+ */
+ public static final int ERROR = 500;
+
+ /**
+ * 接口未实现
+ */
+ public static final int NOT_IMPLEMENTED = 501;
+
+ /**
+ * 系统警告消息
+ */
+ public static final int WARN = 601;
+}
diff --git a/src/main/java/com/wcs/back/constant/ScheduleConstants.java b/src/main/java/com/wcs/back/constant/ScheduleConstants.java
new file mode 100644
index 0000000..9e2b48d
--- /dev/null
+++ b/src/main/java/com/wcs/back/constant/ScheduleConstants.java
@@ -0,0 +1,56 @@
+package com.wcs.back.constant;
+
+/**
+ * 任务调度通用常量
+ *
+ * @author wms
+ */
+public class ScheduleConstants {
+ public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME";
+
+ /**
+ * 执行目标key
+ */
+ public static final String TASK_PROPERTIES = "TASK_PROPERTIES";
+
+ /**
+ * 默认
+ */
+ public static final String MISFIRE_DEFAULT = "0";
+
+ /**
+ * 立即触发执行
+ */
+ public static final String MISFIRE_IGNORE_MISFIRES = "1";
+
+ /**
+ * 触发一次执行
+ */
+ public static final String MISFIRE_FIRE_AND_PROCEED = "2";
+
+ /**
+ * 不触发立即执行
+ */
+ public static final String MISFIRE_DO_NOTHING = "3";
+
+ public enum Status {
+ /**
+ * 正常
+ */
+ NORMAL("0"),
+ /**
+ * 暂停
+ */
+ PAUSE("1");
+
+ private String value;
+
+ private Status(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+ }
+}
diff --git a/src/main/java/com/wcs/back/constant/UserConstants.java b/src/main/java/com/wcs/back/constant/UserConstants.java
new file mode 100644
index 0000000..3e5fdc0
--- /dev/null
+++ b/src/main/java/com/wcs/back/constant/UserConstants.java
@@ -0,0 +1,111 @@
+package com.wcs.back.constant;
+
+/**
+ * 用户常量信息
+ *
+ * @author wms
+ */
+public class UserConstants {
+ /**
+ * 平台内系统用户的唯一标志
+ */
+ public static final String SYS_USER = "SYS_USER";
+
+ /**
+ * 正常状态
+ */
+ public static final String NORMAL = "0";
+
+ /**
+ * 异常状态
+ */
+ public static final String EXCEPTION = "1";
+
+ /**
+ * 用户封禁状态
+ */
+ public static final String USER_DISABLE = "1";
+
+ /**
+ * 角色封禁状态
+ */
+ public static final String ROLE_DISABLE = "1";
+
+ /**
+ * 部门正常状态
+ */
+ public static final String DEPT_NORMAL = "0";
+
+ /**
+ * 部门停用状态
+ */
+ public static final String DEPT_DISABLE = "1";
+
+ /**
+ * 字典正常状态
+ */
+ public static final String DICT_NORMAL = "0";
+
+ /**
+ * 是否为系统默认(是)
+ */
+ public static final String YES = "Y";
+
+ /**
+ * 是否菜单外链(是)
+ */
+ public static final String YES_FRAME = "0";
+
+ /**
+ * 是否菜单外链(否)
+ */
+ public static final String NO_FRAME = "1";
+
+ /**
+ * 菜单类型(目录)
+ */
+ public static final String TYPE_DIR = "M";
+
+ /**
+ * 菜单类型(菜单)
+ */
+ public static final String TYPE_MENU = "C";
+
+ /**
+ * 菜单类型(按钮)
+ */
+ public static final String TYPE_BUTTON = "F";
+
+ /**
+ * Layout组件标识
+ */
+ public final static String LAYOUT = "Layout";
+
+ /**
+ * ParentView组件标识
+ */
+ public final static String PARENT_VIEW = "ParentView";
+
+ /**
+ * InnerLink组件标识
+ */
+ public final static String INNER_LINK = "InnerLink";
+
+ /**
+ * 校验是否唯一的返回标识
+ */
+ public final static boolean UNIQUE = true;
+ public final static boolean NOT_UNIQUE = false;
+
+ /**
+ * 用户名长度限制
+ */
+ public static final int USERNAME_MIN_LENGTH = 2;
+ public static final int USERNAME_MAX_LENGTH = 20;
+
+ /**
+ * 密码长度限制
+ */
+ public static final int PASSWORD_MIN_LENGTH = 5;
+ public static final int PASSWORD_MAX_LENGTH = 20;
+}
diff --git a/src/main/java/com/wcs/back/controller/WcsController.java b/src/main/java/com/wcs/back/controller/WcsController.java
new file mode 100644
index 0000000..58b05b4
--- /dev/null
+++ b/src/main/java/com/wcs/back/controller/WcsController.java
@@ -0,0 +1,81 @@
+package com.wcs.back.controller;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.wcs.back.domain.WcsResult;
+import com.wcs.back.service.IWcsService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * wcs回调Controller
+ *
+ * @author zf
+ * @date 2022-11-11
+ */
+@RestController
+@RequestMapping("/wms")
+@Api(value = "wcs回调控制器", tags = {"wcs回调管理"})
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+public class WcsController {
+
+ private final IWcsService wcsService;
+
+ /**
+ * 普通搬运任务下发
+ */
+ @ApiOperation("普通搬运任务下发")
+ @PostMapping("/SetUp_Task")
+ public WcsResult SetUp_Task(@RequestBody String json, HttpServletRequest request) throws JsonProcessingException {
+ WcsResult wcsResult = wcsService.SetUp_Task(json, request);
+ return wcsResult;
+ }
+
+ /**
+ * 机械臂拆托任务下发
+ */
+ @ApiOperation("机械臂拆托任务下发")
+ @PostMapping("/Dismantling_Task")
+ public WcsResult Dismantling_Task(@RequestBody String json, HttpServletRequest request) throws JsonProcessingException {
+ WcsResult wcsResult = wcsService.Dismantling_Task(json, request);
+ return wcsResult;
+ }
+
+ /**
+ * CTU任务下发
+ */
+ @ApiOperation("CTU任务下发")
+ @PostMapping("/SetUp_CTUTask")
+ public WcsResult SetUp_CTUTask(@RequestBody String json, HttpServletRequest request) throws JsonProcessingException {
+ WcsResult wcsResult = wcsService.SetUp_CTUTask(json, request);
+ return wcsResult;
+ }
+
+ /**
+ * 滚筒任务下发
+ */
+ @ApiOperation("滚筒任务下发")
+ @PostMapping("/DrumLine_Task")
+ public WcsResult DrumLine_Task(@RequestBody String json, HttpServletRequest request) throws JsonProcessingException {
+ WcsResult wcsResult = wcsService.DrumLine_Task(json, request);
+ return wcsResult;
+ }
+
+ /**
+ * 指令下发
+ */
+ @ApiOperation("滚筒任务下发")
+ @PostMapping("/Directives")
+ public WcsResult Directives(@RequestBody String json, HttpServletRequest request) throws JsonProcessingException {
+ WcsResult wcsResult = wcsService.Directives(json, request);
+ return wcsResult;
+ }
+
+}
diff --git a/src/main/java/com/wcs/back/domain/AgvSetUpTask.java b/src/main/java/com/wcs/back/domain/AgvSetUpTask.java
new file mode 100644
index 0000000..a32681b
--- /dev/null
+++ b/src/main/java/com/wcs/back/domain/AgvSetUpTask.java
@@ -0,0 +1,86 @@
+package com.wcs.back.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 普通搬运任务
+ */
+@Builder
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class AgvSetUpTask {
+ /**
+ * 任务号
+ */
+ private String taskNo;
+ /**
+ * 序号(同一任务号,序号从0开始)
+ */
+ private Integer taskIndex;
+ /**
+ * 目的地标
+ */
+ private String armSite;
+ /**
+ * 目的点动作(0 保持 1 取料 2 下料)
+ */
+ private Integer actionType;
+ /**
+ * 指定Agv( 0表示不指定 否则表示为对应的AGVID)
+ */
+ private Integer agv;
+ /**
+ * 是否等待WMS放行信号(0 等待放行 1 直接放行)
+ */
+ private Integer isWaitWMSSingal;
+ /**
+ * 任务创建时间
+ */
+ private String buildTime;
+ private String exeTime;
+ private String finishTime;
+ private String exeAgv;
+ private String taskState;
+ /**
+ * 优先级从1往上数字越大,优先级越小
+ */
+ private String priority;
+
+ /**
+ * 料箱号
+ */
+ private String materialBinId;
+
+ /**
+ * 区域类型::1-CTU库位, 2-AGV库位, 3-四向车库位, 4-堆垛机库位, 5-输送线库位
+ */
+ private String areaType;
+ /**
+ * WMS业务类型
+ */
+ private String data1;
+ /**
+ * WMS业务序号
+ */
+ private String data2;
+ /**
+ * 备用字段
+ */
+ private String data3;
+ /**
+ * 备用字段
+ */
+ private String data4;
+ /**
+ * 备用字段
+ */
+ private String data5;
+ /**
+ * 备用字段
+ */
+ private String data6;
+}
diff --git a/src/main/java/com/wcs/back/domain/CTUTaskBackVo.java b/src/main/java/com/wcs/back/domain/CTUTaskBackVo.java
new file mode 100644
index 0000000..ffcfb91
--- /dev/null
+++ b/src/main/java/com/wcs/back/domain/CTUTaskBackVo.java
@@ -0,0 +1,80 @@
+package com.wcs.back.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+
+/**
+ * CTU任务回调Vo
+ *
+ * @author zf
+ * @date 2023-01-05
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class CTUTaskBackVo implements Serializable {
+ private static final long serialVersionUID = 1L;
+ /**
+ * 任务号
+ */
+ @NotBlank(message = "任务号不能为空")
+ private String taskNo;
+
+ /**
+ * 料箱号
+ */
+ @NotBlank(message = "料箱号不能为空")
+ private String materialBinId;
+
+ /**
+ * wms业务号
+ */
+ private String bizNo;
+
+ /**
+ * 任务状态:10-取料成功,20-拆箱完成,30-拆托完成,40-已送达,99-异常
+ */
+ @NotBlank(message = "任务状态不能为空")
+ private String taskState;
+
+ /**
+ * 异常信息或者其他备注
+ */
+ private String remark;
+
+ /**
+ * 备用字段1
+ */
+ private String data1;
+
+ /**
+ * 备用字段2
+ */
+ private String data2;
+
+ /**
+ * 备用字段3
+ */
+ private String data3;
+
+ /**
+ * 备用字段4
+ */
+ private String data4;
+
+ /**
+ * 备用字段5
+ */
+ private String data5;
+
+ /**
+ * 备用字段6
+ */
+ private String data6;
+}
diff --git a/src/main/java/com/wcs/back/domain/CTUTaskVo.java b/src/main/java/com/wcs/back/domain/CTUTaskVo.java
new file mode 100644
index 0000000..63c3971
--- /dev/null
+++ b/src/main/java/com/wcs/back/domain/CTUTaskVo.java
@@ -0,0 +1,99 @@
+package com.wcs.back.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * CTU任务Vo
+ *
+ * @author zf
+ * @date 2023-01-05
+ */
+@Builder
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class CTUTaskVo implements Serializable {
+ private static final long serialVersionUID = 1L;
+ /**
+ * 任务号
+ */
+ private String taskNo;
+
+ /**
+ * 取料/目的地地标信息列表
+ */
+ private List siteList;
+
+ /**
+ * 任务创建时间
+ */
+ private String buildTime;
+
+ /**
+ * 备用字段
+ */
+ private String data1;
+ /**
+ * 备用字段
+ */
+ private String data2;
+ /**
+ * 备用字段
+ */
+ private String data3;
+ /**
+ * 备用字段
+ */
+ private String data4;
+ /**
+ * 备用字段
+ */
+ private String data5;
+ /**
+ * 备用字段
+ */
+ private String data6;
+
+ /**
+ * 取料地标信息
+ */
+ @Data
+ public static class Site {
+ /**
+ * 序号
+ */
+ private Integer taskIndex;
+
+ /**
+ * 取料地标
+ */
+ private String reclaimingSite;
+
+ /**
+ * 目的地标
+ */
+ private String destinationSite;
+
+ /**
+ * 料箱号
+ */
+ private String materialBinId;
+
+ /**
+ * wcs业务号
+ */
+ private String bizNo;
+
+ /**
+ * 任务类型::10-入库, 20-出库, 30-移库
+ */
+ private String type;
+
+ }
+}
diff --git a/src/main/java/com/wcs/back/domain/DirectivesVo.java b/src/main/java/com/wcs/back/domain/DirectivesVo.java
new file mode 100644
index 0000000..b3715ba
--- /dev/null
+++ b/src/main/java/com/wcs/back/domain/DirectivesVo.java
@@ -0,0 +1,57 @@
+package com.wcs.back.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 指令Vo
+ *
+ * @author zf
+ * @date 2023-01-05
+ */
+@Builder
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class DirectivesVo implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 拆零口
+ */
+ private String pickingPort;
+
+ /**
+ * 指令: 10-滚筒前进, 20-回库滚筒前进, 30-整体前进, 40-取走空料箱
+ */
+ private String directive;
+
+ /**
+ * 备用字段
+ */
+ private String data1;
+ /**
+ * 备用字段
+ */
+ private String data2;
+ /**
+ * 备用字段
+ */
+ private String data3;
+ /**
+ * 备用字段
+ */
+ private String data4;
+ /**
+ * 备用字段
+ */
+ private String data5;
+ /**
+ * 备用字段
+ */
+ private String data6;
+}
diff --git a/src/main/java/com/wcs/back/domain/DrumLineTaskBackVo.java b/src/main/java/com/wcs/back/domain/DrumLineTaskBackVo.java
new file mode 100644
index 0000000..bd9d07d
--- /dev/null
+++ b/src/main/java/com/wcs/back/domain/DrumLineTaskBackVo.java
@@ -0,0 +1,98 @@
+package com.wcs.back.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 滚筒线任务回调Vo
+ *
+ * @author zf
+ * @date 2023-01-05
+ */
+@Builder
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class DrumLineTaskBackVo implements Serializable {
+ private static final long serialVersionUID = 1L;
+ /**
+ * 任务号
+ */
+ private String taskNo;
+
+ /**
+ * 滚筒任务状态::40-已送达, 99-异常
+ */
+ private String taskState;
+
+ /**
+ * 料箱号
+ */
+ private String materialBinId;
+
+ /**
+ * 异常信息或者其他备注
+ */
+ private String remark;
+
+ /**
+ * 备用字段
+ */
+ private String data1;
+ /**
+ * 备用字段
+ */
+ private String data2;
+ /**
+ * 备用字段
+ */
+ private String data3;
+ /**
+ * 备用字段
+ */
+ private String data4;
+ /**
+ * 备用字段
+ */
+ private String data5;
+ /**
+ * 备用字段
+ */
+ private String data6;
+
+ /**
+ * 取料地标信息
+ */
+ @Data
+ public static class Site {
+ /**
+ * 序号
+ */
+ private Integer taskIndex;
+
+ /**
+ * 取料地标
+ */
+ private String reclaimingSite;
+
+ /**
+ * 目的地标
+ */
+ private String destinationSite;
+
+ /**
+ * 料箱号
+ */
+ private String materialBinId;
+
+ /**
+ * 拆箱任务号
+ */
+ private String disassemblyTaskNo;
+
+ }
+}
diff --git a/src/main/java/com/wcs/back/domain/DrumLineTaskVo.java b/src/main/java/com/wcs/back/domain/DrumLineTaskVo.java
new file mode 100644
index 0000000..f86ed9a
--- /dev/null
+++ b/src/main/java/com/wcs/back/domain/DrumLineTaskVo.java
@@ -0,0 +1,71 @@
+package com.wcs.back.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 滚筒线任务Vo
+ *
+ * @author zf
+ * @date 2023-01-05
+ */
+@Builder
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class DrumLineTaskVo implements Serializable {
+ private static final long serialVersionUID = 1L;
+ /**
+ * 任务号
+ */
+ private String taskNo;
+
+ /**
+ * 拣零口
+ */
+ private String pickingPort;
+
+ /**
+ * 分拣口
+ */
+ private String packagingPort;
+
+ /**
+ * 业务号
+ */
+ private String businessNo;
+
+ /**
+ * 任务创建时间
+ */
+ private String buildTime;
+
+ /**
+ * 备用字段
+ */
+ private String data1;
+ /**
+ * 备用字段
+ */
+ private String data2;
+ /**
+ * 备用字段
+ */
+ private String data3;
+ /**
+ * 备用字段
+ */
+ private String data4;
+ /**
+ * 备用字段
+ */
+ private String data5;
+ /**
+ * 备用字段
+ */
+ private String data6;
+}
diff --git a/src/main/java/com/wcs/back/domain/RoboticArmTaskBackVo.java b/src/main/java/com/wcs/back/domain/RoboticArmTaskBackVo.java
new file mode 100644
index 0000000..4bf3d48
--- /dev/null
+++ b/src/main/java/com/wcs/back/domain/RoboticArmTaskBackVo.java
@@ -0,0 +1,81 @@
+package com.wcs.back.domain;
+
+import io.swagger.annotations.ApiModel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+
+/**
+ * 机械臂任务回调Vo
+ *
+ * @author zf
+ * @date 2023-01-05
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@ApiModel(value = "RoboticArmTaskBackVo", description = "机械臂任务回调实体")
+public class RoboticArmTaskBackVo implements Serializable {
+ private static final long serialVersionUID = 1L;
+ /**
+ * 任务号
+ */
+ @NotBlank(message = "任务号不能为空")
+ private String taskNo;
+
+ /**
+ * 拆箱号(除取料成功)
+ */
+ private String disassemblyTaskNo;
+
+ /**
+ * 料箱号(除取料成功)
+ */
+ private String materialBinId;
+
+ /**
+ * 任务状态:10-取料成功,20-拆箱完成,30-拆托完成,40-已送达,99-异常
+ */
+ @NotBlank(message = "任务状态不能为空")
+ private String taskState;
+
+ /**
+ * 异常信息或者其他备注
+ */
+ private String remark;
+
+ /**
+ * 备用字段1
+ */
+ private String data1;
+
+ /**
+ * 备用字段2
+ */
+ private String data2;
+
+ /**
+ * 备用字段3
+ */
+ private String data3;
+
+ /**
+ * 备用字段4
+ */
+ private String data4;
+
+ /**
+ * 备用字段5
+ */
+ private String data5;
+
+ /**
+ * 备用字段6
+ */
+ private String data6;
+}
diff --git a/src/main/java/com/wcs/back/domain/RoboticArmTaskVo.java b/src/main/java/com/wcs/back/domain/RoboticArmTaskVo.java
new file mode 100644
index 0000000..6df5e20
--- /dev/null
+++ b/src/main/java/com/wcs/back/domain/RoboticArmTaskVo.java
@@ -0,0 +1,136 @@
+package com.wcs.back.domain;
+
+import io.swagger.annotations.ApiModel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * 机械臂任务Vo
+ *
+ * @author zf
+ * @date 2023-01-05
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@ApiModel(value = "RoboticArmTaskVo", description = "机械臂任务实体")
+public class RoboticArmTaskVo {
+ /**
+ * 任务号
+ */
+ private String taskNo;
+
+ /**
+ * 取料目的地标
+ */
+ private String reclaimingSite;
+
+ /**
+ * 箱型
+ */
+ private String boxType;
+
+ /**
+ * 垛型
+ */
+ private String stackType;
+
+ /**
+ * 应拆箱的数量
+ */
+ private Integer shouldBoxNum;
+
+ /**
+ * 库存箱数
+ */
+ private Integer fullBoxNum;
+
+ /**
+ * 是否铸铁::10-是, 20-否
+ */
+ private String castIron;
+
+ /**
+ * 是否回库::10-是, 20-否
+ */
+ private String isBack;
+
+ /**
+ * 托盘号
+ */
+ private String palletCode;
+
+ /**
+ * 目的地标信息列表
+ */
+ private List armSiteList;
+
+ /**
+ * 任务创建时间
+ */
+ private String buildTime;
+
+ /**
+ * 备用字段
+ */
+ private String data1;
+ /**
+ * 备用字段
+ */
+ private String data2;
+ /**
+ * 备用字段
+ */
+ private String data3;
+ /**
+ * 备用字段
+ */
+ private String data4;
+ /**
+ * 备用字段
+ */
+ private String data5;
+ /**
+ * 备用字段
+ */
+ private String data6;
+
+ /**
+ * 拆托任务信息
+ */
+ @Data
+ @Builder
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class DismantlingInfo {
+ /**
+ * 序号
+ */
+ private Integer taskIndex;
+
+ /**
+ * 拆箱号
+ */
+ private String disassemblyTaskNo;
+
+ /**
+ * 目的区域::10-料箱区, 20-分拣区, 30-拣零区
+ */
+ private String destinationArea;
+
+ /**
+ * 目的地标
+ */
+ private String destinationSite;
+
+ /**
+ * 料箱号
+ */
+ private String materialBinId;
+ }
+}
diff --git a/src/main/java/com/wcs/back/domain/TaskCallBack.java b/src/main/java/com/wcs/back/domain/TaskCallBack.java
new file mode 100644
index 0000000..b1882ba
--- /dev/null
+++ b/src/main/java/com/wcs/back/domain/TaskCallBack.java
@@ -0,0 +1,131 @@
+package com.wcs.back.domain;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * wcs输送任务完成回调类
+ *
+ * @author zf
+ * @date 2022/11/21
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@ApiModel(value = "TaskCallBack", description = "wcs回调实体")
+public class TaskCallBack {
+
+ /**
+ * 任务号
+ */
+ @ApiModelProperty("任务号")
+ @JsonProperty("taskNo")
+ private String taskNo;
+ /**
+ * 序号(同一任务号,序号从0开始)
+ */
+ @ApiModelProperty("序号(同一任务号,序号从0开始)")
+ @JsonProperty("taskIndex")
+ private Integer taskIndex;
+
+ /**
+ * 目的地标
+ */
+ @ApiModelProperty("目的地标")
+ @JsonProperty("armSite")
+ private String armSite;
+
+ /**
+ * 目的点动作(0 保持 1 取料 2 下料)
+ */
+ @ApiModelProperty("目的点动作(0 保持 1 取料 2 下料)")
+ @JsonProperty("actionType")
+ private Integer actionType;
+
+ /**
+ * 指定Agv( 0表示不指定 否则表示为对应的AGVID)
+ */
+ @ApiModelProperty("指定Agv( 0表示不指定 否则表示为对应的AGVID)")
+ @JsonProperty("agv")
+ private Integer agv;
+
+ /**
+ * 任务创建时间
+ */
+ @ApiModelProperty("任务创建时间")
+ @JsonProperty("buildTime")
+ private String buildTime;
+
+ /**
+ * 任务被执行时间
+ */
+ @ApiModelProperty("任务被执行时间")
+ @JsonProperty("exeTime")
+ private String exeTime;
+
+ /**
+ * 任务完成时间
+ */
+ @ApiModelProperty("任务完成时间")
+ private String finishTime;
+
+ /**
+ * 0 未执行 1执行中 2取料完成 3已完成 4 已作废
+ */
+ @ApiModelProperty("0未执行 1执行中 2取料完成 3已完成 4已作废")
+ private Integer taskState;
+
+ /**
+ * 执行任务的AgvID
+ */
+ @ApiModelProperty("执行任务的AgvID")
+ @JsonProperty("exeAgv")
+ private Integer exeAgv;
+
+ /**
+ * WMS业务类型 需要在下发任务时带给WCS,成功时带回WMS
+ */
+ @ApiModelProperty("WMS业务类型 需要在下发任务时带给WCS,成功时带回WMS")
+ private String data1;
+
+ /**
+ * WMS输送任务标识 需要在下发任务时带给WCS,成功时带回WMS
+ */
+ @ApiModelProperty("WMS输送任务标识 需要在下发任务时带给WCS,成功时带回WMS")
+// @NotBlank(message = "WMS输送任务标识不能为空")
+ @JsonProperty("data2")
+ private String data2;
+
+ /**
+ * 备注
+ */
+ @ApiModelProperty("备注")
+ @JsonProperty("data3")
+ private String data3;
+
+ /**
+ * 备用字段
+ */
+ @ApiModelProperty("备用字段")
+ @JsonProperty("data4")
+ private String data4;
+
+ /**
+ * 备用字段
+ */
+ @ApiModelProperty("备用字段")
+ @JsonProperty("data5")
+ private String data5;
+
+ /**
+ * 备用字段
+ */
+ @ApiModelProperty("备用字段")
+ @JsonProperty("data6")
+ private String data6;
+
+}
diff --git a/src/main/java/com/wcs/back/domain/WcsResult.java b/src/main/java/com/wcs/back/domain/WcsResult.java
new file mode 100644
index 0000000..2a0eb16
--- /dev/null
+++ b/src/main/java/com/wcs/back/domain/WcsResult.java
@@ -0,0 +1,57 @@
+package com.wcs.back.domain;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * wcs返回
+ *
+ * @author zf
+ * @date 2023/11/27
+ */
+@Builder
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class WcsResult {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 0失败 1成功
+ */
+ @JsonProperty("resultCode")
+ private Integer resultCode;
+ /**
+ * 如果失败,该字段记录异常信息
+ */
+ @JsonProperty("message")
+ private String message;
+
+ /**
+ * 返回成功消息
+ *
+ * @return 成功消息
+ */
+ public static WcsResult success() {
+ WcsResult wcsResult = new WcsResult();
+ wcsResult.setResultCode(1);
+ wcsResult.setMessage("成功");
+ return wcsResult;
+ }
+
+ /**
+ * 返回错误消息
+ *
+ * @return 失败消息
+ */
+ public static WcsResult error() {
+ WcsResult wcsResult = new WcsResult();
+ wcsResult.setResultCode(0);
+ wcsResult.setMessage("失败");
+ return wcsResult;
+ }
+}
diff --git a/src/main/java/com/wcs/back/service/IWcsService.java b/src/main/java/com/wcs/back/service/IWcsService.java
new file mode 100644
index 0000000..75a59c9
--- /dev/null
+++ b/src/main/java/com/wcs/back/service/IWcsService.java
@@ -0,0 +1,53 @@
+package com.wcs.back.service;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.wcs.back.domain.WcsResult;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * wcs回调Interface
+ *
+ * @author zf
+ * @date 2023/11/27
+ */
+public interface IWcsService {
+ /**
+ * 普通搬运任务下发
+ * @param json
+ * @return
+ */
+ WcsResult SetUp_Task(String json, HttpServletRequest request) throws JsonProcessingException;
+
+ /**
+ * 机械臂拆托任务下发
+ * @param json
+ * @param request
+ * @return
+ */
+ WcsResult Dismantling_Task(String json, HttpServletRequest request) throws JsonProcessingException;
+
+ /**
+ * CTU任务下发
+ * @param json
+ * @param request
+ * @return
+ */
+ WcsResult SetUp_CTUTask(String json, HttpServletRequest request) throws JsonProcessingException;
+
+ /**
+ * 滚筒线任务下发
+ * @param json
+ * @param request
+ * @return
+ */
+ WcsResult DrumLine_Task(String json, HttpServletRequest request) throws JsonProcessingException;
+
+ /**
+ * 指令下发
+ * @param json
+ * @param request
+ * @return
+ */
+ WcsResult Directives(String json, HttpServletRequest request) throws JsonProcessingException;
+}
diff --git a/src/main/java/com/wcs/back/service/impl/WcsServiceImpl.java b/src/main/java/com/wcs/back/service/impl/WcsServiceImpl.java
new file mode 100644
index 0000000..b01cfa4
--- /dev/null
+++ b/src/main/java/com/wcs/back/service/impl/WcsServiceImpl.java
@@ -0,0 +1,339 @@
+package com.wcs.back.service.impl;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.wcs.back.domain.*;
+import com.wcs.back.service.IWcsService;
+import com.wcs.back.util.http.HttpUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * wcs回调Service
+ *
+ * @author zf
+ * @date 2023/11/27
+ */
+@Service
+public class WcsServiceImpl implements IWcsService {
+ private static final Logger log = LoggerFactory.getLogger(WcsServiceImpl.class);
+
+ @Value("${wms.httpUrl}")
+ public String httpUrl;
+
+ @Value("${wms.roboticArmUrl}")
+ public String roboticArmUrl;
+
+ @Value("${wms.ctuUrl}")
+ public String ctuUrl;
+
+ @Value("${wms.drumLineTaskHttpUrl}")
+ public String drumLineTaskHttpUrl;
+
+ /**
+ * 普通搬运任务下发
+ *
+ * @param json
+ * @return
+ */
+ @Override
+ public WcsResult SetUp_Task(String json, HttpServletRequest request) throws JsonProcessingException {
+ // 获取客户端IP地址
+ String clientIpAddress = getClientIpAddress(request);
+ String url = "http://"+clientIpAddress+httpUrl;
+
+ // 创建一个 ScheduledExecutorService 实例
+ ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
+
+ ObjectMapper objectMapper = new ObjectMapper();
+ List agvSetUpTaskList = objectMapper.readValue(json, objectMapper.getTypeFactory().constructCollectionType(List.class, AgvSetUpTask.class));
+ // 创建两个倒计时任务
+ // 1.30秒后回调取料成功
+ AgvSetUpTask agvSetUpTask = agvSetUpTaskList.get(0);
+ // 2.60秒后回调已送达
+ AgvSetUpTask agvSetUpTask2 = agvSetUpTaskList.get(1);
+ // 定义第一个任务,30秒后执行
+ Runnable task1 = () -> {
+ // 回调1的具体逻辑
+ TaskCallBack taskCallBack = new TaskCallBack();
+ taskCallBack.setTaskNo(agvSetUpTask.getTaskNo());
+ taskCallBack.setTaskIndex(agvSetUpTask.getTaskIndex());
+ taskCallBack.setArmSite(agvSetUpTask.getArmSite());
+ taskCallBack.setActionType(agvSetUpTask.getActionType());
+ taskCallBack.setAgv(1);
+ taskCallBack.setTaskState(2);
+ taskCallBack.setExeAgv(1);
+ sendHttpPost(taskCallBack, url);
+ };
+
+ // 定义第二个任务,60秒后执行
+ Runnable task2 = () -> {
+ // 任务2的具体逻辑
+ TaskCallBack taskCallBack2 = new TaskCallBack();
+ taskCallBack2.setTaskNo(agvSetUpTask2.getTaskNo());
+ taskCallBack2.setTaskIndex(agvSetUpTask2.getTaskIndex());
+ taskCallBack2.setArmSite(agvSetUpTask2.getArmSite());
+ taskCallBack2.setActionType(agvSetUpTask2.getActionType());
+ taskCallBack2.setAgv(1);
+ taskCallBack2.setTaskState(3);
+ taskCallBack2.setExeAgv(1);
+ sendHttpPost(taskCallBack2, url);
+ };
+ // 安排任务1,30秒后执行
+ scheduler.schedule(task1, 30, TimeUnit.SECONDS);
+
+ // 安排任务2,60秒后执行
+ scheduler.schedule(task2, 60, TimeUnit.SECONDS);
+
+ WcsResult wcsResult = new WcsResult();
+ wcsResult.setResultCode(1);
+ wcsResult.setMessage("成功");
+ return wcsResult;
+ }
+
+ /**
+ * 机械臂拆托任务下发
+ *
+ * @param json
+ * @param request
+ * @return
+ */
+ @Override
+ public WcsResult Dismantling_Task(String json, HttpServletRequest request) throws JsonProcessingException {
+ // 获取客户端IP地址
+ String clientIpAddress = getClientIpAddress(request);
+ String url = "http://"+clientIpAddress+roboticArmUrl;
+ // 滚筒url,已送达是滚筒返回
+ String gtUrl = "http://"+clientIpAddress+drumLineTaskHttpUrl;
+ ObjectMapper objectMapper = new ObjectMapper();
+ RoboticArmTaskVo roboticArmTaskVo = objectMapper.readValue(json, RoboticArmTaskVo.class);
+ List armSiteList = roboticArmTaskVo.getArmSiteList();
+ int size = armSiteList.size();
+ // 创建一个 ScheduledExecutorService 实例
+ ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2+(2*size));
+
+ // 创建倒计时任务
+ // 1.30秒后回调取料成功
+ // 2.60秒后,每隔10秒回调拆箱成功,如果全部拆箱完成,则过10秒回调拆托完成
+ // 3.等2的任务全部做完后,等待10秒,每隔10秒回调已送达(目的区域是20-分拣区)
+
+ // 取料成功
+ Runnable task1 = () -> {
+ // 回调1的具体逻辑
+ RoboticArmTaskBackVo roboticArmTaskBackVo = new RoboticArmTaskBackVo();
+ roboticArmTaskBackVo.setTaskNo(roboticArmTaskVo.getTaskNo());
+ roboticArmTaskBackVo.setTaskState("10");
+ roboticArmTaskBackVo.setRemark("取料成功!");
+ sendHttpPost(roboticArmTaskBackVo, url);
+ };
+ // 30秒之后执行,取料成功
+ scheduler.schedule(task1, 30, TimeUnit.SECONDS);
+ // 拆箱成功
+ Integer time = 60;
+ for (RoboticArmTaskVo.DismantlingInfo dismantlingInfo : armSiteList){
+ Runnable taskSite = () -> {
+ // 回调1的具体逻辑
+ RoboticArmTaskBackVo roboticArmTaskBackVo = new RoboticArmTaskBackVo();
+ roboticArmTaskBackVo.setTaskNo(roboticArmTaskVo.getTaskNo());
+ roboticArmTaskBackVo.setDisassemblyTaskNo(dismantlingInfo.getDisassemblyTaskNo());
+ // 料箱号只能模拟从wms调用空料箱
+ String materialBinId = HttpUtils.HttpPostWithJson("http://"+clientIpAddress+":50902/wcs/getEmptyPallet", "");
+ dismantlingInfo.setMaterialBinId(materialBinId);
+ roboticArmTaskBackVo.setMaterialBinId(materialBinId);
+ roboticArmTaskBackVo.setTaskState("20");
+ roboticArmTaskBackVo.setRemark("拆箱成功!");
+ sendHttpPost(roboticArmTaskBackVo, url);
+ };
+ // 循环执行拆箱回调
+ scheduler.schedule(taskSite, time, TimeUnit.SECONDS);
+ time += 10;
+ }
+
+ // 拆托成功,在全部拆箱完成之后执行
+ Runnable ctTask = () -> {
+ // 回调1的具体逻辑
+ RoboticArmTaskBackVo roboticArmTaskBackVo = new RoboticArmTaskBackVo();
+ roboticArmTaskBackVo.setTaskNo(roboticArmTaskVo.getTaskNo());
+ roboticArmTaskBackVo.setTaskState("30");
+ roboticArmTaskBackVo.setRemark("拆托成功!");
+ sendHttpPost(roboticArmTaskBackVo, url);
+ };
+ scheduler.schedule(ctTask, time, TimeUnit.SECONDS);
+
+ // 送至分拣需要回调已送达
+ time += 10;
+ for (RoboticArmTaskVo.DismantlingInfo dismantlingInfo : armSiteList){
+ if (dismantlingInfo.getDestinationArea().equals("20")){
+ Runnable taskSite = () -> {
+ RoboticArmTaskBackVo roboticArmTaskBackVo = new RoboticArmTaskBackVo();
+ roboticArmTaskBackVo.setTaskNo(roboticArmTaskVo.getTaskNo());
+ roboticArmTaskBackVo.setDisassemblyTaskNo(dismantlingInfo.getDisassemblyTaskNo());
+ roboticArmTaskBackVo.setMaterialBinId(dismantlingInfo.getMaterialBinId());
+ roboticArmTaskBackVo.setTaskState("40");
+ roboticArmTaskBackVo.setRemark("已送达!");
+ sendHttpPost(roboticArmTaskBackVo, gtUrl);
+ };
+ // 循环执行拆箱回调
+ scheduler.schedule(taskSite, time, TimeUnit.SECONDS);
+ time += 10;
+ }
+ }
+
+ WcsResult wcsResult = new WcsResult();
+ wcsResult.setResultCode(1);
+ wcsResult.setMessage("成功");
+ return wcsResult;
+ }
+
+ /**
+ * CTU任务下发
+ *
+ * @param json
+ * @param request
+ * @return
+ */
+ @Override
+ public WcsResult SetUp_CTUTask(String json, HttpServletRequest request) throws JsonProcessingException {
+ // 获取客户端IP地址
+ String clientIpAddress = getClientIpAddress(request);
+ String url = "http://"+clientIpAddress+ctuUrl;
+ ObjectMapper objectMapper = new ObjectMapper();
+ CTUTaskVo ctuTaskVo = objectMapper.readValue(json, CTUTaskVo.class);
+ List siteList = ctuTaskVo.getSiteList();
+ int size = siteList.size();
+
+ // 创建一个 ScheduledExecutorService 实例
+ ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2*size);
+
+ // 创建倒计时任务
+ // 循环取料成功
+ Integer time = 10;
+ for (CTUTaskVo.Site site : siteList){
+ Runnable taskSite = () -> {
+ CTUTaskBackVo ctuTaskBackVo = new CTUTaskBackVo();
+ ctuTaskBackVo.setTaskNo(ctuTaskVo.getTaskNo());
+ ctuTaskBackVo.setMaterialBinId(site.getMaterialBinId());
+ ctuTaskBackVo.setBizNo(site.getBizNo());
+ ctuTaskBackVo.setTaskState("10");
+ ctuTaskBackVo.setRemark("取料成功!");
+ sendHttpPost(ctuTaskBackVo, url);
+ };
+ // 循环执行取料成功回调
+ scheduler.schedule(taskSite, time, TimeUnit.SECONDS);
+ time += 10;
+ }
+
+ // 循环已送达
+ time += 20;
+ for (CTUTaskVo.Site site : siteList){
+ Runnable taskSite = () -> {
+ CTUTaskBackVo ctuTaskBackVo = new CTUTaskBackVo();
+ ctuTaskBackVo.setTaskNo(ctuTaskVo.getTaskNo());
+ ctuTaskBackVo.setMaterialBinId(site.getMaterialBinId());
+ ctuTaskBackVo.setBizNo(site.getBizNo());
+ ctuTaskBackVo.setTaskState("40");
+ ctuTaskBackVo.setRemark("已送达!");
+ sendHttpPost(ctuTaskBackVo, url);
+ };
+ // 循环执行送达回调
+ scheduler.schedule(taskSite, time, TimeUnit.SECONDS);
+ time += 10;
+ }
+ WcsResult wcsResult = new WcsResult();
+ wcsResult.setResultCode(1);
+ wcsResult.setMessage("成功");
+ return wcsResult;
+ }
+
+ /**
+ * 滚筒线任务下发
+ *
+ * @param json
+ * @param request
+ * @return
+ */
+ @Override
+ public WcsResult DrumLine_Task(String json, HttpServletRequest request) throws JsonProcessingException {
+ // 获取客户端IP地址
+ String clientIpAddress = getClientIpAddress(request);
+ String url = "http://"+clientIpAddress+drumLineTaskHttpUrl;
+ ObjectMapper objectMapper = new ObjectMapper();
+ DrumLineTaskVo drumLineTaskVo = objectMapper.readValue(json, DrumLineTaskVo.class);
+
+ // 创建一个 ScheduledExecutorService 实例
+ ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
+
+ // 创建倒计时任务
+ Runnable task = () -> {
+ DrumLineTaskBackVo drumLineTaskBackVo = new DrumLineTaskBackVo();
+ drumLineTaskBackVo.setTaskNo(drumLineTaskVo.getTaskNo());
+ drumLineTaskBackVo.setTaskState("40");
+ drumLineTaskBackVo.setMaterialBinId(drumLineTaskVo.getBusinessNo());
+ drumLineTaskBackVo.setRemark("已送达!");
+ sendHttpPost(drumLineTaskBackVo, url);
+ };
+ // 30秒后执行已送达回调
+ scheduler.schedule(task, 30, TimeUnit.SECONDS);
+
+ WcsResult wcsResult = new WcsResult();
+ wcsResult.setResultCode(1);
+ wcsResult.setMessage("成功");
+ return wcsResult;
+ }
+
+ /**
+ * 指令下发
+ *
+ * @param json
+ * @param request
+ * @return
+ */
+ @Override
+ public WcsResult Directives(String json, HttpServletRequest request) throws JsonProcessingException {
+ // 获取客户端IP地址
+ String clientIpAddress = getClientIpAddress(request);
+
+ // 创建一个 ScheduledExecutorService 实例
+ ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
+
+ ObjectMapper objectMapper = new ObjectMapper();
+ DirectivesVo directivesVo = objectMapper.readValue(json, DirectivesVo.class);
+
+ WcsResult wcsResult = new WcsResult();
+ wcsResult.setResultCode(1);
+ wcsResult.setMessage("成功");
+ return wcsResult;
+ }
+
+ // 发送 HTTP POST 请求
+ private WcsResult sendHttpPost(T taskCallBack, String url) {
+ String jsonString = JSON.toJSONString(taskCallBack);
+ String sendPost = HttpUtils.HttpPostWithJson(url, jsonString);
+ WcsResult agvResult = JSONObject.parseObject(sendPost, WcsResult.class);
+ // 处理回调结果,根据具体逻辑设置
+ log.info("请求json:"+jsonString);
+ log.info("响应json:"+agvResult.toString());
+ return agvResult;
+ }
+
+ // 获取请求端ip地址
+ private String getClientIpAddress(HttpServletRequest request) {
+ String xForwardedForHeader = request.getHeader("X-Forwarded-For");
+ if (xForwardedForHeader == null) {
+ return request.getRemoteAddr();
+ }
+ // 如果使用了代理服务器,X-Forwarded-For头部可以包含多个IP地址,从左到右是从原始客户端到最近的代理服务器
+ // 这里简单地取第一个IP地址作为客户端IP地址
+ return xForwardedForHeader.split(",")[0].trim();
+ }
+}
diff --git a/src/main/java/com/wcs/back/text/CharsetKit.java b/src/main/java/com/wcs/back/text/CharsetKit.java
new file mode 100644
index 0000000..f1d1e22
--- /dev/null
+++ b/src/main/java/com/wcs/back/text/CharsetKit.java
@@ -0,0 +1,91 @@
+package com.wcs.back.text;
+
+import com.wcs.back.util.StringUtils;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * 字符集工具类
+ *
+ * @author wms
+ */
+public class CharsetKit {
+ /**
+ * ISO-8859-1
+ */
+ public static final String ISO_8859_1 = "ISO-8859-1";
+ /**
+ * UTF-8
+ */
+ public static final String UTF_8 = "UTF-8";
+ /**
+ * GBK
+ */
+ public static final String GBK = "GBK";
+
+ /**
+ * ISO-8859-1
+ */
+ public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
+ /**
+ * UTF-8
+ */
+ public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
+ /**
+ * GBK
+ */
+ public static final Charset CHARSET_GBK = Charset.forName(GBK);
+
+ /**
+ * 转换为Charset对象
+ *
+ * @param charset 字符集,为空则返回默认字符集
+ * @return Charset
+ */
+ public static Charset charset(String charset) {
+ return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
+ }
+
+ /**
+ * 转换字符串的字符集编码
+ *
+ * @param source 字符串
+ * @param srcCharset 源字符集,默认ISO-8859-1
+ * @param destCharset 目标字符集,默认UTF-8
+ * @return 转换后的字符集
+ */
+ public static String convert(String source, String srcCharset, String destCharset) {
+ return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
+ }
+
+ /**
+ * 转换字符串的字符集编码
+ *
+ * @param source 字符串
+ * @param srcCharset 源字符集,默认ISO-8859-1
+ * @param destCharset 目标字符集,默认UTF-8
+ * @return 转换后的字符集
+ */
+ public static String convert(String source, Charset srcCharset, Charset destCharset) {
+ if (null == srcCharset) {
+ srcCharset = StandardCharsets.ISO_8859_1;
+ }
+
+ if (null == destCharset) {
+ destCharset = StandardCharsets.UTF_8;
+ }
+
+ if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset)) {
+ return source;
+ }
+ return new String(source.getBytes(srcCharset), destCharset);
+ }
+
+ /**
+ * @return 系统字符集编码
+ */
+ public static String systemCharset() {
+ return Charset.defaultCharset().name();
+ }
+}
diff --git a/src/main/java/com/wcs/back/text/Convert.java b/src/main/java/com/wcs/back/text/Convert.java
new file mode 100644
index 0000000..a83afe6
--- /dev/null
+++ b/src/main/java/com/wcs/back/text/Convert.java
@@ -0,0 +1,849 @@
+package com.wcs.back.text;
+
+import com.wcs.back.util.StringUtils;
+import org.apache.commons.lang3.ArrayUtils;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.text.NumberFormat;
+import java.util.Set;
+
+/**
+ * 类型转换器
+ *
+ * @author wms
+ */
+public class Convert {
+ /**
+ * 转换为字符串
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static String toStr(Object value, String defaultValue) {
+ if (null == value) {
+ return defaultValue;
+ }
+ if (value instanceof String) {
+ return (String) value;
+ }
+ return value.toString();
+ }
+
+ /**
+ * 转换为字符串
+ * 如果给定的值为null
,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static String toStr(Object value) {
+ return toStr(value, null);
+ }
+
+ /**
+ * 转换为字符
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static Character toChar(Object value, Character defaultValue) {
+ if (null == value) {
+ return defaultValue;
+ }
+ if (value instanceof Character) {
+ return (Character) value;
+ }
+
+ final String valueStr = toStr(value, null);
+ return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0);
+ }
+
+ /**
+ * 转换为字符
+ * 如果给定的值为null
,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static Character toChar(Object value) {
+ return toChar(value, null);
+ }
+
+ /**
+ * 转换为byte
+ * 如果给定的值为null
,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static Byte toByte(Object value, Byte defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (value instanceof Byte) {
+ return (Byte) value;
+ }
+ if (value instanceof Number) {
+ return ((Number) value).byteValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ try {
+ return Byte.parseByte(valueStr);
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为byte
+ * 如果给定的值为null
,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static Byte toByte(Object value) {
+ return toByte(value, null);
+ }
+
+ /**
+ * 转换为Short
+ * 如果给定的值为null
,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static Short toShort(Object value, Short defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (value instanceof Short) {
+ return (Short) value;
+ }
+ if (value instanceof Number) {
+ return ((Number) value).shortValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ try {
+ return Short.parseShort(valueStr.trim());
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为Short
+ * 如果给定的值为null
,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static Short toShort(Object value) {
+ return toShort(value, null);
+ }
+
+ /**
+ * 转换为Number
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static Number toNumber(Object value, Number defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (value instanceof Number) {
+ return (Number) value;
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ try {
+ return NumberFormat.getInstance().parse(valueStr);
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为Number
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static Number toNumber(Object value) {
+ return toNumber(value, null);
+ }
+
+ /**
+ * 转换为int
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static Integer toInt(Object value, Integer defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (value instanceof Integer) {
+ return (Integer) value;
+ }
+ if (value instanceof Number) {
+ return ((Number) value).intValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ try {
+ return Integer.parseInt(valueStr.trim());
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为int
+ * 如果给定的值为null
,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static Integer toInt(Object value) {
+ return toInt(value, null);
+ }
+
+ /**
+ * 转换为Integer数组
+ *
+ * @param str 被转换的值
+ * @return 结果
+ */
+ public static Integer[] toIntArray(String str) {
+ return toIntArray(",", str);
+ }
+
+ /**
+ * 转换为Long数组
+ *
+ * @param str 被转换的值
+ * @return 结果
+ */
+ public static Long[] toLongArray(String str) {
+ return toLongArray(",", str);
+ }
+
+ /**
+ * 转换为Integer数组
+ *
+ * @param split 分隔符
+ * @param split 被转换的值
+ * @return 结果
+ */
+ public static Integer[] toIntArray(String split, String str) {
+ if (StringUtils.isEmpty(str)) {
+ return new Integer[]{};
+ }
+ String[] arr = str.split(split);
+ final Integer[] ints = new Integer[arr.length];
+ for (int i = 0; i < arr.length; i++) {
+ final Integer v = toInt(arr[i], 0);
+ ints[i] = v;
+ }
+ return ints;
+ }
+
+ /**
+ * 转换为Long数组
+ *
+ * @param split 分隔符
+ * @param str 被转换的值
+ * @return 结果
+ */
+ public static Long[] toLongArray(String split, String str) {
+ if (StringUtils.isEmpty(str)) {
+ return new Long[]{};
+ }
+ String[] arr = str.split(split);
+ final Long[] longs = new Long[arr.length];
+ for (int i = 0; i < arr.length; i++) {
+ final Long v = toLong(arr[i], null);
+ longs[i] = v;
+ }
+ return longs;
+ }
+
+ /**
+ * 转换为String数组
+ *
+ * @param str 被转换的值
+ * @return 结果
+ */
+ public static String[] toStrArray(String str) {
+ return toStrArray(",", str);
+ }
+
+ /**
+ * 转换为String数组
+ *
+ * @param split 分隔符
+ * @param split 被转换的值
+ * @return 结果
+ */
+ public static String[] toStrArray(String split, String str) {
+ return str.split(split);
+ }
+
+ /**
+ * 转换为long
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static Long toLong(Object value, Long defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (value instanceof Long) {
+ return (Long) value;
+ }
+ if (value instanceof Number) {
+ return ((Number) value).longValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ try {
+ // 支持科学计数法
+ return new BigDecimal(valueStr.trim()).longValue();
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为long
+ * 如果给定的值为null
,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static Long toLong(Object value) {
+ return toLong(value, null);
+ }
+
+ /**
+ * 转换为double
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static Double toDouble(Object value, Double defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (value instanceof Double) {
+ return (Double) value;
+ }
+ if (value instanceof Number) {
+ return ((Number) value).doubleValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ try {
+ // 支持科学计数法
+ return new BigDecimal(valueStr.trim()).doubleValue();
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为double
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static Double toDouble(Object value) {
+ return toDouble(value, null);
+ }
+
+ /**
+ * 转换为Float
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static Float toFloat(Object value, Float defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (value instanceof Float) {
+ return (Float) value;
+ }
+ if (value instanceof Number) {
+ return ((Number) value).floatValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ try {
+ return Float.parseFloat(valueStr.trim());
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为Float
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static Float toFloat(Object value) {
+ return toFloat(value, null);
+ }
+
+ /**
+ * 转换为boolean
+ * String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static Boolean toBool(Object value, Boolean defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (value instanceof Boolean) {
+ return (Boolean) value;
+ }
+ String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ valueStr = valueStr.trim().toLowerCase();
+ switch (valueStr) {
+ case "true":
+ case "yes":
+ case "ok":
+ case "1":
+ return true;
+ case "false":
+ case "no":
+ case "0":
+ return false;
+ default:
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为boolean
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static Boolean toBool(Object value) {
+ return toBool(value, null);
+ }
+
+ /**
+ * 转换为Enum对象
+ * 如果给定的值为空,或者转换失败,返回默认值
+ *
+ * @param clazz Enum的Class
+ * @param value 值
+ * @param defaultValue 默认值
+ * @return Enum
+ */
+ public static > E toEnum(Class clazz, Object value, E defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (clazz.isAssignableFrom(value.getClass())) {
+ @SuppressWarnings("unchecked")
+ E myE = (E) value;
+ return myE;
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ try {
+ return Enum.valueOf(clazz, valueStr);
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为Enum对象
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ *
+ * @param clazz Enum的Class
+ * @param value 值
+ * @return Enum
+ */
+ public static > E toEnum(Class clazz, Object value) {
+ return toEnum(clazz, value, null);
+ }
+
+ /**
+ * 转换为BigInteger
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static BigInteger toBigInteger(Object value, BigInteger defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (value instanceof BigInteger) {
+ return (BigInteger) value;
+ }
+ if (value instanceof Long) {
+ return BigInteger.valueOf((Long) value);
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ try {
+ return new BigInteger(valueStr);
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为BigInteger
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static BigInteger toBigInteger(Object value) {
+ return toBigInteger(value, null);
+ }
+
+ /**
+ * 转换为BigDecimal
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @param defaultValue 转换错误时的默认值
+ * @return 结果
+ */
+ public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) {
+ if (value == null) {
+ return defaultValue;
+ }
+ if (value instanceof BigDecimal) {
+ return (BigDecimal) value;
+ }
+ if (value instanceof Long) {
+ return new BigDecimal((Long) value);
+ }
+ if (value instanceof Double) {
+ return BigDecimal.valueOf((Double) value);
+ }
+ if (value instanceof Integer) {
+ return new BigDecimal((Integer) value);
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr)) {
+ return defaultValue;
+ }
+ try {
+ return new BigDecimal(valueStr);
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 转换为BigDecimal
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错
+ *
+ * @param value 被转换的值
+ * @return 结果
+ */
+ public static BigDecimal toBigDecimal(Object value) {
+ return toBigDecimal(value, null);
+ }
+
+ /**
+ * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
+ *
+ * @param obj 对象
+ * @return 字符串
+ */
+ public static String utf8Str(Object obj) {
+ return str(obj, CharsetKit.CHARSET_UTF_8);
+ }
+
+ /**
+ * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
+ *
+ * @param obj 对象
+ * @param charsetName 字符集
+ * @return 字符串
+ */
+ public static String str(Object obj, String charsetName) {
+ return str(obj, Charset.forName(charsetName));
+ }
+
+ /**
+ * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
+ *
+ * @param obj 对象
+ * @param charset 字符集
+ * @return 字符串
+ */
+ public static String str(Object obj, Charset charset) {
+ if (null == obj) {
+ return null;
+ }
+
+ if (obj instanceof String) {
+ return (String) obj;
+ } else if (obj instanceof byte[]) {
+ return str((byte[]) obj, charset);
+ } else if (obj instanceof Byte[]) {
+ byte[] bytes = ArrayUtils.toPrimitive((Byte[]) obj);
+ return str(bytes, charset);
+ } else if (obj instanceof ByteBuffer) {
+ return str((ByteBuffer) obj, charset);
+ }
+ return obj.toString();
+ }
+
+ /**
+ * 将byte数组转为字符串
+ *
+ * @param bytes byte数组
+ * @param charset 字符集
+ * @return 字符串
+ */
+ public static String str(byte[] bytes, String charset) {
+ return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset));
+ }
+
+ /**
+ * 解码字节码
+ *
+ * @param data 字符串
+ * @param charset 字符集,如果此字段为空,则解码的结果取决于平台
+ * @return 解码后的字符串
+ */
+ public static String str(byte[] data, Charset charset) {
+ if (data == null) {
+ return null;
+ }
+
+ if (null == charset) {
+ return new String(data);
+ }
+ return new String(data, charset);
+ }
+
+ /**
+ * 将编码的byteBuffer数据转换为字符串
+ *
+ * @param data 数据
+ * @param charset 字符集,如果为空使用当前系统字符集
+ * @return 字符串
+ */
+ public static String str(ByteBuffer data, String charset) {
+ if (data == null) {
+ return null;
+ }
+
+ return str(data, Charset.forName(charset));
+ }
+
+ /**
+ * 将编码的byteBuffer数据转换为字符串
+ *
+ * @param data 数据
+ * @param charset 字符集,如果为空使用当前系统字符集
+ * @return 字符串
+ */
+ public static String str(ByteBuffer data, Charset charset) {
+ if (null == charset) {
+ charset = Charset.defaultCharset();
+ }
+ return charset.decode(data).toString();
+ }
+
+ // ----------------------------------------------------------------------- 全角半角转换
+
+ /**
+ * 半角转全角
+ *
+ * @param input String.
+ * @return 全角字符串.
+ */
+ public static String toSBC(String input) {
+ return toSBC(input, null);
+ }
+
+ /**
+ * 半角转全角
+ *
+ * @param input String
+ * @param notConvertSet 不替换的字符集合
+ * @return 全角字符串.
+ */
+ public static String toSBC(String input, Set notConvertSet) {
+ char[] c = input.toCharArray();
+ for (int i = 0; i < c.length; i++) {
+ if (null != notConvertSet && notConvertSet.contains(c[i])) {
+ // 跳过不替换的字符
+ continue;
+ }
+
+ if (c[i] == ' ') {
+ c[i] = '\u3000';
+ } else if (c[i] < '\177') {
+ c[i] = (char) (c[i] + 65248);
+
+ }
+ }
+ return new String(c);
+ }
+
+ /**
+ * 全角转半角
+ *
+ * @param input String.
+ * @return 半角字符串
+ */
+ public static String toDBC(String input) {
+ return toDBC(input, null);
+ }
+
+ /**
+ * 替换全角为半角
+ *
+ * @param text 文本
+ * @param notConvertSet 不替换的字符集合
+ * @return 替换后的字符
+ */
+ public static String toDBC(String text, Set notConvertSet) {
+ char[] c = text.toCharArray();
+ for (int i = 0; i < c.length; i++) {
+ if (null != notConvertSet && notConvertSet.contains(c[i])) {
+ // 跳过不替换的字符
+ continue;
+ }
+
+ if (c[i] == '\u3000') {
+ c[i] = ' ';
+ } else if (c[i] > '\uFF00' && c[i] < '\uFF5F') {
+ c[i] = (char) (c[i] - 65248);
+ }
+ }
+ String returnString = new String(c);
+
+ return returnString;
+ }
+
+ /**
+ * 数字金额大写转换 先写个完整的然后将如零拾替换成零
+ *
+ * @param n 数字
+ * @return 中文大写数字
+ */
+ public static String digitUppercase(double n) {
+ String[] fraction = {"角", "分"};
+ String[] digit = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
+ String[][] unit = {{"元", "万", "亿"}, {"", "拾", "佰", "仟"}};
+
+ String head = n < 0 ? "负" : "";
+ n = Math.abs(n);
+
+ String s = "";
+ for (int i = 0; i < fraction.length; i++) {
+ s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
+ }
+ if (s.length() < 1) {
+ s = "整";
+ }
+ int integerPart = (int) Math.floor(n);
+
+ for (int i = 0; i < unit[0].length && integerPart > 0; i++) {
+ String p = "";
+ for (int j = 0; j < unit[1].length && n > 0; j++) {
+ p = digit[integerPart % 10] + unit[1][j] + p;
+ integerPart = integerPart / 10;
+ }
+ s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s;
+ }
+ return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整");
+ }
+}
diff --git a/src/main/java/com/wcs/back/text/StrFormatter.java b/src/main/java/com/wcs/back/text/StrFormatter.java
new file mode 100644
index 0000000..3a1735c
--- /dev/null
+++ b/src/main/java/com/wcs/back/text/StrFormatter.java
@@ -0,0 +1,76 @@
+package com.wcs.back.text;
+
+import com.wcs.back.util.StringUtils;
+
+/**
+ * 字符串格式化
+ *
+ * @author wms
+ */
+public class StrFormatter {
+ public static final String EMPTY_JSON = "{}";
+ public static final char C_BACKSLASH = '\\';
+ public static final char C_DELIM_START = '{';
+ public static final char C_DELIM_END = '}';
+
+ /**
+ * 格式化字符串
+ * 此方法只是简单将占位符 {} 按照顺序替换为参数
+ * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ *
+ * @param strPattern 字符串模板
+ * @param argArray 参数列表
+ * @return 结果
+ */
+ public static String format(final String strPattern, final Object... argArray) {
+ if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray)) {
+ return strPattern;
+ }
+ final int strPatternLength = strPattern.length();
+
+ // 初始化定义好的长度以获得更好的性能
+ StringBuilder sbuf = new StringBuilder(strPatternLength + 50);
+
+ int handledPosition = 0;
+ int delimIndex;// 占位符所在位置
+ for (int argIndex = 0; argIndex < argArray.length; argIndex++) {
+ delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
+ if (delimIndex == -1) {
+ if (handledPosition == 0) {
+ return strPattern;
+ } else { // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果
+ sbuf.append(strPattern, handledPosition, strPatternLength);
+ return sbuf.toString();
+ }
+ } else {
+ if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH) {
+ if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH) {
+ // 转义符之前还有一个转义符,占位符依旧有效
+ sbuf.append(strPattern, handledPosition, delimIndex - 1);
+ sbuf.append(Convert.utf8Str(argArray[argIndex]));
+ handledPosition = delimIndex + 2;
+ } else {
+ // 占位符被转义
+ argIndex--;
+ sbuf.append(strPattern, handledPosition, delimIndex - 1);
+ sbuf.append(C_DELIM_START);
+ handledPosition = delimIndex + 1;
+ }
+ } else {
+ // 正常占位符
+ sbuf.append(strPattern, handledPosition, delimIndex);
+ sbuf.append(Convert.utf8Str(argArray[argIndex]));
+ handledPosition = delimIndex + 2;
+ }
+ }
+ }
+ // 加入最后一个占位符后所有的字符
+ sbuf.append(strPattern, handledPosition, strPattern.length());
+
+ return sbuf.toString();
+ }
+}
diff --git a/src/main/java/com/wcs/back/util/StringUtils.java b/src/main/java/com/wcs/back/util/StringUtils.java
new file mode 100644
index 0000000..0dc6a93
--- /dev/null
+++ b/src/main/java/com/wcs/back/util/StringUtils.java
@@ -0,0 +1,610 @@
+package com.wcs.back.util;
+
+import com.wcs.back.constant.Constants;
+import com.wcs.back.text.StrFormatter;
+import org.springframework.util.AntPathMatcher;
+
+import java.util.*;
+
+/**
+ * 字符串工具类
+ *
+ * @author wms
+ */
+public class StringUtils extends org.apache.commons.lang3.StringUtils
+{
+ /** 空字符串 */
+ private static final String NULLSTR = "";
+
+ /** 下划线 */
+ private static final char SEPARATOR = '_';
+
+ /**
+ * 获取参数不为空值
+ *
+ * @param value defaultValue 要判断的value
+ * @return value 返回值
+ */
+ public static T nvl(T value, T defaultValue)
+ {
+ return value != null ? value : defaultValue;
+ }
+
+ /**
+ * * 判断一个Collection是否为空, 包含List,Set,Queue
+ *
+ * @param coll 要判断的Collection
+ * @return true:为空 false:非空
+ */
+ public static boolean isEmpty(Collection> coll)
+ {
+ return isNull(coll) || coll.isEmpty();
+ }
+
+ /**
+ * * 判断一个Collection是否非空,包含List,Set,Queue
+ *
+ * @param coll 要判断的Collection
+ * @return true:非空 false:空
+ */
+ public static boolean isNotEmpty(Collection> coll)
+ {
+ return !isEmpty(coll);
+ }
+
+ /**
+ * * 判断一个对象数组是否为空
+ *
+ * @param objects 要判断的对象数组
+ ** @return true:为空 false:非空
+ */
+ public static boolean isEmpty(Object[] objects)
+ {
+ return isNull(objects) || (objects.length == 0);
+ }
+
+ /**
+ * * 判断一个对象数组是否非空
+ *
+ * @param objects 要判断的对象数组
+ * @return true:非空 false:空
+ */
+ public static boolean isNotEmpty(Object[] objects)
+ {
+ return !isEmpty(objects);
+ }
+
+ /**
+ * * 判断一个Map是否为空
+ *
+ * @param map 要判断的Map
+ * @return true:为空 false:非空
+ */
+ public static boolean isEmpty(Map, ?> map)
+ {
+ return isNull(map) || map.isEmpty();
+ }
+
+ /**
+ * * 判断一个Map是否为空
+ *
+ * @param map 要判断的Map
+ * @return true:非空 false:空
+ */
+ public static boolean isNotEmpty(Map, ?> map)
+ {
+ return !isEmpty(map);
+ }
+
+ /**
+ * * 判断一个字符串是否为空串
+ *
+ * @param str String
+ * @return true:为空 false:非空
+ */
+ public static boolean isEmpty(String str)
+ {
+ return isNull(str) || NULLSTR.equals(str.trim());
+ }
+
+ /**
+ * * 判断一个字符串是否为非空串
+ *
+ * @param str String
+ * @return true:非空串 false:空串
+ */
+ public static boolean isNotEmpty(String str)
+ {
+ return !isEmpty(str);
+ }
+
+ /**
+ * * 判断一个对象是否为空
+ *
+ * @param object Object
+ * @return true:为空 false:非空
+ */
+ public static boolean isNull(Object object)
+ {
+ return object == null;
+ }
+
+ /**
+ * * 判断一个对象是否非空
+ *
+ * @param object Object
+ * @return true:非空 false:空
+ */
+ public static boolean isNotNull(Object object)
+ {
+ return !isNull(object);
+ }
+
+ /**
+ * * 判断一个对象是否是数组类型(Java基本型别的数组)
+ *
+ * @param object 对象
+ * @return true:是数组 false:不是数组
+ */
+ public static boolean isArray(Object object)
+ {
+ return isNotNull(object) && object.getClass().isArray();
+ }
+
+ /**
+ * 去空格
+ */
+ public static String trim(String str)
+ {
+ return (str == null ? "" : str.trim());
+ }
+
+ /**
+ * 截取字符串
+ *
+ * @param str 字符串
+ * @param start 开始
+ * @return 结果
+ */
+ public static String substring(final String str, int start)
+ {
+ if (str == null)
+ {
+ return NULLSTR;
+ }
+
+ if (start < 0)
+ {
+ start = str.length() + start;
+ }
+
+ if (start < 0)
+ {
+ start = 0;
+ }
+ if (start > str.length())
+ {
+ return NULLSTR;
+ }
+
+ return str.substring(start);
+ }
+
+ /**
+ * 截取字符串
+ *
+ * @param str 字符串
+ * @param start 开始
+ * @param end 结束
+ * @return 结果
+ */
+ public static String substring(final String str, int start, int end)
+ {
+ if (str == null)
+ {
+ return NULLSTR;
+ }
+
+ if (end < 0)
+ {
+ end = str.length() + end;
+ }
+ if (start < 0)
+ {
+ start = str.length() + start;
+ }
+
+ if (end > str.length())
+ {
+ end = str.length();
+ }
+
+ if (start > end)
+ {
+ return NULLSTR;
+ }
+
+ if (start < 0)
+ {
+ start = 0;
+ }
+ if (end < 0)
+ {
+ end = 0;
+ }
+
+ return str.substring(start, end);
+ }
+
+ /**
+ * 格式化文本, {} 表示占位符
+ * 此方法只是简单将占位符 {} 按照顺序替换为参数
+ * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ *
+ * @param template 文本模板,被替换的部分用 {} 表示
+ * @param params 参数值
+ * @return 格式化后的文本
+ */
+ public static String format(String template, Object... params)
+ {
+ if (isEmpty(params) || isEmpty(template))
+ {
+ return template;
+ }
+ return StrFormatter.format(template, params);
+ }
+
+ /**
+ * 是否为http(s)://开头
+ *
+ * @param link 链接
+ * @return 结果
+ */
+ public static boolean ishttp(String link)
+ {
+ return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS);
+ }
+
+ /**
+ * 字符串转set
+ *
+ * @param str 字符串
+ * @param sep 分隔符
+ * @return set集合
+ */
+ public static final Set str2Set(String str, String sep)
+ {
+ return new HashSet(str2List(str, sep, true, false));
+ }
+
+ /**
+ * 字符串转list
+ *
+ * @param str 字符串
+ * @param sep 分隔符
+ * @param filterBlank 过滤纯空白
+ * @param trim 去掉首尾空白
+ * @return list集合
+ */
+ public static final List str2List(String str, String sep, boolean filterBlank, boolean trim)
+ {
+ List list = new ArrayList();
+ if (StringUtils.isEmpty(str))
+ {
+ return list;
+ }
+
+ // 过滤空白字符串
+ if (filterBlank && StringUtils.isBlank(str))
+ {
+ return list;
+ }
+ String[] split = str.split(sep);
+ for (String string : split)
+ {
+ if (filterBlank && StringUtils.isBlank(string))
+ {
+ continue;
+ }
+ if (trim)
+ {
+ string = string.trim();
+ }
+ list.add(string);
+ }
+
+ return list;
+ }
+
+ /**
+ * 判断给定的collection列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value
+ *
+ * @param collection 给定的集合
+ * @param array 给定的数组
+ * @return boolean 结果
+ */
+ public static boolean containsAny(Collection collection, String... array)
+ {
+ if (isEmpty(collection) || isEmpty(array))
+ {
+ return false;
+ }
+ else
+ {
+ for (String str : array)
+ {
+ if (collection.contains(str))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
+ *
+ * @param cs 指定字符串
+ * @param searchCharSequences 需要检查的字符串数组
+ * @return 是否包含任意一个字符串
+ */
+ public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences)
+ {
+ if (isEmpty(cs) || isEmpty(searchCharSequences))
+ {
+ return false;
+ }
+ for (CharSequence testStr : searchCharSequences)
+ {
+ if (containsIgnoreCase(cs, testStr))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 驼峰转下划线命名
+ */
+ public static String toUnderScoreCase(String str)
+ {
+ if (str == null)
+ {
+ return null;
+ }
+ StringBuilder sb = new StringBuilder();
+ // 前置字符是否大写
+ boolean preCharIsUpperCase = true;
+ // 当前字符是否大写
+ boolean curreCharIsUpperCase = true;
+ // 下一字符是否大写
+ boolean nexteCharIsUpperCase = true;
+ for (int i = 0; i < str.length(); i++)
+ {
+ char c = str.charAt(i);
+ if (i > 0)
+ {
+ preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
+ }
+ else
+ {
+ preCharIsUpperCase = false;
+ }
+
+ curreCharIsUpperCase = Character.isUpperCase(c);
+
+ if (i < (str.length() - 1))
+ {
+ nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
+ }
+
+ if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
+ {
+ sb.append(SEPARATOR);
+ }
+ else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
+ {
+ sb.append(SEPARATOR);
+ }
+ sb.append(Character.toLowerCase(c));
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * 是否包含字符串
+ *
+ * @param str 验证字符串
+ * @param strs 字符串组
+ * @return 包含返回true
+ */
+ public static boolean inStringIgnoreCase(String str, String... strs)
+ {
+ if (str != null && strs != null)
+ {
+ for (String s : strs)
+ {
+ if (str.equalsIgnoreCase(trim(s)))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld
+ *
+ * @param name 转换前的下划线大写方式命名的字符串
+ * @return 转换后的驼峰式命名的字符串
+ */
+ public static String convertToCamelCase(String name)
+ {
+ StringBuilder result = new StringBuilder();
+ // 快速检查
+ if (name == null || name.isEmpty())
+ {
+ // 没必要转换
+ return "";
+ }
+ else if (!name.contains("_"))
+ {
+ // 不含下划线,仅将首字母大写
+ return name.substring(0, 1).toUpperCase() + name.substring(1);
+ }
+ // 用下划线将原始字符串分割
+ String[] camels = name.split("_");
+ for (String camel : camels)
+ {
+ // 跳过原始字符串中开头、结尾的下换线或双重下划线
+ if (camel.isEmpty())
+ {
+ continue;
+ }
+ // 首字母大写
+ result.append(camel.substring(0, 1).toUpperCase());
+ result.append(camel.substring(1).toLowerCase());
+ }
+ return result.toString();
+ }
+
+ /**
+ * 驼峰式命名法
+ * 例如:user_name->userName
+ */
+ public static String toCamelCase(String s)
+ {
+ if (s == null)
+ {
+ return null;
+ }
+ if (s.indexOf(SEPARATOR) == -1)
+ {
+ return s;
+ }
+ s = s.toLowerCase();
+ StringBuilder sb = new StringBuilder(s.length());
+ boolean upperCase = false;
+ for (int i = 0; i < s.length(); i++)
+ {
+ char c = s.charAt(i);
+
+ if (c == SEPARATOR)
+ {
+ upperCase = true;
+ }
+ else if (upperCase)
+ {
+ sb.append(Character.toUpperCase(c));
+ upperCase = false;
+ }
+ else
+ {
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
+ *
+ * @param str 指定字符串
+ * @param strs 需要检查的字符串数组
+ * @return 是否匹配
+ */
+ public static boolean matches(String str, List strs)
+ {
+ if (isEmpty(str) || isEmpty(strs))
+ {
+ return false;
+ }
+ for (String pattern : strs)
+ {
+ if (isMatch(pattern, str))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 判断url是否与规则配置:
+ * ? 表示单个字符;
+ * * 表示一层路径内的任意字符串,不可跨层级;
+ * ** 表示任意层路径;
+ *
+ * @param pattern 匹配规则
+ * @param url 需要匹配的url
+ * @return
+ */
+ public static boolean isMatch(String pattern, String url)
+ {
+ AntPathMatcher matcher = new AntPathMatcher();
+ return matcher.match(pattern, url);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static T cast(Object obj)
+ {
+ return (T) obj;
+ }
+
+ /**
+ * 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。
+ *
+ * @param num 数字对象
+ * @param size 字符串指定长度
+ * @return 返回数字的字符串格式,该字符串为指定长度。
+ */
+ public static final String padl(final Number num, final int size)
+ {
+ return padl(num.toString(), size, '0');
+ }
+
+ /**
+ * 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。
+ *
+ * @param s 原始字符串
+ * @param size 字符串指定长度
+ * @param c 用于补齐的字符
+ * @return 返回指定长度的字符串,由原字符串左补齐或截取得到。
+ */
+ public static final String padl(final String s, final int size, final char c)
+ {
+ final StringBuilder sb = new StringBuilder(size);
+ if (s != null)
+ {
+ final int len = s.length();
+ if (s.length() <= size)
+ {
+ for (int i = size - len; i > 0; i--)
+ {
+ sb.append(c);
+ }
+ sb.append(s);
+ }
+ else
+ {
+ return s.substring(len - size, len);
+ }
+ }
+ else
+ {
+ for (int i = size; i > 0; i--)
+ {
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/wcs/back/util/http/HttpUtils.java b/src/main/java/com/wcs/back/util/http/HttpUtils.java
new file mode 100644
index 0000000..fc83736
--- /dev/null
+++ b/src/main/java/com/wcs/back/util/http/HttpUtils.java
@@ -0,0 +1,320 @@
+package com.wcs.back.util.http;
+
+import com.wcs.back.constant.Constants;
+import com.wcs.back.util.StringUtils;
+import org.apache.http.client.ResponseHandler;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.BasicResponseHandler;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.*;
+import java.io.*;
+import java.net.ConnectException;
+import java.net.SocketTimeoutException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.charset.StandardCharsets;
+import java.security.cert.X509Certificate;
+
+/**
+ * 通用http发送方法
+ *
+ * @author wms
+ */
+public class HttpUtils
+{
+ private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
+
+ /**
+ * 向指定 URL 发送GET方法的请求
+ *
+ * @param url 发送请求的 URL
+ * @return 所代表远程资源的响应结果
+ */
+ public static String sendGet(String url)
+ {
+ return sendGet(url, StringUtils.EMPTY);
+ }
+
+ /**
+ * 向指定 URL 发送GET方法的请求
+ *
+ * @param url 发送请求的 URL
+ * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
+ * @return 所代表远程资源的响应结果
+ */
+ public static String sendGet(String url, String param)
+ {
+ return sendGet(url, param, Constants.UTF8);
+ }
+
+ /**
+ * 向指定 URL 发送GET方法的请求
+ *
+ * @param url 发送请求的 URL
+ * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
+ * @param contentType 编码类型
+ * @return 所代表远程资源的响应结果
+ */
+ public static String sendGet(String url, String param, String contentType)
+ {
+ StringBuilder result = new StringBuilder();
+ BufferedReader in = null;
+ try
+ {
+ String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url;
+ log.info("sendGet - {}", urlNameString);
+ URL realUrl = new URL(urlNameString);
+ URLConnection connection = realUrl.openConnection();
+ connection.setRequestProperty("accept", "*/*");
+ connection.setRequestProperty("connection", "Keep-Alive");
+ connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+ connection.connect();
+ in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
+ String line;
+ while ((line = in.readLine()) != null)
+ {
+ result.append(line);
+ }
+ log.info("recv - {}", result);
+ }
+ catch (ConnectException e)
+ {
+ log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
+ }
+ catch (SocketTimeoutException e)
+ {
+ log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
+ }
+ catch (IOException e)
+ {
+ log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
+ }
+ catch (Exception e)
+ {
+ log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
+ }
+ finally
+ {
+ try
+ {
+ if (in != null)
+ {
+ in.close();
+ }
+ }
+ catch (Exception ex)
+ {
+ log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
+ }
+ }
+ return result.toString();
+ }
+
+ /**
+ * 向指定 URL 发送POST方法的请求
+ *
+ * @param url 发送请求的 URL
+ * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
+ * @return 所代表远程资源的响应结果
+ */
+ public static String sendPost(String url, String param)
+ {
+ PrintWriter out = null;
+ BufferedReader in = null;
+ StringBuilder result = new StringBuilder();
+ try
+ {
+ log.info("sendPost - {}", url);
+ URL realUrl = new URL(url);
+ URLConnection conn = realUrl.openConnection();
+ conn.setRequestProperty("accept", "*/*");
+ conn.setRequestProperty("connection", "Keep-Alive");
+ conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+ conn.setRequestProperty("Accept-Charset", "utf-8");
+ conn.setRequestProperty("contentType", "utf-8");
+ conn.setDoOutput(true);
+ conn.setDoInput(true);
+ out = new PrintWriter(conn.getOutputStream());
+ out.print(param);
+ out.flush();
+ in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
+ String line;
+ while ((line = in.readLine()) != null)
+ {
+ result.append(line);
+ }
+ log.info("recv - {}", result);
+ }
+ catch (ConnectException e)
+ {
+ log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
+ }
+ catch (SocketTimeoutException e)
+ {
+ log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
+ }
+ catch (IOException e)
+ {
+ log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
+ }
+ catch (Exception e)
+ {
+ log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
+ }
+ finally
+ {
+ try
+ {
+ if (out != null)
+ {
+ out.close();
+ }
+ if (in != null)
+ {
+ in.close();
+ }
+ }
+ catch (IOException ex)
+ {
+ log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
+ }
+ }
+ return result.toString();
+ }
+
+ public static String sendSSLPost(String url, String param)
+ {
+ StringBuilder result = new StringBuilder();
+ String urlNameString = url + "?" + param;
+ try
+ {
+ log.info("sendSSLPost - {}", urlNameString);
+ SSLContext sc = SSLContext.getInstance("SSL");
+ sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom());
+ URL console = new URL(urlNameString);
+ HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
+ conn.setRequestProperty("accept", "*/*");
+ conn.setRequestProperty("connection", "Keep-Alive");
+ conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+ conn.setRequestProperty("Accept-Charset", "utf-8");
+ conn.setRequestProperty("contentType", "utf-8");
+ conn.setDoOutput(true);
+ conn.setDoInput(true);
+
+ conn.setSSLSocketFactory(sc.getSocketFactory());
+ conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
+ conn.connect();
+ InputStream is = conn.getInputStream();
+ BufferedReader br = new BufferedReader(new InputStreamReader(is));
+ String ret = "";
+ while ((ret = br.readLine()) != null)
+ {
+ if (ret != null && !"".equals(ret.trim()))
+ {
+ result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8));
+ }
+ }
+ log.info("recv - {}", result);
+ conn.disconnect();
+ br.close();
+ }
+ catch (ConnectException e)
+ {
+ log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e);
+ }
+ catch (SocketTimeoutException e)
+ {
+ log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e);
+ }
+ catch (IOException e)
+ {
+ log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e);
+ }
+ catch (Exception e)
+ {
+ log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e);
+ }
+ return result.toString();
+ }
+
+ /**
+ * post请求参数为json格式
+ * @param url url
+ * @param json json
+ * @return String
+ */
+ public static String HttpPostWithJson(String url, String json) {
+ String returnValue = "{\"resultCode\":0,\"message\":\"接口调用失败,请求异常\"}";
+ CloseableHttpClient httpClient = HttpClients.createDefault();
+ ResponseHandler responseHandler = new BasicResponseHandler();
+ try {
+ //第一步:创建HttpClient对象
+ httpClient = HttpClients.createDefault();
+ //第二步:创建httpPost对象
+ HttpPost httpPost = new HttpPost(url);
+ // 设置超时时间
+ int socketTimeout = 10000; // 设置 socketTimeout 为 10000 毫秒(10 秒)
+ int connectTimeout = 5000; // 设置 connectTimeout 为 5000 毫秒(5 秒)
+ RequestConfig requestConfig = RequestConfig.custom()
+ .setSocketTimeout(socketTimeout)
+ .setConnectTimeout(connectTimeout)
+ .build();
+ httpPost.setConfig(requestConfig);
+
+ //第三步:给httpPost设置JSON格式的参数
+ if (!StringUtils.isEmpty(json)){
+ StringEntity requestEntity = new StringEntity(json, "utf-8");
+ requestEntity.setContentEncoding("UTF-8");
+ httpPost.setEntity(requestEntity);
+ }
+ httpPost.setHeader("Content-type", "application/json");
+ //第四步:发送HttpPost请求,获取返回值
+ //调接口获取返回值时,必须用此方法
+ returnValue = httpClient.execute(httpPost, responseHandler);
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ httpClient.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ //第五步:处理返回值
+ return returnValue;
+ }
+
+ private static class TrustAnyTrustManager implements X509TrustManager
+ {
+ @Override
+ public void checkClientTrusted(X509Certificate[] chain, String authType)
+ {
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] chain, String authType)
+ {
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers()
+ {
+ return new X509Certificate[] {};
+ }
+ }
+
+ private static class TrustAnyHostnameVerifier implements HostnameVerifier
+ {
+ @Override
+ public boolean verify(String hostname, SSLSession session)
+ {
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/application-druid.yml b/src/main/resources/application-druid.yml
new file mode 100644
index 0000000..d26a501
--- /dev/null
+++ b/src/main/resources/application-druid.yml
@@ -0,0 +1,5 @@
+wms:
+ httpUrl: :50902/wcs/finishTaskCallBack
+ roboticArmUrl: :50902/wcs/roboticArmTaskCallBack
+ ctuUrl: :50902/wcs/ctuTaskCallBack
+ drumLineTaskHttpUrl: :50902/wcs/drumLineTaskCallBack
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
new file mode 100644
index 0000000..8d7e0ab
--- /dev/null
+++ b/src/main/resources/application.yml
@@ -0,0 +1,59 @@
+# 项目相关配置
+wms:
+ # 名称
+ name: WcsBack
+ # 版本
+ version: 1.0.0
+ # 版权年份
+ copyrightYear: 2023
+
+# 开发环境配置
+server:
+ # 服务器的HTTP端口,默认为5050
+ port: 8080
+ servlet:
+ # 应用的访问路径
+ context-path: /
+ tomcat:
+ # tomcat的URI编码
+ uri-encoding: UTF-8
+ # 连接数满后的排队数,默认为100
+ accept-count: 1000
+ threads:
+ # tomcat最大线程数,默认为200
+ max: 800
+ # Tomcat启动初始化的线程数,默认值10
+ min-spare: 100
+
+# 日志配置
+logging:
+ level:
+ com.wms: debug
+ org.springframework: warn
+
+# Swagger配置
+swagger:
+ # 是否开启swagger
+ enabled: true
+ # 请求前缀
+ pathMapping: /dev-api
+
+# 防止XSS攻击
+xss:
+ # 过滤开关
+ enabled: true
+ # 排除链接(多个用逗号分隔)
+ excludes: /system/notice
+ # 匹配链接
+ urlPatterns: /system/*,/monitor/*,/tool/*
+
+# Spring配置
+spring:
+ # 资源信息
+ profiles:
+ active: druid
+ # 服务模块
+ devtools:
+ restart:
+ # 热部署开关
+ enabled: true
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
new file mode 100644
index 0000000..20f09c6
--- /dev/null
+++ b/src/main/resources/logback.xml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ ${log.pattern}
+
+
+
+
+
+ ${log.path}/sys-info.log
+
+
+
+ ${log.path}/sys-info.%d{yyyy-MM-dd}.log
+
+ 60
+
+
+ ${log.pattern}
+
+
+
+ INFO
+
+ ACCEPT
+
+ DENY
+
+
+
+
+ ${log.path}/sys-error.log
+
+
+
+ ${log.path}/sys-error.%d{yyyy-MM-dd}.log
+
+ 60
+
+
+ ${log.pattern}
+
+
+
+ ERROR
+
+ ACCEPT
+
+ DENY
+
+
+
+
+
+ ${log.path}/sys-user.log
+
+
+ ${log.path}/sys-user.%d{yyyy-MM-dd}.log
+
+ 60
+
+
+ ${log.pattern}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file