Commit a9503118 by 何熠

Initial commit

parents
File added
.gradle
build/
/log/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
buildscript {
ext {
springBootVersion = '2.1.3.RELEASE'
}
repositories {
maven { url 'https://maven.xpaas.lenovo.com/nexus/repository/public/' }
maven { url 'https://maven.xpaas.lenovo.com/nexus/content/groups/public/' }
maven { url "https://repo.spring.io/milestone" }
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.lcrx.selector'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
maven { url 'https://maven.xpaas.lenovo.com/nexus/repository/public/' }
maven { url 'https://maven.xpaas.lenovo.com/nexus/content/groups/public/' }
maven { url "https://repo.spring.io/milestone" }
mavenCentral()
}
ext {
springCloudVersion = 'Greenwich.M3'
}
bootJar {
archiveName = 'selector.jar'
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation('org.springframework.boot:spring-boot-starter-actuator')
implementation('org.springframework.boot:spring-boot-starter-data-jpa')
implementation('org.springframework.boot:spring-boot-starter-web')
implementation('com.google.guava:guava:27.0-jre')
implementation('com.google.code.gson:gson:2.8.5')
implementation('org.apache.commons:commons-lang3:3.8.1')
implementation('io.springfox:springfox-swagger2:2.9.2')
implementation('io.springfox:springfox-swagger-ui:2.9.2')
implementation ("tk.mybatis:mapper-spring-boot-starter:2.0.4")
implementation ('org.postgresql:postgresql')
// implementation('org.flywaydb:flyway-core')
implementation('com.github.dozermapper:dozer-core:6.5.0')
implementation('com.alibaba:easyexcel:1.1.2-beta5')
implementation group: 'org.mvel', name: 'mvel2', version: '2.4.4.Final'
implementation('com.alibaba:fastjson:1.2.53')
implementation "org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.2"
implementation ("com.github.pagehelper:pagehelper-spring-boot-starter:1.2.7")
implementation ("tk.mybatis:mapper-spring-boot-starter:2.0.4")
compileOnly('org.projectlombok:lombok:1.18.2')
annotationProcessor('org.projectlombok:lombok:1.18.2')
testImplementation 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'com.tngtech.archunit:archunit:0.9.3'
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.1.0'
testImplementation 'com.github.tomakehurst:wiremock-standalone:2.16.0'
testImplementation 'it.ozimov:embedded-redis:0.7.2'
}
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MSYS* | MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
rootProject.name = 'selector-service'
package com.lcrx.selector;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* @author ###
*/
@SpringBootApplication(scanBasePackages = {"com.lcrx.selector"})
@Slf4j
@EnableJpaAuditing
@EnableAsync
@EnableScheduling
public class SelectorApplication {
public static void main(String[] args) {
SpringApplication.run(SelectorApplication.class, args);
}
}
package com.lcrx.selector.aop.annotation;
import java.lang.annotation.*;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Key {
int index();
String description();
}
package com.lcrx.selector.aop.annotation;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Module {
String value();
}
package com.lcrx.selector.aop.definition;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BusinessLog {
String action() default "";
String remark() default "";
String operator() default "";
String module() default "";
}
package com.lcrx.selector.aop.definition;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Operator {
}
package com.lcrx.selector.aop.implement;
import com.lcrx.selector.aop.definition.BusinessLog;
import com.lcrx.selector.aop.annotation.Module;
import com.lcrx.selector.enums.LogType;
import com.lcrx.selector.repository.BusinessLogRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;
/**
* @author ###
*/
@Slf4j
@Aspect
@Component
public class BusinessLogAOP {
private final static String REQUEST_METHOD_GET = "GET";
private final BusinessLogger businessLogger;
private final HttpServletRequest request;
private final BusinessLogData businessLogData;
private static final ThreadLocal<Long> startTime = new ThreadLocal<>();
public static final String USER_CODE = "system";
@Autowired
public BusinessLogAOP(BusinessLogger businessLogger,
HttpServletRequest request,
BusinessLogData businessLogData
) {
this.businessLogger = businessLogger;
this.request = request;
this.businessLogData = businessLogData;
}
@Around(value = "@annotation(com.lcrx.selector.aop.definition.BusinessLog)")
public Object aroundMethod(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
startTime.set(System.currentTimeMillis());
Method method = ((MethodSignature) proceedingJoinPoint.getSignature()).getMethod();
BusinessLog businessLogAnnotation = method.getAnnotation(BusinessLog.class);
String module = getModule(businessLogAnnotation, proceedingJoinPoint);
businessLogData.setOperator(request.getHeader(USER_CODE));
if (REQUEST_METHOD_GET.equals(request.getMethod())) {
recordGetRequest(businessLogAnnotation, module);
} else {
recordNonGetRequest(businessLogAnnotation, proceedingJoinPoint, method, module);
}
recordHeaderContext();
return proceedingJoinPoint.proceed();
}
@AfterReturning(value = "@annotation(com.lcrx.selector.aop.definition.BusinessLog)", returning = "response")
public void afterReturn(Object response) {
try {
businessLogData
.setTook(System.currentTimeMillis() - startTime.get())
.setResponse(response);
businessLogger.log(businessLogData);
} catch (Exception e) {
log.error("Record response biz log error.", e);
}
}
private void recordHeaderContext(){
Enumeration<String> enumeration = request.getHeaderNames();
StringBuffer headers = new StringBuffer();
while (enumeration.hasMoreElements()) {
String name = enumeration.nextElement();
String value = request.getHeader(name);
headers.append(name + ":" + value).append(",");
}
businessLogData.setHeaderContext(headers.toString());
}
private int calculateSize(final Object o){
if (o == null) {
return 0;
}
ByteArrayOutputStream buf = new ByteArrayOutputStream(4096);
ObjectOutputStream out = null;
try{
out = new ObjectOutputStream(buf);
out.writeObject(o);
out.flush();
buf.close();
}catch (IOException e){
log.error("calculate object size fail.");
}
return buf.size();
}
private String getModule(BusinessLog businessLogAnnotation, ProceedingJoinPoint pjp) {
String module = businessLogAnnotation.module();
if (StringUtils.isBlank(module)) {
Class<?> classTarget = pjp.getTarget().getClass();
module = Optional.ofNullable(classTarget.getAnnotation(Module.class))
.map(Module::value).orElse("");
}
return module;
}
private void recordGetRequest(BusinessLog businessLogAnnotation, String module) {
String requestUrl = buildGetRequestUrl();
businessLogData.setLogType(LogType.API)
.activate()
.setAction(businessLogAnnotation.action())
.setRequestMethod(request.getMethod())
.setUri(request.getRequestURI())
.setUrl(requestUrl)
.setRemark(businessLogAnnotation.remark())
.setModule(module);
if(StringUtils.isBlank(businessLogData.getOperator())){
businessLogData.setOperator(businessLogAnnotation.operator());
}
}
private void recordNonGetRequest(BusinessLog businessLogAnnotation, ProceedingJoinPoint pjp, Method method, String module) {
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
OptionalInt payloadIndex = IntStream.range(0, parameterAnnotations.length).filter(i ->
Arrays.stream(parameterAnnotations[i]).filter(annotation ->
RequestBody.class.equals(annotation.annotationType())
).anyMatch(Objects::nonNull)
).findFirst();
if (payloadIndex.isPresent()) {
Object[] args = pjp.getArgs();
Object payload = args[payloadIndex.getAsInt()];
businessLogData.setPayload(payload);
}
businessLogData.setLogType(LogType.API)
.activate()
.setAction(businessLogAnnotation.action())
.setRequestMethod(request.getMethod())
.setUri(request.getRequestURI())
.setUrl(request.getRequestURL().toString())
.setRemark(businessLogAnnotation.remark())
.setModule(module);
if(StringUtils.isBlank(businessLogData.getOperator())){
businessLogData.setOperator(businessLogAnnotation.operator());
}
}
private String buildGetRequestUrl() {
StringBuffer urlBuffer = request.getRequestURL();
urlBuffer.append("?");
Map<String, String[]> parameterMap = request.getParameterMap();
AtomicInteger mark = new AtomicInteger(1);
int size = parameterMap.size();
parameterMap.entrySet().stream().forEach(entry -> {
urlBuffer.append(entry.getKey()).append("=");
String[] values = entry.getValue();
IntStream.range(0, values.length).forEach(index -> {
if (index > 0) {
urlBuffer.append(",");
}
urlBuffer.append(values[index]);
});
if (mark.get() < size) {
mark.getAndIncrement();
urlBuffer.append("&");
}
});
return urlBuffer.toString();
}
}
package com.lcrx.selector.aop.implement;
import com.lcrx.selector.enums.LogType;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class BusinessLogData {
private boolean enabled;
private String action;
private String module;
private LogType logType;
private String operator;
private String remark;
private Object payload;
private Object response;
private String requestMethod;
private String uri;
private String url;
private String loginUser;
private long took;
private String headerContext;
public BusinessLogData activate() {
enabled = true;
return this;
}
public BusinessLogData setAction(String actionNew) {
action = actionNew;
return this;
}
public BusinessLogData setModule(String moduleNew) {
module = moduleNew;
return this;
}
public BusinessLogData setLogType(LogType logTypeNew) {
logType = logTypeNew;
return this;
}
public BusinessLogData setOperator(String operatorNew) {
operator = operatorNew;
return this;
}
public BusinessLogData setRemark(String remarkNew) {
remark = remarkNew;
return this;
}
public BusinessLogData setPayload(Object payloadNew) {
payload = payloadNew;
return this;
}
public BusinessLogData setResponse(Object responseNew) {
response = responseNew;
return this;
}
public BusinessLogData setRequestMethod(String requestMethodNew) {
requestMethod = requestMethodNew;
return this;
}
public BusinessLogData setUri(String uriNew) {
uri = uriNew;
return this;
}
public BusinessLogData setUrl(String urlNew) {
url = urlNew;
return this;
}
public BusinessLogData setLoginUser(String loginUserNew) {
loginUser = loginUserNew;
return this;
}
public BusinessLogData setTook(long tookNew) {
took = tookNew;
return this;
}
public BusinessLogData setHeaderContext(String headerContextNew) {
headerContext = headerContextNew;
return this;
}
}
package com.lcrx.selector.aop.implement;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.lcrx.selector.aop.annotation.Key;
import com.lcrx.selector.aop.annotation.Module;
import com.lcrx.selector.aop.definition.*;
import com.lcrx.selector.entity.PO.BusinessLogPO;
import com.lcrx.selector.enums.Action;
import com.lcrx.selector.enums.LogType;
import com.lcrx.selector.repository.BusinessLogRepository;
import com.lcrx.selector.utils.RedisHelper;
import com.lcrx.selector.utils.SnowflakeHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* @author ###
*/
@Slf4j
@Component
public class BusinessLogger {
private final Logger bizLogger = LoggerFactory.getLogger("biz");
private final ObjectMapper objectMapper = new ObjectMapper();
private final BusinessLogRepository businessLogRepository;
private final SnowflakeHelper snowflakeHelper;
@Autowired
public BusinessLogger(BusinessLogRepository businessLogRepository,
SnowflakeHelper snowflakeHelper
)
{
this.businessLogRepository = businessLogRepository;
this.snowflakeHelper = snowflakeHelper;
}
@Deprecated
public void log(LogType logType, Action action, String operator, Object payload) {
String module = Optional.ofNullable(payload.getClass().getAnnotation(Module.class))
.map(Module::value).orElse("");
BusinessLogData businessLogData = new BusinessLogData()
.activate()
.setLogType(logType)
.setAction(action.getDescription())
.setOperator(operator)
.setModule(module)
.setPayload(payload);
log(businessLogData);
}
public void log(BusinessLogData bizLogData) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
Map<String, Object> logMap = Maps.newHashMap();
logMap.put("log_type", bizLogData.getLogType().getDescription());
logMap.put("action", bizLogData.getAction());
logMap.put("operator", bizLogData.getOperator());
logMap.put("api", bizLogData.getRequestMethod() + " " + bizLogData.getUri());
logMap.put("request_url", bizLogData.getUrl());
logMap.put("remark", bizLogData.getRemark());
logMap.put("module", bizLogData.getModule());
logMap.put("loginUser", bizLogData.getLoginUser());
logMap.put("timeStamp", df.format(new Date()));
logMap.put("took",bizLogData.getTook());
logMap.put("headerContext",bizLogData.getHeaderContext());
Object payload = bizLogData.getPayload();
if (payload != null) {
Lists.newArrayList(payload.getClass().getDeclaredFields())
.forEach(field -> {
if (Objects.nonNull(field.getAnnotation(Key.class))) {
Key key = field.getAnnotation(Key.class);
field.setAccessible(true);
try {
logMap.put("k" + key.index(), field.get(payload));
} catch (IllegalAccessException e) {
log.error("error in log biz info", e);
}
}
if (StringUtils.isBlank(bizLogData.getOperator()) && Objects.nonNull(field.getAnnotation(Operator.class))) {
field.setAccessible(true);
try {
logMap.put("operator", field.get(payload));
} catch (IllegalAccessException e) {
log.error("error in log biz info", e);
}
}
});
}
try {
logMap.put("payload", objectMapper.writeValueAsString(payload));
logMap.put("response", objectMapper.writeValueAsString(bizLogData.getResponse()));
//bizLogger.info(objectMapper.writeValueAsString(logMap));
BusinessLogPO businessLogPO = new BusinessLogPO();
businessLogPO.setId(snowflakeHelper.nextId());
businessLogPO.setContents(JSON.toJSONString(logMap));
businessLogRepository.save(businessLogPO);
} catch (JsonProcessingException e) {
log.error("error in log biz info {}", e);
}
}
}
package com.lcrx.selector.api;
import com.alibaba.fastjson.JSON;
import com.lcrx.selector.aop.definition.BusinessLog;
import com.lcrx.selector.constant.RedisKey;
import com.lcrx.selector.utils.RedisHelper;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@Api(tags = "ops", value = "ops")
@RestController
@RequestMapping(value = "/api/v1/ops")
@Slf4j
public class OpsController {
private final RedisHelper redisHelper;
private final RedisTemplate<String, String> redisTemplate;
@Autowired
public OpsController(RedisHelper redisHelper, RedisTemplate<String, String> redisTemplate) {
this.redisHelper = redisHelper;
this.redisTemplate = redisTemplate;
}
@PostMapping("/variantTable")
@BusinessLog
public void setVariantTable(@RequestBody String redis) {
ValueOperations<String, String> operations = redisTemplate.opsForValue();
redisHelper.set(RedisKey.getVariantTableKey("cf", "03", "10G4CTO1WW"), redis);
}
@PostMapping("/debug")
@BusinessLog
public String test() {
Map<String, String> tempMap = new HashMap<>();
tempMap.put("1","a");
tempMap.put("2","b");
return JSON.toJSONString(tempMap);
}
}
package com.lcrx.selector.api.v1;
import com.lcrx.selector.aop.definition.BusinessLog;
import com.lcrx.selector.entity.DTO.*;
import com.lcrx.selector.service.SelectorService;
import com.lcrx.selector.utils.result.Result;
import com.lcrx.selector.utils.result.ResultCode;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
/**
* @author ###
*/
@Api(tags = "selector", value = "selector")
@RestController
@RequestMapping(value = "/api/v1/selector")
@Slf4j
public class SelectorController {
private final SelectorService selectorService;
@Autowired
public SelectorController(SelectorService selectorService) {
this.selectorService = selectorService;
}
@PostMapping("/initialization")
@BusinessLog
public Result<InitializationOutputDTO> initialization(@Valid @RequestBody InitializationInputDTO initializationInputDTO,
Errors errors)
{
//校验处理
if(errors.hasErrors())
{
return Result.genResult(ResultCode.INPUT_DATA_ERROR.getCode(), ResultCode.INPUT_DATA_ERROR.getMsg());
}
return Result.ok(selectorService.initialization(initializationInputDTO));
}
@PostMapping("/preVerify")
@BusinessLog
public Result<PreVerifyOutputDTO> preVerify(@Valid @RequestBody PreVerifyInputDTO preVerifyInputDTO,
Errors errors)
{
//校验处理
if(errors.hasErrors())
{
return Result.genResult(ResultCode.INPUT_DATA_ERROR.getCode(), ResultCode.INPUT_DATA_ERROR.getMsg());
}
return Result.ok(selectorService.preVerify(preVerifyInputDTO));
}
@PostMapping("/buildConfiguration")
@BusinessLog
public Result<BuildConfigurationOutputDTO> buildConfiguration(@Valid @RequestBody BuildConfigurationInputDTO buildConfigurationInputDTO,
Errors errors)
{
//校验处理
if(errors.hasErrors())
{
return Result.genResult(ResultCode.INPUT_DATA_ERROR.getCode(), ResultCode.INPUT_DATA_ERROR.getMsg());
}
return Result.ok(selectorService.buildConfiguration(buildConfigurationInputDTO));
}
@PostMapping("/conflictAnalysis")
@BusinessLog
public Result<ConflictAnalysisOutputDTO> conflictAnalysis(@Valid @RequestBody ConflictAnalysisInputDTO conflictAnalysisInputDTO,
Errors errors)
{
//校验处理
if(errors.hasErrors())
{
return Result.genResult(ResultCode.INPUT_DATA_ERROR.getCode(), ResultCode.INPUT_DATA_ERROR.getMsg());
}
return Result.ok(selectorService.conflictAnalysis(conflictAnalysisInputDTO));
}
@PostMapping("/postVerify")
@BusinessLog
public Result<PostVerifyOutputDTO> postVerify(@Valid @RequestBody PostVerifyInputDTO postVerifyInputDTO,
Errors errors)
{
//校验处理
if(errors.hasErrors())
{
return Result.genResult(ResultCode.INPUT_DATA_ERROR.getCode(), ResultCode.INPUT_DATA_ERROR.getMsg());
}
return Result.ok(selectorService.postVerify(postVerifyInputDTO));
}
@PostMapping(value = "/copyConfiguration")
@ResponseStatus(HttpStatus.OK)
@BusinessLog(action = "复制配置")
public Result<CopyConfigurationOutputDTO> copyConfiguration(@Valid @RequestBody CopyConfigurationInputDTO copyConfigurationInputDTO,
Errors errors) {
//校验处理
if(errors.hasErrors())
{
return Result.genResult(ResultCode.INPUT_DATA_ERROR.getCode(), ResultCode.INPUT_DATA_ERROR.getMsg());
}
return Result.ok(selectorService.copyConfiguration(copyConfigurationInputDTO));
}
@PostMapping(value = "/configurations")
@ResponseStatus(HttpStatus.OK)
@BusinessLog(action = "获取配置")
public Result<List<GetConfigurationOutputDTO>> getConfigurations(@Valid @RequestBody GetConfigurationInputDTO getConfigurationInputDTO,
Errors errors) {
//校验处理
if(errors.hasErrors())
{
return Result.genResult(ResultCode.INPUT_DATA_ERROR.getCode(), ResultCode.INPUT_DATA_ERROR.getMsg());
}
return Result.ok(selectorService.getConfigurations(getConfigurationInputDTO.getConfigIds()));
}
}
package com.lcrx.selector.config;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Configuration;
@EnableCaching
@Configuration
public class CacheConfiguration {
}
package com.lcrx.selector.config;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
/**
* @author ###
*/
@Configuration
public class DataSourceConfiguration {
@Primary
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSourceProperties dataSourceProperties() {
return new DataSourceProperties();
}
@Primary
@Bean
public DataSource dataSource(@Qualifier("dataSourceProperties") DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
}
package com.lcrx.selector.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManager;
import javax.sql.DataSource;
/**
* @author ###
*/
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactory",
transactionManagerRef = "transactionManager",
basePackages = {"com.lcrx.selector.repository"})
public class HibernateConfiguration {
@Autowired
@Qualifier("dataSource")
private DataSource dataSource;
@Autowired
private JpaProperties jpaProperties;
@Autowired
private HibernateProperties hibernateProperties;
@Primary
@Bean(name = "entityManager")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactory(builder).getObject().createEntityManager();
}
@Primary
@Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder) {
return builder.dataSource(dataSource)
.properties(hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings()))
.packages("com.lcrx.selector.entity")
.persistenceUnit("persistenceUnit")
.build();
}
@Primary
@Bean(name = "transactionManager")
public PlatformTransactionManager lmsTransactionManager(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactory(builder).getObject());
}
}
package com.lcrx.selector.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
@Configuration
public class RedisConfiguration {
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate template = new RedisTemplate();
template.setConnectionFactory(connectionFactory);
template.afterPropertiesSet();
return template;
}
}
package com.lcrx.selector.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class Swagger2Configuration {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_12)
.enableUrlTemplating(true)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.lcrx.selector.api"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("selector API文档")
.description("selector API文档")
.version("1.0")
.build();
}
}
package com.lcrx.selector.constant;
/**
* @author ###
*/
public class Constant {
/**
* 请选择的value值
*/
public static String CHARACTERISTIC_UNSELECTED_VALUE = "";
}
package com.lcrx.selector.constant;
/**
* @author ###
*/
public class Message {
public static String POST_VERIFY_FAILURE = "后置校验异常,冲突的特征";
}
package com.lcrx.selector.constant;
import java.text.MessageFormat;
/**
* @author ###
*/
public class RedisKey {
/**
* 系统:产品组:物料编号
*/
private static final String VARIANT_TABLE = "selector:{0}:{1}:{2}:variantTable";
/**
* 系统
*/
private static final String QUANTITY_MAPPING = "selector:{0}:quantityMapping";
/**
* 系统
*/
private static final String TOTAL_QUANTITY_MAPPING = "selector:{0}:totalQuantityMapping";
/**
* TOTAL特征和特征值的缓存id
*/
private static final String TOTAL_CHARACTERISTIC = "selector:characteristic:total:{0}";
/**
* 选中的特征和特征值的缓存id
*/
private static final String SELECTED_CHARACTERISTIC = "selector:characteristic:selected:{0}";
public static String getVariantTableKey(String systemCode,
String productGroupCode,
String materialCode) {
return MessageFormat.format(VARIANT_TABLE, systemCode, productGroupCode, materialCode);
}
public static String getTotalCharacteristicKey(String snowFlakeId) {
return MessageFormat.format(TOTAL_CHARACTERISTIC, snowFlakeId);
}
public static String getSelectedCharacteristicKey(String snowFlakeId) {
return MessageFormat.format(SELECTED_CHARACTERISTIC, snowFlakeId);
}
public static String getQuantityMappingKey(String systemCode) {
return MessageFormat.format(QUANTITY_MAPPING, systemCode);
}
public static String getTotalQuantityMappingKey(String systemCode) {
return MessageFormat.format(TOTAL_QUANTITY_MAPPING, systemCode);
}
}
package com.lcrx.selector.entity.DO;
import lombok.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author ###
*/
@Getter
@Setter
@AllArgsConstructor
@ToString
public class InitializeResultDO {
private Map<Integer, Map<String, List<String>>> variantTableGroupMap;
private Map<Integer, Map<Integer, Map<String, List<String>>>> variantTableMap;
private Map<Integer, List<Integer>> invalidGroupMap;
public InitializeResultDO() {
this.variantTableGroupMap = new HashMap<>();
this.variantTableMap = new HashMap<>();
this.invalidGroupMap = new HashMap<>();
}
}
package com.lcrx.selector.entity.DO;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
/**
* @author ###
*/
@Getter
@Setter
@NoArgsConstructor
@ToString
public class VariantTableDO implements Serializable {
private Integer variantTableId;
private List<String> constraintCharacteristicName;
/**
* 第一索引是行号,第二索引是特征,第三个集合是特征值集合
*/
private Map<Integer, Map<String, List<String>>> constraintCharacteristicValues;
}
package com.lcrx.selector.entity.DTO;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.List;
/**
* @author ###
*/
@NoArgsConstructor
@Data
public class BuildConfigurationInputDTO implements Serializable {
/**
* productGroupCode : ###
* materialCode : ###
* operator : ###
* selectedComplete : true
* sessionId : 会话Id,服务记录total信息的值
* selectedCharacteristicList : [{"characteristicName":"特征名称","characteristicValueName":"特征值名称","quantity":1}]
* keyValues : [{"key":"mode","value":"edit"}]
*/
@NotNull
private String productGroupCode;
@NotNull
private String materialCode;
@NotNull
private String operator;
@NotNull
private Boolean selectedComplete;
@NotNull
private String sessionId;
@NotNull
@Size(min = 1)
private List<SelectedCharacteristicListBean> selectedCharacteristicList;
private List<KeyValuesBean> keyValues;
@NoArgsConstructor
@Data
public static class SelectedCharacteristicListBean implements Serializable {
/**
* characteristicName : 特征名称
* characteristicValueName : 特征值名称
* quantity : 1
*/
private String characteristicName;
private String characteristicValueName;
private int quantity;
private String desc;
}
@NoArgsConstructor
@Data
public static class KeyValuesBean implements Serializable {
/**
* key : mode
* value : edit
*/
private String key;
private String value;
}
}
package com.lcrx.selector.entity.DTO;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author ###
*/
@Data
@NoArgsConstructor
public class BuildConfigurationOutputDTO implements Serializable {
/**
* configId : 6160342
*/
private Long configId;
}
package com.lcrx.selector.entity.DTO;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.List;
/**
* @author ###
*/
@NoArgsConstructor
@Data
public class ConflictAnalysisInputDTO implements Serializable {
/**
* productGroupCode : 03
* materialCode : 90FYCTO1WW
* operator : LIUJJ16
* characteristicName : 特征名称
* characteristicValueName : 特征值名称
* sessionId : 会话Id,redis记录total特征信息,不用再传
* selectedCharacteristicList : [{"characteristicName":"特征名称","characteristicValueName":"特征值名称"}]
* mustSelection : false
*/
@NotNull
private String productGroupCode;
@NotNull
private String materialCode;
@NotNull
private String operator;
@NotNull
private String characteristicName;
@NotNull
private String characteristicValueName;
@NotNull
private String sessionId;
@NotNull
private Boolean mustSelection;
@NotNull
private List<SelectedCharacteristicListBean> selectedCharacteristicList;
@NoArgsConstructor
@Data
public static class SelectedCharacteristicListBean implements Serializable {
/**
* characteristicName : 特征名称
* characteristicValueName : 特征值名称
*/
private String characteristicName;
private String characteristicValueName;
private int quantity;
private String desc;
}
}
package com.lcrx.selector.entity.DTO;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* @author ###
*/
@NoArgsConstructor
@Data
public class ConflictAnalysisOutputDTO implements Serializable {
/**
* conflictCharacteristicList : ["冲突的特征值的Name"]
* activeValues : [{"characteristicName":"###","values":["##"]},{"characteristicName":"###","values":["##","##","##"]}]
* selectedCharacteristicList : [{"characteristicName":"DTPRODUCTNAME90FY","characteristicValueName":"QTM610-N000"}]
* mustSelectionResult : true
*/
private Boolean mustSelectionResult;
private List<String> conflictCharacteristicList;
private List<ActiveValuesBean> activeValues;
private List<SelectedCharacteristicListBean> selectedCharacteristicList;
@NoArgsConstructor
@Data
public static class ActiveValuesBean implements Serializable {
/**
* characteristicName : ###
* values : ["##"]
*/
private String characteristicName;
private List<String> values;
}
@NoArgsConstructor
@Data
public static class SelectedCharacteristicListBean implements Serializable {
/**
* characteristicName : DTPRODUCTNAME90FY
* characteristicValueName : QTM610-N000
*/
private String characteristicName;
private String characteristicValueName;
private int quantity;
private String desc;
}
}
package com.lcrx.selector.entity.DTO;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.List;
/**
* @author ###
*/
@NoArgsConstructor
@Data
public class CopyConfigurationInputDTO implements Serializable {
/**
* operator : LIUJJ16
* configIds : ["1446766968451108866","1447040066106716161"]
*/
@NotNull
private String operator;
@NotNull
@Size(min =1)
private List<String> configIds;
}
package com.lcrx.selector.entity.DTO;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.List;
/**
* @author ###
*/
@Getter
@Setter
@NoArgsConstructor
@Data
public class CopyConfigurationOutputDTO {
private List<ConfigIdsBean> configIds;
@NoArgsConstructor
@Data
public static class ConfigIdsBean {
/**
* configId : 1000
* newConfigId : 1001
*/
private String configId;
private String newConfigId;
}
}
package com.lcrx.selector.entity.DTO;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.List;
/**
* @author ###
*/
@NoArgsConstructor
@Data
public class GetConfigurationInputDTO {
/**
* operator : LIUJJ16
* configIds : ["1446766968451108866","1447040066106716161"]
*/
@NotNull
private String operator;
@NotNull
@Size(min = 1)
private List<String> configIds;
}
package com.lcrx.selector.entity.DTO;
import lombok.*;
import java.io.Serializable;
import java.util.List;
/**
* @author leafinsight
*/
@NoArgsConstructor
@Data
@Getter
@Setter
@ToString
public class GetConfigurationOutputDTO implements Serializable {
/**
* configId : 1451920793390546948
* selectedCharacteristicList : [{"characteristicName":"###","characteristicValueName":"##"},{"characteristicName":"###","characteristicValueName":"##"}]
*/
private String configId;
private String materialCode;
private List<SelectedCharacteristicListBean> selectedCharacteristicList;
@NoArgsConstructor
@Data
public static class SelectedCharacteristicListBean implements Serializable {
/**
* characteristicName : ###
* characteristicValueName : ##
*/
private String characteristicName;
private String characteristicValueName;
private int quantity;
private String desc;
}
}
package com.lcrx.selector.entity.DTO;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.List;
/**
* @author ###
*/
@NoArgsConstructor
@Data
@Getter
public class InitializationInputDTO implements Serializable {
/**
* system : 调用系统
* productGroupCode : 产品组编号
* materialCode : 物料编号
* operator : ###
* configId :
* characteristicList : [{"Name":"特征名称,CTO下唯一","pairCharacteristicName":"匹配的数量型C","type":0,"isDerive":0,"values":[{"Name":"特征值Name,特征下唯一"}]}]
* keyValues : [{"key":"action","value":"edit"},{"key":"###","value":"###"}]
*/
@NotNull
private String system;
@NotNull
private String productGroupCode;
@NotNull
private String materialCode;
@NotNull
private String operator;
private String configId;
@NotNull
@Size(min = 1)
private List<CharacteristicListBean> characteristicList;
private List<KeyValuesBean> keyValues;
@NoArgsConstructor
@Data
public static class CharacteristicListBean implements Serializable {
/**
* Name : 特征名称,CTO下唯一
* pairCharacteristicName : 匹配的数量型C
* type : 0
* isDerive : 0 是派生的特征
* invisibleForSales: 0 销售是否可见的标识
* values : [{"Name":"特征值Name,特征下唯一"}]
*/
private String name;
private String pairCharacteristicName;
private int type;
private int isDerive;
private int invisibleForSales;
private List<ValuesBean> values;
@NoArgsConstructor
@Data
public static class ValuesBean implements Serializable {
/**
* Name : 特征值Name,特征下唯一
*/
private String name;
private List<KeyValuesBean> keyValues;
}
}
@NoArgsConstructor
@Data
public static class KeyValuesBean implements Serializable {
/**
* key : action
* value : edit
*/
private String key;
private String value;
}
}
package com.lcrx.selector.entity.DTO;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* @author ###
*/
@NoArgsConstructor
@Data
public class InitializationOutputDTO implements Serializable {
/**
* materialCode : ###
* productGroupCode : ###
* sessionId : 会话Id,服务记录total信息的值
* characteristicList : [{"Name":"特征Value,CTO下唯一","pairCharacteristicValue":"匹配的数量型C","type":0,"isDerive":0,"values":[{"Name":"特征值Name,特征下唯一","isolated":false,"keyValues":[{"key":"###","value":"###"}]}]}]
* activeValues : [{"characteristicName":"###","values":["##"]},{"characteristicName":"###","values":["##","##","##"]}]
* selectedValues : [{"characteristicName":"###","characteristicValueName":"##"},{"characteristicName":"###","characteristicValueName":"##"}]
* keyValues : [{"key":"fast_path","value":"1"}]
*/
private String materialCode;
private String productGroupCode;
private String sessionId;
private List<CharacteristicListBean> characteristicList;
private List<String> constraintCharacteristicNames;
private List<ActiveValuesBean> activeValues;
private List<SelectedValuesBean> selectedValues;
private List<KeyValuesBean> keyValues;
@NoArgsConstructor
@Data
public static class CharacteristicListBean implements Serializable {
/**
* Name : 特征Value,CTO下唯一
* pairCharacteristicValue : 匹配的数量型C
* type : 0
* isDerive : 0
* values : [{"Name":"特征值Name,特征下唯一","isolated":false,"keyValues":[{"key":"###","value":"###"}]}]
*/
private String Name;
private String pairCharacteristicValueName;
private int type;
private int isDerive;
private List<ValuesBean> values;
@NoArgsConstructor
@Data
public static class ValuesBean implements Serializable {
/**
* Name : 特征值Name,特征下唯一
* isolated : false
* keyValues : [{"key":"###","value":"###"}]
*/
private String Name;
private Boolean isolated;
private List<KeyValuesBean> keyValues;
}
}
@NoArgsConstructor
@Data
public static class ActiveValuesBean implements Serializable {
/**
* characteristicName : ###
* values : ["##"]
*/
private String characteristicName;
private List<String> values;
}
@NoArgsConstructor
@Data
public static class SelectedValuesBean implements Serializable {
/**
* characteristicName : ###
* characteristicValueName : ##
*/
private String characteristicName;
private String characteristicValueName;
private int quantity;
private String desc;
private Boolean available;
}
@NoArgsConstructor
@Data
public static class KeyValuesBean implements Serializable {
/**
* key : fast_path
* value : 1
*/
private String key;
private String value;
}
}
package com.lcrx.selector.entity.DTO;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.List;
/**
* @author ###
*/
@NoArgsConstructor
@Data
public class PostVerifyInputDTO implements Serializable {
/**
* productGroupCode : 03
* materialCode : 90G3CTO1WW
* operator : LIUJJ16
* sessionId : 1447404367220871169
* selectedCharacteristicList : [{"characteristicName":"DTEXTERNAL_USB_PORT_CABLE","characteristicValueName":"FRONT_X4_REAR_X4_USB_PORTS","quantity":1},{"characteristicName":"DTPOWER_SUPPLY","characteristicValueName":"180W_85_ES_TFX","quantity":1}]
* keyValues : [{"key":"mode","value":"edit"}]
*/
@NotNull
private String productGroupCode;
@NotNull
private String materialCode;
@NotNull
private String operator;
@NotNull
private String sessionId;
@NotNull
@Size(min = 1)
private List<SelectedCharacteristicListBean> selectedCharacteristicList;
private List<KeyValuesBean> keyValues;
@NoArgsConstructor
@Data
public static class SelectedCharacteristicListBean implements Serializable {
/**
* characteristicName : DTEXTERNAL_USB_PORT_CABLE
* characteristicValueName : FRONT_X4_REAR_X4_USB_PORTS
* quantity : 1
*/
private String characteristicName;
private String characteristicValueName;
private int quantity;
}
@NoArgsConstructor
@Data
public static class KeyValuesBean implements Serializable {
/**
* key : mode
* value : edit
*/
private String key;
private String value;
}
}
package com.lcrx.selector.entity.DTO;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* @author ###
*/
@Data
@NoArgsConstructor
public class PostVerifyOutputDTO implements Serializable {
/**
* result : false
* characteristicList : ["DTCPU","DTMEMORY"]
* message :
*/
private Boolean result;
private String message;
private List<String> characteristicList;
}
package com.lcrx.selector.entity.DTO;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.List;
/**
* @author ###
*/
@NoArgsConstructor
@Data
public class PreVerifyInputDTO implements Serializable {
/**
* characteristicName : 特征Name
* productGroupCode : ##
* materialCode : ###
* operator : ###
* characteristicValueName : 特征值Name
* sessionId : 会话Id,redis记录total特征信息,不用再传
* keyValues : [{"key":"mode","value":"edit"}]
*/
@NotNull
private String characteristicName;
@NotNull
private String productGroupCode;
@NotNull
private String materialCode;
@NotNull
private String operator;
@NotNull
private String characteristicValueName;
@NotNull
private String sessionId;
@NotNull
private List<SelectedCharacteristicListBean> selectedCharacteristicList;
private List<KeyValuesBean> keyValues;
@NoArgsConstructor
@Data
public static class KeyValuesBean implements Serializable {
/**
* key : mode
* value : edit
*/
private String key;
private String value;
}
@NoArgsConstructor
@Data
public static class SelectedCharacteristicListBean implements Serializable {
/**
* characteristicName : ###
* characteristicValueName : ##
*/
private String characteristicName;
private String characteristicValueName;
private int quantity;
private String desc;
}
}
package com.lcrx.selector.entity.DTO;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* @author ###
*/
@NoArgsConstructor
@Data
public class PreVerifyOutputDTO implements Serializable {
/**
* activeValues : [{"characteristicName":"###","values":["##"]},{"characteristicName":"###","values":["##","##","##"]}]
* message :
* result : true
*/
private String message;
private Boolean result;
private List<String> conflictingCharacteristicList;
private List<ActiveValuesBean> activeValues;
@NoArgsConstructor
@Data
public static class ActiveValuesBean implements Serializable {
/**
* characteristicName : ###
* values : ["##"]
*/
private String characteristicName;
private List<String> values;
}
}
package com.lcrx.selector.entity.PO;
import lombok.*;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
/**
* @author ###
*/
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "business_log")
@EntityListeners(AuditingEntityListener.class)
public class BusinessLogPO {
@Id
@Column(name = "id")
private Long id;
@Column(name = "contents")
private String contents;
}
package com.lcrx.selector.entity.PO;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.*;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.util.Date;
import java.util.List;
/**
* @author ###
*/
@Builder
@Data
@EqualsAndHashCode(exclude = {"configurationCharacteristicValuePOList"})
@ToString(exclude = {"configurationCharacteristicValuePOList"})
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "configuration_basis")
@EntityListeners(AuditingEntityListener.class)
public class ConfigurationBasisPO {
@Id
@Column(name = "config_id")
private Long configId;
@Column(name = "product_group_code")
private String productGroupCode;
@Column(name = "material_code")
private String materialCode;
@Column(name = "operator")
private String operator;
@Column(name = "create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date createTime;
@OneToMany(mappedBy = "configurationBasisPO", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
private List<ConfigurationCharacteristicValuePO> configurationCharacteristicValuePOList;
}
package com.lcrx.selector.entity.PO;
import com.lcrx.selector.entity.PO.ConfigurationBasisPO;
import lombok.*;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
/**
* @author ###
*/
@Builder
@Data
@EqualsAndHashCode(exclude = {"configurationBasisPO"})
@ToString(exclude = {"configurationBasisPO"})
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "configuration_characteristic_and_value")
@EntityListeners(AuditingEntityListener.class)
public class ConfigurationCharacteristicValuePO {
@Id
@Column(name = "id")
private Long id;
@Column(name = "config_id", insertable = false, updatable = false)
private Long configId;
@Column(name = "characteristic_name")
private String characteristicName;
@Column(name = "characteristic_value_name")
private String characteristicValueName;
@Column(name = "characteristic_value_quantity")
private Integer characteristicValueQuantity;
@Column(name = "characteristic_value_desc")
private String characteristicValueDesc;
@ManyToOne(cascade = CascadeType.REFRESH, fetch = FetchType.LAZY)
@JoinColumn(name = "config_id")
private ConfigurationBasisPO configurationBasisPO;
}
package com.lcrx.selector.entity.PO;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author ###
*/
@NoArgsConstructor
@Data
public class QuantityMappingPO implements Serializable {
/**
* primaryCharacteristicName : 主特征名称
* associatedCharacteristicName : 关联的数量型特征名称
*/
private String primaryCharacteristicName;
private String associatedCharacteristicName;
}
package com.lcrx.selector.entity.PO;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author ###
*/
@NoArgsConstructor
@Data
public class TotalQuantityMappingPO implements Serializable {
/**
* totalCharacteristicName : total特征名称
* allowedCharacteristicName : 关联的数量型特征名称
* quantityCharacteristicName : 关联的数量型特征名称
*/
private String totalCharacteristicName;
private String allowedCharacteristicName;
private String quantityCharacteristicName;
}
package com.lcrx.selector.entity.PO;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* @author ###
*/
@NoArgsConstructor
@Data
public class VariantTablePO implements Serializable {
/**
* tableName :
* tableId : 1
* data : {"constraintCharacteristicName":["###","###"],"constraintCharacterValues":[{"groupNumber":"1","characteristicValues":[{"characteristicName":"###","values":["",""]},{"characteristicName":"###","values":["",""]}]}]}
*/
private String tableName;
private int tableId;
private DataBean data;
@NoArgsConstructor
@Data
public static class DataBean implements Serializable {
private List<String> constraintCharacteristicName;
private List<ConstraintCharacteristicValuesBean> constraintCharacteristicValues;
@NoArgsConstructor
@Data
public static class ConstraintCharacteristicValuesBean implements Serializable {
/**
* groupNumber : 1
* characteristicValues : [{"characteristicName":"###","values":["",""]},{"characteristicName":"###","values":["",""]}]
*/
private String groupNumber;
private List<CharacteristicValuesBean> characteristicValues;
@NoArgsConstructor
@Data
public static class CharacteristicValuesBean implements Serializable {
/**
* characteristicName : ###
* values : ["",""]
*/
private String characteristicName;
private List<String> values;
}
}
}
}
package com.lcrx.selector.entity.POJO;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.List;
import java.util.Map;
/**
* @author ###
*/
@Getter
@Setter
@NoArgsConstructor
public class TotalQuantityCalcResultPOJO {
private boolean result;
private boolean partialQuantitySelection = false;
private Map<String, Integer> totalCharacteristicValueList;
private List<String> forceCharacteristicValueList;
private List<String> characteristicValueList;
}
package com.lcrx.selector.enums;
public enum Action {
/**
* 新增
*/
ADD("新增"),
MODIFY("修改"),
DELETE("删除"),
VIEW("查看"),
EXPORT("导出"),
BULK_ADD("批量新增"),
BULK_MODIFY("批量修改"),
BULK_DELETE("批量删除"),
UPLOAD("上传"),
APPROVAL("审批"),
DROP_ORDER("下单"),
QUERY("查询"),
LOAD("加载"),
CONFIGURE("配置");
private String description;
Action(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}
package com.lcrx.selector.enums;
/**
* @author ###
*/
public enum CharacteristicType {
/**
* 字符型
*/
Char(0),
/**
* 数字型
*/
Num(1);
private final int characteristicType;
private CharacteristicType(int value) {
characteristicType = value;
}
public int getCharacteristicType() {
return characteristicType;
}
}
package com.lcrx.selector.enums;
public enum LogType {
/**
* API
*/
API("API"),
MQ("MQ"),
INPUT("INPUT"),
PROCESS("PROCESS"),
RESULT("RESULT"),
@Deprecated
TBD_1("TBD_1"),
@Deprecated
TBD_2("TBD_2");
private final String description;
LogType(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}
package com.lcrx.selector.enums;
/**
* @author ###
*/
public enum YesOrNo {
/**
* 否
*/
No(0),
/**
* 是
*/
Yes(1);
/**
* 是还是否
*/
private final int yesOrNo;
private YesOrNo(int value) {
yesOrNo = value;
}
public int getYesOrNo() {
return yesOrNo;
}
}
package com.lcrx.selector.exception;
import com.lcrx.selector.utils.result.ResultCode;
/**
* 说明: 权限异常
* 用户没有权限,无 token, token 过期, token 不可用等
*/
public class AuthorityException extends RuntimeException{
private static final long serialVersionUID = -1L;
public static final ResultCode TYPE = ResultCode.AUTHORITY;
public AuthorityException(String msg) {
super(msg);
}
public AuthorityException(String msg, Throwable e) {
super(msg, e);
}
public AuthorityException(Throwable e) {
super(e);
}
public static AuthorityException e(String message) {
return new AuthorityException(message);
}
}
package com.lcrx.selector.exception;
public class BadRequestException extends RuntimeException {
public BadRequestException(String message) {
super(message);
}
}
package com.lcrx.selector.exception;
import com.lcrx.selector.utils.result.ResultCode;
/**
* 说明: 业务异常
* 业务本身不允许的异常
* 例如,你在银行有一笔贷款,这笔贷款没有还完之前,不允许再次贷款。这种异常需要根据业务本身来指定。
*/
public class BusinessException extends RuntimeException{
private static final long serialVersionUID = -1L;
public static final ResultCode TYPE = ResultCode.BUSINESS;
public BusinessException(String msg) {
super(msg);
}
public BusinessException(String msg, Throwable e) {
super(msg, e);
}
public BusinessException(Throwable e) {
super(e);
}
public static BusinessException e(String message) {
return new BusinessException(message);
}
}
package com.lcrx.selector.exception;
/**
* @author FYG
* 异常类
*/
public class CommonException extends RuntimeException {
private static final long serialVersionUID = 1664292865075808287L;
private Integer result;
private String message;
/**
* @param result
* @param message
*/
public CommonException(Integer result, String message) {
super();
this.result = result;
this.message = message;
}
public Integer getResult() {
return result;
}
public void setResult(Integer result) {
this.result = result;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
package com.lcrx.selector.exception;
import com.lcrx.selector.utils.result.ResultCode;
/**
* 说明: 数据异常
* 1.1 传入参数合法性校验异常
* 例如入参非空校验,长度校验,格式校验等不符合规范
* 1.2 传入参数有效性校验的异常
* 例如传入的商品id,格式没有问题,但是根据这个id查询不到对应的商品
*
*/
public class DataException extends RuntimeException{
private static final long serialVersionUID = -1L;
public static final ResultCode TYPE = ResultCode.DATA;
public DataException(String msg) {
super(msg);
}
public DataException(String msg, Throwable e) {
super(msg, e);
}
public DataException(Throwable e) {
super(e);
}
public static DataException e(String message) {
return new DataException(message);
}
}
package com.lcrx.selector.exception;
public class ErrorCode {
public static final Integer OK = 200;
public static final Integer FAILED = 500;
/**
* 操作失败,需要确认
*/
public static final Integer NEED_CONFIRM = 510;
/**
* 产品OD或不可卖
*/
public static final Integer OD_DISABLE = 530;
public static final Integer BUSSINESS_FAILED = 550;
public static final Integer FORBIDDEN_FAILED = 403; //无业务权限
public static final Integer UNAUTHENTICATION = 401; //未登录
public static final Integer NOTFOUND = 404;
public static final Integer BADREQUEST = 400;
}
package com.lcrx.selector.exception;
import com.lcrx.selector.utils.result.Result;
import com.lcrx.selector.utils.result.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* 全局异常处理
*/
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
@Value("${applicationSettings.includeStackTrace}")
private Boolean includeStackTrace;
@ExceptionHandler(RuntimeException.class)
@ResponseBody
public Result<Void> runtimeHandler(RuntimeException e){
log.error(logPrefix(ResultCode.UNKNOWN), e);
return getResult(ResultCode.SYS,getMsg(e.getMessage(),ResultCode.UNKNOWN),getStackTrace(e));
}
@ExceptionHandler(AuthorityException.class)
@ResponseBody
public Result<Void> runtimeHandler(AuthorityException e){
log.error(logPrefix(ResultCode.AUTHORITY), e);
return getResult(ResultCode.AUTHORITY,getMsg(e.getMessage(),ResultCode.AUTHORITY),getStackTrace(e));
}
@ExceptionHandler(BusinessException.class)
@ResponseBody
public Result<Void> runtimeHandler(BusinessException e){
log.error(logPrefix(ResultCode.BUSINESS), e);
return getResult(ResultCode.BUSINESS,getMsg(e.getMessage(),ResultCode.BUSINESS),getStackTrace(e));
}
@ExceptionHandler(DataException.class)
@ResponseBody
public Result<Void> runtimeHandler(DataException e){
log.error(logPrefix(ResultCode.DATA), e);
return getResult(ResultCode.DATA,getMsg(e.getMessage(),ResultCode.DATA),getStackTrace(e));
}
@ExceptionHandler(ServiceException.class)
@ResponseBody
public Result<Void> runtimeHandler(ServiceException e){
log.error(logPrefix(ResultCode.SERVICE), e);
return getResult(ResultCode.SERVICE,getMsg(e.getMessage(),ResultCode.SERVICE),getStackTrace(e));
}
@ExceptionHandler(SysException.class)
@ResponseBody
public Result<Void> runtimeHandler(SysException e){
log.error(logPrefix(ResultCode.SYS), e);
return getResult(ResultCode.SYS,getMsg(e.getMessage(),ResultCode.SYS),getStackTrace(e));
}
private String logPrefix(ResultCode resultCode){
return "【" + resultCode.getMsg() + "】: ";
}
private Result<Void> getResult(ResultCode resultCode, String msg, String trace){
if (includeStackTrace) {
return Result.genResult(resultCode.getCode(),msg,trace);
}
return Result.genResult(resultCode.getCode(),msg);
}
private String getMsg(String eMessage,ResultCode resultCode){
String msg = "";
if (eMessage != null) {
int index = eMessage.indexOf(':');
msg = index != -1 ? eMessage.substring(index + 1).trim() : eMessage;
}
return resultCode == null ? msg : logPrefix(resultCode) + msg;
}
private String getStackTrace(Throwable error) {
StringWriter stackTrace = new StringWriter();
error.printStackTrace(new PrintWriter(stackTrace));
stackTrace.flush();
return stackTrace.toString();
}
}
package com.lcrx.selector.exception;
public class InvalidRequestException extends RuntimeException {
public InvalidRequestException(String message) {
super(message);
}
}
package com.lcrx.selector.exception;
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
package com.lcrx.selector.exception;
import com.lcrx.selector.utils.result.Result;
import com.lcrx.selector.utils.result.ResultCode;
/**
* 说明: 服务异常
* 调用其他服务异常
* 例如,订单服务调用商品服务,商品服务一致没有反应,或者商品服务那边报错,没有返回预期数据,而是返回了一个错误。
* @author :chengzi
* Create :2019/8/13 13:54
*/
public class ServiceException extends RuntimeException{
private static final long serialVersionUID = -1L;
public static final ResultCode TYPE = ResultCode.SERVICE;
public ServiceException(String msg) {
super(msg);
}
public ServiceException(String msg, Throwable e) {
super(msg, e);
}
public ServiceException(Throwable e) {
super(e);
}
public static ServiceException e(String message) {
return new ServiceException(message);
}
public static ServiceException e(String message, Throwable e) {
return new ServiceException(message,e);
}
public static String getServiceErrorResult(Result result) {
return ResultCode.SERVICE.getMsg() + ": " + result.getMessage() + ": " + result.getTrace();
}
}
package com.lcrx.selector.exception;
import com.lcrx.selector.utils.result.ResultCode;
/**
* 说明: 系统异常
* 系统本身的异常
* 例如,一些运行时异常,数据传输异常,数据库异常,网络异常等。
*/
public class SysException extends RuntimeException{
private static final long serialVersionUID = -1L;
public static final ResultCode TYPE = ResultCode.SYS;
public SysException(String msg) {
super(msg);
}
public SysException(String msg, Throwable e) {
super(msg, e);
}
public SysException(Throwable e) {
super(e);
}
public static SysException e(String message) {
return new SysException(message);
}
}
package com.lcrx.selector.repository;
import com.lcrx.selector.entity.PO.BusinessLogPO;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* @author ###
*/
@Repository
public interface BusinessLogRepository extends JpaRepository<BusinessLogPO, String> {
}
package com.lcrx.selector.repository;
import com.lcrx.selector.entity.PO.ConfigurationBasisPO;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @author ###
*/
@Repository
public interface ConfigurationBasisRepository extends JpaRepository<ConfigurationBasisPO, Long> {
/**
* 通过configId查找配置详情
* @param configIds 配置id
* @return 配置结果
*/
List<ConfigurationBasisPO> findAllByConfigId(List<Long> configIds);
}
package com.lcrx.selector.repository;
import com.lcrx.selector.entity.PO.ConfigurationCharacteristicValuePO;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/**
* @author ###
*/
@Repository
public interface ConfigurationCharacteristicValueRepository extends JpaRepository<ConfigurationCharacteristicValuePO, String> {
}
package com.lcrx.selector.service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.lcrx.selector.constant.RedisKey;
import com.lcrx.selector.entity.PO.QuantityMappingPO;
import com.lcrx.selector.entity.PO.TotalQuantityMappingPO;
import com.lcrx.selector.entity.PO.VariantTablePO;
import com.lcrx.selector.utils.RedisHelper;
import com.lcrx.selector.utils.StringHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* @author leafinsight
*/
@Service
public class SelectorCacheService {
private final RedisHelper redisHelper;
@Autowired
public SelectorCacheService(RedisHelper redisHelper) {
this.redisHelper = redisHelper;
}
/**
* @return VariantTable
*/
public List<VariantTablePO> getVariantTable(String systemCode, String productGroupCode, String materialCode) {
/* 第一层是VT#,第二层是Line#,第三层是特征#,第四层是特征值# */
List<VariantTablePO> variantTablePOList = null;
try {
String str = redisHelper.get(RedisKey.getVariantTableKey(systemCode, productGroupCode, materialCode));
if (!StringHelper.isNullOrEmpty(str)) {
variantTablePOList = JSON.parseObject(str, new TypeReference<List<VariantTablePO>>() {
});
}
} catch (Exception e) {
e.printStackTrace();
}
return variantTablePOList;
}
/**
* @return 数量型特征的主从映射关系
*/
List<QuantityMappingPO> getQuantityMapping(String systemCode) {
List<QuantityMappingPO> quantityMappingPOList = new ArrayList<>();
try {
String str = redisHelper.get(RedisKey.getQuantityMappingKey(systemCode));
if (!StringHelper.isNullOrEmpty(str)) {
quantityMappingPOList = JSON.parseObject(str, new TypeReference<List<QuantityMappingPO>>() {
});
}
} catch (Exception e) {
e.printStackTrace();
}
return quantityMappingPOList;
}
/**
* @return 数量型特征和total汇总特征的关系
*/
List<TotalQuantityMappingPO> getTotalQuantityMapping(String systemCode) {
List<TotalQuantityMappingPO> totalQuantityMappingPOList = new ArrayList<>();
try {
String str = redisHelper.get(RedisKey.getTotalQuantityMappingKey(systemCode));
if (!StringHelper.isNullOrEmpty(str)) {
totalQuantityMappingPOList = JSON.parseObject(str, new TypeReference<List<TotalQuantityMappingPO>>() {
});
}
} catch (Exception e) {
e.printStackTrace();
}
return totalQuantityMappingPOList;
}
}
package com.lcrx.selector.utils;
public class CastHelper {
@SuppressWarnings("unchecked")
public static <T> T cast(Object obj) {
return (T) obj;
}
}
package com.lcrx.selector.utils;
import java.text.DateFormat;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;
/**
* 时间转换
*/
public class DateHelper {
/**
* 获取现在时间
*
* @return 返回时间类型 yyyy-MM-dd HH:mm:ss
*/
public static Date getNowDate() {
Date currentTime = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = formatter.format(currentTime);
ParsePosition pos = new ParsePosition(8);
Date currentTime_2 = formatter.parse(dateString, pos);
return currentTime_2;
}
/**
* 获取现在时间
*
* @return返回字符串格式 yyyy-MM-dd HH:mm:ss
*/
public static String getStringDate() {
Date currentTime = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = formatter.format(currentTime);
return dateString;
}
public static String getSecondStringDate() {
Date currentTime = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
String dateString = formatter.format(currentTime);
return dateString;
}
/**
* 获取现在时间
*
* @return 返回短时间字符串格式yyyy-MM-dd
*/
public static String getStringDateShort() {
Date currentTime = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
String dateString = formatter.format(currentTime);
return dateString;
}
/**
* 获取时间 小时:分;秒 HH:mm:ss
*
* @return
*/
public static String getTimeShort() {
SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
Date currentTime = new Date();
String dateString = formatter.format(currentTime);
return dateString;
}
/**
* 将长时间格式字符串转换为时间 yyyy-MM-dd HH:mm:ss
*
* @param strDate
* @return
*/
public static Date strToDateLong(String strDate) {
if (Objects.isNull(strDate)) {
return null;
}
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
ParsePosition pos = new ParsePosition(0);
Date strtodate = formatter.parse(strDate, pos);
return strtodate;
}
/**
* 将长时间格式时间转换为字符串 yyyy-MM-dd HH:mm:ss
*
* @param dateDate
* @return
*/
public static String dateToStrLong(Date dateDate) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = formatter.format(dateDate);
return dateString;
}
/**
* 将短时间格式时间转换为字符串 yyyy-MM-dd
*
* @param dateDate
* @param
* @return
*/
public static String dateToStr(Date dateDate) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
String dateString = formatter.format(dateDate);
return dateString;
}
/**
* 将短时间格式字符串转换为时间 yyyy-MM-dd
*
* @param strDate
* @return
*/
public static Date strToDate(String strDate) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
ParsePosition pos = new ParsePosition(0);
Date strtodate = formatter.parse(strDate, pos);
return strtodate;
}
/**
* 得到现在时间
*
* @return
*/
public static Date getNow() {
//return strToDateLong(getStringDate());
Date currentTime = new Date();
return currentTime;
}
/**
* 提取一个月中的最后一天
*
* @param day
* @return
*/
public static Date getLastDate(long day) {
Date date = new Date();
long date_3_hm = date.getTime() - 3600000 * 34 * day;
Date date_3_hm_date = new Date(date_3_hm);
return date_3_hm_date;
}
/**
* 得到现在时间
*
* @return 字符串 yyyyMMdd HHmmss
*/
public static String getStringToday() {
Date currentTime = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd HHmmss");
String dateString = formatter.format(currentTime);
return dateString;
}
/**
* 得到现在小时
*/
public static String getHour() {
Date currentTime = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = formatter.format(currentTime);
String hour;
hour = dateString.substring(11, 13);
return hour;
}
/**
* 得到现在分钟
*
* @return
*/
public static String getTime() {
Date currentTime = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = formatter.format(currentTime);
String min;
min = dateString.substring(14, 16);
return min;
}
/**
* 根据用户传入的时间表示格式,返回当前时间的格式 如果是yyyyMMdd,注意字母y不能大写。
*
* @param sformat yyyyMMddhhmmss
* @return
*/
public static String getUserDate(String sformat) {
Date currentTime = new Date();
SimpleDateFormat formatter = new SimpleDateFormat(sformat);
String dateString = formatter.format(currentTime);
return dateString;
}
/**
* 根据用户传入的时间格式、字符串,验证字符串是否符合传入的时间格式
*
* @param DateFormat 时间格式
* @param str 字符串
* @return true验证通过 false验证失败
*/
public static boolean isValidDate(String DateFormat, String str) {
DateFormat formatter = new SimpleDateFormat(DateFormat);
try {
Date date = (Date) formatter.parse(str);
return str.equals(formatter.format(date));
} catch (Exception e) {
return false;
}
}
//时间字符串转为某种格式的时间字符串
public static String strFormatDateStr(String DateFormat, String str) {
DateFormat formatter = new SimpleDateFormat(DateFormat);
try {
Date date = (Date) formatter.parse(str);
return formatter.format(date);
} catch (Exception e) {
return getStringDate();
}
}
public static String formatDateByPattern(String dataPattern, Date date) {
SimpleDateFormat sdf = new SimpleDateFormat(dataPattern);
return sdf.format(date);
}
/**
* 根据String型时间,获取long型时间,单位毫秒
*
* @return long型时间
*/
public static long fromDateStringToLong() {
Date date = null;
SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss:SSS");
try {
date = inputFormat.parse(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss:SSS").format(new Date()));
} catch (Exception e) {
e.printStackTrace();
}
return date.getTime();
}
}
package com.lcrx.selector.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
/**
* redis帮助类
*
* @author ###
* @date 20211005
*/
@Component
public final class RedisHelper {
private RedisTemplate<String, String> redisTemplate;
@Autowired
public RedisHelper(RedisTemplate<String, String> redisTemplate)
{
this.redisTemplate = redisTemplate;
}
/**
* 设置缓存失效时间
*
* @param key 键
* @param time 时间(秒)
* @return
*/
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 判断key是否存在
*
* @param key 键
* @return true=存在 false=不存在
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除缓存
*
* @param key 可以传一个或多个
*/
public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
/**
* 普通缓存获取
*
* @param key 键
* @return 值
*/
public String get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
/**
* 普通缓存放入
*
* @param key 键
* @param value 值
* @return true=成功 false=失败
*/
public boolean set(String key, String value) {
try {
ValueOperations<String, String> operations = redisTemplate.opsForValue();
operations.set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 普通缓存放入并设置时间
*
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 表示无过期时间
* @return true=成功 false=失败
*/
public boolean set(String key, String value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
\ No newline at end of file
/**
* Copyright (c) 2011-2020, hubin (jobob@qq.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.lcrx.selector.utils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.concurrent.ThreadLocalRandom;
/**
* <p>
* 分布式高效有序ID生产黑科技(sequence) <br>
* 优化开源项目:http://git.oschina.net/yu120/sequence
* </p>
*
* @author hubin
* @date 2016-08-18
*/
@Component
public class SnowflakeHelper {
/**
* 机器标识位数
*/
private final long workerIdBits = 5L;
private final long datacenterIdBits = 5L;
private final long maxDatacenterId = ~(-1L << datacenterIdBits);
private final long workerId;
/**
* 数据标识id部分
*/
private final long datacenterId;
/**
* 0,并发控制
*/
private long sequence = 0L;
/**
* 上次生产id时间戳
*/
private long lastTimestamp = -1L;
public SnowflakeHelper() {
this.datacenterId = getDatacenterId();
this.workerId = getMaxWorkerId(datacenterId);
}
/**
* @param workerId 工作机器ID
* @param datacenterId 序列号
*/
public SnowflakeHelper(long workerId, long datacenterId) {
long maxWorkerId = ~(-1L << workerIdBits);
if (workerId > maxWorkerId || workerId < 0) {
throw new RuntimeException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new RuntimeException(
String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
}
/**
* <p>
* 获取 maxWorkerId
* </p>
*/
protected static long getMaxWorkerId(long datacenterId) {
StringBuilder mpid = new StringBuilder();
mpid.append(datacenterId);
String name = ManagementFactory.getRuntimeMXBean().getName();
if (StringUtils.isNotEmpty(name)) {
/*
* GET jvmPid
*/
mpid.append(name.split("@")[0]);
}
/*
* MAC + PID 的 hashcode 获取16个低位
*/
return (mpid.toString().hashCode() & 0xffff) % ((long) 31 + 1);
}
/**
* <p>
* 数据标识id部分
* </p>
*/
protected static long getDatacenterId() {
long id = 0L;
try {
InetAddress ip = InetAddress.getLocalHost();
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
if (network == null) {
id = 1L;
} else {
byte[] mac = network.getHardwareAddress();
if (null != mac) {
id = ((0x000000FF & (long) mac[mac.length - 1]) | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
id = id % ((long) 31 + 1);
}
}
} catch (Exception e) {
//logger.warn(" getDatacenterId: " + e.getMessage());
}
return id;
}
/**
* 获取下一个ID
*
*/
public synchronized long nextId() {
long timestamp = timeGen();
/* 闰秒 */
if (timestamp < lastTimestamp) {
long offset = lastTimestamp - timestamp;
if (offset <= 5) {
try {
wait(offset << 1);
timestamp = timeGen();
if (timestamp < lastTimestamp) {
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", offset));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", offset));
}
}
/*
毫秒内自增位
*/
long sequenceBits = 12L;
if (lastTimestamp == timestamp) {
// 相同毫秒内,序列号自增
long sequenceMask = ~(-1L << sequenceBits);
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
// 同一毫秒的序列数已经达到最大
timestamp = tilNextMillis(lastTimestamp);
}
} else {
// 不同毫秒内,序列号置为 1 - 3 随机数
sequence = ThreadLocalRandom.current().nextLong(1, 3);
}
lastTimestamp = timestamp;
/*
时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)
*/
long twepoch = 1288834974657L;
/*
时间戳左移动位
*/
long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
long datacenterIdShift = sequenceBits + workerIdBits;
return ((timestamp - twepoch) << timestampLeftShift) /* 时间戳部分 */
| (datacenterId << datacenterIdShift) /* 数据中心部分 */
| (workerId << sequenceBits) /* 机器标识部分 */
| sequence; /* 序列号部分 */
}
protected long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
protected long timeGen() {
return SystemClock.now();
}
}
package com.lcrx.selector.utils;
import java.util.*;
public class StringHelper extends org.springframework.util.StringUtils {
public static boolean isNullOrEmpty(String a) {
return a == null || a.isEmpty();
}
public static boolean isNullOrWhiteSpace(String a) {
return a == null || (a.length() > 0 && a.trim().length() <= 0);
}
/**
* @作者 尧
* @功能 String左对齐
*/
public static String padRight(String src, int len, char ch) {
int diff = len - src.length();
if (diff <= 0) {
return src;
}
char[] charr = new char[len];
System.arraycopy(src.toCharArray(), 0, charr, 0, src.length());
for (int i = src.length(); i < len; i++) {
charr[i] = ch;
}
return new String(charr);
}
/**
* @作者 尧
* @功能 String右对齐
*/
public static String padLeft(String src, int len, char ch) {
int diff = len - src.length();
if (diff <= 0) {
return src;
}
char[] charr = new char[len];
System.arraycopy(src.toCharArray(), 0, charr, diff, src.length());
for (int i = 0; i < diff; i++) {
charr[i] = ch;
}
return new String(charr);
}
public static String substringAndTrim(String src, int startLength, int endLength) {
return src.substring(startLength, endLength).replaceAll("^(0+)", "");
}
/**
* 把其他对象集合转成String集合
*
* @param aryObj
* @return
*/
public static List<String> convertToStringArray(List<Integer> aryObj) {
List<String> aryRet = new ArrayList<>();
for (Integer obj : aryObj) {
aryRet.add(obj.toString());
}
return aryRet;
}
/**
* 求ls对ls2的差集,即ls中有,但ls2中没有的
*
* @param ls
* @param ls2
* @return
*/
public static List diff(List ls, List ls2) {
List list = new ArrayList(Arrays.asList(new Object[ls.size()]));
Collections.copy(list, ls);
list.removeAll(ls2);
return list;
}
/**
* 求2个集合的交集
*
* @param ls
* @param ls2
* @return
*/
public static List intersect(List ls, List ls2) {
List list = new ArrayList(Arrays.asList(new Object[ls.size()]));
Collections.copy(list, ls);
list.retainAll(ls2);
return list;
}
/**
* 求2个集合的交集
*
* @param ls
* @param ls2
* @return
*/
public static List intersect(Set<String> ls, List ls2) {
List list = new ArrayList<String>(ls);
//Collections.copy(list, ls);
list.retainAll(ls2);
return list;
}
/**
* 求2个集合的并集
*
* @param ls
* @param ls2
* @return
*/
public static List union(List ls, List ls2) {
List list = new ArrayList(Arrays.asList(new Object[ls.size()]));
Collections.copy(list, ls);//将ls的值拷贝一份到list中
list.removeAll(ls2);
list.addAll(ls2);
return list;
}
//求两个字符串数组的并集,利用set的元素唯一性
public static String[] union(String[] arr1, String[] arr2) {
Set<String> set = new HashSet<String>();
for (String str : arr1) {
set.add(str);
}
for (String str : arr2) {
set.add(str);
}
String[] result = {};
return set.toArray(result);
}
//求两个数组的交集
public static String[] intersect(String[] arr1, String[] arr2) {
Map<String, Boolean> map = new HashMap<String, Boolean>();
LinkedList<String> list = new LinkedList<String>();
for (String str : arr1) {
if (!map.containsKey(str)) {
map.put(str, Boolean.FALSE);
}
}
for (String str : arr2) {
if (map.containsKey(str)) {
map.put(str, Boolean.TRUE);
}
}
for (Map.Entry<String, Boolean> e : map.entrySet()) {
if (e.getValue().equals(Boolean.TRUE)) {
list.add(e.getKey());
}
}
String[] result = {};
return list.toArray(result);
}
//求两个数组的差集
public static String[] minus(String[] arr1, String[] arr2) {
LinkedList<String> list = new LinkedList<String>();
LinkedList<String> history = new LinkedList<String>();
String[] longerArr = arr1;
String[] shorterArr = arr2;
//找出较长的数组来减较短的数组
if (arr1.length > arr2.length) {
longerArr = arr2;
shorterArr = arr1;
}
for (String str : longerArr) {
if (!list.contains(str)) {
list.add(str);
}
}
for (String str : shorterArr) {
if (list.contains(str)) {
history.add(str);
list.remove(str);
} else {
if (!history.contains(str)) {
list.add(str);
}
}
}
String[] result = {};
return list.toArray(result);
}
/*
* byte数组转换为十六进制的字符串
* **/
private static String conver16HexStr(byte[] b) {
StringBuffer result = new StringBuffer();
for (int i = 0; i < b.length; i++) {
if ((b[i] & 0xff) < 0x10) {
result.append("0");
}
result.append(Long.toString(b[i] & 0xff, 16));
}
return result.toString().toUpperCase();
}
/**
* 十六进制的字符串转换为byte数组
**/
private static byte[] conver16HexToByte(String hex16Str) {
char[] c = hex16Str.toCharArray();
byte[] b = new byte[c.length / 2];
for (int i = 0; i < b.length; i++) {
int pos = i * 2;
b[i] = (byte) ("0123456789ABCDEF".indexOf(c[pos]) << 4 | "0123456789ABCDEF".indexOf(c[pos + 1]));
}
return b;
}
}
/**
* Copyright (c) 2011-2020, hubin (jobob@qq.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.lcrx.selector.utils;
import java.sql.Timestamp;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
/**
* <p>
* 高并发场景下System.currentTimeMillis()的性能问题的优化
* </p>
* <p>
* System.currentTimeMillis()的调用比new一个普通对象要耗时的多(具体耗时高出多少我还没测试过,有人说是100倍左右)<br>
* System.currentTimeMillis()之所以慢是因为去跟系统打了一次交道<br>
* 后台定时更新时钟,JVM退出时,线程自动回收<br>
* 10亿:43410,206,210.72815533980582%<br>
* 1亿:4699,29,162.0344827586207%<br>
* 1000万:480,12,40.0%<br>
* 100万:50,10,5.0%<br>
* </p>
*
* @author hubin
* @Date 2016-08-01
*/
public class SystemClock {
private final long period;
private final AtomicLong now;
private SystemClock(long period) {
this.period = period;
this.now = new AtomicLong(System.currentTimeMillis());
scheduleClockUpdating();
}
private static SystemClock instance() {
return InstanceHolder.INSTANCE;
}
public static long now() {
return instance().currentTimeMillis();
}
public static String nowDate() {
return new Timestamp(instance().currentTimeMillis()).toString();
}
private void scheduleClockUpdating() {
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
public Thread newThread(Runnable runnable) {
Thread thread = new Thread(runnable, "System Clock");
thread.setDaemon(true);
return thread;
}
});
scheduler.scheduleAtFixedRate(new Runnable() {
public void run() {
now.set(System.currentTimeMillis());
}
}, period, period, TimeUnit.MILLISECONDS);
}
private long currentTimeMillis() {
return now.get();
}
private static class InstanceHolder {
public static final SystemClock INSTANCE = new SystemClock(1);
}
}
package com.lcrx.selector.utils.result;//package com.lenovo.ccb.pcaplmsworker.utils.result;
//
//import io.swagger.annotations.ApiModel;
//import io.swagger.annotations.ApiModelProperty;
//import lombok.AllArgsConstructor;
//import lombok.Data;
//import lombok.NoArgsConstructor;
//import lombok.ToString;
//import lombok.experimental.Accessors;
//
//import java.io.Serializable;
//
///**
// * 说明: 分页参数
// *
// * @author :chengzi
// * Create :2020/5/14 10:55
// */
//@Data
//@NoArgsConstructor
//@AllArgsConstructor
//@ToString
//@Accessors(chain = true)
//@ApiModel(description = "分页入参对象")
//public class PageParam<T> implements Serializable {
// private static final long serialVersionUID = 1L;
//
// @ApiModelProperty(name = "pageIndex", value = "当前页码")
// private Integer pageIndex = 1;
//
// @ApiModelProperty(name = "pageSize", value = "每页条数")
// private Integer pageSize = 10;
//
// @ApiModelProperty(name = "params", value = "参数")
// private T params;
//
// public void setPageIndex(Integer pageIndex) {
// if(pageIndex == null || pageIndex < 1){
// pageIndex = 1;
// }
// this.pageIndex = pageIndex;
// }
//
// public void setPageSize(Integer pageSize) {
// if(pageSize == null || pageSize < 1){
// pageSize = 1;
// }
// this.pageSize = pageSize;
// }
//}
package com.lcrx.selector.utils.result;//package com.lenovo.ccb.pcaplmsworker.utils.result;
//
//import com.github.pagehelper.PageInfo;
//import io.swagger.annotations.ApiModel;
//import io.swagger.annotations.ApiModelProperty;
//import lombok.Getter;
//import lombok.Setter;
//import lombok.ToString;
//import lombok.experimental.Accessors;
//
//import java.io.Serializable;
//import java.util.Collections;
//import java.util.List;
//
///**
// * 说明: 分页列表信息
// *
// * @author :chengzi
// * Create :2019/10/17 18:08
// */
//@Getter
//@Setter
//@ToString
//@Accessors(chain = true)
//@ApiModel(description = "分页出参对象")
//public class Pagination<T> implements Serializable {
// private static final long serialVersionUID = 1L;
//
// /**
// * 当前页
// */
// @ApiModelProperty(name = "pageIndex", value = "当前页")
// private int pageIndex;
//
// /**
// * 每页的数量
// */
// @ApiModelProperty(name = "pageSize", value = "每页的数量")
// private int pageSize;
//
// /**
// * 总记录数
// */
// @ApiModelProperty(name = "total", value = "总记录数")
// private long total;
//
// /**
// * 总页数
// */
// @ApiModelProperty(name = "pages", value = "总页数")
// private int pages;
//
// /**
// * 结果集
// */
// @ApiModelProperty(name = "list", value = "结果集")
// private List<T> list;
//
// /**
// * 是否有下一页
// */
// @ApiModelProperty(name = "hasNextPage", value = "是否有下一页")
// private boolean hasNextPage;
//
//
// public void setPageInfo(PageInfo pageInfo) {
// this.pageIndex = pageInfo.getPageNum();
// this.pageSize = pageInfo.getPageSize();
// this.total = pageInfo.getTotal();
// this.pages = pageInfo.getPages();
// this.hasNextPage = pageInfo.isHasNextPage();
// }
//
// public Pagination() {
// }
//
// public Pagination(PageInfo pageInfo) {
// this.pageIndex = pageInfo.getPageNum();
// this.pageSize = pageInfo.getPageSize();
// this.total = pageInfo.getTotal();
// this.pages = pageInfo.getPages();
// this.hasNextPage = pageInfo.isHasNextPage();
// this.list = Collections.emptyList();
// }
//}
package com.lcrx.selector.utils.result;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 统一API响应结果封装 * 新增对应枚举值的封装
* @author chengzi
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "响应结果集")
public class Result<T> implements Serializable {
/**
* 返回的code
*/
@ApiModelProperty(value = "自定义请求状态码")
private Integer result;
/**
* 返回的文言
*/
@ApiModelProperty(value = "自定义请求状态说明")
private String message;
/**
* 返回的数值
*/
@ApiModelProperty(value = "数据结果")
private T data;
/**
* 接口总耗时
*/
@ApiModelProperty(value = "接口耗时")
private Long took;
/**
* 异常堆栈信息
*/
@ApiModelProperty(value = "异常堆栈信息")
public String trace;
public static <T> Result<T> ok() {
return ok(ResultCode.SUCCESS.getMsg(), null);
}
public static <T> Result<T> ok(T data) {
return ok(ResultCode.SUCCESS.getMsg(), data);
}
public static <T> Result<T> ok(String message, T data) {
return Result.<T>builder()
.result(ResultCode.SUCCESS.getCode()).message(ResultCode.SUCCESS.getMsg()).data(data)
.build();
}
/**
* 自定义 code和 message
* @return 本身
*/
public static <T> Result<T> genResult(Integer code, String message) {
return Result.<T>builder()
.result(code).message(message).build();
}
/**
* 自定义 code和 message
* @return 本身
*/
public static <T> Result<T> genResult(Integer code, String message,String trace) {
return Result.<T>builder()
.result(code).message(message).trace(trace).build();
}
public static <T> Result<T> genResult(Integer code, String message, T data) {
return Result.<T>builder()
.result(code).message(message).data(data).build();
}
public boolean success() {
return ResultCode.SUCCESS.getCode() == result || 0 == result;
}
}
package com.lcrx.selector.utils.result;
import java.util.HashMap;
import java.util.Map;
/**
* @author
* 状态码
*/
public enum ResultCode {
/**
* 操作成功
*/
SUCCESS(200, "操作成功!"),
/**
* 数据异常
*/
DATA(400,"数据异常"),
/**
* 权限异常
*/
AUTHORITY(403,"权限异常"),
/**
* 业务异常
*/
BUSINESS(405,"业务异常"),
/**
* 系统异常
*/
SYS(500,"系统异常"),
/**
* 三方服务调用异常
*/
SERVICE(501,"三方服务调用异常"),
/**
* 未知异常
*/
UNKNOWN(9999,"未知异常"),
/**
* 传入的参数异常
*/
INPUT_DATA_ERROR(10001,"传入的参数异常");
ResultCode(int code, String msg) {
this.code = code;
this.msg = msg;
}
/**
* code
*/
private final int code;
/**
* 文言
*/
private final String msg;
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
/**
* 根据key获取value
*
* @param code : 键值key
* @return String
*/
public static String getMsgByCode(int code) {
ResultCode[] enums = ResultCode.values();
for (int i = 0; i < enums.length; i++) {
if (enums[i].getCode() == code) {
return enums[i].getMsg();
}
}
return "";
}
/**
* 转换为MAP集合
*
* @returnMap<String, String>
*/
public static Map<String, String> toMap() {
Map<String, String> map = new HashMap<String, String>();
ResultCode[] enums = ResultCode.values();
for (int i = 0; i < enums.length; i++) {
String key = String.valueOf(enums[i].getCode());
map.put(key, enums[i].getMsg());
}
return map;
}
}
spring:
redis:
host: ${REDIS_HOST:10.46.26.68}
port: ${REDIS_PORT:26379}
jedis:
pool:
max-active: 50
max-idle: 30
max-wait: 1000ms
ssl: false
database: 15
password: GreatWall@4rfv
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://10.46.26.68:5432/selector?currentSchema=public&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: postgres
password: GreatWall@4rfv
\ No newline at end of file
spring:
main:
allow-bean-definition-overriding: true
redis:
host: ${REDIS_HOST:123.56.187.202}
port: ${REDIS_PORT:26379}
jedis:
pool:
max-active: 50
max-idle: 30
max-wait: 1000ms
ssl: false
database: 15
password: a1b2c3d4
# flyway:
# enabled: true
# locations: classpath:db/migration
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://10.101.49.3:5432/selector_test?currentSchema=public
username: cfcrm
password: 1qaz@wsx
\ No newline at end of file
spring:
profiles:
active: cf
main:
allow-bean-definition-overriding: true
# flyway:
# enabled: true
# locations: classpath:db/migration
jpa:
properties:
hibernate:
temp:
use_jdbc_metadata_defaults: false
event:
merge.entity_copy_observer: allow
hibernate:
naming:
implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
ddl-auto: none
applicationSettings:
#缓存超时时间默认一天,单位秒
sessionTimeout: 86400
system: cc
#该variant table下没有任何有效的组,要有一个占位,逻辑验证是不能通过的
variantTableEmptyGroupPlaceholderValue: #
includeStackTrace: true
management:
health:
defaults:
enabled: false
server:
port: 8089
\ No newline at end of file
-- ----------------------------
-- create data structure
-- ----------------------------
/**
* configuration_basis
*/
CREATE TABLE configuration_basis (config_id int8 not null primary key,
product_group_code varchar(20),
material_code varchar(20),
operator varchar(50),
create_time timestamp(0)
);
/**
* configuration_characteristic_and_value
*/
CREATE TABLE configuration_characteristic_and_value (
id int8 not null primary key,
config_id int8 not null,
characteristic_name varchar(255),
characteristic_value_name varchar(255),
characteristic_value_quantity int4,
characteristic_value_desc text
);
/**
* business_log
*/
CREATE TABLE business_log (
id int8 not null primary key,
contents text
);
\ No newline at end of file
/**
* business_log
*/
CREATE TABLE business_log (
id int8 not null primary key,
contents text
);
This source diff could not be displayed because it is too large. You can view the blob instead.
.ivu-select-dropdown-list{padding-left:6px}
\ No newline at end of file
.ivu-select-dropdown-list{padding-left:6px}.arrow-class[data-v-abed09ee]{text-align:center;line-height:295px}.transfer-class[data-v-abed09ee]{margin:8px 0 0 0}[data-v-abed09ee] .ivu-modal-header{line-height:2!important;padding:5px 16px!important;height:40px!important;border-bottom:none!important}[data-v-abed09ee] .ivu-modal-fullscreen .ivu-modal-body{overflow-x:hidden!important;top:40px!important;bottom:0!important}[data-v-abed09ee] .ivu-modal-body{padding:0!important;background:#f2f2f2!important}.info[data-v-abed09ee]{height:620px}.info[data-v-abed09ee] .ivu-form-item{padding:4px 0!important;margin-top:0!important}.card-header[data-v-abed09ee] .ivu-card-head{padding:0 16px!important;height:40px}h4[data-v-abed09ee]{margin-bottom:0!important}
\ No newline at end of file
.contact-class[data-v-515709e0]{min-height:38px;padding:10px 10px}.height[data-v-515709e0]{height:120px}[data-v-515709e0] .ivu-btn{height:32px!important}
\ No newline at end of file
.add-product[data-v-0a94b457]{font-size:13px!important}.mt-20[data-v-0a94b457]{margin-top:20px}[data-v-0a94b457] .ivu-btn{height:32px!important}.transfer-class[data-v-0a94b457]{margin:8px 0 0 0}.arrow-class[data-v-0a94b457]{text-align:center;line-height:290px;height:520px}.table-class[data-v-0a94b457]{max-height:520px;overflow:hidden;overflow-y:auto}[data-v-0a94b457] .ivu-modal-header{line-height:2!important;padding:5px 16px!important;height:40px!important;border-bottom:none!important}[data-v-0a94b457] .ivu-modal-fullscreen .ivu-modal-footer{height:1px!important}[data-v-0a94b457] .ivu-modal-fullscreen .ivu-modal-body{bottom:0!important;overflow-x:hidden;top:40px!important}[data-v-0a94b457] .ivu-table .class-none{display:none}[data-v-0a94b457] .ivu-modal-body{padding:0!important;background:#f2f2f2!important}[data-v-0a94b457] .ivu-btn{height:28px!important}h4[data-v-0a94b457]{margin-bottom:0!important}
\ No newline at end of file
.configurator[data-v-d5540c9a]{background:#fff;height:100vh;padding:5px;overflow-y:scroll}[data-v-d5540c9a] .ant-table{font-size:13px!important}.activeValues[data-v-d5540c9a]{cursor:pointer}.mt10[data-v-d5540c9a]{margin-top:10px}.starClass[data-v-d5540c9a]{color:red}.btn-end[data-v-d5540c9a]{float:right}.characteristicValuesClass[data-v-d5540c9a]{line-height:32px}.characteristicValuesClass li[data-v-d5540c9a]{cursor:pointer;position:relative;padding-left:25px}.characteristicValuesClass li i[data-v-d5540c9a]{position:absolute;top:9px;left:2px}.check[data-v-d5540c9a]{margin-right:10px}.disableAtAll-value[data-v-d5540c9a]{margin:0;padding:0}.disableAtAll-value li[data-v-d5540c9a]{line-height:28px}.disableAtAll-value a[data-v-d5540c9a]{color:red}.disable-value-list[data-v-d5540c9a]{margin:0;padding:0}.disable-value-list li[data-v-d5540c9a]{line-height:28px}.disable-value-list a[data-v-d5540c9a]{color:grey}.characteristicValueItem[data-v-d5540c9a]{width:100%;display:inline-block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;height:25px;vertical-align:text-bottom}.ant-btn[data-v-d5540c9a]{height:28px!important;font-size:13px!important}[data-v-d5540c9a] .ant-progress-text{font-size:13px!important}
\ No newline at end of file
.ivu-select-dropdown-list{padding-left:6px}.ivu-modal-body{padding:6px!important}.titles[data-v-405513b3]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;-webkit-box-align:center;-ms-flex-align:center;align-items:center;text-align:40px;height:40px}[data-v-405513b3] .ivu-modal-fullscreen .ivu-modal-body{overflow-x:hidden!important;top:40px!important;bottom:0!important;padding:0!important}[data-v-405513b3] .ivu-modal-body{padding:0!important;background:#f2f2f2!important}[data-v-405513b3] .ivu-modal-header{line-height:2!important;padding:5px 16px!important;height:40px!important;border-bottom:none!important}.mtb-10[data-v-405513b3]{margin:10px 0}.footer[data-v-405513b3] .ivu-btn{height:32px!important}.transfer-class[data-v-405513b3]{margin:8px 0 0 0}.arrow-class[data-v-405513b3]{text-align:center}.arrow-class[data-v-405513b3] .ivu-btn{padding:0 12px}[data-v-405513b3] .ivu-modal-fullscreen .ivu-modal-footer{height:1px!important;padding:0!important}.card-header[data-v-405513b3] .ivu-card-head{padding:0 16px!important;height:40px}.card-header[data-v-405513b3] .ivu-form-item{margin-top:0!important}h4[data-v-405513b3]{margin-bottom:0!important}
\ No newline at end of file
.message-page-con{height:calc(100vh - 176px);display:inline-block;vertical-align:top;position:relative}.message-page-con.message-category-con{border-right:1px solid #e6e6e6;width:200px}.message-page-con.message-list-con{border-right:1px solid #e6e6e6;width:230px}.message-page-con.message-view-con{position:absolute;left:446px;top:16px;right:16px;bottom:16px;overflow:auto;padding:12px 20px 0}.message-page-con.message-view-con .message-view-header{margin-bottom:20px}.message-page-con.message-view-con .message-view-header .message-view-title{display:inline-block}.message-page-con.message-view-con .message-view-header .message-view-time{margin-left:20px}.message-page-con .category-title{display:inline-block;width:65px}.message-page-con .gray-dadge{background:#dcdcdc}.message-page-con .not-unread-list .msg-title{color:#aaa9a9}.message-page-con .not-unread-list .ivu-menu-item .ivu-btn.ivu-btn-text.ivu-btn-small.ivu-btn-icon-only{display:none}.message-page-con .not-unread-list .ivu-menu-item:hover .ivu-btn.ivu-btn-text.ivu-btn-small.ivu-btn-icon-only{display:inline-block}
\ No newline at end of file
.titles[data-v-21f411da]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;-webkit-box-align:center;-ms-flex-align:center;align-items:center;text-align:40px;height:40px}.featrue-class[data-v-21f411da]{border:1px solid #e8eaec;border-radius:4px;padding:5px;margin:5px}.featrue-class h4[data-v-21f411da]{margin:5px}.arrow-class[data-v-21f411da]{text-align:center;line-height:215px;height:430px}[data-v-21f411da] .ivu-modal-header{line-height:2!important;padding:5px 16px!important;height:40px!important;border-bottom:none!important}[data-v-21f411da] .ivu-modal-fullscreen .ivu-modal-body{top:38px!important;overflow-x:hidden;bottom:0!important}.transfer-class[data-v-21f411da]{margin:8px 0 0 0}[data-v-21f411da] .ivu-modal-body{padding:0!important;background:#f2f2f2!important}[data-v-21f411da] .ivu-modal-fullscreen .ivu-modal-footer{height:1px!important;padding:0!important}h4[data-v-21f411da]{margin-bottom:0!important}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment