Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
|
5ba1cd9a4a |
Binary file not shown.
File diff suppressed because it is too large
Load Diff
72
pom.xml
72
pom.xml
|
@ -6,43 +6,33 @@
|
|||
|
||||
<groupId>com.muyu</groupId>
|
||||
<artifactId>VehicleSimulation</artifactId>
|
||||
<version>1.0.7</version>
|
||||
<version>1.0.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<mybatisplus.version>3.5.7</mybatisplus.version>
|
||||
<forest.version>1.5.36</forest.version>
|
||||
<jjwt.version>0.12.5</jjwt.version>
|
||||
<mybatisplus.version>3.5.1</mybatisplus.version>
|
||||
</properties>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.2.4</version>
|
||||
<version>2.7.15</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<!-- SpringBootWeb开发框架 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- SpringBoot测试框架 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- SpringBoot校验框架 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- mqtt3 -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.paho</groupId>
|
||||
|
@ -50,7 +40,7 @@
|
|||
<version>1.2.5</version>
|
||||
</dependency>
|
||||
|
||||
<!-- lombok插件 -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
|
@ -59,17 +49,25 @@
|
|||
<!-- mybatis-plus 所需依赖 -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>${mybatisplus.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- mysql数据库驱动 -->
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-generator</artifactId>
|
||||
<version>${mybatisplus.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.freemarker</groupId>
|
||||
<artifactId>freemarker</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 使用h2内存数据库 -->
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- json处理框架 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2</artifactId>
|
||||
|
@ -79,8 +77,14 @@
|
|||
<!-- http调用框架 -->
|
||||
<dependency>
|
||||
<groupId>com.dtflys.forest</groupId>
|
||||
<artifactId>forest-spring-boot3-starter</artifactId>
|
||||
<version>${forest.version}</version>
|
||||
<artifactId>forest-spring-boot-starter</artifactId>
|
||||
<version>1.5.33</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.73</version>
|
||||
</dependency>
|
||||
|
||||
<!--常用工具类 -->
|
||||
|
@ -88,28 +92,6 @@
|
|||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- JWT -->
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt</artifactId>
|
||||
<version>${jjwt.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<finalName>vehicle-simulation-${version}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -3,8 +3,6 @@ package com.muyu;
|
|||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
/**
|
||||
* @author DongZeLiang
|
||||
|
@ -12,9 +10,8 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
|||
* @description 车辆模拟启动类
|
||||
* @date 2023/11/9
|
||||
*/
|
||||
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
|
||||
@SpringBootApplication
|
||||
@MapperScan(value = "com.muyu.**.mapper")
|
||||
@EnableTransactionManagement
|
||||
public class VehicleSimulationApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
package com.muyu.cache;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Expiry;
|
||||
import org.checkerframework.checker.index.qual.NonNegative;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/12
|
||||
* @Description: 缓存过期
|
||||
* @Version: 1.0
|
||||
*/
|
||||
public class CacheExpiry<K, V extends ExpiryTime> implements Expiry<K, ExpiryTime> {
|
||||
/**
|
||||
* @param key 缓存键
|
||||
* @param value 缓存值
|
||||
* @param currentTime 当前时间戳
|
||||
*
|
||||
* @return 进入有效期前的时间长度,以纳秒为单位
|
||||
*/
|
||||
@Override
|
||||
public long expireAfterCreate (K key, ExpiryTime value, long currentTime) {
|
||||
return TimeUnit.SECONDS.toNanos(value.getExpiryTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key 缓存键
|
||||
* @param value 缓存值
|
||||
* @param currentTime 当前时间戳
|
||||
* @param currentDuration 剩余时间
|
||||
*
|
||||
* @return 进入有效期前的时间长度,以纳秒为单位
|
||||
*/
|
||||
@Override
|
||||
public long expireAfterUpdate (K key, ExpiryTime value, long currentTime, @NonNegative long currentDuration) {
|
||||
return TimeUnit.SECONDS.toNanos(value.getRefreshTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key 缓存键
|
||||
* @param value 缓存值
|
||||
* @param currentTime 当前时间戳
|
||||
* @param currentDuration 剩余持续时间
|
||||
*
|
||||
* @return 进入有效期前的时间长度,以纳秒为单位
|
||||
*/
|
||||
@Override
|
||||
public long expireAfterRead (K key, ExpiryTime value, long currentTime, @NonNegative long currentDuration) {
|
||||
return TimeUnit.SECONDS.toNanos(value.getRefreshTime());
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package com.muyu.cache;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 缓存配置类
|
||||
*/
|
||||
@Configuration
|
||||
public class CaffeineConfig {
|
||||
@Bean("loginUserCache")
|
||||
public Cache<String, ? extends ExpiryTime> loginUserCache(){
|
||||
CacheExpiry<String, ExpiryTime> cacheExpiry = new CacheExpiry<>();
|
||||
return Caffeine.newBuilder()
|
||||
.expireAfter(cacheExpiry)
|
||||
.initialCapacity(128)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean("messageTemplateCache")
|
||||
public Cache<Long, ? extends ExpiryTime> messageTemplateCache(){
|
||||
CacheExpiry<Long, ExpiryTime> cacheExpiry = new CacheExpiry<>();
|
||||
return Caffeine.newBuilder()
|
||||
.expireAfter(cacheExpiry)
|
||||
.initialCapacity(128)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
package com.muyu.cache;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/12
|
||||
* @Description: 过期时间
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ExpiryTime {
|
||||
|
||||
/**
|
||||
* 过期时间单位(秒) 默认30分钟
|
||||
*/
|
||||
@Builder.Default
|
||||
private long expiryTime = 30*60;
|
||||
|
||||
/**
|
||||
* 刷新时间单位(秒) 默认15分钟
|
||||
*/
|
||||
@Builder.Default
|
||||
private long refreshTime = 15*60;
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
package com.muyu.cache.model;
|
||||
|
||||
import com.muyu.cache.ExpiryTime;
|
||||
import com.muyu.web.domain.MessageTemplate;
|
||||
import com.muyu.web.domain.MessageTemplateValue;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/25
|
||||
* @Description: 模板报文模型
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class MessageTemplateCacheModel extends ExpiryTime {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
private Long key;
|
||||
|
||||
/**
|
||||
* 报文名称
|
||||
*/
|
||||
private String messageName;
|
||||
|
||||
/**
|
||||
* 报文模板值集合
|
||||
*/
|
||||
private List<MessageTemplateValue> messageTemplateValueList;
|
||||
|
||||
public static MessageTemplateCacheModel messageTemplateBuild(
|
||||
MessageTemplate messageTemplate, Function<Long,List<MessageTemplateValue>> function) {
|
||||
return MessageTemplateCacheModel.builder()
|
||||
.key(messageTemplate.getId())
|
||||
.messageName(messageTemplate.getMessageName())
|
||||
.messageTemplateValueList(function.apply(messageTemplate.getId()))
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
package com.muyu.config;
|
||||
|
||||
import com.muyu.utils.AesUtil;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
/**
|
||||
* 数据源配置
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/11
|
||||
* @Description: 数据源配置
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Log4j2
|
||||
@Configuration
|
||||
public class DataSourceConfig {
|
||||
|
||||
/**
|
||||
* 初始化数据源Bean
|
||||
* @param dataSourceProperties 数据库配置
|
||||
* @return hikari数据源
|
||||
*/
|
||||
@Bean
|
||||
public HikariDataSource initDataSource(DataSourceProperties dataSourceProperties) throws Exception {
|
||||
HikariDataSource hikariDataSource = new HikariDataSource();
|
||||
hikariDataSource.setJdbcUrl(AesUtil.decrypt(dataSourceProperties.getUrl()));
|
||||
hikariDataSource.setUsername(AesUtil.decrypt(dataSourceProperties.getUsername()));
|
||||
hikariDataSource.setPassword(AesUtil.decrypt(dataSourceProperties.getPassword()));
|
||||
hikariDataSource.setDriverClassName(dataSourceProperties.getDriverClassName());
|
||||
Connection connection = hikariDataSource.getConnection();
|
||||
log.info("数据源[{}]初始化成功", dataSourceProperties.getName());
|
||||
hikariDataSource.evictConnection(connection);
|
||||
return hikariDataSource;
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
package com.muyu.config;
|
||||
|
||||
import com.muyu.system.exception.BasicException;
|
||||
import com.muyu.web.common.Result;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
/**
|
||||
* 异常类
|
||||
* @author DongZeLiang
|
||||
* @version 1.0
|
||||
* @description 异常类
|
||||
* @date 2023/11/15
|
||||
*/
|
||||
@Log4j2
|
||||
@RestControllerAdvice
|
||||
public class ExceptionAdvice {
|
||||
|
||||
/**
|
||||
* 运行时异常拦截
|
||||
* @param exception 运行时异常
|
||||
* @return 公共返回结果
|
||||
*/
|
||||
@ExceptionHandler(value = RuntimeException.class)
|
||||
public Result<String> runtimeExceptionHandler(HttpServletRequest request, RuntimeException exception){
|
||||
log.error("请求发生异常:[{}] ----- [{}]",request.getRequestURI(), exception.getMessage(), exception);
|
||||
return Result.error(exception.getMessage());
|
||||
}
|
||||
/**
|
||||
* 运行时异常拦截
|
||||
* @param exception 运行时异常
|
||||
* @return 公共返回结果
|
||||
*/
|
||||
@ExceptionHandler(value = BasicException.class)
|
||||
public Result<String> runtimeExceptionHandler(HttpServletRequest request, BasicException exception){
|
||||
log.error("请求发生异常:[{}] ----- [{}]",request.getRequestURI(), exception.getMessage(), exception);
|
||||
|
||||
return Result.error(exception.getCode(), exception.getMessage());
|
||||
}
|
||||
/**
|
||||
* 运行时异常拦截
|
||||
* @param exception 运行时异常
|
||||
* @return 公共返回结果
|
||||
*/
|
||||
@ExceptionHandler(value = MethodArgumentNotValidException.class)
|
||||
public Result<String> runtimeExceptionHandler(HttpServletRequest request, MethodArgumentNotValidException exception){
|
||||
log.error("请求发生异常:[{}] ----- [{}]",request.getRequestURI(), exception.getMessage(), exception);
|
||||
return Result.error(exception.getAllErrors().get(0).getDefaultMessage());
|
||||
}
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
package com.muyu.config;
|
||||
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import com.muyu.system.handle.SystemHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 填充公共字段
|
||||
*
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class MyMetaObjectHandler implements MetaObjectHandler {
|
||||
|
||||
public MyMetaObjectHandler () {
|
||||
log.info("元数据填充初始化成功");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
String[] setterNames = metaObject.getSetterNames();
|
||||
Set<String> setterNamesSet = Arrays.stream(setterNames).collect(Collectors.toSet());
|
||||
if (setterNamesSet.contains("tenantId")){
|
||||
if (metaObject.getValue("tenantId") == null){
|
||||
this.setFieldValByName("tenantId", SystemHandler.getTenantId(),metaObject);
|
||||
}
|
||||
}
|
||||
if (setterNamesSet.contains("createTime")){
|
||||
|
||||
if (metaObject.getValue("createTime") == null) {
|
||||
this.setFieldValByName("createTime", new Date(), metaObject);
|
||||
}
|
||||
}
|
||||
if (setterNamesSet.contains("updateTime")){
|
||||
if (metaObject.getValue("updateTime") == null) {
|
||||
this.setFieldValByName("updateTime", new Date(), metaObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
String[] setterNames = metaObject.getSetterNames();
|
||||
Set<String> setterNamesSet = Arrays.stream(setterNames).collect(Collectors.toSet());
|
||||
if (setterNamesSet.contains("updateTime")){
|
||||
if (metaObject.getValue("updateTime") == null) {
|
||||
this.setFieldValByName("updateTime", new Date(), metaObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package com.muyu.config;
|
||||
|
||||
import com.muyu.config.interceptor.LoginInterceptor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 注册处理器拦截器
|
||||
* */
|
||||
@Configuration
|
||||
public class SystemWebConfigurer implements WebMvcConfigurer {
|
||||
|
||||
@Autowired
|
||||
private LoginInterceptor loginInterceptor;
|
||||
|
||||
/** 拦截器配置 */
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
// 白名单
|
||||
List<String> patterns = new ArrayList<String>();
|
||||
patterns.add("/system/auth/reg");
|
||||
patterns.add("/system/auth/login");
|
||||
patterns.add("/system/auth/logout");
|
||||
patterns.add("/");
|
||||
patterns.add("/static/**");
|
||||
|
||||
// 通过注册工具添加拦截器
|
||||
registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns(patterns);
|
||||
}
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
package com.muyu.config.interceptor;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.muyu.system.constants.TokenConstants;
|
||||
import com.muyu.system.context.SystemUserContext;
|
||||
import com.muyu.system.domain.LoginUserInfo;
|
||||
import com.muyu.system.exception.BasicException;
|
||||
import com.muyu.utils.JwtUtils;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* 用户登录拦截器
|
||||
*/
|
||||
@Component
|
||||
public class LoginInterceptor implements HandlerInterceptor {
|
||||
|
||||
@Resource( name = "loginUserCache")
|
||||
private Cache<String, LoginUserInfo> loginUserInfoCache;
|
||||
|
||||
/**
|
||||
* 在请求被处理之前进行操作
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @param handler
|
||||
* @return 返回true表示继续执行后续的拦截器或Controller;返回false则不再执行后续的拦截器或Controller
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception {
|
||||
// 判断当前请求是否需要被拦截
|
||||
String token = request.getHeader(TokenConstants.AUTHENTICATION);
|
||||
if (StringUtils.isEmpty(token)){
|
||||
throw new BasicException(501,"未授权请求,请重新授权");
|
||||
}
|
||||
Claims claims = JwtUtils.parseToken(token);
|
||||
String userKey = JwtUtils.getUserKey(claims);
|
||||
LoginUserInfo loginUserInfo = loginUserInfoCache.getIfPresent(userKey);
|
||||
if (loginUserInfo == null){
|
||||
throw new BasicException(502,"用户授权过期,请重新登录");
|
||||
}
|
||||
SystemUserContext.set(loginUserInfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在请求被处理之后但视图还未渲染时进行操作
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @param handler
|
||||
* @param modelAndView
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public void postHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, ModelAndView modelAndView) throws Exception {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 在整个请求结束之后(包括视图已经渲染)进行操作
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @param handler
|
||||
* @param ex
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public void afterCompletion(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, Exception ex) throws Exception {
|
||||
SystemUserContext.remove();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
package com.muyu.config.runner;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.muyu.cache.model.MessageTemplateCacheModel;
|
||||
import com.muyu.config.tenant.CustomTenantHandler;
|
||||
import com.muyu.vehicle.VehicleInstance;
|
||||
import com.muyu.vehicle.core.LocalContainer;
|
||||
import com.muyu.web.common.pool.FixedThreadPool;
|
||||
import com.muyu.web.common.pool.ScheduledThreadPool;
|
||||
import com.muyu.web.domain.VehicleInfo;
|
||||
import com.muyu.web.service.MessageTemplateService;
|
||||
import com.muyu.web.service.MessageTemplateValueService;
|
||||
import com.muyu.web.service.VehicleInfoService;
|
||||
import com.muyu.web.service.VehicleInstanceService;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 车辆
|
||||
* @author DongZeLiang
|
||||
* @version 1.0
|
||||
* @description 车辆
|
||||
* @date 2023/11/9
|
||||
*/
|
||||
@Log4j2
|
||||
@Configuration
|
||||
public class VehicleConfigRunner implements ApplicationRunner {
|
||||
|
||||
@Autowired
|
||||
private VehicleInfoService vehicleInfoService;
|
||||
|
||||
@Autowired
|
||||
private VehicleInstanceService vehicleInstanceService;
|
||||
|
||||
@Autowired
|
||||
private CustomTenantHandler customTenantHandler;
|
||||
|
||||
/**
|
||||
* 报文模板缓存
|
||||
*/
|
||||
@Resource(name = "messageTemplateCache")
|
||||
private Cache<Long, MessageTemplateCacheModel> messageTemplateCache;
|
||||
|
||||
/**
|
||||
* 报文模板业务类
|
||||
*/
|
||||
@Autowired
|
||||
private MessageTemplateService messageTemplateService;
|
||||
|
||||
/**
|
||||
* 报文模板业务值类
|
||||
*/
|
||||
@Autowired
|
||||
private MessageTemplateValueService messageTemplateValueService;
|
||||
|
||||
|
||||
public void initMessageTemplate() {
|
||||
long startTime = System.currentTimeMillis();
|
||||
log.info("开始初始化加载报文模板---------------");
|
||||
messageTemplateService
|
||||
.list()
|
||||
.stream()
|
||||
.map(messageTemplate -> MessageTemplateCacheModel.messageTemplateBuild(messageTemplate, messageTemplateValueService::valueListByMsgId))
|
||||
.filter(model -> {
|
||||
log.info(
|
||||
"过滤校验报文模板[{}-{}] 报文值个数-[{}个] -- {}",
|
||||
model.getKey(), model.getMessageName(), model.getMessageTemplateValueList().size(),
|
||||
model.getMessageTemplateValueList().isEmpty() ? "不合格,已过滤" : "合格"
|
||||
);
|
||||
return !model.getMessageTemplateValueList().isEmpty();
|
||||
})
|
||||
.forEach(model -> messageTemplateCache.put(model.getKey(), model));
|
||||
log.info("结束初始化加载报文模板耗时:[{}MS]---------------", System.currentTimeMillis() - startTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化加载汽车数据到内存当中
|
||||
*/
|
||||
public void vehiclePageInit (){
|
||||
long startTime = System.currentTimeMillis();
|
||||
int page = 0, pageSize = 10;
|
||||
log.info("初始开始,批量从数据库当中加载数据到内存当中,每次[{}]条", pageSize);
|
||||
while (true){
|
||||
Page<VehicleInfo> vehiclePage = vehicleInfoService.page(new Page<>(page++, pageSize));
|
||||
List<VehicleInfo> vehicleInfoList = vehiclePage.getRecords();
|
||||
vehicleInfoList.forEach(vehicleInstanceService::init);
|
||||
log.debug("第[{}]页,[{}]条", page, vehicleInfoList.size());
|
||||
if (vehicleInfoList.size() < pageSize){
|
||||
break;
|
||||
}
|
||||
}
|
||||
log.info("数据加载完成,耗时:{} MS", System.currentTimeMillis() - startTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run (ApplicationArguments args) {
|
||||
customTenantHandler.ignore();
|
||||
this.initMessageTemplate();
|
||||
this.vehiclePageInit();
|
||||
customTenantHandler.remove();
|
||||
// 提交给线程池 一分钟 执行一次
|
||||
// ThreadPool.submit(new Thread(vehicleService::syncDb), 30);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭程序前操作
|
||||
*/
|
||||
@PreDestroy
|
||||
public void destroy(){
|
||||
log.info("数据库同步");
|
||||
vehicleInfoService.syncDb();
|
||||
|
||||
log.info("下线所有车辆");
|
||||
List<VehicleInstance> onlineVehicleInstanceList = LocalContainer.getTenantOnlineVehicleInstance();
|
||||
onlineVehicleInstanceList.forEach(VehicleInstance::closeClient);
|
||||
|
||||
log.info("关闭线程池");
|
||||
ScheduledThreadPool.shutdown();
|
||||
FixedThreadPool.shutDown();
|
||||
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
package com.muyu.config.tenant;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
|
||||
import com.muyu.system.handle.SystemHandler;
|
||||
import com.muyu.web.utils.Convert;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.StringValue;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@Component
|
||||
public class CustomTenantHandler implements TenantLineHandler {
|
||||
|
||||
private static final ThreadLocal<Boolean> ignoreTableThreadLocal = new ThreadLocal<>();
|
||||
|
||||
public void ignore(){
|
||||
ignoreTableThreadLocal.set(true);
|
||||
}
|
||||
public void remove(){
|
||||
ignoreTableThreadLocal.remove();
|
||||
}
|
||||
|
||||
private static final Set<String> ignoreTableSet = new HashSet<String>(){{
|
||||
add("user_info");
|
||||
}};
|
||||
|
||||
@Override
|
||||
public Expression getTenantId() {
|
||||
// 假设有一个租户上下文,能够从中获取当前用户的租户
|
||||
String tenantId = SystemHandler.getTenantId();
|
||||
// 返回租户ID的表达式,LongValue 是 JSQLParser 中表示 bigint 类型的 class
|
||||
return new StringValue(tenantId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTenantIdColumn() {
|
||||
return "tenant_id";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ignoreTable(String tableName) {
|
||||
// 根据需要返回是否忽略该表
|
||||
return Convert.toBool(ignoreTableThreadLocal.get(), Boolean.FALSE) || ignoreTableSet.contains(tableName);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
package com.muyu.system.constants;
|
||||
|
||||
/**
|
||||
* 权限相关通用常量
|
||||
*
|
||||
* @author muyu
|
||||
*/
|
||||
public class SecurityConstants {
|
||||
/**
|
||||
* 用户ID字段
|
||||
*/
|
||||
public static final String DETAILS_USER_ID = "user_id";
|
||||
|
||||
/**
|
||||
* 用户名字段
|
||||
*/
|
||||
public static final String DETAILS_USERNAME = "username";
|
||||
|
||||
/**
|
||||
* 授权信息字段
|
||||
*/
|
||||
public static final String AUTHORIZATION_HEADER = "authorization";
|
||||
|
||||
/**
|
||||
* 请求来源
|
||||
*/
|
||||
public static final String FROM_SOURCE = "from-source";
|
||||
|
||||
/**
|
||||
* 内部请求
|
||||
*/
|
||||
public static final String INNER = "inner";
|
||||
|
||||
/**
|
||||
* 用户标识
|
||||
*/
|
||||
public static final String USER_KEY = "user_key";
|
||||
|
||||
/**
|
||||
* 登录用户
|
||||
*/
|
||||
public static final String LOGIN_USER = "login_user";
|
||||
|
||||
/**
|
||||
* 角色权限
|
||||
*/
|
||||
public static final String ROLE_PERMISSION = "role_permission";
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package com.muyu.system.constants;
|
||||
|
||||
/**
|
||||
* Token的Key常量
|
||||
*
|
||||
* @author muyu
|
||||
*/
|
||||
public class TokenConstants {
|
||||
/**
|
||||
* 令牌自定义标识
|
||||
*/
|
||||
public static final String AUTHENTICATION = "Authorization";
|
||||
|
||||
/**
|
||||
* 令牌前缀
|
||||
*/
|
||||
public static final String PREFIX = "Bearer ";
|
||||
|
||||
/**
|
||||
* 令牌秘钥
|
||||
*/
|
||||
public final static String SECRET = "abcdefghijklmnsalieopadfaqawefwerstuvwxyz";
|
||||
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package com.muyu.system.context;
|
||||
|
||||
import com.muyu.system.domain.LoginUserInfo;
|
||||
|
||||
/**
|
||||
* @Description: 系统用户上下文
|
||||
* @author: MuYu
|
||||
* @date: 2024/9/10-下午5:52
|
||||
*/
|
||||
public class SystemUserContext {
|
||||
|
||||
/**
|
||||
* 系统用户线程变量
|
||||
*/
|
||||
private static final ThreadLocal<LoginUserInfo> basicContextLocal = new ThreadLocal<>();
|
||||
|
||||
|
||||
public static LoginUserInfo get() {
|
||||
return basicContextLocal.get();
|
||||
}
|
||||
|
||||
public static void set(LoginUserInfo value) {
|
||||
basicContextLocal.set(value);
|
||||
}
|
||||
|
||||
public static void remove() {
|
||||
basicContextLocal.remove();
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
package com.muyu.system.domain;
|
||||
|
||||
import com.muyu.cache.ExpiryTime;
|
||||
import com.muyu.system.properties.ServerConfigProperties;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
/**
|
||||
* @Description: 登陆用户信息
|
||||
* @author: MuYu
|
||||
* @date: 2024/9/11-上午10:15
|
||||
*/
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class LoginUserInfo extends ExpiryTime {
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户token
|
||||
*/
|
||||
private String userKey;
|
||||
|
||||
/**
|
||||
* 用户名称
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
private String tenantId;
|
||||
|
||||
/**
|
||||
* 服务配置
|
||||
*/
|
||||
private ServerConfigProperties serverConfig;
|
||||
|
||||
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
package com.muyu.system.enums;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/20
|
||||
* @Description: 车辆报文值类型
|
||||
* @Version: 1.0
|
||||
*/
|
||||
public enum MessageTemplateValueType {
|
||||
FIXED("fixed", "固定"),
|
||||
INTERVAL("interval", "区间"),
|
||||
EL("el","表达式");
|
||||
|
||||
/**
|
||||
* 编码
|
||||
*/
|
||||
private final String code;
|
||||
|
||||
/**
|
||||
* 标签
|
||||
*/
|
||||
private final String label;
|
||||
|
||||
MessageTemplateValueType (String code, String label) {
|
||||
this.code = code;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public String code () {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String label () {
|
||||
return label;
|
||||
}
|
||||
|
||||
public static MessageTemplateValueType get(String code){
|
||||
return Arrays.stream(MessageTemplateValueType.values())
|
||||
.filter(valueType -> valueType.code.equals(code))
|
||||
.findFirst().orElse(null);
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package com.muyu.system.exception;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/13
|
||||
* @Description: 公共异常
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class BasicException extends RuntimeException{
|
||||
|
||||
private final int code;
|
||||
|
||||
private final String msg;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the detail message string of this throwable.
|
||||
*
|
||||
* @return the detail message string of this {@code Throwable} instance
|
||||
* (which may be {@code null}).
|
||||
*/
|
||||
@Override
|
||||
public String getMessage () {
|
||||
return this.msg;
|
||||
}
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
package com.muyu.system.handle;
|
||||
|
||||
import com.muyu.system.context.SystemUserContext;
|
||||
import com.muyu.system.domain.LoginUserInfo;
|
||||
import com.muyu.system.properties.ServerConfigProperties;
|
||||
|
||||
/**
|
||||
* @Description: 系统处理器
|
||||
* @author: MuYu
|
||||
* @date: 2024/9/11-上午10:23
|
||||
*/
|
||||
public class SystemHandler {
|
||||
|
||||
/**
|
||||
* 获取登陆用户信息
|
||||
* @return 登陆用户信息
|
||||
*/
|
||||
public static LoginUserInfo getUserInfo(){
|
||||
return SystemUserContext.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户key
|
||||
* @return 用户Key
|
||||
*/
|
||||
public static String getUserKey(){
|
||||
return getUserInfo().getUserKey();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 登陆用户ID
|
||||
* @return 登录用户ID
|
||||
*/
|
||||
public static Long getUserId(){
|
||||
return getUserInfo().getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取服务器配置
|
||||
* @return 当前用户服务器配置
|
||||
*/
|
||||
public static ServerConfigProperties getServerConfig(){
|
||||
return SystemUserContext.get().getServerConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* 存储当前服务器配置
|
||||
*/
|
||||
public static void setServerConfig(ServerConfigProperties serverConfig){
|
||||
SystemUserContext.get().setServerConfig(serverConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取负载地址
|
||||
* @return 负载地址
|
||||
*/
|
||||
public static String getLoadReqUrl(){
|
||||
return getServerConfig().getLoadReqUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取租户ID
|
||||
* @return 租户ID
|
||||
*/
|
||||
public static String getTenantId () {
|
||||
return getUserInfo().getTenantId();
|
||||
}
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
package com.muyu.system.properties;
|
||||
|
||||
import com.muyu.web.domain.ServerConfig;
|
||||
import com.muyu.web.domain.model.ServerConfigModel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/6/10
|
||||
* @Description: 服务器配置类
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ServerConfigProperties {
|
||||
|
||||
/**
|
||||
* 主机地址
|
||||
*/
|
||||
private String host;
|
||||
/**
|
||||
* 端口号
|
||||
*/
|
||||
private String port;
|
||||
/**
|
||||
* 负载地址
|
||||
*/
|
||||
private String uri;
|
||||
/**
|
||||
* 负载请求格式化地址
|
||||
*/
|
||||
private String loadReqUrl;
|
||||
/**
|
||||
* 默认MQTT地址
|
||||
*/
|
||||
private String mqttAddr;
|
||||
/**
|
||||
* 默认MQTT主题
|
||||
*/
|
||||
private String mqttTopic;
|
||||
/**
|
||||
* 默认MQTT交付级别
|
||||
*/
|
||||
private Integer mqttQos;
|
||||
|
||||
/**
|
||||
* 模型构建配置
|
||||
* @param serverConfigModel 配置模型对象
|
||||
* @return 配置对象
|
||||
*/
|
||||
public static ServerConfigProperties modelToProperties(ServerConfigModel serverConfigModel) {
|
||||
|
||||
return ServerConfigProperties.builder()
|
||||
.host(serverConfigModel.getHost())
|
||||
.port(serverConfigModel.getPort())
|
||||
.uri(serverConfigModel.getUri())
|
||||
.mqttAddr(serverConfigModel.getDefaultMqttAddr())
|
||||
.mqttTopic(serverConfigModel.getDefaultMqttTopic())
|
||||
.mqttQos(serverConfigModel.getDefaultMqttQos())
|
||||
.loadReqUrl(
|
||||
String.format(
|
||||
"http://%s:%s%s",
|
||||
serverConfigModel.getHost(),
|
||||
serverConfigModel.getPort(),
|
||||
serverConfigModel.getUri().startsWith("/") ? serverConfigModel.getUri() : "/" + serverConfigModel.getUri()
|
||||
)
|
||||
)
|
||||
.build();
|
||||
}
|
||||
/**
|
||||
* 模型构建配置
|
||||
* @param serverConfig 配置对象
|
||||
* @return 配置对象
|
||||
*/
|
||||
public static ServerConfigProperties configToProperties(ServerConfig serverConfig ) {
|
||||
|
||||
return ServerConfigProperties.builder()
|
||||
.host(serverConfig.getHost())
|
||||
.port(serverConfig.getPort())
|
||||
.uri(serverConfig.getUri())
|
||||
.mqttAddr(serverConfig.getDefaultMqttAddr())
|
||||
.mqttTopic(serverConfig.getDefaultMqttTopic())
|
||||
.mqttQos(serverConfig.getDefaultMqttQos())
|
||||
.loadReqUrl(
|
||||
String.format(
|
||||
"http://%s:%s%s",
|
||||
serverConfig.getHost(),
|
||||
serverConfig.getPort(),
|
||||
serverConfig.getUri().startsWith("/") ? serverConfig.getUri() : "/" + serverConfig.getUri()
|
||||
)
|
||||
)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
package com.muyu.utils;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
|
||||
public class AesUtil {
|
||||
|
||||
private static final String key = "oLXZmx1h1nAo2G832yEceA==";
|
||||
|
||||
private static final String ALGORITHM = "AES";
|
||||
private static final int KEY_SIZE = 128;
|
||||
|
||||
public static String generateKey() throws Exception {
|
||||
KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
|
||||
keyGenerator.init(KEY_SIZE);
|
||||
SecretKey secretKey = keyGenerator.generateKey();
|
||||
return Base64.getEncoder().encodeToString(secretKey.getEncoded());
|
||||
}
|
||||
|
||||
public static String encrypt(String data) throws Exception {
|
||||
Cipher cipher = Cipher.getInstance(ALGORITHM);
|
||||
SecretKeySpec secretKeySpec = new SecretKeySpec(Base64.getDecoder().decode(key), ALGORITHM);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
|
||||
byte[] encryptedBytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
|
||||
return Base64.getEncoder().encodeToString(encryptedBytes);
|
||||
}
|
||||
|
||||
public static String decrypt(String encryptedData) throws Exception {
|
||||
Cipher cipher = Cipher.getInstance(ALGORITHM);
|
||||
SecretKeySpec secretKeySpec = new SecretKeySpec(Base64.getDecoder().decode(key), ALGORITHM);
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
|
||||
byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
|
||||
return new String(decryptedBytes, StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
|
@ -1,134 +0,0 @@
|
|||
package com.muyu.utils;
|
||||
|
||||
/**
|
||||
* 通用常量信息
|
||||
*
|
||||
* @author muyu
|
||||
*/
|
||||
public class Constants {
|
||||
/**
|
||||
* UTF-8 字符集
|
||||
*/
|
||||
public static final String UTF8 = "UTF-8";
|
||||
|
||||
/**
|
||||
* GBK 字符集
|
||||
*/
|
||||
public static final String GBK = "GBK";
|
||||
|
||||
/**
|
||||
* www主域
|
||||
*/
|
||||
public static final String WWW = "www.";
|
||||
|
||||
/**
|
||||
* RMI 远程方法调用
|
||||
*/
|
||||
public static final String LOOKUP_RMI = "rmi:";
|
||||
|
||||
/**
|
||||
* LDAP 远程方法调用
|
||||
*/
|
||||
public static final String LOOKUP_LDAP = "ldap:";
|
||||
|
||||
/**
|
||||
* LDAPS 远程方法调用
|
||||
*/
|
||||
public static final String LOOKUP_LDAPS = "ldaps:";
|
||||
|
||||
/**
|
||||
* http请求
|
||||
*/
|
||||
public static final String HTTP = "http://";
|
||||
|
||||
/**
|
||||
* https请求
|
||||
*/
|
||||
public static final String HTTPS = "https://";
|
||||
|
||||
/**
|
||||
* 成功标记
|
||||
*/
|
||||
public static final Integer SUCCESS = 200;
|
||||
|
||||
/**
|
||||
* 失败标记
|
||||
*/
|
||||
public static final Integer FAIL = 500;
|
||||
|
||||
/**
|
||||
* 登录成功状态
|
||||
*/
|
||||
public static final String LOGIN_SUCCESS_STATUS = "0";
|
||||
|
||||
/**
|
||||
* 登录失败状态
|
||||
*/
|
||||
public static final String LOGIN_FAIL_STATUS = "1";
|
||||
|
||||
/**
|
||||
* 登录成功
|
||||
*/
|
||||
public static final String LOGIN_SUCCESS = "Success";
|
||||
|
||||
/**
|
||||
* 注销
|
||||
*/
|
||||
public static final String LOGOUT = "Logout";
|
||||
|
||||
/**
|
||||
* 注册
|
||||
*/
|
||||
public static final String REGISTER = "Register";
|
||||
|
||||
/**
|
||||
* 登录失败
|
||||
*/
|
||||
public static final String LOGIN_FAIL = "Error";
|
||||
|
||||
/**
|
||||
* 当前记录起始索引
|
||||
*/
|
||||
public static final String PAGE_NUM = "pageNum";
|
||||
|
||||
/**
|
||||
* 每页显示记录数
|
||||
*/
|
||||
public static final String PAGE_SIZE = "pageSize";
|
||||
|
||||
/**
|
||||
* 排序列
|
||||
*/
|
||||
public static final String ORDER_BY_COLUMN = "orderByColumn";
|
||||
|
||||
/**
|
||||
* 排序的方向 "desc" 或者 "asc".
|
||||
*/
|
||||
public static final String IS_ASC = "isAsc";
|
||||
|
||||
/**
|
||||
* 验证码有效期(分钟)
|
||||
*/
|
||||
public static final long CAPTCHA_EXPIRATION = 2;
|
||||
|
||||
/**
|
||||
* 资源映射路径 前缀
|
||||
*/
|
||||
public static final String RESOURCE_PREFIX = "/profile";
|
||||
|
||||
/**
|
||||
* 自动识别json对象白名单配置(仅允许解析的包名,范围越小越安全)
|
||||
*/
|
||||
public static final String[] JSON_WHITELIST_STR = {"org.springframework", "com.muyu"};
|
||||
|
||||
/**
|
||||
* 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
|
||||
*/
|
||||
public static final String[] JOB_WHITELIST_STR = {"com.muyu"};
|
||||
|
||||
/**
|
||||
* 定时任务违规的字符
|
||||
*/
|
||||
public static final String[] JOB_ERROR_STR = {"java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
|
||||
"org.springframework", "org.apache", "com.muyu.common.core.utils.file"};
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
package com.muyu.utils;
|
||||
|
||||
|
||||
/**
|
||||
* ID生成器工具类
|
||||
*
|
||||
* @author muyu
|
||||
*/
|
||||
public class IdUtils {
|
||||
/**
|
||||
* 获取随机UUID
|
||||
*
|
||||
* @return 随机UUID
|
||||
*/
|
||||
public static String randomUUID () {
|
||||
return UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 简化的UUID,去掉了横线
|
||||
*
|
||||
* @return 简化的UUID,去掉了横线
|
||||
*/
|
||||
public static String simpleUUID () {
|
||||
return UUID.randomUUID().toString(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取随机UUID,使用性能更好的ThreadLocalRandom生成UUID
|
||||
*
|
||||
* @return 随机UUID
|
||||
*/
|
||||
public static String fastUUID () {
|
||||
return UUID.fastUUID().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 简化的UUID,去掉了横线,使用性能更好的ThreadLocalRandom生成UUID
|
||||
*
|
||||
* @return 简化的UUID,去掉了横线
|
||||
*/
|
||||
public static String fastSimpleUUID () {
|
||||
return UUID.fastUUID().toString(true);
|
||||
}
|
||||
}
|
|
@ -1,165 +0,0 @@
|
|||
package com.muyu.utils;
|
||||
|
||||
import com.muyu.system.constants.SecurityConstants;
|
||||
import com.muyu.system.constants.TokenConstants;
|
||||
import com.muyu.web.utils.Convert;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import io.jsonwebtoken.security.SecureDigestAlgorithm;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Jwt工具类
|
||||
*
|
||||
* @author muyu
|
||||
*/
|
||||
public class JwtUtils {
|
||||
|
||||
/**
|
||||
* 加密算法
|
||||
*/
|
||||
private final static SecureDigestAlgorithm<SecretKey, SecretKey> ALGORITHM = Jwts.SIG.HS256;
|
||||
/**
|
||||
* 私钥 / 生成签名的时候使用的秘钥secret,一般可以从本地配置文件中读取,切记这个秘钥不能外露,只在服务端使用,在任何场景都不应该流露出去。
|
||||
* 一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。
|
||||
* 应该大于等于 256位(长度32及以上的字符串),并且是随机的字符串
|
||||
*/
|
||||
private final static String secret = TokenConstants.SECRET;
|
||||
/**
|
||||
* 秘钥实例
|
||||
*/
|
||||
public static final SecretKey KEY = Keys.hmacShaKeyFor(secret.getBytes());
|
||||
/**
|
||||
* jwt签发者
|
||||
*/
|
||||
private final static String JWT_ISS = "MUYU";
|
||||
/**
|
||||
* jwt主题
|
||||
*/
|
||||
private final static String SUBJECT = "Peripherals";
|
||||
|
||||
|
||||
/**
|
||||
* 从数据声明生成令牌
|
||||
*
|
||||
* @param claims 数据声明
|
||||
*
|
||||
* @return 令牌
|
||||
*/
|
||||
public static String createToken (Map<String, Object> claims) {
|
||||
return Jwts.builder()
|
||||
// 设置头部信息header
|
||||
.header().add("typ", "JWT").add("alg", "HS256").and()
|
||||
// 设置自定义负载信息payload
|
||||
.claims(claims)
|
||||
// 签发时间
|
||||
.issuedAt(new Date())
|
||||
// 主题
|
||||
.subject(SUBJECT)
|
||||
// 签发者
|
||||
.issuer(JWT_ISS)
|
||||
// 签名
|
||||
.signWith(KEY, ALGORITHM)
|
||||
.compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从令牌中获取数据声明
|
||||
*
|
||||
* @param token 令牌
|
||||
*
|
||||
* @return 数据声明
|
||||
*/
|
||||
public static Claims parseToken (String token) {
|
||||
return Jwts.parser()
|
||||
.verifyWith(KEY)
|
||||
.build()
|
||||
.parseSignedClaims(token)
|
||||
.getPayload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据令牌获取用户标识
|
||||
*
|
||||
* @param token 令牌
|
||||
*
|
||||
* @return 用户ID
|
||||
*/
|
||||
public static String getUserKey (String token) {
|
||||
Claims claims = parseToken(token);
|
||||
return getValue(claims, SecurityConstants.USER_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据令牌获取用户标识
|
||||
*
|
||||
* @param claims 身份信息
|
||||
*
|
||||
* @return 用户ID
|
||||
*/
|
||||
public static String getUserKey (Claims claims) {
|
||||
return getValue(claims, SecurityConstants.USER_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据令牌获取用户ID
|
||||
*
|
||||
* @param token 令牌
|
||||
*
|
||||
* @return 用户ID
|
||||
*/
|
||||
public static String getUserId (String token) {
|
||||
Claims claims = parseToken(token);
|
||||
return getValue(claims, SecurityConstants.DETAILS_USER_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据身份信息获取用户ID
|
||||
*
|
||||
* @param claims 身份信息
|
||||
*
|
||||
* @return 用户ID
|
||||
*/
|
||||
public static String getUserId (Claims claims) {
|
||||
return getValue(claims, SecurityConstants.DETAILS_USER_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据令牌获取用户名
|
||||
*
|
||||
* @param token 令牌
|
||||
*
|
||||
* @return 用户名
|
||||
*/
|
||||
public static String getUserName (String token) {
|
||||
Claims claims = parseToken(token);
|
||||
return getValue(claims, SecurityConstants.DETAILS_USERNAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据身份信息获取用户名
|
||||
*
|
||||
* @param claims 身份信息
|
||||
*
|
||||
* @return 用户名
|
||||
*/
|
||||
public static String getUserName (Claims claims) {
|
||||
return getValue(claims, SecurityConstants.DETAILS_USERNAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据身份信息获取键值
|
||||
*
|
||||
* @param claims 身份信息
|
||||
* @param key 键
|
||||
*
|
||||
* @return 值
|
||||
*/
|
||||
public static String getValue (Claims claims, String key) {
|
||||
return Convert.toStr(claims.get(key), "");
|
||||
}
|
||||
}
|
|
@ -1,503 +0,0 @@
|
|||
package com.muyu.utils;
|
||||
|
||||
import com.muyu.utils.text.StrFormatter;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 字符串工具类
|
||||
*
|
||||
* @author muyu
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为空,并且不是空白字符
|
||||
*
|
||||
* @param str 要判断的value
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
public static boolean hasText (String str) {
|
||||
return (str != null && !str.isEmpty() && containsText(str));
|
||||
}
|
||||
|
||||
private static boolean containsText (CharSequence str) {
|
||||
int strLen = str.length();
|
||||
for (int i = 0 ; i < strLen ; i++) {
|
||||
if (!Character.isWhitespace(str.charAt(i))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化文本, {} 表示占位符<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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断给定的collection列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value
|
||||
*
|
||||
* @param collection 给定的集合
|
||||
* @param array 给定的数组
|
||||
*
|
||||
* @return boolean 结果
|
||||
*/
|
||||
public static boolean containsAny (Collection<String> collection, String... array) {
|
||||
if (isEmpty(collection) || isEmpty(array)) {
|
||||
return false;
|
||||
} else {
|
||||
for (String str : array) {
|
||||
if (collection.contains(str)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 驼峰转下划线命名
|
||||
*/
|
||||
public static String toUnderScoreCase (String str) {
|
||||
if (str == null) {
|
||||
return null;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
// 前置字符是否大写
|
||||
boolean preCharIsUpperCase = true;
|
||||
// 当前字符是否大写
|
||||
boolean curreCharIsUpperCase = true;
|
||||
// 下一字符是否大写
|
||||
boolean nexteCharIsUpperCase = true;
|
||||
for (int i = 0 ; i < str.length() ; i++) {
|
||||
char c = str.charAt(i);
|
||||
if (i > 0) {
|
||||
preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
|
||||
} else {
|
||||
preCharIsUpperCase = false;
|
||||
}
|
||||
|
||||
curreCharIsUpperCase = Character.isUpperCase(c);
|
||||
|
||||
if (i < (str.length() - 1)) {
|
||||
nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
|
||||
}
|
||||
|
||||
if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) {
|
||||
sb.append(SEPARATOR);
|
||||
} else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) {
|
||||
sb.append(SEPARATOR);
|
||||
}
|
||||
sb.append(Character.toLowerCase(c));
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否包含字符串
|
||||
*
|
||||
* @param str 验证字符串
|
||||
* @param strs 字符串组
|
||||
*
|
||||
* @return 包含返回true
|
||||
*/
|
||||
public static boolean inStringIgnoreCase (String str, String... strs) {
|
||||
if (str != null && strs != null) {
|
||||
for (String s : strs) {
|
||||
if (str.equalsIgnoreCase(trim(s))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld
|
||||
*
|
||||
* @param name 转换前的下划线大写方式命名的字符串
|
||||
*
|
||||
* @return 转换后的驼峰式命名的字符串
|
||||
*/
|
||||
public static String convertToCamelCase (String name) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
// 快速检查
|
||||
if (name == null || name.isEmpty()) {
|
||||
// 没必要转换
|
||||
return "";
|
||||
} else if (!name.contains("_")) {
|
||||
// 不含下划线,仅将首字母大写
|
||||
return name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||
}
|
||||
// 用下划线将原始字符串分割
|
||||
String[] camels = name.split("_");
|
||||
for (String camel : camels) {
|
||||
// 跳过原始字符串中开头、结尾的下换线或双重下划线
|
||||
if (camel.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
// 首字母大写
|
||||
result.append(camel.substring(0, 1).toUpperCase());
|
||||
result.append(camel.substring(1).toLowerCase());
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 驼峰式命名法
|
||||
* 例如:user_name->userName
|
||||
*/
|
||||
public static String toCamelCase (String s) {
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
if (s.indexOf(SEPARATOR) == -1) {
|
||||
return s;
|
||||
}
|
||||
s = s.toLowerCase();
|
||||
StringBuilder sb = new StringBuilder(s.length());
|
||||
boolean upperCase = false;
|
||||
for (int i = 0 ; i < s.length() ; i++) {
|
||||
char c = s.charAt(i);
|
||||
|
||||
if (c == SEPARATOR) {
|
||||
upperCase = true;
|
||||
} else if (upperCase) {
|
||||
sb.append(Character.toUpperCase(c));
|
||||
upperCase = false;
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
|
||||
*
|
||||
* @param str 指定字符串
|
||||
* @param strs 需要检查的字符串数组
|
||||
*
|
||||
* @return 是否匹配
|
||||
*/
|
||||
public static boolean matches (String str, List<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();
|
||||
}
|
||||
}
|
|
@ -1,468 +0,0 @@
|
|||
package com.muyu.utils;
|
||||
|
||||
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* 提供通用唯一识别码(universally unique identifier)(UUID)实现
|
||||
*
|
||||
* @author muyu
|
||||
*/
|
||||
public final class UUID implements java.io.Serializable, Comparable<UUID> {
|
||||
@Serial
|
||||
private static final long serialVersionUID = -1185015143654744140L;
|
||||
/**
|
||||
* 此UUID的最高64有效位
|
||||
*/
|
||||
private final long mostSigBits;
|
||||
/**
|
||||
* 此UUID的最低64有效位
|
||||
*/
|
||||
private final long leastSigBits;
|
||||
|
||||
/**
|
||||
* 私有构造
|
||||
*
|
||||
* @param data 数据
|
||||
*/
|
||||
private UUID (@NotNull byte[] data) {
|
||||
long msb = 0;
|
||||
long lsb = 0;
|
||||
assert data.length == 16 : "data must be 16 bytes in length";
|
||||
for (int i = 0 ; i < 8 ; i++) {
|
||||
msb = (msb << 8) | (data[i] & 0xff);
|
||||
}
|
||||
for (int i = 8 ; i < 16 ; i++) {
|
||||
lsb = (lsb << 8) | (data[i] & 0xff);
|
||||
}
|
||||
this.mostSigBits = msb;
|
||||
this.leastSigBits = lsb;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用指定的数据构造新的 UUID。
|
||||
*
|
||||
* @param mostSigBits 用于 {@code UUID} 的最高有效 64 位
|
||||
* @param leastSigBits 用于 {@code UUID} 的最低有效 64 位
|
||||
*/
|
||||
public UUID (long mostSigBits, long leastSigBits) {
|
||||
this.mostSigBits = mostSigBits;
|
||||
this.leastSigBits = leastSigBits;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取类型 4(伪随机生成的)UUID 的静态工厂。
|
||||
*
|
||||
* @return 随机生成的 {@code UUID}
|
||||
*/
|
||||
@NotNull
|
||||
@Contract(" -> new")
|
||||
public static UUID fastUUID () {
|
||||
return randomUUID(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。
|
||||
*
|
||||
* @return 随机生成的 {@code UUID}
|
||||
*/
|
||||
@NotNull
|
||||
@Contract(" -> new")
|
||||
public static UUID randomUUID () {
|
||||
return randomUUID(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。
|
||||
*
|
||||
* @param isSecure 是否使用{@link SecureRandom}如果是可以获得更安全的随机码,否则可以得到更好的性能
|
||||
*
|
||||
* @return 随机生成的 {@code UUID}
|
||||
*/
|
||||
@NotNull
|
||||
@Contract("_ -> new")
|
||||
public static UUID randomUUID (boolean isSecure) {
|
||||
final Random ng = isSecure ? Holder.numberGenerator : getRandom();
|
||||
|
||||
byte[] randomBytes = new byte[16];
|
||||
ng.nextBytes(randomBytes);
|
||||
randomBytes[6] &= 0x0f; /* clear version */
|
||||
randomBytes[6] |= 0x40; /* set to version 4 */
|
||||
randomBytes[8] &= 0x3f; /* clear variant */
|
||||
randomBytes[8] |= (byte) 0x80; /* set to IETF variant */
|
||||
return new UUID(randomBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据指定的字节数组获取类型 3(基于名称的)UUID 的静态工厂。
|
||||
*
|
||||
* @param name 用于构造 UUID 的字节数组。
|
||||
*
|
||||
* @return 根据指定数组生成的 {@code UUID}
|
||||
*/
|
||||
@NotNull
|
||||
@Contract("_ -> new")
|
||||
public static UUID nameUUIDFromBytes (byte[] name) {
|
||||
MessageDigest md;
|
||||
try {
|
||||
md = MessageDigest.getInstance("MD5");
|
||||
} catch (NoSuchAlgorithmException nae) {
|
||||
throw new InternalError("MD5 not supported");
|
||||
}
|
||||
byte[] md5Bytes = md.digest(name);
|
||||
md5Bytes[6] &= 0x0f; /* clear version */
|
||||
md5Bytes[6] |= 0x30; /* set to version 3 */
|
||||
md5Bytes[8] &= 0x3f; /* clear variant */
|
||||
md5Bytes[8] |= (byte) 0x80; /* set to IETF variant */
|
||||
return new UUID(md5Bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 {@link #toString()} 方法中描述的字符串标准表示形式创建{@code UUID}。
|
||||
*
|
||||
* @param name 指定 {@code UUID} 字符串
|
||||
*
|
||||
* @return 具有指定值的 {@code UUID}
|
||||
*
|
||||
* @throws IllegalArgumentException 如果 name 与 {@link #toString} 中描述的字符串表示形式不符抛出此异常
|
||||
*/
|
||||
@NotNull
|
||||
@Contract("_ -> new")
|
||||
public static UUID fromString (String name) {
|
||||
String[] components = name.split("-");
|
||||
if (components.length != 5) {
|
||||
throw new IllegalArgumentException("Invalid UUID string: " + name);
|
||||
}
|
||||
for (int i = 0 ; i < 5 ; i++) {
|
||||
components[i] = "0x" + components[i];
|
||||
}
|
||||
|
||||
long mostSigBits = Long.decode(components[0]);
|
||||
mostSigBits <<= 16;
|
||||
mostSigBits |= Long.decode(components[1]);
|
||||
mostSigBits <<= 16;
|
||||
mostSigBits |= Long.decode(components[2]);
|
||||
|
||||
long leastSigBits = Long.decode(components[3]);
|
||||
leastSigBits <<= 48;
|
||||
leastSigBits |= Long.decode(components[4]);
|
||||
|
||||
return new UUID(mostSigBits, leastSigBits);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回指定数字对应的hex值
|
||||
*
|
||||
* @param val 值
|
||||
* @param digits 位
|
||||
*
|
||||
* @return 值
|
||||
*/
|
||||
@NotNull
|
||||
private static String digits (long val, int digits) {
|
||||
long hi = 1L << (digits * 4);
|
||||
return Long.toHexString(hi | (val & (hi - 1))).substring(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取{@link SecureRandom},类提供加密的强随机数生成器 (RNG)
|
||||
*
|
||||
* @return {@link SecureRandom}
|
||||
*/
|
||||
@NotNull
|
||||
public static SecureRandom getSecureRandom () {
|
||||
try {
|
||||
return SecureRandom.getInstance("SHA1PRNG");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取随机数生成器对象<br>
|
||||
* ThreadLocalRandom是JDK 7之后提供并发产生随机数,能够解决多个线程发生的竞争争夺。
|
||||
*
|
||||
* @return {@link ThreadLocalRandom}
|
||||
*/
|
||||
public static ThreadLocalRandom getRandom () {
|
||||
return ThreadLocalRandom.current();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回此 UUID 的 128 位值中的最低有效 64 位。
|
||||
*
|
||||
* @return 此 UUID 的 128 位值中的最低有效 64 位。
|
||||
*/
|
||||
public long getLeastSignificantBits () {
|
||||
return leastSigBits;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回此 UUID 的 128 位值中的最高有效 64 位。
|
||||
*
|
||||
* @return 此 UUID 的 128 位值中最高有效 64 位。
|
||||
*/
|
||||
public long getMostSignificantBits () {
|
||||
return mostSigBits;
|
||||
}
|
||||
|
||||
/**
|
||||
* 与此 {@code UUID} 相关联的版本号. 版本号描述此 {@code UUID} 是如何生成的。
|
||||
* <p>
|
||||
* 版本号具有以下含意:
|
||||
* <ul>
|
||||
* <li>1 基于时间的 UUID
|
||||
* <li>2 DCE 安全 UUID
|
||||
* <li>3 基于名称的 UUID
|
||||
* <li>4 随机生成的 UUID
|
||||
* </ul>
|
||||
*
|
||||
* @return 此 {@code UUID} 的版本号
|
||||
*/
|
||||
public int version () {
|
||||
// Version is bits masked by 0x000000000000F000 in MS long
|
||||
return (int) ((mostSigBits >> 12) & 0x0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* 与此 {@code UUID} 相关联的变体号。变体号描述 {@code UUID} 的布局。
|
||||
* <p>
|
||||
* 变体号具有以下含意:
|
||||
* <ul>
|
||||
* <li>0 为 NCS 向后兼容保留
|
||||
* <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF RFC 4122</a>(Leach-Salz), 用于此类
|
||||
* <li>6 保留,微软向后兼容
|
||||
* <li>7 保留供以后定义使用
|
||||
* </ul>
|
||||
*
|
||||
* @return 此 {@code UUID} 相关联的变体号
|
||||
*/
|
||||
public int variant () {
|
||||
// This field is composed of a varying number of bits.
|
||||
// 0 - - Reserved for NCS backward compatibility
|
||||
// 1 0 - The IETF aka Leach-Salz variant (used by this class)
|
||||
// 1 1 0 Reserved, Microsoft backward compatibility
|
||||
// 1 1 1 Reserved for future definition.
|
||||
return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63));
|
||||
}
|
||||
|
||||
/**
|
||||
* 与此 UUID 相关联的时间戳值。
|
||||
*
|
||||
* <p>
|
||||
* 60 位的时间戳值根据此 {@code UUID} 的 time_low、time_mid 和 time_hi 字段构造。<br>
|
||||
* 所得到的时间戳以 100 毫微秒为单位,从 UTC(通用协调时间) 1582 年 10 月 15 日零时开始。
|
||||
*
|
||||
* <p>
|
||||
* 时间戳值仅在在基于时间的 UUID(其 version 类型为 1)中才有意义。<br>
|
||||
* 如果此 {@code UUID} 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。
|
||||
*
|
||||
* @throws UnsupportedOperationException 如果此 {@code UUID} 不是 version 为 1 的 UUID。
|
||||
*/
|
||||
public long timestamp () throws UnsupportedOperationException {
|
||||
checkTimeBase();
|
||||
return (mostSigBits & 0x0FFFL) << 48//
|
||||
| ((mostSigBits >> 16) & 0x0FFFFL) << 32//
|
||||
| mostSigBits >>> 32;
|
||||
}
|
||||
|
||||
/**
|
||||
* 与此 UUID 相关联的时钟序列值。
|
||||
*
|
||||
* <p>
|
||||
* 14 位的时钟序列值根据此 UUID 的 clock_seq 字段构造。clock_seq 字段用于保证在基于时间的 UUID 中的时间唯一性。
|
||||
* <p>
|
||||
* {@code clockSequence} 值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。 如果此 UUID 不是基于时间的 UUID,则此方法抛出
|
||||
* UnsupportedOperationException。
|
||||
*
|
||||
* @return 此 {@code UUID} 的时钟序列
|
||||
*
|
||||
* @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1
|
||||
*/
|
||||
public int clockSequence () throws UnsupportedOperationException {
|
||||
checkTimeBase();
|
||||
return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
|
||||
}
|
||||
|
||||
/**
|
||||
* 与此 UUID 相关的节点值。
|
||||
*
|
||||
* <p>
|
||||
* 48 位的节点值根据此 UUID 的 node 字段构造。此字段旨在用于保存机器的 IEEE 802 地址,该地址用于生成此 UUID 以保证空间唯一性。
|
||||
* <p>
|
||||
* 节点值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。<br>
|
||||
* 如果此 UUID 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。
|
||||
*
|
||||
* @return 此 {@code UUID} 的节点值
|
||||
*
|
||||
* @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1
|
||||
*/
|
||||
public long node () throws UnsupportedOperationException {
|
||||
checkTimeBase();
|
||||
return leastSigBits & 0x0000FFFFFFFFFFFFL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回此{@code UUID} 的字符串表现形式。
|
||||
*
|
||||
* <p>
|
||||
* UUID 的字符串表示形式由此 BNF 描述:
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
|
||||
* time_low = 4*<hexOctet>
|
||||
* time_mid = 2*<hexOctet>
|
||||
* time_high_and_version = 2*<hexOctet>
|
||||
* variant_and_sequence = 2*<hexOctet>
|
||||
* node = 6*<hexOctet>
|
||||
* hexOctet = <hexDigit><hexDigit>
|
||||
* hexDigit = [0-9a-fA-F]
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* </blockquote>
|
||||
*
|
||||
* @return 此{@code UUID} 的字符串表现形式
|
||||
*
|
||||
* @see #toString(boolean)
|
||||
*/
|
||||
@NotNull
|
||||
@Override
|
||||
public String toString () {
|
||||
return toString(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回此{@code UUID} 的字符串表现形式。
|
||||
*
|
||||
* <p>
|
||||
* UUID 的字符串表示形式由此 BNF 描述:
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
|
||||
* time_low = 4*<hexOctet>
|
||||
* time_mid = 2*<hexOctet>
|
||||
* time_high_and_version = 2*<hexOctet>
|
||||
* variant_and_sequence = 2*<hexOctet>
|
||||
* node = 6*<hexOctet>
|
||||
* hexOctet = <hexDigit><hexDigit>
|
||||
* hexDigit = [0-9a-fA-F]
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* </blockquote>
|
||||
*
|
||||
* @param isSimple 是否简单模式,简单模式为不带'-'的UUID字符串
|
||||
*
|
||||
* @return 此{@code UUID} 的字符串表现形式
|
||||
*/
|
||||
@NotNull
|
||||
public String toString (boolean isSimple) {
|
||||
final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);
|
||||
// time_low
|
||||
builder.append(digits(mostSigBits >> 32, 8));
|
||||
if (!isSimple) {
|
||||
builder.append('-');
|
||||
}
|
||||
// time_mid
|
||||
builder.append(digits(mostSigBits >> 16, 4));
|
||||
if (!isSimple) {
|
||||
builder.append('-');
|
||||
}
|
||||
// time_high_and_version
|
||||
builder.append(digits(mostSigBits, 4));
|
||||
if (!isSimple) {
|
||||
builder.append('-');
|
||||
}
|
||||
// variant_and_sequence
|
||||
builder.append(digits(leastSigBits >> 48, 4));
|
||||
if (!isSimple) {
|
||||
builder.append('-');
|
||||
}
|
||||
// node
|
||||
builder.append(digits(leastSigBits, 12));
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
// Comparison Operations
|
||||
|
||||
/**
|
||||
* 返回此 UUID 的哈希码。
|
||||
*
|
||||
* @return UUID 的哈希码值。
|
||||
*/
|
||||
@Override
|
||||
public int hashCode () {
|
||||
long hilo = mostSigBits ^ leastSigBits;
|
||||
return ((int) (hilo >> 32)) ^ (int) hilo;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------
|
||||
// Private method start
|
||||
|
||||
/**
|
||||
* 将此对象与指定对象比较。
|
||||
* <p>
|
||||
* 当且仅当参数不为 {@code null}、而是一个 UUID 对象、具有与此 UUID 相同的 varriant、包含相同的值(每一位均相同)时,结果才为 {@code true}。
|
||||
*
|
||||
* @param obj 要与之比较的对象
|
||||
*
|
||||
* @return 如果对象相同,则返回 {@code true};否则返回 {@code false}
|
||||
*/
|
||||
@Override
|
||||
public boolean equals (Object obj) {
|
||||
if ((null == obj) || (obj.getClass() != UUID.class)) {
|
||||
return false;
|
||||
}
|
||||
UUID id = (UUID) obj;
|
||||
return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将此 UUID 与指定的 UUID 比较。
|
||||
*
|
||||
* <p>
|
||||
* 如果两个 UUID 不同,且第一个 UUID 的最高有效字段大于第二个 UUID 的对应字段,则第一个 UUID 大于第二个 UUID。
|
||||
*
|
||||
* @param val 与此 UUID 比较的 UUID
|
||||
*
|
||||
* @return 在此 UUID 小于、等于或大于 val 时,分别返回 -1、0 或 1。
|
||||
*/
|
||||
@Override
|
||||
public int compareTo (UUID val) {
|
||||
// The ordering is intentionally set up so that the UUIDs
|
||||
// can simply be numerically compared as two numbers
|
||||
//
|
||||
//
|
||||
return (this.mostSigBits < val.mostSigBits ? -1 : //
|
||||
(this.mostSigBits > val.mostSigBits ? 1 : //
|
||||
(Long.compare(this.leastSigBits, val.leastSigBits))));
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否为time-based版本UUID
|
||||
*/
|
||||
private void checkTimeBase () {
|
||||
if (version() != 1) {
|
||||
throw new UnsupportedOperationException("Not a time-based UUID");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SecureRandom 的单例
|
||||
*/
|
||||
private static class Holder {
|
||||
static final SecureRandom numberGenerator = getSecureRandom();
|
||||
}
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
package com.muyu.utils.text;
|
||||
|
||||
|
||||
import com.muyu.utils.StringUtils;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* 字符集工具类
|
||||
*
|
||||
* @author muyu
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -1,904 +0,0 @@
|
|||
package com.muyu.utils.text;
|
||||
|
||||
|
||||
import com.muyu.utils.StringUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.math.RoundingMode;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 类型转换器
|
||||
*
|
||||
* @author muyu
|
||||
*/
|
||||
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 str 被转换的值
|
||||
*
|
||||
* @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 str 被转换的值
|
||||
*
|
||||
* @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":
|
||||
case "yes":
|
||||
case "ok":
|
||||
case "1":
|
||||
return true;
|
||||
case "false":
|
||||
case "no":
|
||||
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 BigDecimal.valueOf((Double) value);
|
||||
}
|
||||
if (value instanceof Integer) {
|
||||
return new BigDecimal((Integer) value);
|
||||
}
|
||||
final String valueStr = toStr(value, null);
|
||||
if (StringUtils.isEmpty(valueStr)) {
|
||||
return defaultValue;
|
||||
}
|
||||
try {
|
||||
return new BigDecimal(valueStr);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为BigDecimal<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[] || obj instanceof Byte[]) {
|
||||
if (obj instanceof byte[]) {
|
||||
return str((byte[]) obj, charset);
|
||||
} else {
|
||||
Byte[] bytes = (Byte[]) obj;
|
||||
int length = bytes.length;
|
||||
byte[] dest = new byte[length];
|
||||
for (int i = 0 ; i < length ; i++) {
|
||||
dest[i] = bytes[i];
|
||||
}
|
||||
return str(dest, 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);
|
||||
}
|
||||
}
|
||||
return new String(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* 数字金额大写转换 先写个完整的然后将如零拾替换成零
|
||||
*
|
||||
* @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++) {
|
||||
// 优化double计算精度丢失问题
|
||||
BigDecimal nNum = new BigDecimal(n);
|
||||
BigDecimal decimal = new BigDecimal(10);
|
||||
BigDecimal scale = nNum.multiply(decimal).setScale(2, RoundingMode.HALF_EVEN);
|
||||
double d = scale.doubleValue();
|
||||
s += (digit[(int) (Math.floor(d * 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("^整$", "零元整");
|
||||
}
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
package com.muyu.utils.text;
|
||||
|
||||
|
||||
import com.muyu.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* 字符串格式化
|
||||
*
|
||||
* @author muyu
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -1,20 +1,16 @@
|
|||
package com.muyu.vehicle;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.muyu.cache.model.MessageTemplateCacheModel;
|
||||
import com.muyu.system.enums.MessageTemplateValueType;
|
||||
import com.muyu.utils.StringUtils;
|
||||
import com.muyu.vehicle.model.VehicleData;
|
||||
import com.muyu.vehicle.model.properties.MqttProperties;
|
||||
import com.muyu.vehicle.thread.VehicleThread;
|
||||
import com.muyu.web.common.SystemConstant;
|
||||
import com.muyu.web.common.pool.ScheduledThreadPool;
|
||||
import com.muyu.web.domain.MessageTemplateValue;
|
||||
import com.muyu.web.domain.VehicleInfo;
|
||||
import com.muyu.web.domain.Vehicle;
|
||||
import com.muyu.web.domain.model.PositionModel;
|
||||
import com.muyu.web.utils.CalculateCheckDigit;
|
||||
import com.muyu.web.utils.ConversionUtil;
|
||||
import com.muyu.web.utils.VehicleUtils;
|
||||
import com.muyu.vehicle.model.VehicleData;
|
||||
import com.muyu.vehicle.model.properties.MqttProperties;
|
||||
import com.muyu.vehicle.thread.VehicleThread;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
@ -28,7 +24,6 @@ import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
|
|||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
@ -57,19 +52,11 @@ public class VehicleInstance {
|
|||
/**
|
||||
* 路径队列
|
||||
*/
|
||||
@Builder.Default
|
||||
private LinkedBlockingQueue<PositionModel> positionQueue = new LinkedBlockingQueue<>();
|
||||
|
||||
/**
|
||||
* 车辆
|
||||
*/
|
||||
private VehicleInfo vehicleInfo;
|
||||
|
||||
/**
|
||||
* 报文模板
|
||||
*/
|
||||
private MessageTemplateCacheModel messageTemplate;
|
||||
|
||||
private Vehicle vehicle;
|
||||
/**
|
||||
* 实例数据
|
||||
*/
|
||||
|
@ -94,7 +81,7 @@ public class VehicleInstance {
|
|||
/**
|
||||
* 链接上报
|
||||
*/
|
||||
private MqttClient client;
|
||||
private MqttClient client = null;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -108,15 +95,7 @@ public class VehicleInstance {
|
|||
* @return VIN
|
||||
*/
|
||||
public String getVin() {
|
||||
return this.vehicleInfo.getVin();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前车辆所属租户信息
|
||||
* @return 租户ID
|
||||
*/
|
||||
public String getTenantId(){
|
||||
return this.vehicleInfo.getTenantId();
|
||||
return this.vehicle.getVin();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -160,12 +139,6 @@ public class VehicleInstance {
|
|||
client.connect(options);
|
||||
log.debug("车辆:[{}] 客户端初始化成功连接配置:{}", getVin(),
|
||||
JSONObject.toJSONString(this.mqttProperties));
|
||||
VehicleThread vehicleThread = new VehicleThread();
|
||||
vehicleThread.setVehicleInstance(this);
|
||||
this.setVehicleThread(vehicleThread);
|
||||
ScheduledFuture<?> scheduledFuture = ScheduledThreadPool.submit(vehicleThread);
|
||||
this.setScheduledFuture(scheduledFuture);
|
||||
log.info("初始化车辆上报模拟线程开始:[{}]", this.getVin());
|
||||
} catch (MqttException e) {
|
||||
log.error("车辆:[{}] 客户端初始化异常", getVin(), e);
|
||||
throw new RuntimeException(e);
|
||||
|
@ -206,9 +179,6 @@ public class VehicleInstance {
|
|||
log.error("车辆:[{}] 客户端关闭异常:[{}]",getVin(), e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
if (this.vehicleThread != null){
|
||||
this.vehicleThread.stop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -221,6 +191,46 @@ public class VehicleInstance {
|
|||
log.info("车辆:{} 设置路径成功", this.getVin());
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化线程
|
||||
*/
|
||||
public void initVehicleThread() {
|
||||
if (this.positionCode == null){
|
||||
throw new RuntimeException("车辆["+getVin()+"]未选中路径");
|
||||
}
|
||||
if (!isOnline()){
|
||||
throw new RuntimeException("车辆["+getVin()+"]未和服务器建立链接");
|
||||
}
|
||||
VehicleThread vehicleThread = new VehicleThread();
|
||||
vehicleThread.setVehicleInstance(this);
|
||||
this.setVehicleThread(vehicleThread);
|
||||
ScheduledFuture<?> scheduledFuture = ScheduledThreadPool.submit(vehicleThread);
|
||||
this.setScheduledFuture(scheduledFuture);
|
||||
log.info("初始化车辆上报模拟线程开始:[{}]", this.getVin());
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始上报线程
|
||||
*/
|
||||
public void startSend() {
|
||||
this.msgCode = "上报";
|
||||
if (this.vehicleThread != null){
|
||||
this.vehicleThread.resume();
|
||||
}
|
||||
log.info("车辆[{}],开始上报", this.getVin());
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂停上报线程
|
||||
*/
|
||||
public void pauseSend() {
|
||||
this.msgCode = "暂停";
|
||||
if (this.vehicleThread != null) {
|
||||
this.vehicleThread.pause();
|
||||
}
|
||||
log.info("车辆[{}],暂停上报", this.getVin());
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束发送
|
||||
*/
|
||||
|
@ -244,48 +254,31 @@ public class VehicleInstance {
|
|||
/**
|
||||
* 模拟车辆数据
|
||||
*/
|
||||
public void imitateData() {
|
||||
public String imitateData() {
|
||||
String gear = this.vehicleData.getGear();
|
||||
if (!"D".equals(gear)){
|
||||
log.info("车辆不是动车档位,不进行模拟数据");
|
||||
return null;
|
||||
}
|
||||
// 获取上一次定位点
|
||||
PositionModel lastPositionModel = this.lastPosition == null ? positionQueue.poll() : this.lastPosition;
|
||||
// 获取当前定位点
|
||||
PositionModel currentPositionModel = positionQueue.poll();
|
||||
if (currentPositionModel == null) {
|
||||
currentPositionModel = PositionModel.builder()
|
||||
.latitude(this.vehicleInfo.getLastLatitude())
|
||||
.longitude(this.vehicleInfo.getLastLongitude())
|
||||
.build();
|
||||
}else {
|
||||
this.vehicleInfo.setLastLatitude(currentPositionModel.getLatitude());
|
||||
this.vehicleInfo.setLastLongitude(currentPositionModel.getLongitude());
|
||||
}
|
||||
if (lastPositionModel == null){
|
||||
lastPositionModel = currentPositionModel;
|
||||
return "表示当前定位点已经跑完,需要其他操作";
|
||||
}
|
||||
// 两点之间的距离
|
||||
BigDecimal distance = null;
|
||||
if (currentPositionModel != null) {
|
||||
distance = VehicleUtils.distance(Objects.requireNonNull(lastPositionModel), currentPositionModel);
|
||||
}
|
||||
if (lastPositionModel == currentPositionModel){
|
||||
distance = new BigDecimal("0.01");
|
||||
}
|
||||
BigDecimal distance = VehicleUtils.distance(lastPositionModel, currentPositionModel);
|
||||
// 车辆总里程 相加
|
||||
vehicleData.setMileage(vehicleData.getMileage().add(distance));
|
||||
// 定位点填写
|
||||
vehicleData.setLongitude(
|
||||
currentPositionModel == null || currentPositionModel.getLongitude() == null ? this.vehicleInfo.getLastLongitude() : currentPositionModel.getLongitude()
|
||||
);
|
||||
vehicleData.setLatitude(
|
||||
currentPositionModel == null || currentPositionModel.getLatitude() == null ? this.vehicleInfo.getLastLatitude() : currentPositionModel.getLatitude()
|
||||
);
|
||||
vehicleData.setLongitude(currentPositionModel.getLongitude());
|
||||
vehicleData.setLatitude(currentPositionModel.getLatitude());
|
||||
// 当前电量减少
|
||||
// 电池浮动
|
||||
BigDecimal batteryFloat = VehicleUtils.batteryFloat();
|
||||
// 百公里占比
|
||||
BigDecimal hundredKMScale = null;
|
||||
if (distance != null) {
|
||||
hundredKMScale = distance.divide(SystemConstant.hundredKilometers).setScale(3, RoundingMode.HALF_UP);
|
||||
}
|
||||
BigDecimal hundredKMScale = distance.divide(SystemConstant.hundredKilometers).setScale(3, RoundingMode.HALF_UP);
|
||||
// 使用电量
|
||||
BigDecimal powerUsage = powerConsumption.multiply(hundredKMScale)
|
||||
.multiply(batteryFloat)
|
||||
|
@ -297,43 +290,15 @@ public class VehicleInstance {
|
|||
powerConsumption.multiply(batteryFloat).divide(new BigDecimal(1000)).setScale(2, RoundingMode.HALF_UP).toString()
|
||||
);
|
||||
// 计算总速度
|
||||
if (distance != null) {
|
||||
vehicleData.setSpeed(
|
||||
distance.divide(new BigDecimal(2))
|
||||
.multiply(new BigDecimal("3600"))
|
||||
.setScale(2, RoundingMode.HALF_UP).toString()
|
||||
);
|
||||
}
|
||||
List<MessageTemplateValue> messageTemplateValueList
|
||||
= this.messageTemplate.getMessageTemplateValueList();
|
||||
if (messageTemplateValueList != null){
|
||||
for (MessageTemplateValue messageTemplateValue : messageTemplateValueList) {
|
||||
String valueType = messageTemplateValue.getValueType();
|
||||
MessageTemplateValueType messageTemplateValueType
|
||||
= MessageTemplateValueType.get(valueType);
|
||||
switch (messageTemplateValueType){
|
||||
// 固定值
|
||||
case FIXED -> {
|
||||
String fixedValue = messageTemplateValue.getFixedValue();
|
||||
String[] split = fixedValue.split(",");
|
||||
vehicleData.putData(messageTemplateValue.getCode(), split[0]);
|
||||
}
|
||||
// 区间值
|
||||
case INTERVAL -> {
|
||||
vehicleData.putData(
|
||||
messageTemplateValue.getCode(),
|
||||
vehicleData.getValue(
|
||||
vehicleData.genValue(
|
||||
messageTemplateValue.getMinValue(),
|
||||
messageTemplateValue.getMaxValue()
|
||||
),
|
||||
messageTemplateValue.getLength()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
vehicleData.setSpeed(
|
||||
distance.divide(new BigDecimal(2))
|
||||
.multiply(new BigDecimal("3600"))
|
||||
.setScale(2, RoundingMode.HALF_UP).toString()
|
||||
);
|
||||
vehicleData.imitateBase();
|
||||
vehicleData.imitateMotor();
|
||||
vehicleData.imitateBatteryPack();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -344,38 +309,4 @@ public class VehicleInstance {
|
|||
this.vehicleData.setGear(gear);
|
||||
}
|
||||
|
||||
public String imitateDataAndMsg () {
|
||||
this.imitateData();
|
||||
List<MessageTemplateValue> messageTemplateValueList
|
||||
= this.messageTemplate.getMessageTemplateValueList();
|
||||
StringBuilder elBuilder = new StringBuilder();
|
||||
messageTemplateValueList.stream()
|
||||
.filter(MessageTemplateValue::isEl)
|
||||
.sorted(Comparator.comparing(MessageTemplateValue::getStartLocation))
|
||||
.forEach(value -> {
|
||||
String elValue = value.getElValue();
|
||||
switch (elValue){
|
||||
case "this.vin" -> elBuilder.append(this.vehicleData.getVin());
|
||||
case "this.latitude" -> elBuilder.append(this.vehicleData.getLatitude());
|
||||
case "this.longitude" -> elBuilder.append(this.vehicleData.getLongitude());
|
||||
case "this.timeMillis" -> elBuilder.append(System.currentTimeMillis());
|
||||
}
|
||||
});
|
||||
StringBuilder fixedBuilder = new StringBuilder();
|
||||
messageTemplateValueList.stream()
|
||||
.filter(MessageTemplateValue::isFixed)
|
||||
.sorted(Comparator.comparing(MessageTemplateValue::getStartLocation))
|
||||
.forEach(value -> fixedBuilder.append(this.vehicleData.getData(value.getCode())));
|
||||
|
||||
StringBuilder intervalBuilder = new StringBuilder();
|
||||
messageTemplateValueList.stream()
|
||||
.filter(MessageTemplateValue::isInterval)
|
||||
.sorted(Comparator.comparing(MessageTemplateValue::getStartLocation))
|
||||
.forEach(value -> intervalBuilder.append(this.vehicleData.getData(value.getCode())));
|
||||
return StringUtils.format(
|
||||
"{}#{}#{}~{}{}{}",
|
||||
elBuilder.length(), fixedBuilder.length(), intervalBuilder.length(),
|
||||
elBuilder.toString(), fixedBuilder.toString(), intervalBuilder.toString()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,10 @@ public interface ClientAdmin {
|
|||
* @return 响应结果
|
||||
*/
|
||||
@Post(
|
||||
url = "{vehicleLoadUrl}",
|
||||
interceptor = SimpleInterceptor.class
|
||||
url = "{vehicleLoadUrl}"/*,
|
||||
headers = {
|
||||
"X-co-il: DH5I9OIG+N=="
|
||||
}*/
|
||||
)
|
||||
public Result<MqttServerModel> getVehicleLoadAddr ( @JSONBody VehicleConnectionReq vehicleConnectionReq);
|
||||
}
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
package com.muyu.vehicle.api;
|
||||
|
||||
import com.dtflys.forest.http.ForestRequest;
|
||||
import com.dtflys.forest.interceptor.Interceptor;
|
||||
import com.muyu.system.constants.TokenConstants;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Log4j2
|
||||
@Component
|
||||
public class SimpleInterceptor<T> implements Interceptor<T> {
|
||||
|
||||
@Autowired
|
||||
private HttpServletRequest request;
|
||||
/**
|
||||
* 该方法在请求发送之前被调用, 若返回false则不会继续发送请求
|
||||
* @Param request Forest请求对象
|
||||
*/
|
||||
@Override
|
||||
public boolean beforeExecute(ForestRequest req) {
|
||||
// 执行在发送请求之前处理的代码
|
||||
req.addHeader(TokenConstants.AUTHENTICATION, request.getHeader(TokenConstants.AUTHENTICATION)); // 添加Header
|
||||
return true; // 继续执行请求返回true
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package com.muyu.vehicle.api.req;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
package com.muyu.vehicle.core;
|
||||
|
||||
import com.muyu.system.handle.SystemHandler;
|
||||
import com.muyu.vehicle.VehicleInstance;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author DongZl
|
||||
|
@ -15,26 +14,10 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
*/
|
||||
public class LocalContainer {
|
||||
|
||||
private static final Map<String, Map<String, VehicleInstance>> tenantVehicleDataMap
|
||||
= new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 通过租户ID获取租户下车辆
|
||||
* @param tenantId 租户ID
|
||||
* @return 车辆内容
|
||||
* 车辆容器
|
||||
*/
|
||||
public static Map<String, VehicleInstance> getVehicleDataMap(String tenantId) {
|
||||
return tenantVehicleDataMap
|
||||
.computeIfAbsent(tenantId, k -> new ConcurrentHashMap<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认获取档期啊租户下车辆
|
||||
* @return 车辆内容
|
||||
*/
|
||||
public static Map<String, VehicleInstance> getTenantVehicleDataMap() {
|
||||
return getVehicleDataMap(SystemHandler.getTenantId());
|
||||
}
|
||||
public static final Map<String, VehicleInstance> vehicleDataMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 添加车辆
|
||||
|
@ -44,8 +27,7 @@ public class LocalContainer {
|
|||
vehicleInstance.forEach(LocalContainer::setVehicleInstance);
|
||||
}
|
||||
public static void setVehicleInstance(VehicleInstance vehicleInstance){
|
||||
String vin = vehicleInstance.getVehicleInfo().getVin();
|
||||
Map<String, VehicleInstance> vehicleDataMap = getVehicleDataMap(vehicleInstance.getTenantId());
|
||||
String vin = vehicleInstance.getVehicle().getVin();
|
||||
if (!vehicleDataMap.containsKey(vin)) {
|
||||
vehicleDataMap.put(vin, vehicleInstance);
|
||||
}
|
||||
|
@ -57,7 +39,6 @@ public class LocalContainer {
|
|||
* @return 车辆实例
|
||||
*/
|
||||
public static VehicleInstance getVehicleInstance(String vin){
|
||||
Map<String, VehicleInstance> vehicleDataMap = getTenantVehicleDataMap();
|
||||
return vehicleDataMap.get(vin);
|
||||
}
|
||||
|
||||
|
@ -66,12 +47,10 @@ public class LocalContainer {
|
|||
* @return
|
||||
*/
|
||||
public static long total () {
|
||||
Map<String, VehicleInstance> vehicleDataMap = getTenantVehicleDataMap();
|
||||
return vehicleDataMap.size();
|
||||
}
|
||||
|
||||
public static Collection<VehicleInstance> getVehicleInstanceAll () {
|
||||
Map<String, VehicleInstance> vehicleDataMap = getTenantVehicleDataMap();
|
||||
return vehicleDataMap.values();
|
||||
}
|
||||
|
||||
|
@ -80,29 +59,15 @@ public class LocalContainer {
|
|||
* 获取在线车辆
|
||||
* @return 在线车辆集合
|
||||
*/
|
||||
public static List<VehicleInstance> getTenantOnlineVehicleInstance (){
|
||||
Map<String, VehicleInstance> vehicleDataMap = getTenantVehicleDataMap();
|
||||
public static List<VehicleInstance> getOnlineVehicleInstance(){
|
||||
return vehicleDataMap.values().stream().filter(VehicleInstance::isOnline).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取在线车辆
|
||||
* @return 在线车辆集合
|
||||
*/
|
||||
public static List<VehicleInstance> getOnlineVehicleInstance (){
|
||||
return tenantVehicleDataMap.values()
|
||||
.stream()
|
||||
.map(Map::values)
|
||||
.flatMap(Collection::stream)
|
||||
.filter(VehicleInstance::isOnline).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取在线车辆
|
||||
* @return 在线车辆VIN集合
|
||||
*/
|
||||
public static List<String> getOnlineVehicleVin(){
|
||||
return getTenantOnlineVehicleInstance()
|
||||
return getOnlineVehicleInstance()
|
||||
.stream()
|
||||
.map(VehicleInstance::getVin)
|
||||
.toList();
|
||||
|
@ -113,7 +78,6 @@ public class LocalContainer {
|
|||
* @return 离线车辆集合
|
||||
*/
|
||||
public static List<VehicleInstance> getOfflineVehicleInstance(){
|
||||
Map<String, VehicleInstance> vehicleDataMap = getTenantVehicleDataMap();
|
||||
return vehicleDataMap.values().stream().filter(vehicleInstance -> !vehicleInstance.isOnline()).toList();
|
||||
}
|
||||
|
||||
|
@ -122,7 +86,6 @@ public class LocalContainer {
|
|||
* @param vin 车辆VIN
|
||||
*/
|
||||
public static void removeByVin(String vin) {
|
||||
Map<String, VehicleInstance> vehicleDataMap = getTenantVehicleDataMap();
|
||||
vehicleDataMap.remove(vin);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
package com.muyu.vehicle.core;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.muyu.web.common.pool.FixedThreadPool;
|
||||
import com.muyu.web.common.pool.ScheduledThreadPool;
|
||||
import com.muyu.web.domain.Vehicle;
|
||||
import com.muyu.web.service.VehicleInstanceService;
|
||||
import com.muyu.web.service.VehicleService;
|
||||
import com.muyu.vehicle.VehicleInstance;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author DongZeLiang
|
||||
* @version 1.0
|
||||
* @description 配置
|
||||
* @date 2023/11/9
|
||||
*/
|
||||
@Log4j2
|
||||
@Configuration
|
||||
@AllArgsConstructor
|
||||
public class VehicleConfiguration implements ApplicationRunner {
|
||||
|
||||
private final VehicleService vehicleService;
|
||||
|
||||
private final VehicleInstanceService vehicleInstanceService;
|
||||
|
||||
/**
|
||||
* 初始化加载汽车数据到内存当中
|
||||
*/
|
||||
public void vehiclePageInit (){
|
||||
long startTime = System.currentTimeMillis();
|
||||
int page = 0, pageSize = 10;
|
||||
log.info("初始开始,批量从数据库当中加载数据到内存当中,每次[{}]条", pageSize);
|
||||
while (true){
|
||||
Page<Vehicle> vehiclePage = vehicleService.page(new Page<>(page++, pageSize));
|
||||
List<Vehicle> vehicleList = vehiclePage.getRecords();
|
||||
vehicleList.forEach(vehicleInstanceService::init);
|
||||
log.debug("第[{}]页,[{}]条", page, vehicleList.size());
|
||||
if (vehicleList.size() < pageSize){
|
||||
break;
|
||||
}
|
||||
}
|
||||
log.info("数据加载完成,耗时:{} MS", System.currentTimeMillis() - startTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run (ApplicationArguments args) {
|
||||
this.vehiclePageInit();
|
||||
// 提交给线程池 一分钟 执行一次
|
||||
// ThreadPool.submit(new Thread(vehicleService::syncDb), 30);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭程序前操作
|
||||
*/
|
||||
@PreDestroy
|
||||
public void destroy(){
|
||||
|
||||
|
||||
log.info("数据库同步");
|
||||
vehicleService.syncDb();
|
||||
|
||||
log.info("下线所有车辆");
|
||||
List<VehicleInstance> onlineVehicleInstanceList = LocalContainer.getOnlineVehicleInstance();
|
||||
onlineVehicleInstanceList.forEach(VehicleInstance::closeClient);
|
||||
|
||||
log.info("关闭线程池");
|
||||
ScheduledThreadPool.shutdown();
|
||||
FixedThreadPool.shutDown();
|
||||
|
||||
}
|
||||
}
|
|
@ -1,16 +1,15 @@
|
|||
package com.muyu.vehicle.model;
|
||||
|
||||
|
||||
import com.muyu.web.domain.VehicleInfo;
|
||||
import com.muyu.web.domain.Vehicle;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import static com.muyu.web.utils.VehicleUtils.genValue;
|
||||
|
||||
/**
|
||||
* @author 牧鱼
|
||||
|
@ -27,6 +26,10 @@ public class VehicleData {
|
|||
* VIN
|
||||
*/
|
||||
private String vin;
|
||||
/**
|
||||
* 行驶路线
|
||||
*/
|
||||
private String drivingRoute;
|
||||
|
||||
/**
|
||||
* 经度
|
||||
|
@ -48,51 +51,324 @@ public class VehicleData {
|
|||
*/
|
||||
private BigDecimal mileage;
|
||||
|
||||
/**
|
||||
* 总电压
|
||||
*/
|
||||
private String voltage;
|
||||
|
||||
/**
|
||||
* 总电流
|
||||
*/
|
||||
private String current;
|
||||
|
||||
/**
|
||||
* 绝缘电阻
|
||||
*/
|
||||
private String resistance;
|
||||
|
||||
/**
|
||||
* 档位
|
||||
*/
|
||||
@Builder.Default
|
||||
private String gear = "P";
|
||||
|
||||
/**
|
||||
* 电池剩余电量
|
||||
* 加速踏板行程值
|
||||
*/
|
||||
private BigDecimal remainingBattery;
|
||||
private String accelerationPedal;
|
||||
|
||||
/**
|
||||
* 电池电量
|
||||
* 制动踏板行程值
|
||||
*/
|
||||
private BigDecimal batteryLevel;
|
||||
private String brakePedal;
|
||||
|
||||
/**
|
||||
* 燃料消耗率
|
||||
*/
|
||||
private String fuelConsumptionRate;
|
||||
|
||||
@Builder.Default
|
||||
private Map<String, String> dataMap = new HashMap<String, String>();
|
||||
/**
|
||||
* 电机控制器温度
|
||||
*/
|
||||
private String motorControllerTemperature;
|
||||
|
||||
/**
|
||||
* 存放值
|
||||
* @param key
|
||||
* @param value
|
||||
* 电机转速
|
||||
*/
|
||||
public void putData(String key, String value) {
|
||||
dataMap.put(key, value);
|
||||
}
|
||||
private String motorSpeed;
|
||||
|
||||
/**
|
||||
* 获取值
|
||||
* @param key
|
||||
* @return
|
||||
* 电机转矩
|
||||
*/
|
||||
public String getData(String key) {
|
||||
return dataMap.get(key);
|
||||
}
|
||||
private String motorTorque;
|
||||
|
||||
public String genValue(double start, double end) {
|
||||
Random random = new Random();
|
||||
return String.valueOf(random.nextDouble() * (end - start) + start);
|
||||
/**
|
||||
* 电机温度
|
||||
*/
|
||||
private String motorTemperature;
|
||||
|
||||
/**
|
||||
* 电机电压
|
||||
*/
|
||||
private String motorVoltage;
|
||||
|
||||
/**
|
||||
* 电机电流
|
||||
*/
|
||||
private String motorCurrent;
|
||||
|
||||
/**
|
||||
* 动力电池剩余电量SOC
|
||||
*/
|
||||
private BigDecimal remainingBattery;
|
||||
|
||||
/**
|
||||
* 电池总容量
|
||||
*/
|
||||
private BigDecimal batteryLevel;
|
||||
|
||||
/**
|
||||
* 当前状态允许的最大反馈功率
|
||||
*/
|
||||
private String maximumFeedbackPower;
|
||||
|
||||
/**
|
||||
* 当前状态允许最大放电功率
|
||||
*/
|
||||
private String maximumDischargePower;
|
||||
|
||||
/**
|
||||
* BMS自检计数器
|
||||
*/
|
||||
private String selfCheckCounter;
|
||||
|
||||
/**
|
||||
* 动力电池充放电电流
|
||||
*/
|
||||
private String totalBatteryCurrent;
|
||||
|
||||
/**
|
||||
* 动力电池负载端总电压V3
|
||||
*/
|
||||
private String totalBatteryVoltage;
|
||||
|
||||
/**
|
||||
* 单次最大电压
|
||||
*/
|
||||
private String singleBatteryMaxVoltage;
|
||||
|
||||
/**
|
||||
* 单体电池最低电压
|
||||
*/
|
||||
private String singleBatteryMinVoltage;
|
||||
|
||||
/**
|
||||
* 单体电池最高温度
|
||||
*/
|
||||
private String singleBatteryMaxTemperature;
|
||||
|
||||
/**
|
||||
* 单体电池最低温度
|
||||
*/
|
||||
private String singleBatteryMinTemperature;
|
||||
|
||||
/**
|
||||
* 动力电池可用容量
|
||||
*/
|
||||
private String availableBatteryCapacity;
|
||||
|
||||
/**
|
||||
* 车辆状态
|
||||
*/
|
||||
private int vehicleStatus = 1;
|
||||
|
||||
/**
|
||||
* 充电状态
|
||||
*/
|
||||
private int chargingStatus = 1;
|
||||
|
||||
/**
|
||||
* 运行状态
|
||||
*/
|
||||
private int operatingStatus = 1;
|
||||
|
||||
/**
|
||||
* SOC
|
||||
*/
|
||||
private int socStatus = 1;
|
||||
|
||||
/**
|
||||
* 可充电储能装置工作状态
|
||||
*/
|
||||
private int chargingEnergyStorageStatus = 1;
|
||||
|
||||
/**
|
||||
* 驱动电机状态
|
||||
*/
|
||||
private int driveMotorStatus = 1;
|
||||
|
||||
/**
|
||||
* 定位是否有效
|
||||
*/
|
||||
private int positionStatus = 1;
|
||||
|
||||
/**
|
||||
* EAS(汽车防盗系统)状态
|
||||
*/
|
||||
private int easStatus = 1;
|
||||
|
||||
/**
|
||||
* PTC(电动加热器)状态
|
||||
*/
|
||||
private int ptcStatus = 1;
|
||||
|
||||
/**
|
||||
* EPS(电动助力系统)状态
|
||||
*/
|
||||
private int epsStatus = 1;
|
||||
|
||||
/**
|
||||
* ABS(防抱死)状态
|
||||
*/
|
||||
private int absStatus = 1;
|
||||
|
||||
/**
|
||||
* MCU(电机/逆变器)状态
|
||||
*/
|
||||
private int mcuStatus = 1;
|
||||
|
||||
/**
|
||||
* 动力电池加热状态
|
||||
*/
|
||||
private int heatingStatus = 1;
|
||||
|
||||
/**
|
||||
* 动力电池当前状态
|
||||
*/
|
||||
private int batteryStatus = 1;
|
||||
|
||||
/**
|
||||
* 动力电池保温状态
|
||||
*/
|
||||
private int batteryInsulationStatus = 1;
|
||||
|
||||
/**
|
||||
* DCDC(电力交换系统)状态
|
||||
*/
|
||||
private int dcdcStatus = 1;
|
||||
|
||||
/**
|
||||
* CHG(充电机)状态
|
||||
*/
|
||||
private int chgStatus = 1;
|
||||
|
||||
/**
|
||||
* 车辆状态 报文
|
||||
*/
|
||||
private String vehicleStatusMsg;
|
||||
/**
|
||||
* 智能硬件 报文
|
||||
*/
|
||||
private String smartHardwareMsg;
|
||||
/**
|
||||
* 电池报文
|
||||
*/
|
||||
private String batteryMsg;
|
||||
|
||||
public String getMsg(){
|
||||
//第一位VIN
|
||||
return vin +
|
||||
// 当前时间戳
|
||||
System.currentTimeMillis() +
|
||||
//第二位经度 longitude latitude
|
||||
getValue(longitude, 11) +
|
||||
//第三位维度 longitude latitude
|
||||
getValue(latitude, 10) +
|
||||
//车速
|
||||
getValue(speed, 6) +
|
||||
//总里程
|
||||
getValue(mileage == null ? "" : mileage.toString(), 11) +
|
||||
// 总电压
|
||||
getValue(voltage, 6) +
|
||||
//总电流
|
||||
getValue(current, 5) +
|
||||
//绝缘电阻 79 - 87
|
||||
getValue(resistance, 9) +
|
||||
//档位
|
||||
(gear == null ? "D" : gear) +
|
||||
// 加速踏板行程值
|
||||
getValue(accelerationPedal, 2) +
|
||||
// 制动踏板行程值
|
||||
getValue(brakePedal, 2) +
|
||||
// 燃料消耗率
|
||||
getValue(fuelConsumptionRate, 5) +
|
||||
//电机控制器温度
|
||||
getValue(motorControllerTemperature, 6) +
|
||||
//电机转速
|
||||
getValue(motorSpeed, 5) +
|
||||
//点击转矩
|
||||
getValue(motorTorque, 4) +
|
||||
//电机温度
|
||||
getValue(motorTemperature, 6) +
|
||||
//电机电压
|
||||
getValue(motorVoltage, 5) +
|
||||
//电机电流
|
||||
getValue(motorCurrent, 8) +
|
||||
//动力电池剩余电量SOC
|
||||
getValue(remainingBattery == null ? "" : remainingBattery.toString(), 6) +
|
||||
//当前状态允许的最大反馈功率
|
||||
getValue(maximumFeedbackPower, 6) +
|
||||
//当前状态允许最大放电功率
|
||||
getValue(maximumDischargePower, 6) +
|
||||
//BMS自检计数器
|
||||
getValue(selfCheckCounter, 2) +
|
||||
//动力电池充放电电流
|
||||
getValue(totalBatteryCurrent, 5) +
|
||||
//动力电池负载端总电压V3
|
||||
getValue(totalBatteryVoltage, 6) +
|
||||
//单次最大电压
|
||||
getValue(singleBatteryMaxVoltage, 4) +
|
||||
//单体电池最低电压
|
||||
getValue(singleBatteryMinVoltage, 4) +
|
||||
//单体电池最高温度
|
||||
getValue(singleBatteryMaxTemperature, 6) +
|
||||
//单体电池最低温度
|
||||
getValue(singleBatteryMinTemperature, 6) +
|
||||
//动力电池可用容量
|
||||
getValue(availableBatteryCapacity, 6) +
|
||||
//车辆状态
|
||||
vehicleStatus +
|
||||
//充电状态
|
||||
chargingStatus +
|
||||
//运行状态
|
||||
operatingStatus +
|
||||
//SOC
|
||||
socStatus +
|
||||
//可充电储能装置工作状态
|
||||
chargingEnergyStorageStatus +
|
||||
//驱动电机状态
|
||||
driveMotorStatus +
|
||||
//定位是否有效
|
||||
positionStatus +
|
||||
//EAS
|
||||
easStatus +
|
||||
//PTC
|
||||
ptcStatus +
|
||||
//EPS
|
||||
epsStatus +
|
||||
//ABS
|
||||
absStatus +
|
||||
//MCU
|
||||
mcuStatus +
|
||||
//动力电池加热状态
|
||||
heatingStatus +
|
||||
//动力电池当前状态
|
||||
batteryStatus +
|
||||
//动力电池保温状态
|
||||
batteryInsulationStatus +
|
||||
//DCDC
|
||||
dcdcStatus +
|
||||
//CHG
|
||||
chgStatus;
|
||||
}
|
||||
|
||||
public String getValue(String val , int valLength){
|
||||
|
@ -109,16 +385,136 @@ public class VehicleData {
|
|||
|
||||
/**
|
||||
* 汽车对象构造企业VIN
|
||||
* @param vehicleInfo 汽车对象
|
||||
* @param vehicle 汽车对象
|
||||
* @return 汽车数据对象
|
||||
*/
|
||||
public static VehicleData vehicleBuild (VehicleInfo vehicleInfo) {
|
||||
public static VehicleData vehicleBuild (Vehicle vehicle) {
|
||||
return VehicleData.builder()
|
||||
.vin(vehicleInfo.getVin())
|
||||
.vin(vehicle.getVin())
|
||||
.gear("P")
|
||||
.remainingBattery(vehicleInfo.getRemainingBattery())
|
||||
.batteryLevel(vehicleInfo.getBatteryLevel())
|
||||
.mileage(vehicleInfo.getTotalMileage())
|
||||
.remainingBattery(vehicle.getRemainingBattery())
|
||||
.batteryLevel(vehicle.getBatteryLevel())
|
||||
.mileage(vehicle.getTotalMileage())
|
||||
.vehicleStatus(1)
|
||||
.chargingStatus(1)
|
||||
.operatingStatus(1)
|
||||
.socStatus(1)
|
||||
.chargingEnergyStorageStatus(1)
|
||||
.driveMotorStatus(1)
|
||||
.positionStatus(1)
|
||||
.easStatus(1)
|
||||
.ptcStatus(1)
|
||||
.epsStatus(1)
|
||||
.absStatus(1)
|
||||
.mcuStatus(1)
|
||||
.heatingStatus(1)
|
||||
.batteryStatus(1)
|
||||
.batteryInsulationStatus(1)
|
||||
.dcdcStatus(1)
|
||||
.chgStatus(1)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 模拟基础项
|
||||
*/
|
||||
public void imitateBase(){
|
||||
// 总电压
|
||||
this.voltage = genValue(110, 750);
|
||||
// 总电流
|
||||
this.current = genValue(3, 50);
|
||||
// 绝缘电阻
|
||||
this.resistance = genValue(0,30000);
|
||||
// 加速踏板行程值
|
||||
this.accelerationPedal = genValue(0, 10);
|
||||
// 制动踏板行程值
|
||||
this.brakePedal = genValue(0, 10);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 模拟电机数据
|
||||
*/
|
||||
public void imitateMotor(){
|
||||
// 电机控制器温度
|
||||
this.motorControllerTemperature = genValue(0, 100);
|
||||
// 电机转速
|
||||
this.motorSpeed = genValue(0, 99999);
|
||||
// 电机转矩
|
||||
this.motorTorque = genValue(0, 1000);
|
||||
// 电机温度
|
||||
this.motorTemperature = genValue(0, 150);
|
||||
// 电机电压
|
||||
this.motorVoltage = genValue(110, 300);
|
||||
// 电机电流
|
||||
this.motorCurrent = genValue(0, 15000);
|
||||
}
|
||||
|
||||
/**
|
||||
* 模拟电池包数据
|
||||
*/
|
||||
public void imitateBatteryPack(){
|
||||
// 当前状态允许的最大反馈功率
|
||||
this.maximumFeedbackPower = genValue(0, 100);
|
||||
// 当前状态允许最大放电功率
|
||||
this.maximumDischargePower = genValue(0, 100);
|
||||
// BMS自检计数器
|
||||
this.selfCheckCounter = genValue(0, 15);
|
||||
// 动力电池充放电电流
|
||||
this.totalBatteryCurrent = genValue(0, 15);
|
||||
// 动力电池负载端总电压V3
|
||||
this.totalBatteryVoltage = genValue(220, 750);
|
||||
// 单体电池最高电压
|
||||
this.singleBatteryMaxVoltage = genValue(3, 5);
|
||||
// 单体电池最低电压
|
||||
this.singleBatteryMinVoltage = genValue(3, 5);
|
||||
// 单体电池最高温度
|
||||
this.singleBatteryMaxTemperature = genValue(0, 100);
|
||||
// 单体电池最低温度
|
||||
this.singleBatteryMinTemperature = genValue(0, 100);
|
||||
// 动力电池可用容量
|
||||
this.availableBatteryCapacity = genValue(0,100 );
|
||||
}
|
||||
/**
|
||||
车辆状态
|
||||
vehicleStatus;
|
||||
充电状态
|
||||
chargingStatus;
|
||||
运行状态
|
||||
operatingStatus;
|
||||
SOC
|
||||
socStatus;
|
||||
可充电储能装置工作状态
|
||||
chargingEnergyStorageStatus;
|
||||
驱动电机状态
|
||||
driveMotorStatus;
|
||||
定位是否有效
|
||||
positionStatus;
|
||||
*/
|
||||
|
||||
/**
|
||||
EAS(汽车防盗系统)状态
|
||||
easStatus;
|
||||
PTC(电动加热器)状态
|
||||
ptcStatus;
|
||||
EPS(电动助力系统)状态
|
||||
epsStatus;
|
||||
ABS(防抱死)状态
|
||||
absStatus;
|
||||
MCU(电机/逆变器)状态
|
||||
mcuStatus;
|
||||
*/
|
||||
|
||||
/**
|
||||
动力电池加热状态
|
||||
heatingStatus;
|
||||
动力电池当前状态
|
||||
batteryStatus;
|
||||
动力电池保温状态
|
||||
batteryInsulationStatus;
|
||||
DCDC(电力交换系统)状态
|
||||
dcdcStatus;
|
||||
CHG(充电机)状态
|
||||
chgStatus;
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import lombok.AllArgsConstructor;
|
|||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author DongZeLiang
|
||||
|
@ -41,9 +43,5 @@ public class MqttProperties {
|
|||
* 节点ID
|
||||
*/
|
||||
private String clientId;
|
||||
|
||||
/**
|
||||
* 上报级别
|
||||
*/
|
||||
private int qos = 0;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,11 @@ public class VehicleThread implements Runnable {
|
|||
*/
|
||||
private volatile boolean isStop = false;
|
||||
|
||||
/**
|
||||
* 设置是否暂停
|
||||
*/
|
||||
private volatile boolean isPaused;
|
||||
|
||||
/**
|
||||
* 车辆实例对象
|
||||
*/
|
||||
|
@ -22,9 +27,19 @@ public class VehicleThread implements Runnable {
|
|||
public void run() {
|
||||
try {
|
||||
if (!isStop){
|
||||
String msg = this.vehicleInstance.imitateDataAndMsg();
|
||||
log.info("{} - 上报数据: [{}]", this.vehicleInstance.getVin(), msg);
|
||||
this.vehicleInstance.sendMsg( msg );
|
||||
if (!isPaused){
|
||||
log.info("{} - 上报数据", this.vehicleInstance.getVin());
|
||||
String imitateResult = this.vehicleInstance.imitateData();
|
||||
if (imitateResult == null){
|
||||
this.vehicleInstance.sendMsg(
|
||||
this.vehicleInstance.getVehicleData().getMsg()
|
||||
);
|
||||
}else {
|
||||
log.warn("车辆[{}]数据模拟:{}", this.vehicleInstance.getVin(), imitateResult);
|
||||
}
|
||||
}else {
|
||||
log.info("暂停模拟和上报:[{}]", this.vehicleInstance.getVin());
|
||||
}
|
||||
}else {
|
||||
log.info("终止模拟和上报:[{}]", this.vehicleInstance.getVin());
|
||||
vehicleInstance.cancelExecution();
|
||||
|
@ -34,6 +49,21 @@ public class VehicleThread implements Runnable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂停线程
|
||||
*/
|
||||
public void pause() {
|
||||
isPaused = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始线程
|
||||
*/
|
||||
public void resume() {
|
||||
isPaused = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 停止方法
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package com.muyu.web.config;
|
||||
|
||||
import com.muyu.web.common.Result;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
/**
|
||||
* @author DongZeLiang
|
||||
* @version 1.0
|
||||
* @description 异常类
|
||||
* @date 2023/11/15
|
||||
*/
|
||||
@RestControllerAdvice
|
||||
public class ExceptionAdvice {
|
||||
|
||||
/**
|
||||
* 运行时异常拦截
|
||||
* @param runtimeException 运行时异常
|
||||
* @return 公共返回结果
|
||||
*/
|
||||
@ExceptionHandler(value = RuntimeException.class)
|
||||
public Result<String> runtimeExceptionHandler(RuntimeException runtimeException){
|
||||
return Result.error(runtimeException.getMessage());
|
||||
}
|
||||
}
|
|
@ -1,11 +1,13 @@
|
|||
package com.muyu.config;
|
||||
package com.muyu.web.config;
|
||||
|
||||
import com.dtflys.forest.annotation.BindingVar;
|
||||
import com.muyu.system.handle.SystemHandler;
|
||||
import com.dtflys.forest.reflection.ForestMethod;
|
||||
import com.muyu.web.config.properties.ServiceConfigProperties;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Forest配置类
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/6/10
|
||||
* @Description: Forest配置类
|
||||
|
@ -14,6 +16,9 @@ import org.springframework.stereotype.Service;
|
|||
@Service("forsetConfig")
|
||||
public class ForsetConfig {
|
||||
|
||||
@Autowired
|
||||
private ServiceConfigProperties serviceConfigProperties;
|
||||
|
||||
/**
|
||||
* 使用 @BindingVar 注解
|
||||
* 将变量名 baseUrl 和一段方法代码绑定
|
||||
|
@ -21,7 +26,7 @@ public class ForsetConfig {
|
|||
*/
|
||||
@BindingVar("vehicleLoadUrl")
|
||||
public String getBaseUrl() {
|
||||
return SystemHandler.getLoadReqUrl();
|
||||
return serviceConfigProperties.getLoadReqUrl();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package com.muyu.web.config;
|
||||
|
||||
import com.muyu.web.config.properties.ServiceConfigProperties;
|
||||
import com.muyu.web.domain.model.ServerConfigModel;
|
||||
import com.muyu.web.service.ServerConfigService;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/6/10
|
||||
* @Description: 负载服务器配置
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Configuration
|
||||
public class LoadServerConfig {
|
||||
|
||||
/**
|
||||
* 静态引入,解决循环依赖的问题
|
||||
*/
|
||||
private static final ServiceConfigProperties serviceConfigProperties = new ServiceConfigProperties();
|
||||
|
||||
@Bean
|
||||
public ServiceConfigProperties serverConfig(ServerConfigService serverConfigService) {
|
||||
return serviceConfigProperties.modelToProperties(serverConfigService.get());
|
||||
}
|
||||
|
||||
public static void modelToProperties(ServerConfigModel serverConfigModel){
|
||||
serviceConfigProperties.modelToProperties(serverConfigModel);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.muyu.web.config;
|
||||
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 填充公共字段
|
||||
*
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class MyMetaObjectHandler implements MetaObjectHandler {
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
log.info("start insert fill...");
|
||||
this.setFieldValByName("createTime", new Date(), metaObject);
|
||||
this.setFieldValByName("updateTime", new Date(), metaObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
log.info("start update fill...");
|
||||
this.setFieldValByName("updateTime", new Date(), metaObject);
|
||||
}
|
||||
}
|
|
@ -1,11 +1,8 @@
|
|||
package com.muyu.config;
|
||||
package com.muyu.web.config;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
|
||||
import com.muyu.config.tenant.CustomTenantHandler;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
|
@ -14,9 +11,16 @@ import org.springframework.context.annotation.Configuration;
|
|||
*/
|
||||
@Configuration
|
||||
public class MybatisPlusConfig {
|
||||
/**
|
||||
* 老版本,目前已失效
|
||||
* @return
|
||||
*/
|
||||
/**@Bean
|
||||
public PaginationInterceptor paginationInterceptor() {
|
||||
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
|
||||
return paginationInterceptor;
|
||||
}*/
|
||||
|
||||
@Autowired
|
||||
private CustomTenantHandler customTenantHandler;
|
||||
|
||||
/**
|
||||
* 新的分页插件,一缓和二缓遵循mybatis的规则,
|
||||
|
@ -24,10 +28,7 @@ public class MybatisPlusConfig {
|
|||
@Bean
|
||||
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
||||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||||
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
|
||||
TenantLineInnerInterceptor tenantInterceptor = new TenantLineInnerInterceptor();
|
||||
tenantInterceptor.setTenantLineHandler(customTenantHandler);
|
||||
interceptor.addInnerInterceptor(tenantInterceptor);
|
||||
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
|
||||
return interceptor;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package com.muyu.web.config.properties;
|
||||
|
||||
import com.muyu.web.domain.model.ServerConfigModel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/6/10
|
||||
* @Description: 服务器配置类
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ServiceConfigProperties {
|
||||
|
||||
/**
|
||||
* 主机地址
|
||||
*/
|
||||
private String host;
|
||||
/**
|
||||
* 端口号
|
||||
*/
|
||||
private String port;
|
||||
/**
|
||||
* 负载地址
|
||||
*/
|
||||
private String loadUrl;
|
||||
/**
|
||||
* 负载请求格式化地址
|
||||
*/
|
||||
private String loadReqUrl;
|
||||
/**
|
||||
* 默认MQTT地址
|
||||
*/
|
||||
private String mqttAddr;
|
||||
/**
|
||||
* 默认MQTT主题
|
||||
*/
|
||||
private String mqttTopic;
|
||||
/**
|
||||
* 默认MQTT交付级别
|
||||
*/
|
||||
private Integer mqttQos;
|
||||
|
||||
/**
|
||||
* 模型构建配置
|
||||
* @param serverConfigModel 配置模型对象
|
||||
* @return 配置对象
|
||||
*/
|
||||
public ServiceConfigProperties modelToProperties(ServerConfigModel serverConfigModel) {
|
||||
this.host = serverConfigModel.getHost();
|
||||
this.port = serverConfigModel.getPort();
|
||||
this.loadUrl = serverConfigModel.getLoadUrl();
|
||||
this.mqttAddr = serverConfigModel.getDefaultMqttAddr();
|
||||
this.mqttTopic = serverConfigModel.getDefaultMqttTopic();
|
||||
this.mqttQos = serverConfigModel.getDefaultMqttQos();
|
||||
this.loadReqUrl = String.format("http://%s:%s%s", host, port, loadUrl.startsWith("/") ? loadUrl : "/" + loadUrl);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
package com.muyu.web.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.muyu.web.common.Result;
|
||||
import com.muyu.web.domain.MessageTemplate;
|
||||
import com.muyu.web.domain.MessageTemplateValue;
|
||||
import com.muyu.web.domain.req.MessageTemplateSaveReq;
|
||||
import com.muyu.web.domain.req.MessageTemplateValueSaveReq;
|
||||
import com.muyu.web.service.MessageService;
|
||||
import com.muyu.web.service.MessageTemplateService;
|
||||
import com.muyu.web.service.MessageTemplateValueService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/18
|
||||
* @Description: 报文控制层
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/message")
|
||||
public class MessageController {
|
||||
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
|
||||
@Autowired
|
||||
private MessageTemplateService messageTemplateService;
|
||||
|
||||
@Autowired
|
||||
private MessageTemplateValueService messageTemplateValueService;
|
||||
|
||||
/**
|
||||
* 报文模板列表
|
||||
* @return 列表
|
||||
*/
|
||||
@GetMapping("/template/list")
|
||||
public Result<List<MessageTemplate>> templateList(){
|
||||
return Result.success(
|
||||
messageTemplateService.list()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存报文模板
|
||||
* @return 统一返回值
|
||||
*/
|
||||
@PostMapping("/template")
|
||||
public Result<String> save(@RequestBody @Validated MessageTemplateSaveReq messageTemplateSaveReq){
|
||||
messageService.saveMessageTemplate(messageTemplateSaveReq);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 报文模板值列表
|
||||
* @return 统一返回值
|
||||
*/
|
||||
@GetMapping("/template/{messageTemplateId}/value")
|
||||
public Result<List<MessageTemplateValue>> templateValueList(@PathVariable("messageTemplateId") Long messageTemplateId) {
|
||||
return Result.success(
|
||||
this.messageTemplateValueService.list(
|
||||
new LambdaQueryWrapper<>(){{
|
||||
eq(MessageTemplateValue::getMessageId, messageTemplateId);
|
||||
}}
|
||||
)
|
||||
);
|
||||
}
|
||||
/**
|
||||
* 保存报文模板
|
||||
* @return 统一返回值
|
||||
*/
|
||||
@PostMapping("/template/{messageTemplateId}/value")
|
||||
public Result<String> templateValueSave(
|
||||
@RequestBody @Validated MessageTemplateValueSaveReq messageTemplateValueSaveReq,
|
||||
@PathVariable("messageTemplateId") Long messageTemplateId
|
||||
){
|
||||
messageTemplateValueService.save(
|
||||
MessageTemplateValue.builder()
|
||||
.messageId(messageTemplateId)
|
||||
.code(messageTemplateValueSaveReq.getCode())
|
||||
.category(messageTemplateValueSaveReq.getCategory())
|
||||
.label(messageTemplateValueSaveReq.getLabel())
|
||||
.length(messageTemplateValueSaveReq.getLength())
|
||||
.maxValue(messageTemplateValueSaveReq.getMaxValue())
|
||||
.minValue(messageTemplateValueSaveReq.getMinValue())
|
||||
.valueType(messageTemplateValueSaveReq.getValueType())
|
||||
.elValue(messageTemplateValueSaveReq.getElValue())
|
||||
.fixedValue(messageTemplateValueSaveReq.getFixedValue())
|
||||
.startLocation(messageTemplateValueSaveReq.getStartLocation())
|
||||
.endLocation(messageTemplateValueSaveReq.getEndLocation())
|
||||
.build()
|
||||
);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
package com.muyu.web.controller;
|
||||
|
||||
import com.muyu.system.domain.LoginUserInfo;
|
||||
import com.muyu.web.common.Result;
|
||||
import com.muyu.web.domain.req.UserLoginReq;
|
||||
import com.muyu.web.domain.req.UserRegReq;
|
||||
import com.muyu.web.service.SystemAuthService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/12
|
||||
* @Description: 系统登录接口
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/system/auth")
|
||||
public class SystemAuthController {
|
||||
|
||||
@Autowired
|
||||
private SystemAuthService systemAuthService;
|
||||
|
||||
@PostMapping("/reg")
|
||||
public Result<String> reg(@RequestBody @Validated UserRegReq userRegReq) {
|
||||
systemAuthService.reg(userRegReq);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
* @param userLoginReq 用户登录请求对象
|
||||
* @return token
|
||||
*/
|
||||
@PostMapping("/login")
|
||||
public Result<String> login(@RequestBody @Validated UserLoginReq userLoginReq){
|
||||
String token = systemAuthService.login(userLoginReq.getUserName(), userLoginReq.getPassword());
|
||||
return Result.success(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户退出
|
||||
* @return token
|
||||
*/
|
||||
@GetMapping("/info")
|
||||
public Result<LoginUserInfo> info(){
|
||||
return Result.success(systemAuthService.info());
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户退出
|
||||
* @return token
|
||||
*/
|
||||
@PostMapping("/logout")
|
||||
public Result<String> logout(){
|
||||
systemAuthService.logout();
|
||||
return Result.success();
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
package com.muyu.web.controller;
|
||||
|
||||
import com.muyu.web.common.Result;
|
||||
import com.muyu.web.domain.VehicleInfo;
|
||||
import com.muyu.web.domain.Vehicle;
|
||||
import com.muyu.web.domain.req.VehicleCreateAddReq;
|
||||
import com.muyu.web.service.VehicleInfoService;
|
||||
import com.muyu.web.service.VehicleService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
@ -20,11 +20,11 @@ import java.util.List;
|
|||
public class VehicleController {
|
||||
|
||||
@Autowired
|
||||
private VehicleInfoService vehicleInfoService;
|
||||
private VehicleService vehicleService;
|
||||
|
||||
@GetMapping("/list")
|
||||
public Result<List<VehicleInfo>> list(){
|
||||
return Result.success(vehicleInfoService.list());
|
||||
public Result<List<Vehicle>> list(){
|
||||
return Result.success(vehicleService.list());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -32,12 +32,9 @@ public class VehicleController {
|
|||
* @param sum 车辆总数
|
||||
* @return 结果集
|
||||
*/
|
||||
@GetMapping("/gen/{sum}/{messageTemplateId}")
|
||||
public Result<String> generate(
|
||||
@PathVariable(value = "sum") Integer sum,
|
||||
@PathVariable("messageTemplateId") Long messageTemplateId
|
||||
){
|
||||
vehicleInfoService.generate(sum, messageTemplateId);
|
||||
@GetMapping("/gen/{sum}")
|
||||
public Result<String> generate(@PathVariable(value = "sum") Integer sum){
|
||||
vehicleService.generate(sum);
|
||||
return Result.success();
|
||||
}
|
||||
/**
|
||||
|
@ -47,7 +44,7 @@ public class VehicleController {
|
|||
*/
|
||||
@PostMapping("/create")
|
||||
public Result<String> create(@RequestBody VehicleCreateAddReq vehicleCreateAddReq){
|
||||
vehicleInfoService.create(vehicleCreateAddReq.getVinList(), vehicleCreateAddReq.getMessageTemplateId());
|
||||
vehicleService.create(vehicleCreateAddReq.getVinStr());
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
@ -59,7 +56,7 @@ public class VehicleController {
|
|||
*/
|
||||
@DeleteMapping("/{vin}")
|
||||
public Result<String> delete(@PathVariable("vin") String vin){
|
||||
this.vehicleInfoService.delete(vin);
|
||||
this.vehicleService.delete(vin);
|
||||
return Result.success(null,"删除成功");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
package com.muyu.web.controller;
|
||||
|
||||
import com.muyu.vehicle.core.LocalContainer;
|
||||
import com.muyu.vehicle.model.VehicleData;
|
||||
import com.muyu.web.common.PageList;
|
||||
import com.muyu.web.common.Result;
|
||||
import com.muyu.web.domain.req.CheckPositionReq;
|
||||
import com.muyu.web.domain.req.GearReq;
|
||||
import com.muyu.web.domain.req.MsgReq;
|
||||
import com.muyu.web.domain.req.VehicleInstanceListReq;
|
||||
import com.muyu.web.domain.resp.VehicleInstanceResp;
|
||||
import com.muyu.web.service.VehicleInstanceService;
|
||||
import com.muyu.vehicle.core.LocalContainer;
|
||||
import com.muyu.vehicle.model.VehicleData;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
@ -28,83 +29,80 @@ public class VehicleInstanceController {
|
|||
|
||||
/**
|
||||
* 查询车辆集合
|
||||
*
|
||||
* @param vehicleInstanceListReq 车辆列表查询对象
|
||||
* @return 结果
|
||||
*/
|
||||
@PostMapping("/list")
|
||||
public Result<PageList<VehicleInstanceResp>> list(@RequestBody VehicleInstanceListReq vehicleInstanceListReq) {
|
||||
public Result<PageList<VehicleInstanceResp>> list(@RequestBody VehicleInstanceListReq vehicleInstanceListReq){
|
||||
PageList<VehicleInstanceResp> pageList = vehicleInstanceService.queryList(vehicleInstanceListReq);
|
||||
return Result.success(pageList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据车辆VIN获取车辆数据
|
||||
*
|
||||
* @param vin VIN
|
||||
* @return 车辆数据
|
||||
*/
|
||||
@GetMapping("/data/{vin}")
|
||||
public Result<VehicleData> getVehicleData(@PathVariable("vin") String vin) {
|
||||
public Result<VehicleData> getVehicleData(@PathVariable("vin") String vin){
|
||||
return Result.success(LocalContainer.getVehicleInstance(vin).getVehicleData());
|
||||
}
|
||||
|
||||
/**
|
||||
* 车辆连接初始化
|
||||
*
|
||||
* @param vin vin
|
||||
* @return 初始化
|
||||
*/
|
||||
@PostMapping("/client/start/{vin}")
|
||||
public Result<String> vehicleClientInit(@PathVariable("vin") String vin) {
|
||||
this.vehicleInstanceService.vehicleClientStart(vin);
|
||||
this.vehicleInstanceService.checkPosition(
|
||||
CheckPositionReq.builder()
|
||||
.vin(vin)
|
||||
.positionCode("路径1")
|
||||
.build()
|
||||
);
|
||||
@PostMapping("/client/init/{vin}")
|
||||
public Result<String> vehicleClientInit(@PathVariable("vin") String vin){
|
||||
this.vehicleInstanceService.vehicleClientInit(vin);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭车辆连接
|
||||
*
|
||||
* @param vin vin
|
||||
* @return 初始化
|
||||
*/
|
||||
@PostMapping("/client/close/{vin}")
|
||||
public Result<String> vehicleClientClose(@PathVariable("vin") String vin) {
|
||||
public Result<String> vehicleClientClose(@PathVariable("vin") String vin){
|
||||
this.vehicleInstanceService.vehicleClientClose(vin);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择车辆轨迹
|
||||
*
|
||||
* @param checkPositionReq 轨迹选择
|
||||
* @return 操作提示
|
||||
*/
|
||||
@PostMapping("/position/check")
|
||||
public Result<String> checkPosition(@RequestBody CheckPositionReq checkPositionReq) {
|
||||
public Result<String> checkPosition(@RequestBody CheckPositionReq checkPositionReq){
|
||||
this.vehicleInstanceService.checkPosition(checkPositionReq);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 车辆报文操作
|
||||
* @return 操作提示
|
||||
*/
|
||||
@PostMapping("/msg")
|
||||
public Result<String> msg(@RequestBody MsgReq msgReq){
|
||||
this.vehicleInstanceService.msg(msgReq);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 车辆档位操作
|
||||
*
|
||||
* @return 操作提示
|
||||
*/
|
||||
@PostMapping("/gear")
|
||||
public Result<String> gear(@RequestBody GearReq gearReq) {
|
||||
public Result<String> gear(@RequestBody GearReq gearReq){
|
||||
this.vehicleInstanceService.gear(gearReq);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置车辆故障状态
|
||||
*
|
||||
* @param statusKey
|
||||
* @param vin
|
||||
* @param statusValue
|
||||
|
@ -113,7 +111,7 @@ public class VehicleInstanceController {
|
|||
@PutMapping("/status/{vin}/{statusKey}/{statusValue}")
|
||||
public Result<String> editStatus(@PathVariable("statusKey") String statusKey,
|
||||
@PathVariable("vin") String vin,
|
||||
@PathVariable("statusValue") Integer statusValue) {
|
||||
@PathVariable("statusValue") Integer statusValue){
|
||||
this.vehicleInstanceService.editStatus(vin, statusKey, statusValue);
|
||||
return Result.success();
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package com.muyu.web.controller;
|
||||
|
||||
import com.muyu.system.handle.SystemHandler;
|
||||
import com.muyu.web.common.Result;
|
||||
import com.muyu.system.properties.ServerConfigProperties;
|
||||
import com.muyu.web.config.properties.ServiceConfigProperties;
|
||||
import com.muyu.web.domain.model.MqttServerModel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
@ -19,6 +18,8 @@ import org.springframework.web.bind.annotation.RestController;
|
|||
@AllArgsConstructor
|
||||
public class VerifyController {
|
||||
|
||||
private final ServiceConfigProperties serviceConfigProperties;
|
||||
|
||||
|
||||
/**
|
||||
* 新增车辆默认上线主题
|
||||
|
@ -26,11 +27,10 @@ public class VerifyController {
|
|||
*/
|
||||
@PostMapping("/vehicleConnection")
|
||||
public Result<MqttServerModel> vehicleConnection(){
|
||||
ServerConfigProperties serverConfig = SystemHandler.getServerConfig();
|
||||
return Result.success(
|
||||
MqttServerModel.builder()
|
||||
.broker(serverConfig.getMqttAddr())
|
||||
.topic(serverConfig.getMqttTopic())
|
||||
.broker(serviceConfigProperties.getMqttAddr())
|
||||
.topic(serviceConfigProperties.getMqttTopic())
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
package com.muyu.web.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @Description: 报文模板
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/18
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@TableName(value = "message_template")
|
||||
public class MessageTemplate {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private String tenantId;
|
||||
|
||||
/**
|
||||
* 报文名称
|
||||
*/
|
||||
private String messageName;
|
||||
|
||||
/**
|
||||
* 报文描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Date createTime;
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
package com.muyu.web.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.muyu.system.enums.MessageTemplateValueType;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/18
|
||||
* @Description: 报文模板值规则
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@TableName(value = "message_template_value")
|
||||
public class MessageTemplateValue {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private String tenantId;
|
||||
/**
|
||||
* 报文模板
|
||||
*/
|
||||
private Long messageId;
|
||||
|
||||
/**
|
||||
* 报文长度
|
||||
*/
|
||||
private Integer length;
|
||||
|
||||
/**
|
||||
* 报文类别
|
||||
*/
|
||||
private String category;
|
||||
/**
|
||||
* 报文编码
|
||||
*/
|
||||
private String code;
|
||||
/**
|
||||
* 报文标签
|
||||
*/
|
||||
private String label;
|
||||
/**
|
||||
* 报文起始位置
|
||||
*/
|
||||
private Integer startLocation;
|
||||
/**
|
||||
* 报文终止位置
|
||||
*/
|
||||
private Integer endLocation;
|
||||
/**
|
||||
* 数据类型
|
||||
*/
|
||||
private String valueType;
|
||||
/**
|
||||
* 表达式值
|
||||
*/
|
||||
private String elValue;
|
||||
/**
|
||||
* 固定值
|
||||
*/
|
||||
private String fixedValue;
|
||||
/**
|
||||
* 数据最小范围
|
||||
*/
|
||||
private Double minValue;
|
||||
/**
|
||||
* 数据最大范围
|
||||
*/
|
||||
private Double maxValue;
|
||||
|
||||
public boolean isEl () {
|
||||
return MessageTemplateValueType.EL.code().equals(valueType);
|
||||
}
|
||||
|
||||
public boolean isInterval () {
|
||||
return MessageTemplateValueType.INTERVAL.code().equals(valueType);
|
||||
}
|
||||
|
||||
public boolean isFixed () {
|
||||
return MessageTemplateValueType.FIXED.code().equals(valueType);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package com.muyu.web.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
|
@ -20,7 +19,7 @@ import java.util.Date;
|
|||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@TableName("position_route_info")
|
||||
@TableName("route_info")
|
||||
public class PositionRouteInfo {
|
||||
|
||||
/**
|
||||
|
@ -29,12 +28,6 @@ public class PositionRouteInfo {
|
|||
@TableId("id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
@TableField(value = "tenant_id", fill = FieldFill.INSERT)
|
||||
private String tenantId;
|
||||
|
||||
/**
|
||||
* 名称
|
||||
*/
|
||||
|
@ -44,12 +37,12 @@ public class PositionRouteInfo {
|
|||
/**
|
||||
* 数据
|
||||
*/
|
||||
@TableField(value = "route_data")
|
||||
@TableField(value = "data")
|
||||
private String routeData;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(value = "create_time", fill = FieldFill.INSERT)
|
||||
@TableField(value = "create_time")
|
||||
private Date createTime;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.muyu.web.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.muyu.system.handle.SystemHandler;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.muyu.web.domain.model.ServerConfigModel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
|
@ -26,18 +25,7 @@ public class ServerConfig {
|
|||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId(
|
||||
value = "id",
|
||||
type = IdType.AUTO
|
||||
)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
@TableField(value = "tenant_id", fill = FieldFill.INSERT)
|
||||
private String tenantId;
|
||||
|
||||
private Integer id;
|
||||
/**
|
||||
* 主机地址
|
||||
*/
|
||||
|
@ -49,7 +37,7 @@ public class ServerConfig {
|
|||
/**
|
||||
* 负载地址
|
||||
*/
|
||||
private String uri;
|
||||
private String loadUrl;
|
||||
/**
|
||||
* 默认MQTT地址
|
||||
*/
|
||||
|
@ -63,13 +51,12 @@ public class ServerConfig {
|
|||
*/
|
||||
private Integer defaultMqttQos;
|
||||
|
||||
public static ServerConfig modeBuild (ServerConfigModel serverConfigModel, Supplier<Long> idKey) {
|
||||
public static ServerConfig modeBuild (ServerConfigModel serverConfigModel, Supplier<Integer> idKey) {
|
||||
return builder()
|
||||
.id(idKey.get())
|
||||
.tenantId(SystemHandler.getTenantId())
|
||||
.host(serverConfigModel.getHost())
|
||||
.port(serverConfigModel.getPort())
|
||||
.uri(serverConfigModel.getUri())
|
||||
.loadUrl(serverConfigModel.getLoadUrl())
|
||||
.defaultMqttAddr(serverConfigModel.getDefaultMqttAddr())
|
||||
.defaultMqttTopic(serverConfigModel.getDefaultMqttTopic())
|
||||
.defaultMqttQos(serverConfigModel.getDefaultMqttQos())
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
package com.muyu.web.domain;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/12
|
||||
* @Description: 用户信息
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class UserInfo {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String userName;
|
||||
/**
|
||||
* 用户密码
|
||||
*/
|
||||
private String password;
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
private String tenantId;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
}
|
|
@ -1,9 +1,11 @@
|
|||
package com.muyu.web.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.muyu.web.utils.VehicleUtils;
|
||||
import com.muyu.vehicle.VehicleInstance;
|
||||
import com.muyu.vehicle.model.VehicleData;
|
||||
import com.muyu.web.utils.VehicleUtils;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
@ -11,7 +13,6 @@ import lombok.NoArgsConstructor;
|
|||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* @author DongZeLiang
|
||||
|
@ -23,33 +24,14 @@ import java.util.function.Supplier;
|
|||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@TableName("vehicle_info")
|
||||
public class VehicleInfo {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId(
|
||||
value = "id",
|
||||
type = IdType.AUTO
|
||||
)
|
||||
private Long id;
|
||||
@TableName("vehicle")
|
||||
public class Vehicle {
|
||||
|
||||
/**
|
||||
* VIN
|
||||
*/
|
||||
@TableId(value = "vin")
|
||||
private String vin;
|
||||
/**
|
||||
* VIN
|
||||
*/
|
||||
@TableField(value = "tenant_id", fill = FieldFill.INSERT)
|
||||
private String tenantId;
|
||||
|
||||
/**
|
||||
* 报文模板
|
||||
*/
|
||||
@TableField("message_template_id")
|
||||
private Long messageTemplateId;
|
||||
|
||||
/**
|
||||
* 电池剩余电量
|
||||
|
@ -63,18 +45,6 @@ public class VehicleInfo {
|
|||
@TableField("battery_level")
|
||||
private BigDecimal batteryLevel;
|
||||
|
||||
/**
|
||||
* 上一次经度
|
||||
*/
|
||||
@TableField("last_longitude")
|
||||
private String lastLongitude;
|
||||
|
||||
/**
|
||||
* 上一次维度
|
||||
*/
|
||||
@TableField("last_latitude")
|
||||
private String lastLatitude;
|
||||
|
||||
/**
|
||||
* 总里程
|
||||
*/
|
||||
|
@ -84,27 +54,25 @@ public class VehicleInfo {
|
|||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(value = "create_time", fill = FieldFill.INSERT)
|
||||
@TableField("create_time")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 生成车辆数据
|
||||
* @param messageTemplateId 报文ID
|
||||
* @return 车辆数据
|
||||
*/
|
||||
public static VehicleInfo gen(Supplier<Long> messageTemplateId) {
|
||||
return VehicleInfo.create(VehicleUtils.genVin(), messageTemplateId);
|
||||
public static Vehicle gen() {
|
||||
return Vehicle.create(VehicleUtils.genVin());
|
||||
|
||||
}
|
||||
/**
|
||||
* 生成车辆数据
|
||||
* @return 车辆数据
|
||||
*/
|
||||
public static VehicleInfo create(String vin, Supplier<Long> messageTemplateId) {
|
||||
public static Vehicle create(String vin) {
|
||||
BigDecimal battery = VehicleUtils.genBattery();
|
||||
return VehicleInfo.builder()
|
||||
return Vehicle.builder()
|
||||
.vin(vin)
|
||||
.messageTemplateId(messageTemplateId.get())
|
||||
.createTime(new Date())
|
||||
.batteryLevel(battery)
|
||||
.remainingBattery(battery)
|
||||
|
@ -113,9 +81,9 @@ public class VehicleInfo {
|
|||
|
||||
}
|
||||
|
||||
public static VehicleInfo instanceBuild (VehicleInstance vehicleInstance) {
|
||||
public static Vehicle instanceBuild (VehicleInstance vehicleInstance) {
|
||||
VehicleData vehicle = vehicleInstance.getVehicleData();
|
||||
return VehicleInfo.builder()
|
||||
return Vehicle.builder()
|
||||
.vin(vehicleInstance.getVin())
|
||||
.remainingBattery(vehicle.getRemainingBattery())
|
||||
.totalMileage(vehicle.getMileage())
|
|
@ -1,6 +1,6 @@
|
|||
package com.muyu.web.domain.model;
|
||||
|
||||
import com.muyu.system.properties.ServerConfigProperties;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.muyu.web.domain.ServerConfig;
|
||||
import com.muyu.web.domain.req.ServerConfigEditReq;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
@ -31,7 +31,7 @@ public class ServerConfigModel {
|
|||
/**
|
||||
* 负载地址
|
||||
*/
|
||||
private String uri;
|
||||
private String loadUrl;
|
||||
/**
|
||||
* 默认MQTT地址
|
||||
*/
|
||||
|
@ -49,7 +49,7 @@ public class ServerConfigModel {
|
|||
return builder()
|
||||
.host(serverConfig.getHost().trim())
|
||||
.port(serverConfig.getPort())
|
||||
.uri(serverConfig.getUri().trim())
|
||||
.loadUrl(serverConfig.getLoadUrl().trim())
|
||||
.defaultMqttAddr(serverConfig.getDefaultMqttAddr().trim())
|
||||
.defaultMqttTopic(serverConfig.getDefaultMqttTopic().trim())
|
||||
.defaultMqttQos(serverConfig.getDefaultMqttQos())
|
||||
|
@ -60,21 +60,10 @@ public class ServerConfigModel {
|
|||
return builder()
|
||||
.host(serverConfigReq.getHost().trim())
|
||||
.port(serverConfigReq.getPort())
|
||||
.uri(serverConfigReq.getUri().trim())
|
||||
.loadUrl(serverConfigReq.getLoadUrl().trim())
|
||||
.defaultMqttAddr(serverConfigReq.getDefaultMqttAddr().trim())
|
||||
.defaultMqttTopic(serverConfigReq.getDefaultMqttTopic().trim())
|
||||
.defaultMqttQos(serverConfigReq.getDefaultMqttQos())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static ServerConfigModel serverConfigPropertiesBuild (ServerConfigProperties serverConfigProperties) {
|
||||
return builder()
|
||||
.host(serverConfigProperties.getHost().trim())
|
||||
.port(serverConfigProperties.getPort())
|
||||
.uri(serverConfigProperties.getUri().trim())
|
||||
.defaultMqttAddr(serverConfigProperties.getMqttAddr().trim())
|
||||
.defaultMqttTopic(serverConfigProperties.getMqttTopic().trim())
|
||||
.defaultMqttQos(serverConfigProperties.getMqttQos())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
package com.muyu.web.domain.req;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/18
|
||||
* @Description: 保存报文请求对象
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MessageTemplateSaveReq {
|
||||
|
||||
/**
|
||||
* 报文名称
|
||||
*/
|
||||
private String messageName;
|
||||
|
||||
/**
|
||||
* 报文描述
|
||||
*/
|
||||
private String description;
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
package com.muyu.web.domain.req;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/19
|
||||
* @Description: 报文模板值保存请求对象
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MessageTemplateValueSaveReq {
|
||||
|
||||
/**
|
||||
* 报文类别
|
||||
*/
|
||||
private String category;
|
||||
/**
|
||||
* 报文编码
|
||||
*/
|
||||
private String code;
|
||||
/**
|
||||
* 报文标签
|
||||
*/
|
||||
private String label;
|
||||
|
||||
/**
|
||||
* 报文长度
|
||||
*/
|
||||
private Integer length;
|
||||
|
||||
/**
|
||||
* 报文起始位置
|
||||
*/
|
||||
private Integer startLocation;
|
||||
/**
|
||||
* 报文终止位置
|
||||
*/
|
||||
private Integer endLocation;
|
||||
/**
|
||||
* 数据类型
|
||||
*/
|
||||
private String valueType;
|
||||
/**
|
||||
* 表达式
|
||||
*/
|
||||
private String elValue;
|
||||
/**
|
||||
* 固定值
|
||||
*/
|
||||
private String fixedValue;
|
||||
/**
|
||||
* 数据最小范围
|
||||
*/
|
||||
private Double minValue;
|
||||
/**
|
||||
* 数据最大范围
|
||||
*/
|
||||
private Double maxValue;
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package com.muyu.web.domain.req;
|
||||
|
||||
import com.muyu.web.domain.model.ServerConfigModel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
@ -28,7 +29,7 @@ public class ServerConfigEditReq {
|
|||
/**
|
||||
* 负载地址
|
||||
*/
|
||||
private String uri;
|
||||
private String loadUrl;
|
||||
/**
|
||||
* 默认MQTT地址
|
||||
*/
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
package com.muyu.web.domain.req;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/12
|
||||
* @Description: 用户登录请求对象
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class UserLoginReq {
|
||||
|
||||
/**
|
||||
* 用户名称
|
||||
*/
|
||||
@NotEmpty(message = "请输入用户名称")
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
@NotEmpty(message = "请输入用户密码")
|
||||
private String password;
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
package com.muyu.web.domain.req;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/12
|
||||
* @Description: 用户注册请求对象
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class UserRegReq {
|
||||
|
||||
/**
|
||||
* 用户名称
|
||||
*/
|
||||
@NotEmpty(message = "请输入用户名称")
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
@NotEmpty(message = "请输入用户密码")
|
||||
private String password;
|
||||
}
|
|
@ -5,8 +5,6 @@ import lombok.Builder;
|
|||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author DongZl
|
||||
* @description: 车辆添加
|
||||
|
@ -21,10 +19,5 @@ public class VehicleCreateAddReq {
|
|||
/**
|
||||
* 车辆添加VIN
|
||||
*/
|
||||
private List<String> vinList;
|
||||
|
||||
/**
|
||||
* 报文模板
|
||||
*/
|
||||
private Long messageTemplateId;
|
||||
private String vinStr;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.muyu.web.domain.resp;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.muyu.web.domain.model.ServerConfigModel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
|
@ -29,7 +30,7 @@ public class ServerConfigResp {
|
|||
/**
|
||||
* 负载地址
|
||||
*/
|
||||
private String uri;
|
||||
private String loadUrl;
|
||||
/**
|
||||
* 默认MQTT地址
|
||||
*/
|
||||
|
@ -48,7 +49,7 @@ public class ServerConfigResp {
|
|||
return builder()
|
||||
.host(serverConfigModel.getHost())
|
||||
.port(serverConfigModel.getPort())
|
||||
.uri(serverConfigModel.getUri())
|
||||
.loadUrl(serverConfigModel.getLoadUrl())
|
||||
.defaultMqttAddr(serverConfigModel.getDefaultMqttAddr())
|
||||
.defaultMqttTopic(serverConfigModel.getDefaultMqttTopic())
|
||||
.defaultMqttQos(serverConfigModel.getDefaultMqttQos())
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
package com.muyu.web.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.muyu.web.domain.MessageTemplate;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/6/10
|
||||
* @Description: 报文模板Mapper
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Mapper
|
||||
public interface MessageTemplateMapper extends BaseMapper<MessageTemplate> {
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package com.muyu.web.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.muyu.web.domain.MessageTemplateValue;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/6/10
|
||||
* @Description: 报文模板值配置Mapper
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Mapper
|
||||
public interface MessageTemplateValueMapper extends BaseMapper<MessageTemplateValue> {
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package com.muyu.web.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.muyu.web.domain.UserInfo;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/12
|
||||
* @Description: 用户持久层
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Mapper
|
||||
public interface UserInfoMapper extends BaseMapper<UserInfo> {
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package com.muyu.web.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.muyu.web.domain.VehicleInfo;
|
||||
import com.muyu.web.domain.Vehicle;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
|
@ -13,6 +13,6 @@ import org.apache.ibatis.annotations.Mapper;
|
|||
* @since 2022-07-05
|
||||
*/
|
||||
@Mapper
|
||||
public interface VehicleInfoMapper extends BaseMapper<VehicleInfo> {
|
||||
public interface VehicleMapper extends BaseMapper<Vehicle> {
|
||||
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
package com.muyu.web.service;
|
||||
|
||||
import com.muyu.web.domain.req.MessageTemplateSaveReq;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/20
|
||||
* @Description: 报文业务层
|
||||
* @Version: 1.0
|
||||
*/
|
||||
public interface MessageService {
|
||||
|
||||
/**
|
||||
* 保存报文模板
|
||||
* @param messageTemplateSaveReq 报文模板保存请求对象
|
||||
*/
|
||||
void saveMessageTemplate (MessageTemplateSaveReq messageTemplateSaveReq);
|
||||
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
package com.muyu.web.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.muyu.web.domain.MessageTemplate;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024-9-18
|
||||
* @Description: 报文模板业务层
|
||||
* @Version: 1.0
|
||||
*/
|
||||
public interface MessageTemplateService extends IService<MessageTemplate> {
|
||||
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package com.muyu.web.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.muyu.web.domain.MessageTemplateValue;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024-9-18
|
||||
* @Description: 报文模板值业务层
|
||||
* @Version: 1.0
|
||||
*/
|
||||
public interface MessageTemplateValueService extends IService<MessageTemplateValue> {
|
||||
|
||||
/**
|
||||
* 通过报文模板ID获取报文值集合
|
||||
* @param msgId 模板ID
|
||||
* @return 报文值集合
|
||||
*/
|
||||
List<MessageTemplateValue> valueListByMsgId (Long msgId);
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package com.muyu.web.service;
|
||||
|
||||
import com.muyu.system.domain.LoginUserInfo;
|
||||
import com.muyu.web.domain.req.UserRegReq;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/12
|
||||
* @Description: 授权业务层
|
||||
* @Version: 1.0
|
||||
*/
|
||||
public interface SystemAuthService {
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
* @param userName 用户名称
|
||||
* @param password 用户密码
|
||||
* @return 生成令牌
|
||||
*/
|
||||
String login (String userName, String password);
|
||||
|
||||
/**
|
||||
* 用户登出
|
||||
*/
|
||||
void logout ();
|
||||
|
||||
/**
|
||||
* 获取登录用户信息
|
||||
* @return 登录用户信息
|
||||
*/
|
||||
LoginUserInfo info ();
|
||||
|
||||
/**
|
||||
* 用户注册
|
||||
* @param userRegReq 用户注册请求
|
||||
*/
|
||||
void reg (UserRegReq userRegReq);
|
||||
}
|
|
@ -1,9 +1,10 @@
|
|||
package com.muyu.web.service;
|
||||
|
||||
import com.muyu.web.common.PageList;
|
||||
import com.muyu.web.domain.VehicleInfo;
|
||||
import com.muyu.web.domain.Vehicle;
|
||||
import com.muyu.web.domain.req.CheckPositionReq;
|
||||
import com.muyu.web.domain.req.GearReq;
|
||||
import com.muyu.web.domain.req.MsgReq;
|
||||
import com.muyu.web.domain.req.VehicleInstanceListReq;
|
||||
import com.muyu.web.domain.resp.VehicleInstanceResp;
|
||||
|
||||
|
@ -17,9 +18,9 @@ public interface VehicleInstanceService {
|
|||
|
||||
/**
|
||||
* 根据车辆生成车辆实例
|
||||
* @param vehicleInfo 车辆信息
|
||||
* @param vehicle 车辆信息
|
||||
*/
|
||||
public void init(VehicleInfo vehicleInfo);
|
||||
public void init(Vehicle vehicle);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -35,7 +36,7 @@ public interface VehicleInstanceService {
|
|||
* 车辆客户端初始化
|
||||
* @param vin vin
|
||||
*/
|
||||
void vehicleClientStart (String vin);
|
||||
void vehicleClientInit (String vin);
|
||||
|
||||
/**
|
||||
* 车辆客户端关闭
|
||||
|
@ -49,6 +50,12 @@ public interface VehicleInstanceService {
|
|||
*/
|
||||
void checkPosition (CheckPositionReq checkPositionReq);
|
||||
|
||||
/**
|
||||
* 车辆消息操作
|
||||
* @param msgReq
|
||||
*/
|
||||
void msg (MsgReq msgReq);
|
||||
|
||||
/**
|
||||
* 设置档位
|
||||
* @param gearReq
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package com.muyu.web.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.muyu.web.domain.VehicleInfo;
|
||||
|
||||
import java.util.List;
|
||||
import com.muyu.web.domain.Vehicle;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
|
@ -13,23 +11,19 @@ import java.util.List;
|
|||
* @author DongZeLiang
|
||||
* @since 2022-07-05
|
||||
*/
|
||||
public interface VehicleInfoService extends IService<VehicleInfo> {
|
||||
public interface VehicleService extends IService<Vehicle> {
|
||||
|
||||
/**
|
||||
* 根据数量生成测试车辆
|
||||
*
|
||||
* @param sum 数量
|
||||
* @param messageTemplateId
|
||||
* @param sum 数量
|
||||
*/
|
||||
void generate(Integer sum, Long messageTemplateId);
|
||||
void generate(Integer sum);
|
||||
|
||||
/**
|
||||
* 创建IVN
|
||||
*
|
||||
* @param vinList VIN 集合
|
||||
* @param messageTemplateId 模板ID
|
||||
* @param vinStr VIN
|
||||
*/
|
||||
void create (List<String> vinList, Long messageTemplateId);
|
||||
void create (String vinStr);
|
||||
|
||||
/**
|
||||
* 同步数据库
|
|
@ -1,44 +0,0 @@
|
|||
package com.muyu.web.service.impl;
|
||||
|
||||
import com.muyu.system.enums.MessageTemplateValueType;
|
||||
import com.muyu.web.domain.MessageTemplate;
|
||||
import com.muyu.web.domain.MessageTemplateValue;
|
||||
import com.muyu.web.domain.req.MessageTemplateSaveReq;
|
||||
import com.muyu.web.service.MessageService;
|
||||
import com.muyu.web.service.MessageTemplateService;
|
||||
import com.muyu.web.service.MessageTemplateValueService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/20
|
||||
* @Description: 报文业务实现层
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Service
|
||||
public class MessageServiceImpl implements MessageService {
|
||||
|
||||
@Autowired
|
||||
private MessageTemplateService messageTemplateService;
|
||||
|
||||
@Autowired
|
||||
private MessageTemplateValueService messageTemplateValueService;
|
||||
|
||||
/**
|
||||
* 保存报文模板
|
||||
*
|
||||
* @param messageTemplateSaveReq 报文模板保存请求对象
|
||||
*/
|
||||
@Override
|
||||
public void saveMessageTemplate (MessageTemplateSaveReq messageTemplateSaveReq) {
|
||||
MessageTemplate messageTemplate = MessageTemplate.builder().messageName(messageTemplateSaveReq.getMessageName()).description(messageTemplateSaveReq.getDescription()).build();
|
||||
messageTemplateService.save(messageTemplate);
|
||||
messageTemplateValueService.saveBatch(new ArrayList<>() {{
|
||||
add(MessageTemplateValue.builder().messageId(messageTemplate.getId()).code("vin").label("VIN").category("base").length(17).startLocation(1).endLocation(17).valueType(MessageTemplateValueType.EL.code()).elValue("this.vin").build());
|
||||
add(MessageTemplateValue.builder().messageId(messageTemplate.getId()).code("timeMillis").label("报文采集毫秒").category("base").length(13).startLocation(18).endLocation(30).valueType(MessageTemplateValueType.EL.code()).elValue("this.timeMillis").build());
|
||||
}});
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
package com.muyu.web.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.muyu.web.domain.MessageTemplate;
|
||||
import com.muyu.web.mapper.MessageTemplateMapper;
|
||||
import com.muyu.web.service.MessageTemplateService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/18
|
||||
* @Description: 报文模板实现类
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Service
|
||||
public class MessageTemplateServiceImpl
|
||||
extends ServiceImpl<MessageTemplateMapper, MessageTemplate>
|
||||
implements MessageTemplateService {
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package com.muyu.web.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.muyu.web.domain.MessageTemplateValue;
|
||||
import com.muyu.web.mapper.MessageTemplateValueMapper;
|
||||
import com.muyu.web.service.MessageTemplateValueService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/18
|
||||
* @Description: 报文模板值业务实现层
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Service
|
||||
public class MessageTemplateValueServiceImpl
|
||||
extends ServiceImpl<MessageTemplateValueMapper, MessageTemplateValue>
|
||||
implements MessageTemplateValueService {
|
||||
/**
|
||||
* 通过报文模板ID获取报文值集合
|
||||
*
|
||||
* @param msgId 模板ID
|
||||
*
|
||||
* @return 报文值集合
|
||||
*/
|
||||
@Override
|
||||
public List<MessageTemplateValue> valueListByMsgId (Long msgId) {
|
||||
return this.list(
|
||||
new LambdaQueryWrapper<>(){{
|
||||
this.eq(MessageTemplateValue::getMessageId, msgId);
|
||||
}}
|
||||
);
|
||||
}
|
||||
}
|
|
@ -4,6 +4,8 @@ import com.muyu.vehicle.VehicleInstance;
|
|||
import com.muyu.vehicle.core.LocalContainer;
|
||||
import com.muyu.web.domain.model.OverviewModel;
|
||||
import com.muyu.web.service.OverviewService;
|
||||
import com.muyu.web.service.VehicleInstanceService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collection;
|
||||
|
@ -25,7 +27,7 @@ public class OverviewServiceImpl implements OverviewService {
|
|||
@Override
|
||||
public OverviewModel overview () {
|
||||
// 车辆实例对象
|
||||
Collection<VehicleInstance> instanceList = LocalContainer.getTenantVehicleDataMap().values();
|
||||
Collection<VehicleInstance> instanceList = LocalContainer.vehicleDataMap.values();
|
||||
|
||||
|
||||
return OverviewModel.builder()
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package com.muyu.web.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.muyu.system.handle.SystemHandler;
|
||||
import com.muyu.system.properties.ServerConfigProperties;
|
||||
import com.muyu.web.config.LoadServerConfig;
|
||||
import com.muyu.web.config.properties.ServiceConfigProperties;
|
||||
import com.muyu.web.domain.ServerConfig;
|
||||
import com.muyu.web.domain.model.ServerConfigModel;
|
||||
import com.muyu.web.service.ServerConfigService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
|
@ -18,6 +18,12 @@ import org.springframework.stereotype.Service;
|
|||
*/
|
||||
@Service
|
||||
public class ServerConfigServiceImpl extends ServiceImpl<BaseMapper<ServerConfig>, ServerConfig> implements ServerConfigService {
|
||||
|
||||
/**
|
||||
* 配置Key
|
||||
*/
|
||||
private final Integer key = 1;
|
||||
|
||||
/**
|
||||
* 获取配置模型
|
||||
*
|
||||
|
@ -25,7 +31,8 @@ public class ServerConfigServiceImpl extends ServiceImpl<BaseMapper<ServerConfig
|
|||
*/
|
||||
@Override
|
||||
public ServerConfigModel get () {
|
||||
return ServerConfigModel.serverConfigPropertiesBuild(SystemHandler.getServerConfig());
|
||||
ServerConfig serverConfig = getById(key);
|
||||
return ServerConfigModel.serverConfigBuild(serverConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -35,11 +42,8 @@ public class ServerConfigServiceImpl extends ServiceImpl<BaseMapper<ServerConfig
|
|||
*/
|
||||
@Override
|
||||
public void edit (ServerConfigModel serverConfigModel) {
|
||||
|
||||
ServerConfig serverConfig = ServerConfig.modeBuild(serverConfigModel, SystemHandler::getUserId);
|
||||
update(serverConfig, new UpdateWrapper<>());
|
||||
SystemHandler.setServerConfig(
|
||||
ServerConfigProperties.modelToProperties(serverConfigModel)
|
||||
);
|
||||
ServerConfig serverConfig = ServerConfig.modeBuild(serverConfigModel, () -> key);
|
||||
updateById(serverConfig);
|
||||
LoadServerConfig.modelToProperties(serverConfigModel);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,162 +0,0 @@
|
|||
package com.muyu.web.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.muyu.config.tenant.CustomTenantHandler;
|
||||
import com.muyu.system.constants.SecurityConstants;
|
||||
import com.muyu.system.domain.LoginUserInfo;
|
||||
import com.muyu.system.handle.SystemHandler;
|
||||
import com.muyu.system.properties.ServerConfigProperties;
|
||||
import com.muyu.utils.IdUtils;
|
||||
import com.muyu.utils.JwtUtils;
|
||||
import com.muyu.web.domain.PositionRouteInfo;
|
||||
import com.muyu.web.domain.ServerConfig;
|
||||
import com.muyu.web.domain.UserInfo;
|
||||
import com.muyu.web.domain.req.UserRegReq;
|
||||
import com.muyu.web.mapper.UserInfoMapper;
|
||||
import com.muyu.web.service.PositionRouteService;
|
||||
import com.muyu.web.service.ServerConfigService;
|
||||
import com.muyu.web.service.SystemAuthService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author: DongZeLiang
|
||||
* @date: 2024/9/12
|
||||
* @Description: 系统认证业务层
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Service
|
||||
public class SystemAuthServiceImpl implements SystemAuthService {
|
||||
|
||||
@Autowired
|
||||
private UserInfoMapper userInfoMapper;
|
||||
|
||||
@Autowired
|
||||
private ServerConfigService serverConfigService;
|
||||
|
||||
@Resource( name = "loginUserCache")
|
||||
private Cache<String, LoginUserInfo> loginUserInfoCache;
|
||||
|
||||
@Autowired
|
||||
private CustomTenantHandler customTenantHandler;
|
||||
|
||||
@Autowired
|
||||
private PositionRouteService positionRouteService;
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
*
|
||||
* @param userName 用户名称
|
||||
* @param password 用户密码
|
||||
*
|
||||
* @return 生成令牌
|
||||
*/
|
||||
@Override
|
||||
public String login (String userName, String password) {
|
||||
LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(UserInfo::getUserName, userName);
|
||||
queryWrapper.eq(UserInfo::getPassword, password);
|
||||
List<UserInfo> userInfoList = userInfoMapper.selectList(queryWrapper);
|
||||
if (userInfoList.isEmpty()){
|
||||
throw new RuntimeException("用户用户名或者密码错误");
|
||||
}
|
||||
UserInfo userInfo = userInfoList.get(0);
|
||||
LambdaQueryWrapper<ServerConfig> serverConfigQueryWrapper = new LambdaQueryWrapper<>();
|
||||
serverConfigQueryWrapper.eq(ServerConfig::getTenantId, userInfo.getTenantId());
|
||||
customTenantHandler.ignore();
|
||||
ServerConfig serverConfig = serverConfigService.getOne(serverConfigQueryWrapper);
|
||||
customTenantHandler.remove();
|
||||
LoginUserInfo loginUserInfo = LoginUserInfo.builder()
|
||||
.id(userInfo.getId())
|
||||
.tenantId(userInfo.getTenantId())
|
||||
.userName(userInfo.getUserName())
|
||||
.serverConfig(
|
||||
ServerConfigProperties.configToProperties(serverConfig)
|
||||
)
|
||||
.build();
|
||||
|
||||
String userKey = IdUtils.fastUUID();
|
||||
loginUserInfo.setUserKey(userKey);
|
||||
loginUserInfoCache.put(userKey, loginUserInfo);
|
||||
// Jwt存储信息
|
||||
Map<String, Object> claimsMap = new HashMap<String, Object>();
|
||||
claimsMap.put(SecurityConstants.USER_KEY, userKey);
|
||||
claimsMap.put(SecurityConstants.DETAILS_USER_ID, userInfo.getId());
|
||||
claimsMap.put(SecurityConstants.DETAILS_USERNAME, userName);
|
||||
|
||||
return JwtUtils.createToken(claimsMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户登出
|
||||
*/
|
||||
@Override
|
||||
public void logout () {
|
||||
loginUserInfoCache.invalidate(SystemHandler.getUserKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录用户信息
|
||||
*
|
||||
* @return 登录用户信息
|
||||
*/
|
||||
@Override
|
||||
public LoginUserInfo info () {
|
||||
return SystemHandler.getUserInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户注册
|
||||
*
|
||||
* @param userRegReq 用户注册请求
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void reg (UserRegReq userRegReq) {
|
||||
LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(UserInfo::getUserName, userRegReq.getUserName());
|
||||
Long selectCount = userInfoMapper.selectCount(queryWrapper);
|
||||
if (!selectCount.equals(0L)){
|
||||
throw new RuntimeException("用户名称重复,请重新输入");
|
||||
}
|
||||
UserInfo userInfo = UserInfo.builder()
|
||||
.userName(userRegReq.getUserName())
|
||||
.password(userRegReq.getPassword())
|
||||
.createTime(new Date())
|
||||
.tenantId("TX_" + IdUtils.simpleUUID().substring(0, 10).toUpperCase())
|
||||
.build();
|
||||
this.userInfoMapper.insert(userInfo);
|
||||
|
||||
customTenantHandler.ignore();
|
||||
LambdaQueryWrapper<PositionRouteInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
lambdaQueryWrapper.eq(PositionRouteInfo::getTenantId, "TX_8689BE3CDB");
|
||||
List<PositionRouteInfo> positionRouteInfoList = positionRouteService.list(lambdaQueryWrapper);
|
||||
|
||||
for (PositionRouteInfo positionRouteInfo : positionRouteInfoList) {
|
||||
positionRouteInfo.setId(null);
|
||||
positionRouteInfo.setTenantId(userInfo.getTenantId());
|
||||
}
|
||||
positionRouteService.saveBatch(positionRouteInfoList);
|
||||
serverConfigService.save(
|
||||
ServerConfig.builder()
|
||||
.tenantId(userInfo.getTenantId())
|
||||
.host("127.0.0.1")
|
||||
.port("81")
|
||||
.uri("/verify/vehicleConnection")
|
||||
.defaultMqttAddr("127.0.0.1")
|
||||
.defaultMqttTopic("vehicle")
|
||||
.defaultMqttQos(1)
|
||||
.build()
|
||||
);
|
||||
customTenantHandler.remove();
|
||||
|
||||
}
|
||||
}
|
|
@ -3,11 +3,10 @@ package com.muyu.web.service.impl;
|
|||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.muyu.system.handle.SystemHandler;
|
||||
import com.muyu.web.domain.VehicleInfo;
|
||||
import com.muyu.web.mapper.VehicleInfoMapper;
|
||||
import com.muyu.web.domain.Vehicle;
|
||||
import com.muyu.web.mapper.VehicleMapper;
|
||||
import com.muyu.web.service.VehicleInstanceService;
|
||||
import com.muyu.web.service.VehicleInfoService;
|
||||
import com.muyu.web.service.VehicleService;
|
||||
import com.muyu.vehicle.VehicleInstance;
|
||||
import com.muyu.vehicle.core.LocalContainer;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
|
@ -31,7 +30,7 @@ import java.util.stream.Stream;
|
|||
*/
|
||||
@Log4j2
|
||||
@Service
|
||||
public class VechileInfoServiceImpl extends ServiceImpl<VehicleInfoMapper, VehicleInfo> implements VehicleInfoService {
|
||||
public class VechileServiceImpl extends ServiceImpl<VehicleMapper, Vehicle> implements VehicleService {
|
||||
|
||||
|
||||
@Autowired
|
||||
|
@ -40,37 +39,32 @@ public class VechileInfoServiceImpl extends ServiceImpl<VehicleInfoMapper, Vehic
|
|||
/**
|
||||
* 根据数量生成测试车辆
|
||||
*
|
||||
* @param sum 数量
|
||||
* @param messageTemplateId
|
||||
* @param sum 数量
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void generate (Integer sum, Long messageTemplateId) {
|
||||
List<VehicleInfo> vehicleInfoList =
|
||||
Stream.generate(() -> VehicleInfo.gen(() -> messageTemplateId == null ? 0 : messageTemplateId))
|
||||
.limit(sum)
|
||||
.toList();
|
||||
this.saveBatch(vehicleInfoList);
|
||||
vehicleInfoList.forEach(vehicleInstanceService::init);
|
||||
public void generate (Integer sum) {
|
||||
List<Vehicle> vehicleList = Stream.generate(Vehicle::gen).limit(sum).toList();
|
||||
this.saveBatch(vehicleList);
|
||||
vehicleList.forEach(vehicleInstanceService::init);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建IVN
|
||||
*
|
||||
* @param vinStr VIN
|
||||
* @param messageTemplateId 报文模板
|
||||
* @param vinStr VIN
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public void create (List<String> vinList, Long messageTemplateId) {
|
||||
public void create (String vinStr) {
|
||||
String[] vinList = vinStr.split("\n");
|
||||
StringBuilder errorMsg = new StringBuilder();
|
||||
for (String vin : vinList) {
|
||||
if (vin.length() != 17) {
|
||||
errorMsg.append("vin[").append(vin).append("]").append("不为17位\n");
|
||||
} else {
|
||||
LambdaQueryWrapper<VehicleInfo> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(VehicleInfo::getVin, vin);
|
||||
queryWrapper.eq(VehicleInfo::getTenantId, SystemHandler.getTenantId());
|
||||
LambdaQueryWrapper<Vehicle> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(Vehicle::getVin, vin);
|
||||
long count = this.count(queryWrapper);
|
||||
if (count == 1) {
|
||||
errorMsg.append("vin[").append(vin).append("]").append("已经存在\n");
|
||||
|
@ -80,11 +74,9 @@ public class VechileInfoServiceImpl extends ServiceImpl<VehicleInfoMapper, Vehic
|
|||
if (!errorMsg.isEmpty()) {
|
||||
throw new RuntimeException(errorMsg.toString());
|
||||
}
|
||||
List<VehicleInfo> vehicleInfoList = vinList.stream()
|
||||
.map((String vin) -> VehicleInfo.create(vin, () -> messageTemplateId == null ? 0 : messageTemplateId))
|
||||
.toList();
|
||||
this.saveBatch(vehicleInfoList);
|
||||
vehicleInfoList.forEach(vehicleInstanceService::init);
|
||||
List<Vehicle> vehicleList = Arrays.stream(vinList).map(Vehicle::create).toList();
|
||||
this.saveBatch(vehicleList);
|
||||
vehicleList.forEach(vehicleInstanceService::init);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -96,18 +88,18 @@ public class VechileInfoServiceImpl extends ServiceImpl<VehicleInfoMapper, Vehic
|
|||
// vehicleInstanceService.isTaskStatus();
|
||||
log.info("同步数据库开始");
|
||||
long startTime = System.currentTimeMillis();
|
||||
Collection<VehicleInstance> vehicleInstanceList = LocalContainer.getTenantOnlineVehicleInstance();
|
||||
Collection<VehicleInstance> vehicleInstanceList = LocalContainer.getOnlineVehicleInstance();
|
||||
// 成功数量
|
||||
AtomicInteger syncSuccessSum = new AtomicInteger();
|
||||
List<VehicleInfo> vehicleInfoList = vehicleInstanceList.stream()
|
||||
List<Vehicle> vehicleList = vehicleInstanceList.stream()
|
||||
.filter(VehicleInstance::isOnline)
|
||||
.map(VehicleInfo::instanceBuild)
|
||||
.map(Vehicle::instanceBuild)
|
||||
.toList();
|
||||
vehicleInfoList.forEach(vehicle -> {
|
||||
LambdaUpdateWrapper<VehicleInfo> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.set(VehicleInfo::getRemainingBattery, vehicle.getRemainingBattery());
|
||||
updateWrapper.set(VehicleInfo::getTotalMileage, vehicle.getTotalMileage());
|
||||
updateWrapper.eq(VehicleInfo::getVin, vehicle.getVin());
|
||||
vehicleList.forEach(vehicle -> {
|
||||
LambdaUpdateWrapper<Vehicle> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.set(Vehicle::getRemainingBattery, vehicle.getRemainingBattery());
|
||||
updateWrapper.set(Vehicle::getTotalMileage, vehicle.getTotalMileage());
|
||||
updateWrapper.eq(Vehicle::getVin, vehicle.getVin());
|
||||
try {
|
||||
this.update(updateWrapper);
|
||||
syncSuccessSum.incrementAndGet();
|
||||
|
@ -117,7 +109,7 @@ public class VechileInfoServiceImpl extends ServiceImpl<VehicleInfoMapper, Vehic
|
|||
}
|
||||
});
|
||||
log.info("同步数据库结束 - 耗时:[{}MS],同步量:[{}辆],成功:[{}辆],失败:[{}辆]",
|
||||
System.currentTimeMillis() - startTime, vehicleInfoList.size(),syncSuccessSum.get(), vehicleInfoList.size() - syncSuccessSum.get());
|
||||
System.currentTimeMillis() - startTime, vehicleList.size(),syncSuccessSum.get(), vehicleList.size() - syncSuccessSum.get());
|
||||
}catch (Exception exception){
|
||||
log.error("数据同步异常:{}", exception.getMessage(), exception);
|
||||
}
|
|
@ -1,7 +1,5 @@
|
|||
package com.muyu.web.service.impl;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.muyu.cache.model.MessageTemplateCacheModel;
|
||||
import com.muyu.vehicle.VehicleInstance;
|
||||
import com.muyu.vehicle.api.ClientAdmin;
|
||||
import com.muyu.vehicle.api.req.VehicleConnectionReq;
|
||||
|
@ -10,18 +8,18 @@ import com.muyu.vehicle.model.VehicleData;
|
|||
import com.muyu.vehicle.model.properties.MqttProperties;
|
||||
import com.muyu.web.common.PageList;
|
||||
import com.muyu.web.common.Result;
|
||||
import com.muyu.web.domain.VehicleInfo;
|
||||
import com.muyu.web.domain.Vehicle;
|
||||
import com.muyu.web.domain.model.MqttServerModel;
|
||||
import com.muyu.web.domain.model.PositionModel;
|
||||
import com.muyu.web.domain.req.CheckPositionReq;
|
||||
import com.muyu.web.domain.req.GearReq;
|
||||
import com.muyu.web.domain.req.MsgReq;
|
||||
import com.muyu.web.domain.req.VehicleInstanceListReq;
|
||||
import com.muyu.web.domain.resp.VehicleInstanceResp;
|
||||
import com.muyu.web.service.PositionRouteService;
|
||||
import com.muyu.web.service.VehicleInstanceService;
|
||||
import com.muyu.web.utils.MD5Util;
|
||||
import com.muyu.web.utils.ReflectUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -30,7 +28,6 @@ import org.springframework.stereotype.Service;
|
|||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
|
@ -49,28 +46,19 @@ public class VehicleInstanceServiceImpl implements VehicleInstanceService {
|
|||
@Autowired
|
||||
private ClientAdmin clientAdmin;
|
||||
|
||||
/**
|
||||
* 报文模板缓存
|
||||
*/
|
||||
@Resource(name = "messageTemplateCache")
|
||||
private Cache<Long, MessageTemplateCacheModel> messageTemplateCache;
|
||||
|
||||
|
||||
/**
|
||||
* 根据车辆生成车辆实例
|
||||
*
|
||||
* @param vehicleInfo 车辆信息
|
||||
* @param vehicle 车辆信息
|
||||
*/
|
||||
@Override
|
||||
public void init(VehicleInfo vehicleInfo) {
|
||||
public void init(Vehicle vehicle) {
|
||||
VehicleInstance vehicleInstance = new VehicleInstance();
|
||||
vehicleInstance.setVehicleInfo(vehicleInfo);
|
||||
vehicleInstance.setVehicleData(VehicleData.vehicleBuild(vehicleInfo));
|
||||
vehicleInstance.setMessageTemplate(
|
||||
messageTemplateCache.get(vehicleInfo.getMessageTemplateId(), messageTemplateId -> MessageTemplateCacheModel.builder().build())
|
||||
);
|
||||
vehicleInstance.setVehicle(vehicle);
|
||||
vehicleInstance.setVehicleData(VehicleData.vehicleBuild(vehicle));
|
||||
LocalContainer.setVehicleInstance(vehicleInstance);
|
||||
log.debug("构建车辆对象: [{}]", vehicleInfo.getVin());
|
||||
log.debug("构建车辆对象: [{}]", vehicle.getVin());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -82,7 +70,7 @@ public class VehicleInstanceServiceImpl implements VehicleInstanceService {
|
|||
*/
|
||||
@Override
|
||||
public PageList<VehicleInstanceResp> queryList (VehicleInstanceListReq vehicleInstanceListReq) {
|
||||
Stream<VehicleInstance> stream = LocalContainer.getTenantVehicleDataMap().values()
|
||||
Stream<VehicleInstance> stream = LocalContainer.vehicleDataMap.values()
|
||||
.stream();
|
||||
if (StringUtils.isNotBlank(vehicleInstanceListReq.getVin())){
|
||||
stream = stream.filter(vehicleInstance ->
|
||||
|
@ -111,7 +99,7 @@ public class VehicleInstanceServiceImpl implements VehicleInstanceService {
|
|||
* @param vin vin
|
||||
*/
|
||||
@Override
|
||||
public void vehicleClientStart (String vin) {
|
||||
public void vehicleClientInit (String vin) {
|
||||
log.info("vin[{}],开始上线", vin);
|
||||
VehicleInstance vehicleInstance = LocalContainer.getVehicleInstance(vin);
|
||||
if (vehicleInstance == null){
|
||||
|
@ -128,9 +116,7 @@ public class VehicleInstanceServiceImpl implements VehicleInstanceService {
|
|||
Result<MqttServerModel> result = clientAdmin.getVehicleLoadAddr(connectionReq);
|
||||
if (result.getCode() != 200){
|
||||
log.error("车辆:[{}],申请上线异常:[{}]", vin, result.getMsg());
|
||||
throw new RuntimeException(
|
||||
String.format("车辆:[%s],申请上线异常:[%s]", vin, result.getMsg())
|
||||
);
|
||||
throw new RuntimeException("远程服务器没有【"+vin+"】车辆");
|
||||
}
|
||||
MqttServerModel mqttServerModel = result.getData();
|
||||
MqttProperties mqttProperties = MqttProperties.builder()
|
||||
|
@ -171,6 +157,27 @@ public class VehicleInstanceServiceImpl implements VehicleInstanceService {
|
|||
vehicleInstance.setPositionCode(checkPositionReq.getPositionCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* 车辆消息操作
|
||||
*
|
||||
* @param msgReq
|
||||
*/
|
||||
@Override
|
||||
public void msg (MsgReq msgReq) {
|
||||
VehicleInstance vehicleInstance = LocalContainer.getVehicleInstance(msgReq.getVin());
|
||||
switch (msgReq.getMsgCode()){
|
||||
case "上报" -> {
|
||||
if(vehicleInstance.getVehicleThread() == null){
|
||||
vehicleInstance.initVehicleThread();
|
||||
}
|
||||
vehicleInstance.startSend();
|
||||
}
|
||||
case "暂停" -> vehicleInstance.pauseSend();
|
||||
case "停止" -> vehicleInstance.stopSend();
|
||||
default -> throw new RuntimeException("车辆消息事件错误");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置档位
|
||||
*
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.muyu.vehicle.core.LocalContainer;
|
|||
import com.muyu.web.domain.PositionRouteInfo;
|
||||
import com.muyu.web.domain.model.PositionModel;
|
||||
import com.muyu.web.domain.model.TaskModel;
|
||||
import com.muyu.web.domain.req.MsgReq;
|
||||
import com.muyu.web.domain.resp.UnifiedTaskResp;
|
||||
import com.muyu.web.service.PositionRouteService;
|
||||
import com.muyu.web.service.VehicleInstanceService;
|
||||
|
@ -50,7 +51,7 @@ public class VehicleUnifiedServiceImpl implements VehicleUnifiedService {
|
|||
.map(VehicleInstance::getVin)
|
||||
.toList();
|
||||
taskModel.submit("一键上线", vinList, (vin) -> {
|
||||
vehicleInstanceService.vehicleClientStart(vin);
|
||||
vehicleInstanceService.vehicleClientInit(vin);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -95,6 +96,12 @@ public class VehicleUnifiedServiceImpl implements VehicleUnifiedService {
|
|||
vehicleInstance.setPositionCode(positionCode);
|
||||
// 设置车辆档位
|
||||
vehicleInstance.setGear("D");
|
||||
vehicleInstanceService.msg(
|
||||
MsgReq.builder()
|
||||
.vin(vin)
|
||||
.msgCode("上报")
|
||||
.build()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -136,6 +143,12 @@ public class VehicleUnifiedServiceImpl implements VehicleUnifiedService {
|
|||
// 获取在线车辆VIN
|
||||
List<String> vinList = LocalContainer.getOnlineVehicleVin();
|
||||
taskModel.submit("一键取消上报", vinList, (vin) -> {
|
||||
vehicleInstanceService.msg(
|
||||
MsgReq.builder()
|
||||
.vin(vin)
|
||||
.msgCode("停止")
|
||||
.build()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,23 +1,36 @@
|
|||
server:
|
||||
port: 9865
|
||||
port: 81
|
||||
spring:
|
||||
main:
|
||||
allow-circular-references: true
|
||||
mvc:
|
||||
static-path-pattern: /static/**
|
||||
# 数据源配置
|
||||
|
||||
datasource:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: 2ZitL3jpzknSZrWv7sXHKxVrqb6a+IESAbAQ7JPw71zjt+9oPTC40vnZ6ocXjW6/m8uUerZINCQtVyBbz0GFI8ycOxuM9zgxLswJu1P/yW2crEvrVXA2Fu4v1c9bWpZ1cWRBXhYq1VYu/nYAetZuTaX9WVgzLwClczrZjMT8kJVleiDsvZLx6e5z0W9vfzxuGPLpwZpAeBT8QzcVoZaONGPzCcIcSXPysjKvhrPiYoA=
|
||||
username: HskuzU7cEWAMeTvYdlc4yg==
|
||||
password: 4ULjnyG3ZFlyKeCCT6hySw==
|
||||
name: vehicle-test-db
|
||||
generate-unique-name: false
|
||||
username: muyu
|
||||
password: 123456
|
||||
# 如果需要数据本地化,则改成 file 方式
|
||||
# jdbc:h2:mem:testDB;DB_CLOSE_DELAY=-1
|
||||
url: jdbc:h2:file:./db/vehicleSimulationDataBaseFile;AUTO_SERVER=TRUE;DB_CLOSE_DELAY=-1
|
||||
driver-class-name: org.h2.Driver
|
||||
h2:
|
||||
# 开启这个配置就可以通过 web 页面访问了,例如:http://localhost:8080/springboot-h2/h2-console
|
||||
console:
|
||||
enabled: true
|
||||
settings:
|
||||
# 开启h2 console 跟踪 方便调试 默认 false
|
||||
trace: false
|
||||
# 允许console 远程访问 默认false
|
||||
web-allow-others: true
|
||||
# h2 访问路径上下文
|
||||
path: /h2-console
|
||||
|
||||
|
||||
# mybatis-plus 配置
|
||||
mybatis-plus:
|
||||
mapper-locations: classpath*:/com.muyu.mapper/**/*.xml
|
||||
#实体扫描,多个package用逗号或者分号分隔
|
||||
typeAliasesPackage: com.dmo.entity
|
||||
global-config:
|
||||
#数据库相关配置
|
||||
db-config:
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
|||
.box-card[data-v-6151d512]{margin-top:20px}.grid-content[data-v-6151d512]{margin-top:10px;border-radius:4px;overflow-x:hidden;overflow-y:auto}.grid-content[data-v-6151d512]::-webkit-scrollbar{width:4px}.grid-content[data-v-6151d512]::-webkit-scrollbar-thumb{border-radius:10px;background:rgba(0,0,0,.2)}.grid-content[data-v-6151d512]::-webkit-scrollbar-track{border-radius:0;background:rgba(0,0,0,.1)}.el-dialog[data-v-6151d512]{background-color:#fff}
|
|
@ -0,0 +1 @@
|
|||
.app-container[data-v-26d8c57e]{padding:10px 5px 0 10px;background-color:#f4f4f5}.el-row[data-v-26d8c57e]{&:last-child{margin-bottom:0}}.bg-purple[data-v-26d8c57e]{background:#f4f4f5}.grid-content[data-v-26d8c57e]{border-radius:4px;overflow-x:hidden;overflow-y:auto}.grid-content[data-v-26d8c57e]::-webkit-scrollbar{width:4px}.grid-content[data-v-26d8c57e]::-webkit-scrollbar-thumb{border-radius:10px;background:rgba(0,0,0,.2)}.grid-content[data-v-26d8c57e]::-webkit-scrollbar-track{border-radius:0;background:rgba(0,0,0,.1)}.vehicleDiv[data-v-26d8c57e]{height:50px;margin:0 0 10px 0}.contentMain[data-v-26d8c57e]{margin-top:10px}.vehicleDataTab[data-v-26d8c57e]{width:100%;overflow-y:auto;overflow-x:hidden}.vehicleDataTab[data-v-26d8c57e]::-webkit-scrollbar{width:4px}.vehicleDataTab[data-v-26d8c57e]::-webkit-scrollbar-thumb{border-radius:10px;background:rgba(0,0,0,.2)}.vehicleDataTab[data-v-26d8c57e]::-webkit-scrollbar-track{border-radius:0;background:rgba(0,0,0,.1)}.el-form-item__label[data-v-26d8c57e]{padding:0}.el-form-item[data-v-26d8c57e]{margin-bottom:5px}
|
|
@ -1 +0,0 @@
|
|||
.el-col[data-v-7a92ea84]{margin-top:20px}
|
|
@ -0,0 +1 @@
|
|||
@supports(-webkit-mask:none) and (not (cater-color:#fff)){.login-container .el-input input{color:#fff}}.login-container .el-input{display:inline-block;height:47px;width:85%}.login-container .el-input input{background:transparent;border:0;-webkit-appearance:none;border-radius:0;padding:12px 5px 12px 15px;color:#fff;height:47px;caret-color:#fff}.login-container .el-input input:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px #283443 inset!important;box-shadow:inset 0 0 0 1000px #283443!important;-webkit-text-fill-color:#fff!important}.login-container .el-form-item{border:1px solid hsla(0,0%,100%,.1);background:rgba(0,0,0,.1);border-radius:5px;color:#454545}.login-container[data-v-5d9ae9a2]{min-height:100%;width:100%;background-color:#2d3a4b;overflow:hidden}.login-container .login-form[data-v-5d9ae9a2]{position:relative;width:520px;max-width:100%;padding:160px 35px 0;margin:0 auto;overflow:hidden}.login-container .tips[data-v-5d9ae9a2]{font-size:14px;color:#fff;margin-bottom:10px}.login-container .tips span[data-v-5d9ae9a2]:first-of-type{margin-right:16px}.login-container .svg-container[data-v-5d9ae9a2]{padding:6px 5px 6px 15px;color:#889aa4;vertical-align:middle;width:30px;display:inline-block}.login-container .title-container[data-v-5d9ae9a2]{position:relative}.login-container .title-container .title[data-v-5d9ae9a2]{font-size:26px;color:#eee;margin:0 auto 40px auto;text-align:center;font-weight:700}.login-container .show-pwd[data-v-5d9ae9a2]{position:absolute;right:10px;top:7px;font-size:16px;color:#889aa4;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
|
|
@ -1 +0,0 @@
|
|||
.app-container[data-v-2ab19043]{padding:10px 5px 0 10px;background-color:#f4f4f5}.el-row[data-v-2ab19043]{&:last-child{margin-bottom:0}}.bg-purple[data-v-2ab19043]{background:#f4f4f5}.grid-content[data-v-2ab19043]{border-radius:4px;overflow-x:hidden;overflow-y:auto}.grid-content[data-v-2ab19043]::-webkit-scrollbar{width:4px}.grid-content[data-v-2ab19043]::-webkit-scrollbar-thumb{border-radius:10px;background:rgba(0,0,0,.2)}.grid-content[data-v-2ab19043]::-webkit-scrollbar-track{border-radius:0;background:rgba(0,0,0,.1)}.vehicleDiv[data-v-2ab19043]{height:50px;margin:0 0 10px 0}.contentMain[data-v-2ab19043]{margin-top:10px}.vehicleDataTab[data-v-2ab19043]{width:100%;overflow-y:auto;overflow-x:hidden}.vehicleDataTab[data-v-2ab19043]::-webkit-scrollbar{width:4px}.vehicleDataTab[data-v-2ab19043]::-webkit-scrollbar-thumb{border-radius:10px;background:rgba(0,0,0,.2)}.vehicleDataTab[data-v-2ab19043]::-webkit-scrollbar-track{border-radius:0;background:rgba(0,0,0,.1)}.el-form-item__label[data-v-2ab19043]{padding:0}.el-form-item[data-v-2ab19043]{margin-bottom:5px}
|
|
@ -1 +0,0 @@
|
|||
.el-dialog{background-color:#2d3a4b}@supports(-webkit-mask:none) and (not (cater-color:#fff)){.login-container .el-input input{color:#fff}}.login-container .el-input{display:inline-block;height:47px;width:85%}.login-container .el-input input{background:transparent;border:0;-webkit-appearance:none;border-radius:0;padding:12px 5px 12px 15px;color:#fff;height:47px;caret-color:#fff}.login-container .el-input input:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px #283443 inset!important;box-shadow:inset 0 0 0 1000px #283443!important;-webkit-text-fill-color:#fff!important}.login-container .el-form-item{border:1px solid hsla(0,0%,100%,.1);background:rgba(0,0,0,.1);border-radius:5px;color:#454545}.login-container[data-v-7fa60b7a]{min-height:100%;width:100%;background-color:#2d3a4b;overflow:hidden}.login-container .login-form[data-v-7fa60b7a]{position:relative;width:520px;max-width:100%;padding:160px 35px 0;margin:0 auto;overflow:hidden}.login-container .tips[data-v-7fa60b7a]{font-size:14px;color:#fff;margin-bottom:10px}.login-container .tips span[data-v-7fa60b7a]:first-of-type{margin-right:16px}.login-container .svg-container[data-v-7fa60b7a]{padding:6px 5px 6px 15px;color:#889aa4;vertical-align:middle;width:30px;display:inline-block}.login-container .title-container[data-v-7fa60b7a]{position:relative}.login-container .title-container .title[data-v-7fa60b7a]{font-size:26px;color:#eee;margin:0 auto 40px auto;text-align:center;font-weight:700}.login-container .show-pwd[data-v-7fa60b7a]{position:absolute;right:10px;top:7px;font-size:16px;color:#889aa4;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
|
|
@ -0,0 +1 @@
|
|||
.el-col[data-v-1fac6224]{margin-top:20px}
|
|
@ -1 +1 @@
|
|||
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=/favicon.ico><title>车辆</title><link href=/static/css/app.e2ca9161.css rel=preload as=style><link href=/static/css/chunk-elementUI.c1c3b808.css rel=preload as=style><link href=/static/css/chunk-libs.3dfb7769.css rel=preload as=style><link href=/static/js/app.a2f5934b.js rel=preload as=script><link href=/static/js/chunk-elementUI.2491fb2f.js rel=preload as=script><link href=/static/js/chunk-libs.5e39c7d0.js rel=preload as=script><link href=/static/css/chunk-elementUI.c1c3b808.css rel=stylesheet><link href=/static/css/chunk-libs.3dfb7769.css rel=stylesheet><link href=/static/css/app.e2ca9161.css rel=stylesheet></head><body><noscript><strong>We're sorry but 车辆 doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>(function(e){function t(t){for(var r,c,u=t[0],f=t[1],i=t[2],l=0,d=[];l<u.length;l++)c=u[l],Object.prototype.hasOwnProperty.call(o,c)&&o[c]&&d.push(o[c][0]),o[c]=0;for(r in f)Object.prototype.hasOwnProperty.call(f,r)&&(e[r]=f[r]);s&&s(t);while(d.length)d.shift()();return a.push.apply(a,i||[]),n()}function n(){for(var e,t=0;t<a.length;t++){for(var n=a[t],r=!0,c=1;c<n.length;c++){var u=n[c];0!==o[u]&&(r=!1)}r&&(a.splice(t--,1),e=f(f.s=n[0]))}return e}var r={},c={runtime:0},o={runtime:0},a=[];function u(e){return f.p+"static/js/"+({}[e]||e)+"."+{"chunk-00a52ac4":"5f82d470","chunk-159c7f2c":"0fa7a8a3","chunk-2cbbeb82":"e1753706","chunk-643fd843":"ad8a85d9","chunk-6f60c8f1":"f16bf298","chunk-0e8cf5f4":"b7552abc","chunk-7d1a163b":"4d8cc933","chunk-8f81ac56":"da9fce35"}[e]+".js"}function f(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,f),n.l=!0,n.exports}f.e=function(e){var t=[],n={"chunk-00a52ac4":1,"chunk-159c7f2c":1,"chunk-2cbbeb82":1,"chunk-643fd843":1,"chunk-0e8cf5f4":1,"chunk-8f81ac56":1};c[e]?t.push(c[e]):0!==c[e]&&n[e]&&t.push(c[e]=new Promise((function(t,n){for(var r="static/css/"+({}[e]||e)+"."+{"chunk-00a52ac4":"71c8f52e","chunk-159c7f2c":"3c7f5ad9","chunk-2cbbeb82":"59a1d200","chunk-643fd843":"5488218b","chunk-6f60c8f1":"31d6cfe0","chunk-0e8cf5f4":"3328abfd","chunk-7d1a163b":"31d6cfe0","chunk-8f81ac56":"1efc9dd1"}[e]+".css",o=f.p+r,a=document.getElementsByTagName("link"),u=0;u<a.length;u++){var i=a[u],l=i.getAttribute("data-href")||i.getAttribute("href");if("stylesheet"===i.rel&&(l===r||l===o))return t()}var d=document.getElementsByTagName("style");for(u=0;u<d.length;u++){i=d[u],l=i.getAttribute("data-href");if(l===r||l===o)return t()}var s=document.createElement("link");s.rel="stylesheet",s.type="text/css",s.onload=t,s.onerror=function(t){var r=t&&t.target&&t.target.src||o,a=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");a.code="CSS_CHUNK_LOAD_FAILED",a.request=r,delete c[e],s.parentNode.removeChild(s),n(a)},s.href=o;var h=document.getElementsByTagName("head")[0];h.appendChild(s)})).then((function(){c[e]=0})));var r=o[e];if(0!==r)if(r)t.push(r[2]);else{var a=new Promise((function(t,n){r=o[e]=[t,n]}));t.push(r[2]=a);var i,l=document.createElement("script");l.charset="utf-8",l.timeout=120,f.nc&&l.setAttribute("nonce",f.nc),l.src=u(e);var d=new Error;i=function(t){l.onerror=l.onload=null,clearTimeout(s);var n=o[e];if(0!==n){if(n){var r=t&&("load"===t.type?"missing":t.type),c=t&&t.target&&t.target.src;d.message="Loading chunk "+e+" failed.\n("+r+": "+c+")",d.name="ChunkLoadError",d.type=r,d.request=c,n[1](d)}o[e]=void 0}};var s=setTimeout((function(){i({type:"timeout",target:l})}),12e4);l.onerror=l.onload=i,document.head.appendChild(l)}return Promise.all(t)},f.m=e,f.c=r,f.d=function(e,t,n){f.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},f.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,t){if(1&t&&(e=f(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(f.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)f.d(n,r,function(t){return e[t]}.bind(null,r));return n},f.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return f.d(t,"a",t),t},f.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},f.p="/",f.oe=function(e){throw console.error(e),e};var i=window["webpackJsonp"]=window["webpackJsonp"]||[],l=i.push.bind(i);i.push=t,i=i.slice();for(var d=0;d<i.length;d++)t(i[d]);var s=l;n()})([]);</script><script src=/static/js/chunk-elementUI.2491fb2f.js></script><script src=/static/js/chunk-libs.5e39c7d0.js></script><script src=/static/js/app.a2f5934b.js></script></body></html>
|
||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=/favicon.ico><title>车辆</title><link href=/static/css/app.63269458.css rel=preload as=style><link href=/static/css/chunk-elementUI.c1c3b808.css rel=preload as=style><link href=/static/css/chunk-libs.3dfb7769.css rel=preload as=style><link href=/static/js/app.aa5f6632.js rel=preload as=script><link href=/static/js/chunk-elementUI.2491fb2f.js rel=preload as=script><link href=/static/js/chunk-libs.2ec7c235.js rel=preload as=script><link href=/static/css/chunk-elementUI.c1c3b808.css rel=stylesheet><link href=/static/css/chunk-libs.3dfb7769.css rel=stylesheet><link href=/static/css/app.63269458.css rel=stylesheet></head><body><noscript><strong>We're sorry but 车辆 doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>(function(e){function t(t){for(var r,o,u=t[0],i=t[1],f=t[2],l=0,s=[];l<u.length;l++)o=u[l],Object.prototype.hasOwnProperty.call(c,o)&&c[o]&&s.push(c[o][0]),c[o]=0;for(r in i)Object.prototype.hasOwnProperty.call(i,r)&&(e[r]=i[r]);d&&d(t);while(s.length)s.shift()();return a.push.apply(a,f||[]),n()}function n(){for(var e,t=0;t<a.length;t++){for(var n=a[t],r=!0,o=1;o<n.length;o++){var u=n[o];0!==c[u]&&(r=!1)}r&&(a.splice(t--,1),e=i(i.s=n[0]))}return e}var r={},o={runtime:0},c={runtime:0},a=[];function u(e){return i.p+"static/js/"+({}[e]||e)+"."+{"chunk-019c66da":"ded8571e","chunk-123c65a8":"078492c0","chunk-6f60c8f1":"f16bf298","chunk-4a014042":"2fe4ac72","chunk-6fb69ae7":"8ca4dbc6","chunk-e4980b30":"83907799","chunk-22cea610":"fd8494c8","chunk-510f32e7":"792568de"}[e]+".js"}function i(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,i),n.l=!0,n.exports}i.e=function(e){var t=[],n={"chunk-123c65a8":1,"chunk-4a014042":1,"chunk-e4980b30":1,"chunk-22cea610":1,"chunk-510f32e7":1};o[e]?t.push(o[e]):0!==o[e]&&n[e]&&t.push(o[e]=new Promise((function(t,n){for(var r="static/css/"+({}[e]||e)+"."+{"chunk-019c66da":"31d6cfe0","chunk-123c65a8":"887652d5","chunk-6f60c8f1":"31d6cfe0","chunk-4a014042":"3328abfd","chunk-6fb69ae7":"31d6cfe0","chunk-e4980b30":"27dfab27","chunk-22cea610":"3c7f5ad9","chunk-510f32e7":"1510e3c5"}[e]+".css",c=i.p+r,a=document.getElementsByTagName("link"),u=0;u<a.length;u++){var f=a[u],l=f.getAttribute("data-href")||f.getAttribute("href");if("stylesheet"===f.rel&&(l===r||l===c))return t()}var s=document.getElementsByTagName("style");for(u=0;u<s.length;u++){f=s[u],l=f.getAttribute("data-href");if(l===r||l===c)return t()}var d=document.createElement("link");d.rel="stylesheet",d.type="text/css",d.onload=t,d.onerror=function(t){var r=t&&t.target&&t.target.src||c,a=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");a.code="CSS_CHUNK_LOAD_FAILED",a.request=r,delete o[e],d.parentNode.removeChild(d),n(a)},d.href=c;var h=document.getElementsByTagName("head")[0];h.appendChild(d)})).then((function(){o[e]=0})));var r=c[e];if(0!==r)if(r)t.push(r[2]);else{var a=new Promise((function(t,n){r=c[e]=[t,n]}));t.push(r[2]=a);var f,l=document.createElement("script");l.charset="utf-8",l.timeout=120,i.nc&&l.setAttribute("nonce",i.nc),l.src=u(e);var s=new Error;f=function(t){l.onerror=l.onload=null,clearTimeout(d);var n=c[e];if(0!==n){if(n){var r=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;s.message="Loading chunk "+e+" failed.\n("+r+": "+o+")",s.name="ChunkLoadError",s.type=r,s.request=o,n[1](s)}c[e]=void 0}};var d=setTimeout((function(){f({type:"timeout",target:l})}),12e4);l.onerror=l.onload=f,document.head.appendChild(l)}return Promise.all(t)},i.m=e,i.c=r,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)i.d(n,r,function(t){return e[t]}.bind(null,r));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="/",i.oe=function(e){throw console.error(e),e};var f=window["webpackJsonp"]=window["webpackJsonp"]||[],l=f.push.bind(f);f.push=t,f=f.slice();for(var s=0;s<f.length;s++)t(f[s]);var d=l;n()})([]);</script><script src=/static/js/chunk-elementUI.2491fb2f.js></script><script src=/static/js/chunk-libs.2ec7c235.js></script><script src=/static/js/app.aa5f6632.js></script></body></html>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue