Commit 8759616b authored by 李健华's avatar 李健华

big-stms new stms

parents
Pipeline #1830 failed with stages
**/target/
**/.settings/
**/.classpath
**/.project
**/.idea/
**/*.iml
**/.factorypath
*.log
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>cn.quantgroup.big</groupId>
<artifactId>stms</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>stms</name>
<description>大数据部门 结算系统</description>
<url>http://maven.apache.org</url>
<parent>
<groupId>cn.quantgroup</groupId>
<artifactId>commons-parent</artifactId>
<version>0.5.4</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<maven.test.skip>true</maven.test.skip>
<aviator.version>4.2.5</aviator.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.10.0</version>
</dependency>
<dependency>
<groupId>cn.quantgroup</groupId>
<artifactId>security</artifactId>
<version>0.1.2</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>logging-interceptor</artifactId>
<version>3.10.0</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>*</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
<version>1.5.8.RELEASE</version>
</dependency>
<dependency>
<groupId>cn.quantgroup</groupId>
<artifactId>commons-spring</artifactId>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
<exclusion>
<groupId>io.reactivex</groupId>
<artifactId>rxnetty</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!-- <dependency>
<groupId>cn.quantgroup</groupId>
<artifactId>brave-spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>-->
<dependency>
<groupId>cn.quantgroup</groupId>
<artifactId>shutdown-spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- mongodb依赖 -->
<!-- <dependency>-->
<!-- <groupId>org.springframework.data</groupId>-->
<!-- <artifactId>spring-data-mongodb</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-data-mongodb</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.mongodb</groupId>-->
<!-- <artifactId>mongo-java-driver</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
<scope>compile</scope>
</dependency>
<!-- mail -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.10</version>
<!--
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
-->
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>com.googlecode.aviator</groupId>
<artifactId>aviator</artifactId>
<version>${aviator.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.36.Final</version>
</dependency>
<!--xxl-job-->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.1.0</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
</resource>
<resource>
<directory>${project.build.directory}/generated-resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<compilerArgs>
<arg>-Xlint:unchecked</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package cn.quantgroup.big.stms;
import feign.Logger;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
//@SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
@Slf4j
@ComponentScan(basePackages = {"cn.quantgroup.big.stms.*"})
@EnableTransactionManagement
@EnableAsync
@EnableFeignClients
public class BigSTMSApplication {
public static void main(String[] args) {
SpringApplication.run(BigSTMSApplication.class, args);
log.info("big stms started...");
}
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
package cn.quantgroup.big.stms.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 枚举的key,可以通过它获取到对应的枚举类,不能重复
*
* @author rong yang
* @date 2019/12/07 15:16
**/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface EnumKey {
String value();
}
package cn.quantgroup.big.stms.common.aop;
import cn.quantgroup.big.stms.common.context.AppContextHolder;
import cn.quantgroup.big.stms.common.context.OnlineUser;
import cn.quantgroup.big.stms.common.utils.IpAddrUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
/**
* 访问日志记录
* @author rong yang
*
*/
@Aspect
@Component
public class AccessLogAspect {
private final static Logger logger = LoggerFactory.getLogger(AccessLogAspect.class);
@Autowired
private ObjectMapper objectMapper;
/** 以 controller 包下定义的所有请求为切入点 */
@Pointcut("execution(public * cn.quantgroup.big.stms..controller.*.*(..)) && !execution(public * cn.quantgroup.big.stms.sys.controller.OauthController.login(..))")
public void accessPointcut() {}
/**
* 在切点之前织入
* @param joinPoint
* @throws Throwable
*/
@Before("accessPointcut()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
logger.info("-------------------------------------------------- start --------------------------------------------------");
logger.info("IP : {}", IpAddrUtils.getIpAddr(request));
OnlineUser onlineUser = AppContextHolder.getOnlineUser();
if(null != onlineUser) {
logger.info("Access User : {}", onlineUser.getAccount());
}
logger.info("URL : {}", request.getRequestURL().toString());
logger.info("HTTP Method : {}", request.getMethod());
logger.info("Class Method : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
logger.info("Request Args : {}", tojson(joinPoint.getArgs()));
}
@SuppressWarnings("unchecked")
private final String tojson(Object[] args) throws Throwable{
if(null == args) {
return null;
}
@SuppressWarnings("rawtypes")
List printArgs = new ArrayList();
for(Object obj : args) {
if(obj instanceof ServletRequest || obj instanceof ServletResponse) {
continue;
}
printArgs.add(obj);
}
return objectMapper.writeValueAsString(printArgs);
}
/**
* 在切点之后织入
* @throws Throwable
*/
@After("accessPointcut()")
public void doAfter() throws Throwable {
logger.info("--------------------------------------------------- end ---------------------------------------------------");
}
/**
* 环绕
* @param proceedingJoinPoint
* @return
* @throws Throwable
*/
@Around("accessPointcut()")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = proceedingJoinPoint.proceed();
logger.debug("Response Data : {}", objectMapper.writeValueAsString(result));
logger.info("Time-Consuming : {} ms", System.currentTimeMillis() - startTime);
return result;
}
}
package cn.quantgroup.big.stms.common.aop;
import cn.quantgroup.big.stms.common.constants.HttpReqHeadKeyCnst;
import cn.quantgroup.big.stms.common.constants.StmsConstants;
import cn.quantgroup.big.stms.common.context.AppContextHolder;
import cn.quantgroup.big.stms.common.context.OnlineUser;
import cn.quantgroup.big.stms.common.enums.TenantEnum;
import cn.quantgroup.big.stms.common.exception.BizException;
import cn.quantgroup.big.stms.common.result.ResultCode;
import cn.quantgroup.big.stms.common.service.PermissionService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.HashSet;
import java.util.Set;
/**
* 权限处理
*
* @author yutong
* @data 2020年1月19日
*/
@Aspect
@Order(99)
@Component
@Slf4j
public class PermissionAop {
@Autowired
private PermissionService service;
/**
* 先使用弱校验, 仅保证关键后端接口增加注解后校验权限
*/
// @Pointcut(value = "@annotation(cn.quantgroup.big.stms.common.annotation.Permission)")
@Pointcut("execution(public * cn.quantgroup.big.stms..controller.*.*(..)) && !execution(public * cn.quantgroup.big.stms.sys.controller.OauthController.login(..))")
private void cutPermission() {
}
@Around("cutPermission()")
public Object checkPermission(ProceedingJoinPoint point) throws Throwable {
MethodSignature ms = (MethodSignature) point.getSignature();
// Permission permission = ms.getMethod().getAnnotation(Permission.class);
OnlineUser onlineUser = AppContextHolder.getOnlineUser();
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String tenantId = request.getHeader(HttpReqHeadKeyCnst.tenantId);
Integer tenant = TenantEnum.KDSP.getTenantId();
if(StringUtils.isNotEmpty(tenantId) && !"undefined".equals(tenantId)){
tenant=Integer.parseInt(tenantId);
}
// 先判断用户&角色
if (onlineUser == null) {
return point.proceed();
} else if (onlineUser.getId().equalsIgnoreCase(StmsConstants.ADMINISTRATOR_ID)) {
log.debug("超级管理员访问,越过权限处理!");
// 超级管理员
return point.proceed();
} else {
String requestUrl = getRequestURL();
log.info("用户:{},请求路径:{}", onlineUser.getName(), requestUrl);
// String appCode = req.getHeader("AppCode");
if (service.checkIgnore(requestUrl)) {
// 忽略全局无需验证权限的接口
return point.proceed();
} else if (service.checkUri(tenant,requestUrl)) {
// 通过redis中缓存的权限匹配
return point.proceed();
} else {
throw new BizException("没有权限,拒绝访问", ResultCode.FORBIDDEN);
}
}
}
/**
* 从req中获取url
* @return
*/
private String getRequestURL() {
// 判断用户登录应用系统(TODO 考虑通过域名或登录时指定的应用AppCode)
HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest();
// StringBuffer requestURL = req.getRequestURL();
// String params_ymbol = "?";
// String anchor_ymbol = "#";
// if (requestURL.indexOf(anchor_ymbol) > -1) {
// requestURL.deleteCharAt(requestURL.indexOf(anchor_ymbol));
// }
// if (requestURL.indexOf(params_ymbol) > -1) {
// requestURL.deleteCharAt(requestURL.indexOf(params_ymbol));
// }
return req.getRequestURI();
}
/*
* 从RequestMapping中获取全部uri
*/
private String[] getMappingUri(MethodSignature ms) {
Set<String> mappingUri = new HashSet<>();
@SuppressWarnings("unchecked")
RequestMapping tma = (RequestMapping) ms.getDeclaringType().getAnnotation(RequestMapping.class);
RequestMapping mma = ms.getMethod().getAnnotation(RequestMapping.class);
GetMapping gma = ms.getMethod().getAnnotation(GetMapping.class);
PostMapping pma = ms.getMethod().getAnnotation(PostMapping.class);
String[] tms = tma.value().length > 0 ? tma.value() : new String[] { "" };
if (mma != null && mma.value().length > 0) {
doubleloop(mappingUri, tms, mma.value());
} else if (gma != null && gma.value().length > 0) {
doubleloop(mappingUri, tms, gma.value());
} else if (pma != null && pma.value().length > 0) {
doubleloop(mappingUri, tms, pma.value());
} else {
mappingUri.add(tms[0]);
}
if (log.isDebugEnabled()) {
for (String mu : mappingUri) {
log.debug("用户访问后端controller层mapping: {}", mu);
}
}
return mappingUri.toArray(new String[mappingUri.size()]);
}
private void doubleloop(Set<String> mappingUri, String[] ph1, String[] ph2) {
for (String h1 : ph1) {
for (String h2 : ph2) {
mappingUri.add(h1 + h2);
}
}
}
}
package cn.quantgroup.big.stms.common.aviator.ext.function;
import com.googlecode.aviator.exception.ExpressionRuntimeException;
import com.googlecode.aviator.runtime.function.AbstractVariadicFunction;
import com.googlecode.aviator.runtime.type.AviatorObject;
import java.util.Map;
/**
* case 函数<br/>
* 表达式判断函数,case(x1,x2,...,xn):表示如果x1为真,则返回x2;x3为真,返回x4.以此类推如果,如果参数有奇数个,最后一个为默认值
*
*
* @author rong yang
*
*/
public class CaseFunction extends AbstractVariadicFunction {
/**
* 表达式在参数中的步长
*/
private final int EXP_STEP = 2;
@Override
public String getName() {
return "case";
}
@Override
public AviatorObject variadicCall(Map<String, Object> env, AviatorObject... args) {
for (int i = 0; i < args.length - 1; i += EXP_STEP) {
Boolean value = (Boolean)args[i].getValue(env);
if(value != null && value.booleanValue()){
return args[i + 1];
}
}
if (args.length % EXP_STEP == 1) {
return args[args.length - 1];
} else {
throw new ExpressionRuntimeException("case函数没有匹配到合适的值,并且没有默认值!");
}
}
}
package cn.quantgroup.big.stms.common.aviator.ext.function;
import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;
import com.googlecode.aviator.exception.ExpressionRuntimeException;
import com.googlecode.aviator.runtime.function.AbstractFunction;
import com.googlecode.aviator.runtime.function.FunctionUtils;
import com.googlecode.aviator.runtime.type.AviatorLong;
import com.googlecode.aviator.runtime.type.AviatorObject;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.Map;
/**
*
* <p>
* description: 计算指定日期与当前日期相差天数
* </p>
*
* @author rong.yang/阳荣
*
*/
public class DaysDiffFunction extends AbstractFunction {
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject date) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String sd1 = FunctionUtils.getStringValue(date, env);
if(null == sd1 || 0 == sd1.trim().length()) {
throw new ExpressionRuntimeException(getName() + "函数参数不能为空!");
}
LocalDate date1 = LocalDate.parse(sd1, formatter);
long days = ChronoUnit.DAYS.between(date1, LocalDate.now());
return AviatorLong.valueOf(days);
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String sd1 = FunctionUtils.getStringValue(arg1, env);
if(null == sd1 || 0 == sd1.trim().length()) {
throw new ExpressionRuntimeException(getName() + "函数参数不能为空!");
}
String sd2 = FunctionUtils.getStringValue(arg2, env);
if(null == sd2 || 0 == sd2.trim().length()) {
throw new ExpressionRuntimeException(getName() + "函数参数不能为空!");
}
LocalDate date1 = LocalDate.parse(sd1, formatter);
LocalDate date2 = LocalDate.parse(sd2, formatter);
long days = ChronoUnit.DAYS.between(date1, date2);
return AviatorLong.valueOf(days);
}
public String getName() {
return "date.daysDiff";
}
public static void main(String[] args) {
AviatorEvaluator.addFunction(new DaysDiffFunction());
String expression = "date.daysDiff(date)";
Map env = new HashMap();
env.put("date", "2019-10-01");
Expression ex = AviatorEvaluator.compile(expression, true);
Object obj = ex.execute(env);
System.out.println(obj);
Object rs = AviatorEvaluator.execute("date.daysDiff(date)", env);
System.out.println(rs);
}
}
package cn.quantgroup.big.stms.common.aviator.ext.function;
import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.exception.ExpressionRuntimeException;
import com.googlecode.aviator.runtime.function.AbstractVariadicFunction;
import com.googlecode.aviator.runtime.function.FunctionUtils;
import com.googlecode.aviator.runtime.type.AviatorObject;
import java.util.HashMap;
import java.util.Map;
/**
* decode 函数 与oracle的decode函数定义一样
*
* @author rong yang
*
*/
public class DecodeFunction extends AbstractVariadicFunction {
/**
* 表达式在参数中的步长
*/
private final int EXP_STEP = 2;
@Override
public String getName() {
return "decode";
}
@Override
public AviatorObject variadicCall(Map<String, Object> env, AviatorObject... args) {
Number rs = FunctionUtils.getNumberValue(args[0], env);
for (int i = 1; i < args.length - 1; i += EXP_STEP) {
if (rs.intValue() == FunctionUtils.getNumberValue(args[i], env).intValue()) {
return args[i + 1];
}
}
if (args.length % EXP_STEP == 0) {
return args[args.length - 1];
} else {
throw new ExpressionRuntimeException("decode函数没有匹配到合适的值,并且没有默认值!");
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void main(String[] args) {
AviatorEvaluator.addFunction(new DecodeFunction());
Integer[] a = new Integer[]{20,21,22,23};
Map map = new HashMap();
map.put("a", a);
Object rs = AviatorEvaluator.execute("decode(20,a[0],2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19)",map);
System.out.println(rs);
}
}
package cn.quantgroup.big.stms.common.aviator.ext.function;
import com.googlecode.aviator.runtime.function.AbstractFunction;
import com.googlecode.aviator.runtime.function.FunctionUtils;
import com.googlecode.aviator.runtime.type.AviatorLong;
import com.googlecode.aviator.runtime.type.AviatorObject;
import java.util.Map;
/**
* sign(d) function
*
* @author rong yang
*
*/
public class MathSignFunction extends AbstractFunction {
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1) {
Number num = FunctionUtils.getNumberValue(arg1, env);
if(num.doubleValue() > 0){
return AviatorLong.valueOf(1);
}else if(num.doubleValue() < 0){
return AviatorLong.valueOf(-1);
}else{
return AviatorLong.valueOf(0);
}
}
public String getName() {
return "math.sign";
}
}
package cn.quantgroup.big.stms.common.aviator.ext.function;
import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.exception.ExpressionRuntimeException;
import com.googlecode.aviator.runtime.function.AbstractFunction;
import com.googlecode.aviator.runtime.function.FunctionUtils;
import com.googlecode.aviator.runtime.type.AviatorLong;
import com.googlecode.aviator.runtime.type.AviatorObject;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.Map;
/**
*
* <p>
* description: 计算指定日期所在月份的月份差
* </p>
*
* @author rong.yang/阳荣
*
*/
public class MonthsDiffFunction extends AbstractFunction {
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject date) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String sd1 = FunctionUtils.getStringValue(date, env);
if(null == sd1 || 0 == sd1.trim().length()) {
throw new ExpressionRuntimeException(getName() + "函数参数不能为空!");
}
LocalDate date1 = LocalDate.parse(sd1, formatter);
LocalDate date11 = LocalDate.of(date1.getYear(), date1.getMonth(), 1);
LocalDate now = LocalDate.now();
long months = ChronoUnit.MONTHS.between(date11, LocalDate.of(now.getYear(), now.getMonth(), 1));
return AviatorLong.valueOf(months);
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String sd1 = FunctionUtils.getStringValue(arg1, env);
if(null == sd1 || 0 == sd1.trim().length()) {
throw new ExpressionRuntimeException(getName() + "函数参数不能为空!");
}
String sd2 = FunctionUtils.getStringValue(arg2, env);
if(null == sd2 || 0 == sd2.trim().length()) {
throw new ExpressionRuntimeException(getName() + "函数参数不能为空!");
}
LocalDate date1 = LocalDate.parse(sd1, formatter);
LocalDate date11 = LocalDate.of(date1.getYear(), date1.getMonth(), 1);
LocalDate date2 = LocalDate.parse(sd2, formatter);
LocalDate date22 = LocalDate.of(date2.getYear(), date2.getMonth(), 1);
long months = ChronoUnit.MONTHS.between(date11, LocalDate.of(date22.getYear(), date22.getMonth(), 1));
return AviatorLong.valueOf(months);
}
public String getName() {
return "date.monthsDiff";
}
public static void main(String[] args) {
AviatorEvaluator.addFunction(new MonthsDiffFunction());
Map map = new HashMap();
map.put("a", "2019-10-05");
Object rs = AviatorEvaluator.execute("date.monthsDiff(a,'2019-11-03')", map);
System.out.println(rs);
}
}
package cn.quantgroup.big.stms.common.aviator.ext.function;
import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Options;
import com.googlecode.aviator.runtime.function.AbstractFunction;
import com.googlecode.aviator.runtime.function.FunctionUtils;
import com.googlecode.aviator.runtime.type.AviatorDecimal;
import com.googlecode.aviator.runtime.type.AviatorObject;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Map;
public class RoundDownFunction extends AbstractFunction {
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject number) {
Number num = FunctionUtils.getNumberValue(number, env);
if (num == null) {
return AviatorDecimal.valueOf("0.00");
}
BigDecimal m = BigDecimal.valueOf(num.doubleValue()).setScale(2, RoundingMode.DOWN);
return AviatorDecimal.valueOf(m);
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
Number num = FunctionUtils.getNumberValue(arg1, env);
if (num == null) {
return AviatorDecimal.valueOf("0.00");
}
Number scale = FunctionUtils.getNumberValue(arg2, env);
int newScale = scale == null ? 2 : scale.intValue();
BigDecimal m = BigDecimal.valueOf(num.doubleValue()).setScale(newScale, RoundingMode.DOWN);
return AviatorDecimal.valueOf(m);
}
@Override
public String getName() {
return "math.round_down";
}
public static void main(String[] args) {
AviatorEvaluator.setOption(Options.ALWAYS_PARSE_FLOATING_POINT_NUMBER_INTO_DECIMAL, true);
AviatorEvaluator.addFunction(new RoundDownFunction());
Object rs = AviatorEvaluator.execute("math.round_down(3.425,2)");
System.out.println(rs);
rs = AviatorEvaluator.execute("math.round_down(3.424,2)");
System.out.println(rs);
rs = AviatorEvaluator.execute("math.round_down(3.426,2)");
System.out.println(rs);
}
}
package cn.quantgroup.big.stms.common.aviator.ext.function;
import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Options;
import com.googlecode.aviator.runtime.function.AbstractFunction;
import com.googlecode.aviator.runtime.function.FunctionUtils;
import com.googlecode.aviator.runtime.type.AviatorDecimal;
import com.googlecode.aviator.runtime.type.AviatorObject;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;
/**
* 四舍五入
* @author rong yang
*
*/
public class RoundFunction extends AbstractFunction {
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject number) {
Number num = FunctionUtils.getNumberValue(number, env);
if (num == null) {
return AviatorDecimal.valueOf("0.00");
}
BigDecimal m = BigDecimal.valueOf(num.doubleValue()).setScale(2, RoundingMode.HALF_UP);
return AviatorDecimal.valueOf(m);
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
Number num = FunctionUtils.getNumberValue(arg1, env);
if (num == null) {
return AviatorDecimal.valueOf("0.00");
}
Number scale = FunctionUtils.getNumberValue(arg2, env);
int newScale = scale == null ? 2 : scale.intValue();
BigDecimal m = new BigDecimal(num.toString()).setScale(newScale, RoundingMode.HALF_UP);
return AviatorDecimal.valueOf(m);
}
@Override
public String getName() {
return "math.round";
}
public static void main(String[] args) {
AviatorEvaluator.setOption(Options.ALWAYS_PARSE_FLOATING_POINT_NUMBER_INTO_DECIMAL, true);
AviatorEvaluator.addFunction(new RoundFunction());
AviatorEvaluator.addFunction(new CaseFunction());
Map<String,Object> env = new HashMap<>();
env.put("term",6);
Object rs = AviatorEvaluator.execute("case(term <= 6, 6000.00*(0.04670-0.472*math.round((3542.67/78000),5))-130.7923, term == 9, 6000.00*(0.07502-0.508*math.round((3542.67/78000),5))-130.7923, term == 12, 6000.00*(0.10328-0.544*math.round((3542.67/78000),5))-130.7923)");
System.out.println(rs);
rs = AviatorEvaluator.execute("math.round(3.424445,5)");
System.out.println(rs);
rs = AviatorEvaluator.execute("math.round(3.426444,5)");
System.out.println(rs);
}
}
package cn.quantgroup.big.stms.common.aviator.ext.function;
import com.googlecode.aviator.runtime.function.AbstractFunction;
import com.googlecode.aviator.runtime.function.FunctionUtils;
import com.googlecode.aviator.runtime.type.AviatorDecimal;
import com.googlecode.aviator.runtime.type.AviatorObject;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Map;
public class RoundUpFunction extends AbstractFunction {
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject number) {
Number num = FunctionUtils.getNumberValue(number, env);
if (num == null) {
return AviatorDecimal.valueOf("0.00");
}
BigDecimal m = BigDecimal.valueOf(num.doubleValue()).setScale(2, RoundingMode.UP);
return AviatorDecimal.valueOf(m);
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
Number num = FunctionUtils.getNumberValue(arg1, env);
if (num == null) {
return AviatorDecimal.valueOf("0.00");
}
Number scale = FunctionUtils.getNumberValue(arg2, env);
int newScale = scale == null ? 2 : scale.intValue();
BigDecimal m = BigDecimal.valueOf(num.doubleValue()).setScale(newScale, RoundingMode.UP);
return AviatorDecimal.valueOf(m);
}
@Override
public String getName() {
return "math.round_up";
}
}
package cn.quantgroup.big.stms.common.config;
import cn.quantgroup.big.stms.common.convert.UniversalEnumConverterFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* 枚举转换器配置
* @Author meng.xin@quantgroup.cn
* @Date 2019-11-06 16:42
* @Version 1.0
*/
@Configuration
public class ConvertConfig extends WebMvcConfigurerAdapter {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverterFactory(new UniversalEnumConverterFactory());
}
}
\ No newline at end of file
package cn.quantgroup.big.stms.common.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.mail.*;
import java.util.Properties;
@Component
public class EmailAuthentication implements IAuthentication{
private static Logger logger = LoggerFactory.getLogger(EmailAuthentication.class);
private static final int TIMEOUT = 10000;
private static final int CONNECTION_TIMEOUT = 10000;
private static final int WRITE_TIMEOUT = 10000;
/**
* 通过邮件系统,验证用户名密码的合法性
*
* @param username
* @param password
* @return
*/
@Override
public boolean authenticate(final String username, final String password) {
//新邮箱服务
String u = username.endsWith("@quantgroup.cn") ? username : username + "@quantgroup.cn";
Properties props = new Properties();
props.put("mail.debug", "false");
props.put("mail.smtp.timeout", TIMEOUT);//milliseconds
props.put("mail.smtp.connectiontimeout", CONNECTION_TIMEOUT);
props.put("mail.smtp.writetimeout", WRITE_TIMEOUT);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.host", "mail.quantgroup.cn"); // smtp主机名。
props.put("mail.smtp.port", "587");
boolean success = authenticate(u, password, props);
return success;
}
/**
* <p>
* description: 邮件服务器认证
* </p>
*
* @param
* @return
* @author rong.yang/阳荣
*/
private boolean authenticate(final String username, final String password, final Properties props) {
boolean success = false;
// 邮件用户名密码认证。
Authenticator authenticator = new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
};
Session session = Session.getInstance(props, authenticator);
Transport transport = null;
try {
transport = session.getTransport("smtp");
transport.connect();
success = true;
} catch (NoSuchProviderException e) {
logger.warn("通过邮箱账户登录失败:" + e.getMessage());
} catch (javax.mail.MessagingException e) {
logger.warn("通过邮箱账户登录失败:" + e.getMessage());
} finally {
if (null != transport) {
try {
transport.close();
} catch (javax.mail.MessagingException e) {
logger.warn("通过邮箱账户登录失败:" + e.getMessage());
}
}
}
return success;
}
}
package cn.quantgroup.big.stms.common.config;
/**
* 用户认证接口
*/
public interface IAuthentication {
/**
* 用户认证
* @param username 用户名/邮箱
* @param password 密码
* @return 认证成功?
*/
boolean authenticate(String username, String password);
}
package cn.quantgroup.big.stms.common.config;
import redis.clients.jedis.JedisPoolConfig;
public class JedisPoolUtil {
public static JedisPoolConfig getPoolConfig() {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMinIdle(20);
poolConfig.setMaxTotal(200);
poolConfig.setMaxIdle(100);
poolConfig.setMaxWaitMillis(2000);
poolConfig.setTestOnBorrow(true);
return poolConfig;
}
}
package cn.quantgroup.big.stms.common.config;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import java.util.Properties;
@Component
public class KaptchaConfig {
@Bean
public DefaultKaptcha getDefaultKaptcha() {
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
properties.setProperty("kaptcha.border", "yes");
properties.setProperty("kaptcha.border.color", "105,179,90");
properties.setProperty("kaptcha.textproducer.font.color", "blue");
properties.setProperty("kaptcha.image.width", "110");
properties.setProperty("kaptcha.image.height", "40");
properties.setProperty("kaptcha.textproducer.font.size", "30");
properties.setProperty("kaptcha.session.key", "code");
properties.setProperty("kaptcha.textproducer.char.length", "5");
properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}
package cn.quantgroup.big.stms.common.config;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.Control;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import java.util.Hashtable;
/**
* ldap 用户认证
*
* @author axq
*/
@Component
@Slf4j
public class LDAPAuthentication implements IAuthentication {
private static final String LDAP_URL = "ldap://ldap.quantgroups.com:389/";
private static final String BIND_DN = "cn=common_auth_query,cn=users,DC=quantgroup,DC=cn";
private static final String BIND_CREDENTIALS = "Quantgroup.com@2o17";
private static final String SEARCH_BASE = "ou=北京量科邦信息技术有限公司,dc=quantgroup,dc=cn";
private Control[] connCtls = null;
public LdapContext getCtx() {
LdapContext ctx = null;
Hashtable<String, String> env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, LDAP_URL + SEARCH_BASE);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, BIND_DN);
env.put(Context.SECURITY_CREDENTIALS, BIND_CREDENTIALS);
try {
// 链接ldap
ctx = new InitialLdapContext(env, connCtls);
log.info("ldap 链接成功");
} catch (AuthenticationException e) {
log.error("认证失败");
} catch (Exception e) {
log.error("认证出错:");
e.printStackTrace();
}
return ctx;
}
@Override
public boolean authenticate(String username, String password) {
boolean valide = false;
String email = username.endsWith("@quantgroup.cn") ? username : username + "@quantgroup.cn";
String userDN = "";
LdapContext ctx = getCtx();
if (ctx != null) {
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration en = ctx.search("", "mail=" + email, constraints);
while (en.hasMoreElements()) {
Object obj = en.nextElement();
if (obj instanceof SearchResult) {
SearchResult si = (SearchResult) obj;
userDN = userDN + si.getName();
userDN += "," + SEARCH_BASE;
}
}
} catch (Exception e) {
log.error("Exception in search():" + e);
e.printStackTrace();
}
}
if(StringUtils.isNotBlank(userDN)) {
try {
ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN);
ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
ctx.reconnect(connCtls);
log.info(userDN + " is authenticated");
valide = true;
} catch (AuthenticationException e) {
log.error(userDN + " is not authenticated");
e.printStackTrace();
valide = false;
} catch (NamingException e) {
log.error(userDN + " is not authenticated");
valide = false;
} catch (Exception e) {
e.printStackTrace();
}
}
return valide;
}
}
package cn.quantgroup.big.stms.common.config;
import cn.quantgroup.tool.monitor.metric.api.TechOkHttpClient;
import okhttp3.ConnectionPool;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;
/**
* @version 2018/7/13 下午2:11
* @auther jinsong.zhu
*/
@Configuration
public class OkHttpConfig {
public final static int CONNECT_TIMEOUT = 20;//设置连接超时时间
public final static int READ_TIMEOUT = 20;
public final static int WRITE_TIMEOUT = 20;
/* //注入brave-spring-boot-starter提供的techOkHttpClient
@Resource
private ITechOkHttpClient techOkHttpClient;*/
private OkHttpClient.Builder defaultBuilder(int maxIdleConnections, long keepAliveDuration) {
//创建okHttpClient
OkHttpClient.Builder builder = TechOkHttpClient.createOkHttpClientBuilder()
.retryOnConnectionFailure(true)
.connectionPool(new ConnectionPool(maxIdleConnections, keepAliveDuration, MINUTES))
.connectTimeout(CONNECT_TIMEOUT, SECONDS)
.readTimeout(READ_TIMEOUT, SECONDS)
.writeTimeout(WRITE_TIMEOUT, SECONDS);
return builder;
}
private OkHttpClient.Builder defaultBuilder() {
return defaultBuilder(10, 5);
}
@Bean
@Scope
public OkHttpClient defaultHttpClient() {
return defaultBuilder().build();
}
private static final String HAO_AN_KEY = "b5140fb2-2c85-4b5a-abcf-3e97528014db";
@Bean
public OkHttpClient outerApiHttpClient() {
OkHttpClient.Builder builder = defaultBuilder();
//调用数据源 risk-data项目的接口需要加上一个header: key->b5140fb2-2c85-4b5a-abcf-3e97528014db
Interceptor keyHeaderInterceptor = chain -> chain.proceed(chain.request().newBuilder()
.header("key", HAO_AN_KEY)
.build());
builder.addInterceptor(keyHeaderInterceptor);
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
// interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
builder.addInterceptor(interceptor);
return builder.build();
}
}
package cn.quantgroup.big.stms.common.config;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.util.Assert;
import redis.clients.jedis.JedisPoolConfig;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class RedisConfig {
@Value("${redis.defaultExpiration}")
private Long defaultExpiration;
@Value("${redis.master.host}")
private String masterHost;
@Value("${redis.master.port}")
private Integer masterPort;
@Value("${redis.sentinel.nodes}")
private String sentinelNodes;
@Value("${redis.sentinel.master.name}")
private String sentinelMasterName;
@Value("${spring.redis.password:}")
private String passWord;
private RedisConnectionFactory getConnectionFactoryOfSingleton() {
JedisConnectionFactory factory = new JedisConnectionFactory();
factory.setHostName(masterHost);
factory.setPort(masterPort);
factory.setUsePool(true);
factory.setConvertPipelineAndTxResults(true);
JedisPoolConfig poolConfig = JedisPoolUtil.getPoolConfig();
factory.setPoolConfig(poolConfig);
if(StringUtils.isNotEmpty(passWord)){
factory.setPassword(passWord);
}
factory.afterPropertiesSet();
return factory;
}
private RedisConnectionFactory getConnectionFactoryOfCluster() {
List<RedisNode> sentinels = createSentinels(sentinelNodes);
RedisSentinelConfiguration sentinelConfiguration = new RedisSentinelConfiguration();
sentinelConfiguration.setMaster(sentinelMasterName);
sentinelConfiguration.setSentinels(sentinels);
JedisPoolConfig poolConfig = JedisPoolUtil.getPoolConfig();
JedisConnectionFactory factory = new JedisConnectionFactory(sentinelConfiguration, poolConfig);
factory.setTimeout(2000);
factory.setUsePool(true);
factory.setConvertPipelineAndTxResults(true);
factory.afterPropertiesSet();
return factory;
}
private List<RedisNode> createSentinels(String sentinelNodes) {
List<RedisNode> nodes = new ArrayList<RedisNode>();
for (String node : org.springframework.util.StringUtils
.commaDelimitedListToStringArray(sentinelNodes)) {
try {
String[] parts = org.springframework.util.StringUtils.split(node, ":");
Assert.state(parts.length == 2, "Must be defined as 'host:port'");
nodes.add(new RedisNode(parts[0], Integer.valueOf(parts[1])));
} catch (RuntimeException ex) {
throw new IllegalStateException(
"Invalid redis sentinel " + "property '" + node + "'", ex);
}
}
return nodes;
}
@Bean(name = "redisConnectionFactory")
public RedisConnectionFactory redisConnectionFactory() {
if (StringUtils.isEmpty(sentinelMasterName)) {
return getConnectionFactoryOfSingleton();
} else {
return getConnectionFactoryOfCluster();
}
}
@Bean(name = "redisTemplate")
public RedisTemplate<String, Object> redisTemplate(
RedisConnectionFactory factory) {
final RedisTemplate<String, Object> template = new RedisTemplate<>();
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
template.setEnableTransactionSupport(false);
template.setKeySerializer(stringRedisSerializer);
template.setHashKeySerializer(stringRedisSerializer);
template.setValueSerializer(genericJackson2JsonRedisSerializer);
template.setDefaultSerializer(genericJackson2JsonRedisSerializer);
template.setConnectionFactory(factory);
return template;
}
@Bean(name = "stringRedisTemplate")
public RedisTemplate<String, String> stringRedisTemplate(
RedisConnectionFactory factory) {
final RedisTemplate<String, String> template = new RedisTemplate<>();
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
template.setEnableTransactionSupport(false);
template.setKeySerializer(stringRedisSerializer);
template.setHashKeySerializer(stringRedisSerializer);
template.setValueSerializer(stringRedisSerializer);
template.setDefaultSerializer(stringRedisSerializer);
template.setConnectionFactory(factory);
return template;
}
@Bean(name = "cacheManager")
public CacheManager cacheManager(RedisTemplate<String, Object> redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
cacheManager.setDefaultExpiration(defaultExpiration);
cacheManager.setUsePrefix(true);
return cacheManager;
}
}
package cn.quantgroup.big.stms.common.config;
import cn.quantgroup.big.stms.common.filter.XssFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import javax.servlet.DispatcherType;
//@Configuration
public class XssConfiguration {
/**
* xss过滤拦截器
*/
@Bean
public FilterRegistrationBean xssFilterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new XssFilter());
filterRegistrationBean.setOrder(1);
filterRegistrationBean.setEnabled(true);
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST);
return filterRegistrationBean;
}
}
package cn.quantgroup.big.stms.common.config;
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* xxl-job config
*
* @author xuxueli 2017-04-28
*/
@Configuration
public class XxlJobConfig {
private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);
@Value("${xxl.job.admin.addresses}")
private String adminAddresses;
@Value("${xxl.job.executor.appname}")
private String appName;
@Value("${xxl.job.executor.ip}")
private String ip;
@Value("${xxl.job.executor.port}")
private int port;
@Value("${xxl.job.accessToken}")
private String accessToken;
@Value("${xxl.job.executor.logpath}")
private String logPath;
@Value("${xxl.job.executor.logretentiondays}")
private int logRetentionDays;
@Bean(initMethod = "start", destroyMethod = "destroy")
public XxlJobSpringExecutor xxlJobSpringExecutor() {
logger.info(">>>>>>>>>>> xxl-job config init.");
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
xxlJobSpringExecutor.setAppName(appName);
xxlJobSpringExecutor.setIp(ip);
xxlJobSpringExecutor.setPort(port);
xxlJobSpringExecutor.setAccessToken(accessToken);
xxlJobSpringExecutor.setLogPath(logPath);
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
return xxlJobSpringExecutor;
}
/**
* 针对多网卡、容器内部署等情况,可借助 "spring-cloud-commons" 提供的 "InetUtils" 组件灵活定制注册IP;
*
* 1、引入依赖:
* <dependency>
* <groupId>org.springframework.cloud</groupId>
* <artifactId>spring-cloud-commons</artifactId>
* <version>${version}</version>
* </dependency>
*
* 2、配置文件,或者容器启动变量
* spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.'
*
* 3、获取IP
* String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
*/
}
\ No newline at end of file
package cn.quantgroup.big.stms.common.config;
\ No newline at end of file
package cn.quantgroup.big.stms.common.constants;
/**
* @Describe:
* @Created by tangfeng 2020-09-13 19:24
*/
public class HttpReqHeadKeyCnst {
public static String tenantId = "qg-tenant-id";
}
package cn.quantgroup.big.stms.common.constants;
/**
* 系统常量
*
* @author yutong
*/
public interface StmsConstants {
/* 超级管理员ID */
String ADMINISTRATOR_ID = "78825667-912c-49c3-a44a-19b85ffc640c";
/* 权限系统编码 */
String AUTH_APP_CODE = "APP000";
/* 常用符号 , */
String SYMBOL_COMMA = ",";
/* 常用符号 . */
String SYMBOL_DOT = ".";
/* 主公司名称中的关键字 */
String PRIMARY_ORG_KW = "众信利民";
/* 商务组织名称中的关键字 */
String BIZ_ORG_KW = "商务";
/* 财务组织名称中的关键字 */
String FINZ_ORG_KW = "财务";
}
package cn.quantgroup.big.stms.common.context;
import java.util.HashMap;
import java.util.Map;
public class AppContextHolder {
/**当前用户**/
private final static String ONLINE_USER_INFO = "CURRENT_ONLINE_USER_INFO";//当前用户信息
private static ThreadLocal<Map<String, Object>> context = new ThreadLocal<>();
private static void set(String key, Object value) {
Map<String, Object> map = context.get();
if (map == null) {
map = new HashMap<String, Object>();
context.set(map);
}
map.put(key, value);
}
private static Object get(String key) {
Map<String, Object> map = context.get();
if (map == null) {
map = new HashMap<String, Object>();
context.set(map);
}
return map.get(key);
}
public static void setOnlineUser(OnlineUser onlineUser) {
set(ONLINE_USER_INFO, onlineUser);
}
public static OnlineUser getOnlineUser() {
return (OnlineUser) get(ONLINE_USER_INFO);
}
public static void remove() {
context.remove();
}
}
package cn.quantgroup.big.stms.common.context;
import cn.quantgroup.big.stms.common.annotation.EnumKey;
import cn.quantgroup.big.stms.common.enums.BaseEnum;
import cn.quantgroup.big.stms.common.exception.BizException;
import cn.quantgroup.big.stms.common.result.ResultCode;
import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@SuppressWarnings("rawtypes")
public class EnumClassFactory {
private final static Logger logger = LoggerFactory.getLogger(EnumClassFactory.class);
private static Map<String, Class<? extends BaseEnum>> enums = new HashMap<>();
static {
Reflections reflections = new Reflections("cn.quantgroup.big.stms");
Set<Class<? extends BaseEnum>> enumsClasses = reflections.getSubTypesOf(BaseEnum.class);
for (Class<? extends BaseEnum> it : enumsClasses) {
enums.put(it.getName(), it);
String key = it.getSimpleName().toLowerCase();
EnumKey enumKey = it.getAnnotation(EnumKey.class);
if (null != enumKey) {
key = enumKey.value();
}
if (!enums.containsKey(key)) {
enums.put(key, it);
}
}
logger.info("枚举类已注册到枚举工厂 ");
}
public static Class<? extends BaseEnum> getEnumClass(String name) {
Class<? extends BaseEnum> clazz = enums.get(name);
if (null == clazz) {
throw new BizException("请求的枚举类不存在", ResultCode.PARAM_ERROR);
}
return clazz;
}
}
package cn.quantgroup.big.stms.common.context;
import com.google.gson.Gson;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
public class OnlineUser implements Serializable {
/**
* 用户ID
**/
private String id;
/**
* 登录账号
**/
private String account;
/**
* 用户显示名称
**/
private String name;
/**
* 用户所属组织ID
**/
private String orgId;
/**
* 用户所属组织名称
**/
private String orgName;
/**
* 登录IP
**/
private String loginIp;
/**
* 租户id
*/
private String tenantIds;
/**
* 账户类型,默认值为0,原有账户分配用户;如果是第三方登录用户,值为1
*/
private int accountType;
private String supplierCode;
private String permissions;
/**
* 是否绑定了第三方账户
*/
private boolean bindStatus = false;
public OnlineUser(String id, String account, String name, String orgId, String orgName,
String loginIp, String tenantIds,String supplierCode,String permissions) {
this(id,account,name,orgId,orgName,loginIp,tenantIds,supplierCode,0);
this.permissions= permissions;
}
public OnlineUser(String id, String account, String name, String orgId, String orgName,
String loginIp, String tenantIds,String supplierCode) {
this(id,account,name,orgId,orgName,loginIp,tenantIds,supplierCode,0);
}
public OnlineUser(String id, String account, String name, String orgId, String orgName,
String loginIp, String tenantIds, String supplierCode,int accountType) {
super();
this.id = id;
this.account = account;
this.name = name;
this.orgId = orgId;
this.orgName = orgName;
this.loginIp = loginIp;
this.tenantIds = tenantIds;
this.accountType = accountType;
this.supplierCode = supplierCode;
}
public OnlineUser(String json) {
Gson gson = new Gson();
OnlineUser user = gson.fromJson(json,OnlineUser.class);
this.setId(user.getId());
this.setAccount(user.getAccount());
this.setName(user.getName());
this.setOrgId(user.getOrgId());
this.setOrgName(user.getOrgName());
this.setLoginIp(user.getLoginIp());
this.setSupplierCode(user.getSupplierCode());
this.setAccountType(user.getAccountType());
this.setBindStatus(user.isBindStatus());
this.setTenantIds(user.getTenantIds());
}
public String getId() {
return id;
}
public String getAccount() {
return account;
}
public String getName() {
return name;
}
public String getOrgId() {
return orgId;
}
@Override
public String toString() {
return name;
}
public String toJson() {
Gson gson = new Gson();
return gson.toJson(this);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
OnlineUser other = (OnlineUser) obj;
if (id == null) {
if (other.id != null) {
return false;
}
} else if (!id.equals(other.id)) {
return false;
}
return true;
}
}
package cn.quantgroup.big.stms.common.context;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringContextHolder implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextHolder.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
assertApplicationContext();
return applicationContext;
}
@SuppressWarnings("unchecked")
public static <T> T getBean(String beanName) {
assertApplicationContext();
return (T) applicationContext.getBean(beanName);
}
public static <T> T getBean(Class<T> requiredType) {
assertApplicationContext();
return applicationContext.getBean(requiredType);
}
public static <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return applicationContext.getBean(name, requiredType);
}
private static void assertApplicationContext() {
if (SpringContextHolder.applicationContext == null) {
throw new RuntimeException("applicaitonContext属性为null,请检查是否注入了SpringContextHolder!");
}
}
}
package cn.quantgroup.big.stms.common.context;
\ No newline at end of file
package cn.quantgroup.big.stms.common.controller;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Sort;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
public class BaseController {
/**
* 分页排序:创建时间-倒序,排序号-倒序
*
* @return
*/
public Sort getSort() {
List<Sort.Order> orders = new ArrayList<>();
Sort.Order order1 = new Sort.Order(Sort.Direction.DESC, "sortNo");
Sort.Order order2 = new Sort.Order(Sort.Direction.DESC, "createTime");
orders.add(order1);
orders.add(order2);
return new Sort(orders);
}
/**
* 分页排序:创建时间-升序,排序号-倒序
*
* @return
*/
public Sort getSortByCreateTimeAES() {
List<Sort.Order> orders = new ArrayList<>();
Sort.Order order1 = new Sort.Order(Sort.Direction.DESC, "sortNo");
Sort.Order order2 = new Sort.Order(Sort.Direction.ASC, "createTime");
orders.add(order1);
orders.add(order2);
return new Sort(orders);
}
/**
* 创建匹配器,组装查询条件
* 字符串模糊查询 & 忽略大小写
*
* @return
*/
public ExampleMatcher getExampleMatcher() {
// 创建匹配器,组装查询条件
ExampleMatcher matcher = ExampleMatcher.matching() // 构建对象
.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING) // 改变默认字符串匹配方式:模糊查询
.withIgnoreCase(true) // 改变默认大小写忽略方式:忽略大小写
.withIgnoreNullValues();
return matcher;
}
/**
* 获取对象的属性值为空的属性
*
* @param source
* @return
*/
public String[] getNullPropertyNames(Object source) {
final BeanWrapper src = new BeanWrapperImpl(source);
java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();
Set<String> emptyNames = new HashSet<String>();
for (java.beans.PropertyDescriptor pd : pds) {
Object srcValue = src.getPropertyValue(pd.getName());
if (srcValue == null) {
emptyNames.add(pd.getName());
}
}
String[] result = new String[emptyNames.size()];
return emptyNames.toArray(result);
}
/**
* String转Date
*
* @return 返回时间类型 yyyy-MM-dd HH:mm:ss
*/
public static Date getDate(String date) {
if (StringUtils.isBlank(date)) {
return new Date();
}
return getDate(date, null);
}
/**
* String转Date
*
* @return 返回时间类型 yyyy-MM-dd HH:mm:ss
*/
public static Date getDate(String date, String pattern) {
if (StringUtils.isBlank(date)) {
return new Date();
}
if (StringUtils.isBlank(pattern)) {
pattern = "yyyy-MM-dd HH:mm:ss";
}
SimpleDateFormat formatter = new SimpleDateFormat(pattern);
try {
return formatter.parse(date);
} catch (ParseException e) {
return new Date();
}
}
}
package cn.quantgroup.big.stms.common.convert;
/**
* 枚举转换器工厂(需要用@ModelAttribute 转换对象,@RequestBody 不走转换器)
* @Author meng.xin@quantgroup.cn
* @Date 2019-11-06 15:47
* @Version 1.0
*/
import cn.quantgroup.big.stms.common.enums.BaseEnum;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
public class UniversalEnumConverterFactory implements ConverterFactory<String, BaseEnum> {
private static final Map<Class, Converter> converterMap = new WeakHashMap<>();
@Override
public <T extends BaseEnum> Converter<String, T> getConverter(Class<T> targetType) {
Converter result = converterMap.get(targetType);
if(result == null) {
result = new IntegerStrToEnum<T>(targetType);
converterMap.put(targetType, result);
}
return result;
}
class IntegerStrToEnum<T extends BaseEnum> implements Converter<String, T> {
private final Class<T> enumType;
private Map<String, T> enumMap = new HashMap<>();
public IntegerStrToEnum(Class<T> enumType) {
this.enumType = enumType;
T[] enums = enumType.getEnumConstants();
for(T e : enums) {
enumMap.put(e.getValue() + "", e);
}
}
@Override
public T convert(String source) {
T result = enumMap.get(source);
if(result == null) {
throw new IllegalArgumentException("No element matches " + source);
}
return result;
}
}
}
\ No newline at end of file
package cn.quantgroup.big.stms.common.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean;
import java.io.Serializable;
@NoRepositoryBean
public interface BaseRepository<T,ID extends Serializable> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T> {
}
package cn.quantgroup.big.stms.common.dao;
import cn.quantgroup.big.stms.common.model.BaseTreeVO;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.query.Param;
import java.io.Serializable;
@NoRepositoryBean
public interface TreeRepository<T extends BaseTreeVO<T,ID>,ID extends Serializable> extends BaseRepository<T, ID>{
/**
*
* <p>date: 2019年10月16日 上午10:13:25</p>
* <p>description: 查询根节点的最大层级码</p>
* @author rong.yang/阳荣
* @param
* @return
*/
@Query("select max(t.levelCode) from #{#entityName} t where t.parent.id is null")
String getMaxLevelCodeOfTopNode();
@Query("select max(t.levelCode) from #{#entityName} t where t.parent.id = :parentId")
String getMaxLevelCodeOfChildren(@Param("parentId") ID parentId);
}
package cn.quantgroup.big.stms.common.enums;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serializable;
/**
* <p>date: 2019年6月15日 下午3:46:52</p>
* <p>description: 枚举基础类</p>
*
* @author rong.yang/阳荣
*/
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public interface BaseEnum<T> extends Serializable {
/**
* 获取枚举的值
*
* @return
*/
T getValue();
/**
* 获取枚举的名称
*
* @return
*/
String getName();
}
package cn.quantgroup.big.stms.common.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
/**
* <B>描述:基础数据的状态</B><BR>
*
* @author rong yang
* @version 1.0 2013-06-22
*/
public enum BasicDataStatus implements BaseEnum<Integer> {
SAVE("新增", 1),
VALID("有效", 2),
INVALID("无效", 3);
private final String name;
private final Integer value;
BasicDataStatus(String name, int value) {
this.name = name;
this.value = value;
}
@Override
public String getName() {
return name;
}
@Override
//@JsonValue//返回前端只返回value,不返回name
public Integer getValue() {
return value;
}
/**
* 解决json枚举类型转换问题
*
* @param value
* @return
*/
@JsonCreator
public static BasicDataStatus get(int value) {
for (BasicDataStatus e : values()) {
if (e.getValue().equals(value)) {
return e;
}
}
return null;
}
}
package cn.quantgroup.big.stms.common.enums;
import com.google.common.collect.Maps;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.util.Map;
/**
* @Describe: 租户枚举
* @Created by tangfeng 2021/11/15 10:38 上午
*/
@Getter
@AllArgsConstructor
@NoArgsConstructor
public enum TenantEnum {
KDSP(560761, "羊小咩"),
QING_HAI_MOBILE(560867, "青海移动"),
JIANG_SU_MOBILE(560868, "江苏移动"),
;
private Integer tenantId;
private String desc;
private static Map<Integer,TenantEnum> tenantIdEnumMap = Maps.newHashMap();
static {
for (TenantEnum value : TenantEnum.values()) {
tenantIdEnumMap.put(value.tenantId, value);
}
}
}
package cn.quantgroup.big.stms.common.enums;
\ No newline at end of file
/**
*
*/
package cn.quantgroup.big.stms.common.exception;
import cn.quantgroup.big.stms.common.result.ResultCode;
/**
* @author rong yang
*
*/
@SuppressWarnings("serial")
public class BizException extends RuntimeException {
private ResultCode resultCode;
/**
*
*/
public BizException() {
}
/**
* @param message
*/
public BizException(String message) {
super(message);
}
/**
* @param cause
*/
public BizException(Throwable cause) {
super(cause);
}
public BizException(String message, Throwable cause, ResultCode resultCode) {
super(message, cause);
this.resultCode = resultCode;
}
public BizException(String message, ResultCode resultCode) {
super(message);
this.resultCode = resultCode;
}
public BizException(ResultCode resultCode) {
super(resultCode.getMsg());
this.resultCode = resultCode;
}
/**
* @param message
* @param cause
*/
public BizException(String message, Throwable cause) {
super(message, cause);
}
/**
* @param message
* @param cause
* @param enableSuppression
* @param writableStackTrace
*/
public BizException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
/**
* @return the resultCode
*/
public ResultCode getResultCode() {
return resultCode;
}
}
package cn.quantgroup.big.stms.common.exception;
import cn.quantgroup.big.stms.common.result.Result;
import cn.quantgroup.big.stms.common.result.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = { ConstraintViolationException.class })
public Object constraintViolationHandle(ConstraintViolationException e) {
log.warn("参数校验错误!",e);
Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
if (violations != null) {
StringBuilder buffer = new StringBuilder();
for (ConstraintViolation<?> constraintViolation : violations) {
if (constraintViolation != null) {
buffer.append(constraintViolation.getMessage()).append(";");
}
}
return Result.failure(ResultCode.PARAM_ERROR, buffer.toString());
}
return Result.failure(ResultCode.PARAM_ERROR);
}
@ExceptionHandler(value = { MethodArgumentNotValidException.class })
public Object validHandle(MethodArgumentNotValidException e) {
log.warn("方法参数校验错误!",e);
BindingResult result = e.getBindingResult();
if (result != null && result.getAllErrors() != null) {
StringBuilder buffer = new StringBuilder();
for (ObjectError error : result.getAllErrors()) {
buffer.append(error.getDefaultMessage()).append(";");
}
return Result.failure(ResultCode.PARAM_ERROR, buffer.toString());
}
return Result.failure(ResultCode.PARAM_ERROR);
}
@ExceptionHandler(value = { BindException.class })
public Object validHandle(BindException e) {
log.warn("参数校验错误!",e);
BindingResult result = e.getBindingResult();
if (result != null && result.getAllErrors() != null) {
StringBuilder buffer = new StringBuilder();
for (ObjectError error : result.getAllErrors()) {
buffer.append(error.getDefaultMessage()).append(";");
}
return Result.failure(ResultCode.PARAM_ERROR, buffer.toString());
}
return Result.failure(ResultCode.PARAM_ERROR);
}
@ExceptionHandler(value = { BizException.class })
public Object bizExceptionHandle(BizException e) {
log.error("业务处理异常!", e);
ResultCode resultCode = e.getResultCode();
if (null != resultCode) {
return Result.failure(resultCode, e.getMessage());
} else {
return Result.failure(ResultCode.SERVICE_ERROR, e.getMessage());
}
}
@ExceptionHandler(value = { Throwable.class })
public Object errorHandle(Exception e) {
log.error("服务器异常!", e);
return Result.failure(ResultCode.SERVICE_ERROR, e.getMessage());
}
}
\ No newline at end of file
package cn.quantgroup.big.stms.common.exception;
\ No newline at end of file
package cn.quantgroup.big.stms.common.filter;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.safety.Whitelist;
import org.springframework.web.util.HtmlUtils;
import java.io.IOException;
public class JsoupUtil {
/**
* 使用自带的basicWithImages 白名单
* 允许的便签有a,b,blockquote,br,cite,code,dd,dl,dt,em,i,li,ol,p,pre,q,small,span,
* strike,strong,sub,sup,u,ul,img
* 以及a标签的href,img标签的src,align,alt,height,width,title属性
*/
private static final Whitelist whitelist = Whitelist.basicWithImages();
/** 配置过滤化参数,不对代码进行格式化 */
private static final Document.OutputSettings outputSettings = new Document.OutputSettings().prettyPrint(false);
static {
// 增加需要过滤的其它白名单属性、标签等
// 富文本编辑时一些样式是使用style来进行实现的
// 比如红色字体 style="color:red;"
// 所以需要给所有标签添加style属性
whitelist.addAttributes(":all", "style");
}
public static String clean(String content) {
if (StringUtils.isNotBlank(content)) {
content = content.trim();
}
return Jsoup.clean(content, "", whitelist, outputSettings);
}
public static void main(String[] args) throws IOException {
String text = " <a href=\"http://www.baidu.com/a\" onclick=\"alert(1);\">sss</a><script>alert(0);</script>sss ";
System.out.println(clean(text));
System.out.println(StringEscapeUtils.escapeHtml4(text));
System.out.println(HtmlUtils.htmlEscape(text));
}
}
package cn.quantgroup.big.stms.common.filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class XssFilter implements Filter {
private static Logger logger = LoggerFactory.getLogger(XssFilter.class);
/**
* 排除不过滤的request请求
*/
public List<String> excludes = new ArrayList<>();
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException,ServletException {
logger.debug("Xss Filter is Open");
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
filterChain.doFilter(xssRequest, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}
package cn.quantgroup.big.stms.common.filter;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.safety.Whitelist;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
private final String d_param_name = "content";
private final String d_param_endsWith = "withHtml";
private HttpServletRequest originalRequest = null;
/**
* 配置可以通过过滤的白名单
*/
private static final Whitelist whitelist = Whitelist.relaxed();
/**
* 配置过滤化参数,不对代码进行格式化
*/
private static final Document.OutputSettings outputSettings = new Document.OutputSettings().prettyPrint(false);
static {
// 增加需要过滤的其它白名单属性、标签等
// 富文本编辑时一些样式是使用style来进行实现的
// 比如红色字体 style="color:red;"
// 所以需要给所有标签添加style属性
whitelist.addAttributes(":all", "style");
}
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
this.originalRequest = request;
}
@Override
public ServletInputStream getInputStream() throws IOException {
try(BufferedReader br = new BufferedReader(new InputStreamReader(originalRequest.getInputStream()))) {
String result = "";
String line = br.readLine();
while (line != null) {
result += clean(line);
line = br.readLine();
}
return new WrappedServletInputStream(new ByteArrayInputStream(result.getBytes()));
}catch (Exception e) {
throw new IOException(e);
}
}
/**
* 覆盖getParameter方法,将参数名和参数值都做xss过滤。
*
* 如果需要获得原始的值,则通过super.getParameterValues(name)来获取
*
* getParameterNames,getParameterValues和getParameterMap也可能需要覆盖
*/
@Override
public String getParameter(String name) {
if ((d_param_name.equals(name) || name.endsWith(d_param_endsWith))) {
return super.getParameter(name);
}
name = clean(name);
String value = super.getParameter(name);
if (StringUtils.isNotBlank(value)) {
value = clean(value);
}
return value;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public Map getParameterMap() {
Map map = super.getParameterMap();
// 返回值Map
Map<String, String> returnMap = new HashMap<String, String>();
Iterator entries = map.entrySet().iterator();
Map.Entry entry = null;
String name = "";
String value = "";
while (entries.hasNext()) {
entry = (Map.Entry) entries.next();
name = (String) entry.getKey();
Object valueObj = entry.getValue();
if (null == valueObj) {
value = "";
} else if (valueObj instanceof String[]) {
String[] values = (String[]) valueObj;
for (int i = 0; i < values.length; i++) {
value = values[i] + ",";
}
value = value.substring(0, value.length() - 1);
} else {
value = valueObj.toString();
}
returnMap.put(name, clean(value).trim());
}
return returnMap;
}
@Override
public String[] getParameterValues(String name) {
String[] arr = super.getParameterValues(name);
if (arr != null) {
for (int i = 0; i < arr.length; i++) {
arr[i] = clean(arr[i]);
}
}
return arr;
}
/**
* 覆盖getHeader方法,将参数名和参数值都做xss过滤。
*
* 如果需要获得原始的值,则通过super.getHeaders(name)来获取
*
* getHeaderNames 也可能需要覆盖
*/
@Override
public String getHeader(String name) {
name = clean(name);
String value = super.getHeader(name);
if (StringUtils.isNotBlank(value)) {
value = clean(value);
}
return value;
}
/**
* 127 * 获取最原始的request
*
* @return
*/
public HttpServletRequest getOriginalRequestRequest() {
return originalRequest;
}
/**
* 获取最原始的request的静态方法
*
* @return
*/
public static HttpServletRequest getOriginalRequestRequest(HttpServletRequest req) {
if (req instanceof XssHttpServletRequestWrapper) {
return ((XssHttpServletRequestWrapper) req).getOriginalRequestRequest();
}
return req;
}
private String clean(String content) {
String result = Jsoup.clean(content, "", whitelist, outputSettings);
return result;
}
private class WrappedServletInputStream extends ServletInputStream {
private InputStream stream;
public WrappedServletInputStream(InputStream stream) {
this.stream = stream;
}
@Override
public int read() throws IOException {
return stream.read();
}
@Override
public boolean isFinished() {
return true;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
}
}
}
package cn.quantgroup.big.stms.common.hibernate.usertype;
import cn.quantgroup.big.stms.common.context.EnumClassFactory;
import cn.quantgroup.big.stms.common.enums.BaseEnum;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.usertype.ParameterizedType;
import org.hibernate.usertype.UserType;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Properties;
/**
*
* <p>date: 2019年10月16日 下午5:25:38</p>
* <p>description: 自定义枚举类型处理</p>
*
*
* @package com.matrix.core.hibernate.usertype
* @author rong.yang/阳荣
*
* 使用方法:<br/>
* 1. 枚举类要实现cn.quantgroup.big.common.enums.BaseEnum接口<br/>
* 2. 在模型的枚举属性上增加以下注解<br/>
* <p>
* @Type(type="cn.quantgroup.big.stms.common.hibernate.usertype.UserEnumType",parameters={@Parameter(name="enumClass",value="枚举的全路径")})
* </p>
*
*/
public class UserEnumType<E extends Enum<?> & BaseEnum<?>> implements UserType, ParameterizedType {
private static final String ENUM_CLASS = "enumClass";
private static final String VALUE_FIELD = "value";
private Class<E> enumClass;
private int sqlType;
@Override
public void setParameterValues(Properties parameters) {
if (null == parameters) {
throw new IllegalArgumentException("enum must set parameters");
}
try {
enumClass = (Class<E>) EnumClassFactory.getEnumClass(parameters.getProperty(ENUM_CLASS));
//enumClass = (Class<E>) Class.forName(parameters.getProperty(ENUM_CLASS));
Class<?> valueType = enumClass.getDeclaredField(VALUE_FIELD).getType();
if(valueType.isAssignableFrom(Integer.class)){
sqlType = Types.INTEGER;
}else if(valueType.isAssignableFrom(String.class)){
sqlType = Types.VARCHAR;
}else{
throw new IllegalArgumentException("enum value property type must be String or Integer");
}
} catch (NoSuchFieldException | SecurityException e) {
throw new IllegalArgumentException("enum set parameters set error!",e);
}
}
@Override
public int[] sqlTypes() {
return new int[]{sqlType};
}
@SuppressWarnings("rawtypes")
@Override
public Class returnedClass() {
return enumClass;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return (x!=null && y!=null) ? x.equals(y) : false;
}
@Override
public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
Object value = rs.getObject(names[0]);
return of(value);
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session)
throws HibernateException, SQLException {
Object val = null;
if (null != value ) {
val = ((BaseEnum<?>)value).getValue();
}
st.setObject(index, val);
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable) value;
}
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return cached;
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
private E of(Object value) {
E[] enumConstants = enumClass.getEnumConstants();
for (E e : enumConstants) {
if (e.getValue().equals(value)) {
return e;
}
}
return null;
}
}
package cn.quantgroup.big.stms.common.interceptor;
import org.springframework.http.HttpStatus;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CorsInterceptor implements HandlerInterceptor {
/**
* 拦截器禁用的方法
*/
private final String OPTIONS = "OPTIONS";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS");
response.setHeader("Access-Control-Max-Age", "86400");
response.setHeader("Access-Control-Allow-Headers", "*");
// 如果是OPTIONS则结束请求
if (OPTIONS.equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpStatus.NO_CONTENT.value());
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
}
}
package cn.quantgroup.big.stms.common.interceptor;
\ No newline at end of file
package cn.quantgroup.big.stms.common.model;
import java.util.Date;
/**
*
* @author 可审核的实体
*
*/
public interface Auditable {
/**
* 获取创建时间
* @return
*/
public Date getCreateTime();
/**
* 设置创建时间
* @return
*/
public void setCreateTime(Date createTime);
/**
* 获取最后更新时间
* @return
*/
public Date getUpdateTime();
/**
* 设置最后更新时间
* @return
*/
public void setUpdateTime(Date updateTime);
/**
* 获取最后更新人 ,操作人的登录账号
* @return
*/
public String getUpdateUser();
/**
* 设置最后更新人 ,操作人的登录账号
* @return
*/
public void setUpdateUser(String updateUser);
/**
* 获取创建新人 ,操作人的登录账号
* @return
*/
public String getCreator();
/**
* 设置创建新人 ,操作人的登录账号
* @return
*/
public void setCreator(String creator);
}
package cn.quantgroup.big.stms.common.model;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.format.annotation.DateTimeFormat;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import java.io.Serializable;
import java.util.Date;
/**
* @author ouyangjie
* @create 2019-10-29 下午 4:44
**/
@MappedSuperclass
public abstract class BaseAssociatedVO<ID extends Serializable> extends BaseEntityVO<ID> {
private static final long serialVersionUID = 1L;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Column(name = "create_time", updatable = false)
@CreatedDate
private Date createTime;
/**
* 创建者的用户,登录的用户账号
*/
@Column(length = 36, updatable = false)
private String creator;
public BaseAssociatedVO() {
super();
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public String getCreator() {
return creator;
}
public void setCreator(String creator) {
this.creator = creator;
}
}
package cn.quantgroup.big.stms.common.model;
import cn.quantgroup.big.stms.common.enums.BasicDataStatus;
import org.hibernate.annotations.Parameter;
import org.hibernate.annotations.Type;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import java.io.Serializable;
@MappedSuperclass
public abstract class BaseBasicDataVO<ID extends Serializable> extends BaseVO<ID> {
/**
*
*/
private static final long serialVersionUID = 1L;
/** 编码 */
@Column(name = "code", nullable = false, length = 32)
private String code;
/** 名称 */
@Column(name = "name", nullable = false, length = 64)
private String name;
/**
* 状态
*
*/
@Type(type= "cn.quantgroup.big.stms.common.hibernate.usertype.UserEnumType",
parameters={@Parameter(name="enumClass",value="cn.quantgroup.big.stms.common.enums.BasicDataStatus")})
@Column(name = "status", columnDefinition = "int")
private BasicDataStatus status;
/** 排序号 */
@Column(name = "sort_no")
private Integer sortNo;
/** 描述 */
@Column(name = "description", length = 128)
private String description;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code == null ? null : code.trim();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name == null ? null : name.trim();
}
public Integer getSortNo() {
return sortNo;
}
public void setSortNo(Integer sortNo) {
this.sortNo = sortNo;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description == null ? null : description.trim();
}
public BasicDataStatus getStatus() {
return status;
}
public void setStatus(BasicDataStatus status) {
this.status = status;
}
}
package cn.quantgroup.big.stms.common.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
import java.io.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* <b>类名称:</b>Entity<br/>
* <b>类描述:</b>可持久化的对象<br/>
* <b>创建人:</b>rong yang<br/>
* <b>修改人:</b>rong yang<br/>
* <b>修改时间:</b>2013-6-26 下午9:18:49<br/>
* <b>修改备注:</b><br/>
*
* @version 1.0.0<br/>
*
*/
@MappedSuperclass
public abstract class BaseEntityVO<ID extends Serializable> implements Serializable, Cloneable {
/**
*
*/
private static final long serialVersionUID = 1L;
public abstract ID getId();
/** 额外的临时信息 */
@JsonIgnore
@SuppressWarnings("rawtypes")
@Transient
private Map additional;
public abstract void setId(ID id);
@SuppressWarnings("rawtypes")
public Map getAdditional() {
if (null == additional) {
additional = new HashMap();
}
return additional;
}
public Object getAdditional(Object key) {
// 参数合法性检查
Object result = getAdditional().get(key);
return result;
}
@SuppressWarnings("unchecked")
public void setAdditional(Object key, Object value) {
// 参数合法性检查
getAdditional().put(key, value);
}
@SuppressWarnings("rawtypes")
@JsonIgnore
public Collection getAdditionalKeys() {
return (Collection) getAdditional().keySet();
}
public Object clone() throws CloneNotSupportedException {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(this);
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
return in.readObject();
} catch (Exception e) {
throw new RuntimeException("cannot clone class [" + this.getClass().getName() + "] var serialization: " + e.toString());
}
}
}
package cn.quantgroup.big.stms.common.model;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import java.io.Serializable;
@MappedSuperclass
public abstract class BaseTreeVO<T extends BaseTreeVO<T,ID>, ID extends Serializable> extends BaseBasicDataVO<ID> {
/**
*
*/
private static final long serialVersionUID = 1L;
/** 树的层级编码 */
@Column(name = "level_code", length = 255)
private String levelCode;
/** 全称 **/
@Column(name = "full_name", length = 255)
private String fullName;
/** 树的度 */
@Column(name = "degree")
private Integer degree;
/** 是否叶子节点 */
@Column(name = "is_leaf")
private Boolean isLeaf;
public String getLevelCode() {
return levelCode;
}
public void setLevelCode(String levelCode) {
this.levelCode = levelCode;
}
public Integer getDegree() {
return degree;
}
public void setDegree(Integer degree) {
this.degree = degree;
}
public Boolean getIsLeaf() {
return isLeaf;
}
public void setIsLeaf(Boolean isLeaf) {
this.isLeaf = isLeaf;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
/**
* 获取父节点
* @return
*/
public abstract T getParent();
/**
* 设置父节点
* @return
*/
public abstract void setParent(T parent);
}
package cn.quantgroup.big.stms.common.model;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.format.annotation.DateTimeFormat;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import java.io.Serializable;
import java.util.Date;
/**
* <B>描述:</B><BR>
* 值对象最高基类 <BR>
*
* @author rong yang
* @version 1.0 2013-06-22
*/
@MappedSuperclass
public abstract class BaseVO<ID extends Serializable> extends BaseEntityVO<ID> implements Auditable {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Column(name = "create_time", updatable = false)
@CreatedDate
private Date createTime;
/**
* 最近一次更新时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Column(name = "update_time")
@LastModifiedDate
private Date updateTime;
/**
* 更新人员,登录的用户账号
*/
@Column(name = "update_user")
private String updateUser;
/**
* 创建者的用户,登录的用户账号
*/
@Column(length = 36, updatable = false)
private String creator;
public BaseVO() {
super();
}
@Override
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Override
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public String getUpdateUser() {
return updateUser;
}
public void setUpdateUser(String updateUser) {
this.updateUser = updateUser;
}
public String getCreator() {
return creator;
}
public void setCreator(String creator) {
this.creator = creator;
}
}
package cn.quantgroup.big.stms.common.model;
import lombok.Data;
@Data
public class ClientVO {
private String userId;
private String clientId;
private String clientSecret;
private String scopes;
private String redirectUrl;
private Integer status;
private String callbackUrl;
}
package cn.quantgroup.big.stms.common.model;
import lombok.Data;
@Data
public class Supplier {
private Integer id;
private String name;
private String supplierCode;
}
package cn.quantgroup.big.stms.common.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TenantVO {
private Integer id;
private String name;
}
package cn.quantgroup.big.stms.common.model;
import java.util.List;
/**
* @author aoxq
* @date 2019/12/4 18:02
**/
public class TreeNode<T> {
private T node;
private List<TreeNode<T>> childNodes;
public T getNode() {
return node;
}
public void setNode(T node) {
this.node = node;
}
public List<TreeNode<T>> getChildNodes() {
return childNodes;
}
public void setChildNodes(List<TreeNode<T>> childNodes) {
this.childNodes = childNodes;
}
}
package cn.quantgroup.big.stms.common;
\ No newline at end of file
package cn.quantgroup.big.stms.common.result;
/**
* API 调用返回的结果对象
*
* @author rong yang
*
*/
@SuppressWarnings("serial")
public class Result implements java.io.Serializable {
private Integer code;
/** 消息 **/
private String msg;
/** 详细消息 **/
private String detail;
/** 数据 **/
private Object data;
public String getMsg() {
return msg;
}
public Object getData() {
return data;
}
/**
* @return the code
*/
public Integer getCode() {
return code;
}
public String getDetail() {
return detail;
}
private void setDetail(String detail) {
this.detail = detail;
}
/**
* @param resultCode
*/
protected void setResultCode(ResultCode resultCode) {
this.code = resultCode.getCode();
this.msg = resultCode.getMsg();
}
protected void setData(Object data) {
this.data = data;
}
public static Result success() {
Result result = new Result();
result.setResultCode(ResultCode.SUCCESS);
return result;
}
public static Result success(Object data) {
Result result = new Result();
result.setResultCode(ResultCode.SUCCESS);
result.setData(data);
return result;
}
public static Result failure(ResultCode resultCode) {
Result result = new Result();
result.setResultCode(resultCode);
return result;
}
public static Result failure(ResultCode resultCode, String detail) {
Result result = new Result();
result.setResultCode(resultCode);
result.setDetail(detail);
return result;
}
}
package cn.quantgroup.big.stms.common.result;
/**
* API调用结果状态码定义
*
* @author rong yang
*/
public enum ResultCode {
SUCCESS(2000, "成功"),
PARAM_ERROR(4000, "参数错误"),
UNAUTHORIZED(4010, "未登录、请先登录"),
REFRESH_TOKEN_EXPIRE(4011, "Refresh-Token过期,请重新登录系统"),
FAIL_LOGIN_MAX(4012, "超过最大错误次数,请10分钟后重试"),
FORBIDDEN(4030, "没有访问权限,禁止访问"),
INVALID_USERNAME_OR_PASSWORD(4031, "用户名密码不正确"),
INVALID_VERIFICATION_CODE(4032, "验证码不正确"),
ACCESS_TOKEN_EXPIRE(4033, "Access-Token过期,请重新获取Access-Token"),
INVALID_USERNAME_OR_PASSWORD_ORIGINAL(4034, "原密码不正确"),
SERVICE_ERROR(5000, "服务器器异常"),
DOWNLOAD_ERROR(6000, "有人正在下载,请稍后再试"),
REPEAT_SUBMIT_ERROR(6010, "重复提交"),
SUPPLIER_NON_EXISTENT(7000,"此供应商不存在,请先添加供应商"),
ORGANIZATION_NO_EXISTENT(7001,"组织不存在"),
UN_MERCHANT_ORGANIZATION(7002,"非供应商租户"),
ROLE_NOT_EXISTENT(7004,"角色不存在"),
ORGANIZATION_FROZEN(7003,"商户已解约,请联系平台申请重新入驻"),
EXTERNAL_LOGIN_ERROR(4100,"第三方账号登录失败"),
DISABLED_USER(4101,"用户已经禁用"),
INVALID_PHONE(4102,"不可以验证的手机号码"),
DUPLICATION_DATA(4103,"手机号码已经绑定,请解绑后再绑定"),
BIND_PHONE_ERROR(4104,"手机绑定失败,请联系客服"),
BIND_SUPPLIER_CODE_ERROR(4104,"供应链code绑定失败"),
UN_DELETE_ORG(4105,"该组织结构不支持删除"),
UN_FROZEN_ORG(4106,"当前组织不支持冻结"),
UN_BIND_CODE(4107,"当前微信账户还未绑定成功"),
INVALID_BIND_CODE(4108,"不可验证的绑定码"),
AUTHORIZE_CODE_MISMATCH(4109,"授权码不匹配"),
REFRESH_TOKEN_MISMATCH(4110, "Refresh-Token不匹配"),
;
private Integer code;
private String msg;
private ResultCode(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
package cn.quantgroup.big.stms.common.service;
import cn.quantgroup.big.stms.common.model.BaseEntityVO;
import java.io.Serializable;
/**
* @author xinm
* @create 2019-10-30
**/
public interface AssociatedService<T extends BaseEntityVO<ID>, ID extends Serializable> extends EntityService<T, ID> {
}
package cn.quantgroup.big.stms.common.service;
import cn.quantgroup.big.stms.common.model.BaseEntityVO;
import java.io.Serializable;
public interface BaseService<T extends BaseEntityVO<ID>, ID extends Serializable> extends EntityService<T, ID> {
}
package cn.quantgroup.big.stms.common.service;
import cn.quantgroup.big.stms.common.model.BaseBasicDataVO;
import java.io.Serializable;
import java.util.List;
public interface BasicDataService<T extends BaseBasicDataVO<ID>, ID extends Serializable> extends BaseService<T, ID> {
public void submit(ID id);
public void submit(T entity);
public T findByCode(String code);
T findByName(String name);
T findByCodeAndParentId(String code,ID parentId);
/**
* 启用
* @param id
*/
public void enabled(ID id);
/**
* 启用
* @param entity
*/
public void enabled(T entity);
/**
*
* <p>date: 2018年7月23日 下午6:34:46</p>
* <p>description: 禁用</p>
* @author rong.yang/阳荣
* @param
* @return
*/
public void disabled(ID id);
/**
*
* <p>date: 2018年7月23日 下午6:34:58</p>
* <p>description: 禁用</p>
* @author rong.yang/阳荣
* @param
* @return
*/
public void disabled(T entity);
/**
*
* <p>
* date: 2015年5月23日 下午2:49:01
* </p>
* <p>
* description: 获取所有的有效对象
* </p>
*
* @author rong.yang/阳荣
* @param
* @return
*/
public List<T> getValidObject();
}
\ No newline at end of file
package cn.quantgroup.big.stms.common.service;
import cn.quantgroup.big.stms.common.dao.BaseRepository;
import cn.quantgroup.big.stms.common.model.BaseEntityVO;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.Query;
import javax.persistence.EntityManager;
import java.io.Serializable;
import java.util.List;
import java.util.Optional;
/**
* <b>类名称:</b>BaseService<br/>
* <b>类描述:</b><br/>
* <b>创建人:</b>rong yang<br/>
* <b>修改人:</b>rong yang<br/>
* <b>修改时间:</b>2013-6-26 下午9:47:12<br/>
* <b>修改备注:</b><br/>
*
* @version 1.0.0<br/>
*
*/
public interface EntityService<T extends BaseEntityVO<ID>, ID extends Serializable> {
<R extends BaseRepository<T, ID>> R getRepository();
//CURD
/**
* Saves a given entity. Use the returned instance for further operations as the save operation might have changed the
* entity instance completely.
*
* @param entity must not be {@literal null}.
* @return the saved entity will never be {@literal null}.
*/
<S extends T> S save(S entity);
/**
* Saves all given entities.
*
* @param entities must not be {@literal null}.
* @return the saved entities will never be {@literal null}.
* @throws IllegalArgumentException in case the given entity is {@literal null}.
*/
<S extends T> Iterable<S> saveAll(Iterable<S> entities);
/**
* Retrieves an entity by its id.
*
* @param id must not be {@literal null}.
* @return the entity with the given id or {@literal Optional#empty()} if none found
* @throws IllegalArgumentException if {@code id} is {@literal null}.
*/
T findById(ID id);
/**
* Returns whether an entity with the given id exists.
*
* @param id must not be {@literal null}.
* @return {@literal true} if an entity with the given id exists, {@literal false} otherwise.
* @throws IllegalArgumentException if {@code id} is {@literal null}.
*/
boolean existsById(ID id);
/**
* Returns all instances of the type.
*
* @return all entities
*/
Iterable<T> findAll();
/**
* Returns all instances of the type with the given IDs.
*
* @param ids
* @return
*/
Iterable<T> findAllById(Iterable<ID> ids);
/**
* Returns the number of entities available.
*
* @return the number of entities
*/
long count();
/**
* Deletes the entity with the given id.
*
* @param id must not be {@literal null}.
* @throws IllegalArgumentException in case the given {@code id} is {@literal null}
*/
void deleteById(ID id);
/**
* Deletes a given entity.
*
* @param entity
* @throws IllegalArgumentException in case the given entity is {@literal null}.
*/
void delete(T entity);
/**
* Deletes the given entities.
*
* @param entities
* @throws IllegalArgumentException in case the given {@link Iterable} is {@literal null}.
*/
void deleteAll(Iterable<? extends T> entities);
/**
* Deletes all entities managed by the repository.
*/
void deleteAll();
//JPA
/*
* (non-Javadoc)
* @see org.springframework.data.repository.PagingAndSortingRepository#findAll(org.springframework.data.domain.Sort)
*/
List<T> findAll(Sort sort);
/**
* Flushes all pending changes to the database.
*/
void flush();
/**
* Saves an entity and flushes changes instantly.
*
* @param entity
* @return the saved entity
*/
<S extends T> S saveAndFlush(S entity);
/**
* Deletes the given entities in a batch which means it will create a single {@link Query}. Assume that we will clear
* the {@link EntityManager} after the call.
*
* @param entities
*/
void deleteInBatch(Iterable<T> entities);
/**
* Deletes all entities in a batch call.
*/
void deleteAllInBatch();
/**
* Returns a reference to the entity with the given identifier.
*
* @param id must not be {@literal null}.
* @return a reference to the entity with the given identifier.
* @see EntityManager#getReference(Class, Object)
* @throws javax.persistence.EntityNotFoundException if no entity exists for given {@code id}.
*/
T getOne(ID id);
/*
* (non-Javadoc)
* @see org.springframework.data.repository.query.QueryByExampleExecutor#findAll(org.springframework.data.domain.Example)
*/
<S extends T> List<S> findAll(Example<S> example);
/*
* (non-Javadoc)
* @see org.springframework.data.repository.query.QueryByExampleExecutor#findAll(org.springframework.data.domain.Example, org.springframework.data.domain.Sort)
*/
<S extends T> List<S> findAll(Example<S> example, Sort sort);
<S extends T> Page<S> findAll(Example<S> example, Pageable pageable);
//Page
/**
* Returns a {@link Page} of entities meeting the paging restriction provided in the {@code Pageable} object.
*
* @param pageable
* @return a page of entities
*/
Page<T> findAll(Pageable pageable);
//JpaSpecificationExecutor
/**
* Returns a single entity matching the given {@link Specification} or {@link Optional#empty()} if none found.
*
* @param spec can be {@literal null}.
* @return never {@literal null}.
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if more than one entity found.
*/
T findOne(Specification<T> spec);
/**
* Returns all entities matching the given {@link Specification}.
*
* @param spec can be {@literal null}.
* @return never {@literal null}.
*/
List<T> findAll(Specification<T> spec);
/**
* Returns a {@link Page} of entities matching the given {@link Specification}.
*
* @param spec can be {@literal null}.
* @param pageable must not be {@literal null}.
* @return never {@literal null}.
*/
Page<T> findAll(Specification<T> spec, Pageable pageable);
/**
* Returns all entities matching the given {@link Specification} and {@link Sort}.
*
* @param spec can be {@literal null}.
* @param sort must not be {@literal null}.
* @return never {@literal null}.
*/
List<T> findAll(Specification<T> spec, Sort sort);
/**
* Returns the number of instances that the given {@link Specification} will return.
*
* @param spec the {@link Specification} to count instances for. Can be {@literal null}.
* @return the number of instances.
*/
long count(Specification<T> spec);
}
package cn.quantgroup.big.stms.common.service;
import javax.mail.MessagingException;
/**
* @Author meng.xin@quantgroup.cn
* @Date 2020-01-13 11:50
* @Version 1.0
*/
public interface MailService {
/**
* 简单的文本邮件
*
* @param to 收件人地址
* @param subject 主题
* @param content 内容
*/
void sendSimpleMail(String to, String subject, String content);
/**
* 富文本邮件
* MimeMessageHelper支持发送复杂邮件模板,支持文本、附件、HTML、图片等。
*
* @param to 收件人地址
* @param subject 主题
* @param content 内容
* @param rscPath 资源路径
* @param rscId 资源ID
* @throws MessagingException
*/
void sendInlineResourceMail(String to, String subject, String content, String rscPath, String rscId) throws MessagingException;
}
package cn.quantgroup.big.stms.common.service;
import java.util.Set;
/**
* 权限校验
* @author yutong
* @data 2020年1月19日
*/
public interface PermissionService {
String ROLE_KEY = "role:user:";
/**
* 检查登录用户的请求request与权限
* @param paths
* @return
*/
boolean checkIgnore(String... paths);
/**
* 检查登录用户是否有指定权限 (TODO 未确认需求)
* @param ids
* @return
*/
boolean checkUsers(String... ids);
/**
* 检查用户权限路径
* @param tenantId 租户id
* @param paths
* @return
*/
boolean checkUri(Integer tenantId,String... paths);
/**
* 获取用户权限(正则转换)
* @param userid, null为刷新当前用户权限
* @return
*/
Set<String> getRegPermission(Integer tenantId ,String userid);
/**
* 刷新用户权限
* @param userid, null为刷新当前用户权限
* @return
*/
String refreshPermission(String userid,Integer tenantId);
/**
* 清理用户权限
* @param userIds
* @return
*/
boolean clearPermission(String... userIds);
}
package cn.quantgroup.big.stms.common.service;
import cn.quantgroup.big.stms.common.model.BaseTreeVO;
import cn.quantgroup.big.stms.common.model.TreeNode;
import java.io.Serializable;
import java.util.List;
public interface TreeService <T extends BaseTreeVO<T,ID>,ID extends Serializable> extends BasicDataService<T,ID>{
List<T> getPath(ID id);
List<TreeNode<T>> getTree(List<T> list);
}
package cn.quantgroup.big.stms.common.service.impl;
import cn.quantgroup.big.stms.common.context.AppContextHolder;
import cn.quantgroup.big.stms.common.model.BaseAssociatedVO;
import cn.quantgroup.big.stms.common.service.AssociatedService;
import java.io.Serializable;
import java.util.Date;
/**
* @author xinm
* @create 2019-10-30
**/
public abstract class BaseAssociatedServiceImpl<T extends BaseAssociatedVO<ID>, ID extends Serializable> extends BaseEntityServiceImpl<T, ID> implements AssociatedService<T, ID> {
protected void beforeSave(T entity) {
entity.setCreateTime(new Date());
entity.setCreator(AppContextHolder.getOnlineUser() == null ? null : AppContextHolder.getOnlineUser().getAccount());
}
}
package cn.quantgroup.big.stms.common.service.impl;
import cn.quantgroup.big.stms.common.enums.BasicDataStatus;
import cn.quantgroup.big.stms.common.model.BaseBasicDataVO;
import cn.quantgroup.big.stms.common.service.BasicDataService;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public abstract class BaseBasicDataServiceImpl<T extends BaseBasicDataVO<ID>, ID extends Serializable> extends BaseServiceImpl<T, ID> implements BasicDataService<T, ID> {
/**
* 分页排序:创建时间-倒序,排序号-倒序
*
* @return
*/
public Sort getSort() {
List<Sort.Order> orders = new ArrayList<>();
Sort.Order order1 = new Sort.Order(Direction.DESC, "sortNo");
Sort.Order order2 = new Sort.Order(Direction.DESC, "createTime");
orders.add(order1);
orders.add(order2);
return new Sort(orders);
}
/**
* 分页排序:创建时间-升序,排序号-倒序
*
* @return
*/
public Sort getSortByCreateTimeAES() {
List<Sort.Order> orders = new ArrayList<>();
Sort.Order order1 = new Sort.Order(Direction.DESC, "sortNo");
Sort.Order order2 = new Sort.Order(Direction.ASC, "createTime");
orders.add(order1);
orders.add(order2);
return new Sort(orders);
}
/**
* * <p>date: 2019年10月16日 下午6:34:46</p>
* <p>
* description: 获取所有的有效对象
* </p>
*
* @author rong.yang/阳荣
* @param
* @return
*/
public List<T> getValidObject() {
return findAll(new Specification<T>() {
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
return cb.equal(root.get("status"), BasicDataStatus.VALID);
}
},new Sort(Direction.ASC, "sortNo"));
}
public void submit(ID id) {
T entity = getOne(id);
submit(entity);
}
public void submit(T entity) {
check(entity);
beforeSubmit(entity);
entity.setStatus(BasicDataStatus.VALID);
save(entity);
afterSubmit(entity);
}
public T findByCode(String code) {
return findOne(new Specification<T>() {
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
return cb.equal(root.get("code"), code);
}
});
}
public T findByName(String name){
return findOne(new Specification<T>() {
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
return cb.equal(root.get("name"), name);
}
});
}
public T findByCodeAndParentId(String code,ID parentId) {
return findOne(new Specification<T>() {
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Predicate p1 = cb.equal(root.get("code"), code);
Predicate p2 = null;
if(null == parentId) {
p2 = cb.isNull(root.get("parent").get("id"));
}else {
p2 = cb.equal(root.get("parent").get("id"), parentId);
}
return cb.and(p1,p2);
}
});
}
/**
* 启用
* @param id
*/
public void enabled(ID id) {
T entity = getOne(id);
enabled(entity);
}
/**
* 启用
* @param entity
*/
public void enabled(T entity) {
beforeSubmit(entity);
entity.setStatus(BasicDataStatus.VALID);
save(entity);
afterSubmit(entity);
}
/**
*
* <p>date: 2019年10月16日 下午6:34:46</p>
* <p>description: 禁用</p>
* @author rong.yang/阳荣
* @param
* @return
*/
public void disabled(ID id) {
T entity = getOne(id);
disabled(entity);
}
/**
*
* <p>date: 2019年10月16日 下午6:34:46</p>
* <p>description: 禁用</p>
* @author rong.yang/阳荣
* @param
* @return
*/
public void disabled(T entity) {
beforeSubmit(entity);
entity.setStatus(BasicDataStatus.INVALID);
save(entity);
afterSubmit(entity);
}
/**
*
* <p>date: 2019年10月16日 下午6:34:46</p>
* <p>description: 提交时检查数据</p>
* @author rong.yang/阳荣
* @param
* @return
*/
protected void check(T vo) {
}
protected void beforeSubmit(T entity) {
}
protected void afterSubmit(T entity) {
}
/**
* 新增时设置状态
* @param entity
*/
protected void setAddNew(T entity) {
super.setAddNew(entity);
entity.setStatus(BasicDataStatus.SAVE);
}
}
package cn.quantgroup.big.stms.common.service.impl;
import cn.quantgroup.big.stms.common.model.BaseEntityVO;
import cn.quantgroup.big.stms.common.service.EntityService;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import java.io.Serializable;
import java.util.List;
public abstract class BaseEntityServiceImpl<T extends BaseEntityVO<ID>, ID extends Serializable>
implements EntityService<T, ID> {
@Override
public <S extends T> S save(S entity) {
beforeSave(entity);
entity = getRepository().save(entity);
afterSave(entity);
flush();
return entity;
}
@Override
public <S extends T> Iterable<S> saveAll(Iterable<S> entities) {
if (null == entities) {
return null;
}
entities.forEach(entity -> {
beforeSave(entity);
entity = getRepository().save(entity);
afterSave(entity);
});
flush();
return entities;
}
@Override
public T findById(ID id) {
return getRepository().findOne(id);
}
@Override
public boolean existsById(ID id) {
return getRepository().exists(id);
}
@Override
public Iterable<T> findAll() {
return getRepository().findAll();
}
@Override
public Iterable<T> findAllById(Iterable<ID> ids) {
return getRepository().findAll(ids);
}
@Override
public long count() {
return getRepository().count();
}
@Override
public void deleteById(ID id) {
T obj = findById(id);
if (null != obj) {
delete(obj);
}
}
@Override
public void delete(T entity) {
beforeDelete(entity);
getRepository().delete(entity);
afterDelete(entity);
flush();
}
@Override
public void deleteAll(Iterable<? extends T> entities) {
if (null == entities) {
return;
}
entities.forEach(entity -> {
beforeDelete(entity);
getRepository().delete(entity);
afterDelete(entity);
});
flush();
}
@Override
public List<T> findAll(Sort sort) {
return getRepository().findAll(sort);
}
@Override
public void flush() {
getRepository().flush();
}
@Override
public <S extends T> S saveAndFlush(S entity) {
beforeSave(entity);
entity = getRepository().saveAndFlush(entity);
afterSave(entity);
return entity;
}
// 不建议在业务功能在使用
@Override
public void deleteInBatch(Iterable<T> entities) {
getRepository().deleteInBatch(entities);
}
// 不建议在业务功能在使用
@Override
public void deleteAllInBatch() {
getRepository().deleteAllInBatch();
}
// 不建议在业务功能在使用
@Override
public void deleteAll() {
getRepository().deleteAll();
}
@Override
public T getOne(ID id) {
return getRepository().getOne(id);
}
@Override
public <S extends T> List<S> findAll(Example<S> example) {
return getRepository().findAll(example);
}
@Override
public <S extends T> List<S> findAll(Example<S> example, Sort sort) {
return getRepository().findAll(example, sort);
}
public <S extends T> Page<S> findAll(Example<S> example, Pageable pageable){
return getRepository().findAll(example,pageable);
}
@Override
public Page<T> findAll(Pageable pageable) {
return getRepository().findAll(pageable);
}
@Override
public T findOne(Specification<T> spec) {
return getRepository().findOne(spec);
}
@Override
public List<T> findAll(Specification<T> spec) {
return getRepository().findAll(spec);
}
@Override
public Page<T> findAll(Specification<T> spec, Pageable pageable) {
return getRepository().findAll(spec, pageable);
}
@Override
public List<T> findAll(Specification<T> spec, Sort sort) {
return getRepository().findAll(spec, sort);
}
@Override
public long count(Specification<T> spec) {
return getRepository().count(spec);
}
protected void beforeSave(T entity) {
}
protected void afterSave(T entity) {
}
protected void beforeDelete(T entity) {
}
protected void afterDelete(T entity) {
}
}
package cn.quantgroup.big.stms.common.service.impl;
import cn.quantgroup.big.stms.common.context.AppContextHolder;
import cn.quantgroup.big.stms.common.model.BaseVO;
import cn.quantgroup.big.stms.common.service.BaseService;
import java.io.Serializable;
import java.util.Date;
public abstract class BaseServiceImpl <T extends BaseVO<ID>, ID extends Serializable> extends BaseEntityServiceImpl<T, ID> implements BaseService<T,ID>{
@Override
protected void beforeSave(T entity) {
super.beforeSave(entity);
if(isNew(entity)){
setAddNew(entity);
}else{
setUpdate(entity);
}
}
private boolean isNew(T entity){
if(null == entity || null == entity.getId()){
return true;
}
return !existsById(entity.getId());
}
/**
* 新增时设置默认的属性
* @param entity
*/
protected void setAddNew(T entity) {
Date now = new Date();
entity.setCreateTime(now);
entity.setCreator(AppContextHolder.getOnlineUser() == null ? null : AppContextHolder.getOnlineUser().getAccount());
setDefaultValue(entity);
}
/**
* 设置默认值
*/
protected void setDefaultValue(T entity){
}
/**
* 更新时时设置默认的属性
* @param entity
*/
protected void setUpdate(T entity) {
Date now = new Date();
entity.setUpdateTime(now);
entity.setUpdateUser(AppContextHolder.getOnlineUser() == null ? null : AppContextHolder.getOnlineUser().getAccount());
}
}
package cn.quantgroup.big.stms.common.service.impl;
import cn.quantgroup.big.stms.common.dao.TreeRepository;
import cn.quantgroup.big.stms.common.exception.BizException;
import cn.quantgroup.big.stms.common.model.BaseTreeVO;
import cn.quantgroup.big.stms.common.model.TreeNode;
import cn.quantgroup.big.stms.common.service.TreeService;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
@SuppressWarnings({"rawtypes", "unchecked"})
public abstract class BaseTreeServiceImpl<T extends BaseTreeVO<T,ID>, ID extends Serializable> extends BaseBasicDataServiceImpl<T, ID> implements TreeService<T, ID> {
private static Logger logger = LoggerFactory.getLogger(BaseTreeServiceImpl.class);
public static final String LEVEL_CODE_DELIMITER = "-";
@Override
protected void setAddNew(T entity) {
//树节点相关属性的设置
if (isRootNode(entity)) {
//根节点
entity.setParent(null);
// try {
// PropertyUtils.setSimpleProperty(entity, "parent", null);
// } catch (Exception e) {
// logger.error(e.getMessage(), e);
// }
int count = getMaxLevelCodeOfChildren(null) + 1;
entity.setLevelCode(StringUtils.leftPad("" + count, getlevelCodeLength(), "0"));
entity.setDegree(0);//根结点设置为0
entity.setIsLeaf(true);
} else {
T parent = findById(entity.getParent().getId());
entity.setParent(parent);
// try {
// PropertyUtils.setSimpleProperty(entity, "parent", parent);
// } catch (Exception e) {
// logger.error(e.getMessage(), e);
// }
long count = getMaxLevelCodeOfChildren(parent.getId()) + 1;
String levelCode = parent.getLevelCode() + LEVEL_CODE_DELIMITER + StringUtils.leftPad("" + count, getlevelCodeLength(), "0");
entity.setLevelCode(levelCode);
entity.setDegree(parent.getDegree() + 1);
entity.setIsLeaf(true);
if (parent.getIsLeaf()) {
parent.setIsLeaf(false);
save(parent);
}
}
super.setAddNew(entity);
}
/**
* 是否根结点
*
* @param entity
* @return
*/
private boolean isRootNode(T entity) {
boolean isRoot = true;
if (null != entity.getParent()
&& null != entity.getParent().getId()
&& StringUtils.isNotEmpty(entity.getParent().getId().toString())) {
isRoot = false;
}
return isRoot;
}
protected void setUpdate(T entity) {
super.setUpdate(entity);
if (isRootNode(entity)) {
entity.setParent(null);
// try {
// PropertyUtils.setSimpleProperty(entity, "parent", null);
// } catch (Exception e) {
// logger.error(e.getMessage(), e);
// }
}
}
@Override
protected void afterDelete(T entity) {
super.afterDelete(entity);
if (null != entity.getParent()) {
T parent = entity.getParent();
long count = getChildrenSize(parent.getId());
if (0 == count) {
parent.setIsLeaf(true);
save(parent);
}
}
}
/**
* <p>date: 2017年6月29日 下午4:41:16</p>
* <p>description: 获取当前节点到顶层节点的路径</p>
*
* @param
* @return
* @author rong.yang/阳荣
*/
public List<T> getPath(ID id) {
LinkedList<T> aa = new LinkedList<T>();
T obj = getOne(id);
aa.addFirst(obj);
while (null != obj.getParent() && null != obj.getParent().getId()) {
obj = getOne(obj.getParent().getId());
aa.addFirst(obj);
}
return aa;
}
public List<T> getChildren(String parentId) {
return findAll(new Specification<T>() {
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Predicate predicate = null;
if (StringUtils.isEmpty(parentId)) {
predicate = cb.isNull(root.get("parent").get("id"));
} else {
predicate = cb.equal(root.get("parent").get("id"), parentId);
}
return predicate;
}
}, new Sort(Direction.ASC, "sortNo"));
}
/**
* 如是 parentId 为null 或空,则返回根节点个数
*
* @param parentId
* @return
*/
public long getChildrenSize(ID parentId) {
return count(new Specification<T>() {
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Predicate predicate = null;
if (null == parentId || StringUtils.isBlank(parentId.toString())) {
predicate = cb.isNull(root.get("parent").get("id"));
} else {
predicate = cb.equal(root.get("parent").get("id"), parentId);
}
return predicate;
}
});
}
private int getMaxLevelCodeOfChildren(ID parentId) {
int maxLevelCodeOfChildren = 0;//默认为零
String maxLevelCode = null;
if (null == parentId || StringUtils.isEmpty(parentId.toString())) {
maxLevelCode = ((TreeRepository) getRepository()).getMaxLevelCodeOfTopNode();
} else {
maxLevelCode = ((TreeRepository) getRepository()).getMaxLevelCodeOfChildren(parentId);
}
if (StringUtils.isNotEmpty(maxLevelCode)) {
int index = maxLevelCode.lastIndexOf(LEVEL_CODE_DELIMITER);
if (-1 != index) {
maxLevelCode = maxLevelCode.substring(index + 1);
}
maxLevelCodeOfChildren = Integer.valueOf(maxLevelCode);
}
return maxLevelCodeOfChildren;
}
protected void beforeDelete(T entity) {
long count = getChildrenSize(entity.getId());
if (count > 0) {
throw new BizException("该记录还有下级数据,不能删除!");
}
super.beforeDelete(entity);
}
//获取层次码的长度
protected int getlevelCodeLength() {
return 4;
}
//TODO 待优化,非递归方法实现
@Override
public List<TreeNode<T>> getTree(List<T> list) {
List<TreeNode<T>> treeNodeList = Lists.newArrayList();
for (T t : list) {
if (t.getParent() == null || !list.contains(t.getParent()) ) {
TreeNode treeNode = new TreeNode();
treeNode.setNode(t);
treeNode.setChildNodes(getChild(t, list));
treeNodeList.add(treeNode);
}
}
return treeNodeList;
}
private List<TreeNode<T>> getChild(T t, List<T> list) {
List<TreeNode<T>> treeNodeList = Lists.newArrayList();
for (T tt : list) {
if (tt.getParent() == t) {
TreeNode<T> treeNode = new TreeNode<>();
treeNodeList.add(treeNode);
treeNode.setNode(tt);
treeNode.setChildNodes(getChild(tt, list));
}
}
return treeNodeList;
}
}
package cn.quantgroup.big.stms.common.service.impl;
import cn.quantgroup.big.stms.common.service.MailService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;
/**
* @Author meng.xin@quantgroup.cn
* @Date 2020-01-13 11:51
* @Version 1.0
*/
@Service
public class MailServiceImpl implements MailService {
@Autowired
private JavaMailSender mailSender;
@Value("${spring.mail.username}")
private String from;// 邮件发送者
@Override
public void sendSimpleMail(String to, String subject, String content) throws MailException {
if(StringUtils.isEmpty(to)){
return;
}
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(from);
message.setTo(to); // 邮件接受者
message.setSubject(subject); // 主题
message.setText(content); // 内容
mailSender.send(message);
}
@Override
public void sendInlineResourceMail(String to, String subject, String content, String rscPath, String rscId) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(content, true);
File file = new File(rscPath);
FileSystemResource res = new FileSystemResource(file);
helper.addInline(rscId, res);
mailSender.send(message);
}
}
package cn.quantgroup.big.stms.common.utils;
import cn.quantgroup.security.AESEncryption;
import cn.quantgroup.security.CipherUtil;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigService;
import org.apache.commons.lang3.StringUtils;
public class AESUtils {
public static AESEncryption encryption;
public static String encrypt(final String plainValue) {
if(StringUtils.isNotEmpty(plainValue) && !CipherUtil.isCipherBase64((plainValue))){
return encryption().encryptBase64(plainValue);
}
return plainValue;
}
public static String decrypt(String cipherValue){
return StringUtils.isNotEmpty(cipherValue) && CipherUtil.isCipherBase64(cipherValue)?encryption().decryptBase64(cipherValue):cipherValue;
}
public static AESEncryption encryption() {
if (encryption == null) {
Config config = ConfigService.getAppConfig();
String key = config.getProperty("encrypt.key","");
String iv = config.getProperty("encrypt.iv","");
encryption = new AESEncryption(key, iv, true);
}
return encryption;
}
}
package cn.quantgroup.big.stms.common.utils;
public class Constants {
public static final String ACCESS_TOKEN = "Access-Token";
public static final String SUBJECT_OPEN = "账户开通信息";
public final static String CAPTCHA_KEY = "st:captcha:";
public final static String TOKEN_KEY = "st:token:";
// 代替敏感信息
public static final String SECRET = "*************";
public final static long ACCESS_TOKEN_EXPIRE = 3600L * 2;
/**
* 刷新token过期时间 单位秒
**/
public final static long REFRESH_TOKEN_EXPIRE = 3600L * 24 * 30;
public static final int PASSWORD_LENGTH_MIN = 13;// 密码最小长度
public static final int PASSWORD_LENGTH_MAX = 18;// 密码最大长度
public static final int SALT_LENGTH = 16;// 加密盐长度
/**
* 验证码过期时间 单位秒
**/
public final static long CAPTCHA_EXPIRE = 120;
public static final String OAUTH2_CODE_KEY = "st:oauth2:code:";
public static final String OAUTH2_TOKEN_KEY = "st:oauth2:token:";
public static final String OAUTH2_ACCESS_TOKEN = "QG-Access-Token";
}
package cn.quantgroup.big.stms.common.utils;
import org.apache.commons.lang3.StringUtils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
/**
* @author aoxq
* @date 2019/11/21 10:10
**/
public class DateUtil {
public static final String DATE_FORMAT_6 = "yyyyMM";
public static final String DATE_FORMAT_10 = "yyyy-MM-dd";
public static final String DATE_FORMAT_14 = "yyyyMMddHHmmss";
public static final String DATE_FORMAT_17 = "yyyyMMdd HH:mm:ss";
public static final String DATE_FORMAT_19 = "yyyy-MM-dd HH:mm:ss";
public static final String DATE_FORMAT_19_FORWARD_SLASH = "yyyy/MM/dd HH:mm:ss";
private DateUtil() {
throw new RuntimeException("不允许构造DateUtil的实例!");
}
/**
* 将Date转换成LocalDate
*/
public static LocalDate date2LocalDate(Date date) {
if (null == date) {
throw new RuntimeException("date can't be null");
}
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
}
/**
* 将localDate 转化为 Date
*/
public static Date localDate2Date(LocalDate localDate) {
if (localDate == null) {
throw new RuntimeException("date can't be null");
}
return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
}
/**
* 计算两个日期之前的月份
*/
public static int monthsBetween(Date start, Date end) {
if (start == null || end == null) {
throw new RuntimeException("date can't be null !");
}
LocalDate startLD = date2LocalDate(start);
LocalDate endLD = date2LocalDate(end);
if (startLD.compareTo(endLD) > 0) {
return monthsBetween(end, start);
}
int startYear = startLD.getYear();
int endYear = endLD.getYear();
int startMonth = startLD.getMonthValue();
int endMonth = endLD.getMonthValue();
return startYear == endYear ? (endMonth - startMonth) :
(endMonth + 12 * (endYear - startYear) - startMonth);
}
/**
* 字符串转时间
*
* @param str
* @return
* @throws ParseException
*/
public static Date stringToDate(String str) throws ParseException {
return stringToDate(str, null);
}
/**
* 字符串转时间
*
* @param str
* @param pattern 时间格式
* @return
* @throws ParseException
*/
public static Date stringToDate(String str, String pattern) throws ParseException {
if (null == str) {
return null;
}
if (StringUtils.isBlank(pattern)) {
pattern = "yyyy-MM-dd HH:mm:ss";
}
SimpleDateFormat format = new SimpleDateFormat(pattern);
return format.parse(str);
}
/**
* 计算两个日期之间的天数
*/
public static long daysBetween(Date start, Date end) {
if (start == null || end == null) {
throw new RuntimeException("date can't be null !");
}
LocalDate startLD = date2LocalDate(start);
LocalDate endLD = date2LocalDate(end);
return endLD.toEpochDay() - startLD.toEpochDay();
}
/**
* 格式化日期
* @param date
* @param dateFormat
* @return
*/
public static String format(Date date, String dateFormat) {
if (date == null) {
return "";
}
if (StringUtils.isEmpty(dateFormat)) {
dateFormat = DATE_FORMAT_19;
}
return new SimpleDateFormat(dateFormat).format(date);
}
/**
* 月份控制
* @param date
* @param addMonth
* @return
*/
public static Date controlMonth(Date date, int addMonth) {
if (date == null) {
date = new Date();
}
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.MONTH, addMonth);
return cal.getTime();
}
}
package cn.quantgroup.big.stms.common.utils;
\ No newline at end of file
package cn.quantgroup.big.stms.sys.controller;
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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