作者 钟来

初始提交

正在显示 62 个修改的文件 包含 4460 行增加170 行删除
... ... @@ -12,12 +12,11 @@
<artifactId>lh-mqtt-service</artifactId>
<dependencies>
<!-- 通用工具-->
<!-- SpringBoot Web容器 -->
<dependency>
<groupId>com.zhonglai.luhui</groupId>
<artifactId>ruoyi-common</artifactId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 文档 -->
<dependency>
<groupId>io.springfox</groupId>
... ... @@ -52,16 +51,6 @@
<version>${swagger-ui.version}</version>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<!-- 建议使用最新版本,最新版本请从项目首页查找 -->
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
</dependency>
<!-- mqtt -->
<dependency>
<groupId>org.eclipse.paho</groupId>
... ... @@ -100,6 +89,42 @@
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
<!-- 支持data -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- 阿里JSON解析器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<!--常用工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- redis 缓存操作 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Token生成与解析-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
</dependencies>
<build>
... ...
... ... @@ -2,17 +2,15 @@ package com.zhonglai.luhui.mqtt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = {
"com.luhui.ly.device.mqtt.comm.config",
"com.luhui.ly.device.mqtt.comm.factory",
"com.luhui.ly.device.mqtt.comm.agreement",
"com.luhui.ly.device.mqtt.comm.service",
"com.zhonglai.luhui.mqtt.comm.config",
"com.zhonglai.luhui.mqtt.comm.agreement",
"com.zhonglai.luhui.mqtt.comm.service",
"com.zhonglai.luhui.mqtt.config",
"com.zhonglai.luhui.mqtt.agreement",
"com.zhonglai.luhui.mqtt.service",
... ...
package com.zhonglai.luhui.mqtt.agreement;
import com.luhui.ly.device.mqtt.comm.dto.ServerDto;
import com.luhui.ly.device.mqtt.comm.factory.BusinessAgreement;
import com.luhui.ly.device.mqtt.comm.factory.Topic;
import com.zhonglai.luhui.mqtt.dto.PutReqDto;
import com.zhonglai.luhui.mqtt.comm.dto.ServerDto;
import com.zhonglai.luhui.mqtt.comm.factory.BusinessAgreement;
import com.zhonglai.luhui.mqtt.comm.factory.Topic;
import com.zhonglai.luhui.mqtt.dto.topic.PutReqDto;
import org.springframework.stereotype.Service;
@Service("PUT_REQ")
... ... @@ -17,7 +17,6 @@ public class PutReqAgreement implements BusinessAgreement<PutReqDto> {
@Override
public PutReqDto toData(byte[] bytes) {
String str = new String(bytes);
return new PutReqDto().setData(str);
}
... ...
package com.zhonglai.luhui.mqtt.comm.clien;
import com.ruoyi.common.core.domain.Message;
import com.zhonglai.luhui.mqtt.comm.dto.ServerAgreementContent;
import com.zhonglai.luhui.mqtt.dto.Message;
/**
* 客户端链接
... ...
package com.zhonglai.luhui.mqtt.comm.clien.impl;
import com.ruoyi.common.core.domain.Message;
import com.ruoyi.common.core.domain.MessageCode;
import com.ruoyi.common.core.domain.MessageCodeType;
import com.zhonglai.luhui.mqtt.comm.clien.ClienConnection;
import com.zhonglai.luhui.mqtt.comm.dto.ServerAgreementContent;
import com.zhonglai.luhui.mqtt.dto.Message;
import com.zhonglai.luhui.mqtt.dto.MessageCode;
import com.zhonglai.luhui.mqtt.dto.MessageCodeType;
public class ClienConnectionImpl implements ClienConnection {
private Message message = new Message();
... ...
package com.zhonglai.luhui.mqtt.comm.config;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
@Aspect
@Component
public class ControllerLogAspect {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Pointcut("execution(public * com.zhonglai.luhui.mqtt.*.controller..*.*(..))")
public void controllerLog() {
}
@Before("controllerLog()")
public void doBefore(JoinPoint joinPoint)
{
// 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
Enumeration<String> hs = request.getHeaderNames();
Map<String,Object> map = new HashMap<>();
while (hs.hasMoreElements())
{
String key= hs.nextElement();
map.put(key,request.getHeader(key));
}
logger.info("请求url:{},请求head:{},请求IP:{},请求方法:{},请求参数:{}",request.getRequestURL(),map,request.getRemoteAddr(),joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName(),joinPoint.getArgs());
}
@AfterReturning(returning = "ret", pointcut = "controllerLog()")
public void doAfterReturning(Object ret) {
// 处理完请求,返回内容
logger.info("返回 {} " , GsonConstructor.get().toJson(ret));
}
}
package com.zhonglai.luhui.mqtt.comm.config;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.utils.http.HttpUtils;
import com.zhonglai.luhui.mqtt.comm.util.http.HttpUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
... ...
... ... @@ -50,7 +50,7 @@ public class BaseDao {
{//
Method method;
try {
method = object.getClass().getMethod("get"+com.ruoyi.common.utils.StringUtils.getName(field.getName()));
method = object.getClass().getMethod("get"+com.zhonglai.luhui.mqtt.comm.util.StringUtils.getName(field.getName()));
Object value = method.invoke(object);
if(null != value)
{
... ... @@ -165,7 +165,7 @@ public class BaseDao {
{//
Method method;
try {
method = object.getClass().getMethod("get"+com.ruoyi.common.utils.StringUtils.getName(field.getName()));
method = object.getClass().getMethod("get"+com.zhonglai.luhui.mqtt.comm.util.StringUtils.getName(field.getName()));
Object value = method.invoke(object);
if(!"(".equals(values) )
{
... ... @@ -233,7 +233,7 @@ public class BaseDao {
{
Field field = fields[i];
try {
Method method = object.getClass().getMethod("get"+com.ruoyi.common.utils.StringUtils.getName(field.getName()));
Method method = object.getClass().getMethod("get"+com.zhonglai.luhui.mqtt.comm.util.StringUtils.getName(field.getName()));
Object value = method.invoke(object);
if(null != value)
{
... ... @@ -273,7 +273,7 @@ public class BaseDao {
for(int i =0;i<wheres.length;i++)
{
try {
Method method = object.getClass().getMethod("get"+com.ruoyi.common.utils.StringUtils.getName(wheres[i]));
Method method = object.getClass().getMethod("get"+com.zhonglai.luhui.mqtt.comm.util.StringUtils.getName(wheres[i]));
Object value = method.invoke(object);
sql += " and ";
sql += changTableNameFromObject(wheres[i]) + "=?";
... ... @@ -300,7 +300,7 @@ public class BaseDao {
}else{
Method method = null;
try {
method = object.getClass().getMethod("get"+ com.ruoyi.common.utils.StringUtils.getName("id"));
method = object.getClass().getMethod("get"+ com.zhonglai.luhui.mqtt.comm.util.StringUtils.getName("id"));
Object value = method.invoke(object);
sql += " and ";
sql += "id=?";
... ... @@ -690,7 +690,7 @@ public class BaseDao {
Field field = fields[i];
try {
Method method;
method = object.getClass().getMethod("get"+ com.ruoyi.common.utils.StringUtils.getName(field.getName()));
method = object.getClass().getMethod("get"+ com.zhonglai.luhui.mqtt.comm.util.StringUtils.getName(field.getName()));
Object value = method.invoke(object);
if(!(null == value))
{
... ... @@ -759,7 +759,7 @@ public class BaseDao {
{//
Method method;
try {
method = object.getClass().getMethod("get"+com.ruoyi.common.utils.StringUtils.getName(field.getName()));
method = object.getClass().getMethod("get"+com.zhonglai.luhui.mqtt.comm.util.StringUtils.getName(field.getName()));
Object value = method.invoke(object);
if(null != value)
{
... ... @@ -841,7 +841,7 @@ public class BaseDao {
Field field = fields[j];
Method method;
try {
method = object.getClass().getMethod("get"+com.ruoyi.common.utils.StringUtils.getName(field.getName()));
method = object.getClass().getMethod("get"+com.zhonglai.luhui.mqtt.comm.util.StringUtils.getName(field.getName()));
Object value = method.invoke(object);
if(null == value)
{
... ... @@ -945,6 +945,6 @@ public class BaseDao {
e.printStackTrace();
}
return com.ruoyi.common.utils.StringUtils.toUnderScoreCase(tableNmae);
return com.zhonglai.luhui.mqtt.comm.util.StringUtils.toUnderScoreCase(tableNmae);
}
}
... ...
package com.zhonglai.luhui.mqtt.comm.dto;
import com.luhui.domain.log.LogDeviceOperation;
/**
* 设备操作类型
... ...
package com.zhonglai.luhui.mqtt.comm.dto;
import com.zhonglai.luhui.mqtt.dto.Message;
import lombok.Data;
@Data
... ...
... ... @@ -2,6 +2,7 @@ package com.zhonglai.luhui.mqtt.comm.dto;
import com.zhonglai.luhui.mqtt.comm.factory.Topic;
import com.zhonglai.luhui.mqtt.dto.Message;
public interface ServerAgreementContent {
String getClienConnectionId();
... ...
package com.zhonglai.luhui.mqtt.comm.dto;
import com.luhui.ly.service.comm.nio.util.TableUtil;
import com.zhonglai.luhui.mqtt.comm.util.TableUtil;
import java.util.Date;
... ...
package com.zhonglai.luhui.mqtt.comm.dto.iot;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* 主机/网关对象 iot_device
*
* @author 钟来
* @date 2022-08-26
*/
@ApiModel("主机/网关")
public class IotDevice
{
private static final long serialVersionUID = 1L;
/** 激活时间 */
@ApiModelProperty("激活时间")
private Integer active_time;
/** 主键 */
@ApiModelProperty("主键")
private String client_id;
/** 是否补充权限,前面加${{roleid}}/${{username}}/${{clientid}}(0否,1是) */
@ApiModelProperty("是否补充权限,前面加${{roleid}}/${{username}}/${{clientid}}(0否,1是)")
private Integer completion_auth;
/** 创建者 */
@ApiModelProperty("创建者")
private String create_by;
/** 创建时间 */
@ApiModelProperty("创建时间")
private Integer create_time;
/** 删除标志(0代表存在 2代表删除) */
@ApiModelProperty("删除标志(0代表存在 2代表删除)")
private Integer del_flag;
/** 固件版本 */
@ApiModelProperty("固件版本")
private Float firmware_version;
/** 图片地址 */
@ApiModelProperty("图片地址")
private String img_url;
/** 是否启用设备影子(0=禁用,1=启用) */
@ApiModelProperty("是否启用设备影子(0=禁用,1=启用)")
private Integer is_shadow;
/** 设备纬度 */
@ApiModelProperty("设备纬度")
private Double latitude;
/** 定位方式(1=ip自动定位,2=设备定位,3=自定义) */
@ApiModelProperty("定位方式(1=ip自动定位,2=设备定位,3=自定义)")
private Integer location_way;
/** 设备经度 */
@ApiModelProperty("设备经度")
private Double longitude;
/** 设备名称 */
@ApiModelProperty("设备名称")
private String name;
/** 设备所在地址 */
@ApiModelProperty("设备所在地址")
private String network_address;
/** 设备入网IP */
@ApiModelProperty("设备入网IP")
private String network_ip;
/** 信号强度( 信号极好4格[-55— 0], 信号好3格[-70— -55], 信号一般2格[-85— -70], 信号差1格[-100— -85]) */
@ApiModelProperty("信号强度( 信号极好4格[-55— 0], 信号好3格[-70— -55], 信号一般2格[-85— -70], 信号差1格[-100— -85])")
private Integer rssi;
/** 设备状态(1-未激活,2-禁用,3-在线,4-离线) */
@ApiModelProperty("设备状态(1-未激活,2-禁用,3-在线,4-离线)")
private Integer status;
/** 设备摘要,格式[{"name":"device"},{"chip":"esp8266"}] */
@ApiModelProperty("设备摘要,格式[{\"name\":\"device\"},{\"chip\":\"esp8266\"}]")
private String summary;
/** 物模型值 */
@ApiModelProperty("物模型值")
private String things_model_value;
/** 更新者 */
@ApiModelProperty("更新者")
private String update_by;
/** 更新时间 */
@ApiModelProperty("更新时间")
private Integer update_time;
/** 用户id */
@ApiModelProperty("用户id")
private Integer user_id;
@ApiModelProperty("负载类型(String,Json,Bite16,Bite32)")
private String payload_type;
public String getPayload_type() {
return payload_type;
}
public void setPayload_type(String payload_type) {
this.payload_type = payload_type;
}
public void setActive_time(Integer active_time)
{
this.active_time = active_time;
}
public Integer getActive_time()
{
return active_time;
}
public void setClient_id(String client_id)
{
this.client_id = client_id;
}
public String getClient_id()
{
return client_id;
}
public void setCompletion_auth(Integer completion_auth)
{
this.completion_auth = completion_auth;
}
public Integer getCompletion_auth()
{
return completion_auth;
}
public void setCreate_by(String create_by)
{
this.create_by = create_by;
}
public String getCreate_by()
{
return create_by;
}
public void setCreate_time(Integer create_time)
{
this.create_time = create_time;
}
public Integer getCreate_time()
{
return create_time;
}
public void setDel_flag(Integer del_flag)
{
this.del_flag = del_flag;
}
public Integer getDel_flag()
{
return del_flag;
}
public void setFirmware_version(Float firmware_version)
{
this.firmware_version = firmware_version;
}
public Float getFirmware_version()
{
return firmware_version;
}
public void setImg_url(String img_url)
{
this.img_url = img_url;
}
public String getImg_url()
{
return img_url;
}
public void setIs_shadow(Integer is_shadow)
{
this.is_shadow = is_shadow;
}
public Integer getIs_shadow()
{
return is_shadow;
}
public void setLatitude(Double latitude)
{
this.latitude = latitude;
}
public Double getLatitude()
{
return latitude;
}
public void setLocation_way(Integer location_way)
{
this.location_way = location_way;
}
public Integer getLocation_way()
{
return location_way;
}
public void setLongitude(Double longitude)
{
this.longitude = longitude;
}
public Double getLongitude()
{
return longitude;
}
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
public void setNetwork_address(String network_address)
{
this.network_address = network_address;
}
public String getNetwork_address()
{
return network_address;
}
public void setNetwork_ip(String network_ip)
{
this.network_ip = network_ip;
}
public String getNetwork_ip()
{
return network_ip;
}
public void setRssi(Integer rssi)
{
this.rssi = rssi;
}
public Integer getRssi()
{
return rssi;
}
public void setStatus(Integer status)
{
this.status = status;
}
public Integer getStatus()
{
return status;
}
public void setSummary(String summary)
{
this.summary = summary;
}
public String getSummary()
{
return summary;
}
public void setThings_model_value(String things_model_value)
{
this.things_model_value = things_model_value;
}
public String getThings_model_value()
{
return things_model_value;
}
public void setUpdate_by(String update_by)
{
this.update_by = update_by;
}
public String getUpdate_by()
{
return update_by;
}
public void setUpdate_time(Integer update_time)
{
this.update_time = update_time;
}
public Integer getUpdate_time()
{
return update_time;
}
public void setUser_id(Integer user_id)
{
this.user_id = user_id;
}
public Integer getUser_id()
{
return user_id;
}
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("active_time", getActive_time())
.append("client_id", getClient_id())
.append("completion_auth", getCompletion_auth())
.append("create_by", getCreate_by())
.append("create_time", getCreate_time())
.append("del_flag", getDel_flag())
.append("firmware_version", getFirmware_version())
.append("img_url", getImg_url())
.append("is_shadow", getIs_shadow())
.append("latitude", getLatitude())
.append("location_way", getLocation_way())
.append("longitude", getLongitude())
.append("name", getName())
.append("network_address", getNetwork_address())
.append("network_ip", getNetwork_ip())
.append("rssi", getRssi())
.append("status", getStatus())
.append("summary", getSummary())
.append("things_model_value", getThings_model_value())
.append("update_by", getUpdate_by())
.append("update_time", getUpdate_time())
.append("user_id", getUser_id())
.toString();
}
}
... ...
package com.zhonglai.luhui.mqtt.comm.dto.iot;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* topic权限控制对象 iot_permission
*
* @author 钟来
* @date 2022-08-26
*/
@ApiModel("topic权限控制")
public class IotPermission
{
private static final long serialVersionUID = 1L;
/** 动作(PUBLISH,SUBSCRIBE,ALL) */
@ApiModelProperty("动作(PUBLISH,SUBSCRIBE,ALL)")
private String activity;
/** 创建时间 */
@ApiModelProperty("创建时间")
private Integer create_time;
/** 描述 */
@ApiModelProperty("描述")
private String describe;
/** 主键 */
@ApiModelProperty("主键")
private Integer id;
/** 质量(ZERO,ONE,TWO,ZERO_ONE,ZERO_TWO,ONE_TWO,ALL) */
@ApiModelProperty("质量(ZERO,ONE,TWO,ZERO_ONE,ZERO_TWO,ONE_TWO,ALL)")
private String qos;
/** 是否保留(RETAINED,NOT_RETAINED,ALL) */
@ApiModelProperty("是否保留(RETAINED,NOT_RETAINED,ALL)")
private String retain;
/** 角色id */
@ApiModelProperty("角色id")
private Integer role_id;
/** 共享组 */
@ApiModelProperty("共享组")
private String shared_group;
/** 共享订阅(SHARED,NOT_SHARED,ALL) */
@ApiModelProperty("共享订阅(SHARED,NOT_SHARED,ALL)")
private String shared_subscription;
/** topic(同一角色有切只有一个) */
@ApiModelProperty("topic(同一角色有切只有一个)")
private String topic;
public void setActivity(String activity)
{
this.activity = activity;
}
public String getActivity()
{
return activity;
}
public void setCreate_time(Integer create_time)
{
this.create_time = create_time;
}
public Integer getCreate_time()
{
return create_time;
}
public void setDescribe(String describe)
{
this.describe = describe;
}
public String getDescribe()
{
return describe;
}
public void setId(Integer id)
{
this.id = id;
}
public Integer getId()
{
return id;
}
public void setQos(String qos)
{
this.qos = qos;
}
public String getQos()
{
return qos;
}
public void setRetain(String retain)
{
this.retain = retain;
}
public String getRetain()
{
return retain;
}
public void setRole_id(Integer role_id)
{
this.role_id = role_id;
}
public Integer getRole_id()
{
return role_id;
}
public void setShared_group(String shared_group)
{
this.shared_group = shared_group;
}
public String getShared_group()
{
return shared_group;
}
public void setShared_subscription(String shared_subscription)
{
this.shared_subscription = shared_subscription;
}
public String getShared_subscription()
{
return shared_subscription;
}
public void setTopic(String topic)
{
this.topic = topic;
}
public String getTopic()
{
return topic;
}
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("activity", getActivity())
.append("create_time", getCreate_time())
.append("describe", getDescribe())
.append("id", getId())
.append("qos", getQos())
.append("retain", getRetain())
.append("role_id", getRole_id())
.append("shared_group", getShared_group())
.append("shared_subscription", getShared_subscription())
.append("topic", getTopic())
.toString();
}
}
... ...
package com.zhonglai.luhui.mqtt.comm.dto.iot;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* 公司对象 iot_role
*
* @author 钟来
* @date 2022-08-26
*/
@ApiModel("公司")
public class IotRole
{
private static final long serialVersionUID = 1L;
/** 创建时间 */
@ApiModelProperty("创建时间")
private Integer create_time;
/** 描述 */
@ApiModelProperty("描述")
private String describe;
/** 主键 */
@ApiModelProperty("主键")
private Integer id;
/** 名称 */
@ApiModelProperty("名称")
private String name;
/** 是否使用(0否,1是) */
@ApiModelProperty("是否使用(0否,1是)")
private Integer used;
public void setCreate_time(Integer create_time)
{
this.create_time = create_time;
}
public Integer getCreate_time()
{
return create_time;
}
public void setDescribe(String describe)
{
this.describe = describe;
}
public String getDescribe()
{
return describe;
}
public void setId(Integer id)
{
this.id = id;
}
public Integer getId()
{
return id;
}
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
public void setUsed(Integer used)
{
this.used = used;
}
public Integer getUsed()
{
return used;
}
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("create_time", getCreate_time())
.append("describe", getDescribe())
.append("id", getId())
.append("name", getName())
.append("used", getUsed())
.toString();
}
}
... ...
package com.zhonglai.luhui.mqtt.comm.dto.iot;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* 终端对象 iot_terminal
*
* @author 钟来
* @date 2022-08-26
*/
@ApiModel("终端")
public class IotTerminal
{
private static final long serialVersionUID = 1L;
/** 网关id */
@ApiModelProperty("网关id")
private String device_id;
/** 主键id */
@ApiModelProperty("主键id")
private String id;
/** 终端名称 */
@ApiModelProperty("终端名称")
private String name;
/** 物模型值 */
@ApiModelProperty("物模型值")
private String things_model_value;
/** 更新时间 */
@ApiModelProperty("更新时间")
private Integer update_time;
public void setDevice_id(String device_id)
{
this.device_id = device_id;
}
public String getDevice_id()
{
return device_id;
}
public void setId(String id)
{
this.id = id;
}
public String getId()
{
return id;
}
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
public void setThings_model_value(String things_model_value)
{
this.things_model_value = things_model_value;
}
public String getThings_model_value()
{
return things_model_value;
}
public void setUpdate_time(Integer update_time)
{
this.update_time = update_time;
}
public Integer getUpdate_time()
{
return update_time;
}
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("device_id", getDevice_id())
.append("id", getId())
.append("name", getName())
.append("things_model_value", getThings_model_value())
.append("update_time", getUpdate_time())
.toString();
}
}
... ...
package com.zhonglai.luhui.mqtt.comm.dto.iot;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* 物模型模板对象 iot_things_model
*
* @author 钟来
* @date 2022-08-26
*/
@ApiModel("物模型模板")
public class IotThingsModel
{
private static final long serialVersionUID = 1L;
/** 创建者 */
@ApiModelProperty("创建者")
private String create_by;
/** 创建时间 */
@ApiModelProperty("创建时间")
private java.util.Date create_time;
/** 数据类型(integer、decimal、string、bool、array、enum) */
@ApiModelProperty("数据类型(integer、decimal、string、bool、array、enum)")
private String data_type;
/** 删除标志(0代表存在 2代表删除) */
@ApiModelProperty("删除标志(0代表存在 2代表删除)")
private String del_flag;
/** 标识符,用户下唯一 */
@ApiModelProperty("标识符,用户下唯一")
private String identifier;
/** 是否实时监测(0-否,1-是) */
@ApiModelProperty("是否实时监测(0-否,1-是)")
private Integer is_monitor;
/** 是否记录日志(0否,1是) */
@ApiModelProperty("是否记录日志(0否,1是)")
private Integer is_save_log;
/** 是否首页显示(0-否,1-是) */
@ApiModelProperty("是否首页显示(0-否,1-是)")
private Integer is_top;
/** 物模型ID */
@ApiModelProperty("物模型ID")
private Integer model_id;
/** 物模型名称 */
@ApiModelProperty("物模型名称")
private String model_name;
/** 数据定义 */
@ApiModelProperty("数据定义")
private String specs;
/** 模型类别(1-属性,2-功能,3-事件) */
@ApiModelProperty("模型类别(1-属性,2-功能,3-事件)")
private Integer type;
/** 更新者 */
@ApiModelProperty("更新者")
private String update_by;
/** 更新时间 */
@ApiModelProperty("更新时间")
private java.util.Date update_time;
/** 用户id */
@ApiModelProperty("用户id")
private Integer user_id;
public void setCreate_by(String create_by)
{
this.create_by = create_by;
}
public String getCreate_by()
{
return create_by;
}
public void setCreate_time(java.util.Date create_time)
{
this.create_time = create_time;
}
public java.util.Date getCreate_time()
{
return create_time;
}
public void setData_type(String data_type)
{
this.data_type = data_type;
}
public String getData_type()
{
return data_type;
}
public void setDel_flag(String del_flag)
{
this.del_flag = del_flag;
}
public String getDel_flag()
{
return del_flag;
}
public void setIdentifier(String identifier)
{
this.identifier = identifier;
}
public String getIdentifier()
{
return identifier;
}
public void setIs_monitor(Integer is_monitor)
{
this.is_monitor = is_monitor;
}
public Integer getIs_monitor()
{
return is_monitor;
}
public void setIs_save_log(Integer is_save_log)
{
this.is_save_log = is_save_log;
}
public Integer getIs_save_log()
{
return is_save_log;
}
public void setIs_top(Integer is_top)
{
this.is_top = is_top;
}
public Integer getIs_top()
{
return is_top;
}
public void setModel_id(Integer model_id)
{
this.model_id = model_id;
}
public Integer getModel_id()
{
return model_id;
}
public void setModel_name(String model_name)
{
this.model_name = model_name;
}
public String getModel_name()
{
return model_name;
}
public void setSpecs(String specs)
{
this.specs = specs;
}
public String getSpecs()
{
return specs;
}
public void setType(Integer type)
{
this.type = type;
}
public Integer getType()
{
return type;
}
public void setUpdate_by(String update_by)
{
this.update_by = update_by;
}
public String getUpdate_by()
{
return update_by;
}
public void setUpdate_time(java.util.Date update_time)
{
this.update_time = update_time;
}
public java.util.Date getUpdate_time()
{
return update_time;
}
public void setUser_id(Integer user_id)
{
this.user_id = user_id;
}
public Integer getUser_id()
{
return user_id;
}
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("create_by", getCreate_by())
.append("create_time", getCreate_time())
.append("data_type", getData_type())
.append("del_flag", getDel_flag())
.append("identifier", getIdentifier())
.append("is_monitor", getIs_monitor())
.append("is_save_log", getIs_save_log())
.append("is_top", getIs_top())
.append("model_id", getModel_id())
.append("model_name", getModel_name())
.append("specs", getSpecs())
.append("type", getType())
.append("update_by", getUpdate_by())
.append("update_time", getUpdate_time())
.append("user_id", getUser_id())
.toString();
}
}
... ...
package com.zhonglai.luhui.mqtt.comm.dto.iot;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* 产品对象 iot_user
*
* @author 钟来
* @date 2022-08-26
*/
@ApiModel("产品")
public class IotUser
{
private static final long serialVersionUID = 1L;
/** 创建时间 */
@ApiModelProperty("创建时间")
private Integer create_time;
/** 加密类型 */
@ApiModelProperty("加密类型")
private String encryption_type;
/** 主键id */
@ApiModelProperty("主键id")
private Integer id;
/** 开启加密(0不开启,1开启) */
@ApiModelProperty("开启加密(0不开启,1开启)")
private Integer open_encryption;
/** 密码 */
@ApiModelProperty("密码")
private String password;
/** 角色id */
@ApiModelProperty("角色id")
private Integer role_id;
/** 盐 */
@ApiModelProperty("盐")
private String salt;
/** 是否使用(0否,1是) */
@ApiModelProperty("是否使用(0否,1是)")
private Integer used;
/** 用户名 */
@ApiModelProperty("用户名")
private String username;
public void setCreate_time(Integer create_time)
{
this.create_time = create_time;
}
public Integer getCreate_time()
{
return create_time;
}
public void setEncryption_type(String encryption_type)
{
this.encryption_type = encryption_type;
}
public String getEncryption_type()
{
return encryption_type;
}
public void setId(Integer id)
{
this.id = id;
}
public Integer getId()
{
return id;
}
public void setOpen_encryption(Integer open_encryption)
{
this.open_encryption = open_encryption;
}
public Integer getOpen_encryption()
{
return open_encryption;
}
public void setPassword(String password)
{
this.password = password;
}
public String getPassword()
{
return password;
}
public void setRole_id(Integer role_id)
{
this.role_id = role_id;
}
public Integer getRole_id()
{
return role_id;
}
public void setSalt(String salt)
{
this.salt = salt;
}
public String getSalt()
{
return salt;
}
public void setUsed(Integer used)
{
this.used = used;
}
public Integer getUsed()
{
return used;
}
public void setUsername(String username)
{
this.username = username;
}
public String getUsername()
{
return username;
}
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("create_time", getCreate_time())
.append("encryption_type", getEncryption_type())
.append("id", getId())
.append("open_encryption", getOpen_encryption())
.append("password", getPassword())
.append("role_id", getRole_id())
.append("salt", getSalt())
.append("used", getUsed())
.append("username", getUsername())
.toString();
}
}
... ...
... ... @@ -3,18 +3,25 @@ package com.zhonglai.luhui.mqtt.comm.factory;
import com.zhonglai.luhui.mqtt.comm.config.RedisConfig;
import com.zhonglai.luhui.mqtt.comm.config.SysParameter;
import com.zhonglai.luhui.mqtt.comm.dto.MyException;
import com.zhonglai.luhui.mqtt.comm.service.MqttCallback;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.util.Optional;
@Data
public class Topic {
private static final Logger log = LoggerFactory.getLogger(Topic.class);
private String roleid;
private String username;
private String clientid;
private String topicType;
private String redicKey;
private String messageid;
private String payloadtype;
public Topic(String topic)
{
topic = Optional.ofNullable(topic).orElseThrow(()->new MyException("topic为空"));
... ... @@ -23,23 +30,13 @@ public class Topic {
for(int i=0;i<config.length;i++)
{
String cf = config[i].replace("{{","").replace("}}","");
switch (cf)
{
case "roleid":
roleid = sts[i];
break;
case "username":
username = sts[i];
break;
case "clientid":
clientid = sts[i];
break;
case "topicType":
topicType = sts[i];
break;
case "messageid":
messageid = sts[i];
break;
try {
Field field = this.getClass().getField(cf);
field.set(this,sts[i]);
} catch (NoSuchFieldException e) {
log.info("{}生成topic时没有属性",topic,cf);
} catch (IllegalAccessException e) {
log.info("{}生成topic时无法给{}赋值{}",topic,cf,sts[i]);
}
}
}
... ...
package com.zhonglai.luhui.mqtt.comm.service;
import com.ruoyi.common.core.domain.Message;
import com.ruoyi.common.utils.ByteUtil;
import com.zhonglai.luhui.mqtt.comm.clien.ClienConnection;
import com.zhonglai.luhui.mqtt.comm.clien.impl.ClienConnectionImpl;
import com.zhonglai.luhui.mqtt.comm.dto.ServerDto;
import com.zhonglai.luhui.mqtt.comm.factory.Topic;
import com.zhonglai.luhui.mqtt.comm.util.ByteUtil;
import com.zhonglai.luhui.mqtt.dto.Message;
import net.jodah.expiringmap.ExpirationListener;
import net.jodah.expiringmap.ExpirationPolicy;
import net.jodah.expiringmap.ExpiringMap;
... ...
package com.zhonglai.luhui.mqtt.comm.service;
import com.ruoyi.common.utils.DateUtils;
import com.zhonglai.luhui.mqtt.comm.dao.BaseDao;
import com.zhonglai.luhui.mqtt.comm.dto.*;
import com.zhonglai.luhui.mqtt.comm.factory.Topic;
import com.zhonglai.luhui.mqtt.comm.util.DateUtils;
import com.zhonglai.luhui.mqtt.comm.util.TableUtil;
import org.apache.commons.lang3.StringUtils;
... ...
package com.zhonglai.luhui.mqtt.comm.service;
import com.luhui.ly.device.mqtt.comm.dto.ServerDto;
import com.luhui.ly.device.mqtt.comm.factory.BusinessAgreement;
import com.luhui.ly.device.mqtt.comm.factory.BusinessAgreementFactory;
import com.luhui.ly.device.mqtt.comm.factory.Topic;
import com.luhui.ly.device.mqtt.comm.service.CacheService;
import com.luhui.ly.device.mqtt.comm.service.ClienNoticeService;
import com.luhui.ly.device.mqtt.comm.service.DataPersistenceService;
import com.luhui.ly.device.mqtt.comm.service.TerminalService;
import com.zhonglai.luhui.mqtt.comm.dto.ServerDto;
import com.zhonglai.luhui.mqtt.comm.factory.BusinessAgreement;
import com.zhonglai.luhui.mqtt.comm.factory.BusinessAgreementFactory;
import com.zhonglai.luhui.mqtt.comm.factory.Topic;
import com.zhonglai.luhui.mqtt.comm.util.ByteUtil;
import lombok.SneakyThrows;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
... ... @@ -20,7 +17,7 @@ import org.springframework.stereotype.Component;
@Component
public class MqttCallback implements MqttCallbackExtended {
private static final Logger log = LoggerFactory.getLogger(com.luhui.ly.device.mqtt.comm.service.MqttCallback.class);
private static final Logger log = LoggerFactory.getLogger(MqttCallback.class);
@Autowired
private BusinessAgreementFactory businessAgreementFactory;
@Autowired
... ... @@ -51,7 +48,7 @@ public class MqttCallback implements MqttCallbackExtended {
@Override
public void messageArrived(String s, MqttMessage mqttMessage) {
//接收到消息
// log.info("接收到消息topc:{}, mqttMessage {},payload 十六进制 {}",s,mqttMessage,ByteUtil.hexStringToSpace(ByteUtil.toHexString(mqttMessage.getPayload())));
log.info("接收到消息topc:{}, mqttMessage {},payload 十六进制 {}",s,mqttMessage, ByteUtil.hexStringToSpace(ByteUtil.toHexString(mqttMessage.getPayload())));
Topic topic = new Topic(s);
BusinessAgreement businessAgreement = businessAgreementFactory.createBusinessAgreement(topic.getTopicType());
... ...
package com.zhonglai.luhui.mqtt.comm.service;
import com.luhui.ly.device.mqtt.comm.config.RedisConfig;
import com.luhui.ly.device.mqtt.comm.service.DataPersistenceService;
import com.zhonglai.luhui.mqtt.comm.config.RedisConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
... ...
package com.zhonglai.luhui.mqtt.comm.service;
import com.luhui.ly.comm.util.GsonConstructor;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
... ... @@ -18,7 +18,7 @@ import java.util.stream.Collectors;
*/
@Service
public class RedisService {
private static final Logger log = LoggerFactory.getLogger(com.luhui.ly.device.mqtt.comm.service.RedisService.class);
private static final Logger log = LoggerFactory.getLogger(RedisService.class);
@Resource
private RedisTemplate<String,Object> redisTemplate;
... ... @@ -359,9 +359,9 @@ public class RedisService {
Map<Object, Object> hmget = hmget(key);
if(CollectionUtils.isEmpty(hmget)) return null;
//查询到了 先把数据转成json字符串
String s = GsonConstructor.get().toJson(hmget);
String s = JSONObject.toJSONString(hmget);
//再把json字符串转回对象
return GsonConstructor.get().fromJson(s,tClass);
return JSONObject.parseObject(s,tClass);
}
/**
... ... @@ -380,8 +380,8 @@ public class RedisService {
}
public boolean hmset(String key,Object object){
try {
String s = GsonConstructor.get().toJson(object);
Map<String, String> map = GsonConstructor.get().fromJson(s,HashMap.class);
String s = JSONObject.toJSONString(object);
Map<String, String> map = JSONObject.parseObject(s,HashMap.class);
redisTemplate.opsForHash().putAll(key, map);
return true;
}catch (Exception e){
... ...
package com.zhonglai.luhui.mqtt.comm.service;
import com.luhui.ly.device.mqtt.comm.config.SysParameter;
import com.luhui.ly.device.mqtt.comm.service.MqttCallback;
import com.zhonglai.luhui.mqtt.comm.config.SysParameter;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
... ... @@ -26,7 +25,7 @@ import java.util.concurrent.TimeUnit;
*/
@Service
public class TerminalService {
private static final Logger log = LoggerFactory.getLogger(com.luhui.ly.device.mqtt.comm.service.TerminalService.class);
private static final Logger log = LoggerFactory.getLogger(TerminalService.class);
@Autowired
private MqttCallback mqttCallback;
... ...
package com.zhonglai.luhui.mqtt.comm.util;
import java.util.Arrays;
public class ByteUtil {
/**
* byte数组中取int数值,本方法适用于(低位在前,高位在后)的顺序,和和intToBytes()配套使用
*
* @param src
* byte数组
* @param offset
* 从数组的第offset位开始
* @return int数值
*/
public static long bytesToLongASC(byte[] src, int offset,int lenth) {
int value = 0;
for(int i=0;i<lenth;i++)
{
value = value | ((src[offset+i] & 0xFF)<<(8*i));
}
return value;
}
/**
* 把16进制字符串转换成字节数组
*
* @param hex
* @return
*/
public static byte[] hexStringToByte(String hex) {
int len = (hex.length() / 2);
byte[] result = new byte[len];
char[] achar = hex.toCharArray();
for (int i = 0; i < len; i++) {
int pos = i * 2;
result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
}
return result;
}
private static byte toByte(char c) {
byte b = (byte) "0123456789ABCDEF".indexOf(c);
return b;
}
/**
* 把16进制字符串转换成字节数组
*
* @param hex
* @return
*/
public static String hexStringToSpace(String hex) {
if (null == hex) {
return null;
} else {
StringBuilder sb = new StringBuilder(hex.length() << 1);
for(int i = 0; i < hex.length(); i+=2) {
sb.append(hex.substring(i,i+2)).append(" ");
}
return sb.toString();
}
}
/**
* 把原数组加点目标数组后面
* @param dest 目标数组
* @param src 原数组
* @return
*/
public static byte[] addBytes(byte[] dest,byte[] src )
{
int dl = dest.length;
int sl = src.length;
dest = Arrays.copyOf(dest, dl+sl);//数组扩容
System.arraycopy(src,0,dest,dl,src.length);
return dest;
}
/**
* 将int数值转换为占四个字节的byte数组,本方法适用于(高位在前,低位在后)的顺序。 和bytesToInt2()配套使用
*/
public static byte[] intToBytesDESC(long value,int lenth)
{
byte[] src = new byte[lenth];
for(int i=0;i<lenth;i++)
{
src[i] = (byte) ((value>>(8*(lenth-i-1))) & 0xFF);
}
return src;
}
/**
* 将int数值转换为占四个字节的byte数组,本方法适用于(低位在前,高位在后)的顺序。 和bytesToInt()配套使用
* @param value
* 要转换的int值
* @return byte数组
*/
public static byte[] intToBytesASC( long value,int lenth)
{
byte[] src = new byte[lenth];
for(int i=lenth;i>0;i--)
{
src[i-1] = (byte) ((value>>(8*(i-1))) & 0xFF);
}
return src;
}
public static void main(String[] args) {
System.out.println(ByteUtil.toHexString( ByteUtil.intToBytesASC(2011239256,4)));
}
/**
* ip转化位4byte
* @param ip
* @return
*/
public static byte[] ipTo4Byte(String ip)
{
String[] ips = ip.split(".");
return new byte[]{(byte) Integer.parseInt(ips[0]),(byte) Integer.parseInt(ips[1]),(byte) Integer.parseInt(ips[2]),(byte) Integer.parseInt(ips[3])};
}
/**
* byte数组中取int数值,本方法适用于(低位在后,高位在前)的顺序。和intToBytes2()配套使用
*/
public static long bytesToLongDESC(byte[] src, int offset,int lenth) {
long value = 0;
for(int i=lenth;i>0;i--)
{
value = value | ((src[offset+(lenth-i)] & 0xFF)<<(8*(i-1)));
}
return value;
}
private static final char[] hex = "0123456789abcdef".toCharArray();
public static String toHexString(byte[] bytes) {
if (null == bytes) {
return null;
} else {
StringBuilder sb = new StringBuilder(bytes.length << 1);
for(int i = 0; i < bytes.length; ++i) {
sb.append(hex[(bytes[i] & 240) >> 4]).append(hex[bytes[i] & 15]);
}
return sb.toString();
}
}
/**
* 计算CRC16/Modbus校验码 低位在前,高位在后
*
* @param str 十六进制字符串
* @return
*/
public static String getCRC16(String str) {
byte[] bytes = hexStringToByte(str);
return getCRC16(bytes);
}
/**
* 计算CRC16/Modbus校验码 低位在前,高位在后
*
* @return
*/
public static String getCRC16( byte[] bytes) {
int CRC = 0x0000ffff;
int POLYNOMIAL = 0x0000a001;
int i, j;
for (i = 0; i < bytes.length; i++) {
CRC ^= ((int) bytes[i] & 0x000000ff);
for (j = 0; j < 8; j++) {
if ((CRC & 0x00000001) != 0) {
CRC >>= 1;
CRC ^= POLYNOMIAL;
} else {
CRC >>= 1;
}
}
}
String crc = Integer.toHexString(CRC);
if (crc.length() == 2) {
crc = "00" + crc;
} else if (crc.length() == 3) {
crc = "0" + crc;
}
crc = crc.substring(2, 4) + crc.substring(0, 2);
return crc.toUpperCase();
}
}
... ...
package com.zhonglai.luhui.mqtt.comm.util;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/**
* 字符集工具类
*
* @author ruoyi
*/
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();
}
}
... ...
package com.zhonglai.luhui.mqtt.comm.util;
import io.jsonwebtoken.Claims;
/**
* 通用常量信息
*
* @author ruoyi
*/
public class Constants
{
/**
* UTF-8 字符集
*/
public static final String UTF8 = "UTF-8";
/**
* GBK 字符集
*/
public static final String GBK = "GBK";
/**
* 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";
/**
* 验证码 redis key
*/
public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
/**
* 登录用户 redis key
*/
public static final String LOGIN_TOKEN_KEY = "login_tokens:";
/**
* 防重提交 redis key
*/
public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
/**
* 限流 redis key
*/
public static final String RATE_LIMIT_KEY = "rate_limit:";
/**
* 验证码有效期(分钟)
*/
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 = Claims.SUBJECT;
/**
* 用户头像
*/
public static final String JWT_AVATAR = "avatar";
/**
* 创建时间
*/
public static final String JWT_CREATED = "created";
/**
* 用户权限
*/
public static final String JWT_AUTHORITIES = "authorities";
/**
* 参数管理 cache key
*/
public static final String SYS_CONFIG_KEY = "sys_config:";
/**
* 字典管理 cache key
*/
public static final String SYS_DICT_KEY = "sys_dict:";
/**
* 资源映射路径 前缀
*/
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.ruoyi" };
/**
* 定时任务违规的字符
*/
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
"org.springframework", "org.apache", "com.ruoyi.common.utils.file" };
}
... ...
package com.zhonglai.luhui.mqtt.comm.util;
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 ruoyi
*/
public class Convert
{
/**
* 转换为字符串<br>
* 如果给定的值为null,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @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();
}
/**
* 转换为字符串<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static String toStr(Object value)
{
return toStr(value, null);
}
/**
* 转换为字符<br>
* 如果给定的值为null,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @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);
}
/**
* 转换为字符<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Character toChar(Object value)
{
return toChar(value, null);
}
/**
* 转换为byte<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @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<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Byte toByte(Object value)
{
return toByte(value, null);
}
/**
* 转换为Short<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @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<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Short toShort(Object value)
{
return toShort(value, null);
}
/**
* 转换为Number<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @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<br>
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Number toNumber(Object value)
{
return toNumber(value, null);
}
/**
* 转换为int<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @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<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Integer toInt(Object value)
{
return toInt(value, null);
}
/**
* 转换为Integer数组<br>
*
* @param str 被转换的值
* @return 结果
*/
public static Integer[] toIntArray(String str)
{
return toIntArray(",", str);
}
/**
* 转换为Long数组<br>
*
* @param str 被转换的值
* @return 结果
*/
public static Long[] toLongArray(String str)
{
return toLongArray(",", str);
}
/**
* 转换为Integer数组<br>
*
* @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数组<br>
*
* @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数组<br>
*
* @param str 被转换的值
* @return 结果
*/
public static String[] toStrArray(String str)
{
return toStrArray(",", str);
}
/**
* 转换为String数组<br>
*
* @param split 分隔符
* @param split 被转换的值
* @return 结果
*/
public static String[] toStrArray(String split, String str)
{
return str.split(split);
}
/**
* 转换为long<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @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<br>
* 如果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Long toLong(Object value)
{
return toLong(value, null);
}
/**
* 转换为double<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @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<br>
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Double toDouble(Object value)
{
return toDouble(value, null);
}
/**
* 转换为Float<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @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<br>
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Float toFloat(Object value)
{
return toFloat(value, null);
}
/**
* 转换为boolean<br>
* String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @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":
return true;
case "false":
return false;
case "yes":
return true;
case "ok":
return true;
case "no":
return false;
case "1":
return true;
case "0":
return false;
default:
return defaultValue;
}
}
/**
* 转换为boolean<br>
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static Boolean toBool(Object value)
{
return toBool(value, null);
}
/**
* 转换为Enum对象<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
*
* @param clazz Enum的Class
* @param value 值
* @param defaultValue 默认值
* @return Enum
*/
public static <E extends Enum<E>> E toEnum(Class<E> 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对象<br>
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
*
* @param clazz Enum的Class
* @param value 值
* @return Enum
*/
public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value)
{
return toEnum(clazz, value, null);
}
/**
* 转换为BigInteger<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @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<br>
* 如果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static BigInteger toBigInteger(Object value)
{
return toBigInteger(value, null);
}
/**
* 转换为BigDecimal<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @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 new BigDecimal((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<br>
* 如果给定的值为空,或者转换失败,返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
* @return 结果
*/
public static BigDecimal toBigDecimal(Object value)
{
return toBigDecimal(value, null);
}
/**
* 将对象转为字符串<br>
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
*
* @param obj 对象
* @return 字符串
*/
public static String utf8Str(Object obj)
{
return str(obj, CharsetKit.CHARSET_UTF_8);
}
/**
* 将对象转为字符串<br>
* 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));
}
/**
* 将对象转为字符串<br>
* 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<Character> 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<Character> 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("^整$", "零元整");
}
}
... ...
package com.zhonglai.luhui.mqtt.comm.util;
import org.apache.commons.lang3.time.DateFormatUtils;
import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.util.Date;
/**
* 时间工具类
*
* @author ruoyi
*/
public class DateUtils extends org.apache.commons.lang3.time.DateUtils
{
public static String YYYY = "yyyy";
public static String YYYY_MM = "yyyy-MM";
public static String YYYY_MM_DD = "yyyy-MM-dd";
public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
private static String[] parsePatterns = {
"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
"yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
/**
* 获取当前Date型日期
*
* @return Date() 当前日期
*/
public static Date getNowDate()
{
return new Date();
}
/**
* 获取当前日期, 默认格式为yyyy-MM-dd
*
* @return String
*/
public static String getDate()
{
return dateTimeNow(YYYY_MM_DD);
}
public static final String getTime()
{
return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
}
public static final String dateTimeNow()
{
return dateTimeNow(YYYYMMDDHHMMSS);
}
public static final String dateTimeNow(final String format)
{
return parseDateToStr(format, new Date());
}
public static final String dateTime(final Date date)
{
return parseDateToStr(YYYY_MM_DD, date);
}
public static final String parseDateToStr(final String format, final Date date)
{
return new SimpleDateFormat(format).format(date);
}
public static final Date dateTime(final String format, final String ts)
{
try
{
return new SimpleDateFormat(format).parse(ts);
}
catch (ParseException e)
{
throw new RuntimeException(e);
}
}
/**
* 日期路径 即年/月/日 如2018/08/08
*/
public static final String datePath()
{
Date now = new Date();
return DateFormatUtils.format(now, "yyyy/MM/dd");
}
/**
* 日期路径 即年/月/日 如20180808
*/
public static final String dateTime()
{
Date now = new Date();
return DateFormatUtils.format(now, "yyyyMMdd");
}
/**
* 日期型字符串转化为日期 格式
*/
public static Date parseDate(Object str)
{
if (str == null)
{
return null;
}
try
{
return parseDate(str.toString(), parsePatterns);
}
catch (ParseException e)
{
return null;
}
}
/**
* 获取服务器启动时间
*/
public static Date getServerStartDate()
{
long time = ManagementFactory.getRuntimeMXBean().getStartTime();
return new Date(time);
}
/**
* 计算相差天数
*/
public static int differentDaysByMillisecond(Date date1, Date date2)
{
return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
}
/**
* 计算两个时间差
*/
public static String getDatePoor(Date endDate, Date nowDate)
{
long nd = 1000 * 24 * 60 * 60;
long nh = 1000 * 60 * 60;
long nm = 1000 * 60;
// long ns = 1000;
// 获得两个时间的毫秒时间差异
long diff = endDate.getTime() - nowDate.getTime();
// 计算差多少天
long day = diff / nd;
// 计算差多少小时
long hour = diff % nd / nh;
// 计算差多少分钟
long min = diff % nd % nh / nm;
// 计算差多少秒//输出结果
// long sec = diff % nd % nh % nm / ns;
return day + "天" + hour + "小时" + min + "分钟";
}
/**
* 增加 LocalDateTime ==> Date
*/
public static Date toDate(LocalDateTime temporalAccessor)
{
ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
return Date.from(zdt.toInstant());
}
/**
* 增加 LocalDate ==> Date
*/
public static Date toDate(LocalDate temporalAccessor)
{
LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
return Date.from(zdt.toInstant());
}
public static Integer getNowTimeMilly() {
String time = System.currentTimeMillis() / 1000L + "";
return Integer.parseInt(time);
}
}
... ...
package com.zhonglai.luhui.mqtt.comm.util;
/**
* 字符串格式化
*
* @author ruoyi
*/
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 = '}';
/**
* 格式化字符串<br>
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
* 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
* 例:<br>
* 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br>
* 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
* 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
*
* @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();
}
}
... ...
package com.zhonglai.luhui.mqtt.comm.util;
import org.springframework.util.AntPathMatcher;
import java.util.*;
/**
* 字符串工具类
*
* @author ruoyi
*/
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> 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);
}
/**
* 格式化文本, {} 表示占位符<br>
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
* 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
* 例:<br>
* 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br>
* 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
* 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
*
* @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<String> str2Set(String str, String sep)
{
return new HashSet<String>(str2List(str, sep, true, false));
}
/**
* 字符串转list
*
* @param str 字符串
* @param sep 分隔符
* @param filterBlank 过滤纯空白
* @param trim 去掉首尾空白
* @return list集合
*/
public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim)
{
List<String> list = new ArrayList<String>();
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;
}
/**
* 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
*
* @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;
}
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<String> 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> 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();
}
/**
* [简要描述]:首字母大写
*
* @author com.zhonglai
* @param str
* @return
*/
public static String getName(String str) {
char ch = str.toCharArray()[0];
ch = (char) ((ch - 97) + 'A');
str = ch + str.substring(1);
return str;
}
}
\ No newline at end of file
... ...
package com.zhonglai.luhui.mqtt.comm.util;
import com.ruoyi.common.utils.DateUtils;
import java.util.Date;
... ...
package com.zhonglai.luhui.mqtt.comm.util.http;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
/**
* 通用http工具封装
*
* @author ruoyi
*/
public class HttpHelper
{
private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class);
public static String getBodyString(ServletRequest request)
{
StringBuilder sb = new StringBuilder();
BufferedReader reader = null;
try (InputStream inputStream = request.getInputStream())
{
reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
String line = "";
while ((line = reader.readLine()) != null)
{
sb.append(line);
}
}
catch (IOException e)
{
LOGGER.warn("getBodyString出现问题!");
}
finally
{
if (reader != null)
{
try
{
reader.close();
}
catch (IOException e)
{
LOGGER.error(ExceptionUtils.getMessage(e));
}
}
}
return sb.toString();
}
}
... ...
package com.zhonglai.luhui.mqtt.comm.util.http;
import com.zhonglai.luhui.mqtt.comm.util.Constants;
import com.zhonglai.luhui.mqtt.comm.util.StringUtils;
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 ruoyi
*/
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();
}
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
... ...
package com.zhonglai.luhui.mqtt.comm.util.http;
import com.alibaba.fastjson.JSONObject;
import okhttp3.*;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.math.NumberUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public class OkHttpUtils {
private static OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();
public static String generateGetUrl(String url, Map<String,String> map)
{
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(url);
if(null != map && map.size() !=0)
{
stringBuffer.append("?1=1");
for(String key:map.keySet())
{
stringBuffer.append("&");
stringBuffer.append(key+"="+map.get(key));
}
}
return stringBuffer.toString();
}
public static JSONObject reqstFormBodyHttp(RequestFunction requestFunction, String url)
{
FormBody.Builder builder = new FormBody.Builder();
requestFunction.builderParameter(builder);
return reqstHttp(url,builder.build());
}
public static JSONObject reqstHttp(String url, RequestBody requestBody)
{
Response response = httpPostJson(url,requestBody);
JSONObject clJs = null;
try {
clJs = JSONObject.parseObject(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(clJs.toJSONString());
return clJs;
}
public static Response httpPostJson(String url, RequestBody requestBody) {
Request request = getPostRequest( url, requestBody);
return response(request,3);
}
public static Response response(Request request,int number) {
Response response = null;
if(null == request)
{
System.out.println("request为空:");
return response;
}
try {
response = okHttpClient.newCall(request).execute();
} catch (IOException e) {
System.out.println("请求出错:"+e.getMessage());
if(0<number)
{
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
response(request,number-1);
}else{
e.printStackTrace();
}
}
try {
if (!response.isSuccessful()) {
throw new Exception("Unexpected code " + response);
}
} catch (Exception e) {
response.body().close();
}
return response;
}
public static Request getPostRequest(String url, RequestBody requestBody)
{
return new Request.Builder()
.url(url)
.post(requestBody)
.build();
}
public interface RequestFunction
{
void builderParameter(FormBody.Builder builder);
}
/**
*
* 压缩图片,并等比缩小。
*
* @author aren
* @param data
* 输入图片数据的byte[]。
* @param width
* 最大输出宽度,但是最后会根据图片本身比例调整。推荐值800。
* @param height
* 最大输出高度,但是最后会根据图片本身比例调整。推荐值600。
* @param type
* 指定最后存储的图片类型,支持字符串jpg,png,gif,bmp,jpeg。如果为null,则默认输出jpg格式图片。
* @param maxSize
* 指定最大输出图片的容量大小。可以为null表示不指定压缩容量大小。不要小于10000,推荐100000。
* @return 输出图片数据的byte[]。
* @throws Exception
*/
public static byte[] zipImageToScaledSize(byte[] data, int width, int height, String type, Integer maxSize)
throws Exception {
if (data == null) {
return null;
}
if (width <= 0 || height <= 0) {
width = 800;
height = 600;
}
// 设定输出格式
String[] supportType = new String[] { "jpg", "png", "bmp", "jpeg", "gif" };
if (type == null || !ArrayUtils.contains(supportType, type)) {
type = "jpg";
}
int pointedHeight;
int pointedWidth;
ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
BufferedImage bufferedImage = ImageIO.read(inputStream);
inputStream.close();
int originalHeight = bufferedImage.getHeight();
int originalWidth = bufferedImage.getWidth();
// 设定等比例压缩。
if ((originalHeight / (double) height) > (originalWidth / (double) width)) {
pointedHeight = NumberUtils.min(height, originalHeight);
pointedWidth = -1;
} else {
pointedHeight = -1;
pointedWidth = NumberUtils.min(width, originalWidth);
}
// 压缩图片,此处附上颜色类型BufferedImage.TYPE_INT_RGB。Color.WHITE,可以有效避免png转jpg时图片发红的问题。
Image newImage = bufferedImage.getScaledInstance(pointedWidth, pointedHeight, Image.SCALE_SMOOTH);
BufferedImage newBufferedImage = new BufferedImage(newImage.getWidth(null), newImage.getHeight(null),
BufferedImage.TYPE_INT_RGB);
newBufferedImage.getGraphics().drawImage(newImage, 0, 0,Color.WHITE, null);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(newBufferedImage, type, byteArrayOutputStream);
byteArrayOutputStream.close();
data = byteArrayOutputStream.toByteArray();
if (maxSize != null && data.length > maxSize) {
// 设定递归的保险,以免图片质量太差
if (maxSize < 5000 && (data.length > 10 * maxSize)) {
maxSize = 5000;
}
// 递归压缩
double scale = Math.max(Math.pow(maxSize / (double) data.length, 0.5), 0.9);
return zipImageToScaledSize(data, (int) (width * scale), (int) (height * scale), type, maxSize);
} else {
return data;
}
}
}
... ...
package com.zhonglai.luhui.mqtt.controller;
import com.luhui.ly.comm.util.CommonUtil;
import com.luhui.ly.device.mqtt.comm.service.ClienNoticeService;
import com.zhonglai.dto.Message;
import com.zhonglai.luhui.mqtt.dto.PutDto;
import com.zhonglai.luhui.mqtt.comm.service.ClienNoticeService;
import com.zhonglai.luhui.mqtt.comm.util.DateUtils;
import com.zhonglai.luhui.mqtt.dto.Message;
import com.zhonglai.luhui.mqtt.dto.topic.PutDto;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.eclipse.paho.client.mqttv3.MqttException;
... ... @@ -26,7 +26,7 @@ public class DeviceController {
// ByteBuf message = Unpooled.buffer(bs.length);
// message.writeBytes(bs);
mqttMessage.setPayload(bs);
Message message = clienNoticeService.sendMessage(clienid,mqttMessage, CommonUtil.getNowTimeMilly()+"");
Message message = clienNoticeService.sendMessage(clienid,mqttMessage, DateUtils.getNowTimeMilly()+"");
return message;
}
... ...
package com.zhonglai.luhui.mqtt.dto;
import lombok.Data;
@Data
public class Message {
private int code;
private String message;
private Object data;
public Message() {
}
public Message(MessageCodeType code, String message, Object data) {
this.code = code.getCode();
this.message = message;
if (null == message || "".equals(message)) {
this.message = code.getMessage();
}
this.data = data;
}
public Message(MessageCodeType code, Object data) {
this.code = code.getCode();
this.message = code.getMessage();
this.data = data;
}
public Message(MessageCodeType code, String message) {
this.code = code.getCode();
this.message = message;
this.data = null;
}
public Message(MessageCodeType code) {
this.code = code.getCode();
this.message = code.getMessage();
}
public void setCode(MessageCode messageCode )
{
code = messageCode.code;
}
public void setCode(MessageCodeType code) {
this.code = code.getCode();
}
}
... ...
package com.zhonglai.luhui.mqtt.dto;
public enum MessageCode implements MessageCodeType{
DEFAULT_FAIL_CODE(0, "请求失败"),
DEFAULT_SUCCESS_CODE(1, "请求成功"),
SESSION_TIME_OUT(2, "会话超时,请刷新令牌"),
USER_INVALID(4, "用户失效,请重新登录"),
SYS_ERROR(3, "已知系统错误"),
REQUEST_METHOD_ERROR(6, "请求方式错误"),
REQUEST_PATH_ERROR(7, "请求路径错误"),
UNKNOWN_SYS_ERROR(5, "未知系统错误");
public int code;
public String message;
public int getCode() {
return this.code;
}
public String getMessage() {
return this.message;
}
private MessageCode(int code, String message) {
this.code = code;
this.message = message;
}
}
... ...
package com.zhonglai.luhui.mqtt.dto;
public interface MessageCodeType {
int getCode();
String getMessage();
}
... ...
package com.zhonglai.luhui.mqtt.dto;
import lombok.Data;
/**
* 服务器下发数据
*/
@Data
public class PutDto {
private String data;
}
package com.zhonglai.luhui.mqtt.dto.topic;
import com.alibaba.fastjson.JSONObject;
import com.zhonglai.luhui.mqtt.comm.dto.ServerAgreementContent;
import com.zhonglai.luhui.mqtt.comm.dto.ServerDto;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class AddPostDto implements ServerDto {
private JSONObject data;
@Override
public ServerAgreementContent getServerAgreementContent() {
return null;
}
@Override
public boolean isReplyMessage() {
return false;
}
}
... ...
package com.zhonglai.luhui.mqtt.dto.topic;
import com.zhonglai.luhui.mqtt.comm.dto.ServerAgreementContent;
import com.zhonglai.luhui.mqtt.comm.dto.ServerDto;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class AllPostDto implements ServerDto {
@Override
public ServerAgreementContent getServerAgreementContent() {
return null;
}
@Override
public boolean isReplyMessage() {
return false;
}
}
... ...
package com.zhonglai.luhui.mqtt.dto.topic;
import com.zhonglai.luhui.mqtt.comm.dto.ServerAgreementContent;
import com.zhonglai.luhui.mqtt.comm.dto.ServerDto;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class DbDistributeDto implements ServerDto {
@Override
public ServerAgreementContent getServerAgreementContent() {
return null;
}
@Override
public boolean isReplyMessage() {
return false;
}
}
... ...
package com.zhonglai.luhui.mqtt.dto.topic;
import com.zhonglai.luhui.mqtt.comm.dto.ServerAgreementContent;
import com.zhonglai.luhui.mqtt.comm.dto.ServerDto;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class GetDto implements ServerDto {
@Override
public ServerAgreementContent getServerAgreementContent() {
return null;
}
@Override
public boolean isReplyMessage() {
return false;
}
}
... ...
package com.zhonglai.luhui.mqtt.dto.topic;
import com.zhonglai.luhui.mqtt.comm.dto.ServerAgreementContent;
import com.zhonglai.luhui.mqtt.comm.dto.ServerDto;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class GetReqDto implements ServerDto {
@Override
public ServerAgreementContent getServerAgreementContent() {
return null;
}
@Override
public boolean isReplyMessage() {
return false;
}
}
... ...
package com.zhonglai.luhui.mqtt.dto.topic;
import com.zhonglai.luhui.mqtt.comm.dto.ServerAgreementContent;
import com.zhonglai.luhui.mqtt.comm.dto.ServerDto;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class OnlineDto implements ServerDto {
@Override
public ServerAgreementContent getServerAgreementContent() {
return null;
}
@Override
public boolean isReplyMessage() {
return false;
}
}
... ...
package com.zhonglai.luhui.mqtt.dto.topic;
import com.zhonglai.luhui.mqtt.comm.dto.ServerAgreementContent;
import com.zhonglai.luhui.mqtt.comm.dto.ServerDto;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 服务器下发数据
*/
@Data
@Accessors(chain = true)
public class PutDto implements ServerDto {
private String data;
@Override
public ServerAgreementContent getServerAgreementContent() {
return null;
}
@Override
public boolean isReplyMessage() {
return false;
}
}
... ...
package com.zhonglai.luhui.mqtt.dto;
package com.zhonglai.luhui.mqtt.dto.topic;
import com.google.gson.JsonObject;
import com.luhui.ly.comm.util.GsonConstructor;
import com.luhui.ly.device.mqtt.comm.dto.ServerAgreementContent;
import com.luhui.ly.device.mqtt.comm.dto.ServerDto;
import com.luhui.ly.device.mqtt.comm.factory.Topic;
import com.zhonglai.dto.Message;
import com.zhonglai.dto.MessageCode;
import com.alibaba.fastjson.JSONObject;
import com.zhonglai.luhui.mqtt.comm.dto.ServerAgreementContent;
import com.zhonglai.luhui.mqtt.comm.dto.ServerDto;
import com.zhonglai.luhui.mqtt.comm.factory.Topic;
import com.zhonglai.luhui.mqtt.dto.Message;
import com.zhonglai.luhui.mqtt.dto.MessageCode;
import lombok.Data;
import lombok.experimental.Accessors;
... ... @@ -28,9 +27,9 @@ public class PutReqDto implements ServerDto {
@Override
public byte[] getCommd() {
JsonObject jsonObject = GsonConstructor.get().fromJson(GsonConstructor.get().toJson(putReqDto), JsonObject.class);
JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(putReqDto));
jsonObject.remove("messageid");
return GsonConstructor.get().toJson(jsonObject).getBytes();
return jsonObject.toJSONString().getBytes();
}
@Override
... ...
... ... @@ -3,7 +3,7 @@ package com.zhonglai.luhui.mqtt.service;
import com.zhonglai.luhui.mqtt.comm.dto.ServerDto;
import com.zhonglai.luhui.mqtt.comm.factory.Topic;
import com.zhonglai.luhui.mqtt.comm.service.CacheService;
import com.zhonglai.luhui.mqtt.dto.PutReqDto;
import com.zhonglai.luhui.mqtt.dto.topic.PutReqDto;
import org.springframework.stereotype.Service;
@Service
... ...
package com.zhonglai.luhui.mqtt.service.topic;
import com.zhonglai.luhui.mqtt.comm.dto.ServerDto;
import com.zhonglai.luhui.mqtt.comm.factory.BusinessAgreement;
import com.zhonglai.luhui.mqtt.comm.factory.Topic;
import com.zhonglai.luhui.mqtt.dto.topic.AddPostDto;
import org.springframework.stereotype.Service;
/**
* 增量上报数据,不需要返回
*/
@Service("ADD_POST")
public class AddPostTopic implements BusinessAgreement<AddPostDto> {
@Override
public ServerDto analysis(Topic topic, AddPostDto data) throws Exception {
return null;
}
@Override
public AddPostDto toData(byte[] data) {
return null;
}
}
... ...
package com.zhonglai.luhui.mqtt.service.topic;
import com.zhonglai.luhui.mqtt.comm.dto.ServerDto;
import com.zhonglai.luhui.mqtt.comm.factory.BusinessAgreement;
import com.zhonglai.luhui.mqtt.comm.factory.Topic;
import com.zhonglai.luhui.mqtt.dto.topic.AllPostDto;
import org.springframework.stereotype.Service;
/**
* 全量上报数据,不需要返回
*/
@Service("ALL_POST")
public class AllPostTopic implements BusinessAgreement<AllPostDto> {
@Override
public ServerDto analysis(Topic topic, AllPostDto data) throws Exception {
return null;
}
@Override
public AllPostDto toData(byte[] data) {
return null;
}
}
... ...
package com.zhonglai.luhui.mqtt.service.topic;
import com.zhonglai.luhui.mqtt.comm.dto.ServerDto;
import com.zhonglai.luhui.mqtt.comm.factory.BusinessAgreement;
import com.zhonglai.luhui.mqtt.comm.factory.Topic;
import com.zhonglai.luhui.mqtt.dto.topic.DbDistributeDto;
import org.springframework.stereotype.Service;
/**
* 数据库topic分发
*/
@Service("DB_TOPIC_DISTRIBUTE")
public class DbDistributeTopic implements BusinessAgreement<DbDistributeDto> {
@Override
public ServerDto analysis(Topic topic, DbDistributeDto data) throws Exception {
return null;
}
@Override
public DbDistributeDto toData(byte[] data) {
return null;
}
}
... ...
package com.zhonglai.luhui.mqtt.service.topic;
import com.zhonglai.luhui.mqtt.comm.dto.ServerDto;
import com.zhonglai.luhui.mqtt.comm.factory.BusinessAgreement;
import com.zhonglai.luhui.mqtt.comm.factory.Topic;
import com.zhonglai.luhui.mqtt.dto.topic.GetReqDto;
import org.springframework.stereotype.Service;
/**
* 获取数据的返回结果
*/
@Service("GET_REQ")
public class GetReqTopic implements BusinessAgreement<GetReqDto> {
@Override
public ServerDto analysis(Topic topic, GetReqDto data) throws Exception {
return null;
}
@Override
public GetReqDto toData(byte[] data) {
return null;
}
}
... ...
package com.zhonglai.luhui.mqtt.service.topic;
import com.zhonglai.luhui.mqtt.comm.dto.ServerDto;
import com.zhonglai.luhui.mqtt.comm.factory.BusinessAgreement;
import com.zhonglai.luhui.mqtt.comm.factory.Topic;
import com.zhonglai.luhui.mqtt.dto.topic.GetDto;
import org.springframework.stereotype.Service;
/**
* 获取数据
*/
@Service("GET")
public class GetTopic implements BusinessAgreement<GetDto> {
@Override
public ServerDto analysis(Topic topic, GetDto data) throws Exception {
return null;
}
@Override
public GetDto toData(byte[] data) {
return null;
}
}
... ...
package com.zhonglai.luhui.mqtt.service.topic;
import com.zhonglai.luhui.mqtt.comm.dto.ServerDto;
import com.zhonglai.luhui.mqtt.comm.factory.BusinessAgreement;
import com.zhonglai.luhui.mqtt.comm.factory.Topic;
import com.zhonglai.luhui.mqtt.dto.topic.OnlineDto;
import org.springframework.stereotype.Service;
@Service("ONLINE")
public class OnlineTopic implements BusinessAgreement<OnlineDto> {
@Override
public ServerDto analysis(Topic topic, OnlineDto data) throws Exception {
return null;
}
@Override
public OnlineDto toData(byte[] data) {
return null;
}
}
... ...
package com.zhonglai.luhui.mqtt.service.topic;
import com.zhonglai.luhui.mqtt.comm.dto.ServerDto;
import com.zhonglai.luhui.mqtt.comm.factory.BusinessAgreement;
import com.zhonglai.luhui.mqtt.comm.factory.Topic;
import com.zhonglai.luhui.mqtt.dto.topic.PutReqDto;
import org.springframework.stereotype.Service;
/**
* 更新数据的执行结果
*/
@Service("PUT_REQ")
public class PutReqTopic implements BusinessAgreement<PutReqDto> {
@Override
public ServerDto analysis(Topic topic, PutReqDto data) throws Exception {
return null;
}
@Override
public PutReqDto toData(byte[] data) {
return null;
}
}
... ...
package com.zhonglai.luhui.mqtt.service.topic;
import com.zhonglai.luhui.mqtt.comm.dto.ServerDto;
import com.zhonglai.luhui.mqtt.comm.factory.BusinessAgreement;
import com.zhonglai.luhui.mqtt.comm.factory.Topic;
import com.zhonglai.luhui.mqtt.dto.topic.PutDto;
import org.springframework.stereotype.Service;
/**
* 更新数据,需要返回执行结果
*/
@Service("PUT")
public class PutTopic implements BusinessAgreement<PutDto> {
@Override
public ServerDto analysis(Topic topic, PutDto data) throws Exception {
return null;
}
@Override
public PutDto toData(byte[] data) {
return null;
}
}
... ...
... ... @@ -44,8 +44,8 @@ mqtt:
#唯一标识
clientId: lh-mqtt-service-001
#订阅的topic
topics: "/2/2/X6/+/PUT_REQ"
topicconfig: "/{{roleid}}/{{userid}}/{{username}}/{{clientid}}/{{topicType}}"
topics: "/2/#"
topicconfig: "/{{roleid}}/{{username}}/{{clientid}}/{{payloadtype}}/{{topicType}}"
username: sysuser
password: "!@#1qaz"
client:
... ... @@ -61,4 +61,5 @@ mqtt:
sys:
redis:
field: "lh:mqtt:service:"
\ No newline at end of file
field: "lh:mqtt:service:"
... ...
... ... @@ -60,12 +60,12 @@ public class SysLoginService
*/
public String login(String username, String password, String code, String uuid)
{
boolean captchaOnOff = configService.selectCaptchaOnOff();
// 验证码开关
if (captchaOnOff)
{
validateCaptcha(username, code, uuid);
}
// boolean captchaOnOff = configService.selectCaptchaOnOff();
// // 验证码开关
// if (captchaOnOff)
// {
// validateCaptcha(username, code, uuid);
// }
// 用户验证
Authentication authentication = null;
try
... ...
... ... @@ -106,7 +106,18 @@ public class IotDevice extends BaseEntity
@ApiModelProperty("用户id")
private Integer user_id;
public void setActive_time(Integer active_time)
@ApiModelProperty("负载类型(String,Json,Bite16,Bite32)")
private String payload_type;
public String getPayload_type() {
return payload_type;
}
public void setPayload_type(String payload_type) {
this.payload_type = payload_type;
}
public void setActive_time(Integer active_time)
{
this.active_time = active_time;
}
... ...
... ... @@ -28,10 +28,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="update_by" column="update_by" />
<result property="update_time" column="update_time" />
<result property="user_id" column="user_id" />
<result property="payload_type" column="payload_type" />
</resultMap>
<sql id="selectIotDeviceVo">
select active_time, client_id, completion_auth, create_by, create_time, del_flag, firmware_version, img_url, is_shadow, latitude, location_way, longitude, name, network_address, network_ip, remark, rssi, status, summary, things_model_value, update_by, update_time, user_id from iot_device
select active_time, client_id, completion_auth, create_by, create_time, del_flag, firmware_version, img_url, is_shadow, latitude, location_way, longitude, `name`, network_address, network_ip, remark, rssi, status, summary, things_model_value, update_by, update_time, user_id,payload_type from iot_device
</sql>
<select id="selectIotDeviceList" parameterType="IotDevice" resultMap="IotDeviceResult">
... ... @@ -71,6 +73,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="update_by != null">update_by,</if>
<if test="update_time != null">update_time,</if>
<if test="user_id != null">user_id,</if>
<if test="payload_type != null">payload_type,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="active_time != null">#{active_time},</if>
... ... @@ -96,6 +100,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="update_by != null">#{update_by},</if>
<if test="update_time != null">#{update_time},</if>
<if test="user_id != null">#{user_id},</if>
<if test="payload_type != null">#{payload_type},</if>
</trim>
</insert>
... ... @@ -124,6 +129,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="update_by != null">update_by = #{update_by},</if>
<if test="update_time != null">update_time = #{update_time},</if>
<if test="user_id != null">user_id = #{user_id},</if>
<if test="payload_type != null">user_id = #{payload_type},</if>
</trim>
where client_id = #{client_id}
</update>
... ...