Initial commit
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
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>
|
||||
|
||||
<artifactId>common</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>公共模块</name>
|
||||
|
||||
<parent>
|
||||
<groupId>com.linln</groupId>
|
||||
<artifactId>pet-admin</artifactId>
|
||||
<version>2.0.3</version>
|
||||
</parent>
|
||||
</project>
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.linln.common;
|
||||
|
||||
|
||||
import com.linln.common.enums.ResultEnum;
|
||||
import com.linln.common.exception.ResultException;
|
||||
import com.linln.common.utils.EhCacheUtil;
|
||||
import net.sf.ehcache.Cache;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class MiniRequestInterceptor implements HandlerInterceptor {
|
||||
|
||||
public static final String TOKEN_ID = "token";
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
String token = request.getHeader(TOKEN_ID);
|
||||
Cache tokenCache = EhCacheUtil.getTokenCache();
|
||||
if (!tokenCache.isKeyInCache(token)) {
|
||||
throw new ResultException(ResultEnum.USER_TOKEN_INVALID);
|
||||
}
|
||||
return HandlerInterceptor.super.preHandle(request, response, handler);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.linln.common.config;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
/**
|
||||
* @author gion
|
||||
* @date 2021/3/19
|
||||
*/
|
||||
@ComponentScan(basePackages = "com.linln.common")
|
||||
public class CommonAutoConfig {
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.linln.common.config;
|
||||
|
||||
import com.linln.common.config.properties.ProjectProperties;
|
||||
import com.linln.common.xss.XssFilter;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* xss过滤拦截器
|
||||
* @author gion
|
||||
* @date 2018/12/9
|
||||
*/
|
||||
@Configuration
|
||||
public class XssFilterConfig {
|
||||
private static final int FILTER_ORDER = 1;
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean xssFilterRegistrationBean(ProjectProperties properties) {
|
||||
ProjectProperties.Xxs propertiesXxs = properties.getXxs();
|
||||
FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<Filter>();
|
||||
registration.setFilter(new XssFilter());
|
||||
registration.setOrder(FILTER_ORDER);
|
||||
registration.setEnabled(propertiesXxs.isEnabled());
|
||||
registration.addUrlPatterns(propertiesXxs.getUrlPatterns().split(","));
|
||||
Map<String, String> initParameters = new HashMap<>(16);
|
||||
initParameters.put("excludes", propertiesXxs.getExcludes());
|
||||
registration.setInitParameters(initParameters);
|
||||
return registration;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.linln.common.config.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* 项目配置项
|
||||
* @author gion
|
||||
* @date 2018/11/6
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "project")
|
||||
public class ProjectProperties {
|
||||
|
||||
/** 是否开启验证码 */
|
||||
private boolean captchaOpen = false;
|
||||
|
||||
/** 是否开启Swagger数据接口文档 */
|
||||
private boolean swaggerEnabled = true;
|
||||
|
||||
/** xss防护设置 */
|
||||
private ProjectProperties.Xxs xxs = new ProjectProperties.Xxs();
|
||||
|
||||
/**
|
||||
* xss防护设置
|
||||
*/
|
||||
@Data
|
||||
public static class Xxs {
|
||||
/** xss防护开关 */
|
||||
private boolean enabled = true;
|
||||
|
||||
/** 拦截规则,可通过“,”隔开多个 */
|
||||
private String urlPatterns = "/*";
|
||||
|
||||
/** 默认忽略规则(无需修改) */
|
||||
private String defaultExcludes = "/favicon.ico,/img/*,/js/*,/css/*,/lib/*";
|
||||
|
||||
/** 忽略规则,可通过“,”隔开多个 */
|
||||
private String excludes = "";
|
||||
|
||||
/**
|
||||
* 拼接忽略规则
|
||||
*/
|
||||
public String getExcludes() {
|
||||
if (!StringUtils.isEmpty(excludes.trim())) {
|
||||
return defaultExcludes + "," + excludes;
|
||||
}
|
||||
return defaultExcludes;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.linln.common.constant;
|
||||
|
||||
/**
|
||||
* 超级管理员常量
|
||||
* @author gion
|
||||
* @date 2018/8/14
|
||||
*/
|
||||
public class AdminConst {
|
||||
|
||||
/**
|
||||
* 超级管理员id
|
||||
*/
|
||||
public static Long ADMIN_ID = 1L;
|
||||
|
||||
/**
|
||||
* 超级管理员用户名
|
||||
*/
|
||||
public static String ADMIN_NAME = "admin";
|
||||
|
||||
/**
|
||||
* 超级管理员角色id
|
||||
*/
|
||||
public static Long ADMIN_ROLE_ID = 1L;
|
||||
|
||||
/**
|
||||
* 超级管理员角色标识名称
|
||||
*/
|
||||
public static String ADMIN_ROLE_NAME = "admin";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.linln.common.constant;
|
||||
|
||||
/**
|
||||
* 数据状态常量
|
||||
* @author gion
|
||||
* @date 2019/2/22
|
||||
*/
|
||||
public class StatusConst {
|
||||
|
||||
/** 正常状态码 */
|
||||
public static final byte OK = 1;
|
||||
|
||||
/** 冻结状态码 */
|
||||
public static final byte FREEZED = 2;
|
||||
|
||||
/** 删除状态码 */
|
||||
public static final byte DELETE = 3;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.linln.common.data;
|
||||
|
||||
import com.linln.common.utils.HttpServletUtil;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
|
||||
/**
|
||||
* 分页排序数据
|
||||
* @author gion
|
||||
* @date 2018/12/8
|
||||
*/
|
||||
public class PageSort {
|
||||
|
||||
private static final Integer PAGE_SIZE_DEF = 10;
|
||||
private static final String ORDER_BY_COLUMN_DEF = "createDate";
|
||||
private static final Sort.Direction SORT_DIRECTION = Sort.Direction.DESC;
|
||||
|
||||
/**
|
||||
* 创建分页排序对象
|
||||
*/
|
||||
public static PageRequest pageRequest(){
|
||||
return pageRequest(PAGE_SIZE_DEF, ORDER_BY_COLUMN_DEF, SORT_DIRECTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建分页排序对象
|
||||
* @param sortDirection 排序方式默认值
|
||||
*/
|
||||
public static PageRequest pageRequest(Sort.Direction sortDirection){
|
||||
return pageRequest(PAGE_SIZE_DEF, ORDER_BY_COLUMN_DEF, sortDirection);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建分页排序对象
|
||||
* @param orderByColumnDef 排序字段名称默认值
|
||||
* @param sortDirection 排序方式默认值
|
||||
*/
|
||||
public static PageRequest pageRequest(String orderByColumnDef, Sort.Direction sortDirection){
|
||||
return pageRequest(PAGE_SIZE_DEF, orderByColumnDef, sortDirection);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建分页排序对象
|
||||
* @param pageSizeDef 分页数据数量默认值
|
||||
* @param orderByColumnDef 排序字段名称默认值
|
||||
* @param sortDirection 排序方式默认值
|
||||
*/
|
||||
public static PageRequest pageRequest(Integer pageSizeDef, String orderByColumnDef, Sort.Direction sortDirection){
|
||||
Integer pageIndex = HttpServletUtil.getParameterInt("page", 1);
|
||||
Integer pageSize = HttpServletUtil.getParameterInt("size", pageSizeDef);
|
||||
String orderByColumn = HttpServletUtil.getParameter("orderByColumn", orderByColumnDef);
|
||||
String direction = HttpServletUtil.getParameter("isAsc", sortDirection.toString());
|
||||
Sort sort = Sort.by(Sort.Direction.fromString(direction), orderByColumn);
|
||||
return PageRequest.of((pageIndex-1), pageSize, sort);
|
||||
}
|
||||
|
||||
public static PageRequest pageRequest(int pageNo) {
|
||||
return PageRequest.of(pageNo-1, PAGE_SIZE_DEF, SORT_DIRECTION);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
package com.linln.common.data;
|
||||
|
||||
import com.linln.common.enums.ResultEnum;
|
||||
import com.linln.common.enums.StatusEnum;
|
||||
import com.linln.common.exception.ResultException;
|
||||
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.beans.BeanInfo;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author gion
|
||||
* @date 2018/12/7
|
||||
*/
|
||||
public class QuerySpec {
|
||||
/* 查询规则 */
|
||||
/** 精确查询(=) */
|
||||
public static final Long EQUAL = 0L;
|
||||
/** 模糊查询(*XX*) */
|
||||
public static final Long LIKE = 1L;
|
||||
/** 左模糊查询(*XX) */
|
||||
public static final Long LEFT_LIKE = 2L;
|
||||
/** 右模糊查询(XX*) */
|
||||
public static final Long RIGHT_LIKE = 3L;
|
||||
/** 不等于(!=) */
|
||||
public static final Long NOT_EQUAL = 4L;
|
||||
/** 大于(>) */
|
||||
public static final Long GT = 5L;
|
||||
/** 大于等于(>=) */
|
||||
public static final Long GE = 6L;
|
||||
/** 小于(<) */
|
||||
public static final Long LT = 7L;
|
||||
/** 小于等于(<=) */
|
||||
public static final Long LE = 8L;
|
||||
/** 多值(in) */
|
||||
public static final Long IN = 9L;
|
||||
/** 区间查询(between) */
|
||||
public static final Long BETWEEN = 10L;
|
||||
|
||||
/** 字段规则列表 */
|
||||
private Map<String, Long> fieldRules;
|
||||
/** 忽视字段 */
|
||||
private String[] ignoredPaths;
|
||||
/** 多值in查询方式值列表 */
|
||||
private Map<String, List<Object>> inValues;
|
||||
/** 区间between查询方式值列表 */
|
||||
private Map<String, Long[]> betweenValues;
|
||||
/** 状态字段名称 */
|
||||
private String status = "status";
|
||||
|
||||
/**
|
||||
* 无参构造方法,初始化数据
|
||||
*/
|
||||
private QuerySpec(){
|
||||
fieldRules = new HashMap<>();
|
||||
inValues = new HashMap<>();
|
||||
betweenValues = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建查询匹配器
|
||||
*/
|
||||
public static QuerySpec matching(){
|
||||
return new QuerySpec();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一条匹配规则
|
||||
* @param propertyPath 需要验证的字段名称
|
||||
* @param regulation 查询规则
|
||||
*/
|
||||
public QuerySpec withMatcher(String propertyPath, Long regulation){
|
||||
fieldRules.put(propertyPath, regulation);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一条IN匹配规则
|
||||
* @param propertyPath 需要验证的字段名称
|
||||
* @param inValueList IN数据列表
|
||||
*/
|
||||
public QuerySpec withMatcherIn(String propertyPath, List<Object> inValueList){
|
||||
fieldRules.put(propertyPath, IN);
|
||||
inValues.put(propertyPath, inValueList);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一条BETWEEN匹配规则
|
||||
* @param propertyPath 需要验证的字段名称
|
||||
* @param x 第一个值
|
||||
* @param y 第二个值
|
||||
*/
|
||||
public QuerySpec withMatcherBetween(String propertyPath, Long x, Long y){
|
||||
fieldRules.put(propertyPath, BETWEEN);
|
||||
betweenValues.put(propertyPath, new Long[]{x, y});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置忽略的字段
|
||||
* @param ignoredPaths 忽略字段
|
||||
*/
|
||||
public QuerySpec withIgnorePaths(String... ignoredPaths){
|
||||
this.ignoredPaths = ignoredPaths;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取规则列表
|
||||
*/
|
||||
private Map<String, Long> getFieldRules(){
|
||||
return fieldRules;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取忽略字段列表
|
||||
*/
|
||||
private List<String> getIgnoredPaths(){
|
||||
return Arrays.asList(ignoredPaths);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取in查询方式值列表
|
||||
*/
|
||||
private Map<String, List<Object>> getInValues(){
|
||||
return inValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取区间between查询方式值列表
|
||||
*/
|
||||
private Map<String, Long[]> getBetweenValues(){
|
||||
return betweenValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Specification<T>复杂查询实例
|
||||
* @param probe 实体对象
|
||||
* @param querySpec 匹配器
|
||||
*/
|
||||
public static <T> Specification<T> of(T probe, QuerySpec querySpec){
|
||||
|
||||
// 获取用户规则
|
||||
Map<String, Long> fieldRules = querySpec.getFieldRules();
|
||||
// 获取忽略字段
|
||||
List<String> ignoredPaths = querySpec.getIgnoredPaths();
|
||||
// 获取in查询方式值列表
|
||||
Map<String, List<Object>> inValues = querySpec.getInValues();
|
||||
// 获取in查询方式值列表
|
||||
Map<String, Long[]> betweenValues = querySpec.getBetweenValues();
|
||||
|
||||
// 创建Specification<T>对象
|
||||
Specification<T> specification = new Specification<T>(){
|
||||
|
||||
@Override
|
||||
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
|
||||
|
||||
List<Predicate> preList = new ArrayList<>();
|
||||
// 通过反射遍历实体对象
|
||||
try {
|
||||
final BeanInfo bi = Introspector.getBeanInfo(probe.getClass());
|
||||
for (final PropertyDescriptor pd : bi.getPropertyDescriptors()) {
|
||||
final Object value = pd.getReadMethod().invoke(probe, (Object[]) null);
|
||||
if(!(value instanceof Class) && value != null && !ignoredPaths.contains(pd.getName())){
|
||||
// 判断是否对数据状态进行非法请求
|
||||
if(querySpec.status.equals(pd.getName()) && StatusEnum.DELETE.getCode().equals(Byte.valueOf(String.valueOf(value)))){
|
||||
throw new ResultException(ResultEnum.STATUS_ERROR);
|
||||
}
|
||||
|
||||
// 进行查询匹配器配对
|
||||
if(fieldRules.containsKey(pd.getName())){
|
||||
Long regulation = fieldRules.get(pd.getName());
|
||||
// 精确查询
|
||||
if(regulation.equals(QuerySpec.EQUAL)){
|
||||
preList.add(cb.equal(root.get(pd.getName()).as(value.getClass()), value));
|
||||
}else
|
||||
// 模糊查询
|
||||
if(regulation.equals(QuerySpec.LIKE)){
|
||||
preList.add(cb.like(root.get(pd.getName()).as(String.class), "%"+ String.valueOf(value) +"%"));
|
||||
}else
|
||||
// 左模糊查询
|
||||
if(regulation.equals(QuerySpec.LEFT_LIKE)){
|
||||
preList.add(cb.like(root.get(pd.getName()).as(String.class), "%"+ String.valueOf(value)));
|
||||
}else
|
||||
// 右模糊查询
|
||||
if(regulation.equals(QuerySpec.RIGHT_LIKE)){
|
||||
preList.add(cb.like(root.get(pd.getName()).as(String.class), String.valueOf(value) +"%"));
|
||||
}else
|
||||
// 不等于查询
|
||||
if(regulation.equals(QuerySpec.NOT_EQUAL)){
|
||||
preList.add(cb.notEqual(root.get(pd.getName()).as(value.getClass()), value));
|
||||
}else
|
||||
// 大于查询
|
||||
if(regulation.equals(QuerySpec.GT)){
|
||||
preList.add(cb.gt(root.get(pd.getName()).as(Long.class), Long.valueOf(String.valueOf(value))));
|
||||
}else
|
||||
// 大于等于查询
|
||||
if(regulation.equals(QuerySpec.GE)){
|
||||
preList.add(cb.ge(root.get(pd.getName()).as(Long.class), Long.valueOf(String.valueOf(value))));
|
||||
}else
|
||||
// 小于查询
|
||||
if(regulation.equals(QuerySpec.LT)){
|
||||
preList.add(cb.lt(root.get(pd.getName()).as(Long.class), Long.valueOf(String.valueOf(value))));
|
||||
}else
|
||||
// 小于等于查询
|
||||
if(regulation.equals(QuerySpec.LE)){
|
||||
preList.add(cb.le(root.get(pd.getName()).as(Long.class), Long.valueOf(String.valueOf(value))));
|
||||
}else
|
||||
// 多值查询
|
||||
if(regulation.equals(QuerySpec.IN)){
|
||||
CriteriaBuilder.In<Object> in = cb.in(root.get(pd.getName()));
|
||||
List<Object> inList = inValues.get(pd.getName());
|
||||
if(inList != null){
|
||||
inList.forEach(in::value);
|
||||
preList.add(in);
|
||||
}
|
||||
}else
|
||||
// 区间查询
|
||||
if(regulation.equals(QuerySpec.BETWEEN)){
|
||||
Long[] between = betweenValues.get(pd.getName());
|
||||
preList.add(cb.between(root.get(pd.getName()), between[0], between[1]));
|
||||
}
|
||||
}else{
|
||||
preList.add(cb.equal(root.get(pd.getName()).as(value.getClass()), value));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (InvocationTargetException | IntrospectionException | IllegalAccessException e) {
|
||||
throw new IllegalArgumentException("获取实体类数据时出错,请检查实体类Bean格式是否规范!", e);
|
||||
}
|
||||
|
||||
Predicate[] pres = new Predicate[preList.size()];
|
||||
return query.where(preList.toArray(pres)).getRestriction();
|
||||
}
|
||||
};
|
||||
|
||||
return specification;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.linln.common.data;
|
||||
|
||||
import com.linln.common.utils.HttpServletUtil;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 封装URL地址,自动添加应用上下文路径
|
||||
*
|
||||
* @author gion
|
||||
* @date 2018/10/15
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("封装URL地址,自动添加应用上下文路径")
|
||||
public class URL {
|
||||
|
||||
@ApiModelProperty("URL地址")
|
||||
private String url;
|
||||
|
||||
public URL() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 封装URL地址,自动添加应用上下文路径
|
||||
*
|
||||
* @param url URL地址
|
||||
*/
|
||||
public URL(String url) {
|
||||
this.url = HttpServletUtil.getRequest().getContextPath() + url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.url;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.linln.common.dialect;
|
||||
|
||||
import org.hibernate.dialect.MySQL5Dialect;
|
||||
|
||||
/**
|
||||
* 重写数据库方言,设置默认字符集为utf8
|
||||
* @author gion
|
||||
* @date 2018/10/15
|
||||
*/
|
||||
public class MySQLDialectUTF8 extends MySQL5Dialect {
|
||||
|
||||
@Override
|
||||
public String getTableTypeString() {
|
||||
return " ENGINE=InnoDB DEFAULT CHARSET=utf8";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.linln.common.enums;
|
||||
|
||||
import com.linln.common.exception.interfaces.ResultInterface;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 后台返回结果集枚举
|
||||
* @author gion
|
||||
* @date 2018/8/14
|
||||
*/
|
||||
@Getter
|
||||
public enum ResultEnum implements ResultInterface {
|
||||
|
||||
/**
|
||||
* 通用状态
|
||||
*/
|
||||
SUCCESS(200, "成功"),
|
||||
ERROR(400, "错误"),
|
||||
|
||||
/**
|
||||
* 账户问题
|
||||
*/
|
||||
USER_EXIST(401, "该用户名已经存在"),
|
||||
USER_PWD_NULL(402, "密码不能为空"),
|
||||
USER_INEQUALITY(403, "两次密码不一致"),
|
||||
USER_OLD_PWD_ERROR(404, "原来密码不正确"),
|
||||
USER_NAME_PWD_NULL(405, "用户名和密码不能为空"),
|
||||
USER_CAPTCHA_ERROR(406, "验证码错误"),
|
||||
USER_TOKEN_INVALID(407, "token无效"),
|
||||
ENTRUST_NOT_FOUND(408, "委托单不存在"),
|
||||
SAMPLE_NOT_FOUND(409, "样品不存在"),
|
||||
|
||||
/**
|
||||
* 角色问题
|
||||
*/
|
||||
ROLE_EXIST(401, "该角色标识已经存在,不允许重复!"),
|
||||
|
||||
/**
|
||||
* 部门问题
|
||||
*/
|
||||
DEPT_EXIST_USER(401, "部门存在用户,无法删除"),
|
||||
|
||||
/**
|
||||
* 字典问题
|
||||
*/
|
||||
DICT_EXIST(401, "该字典标识已经存在,不允许重复!"),
|
||||
|
||||
/**
|
||||
* 非法操作
|
||||
*/
|
||||
STATUS_ERROR(401, "非法操作:状态有误"),
|
||||
|
||||
/**
|
||||
* 权限问题
|
||||
*/
|
||||
NO_PERMISSIONS(401, "权限不足!"),
|
||||
NO_ADMIN_AUTH(500, "不允许操作超级管理员"),
|
||||
NO_ADMIN_STATUS(501, "不能修改超级管理员状态"),
|
||||
NO_ADMINROLE_AUTH(500, "不允许操作管理员角色"),
|
||||
NO_ADMINROLE_STATUS(501, "不能修改管理员角色状态"),
|
||||
NOT_ENTRUST(502, "不存在委托单"),
|
||||
|
||||
;
|
||||
|
||||
private Integer code;
|
||||
|
||||
private String message;
|
||||
|
||||
ResultEnum(Integer code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.linln.common.enums;
|
||||
|
||||
import com.linln.common.constant.StatusConst;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 数据状态枚举-用于逻辑删除控制
|
||||
* @author gion
|
||||
* @date 2018/8/14
|
||||
*/
|
||||
@Getter
|
||||
public enum StatusEnum {
|
||||
|
||||
/**
|
||||
* 正常的数据
|
||||
*/
|
||||
OK(StatusConst.OK, "正常"),
|
||||
/**
|
||||
* 被冻结的数据,不可用
|
||||
*/
|
||||
FREEZED(StatusConst.FREEZED, "冻结"),
|
||||
/**
|
||||
* 数据已被删除
|
||||
*/
|
||||
DELETE(StatusConst.DELETE, "删除");
|
||||
|
||||
private Byte code;
|
||||
|
||||
private String message;
|
||||
|
||||
StatusEnum(Byte code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.linln.common.exception;
|
||||
|
||||
import com.linln.common.enums.ResultEnum;
|
||||
import com.linln.common.exception.interfaces.ResultInterface;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 自定义异常对象
|
||||
* @author gion
|
||||
* @date 2018/8/14
|
||||
*/
|
||||
@Getter
|
||||
public class ResultException extends RuntimeException {
|
||||
|
||||
private Integer code;
|
||||
|
||||
/**
|
||||
* 统一异常处理
|
||||
* @param resultEnum 状态枚举
|
||||
*/
|
||||
public ResultException(ResultEnum resultEnum) {
|
||||
super(resultEnum.getMessage());
|
||||
this.code = resultEnum.getCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一异常处理
|
||||
* @param resultEnum 枚举类型,需要实现结果枚举接口
|
||||
*/
|
||||
public ResultException(ResultInterface resultEnum) {
|
||||
super(resultEnum.getMessage());
|
||||
this.code = resultEnum.getCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一异常处理
|
||||
* @param code 状态码
|
||||
* @param message 提示信息
|
||||
*/
|
||||
public ResultException(Integer code, String message) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.linln.common.exception;
|
||||
|
||||
import com.linln.common.enums.ResultEnum;
|
||||
|
||||
/**
|
||||
* 自定义异常对象{统一异常处理:失败}
|
||||
* @author gion
|
||||
* @date 2019/10/17
|
||||
*/
|
||||
public class ResultExceptionError extends ResultException {
|
||||
|
||||
/**
|
||||
* 统一异常处理:抛出默认失败信息
|
||||
*/
|
||||
public ResultExceptionError() {
|
||||
super(ResultEnum.ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一异常处理:抛出失败提示信息
|
||||
* @param message 提示信息
|
||||
*/
|
||||
public ResultExceptionError(String message) {
|
||||
super(ResultEnum.ERROR.getCode(), message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.linln.common.exception;
|
||||
|
||||
import com.linln.common.exception.advice.ResultExceptionAdvice;
|
||||
import com.linln.common.utils.ResultVoUtil;
|
||||
import com.linln.common.utils.SpringContextUtil;
|
||||
import com.linln.common.vo.ResultVo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 全局统一异常处理
|
||||
* @author gion
|
||||
* @date 2018/8/14
|
||||
*/
|
||||
@ControllerAdvice
|
||||
@Slf4j
|
||||
public class ResultExceptionHandler {
|
||||
|
||||
/** 拦截自定义异常 */
|
||||
@ExceptionHandler(ResultException.class)
|
||||
@ResponseBody
|
||||
public ResultVo resultException(ResultException e){
|
||||
return ResultVoUtil.error(e.getCode(), e.getMessage());
|
||||
}
|
||||
|
||||
/** 拦截表单验证异常 */
|
||||
@ExceptionHandler(BindException.class)
|
||||
@ResponseBody
|
||||
public ResultVo bindException(BindException e){
|
||||
BindingResult bindingResult = e.getBindingResult();
|
||||
return ResultVoUtil.error(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
|
||||
}
|
||||
|
||||
/** 拦截未知的运行时异常 */
|
||||
@ExceptionHandler(RuntimeException.class)
|
||||
@ResponseBody
|
||||
public ResultVo runtimeException(RuntimeException e) {
|
||||
ResultExceptionAdvice resultExceptionAdvice = SpringContextUtil.getBean(ResultExceptionAdvice.class);
|
||||
resultExceptionAdvice.runtimeException(e);
|
||||
log.error("【系统异常】", e);
|
||||
return ResultVoUtil.error(500, "未知错误:EX4399");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.linln.common.exception;
|
||||
|
||||
import com.linln.common.enums.ResultEnum;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 自定义异常对象{统一异常处理:成功}
|
||||
* @author gion
|
||||
* @date 2019/10/17
|
||||
*/
|
||||
@Getter
|
||||
public class ResultExceptionSuccess extends ResultException {
|
||||
|
||||
/**
|
||||
* 统一异常处理:抛出默认成功信息
|
||||
*/
|
||||
public ResultExceptionSuccess() {
|
||||
super(ResultEnum.SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一异常处理:抛出成功提示信息
|
||||
* @param message 提示信息
|
||||
*/
|
||||
public ResultExceptionSuccess(String message) {
|
||||
super(ResultEnum.SUCCESS.getCode(), message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.linln.common.exception.advice;
|
||||
|
||||
/**
|
||||
* 异常通知器接口
|
||||
* @author gion
|
||||
* @date 2019/4/5
|
||||
*/
|
||||
public interface ExceptionAdvice {
|
||||
|
||||
/**
|
||||
* 运行
|
||||
* @param e 异常对象
|
||||
*/
|
||||
void run(RuntimeException e);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.linln.common.exception.advice;
|
||||
|
||||
import com.linln.common.utils.SpringContextUtil;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 异常通知器
|
||||
* @author gion
|
||||
* @date 2019/4/5
|
||||
*/
|
||||
@ControllerAdvice
|
||||
public class ResultExceptionAdvice {
|
||||
/** 运行切入程序集合 */
|
||||
private List<ExceptionAdvice> proceed = new ArrayList<>();
|
||||
|
||||
/** 添加切入程序 */
|
||||
public void putProceed(ExceptionAdvice advice){
|
||||
proceed.add(advice);
|
||||
}
|
||||
|
||||
/** 执行异常通知 */
|
||||
public void runtimeException(RuntimeException e){
|
||||
for (ExceptionAdvice ea : proceed) {
|
||||
ExceptionAdvice advice = SpringContextUtil.getBean(ea.getClass());
|
||||
advice.run(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.linln.common.exception.interfaces;
|
||||
|
||||
/**
|
||||
* 结果枚举接口
|
||||
* @author gion
|
||||
* @date 2019/2/13
|
||||
*/
|
||||
public interface ResultInterface {
|
||||
|
||||
/**
|
||||
* 获取状态编码
|
||||
* @return 编码
|
||||
*/
|
||||
Integer getCode();
|
||||
|
||||
/**
|
||||
* 获取提示信息
|
||||
* @return 提示信息
|
||||
*/
|
||||
String getMessage();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.linln.common.utils;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* 验证码生成工具
|
||||
* @author gion
|
||||
* @date 2018/11/7
|
||||
*/
|
||||
public class CaptchaUtil {
|
||||
|
||||
private final static int WIDTH = 120;
|
||||
private final static int HEIGHT = 45;
|
||||
private final static int LENGTH = 4;
|
||||
private final static String EX_CHARS = "10ioIO";
|
||||
|
||||
/**
|
||||
* 生成随机验证码
|
||||
*/
|
||||
public static String getRandomCode(){
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Random random = new Random();
|
||||
int i = 0;
|
||||
while(i< LENGTH){
|
||||
int t=random.nextInt(123);
|
||||
if((t>=97||(t>=65&&t<=90)||(t>=48&&t<=57))&&(EX_CHARS ==null|| EX_CHARS.indexOf((char)t)<0)){
|
||||
sb.append((char)t);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成验证码图片
|
||||
* @param randomCode 验证码
|
||||
*/
|
||||
public static BufferedImage genCaptcha(String randomCode){
|
||||
// 创建画布
|
||||
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D g = image.createGraphics();
|
||||
g.setColor(getRandColor(200, 250));
|
||||
g.fillRect(0, 0, WIDTH, HEIGHT);
|
||||
Random random = new Random();
|
||||
|
||||
// 绘制干扰线
|
||||
g.setColor(getRandColor(100, 180));
|
||||
for (int i = 0; i < 30; i++) {
|
||||
int x = random.nextInt(WIDTH - 1);
|
||||
int y = random.nextInt(HEIGHT - 1);
|
||||
int xl = random.nextInt(WIDTH / 2);
|
||||
int yl = random.nextInt(WIDTH / 2);
|
||||
g.drawLine(x, y, x + xl, y + yl + 20);
|
||||
}
|
||||
|
||||
// 添加噪点
|
||||
float rate = 0.1f;
|
||||
int area = (int) (rate * WIDTH * HEIGHT);
|
||||
for (int i = 0; i < area; i++) {
|
||||
int x = random.nextInt(WIDTH);
|
||||
int y = random.nextInt(HEIGHT);
|
||||
image.setRGB(x, y, getRandColor(100, 200).getRGB());
|
||||
}
|
||||
|
||||
// 绘制验证码
|
||||
int size = HEIGHT -4;
|
||||
Font font = new Font("Algerian", Font.ITALIC, size);
|
||||
g.setFont(font);
|
||||
char[] chars = randomCode.toCharArray();
|
||||
for(int i = 0; i < randomCode.length(); i++){
|
||||
g.drawChars(chars, i, 1, ((WIDTH -10) / randomCode.length()) * i + 5, HEIGHT /2 + size/2 - 6);
|
||||
}
|
||||
|
||||
g.dispose();
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取相应范围的随机颜色
|
||||
* @param min 最小值
|
||||
* @param max 最大值
|
||||
*/
|
||||
private static Color getRandColor(int min, int max) {
|
||||
min = min > 255 ? 255 : min;
|
||||
max = max > 255 ? 255 : max;
|
||||
Random random = new Random();
|
||||
int r = min + random.nextInt(max - min);
|
||||
int g = min + random.nextInt(max - min);
|
||||
int b = min + random.nextInt(max - min);
|
||||
return new Color(r, g, b);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.linln.common.utils;
|
||||
|
||||
import net.sf.ehcache.Cache;
|
||||
import net.sf.ehcache.CacheManager;
|
||||
|
||||
/**
|
||||
* EhCache缓存操作工具
|
||||
* @author gion
|
||||
* @date 2018/11/7
|
||||
*/
|
||||
public class EhCacheUtil {
|
||||
|
||||
/**
|
||||
* 获取EhCacheManager管理对象
|
||||
*/
|
||||
public static CacheManager getCacheManager(){
|
||||
return SpringContextUtil.getBean(CacheManager.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取EhCache缓存对象
|
||||
*/
|
||||
public static Cache getCache(String name){
|
||||
return getCacheManager().getCache(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字典缓存对象
|
||||
*/
|
||||
public static Cache getDictCache(){
|
||||
return getCacheManager().getCache("dictionary");
|
||||
}
|
||||
|
||||
public static Cache getTokenCache() {
|
||||
return getCacheManager().getCache("tokenCache");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.linln.common.utils;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* 加密工具
|
||||
* @author gion
|
||||
* @date 2019/4/25
|
||||
*/
|
||||
public class EncryptUtil {
|
||||
|
||||
/** 加密算法 */
|
||||
public final static String HASH_ALGORITHM_NAME = "SHA-256";
|
||||
/** 加密循环次数 */
|
||||
public final static int HASH_ITERATIONS = 1024;
|
||||
/** 字符编码 */
|
||||
private final static String CHARSET = "UTF-8";
|
||||
|
||||
/**
|
||||
* 加密处理
|
||||
* @param password 密码
|
||||
* @param salt 密码盐
|
||||
*/
|
||||
public static String encrypt(String password, String salt) {
|
||||
return encrypt(password, salt, HASH_ALGORITHM_NAME, HASH_ITERATIONS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密处理
|
||||
* @param password 密码
|
||||
* @param salt 密码盐
|
||||
* @param hashAlgorithmName 加密算法
|
||||
* @param hashIterations 加密循环次数
|
||||
*/
|
||||
public static String encrypt(String password, String salt, String hashAlgorithmName, int hashIterations) {
|
||||
// 将字符串转换为字节数组
|
||||
byte[] byteSalt = new byte[0];
|
||||
byte[] bytePassword = new byte[0];
|
||||
try {
|
||||
byteSalt = salt.getBytes(CHARSET);
|
||||
bytePassword = password.getBytes(CHARSET);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// 创建加密方式
|
||||
MessageDigest digest = null;
|
||||
try {
|
||||
// 根据加密算法获取加密对象
|
||||
digest = MessageDigest.getInstance(hashAlgorithmName);
|
||||
|
||||
// 加盐混淆
|
||||
digest.reset();
|
||||
digest.update(byteSalt);
|
||||
|
||||
// 密码混淆
|
||||
byte[] hashed = digest.digest(bytePassword);
|
||||
|
||||
// 循环混淆
|
||||
for(int i = 0; i < hashIterations - 1; ++i) {
|
||||
digest.reset();
|
||||
hashed = digest.digest(hashed);
|
||||
}
|
||||
|
||||
// 返回16进制字符串
|
||||
return bytesToHexString(hashed);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取随机盐值
|
||||
*/
|
||||
public static String getRandomSalt(){
|
||||
return ToolUtil.getRandomString(6);
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符数组转16进制字符串
|
||||
* @param data 字符数组
|
||||
*/
|
||||
private static String bytesToHexString(byte[] data){
|
||||
char[] digits = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||
final int l = data.length;
|
||||
final char[] out = new char[l << 1];
|
||||
for (int i = 0, j = 0; i < l; i++) {
|
||||
out[j++] = digits[(0xF0 & data[i]) >>> 4];
|
||||
out[j++] = digits[0x0F & data[i]];
|
||||
}
|
||||
return new String(out);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
package com.linln.common.utils;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import javax.persistence.Id;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 实体对象操作工具
|
||||
*
|
||||
* @author gion
|
||||
* @date 2018/10/15
|
||||
*/
|
||||
public class EntityBeanUtil {
|
||||
|
||||
/** 复制实体对象保留的默认字段 */
|
||||
private static String[] defaultFields = new String[]{
|
||||
"createDate",
|
||||
"updateDate",
|
||||
"createBy",
|
||||
"updateBy",
|
||||
"status"
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取实体对象ID字段值
|
||||
*
|
||||
* @param entity 实体对象
|
||||
* @return [0]为ID字段名,[1]为ID字段值
|
||||
*/
|
||||
public static Object[] getId(Object entity) {
|
||||
Field[] fields = entity.getClass().getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
Id id = field.getAnnotation(Id.class);
|
||||
if (id != null) {
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
return new Object[]{field.getName(), field.get(entity)};
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new FatalBeanException(
|
||||
"获取" + entity.getClass().getName() + "实体对象主键出错!", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字段名获取实体对象值
|
||||
*
|
||||
* @param entity 实体对象
|
||||
* @param fieldName 字段名
|
||||
* @return Object对象
|
||||
*/
|
||||
public static Object getField(Object entity, String fieldName) throws InvocationTargetException, IllegalAccessException {
|
||||
PropertyDescriptor beanObjectPd = BeanUtils.getPropertyDescriptor(entity.getClass(), fieldName);
|
||||
if (beanObjectPd != null) {
|
||||
Method readMethod = beanObjectPd.getReadMethod();
|
||||
if (readMethod != null) {
|
||||
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
|
||||
readMethod.setAccessible(true);
|
||||
}
|
||||
return readMethod.invoke(entity);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字段名获取实体对象值
|
||||
*
|
||||
* @param entity 实体对象
|
||||
* @param fieldName 字段名
|
||||
* @param value 字段值
|
||||
*/
|
||||
public static void setField(Object entity, String fieldName, Object value) throws InvocationTargetException, IllegalAccessException {
|
||||
PropertyDescriptor beanObjectPd = BeanUtils.getPropertyDescriptor(entity.getClass(), fieldName);
|
||||
if (beanObjectPd != null) {
|
||||
Method writeMethod = beanObjectPd.getWriteMethod();
|
||||
if (writeMethod != null) {
|
||||
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
|
||||
writeMethod.setAccessible(true);
|
||||
}
|
||||
writeMethod.invoke(entity, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制实体对象指定字段的数据,复制默认字段数据
|
||||
* {用于保留部分原始数据}
|
||||
*
|
||||
* @param source 源对象
|
||||
* @param target 目标对象
|
||||
*/
|
||||
public static void copyProperties(Object source, Object target) throws BeansException {
|
||||
EntityBeanUtil.copyProperties(source, target, null, defaultFields);
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制实体对象指定字段的数据,复制自定义的字段数据
|
||||
* {用于保留部分原始数据}
|
||||
*
|
||||
* @param source 源对象
|
||||
* @param target 目标对象
|
||||
* @param fields 需要保留的自定义字段
|
||||
*/
|
||||
public static void copyProperties(Object source, Object target, String... fields) throws BeansException {
|
||||
// 合并两个数组
|
||||
String[] jointRetainProperties = new String[defaultFields.length + fields.length];
|
||||
System.arraycopy(defaultFields, 0, jointRetainProperties, 0, defaultFields.length);
|
||||
System.arraycopy(fields, 0, jointRetainProperties, defaultFields.length, fields.length);
|
||||
EntityBeanUtil.copyProperties(source, target, null, jointRetainProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制实体对象指定字段的数据
|
||||
* {用于保留部分原始数据}
|
||||
* {代码基于BeanUtils.copyProperties(...)}
|
||||
*
|
||||
* @param source 源对象
|
||||
* @param target 目标对象
|
||||
* @param editable 将字段设置限制为的类(或接口)
|
||||
* @param fields 需要保留的自定义字段
|
||||
*/
|
||||
private static void copyProperties(Object source, Object target, @Nullable Class<?> editable,
|
||||
@Nullable String... fields) throws BeansException {
|
||||
|
||||
Assert.notNull(source, "Source must not be null");
|
||||
Assert.notNull(target, "Target must not be null");
|
||||
|
||||
Class<?> actualEditable = target.getClass();
|
||||
if (editable != null) {
|
||||
if (!editable.isInstance(target)) {
|
||||
throw new IllegalArgumentException("Target class [" + target.getClass().getName() +
|
||||
"] not assignable to Editable class [" + editable.getName() + "]");
|
||||
}
|
||||
actualEditable = editable;
|
||||
}
|
||||
PropertyDescriptor[] targetPds = BeanUtils.getPropertyDescriptors(actualEditable);
|
||||
List<String> ignoreList = (fields != null ? Arrays.asList(fields) : null);
|
||||
|
||||
for (PropertyDescriptor targetPd : targetPds) {
|
||||
Method writeMethod = targetPd.getWriteMethod();
|
||||
if (writeMethod != null && (ignoreList == null || ignoreList.contains(targetPd.getName()))) {
|
||||
PropertyDescriptor sourcePd = BeanUtils.getPropertyDescriptor(source.getClass(), targetPd.getName());
|
||||
if (sourcePd != null) {
|
||||
Method readMethod = sourcePd.getReadMethod();
|
||||
if (readMethod != null &&
|
||||
ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
|
||||
try {
|
||||
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
|
||||
readMethod.setAccessible(true);
|
||||
}
|
||||
Object value = readMethod.invoke(source);
|
||||
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
|
||||
writeMethod.setAccessible(true);
|
||||
}
|
||||
writeMethod.invoke(target, value);
|
||||
} catch (Throwable ex) {
|
||||
throw new FatalBeanException(
|
||||
"Could not copy property '" + targetPd.getName() + "' from source to target", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制实体对象数据,忽略默认字段数据
|
||||
* {用于忽略部分原始数据,功能与copyProperties相反}
|
||||
*
|
||||
* @param source 源对象
|
||||
* @param target 目标对象
|
||||
*/
|
||||
public static void copyPropertiesIgnores(Object source, Object target) {
|
||||
BeanUtils.copyProperties(source, target, defaultFields);
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制实体对象数据,忽略默认字段数据
|
||||
* {用于忽略部分原始数据,功能与copyProperties相反}
|
||||
*
|
||||
* @param source 源对象
|
||||
* @param target 目标对象
|
||||
* @param ignoreProperties 需要忽略的自定义字段
|
||||
*/
|
||||
public static void copyPropertiesIgnores(Object source, Object target, String... ignoreProperties) {
|
||||
// 合并两个数组
|
||||
String[] jointIgnoreProperties = new String[defaultFields.length + ignoreProperties.length];
|
||||
System.arraycopy(defaultFields, 0, jointIgnoreProperties, 0, defaultFields.length);
|
||||
System.arraycopy(ignoreProperties, 0, jointIgnoreProperties, defaultFields.length, ignoreProperties.length);
|
||||
BeanUtils.copyProperties(source, target, jointIgnoreProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* 克隆一个新的bean对象
|
||||
*
|
||||
* @param object 源对象
|
||||
*/
|
||||
public static Object cloneBean(Object object) {
|
||||
return cloneBean(object, (String[]) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 克隆一个新的bean对象,忽略部分字段
|
||||
*
|
||||
* @param object 源对象
|
||||
* @param ignoreProperties 需要忽略的字段
|
||||
*/
|
||||
public static Object cloneBean(Object object, String... ignoreProperties) {
|
||||
Object cloneObject = null;
|
||||
if (object != null) {
|
||||
try {
|
||||
cloneObject = object.getClass().newInstance();
|
||||
BeanUtils.copyProperties(object, cloneObject, ignoreProperties);
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return cloneObject;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.linln.common.utils;
|
||||
|
||||
import com.linln.common.MiniRequestInterceptor;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* 获取HttpServlet子对象
|
||||
* @author gion
|
||||
* @date 2018/10/15
|
||||
*/
|
||||
public class HttpServletUtil {
|
||||
|
||||
/**
|
||||
* 获取ServletRequestAttributes对象
|
||||
*/
|
||||
public static ServletRequestAttributes getServletRequest(){
|
||||
return (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取HttpServletRequest对象
|
||||
*/
|
||||
public static HttpServletRequest getRequest(){
|
||||
return getServletRequest().getRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取HttpServletResponse对象
|
||||
*/
|
||||
public static HttpServletResponse getResponse(){
|
||||
return getServletRequest().getResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求参数
|
||||
*/
|
||||
public static String getParameter(String param){
|
||||
return getRequest().getParameter(param);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求参数,带默认值
|
||||
*/
|
||||
public static String getParameter(String param, String defaultValue){
|
||||
String parameter = getRequest().getParameter(param);
|
||||
return StringUtils.isEmpty(parameter) ? defaultValue : parameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求参数转换为int类型
|
||||
*/
|
||||
public static Integer getParameterInt(String param){
|
||||
return Integer.valueOf(getRequest().getParameter(param));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求参数转换为int类型,带默认值
|
||||
*/
|
||||
public static Integer getParameterInt(String param, Integer defaultValue){
|
||||
return Integer.valueOf(getParameter(param, String.valueOf(defaultValue)));
|
||||
}
|
||||
|
||||
public static String getRequestToken() {
|
||||
return getRequest().getHeader(MiniRequestInterceptor.TOKEN_ID);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.linln.common.utils;
|
||||
|
||||
import com.linln.common.enums.ResultEnum;
|
||||
import com.linln.common.vo.ResultVo;
|
||||
|
||||
/**
|
||||
* 响应数据(结果)最外层对象工具
|
||||
*
|
||||
* @author gion
|
||||
* @date 2018/10/15
|
||||
*/
|
||||
public class ResultVoUtil {
|
||||
|
||||
public static ResultVo SAVE_SUCCESS = success("保存成功");
|
||||
|
||||
/**
|
||||
* 操作成功
|
||||
*
|
||||
* @param msg 提示信息
|
||||
* @param object 对象
|
||||
*/
|
||||
public static <T> ResultVo<T> success(String msg, T object) {
|
||||
ResultVo<T> resultVo = new ResultVo<>();
|
||||
resultVo.setMsg(msg);
|
||||
resultVo.setCode(ResultEnum.SUCCESS.getCode());
|
||||
resultVo.setData(object);
|
||||
return resultVo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作成功,使用默认的提示信息
|
||||
*
|
||||
* @param object 对象
|
||||
*/
|
||||
public static <T> ResultVo<T> success(T object) {
|
||||
String message = ResultEnum.SUCCESS.getMessage();
|
||||
return success(message, object);
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作成功,返回提示信息,不返回数据
|
||||
*/
|
||||
public static <T> ResultVo<T> success(String msg) {
|
||||
return success(msg, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作成功,不返回数据
|
||||
*/
|
||||
public static ResultVo success() {
|
||||
return success(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作有误
|
||||
*
|
||||
* @param code 错误码
|
||||
* @param msg 提示信息
|
||||
*/
|
||||
public static ResultVo error(Integer code, String msg) {
|
||||
ResultVo resultVo = new ResultVo();
|
||||
resultVo.setMsg(msg);
|
||||
resultVo.setCode(code);
|
||||
return resultVo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作有误,使用默认400错误码
|
||||
*
|
||||
* @param msg 提示信息
|
||||
*/
|
||||
public static ResultVo error(String msg) {
|
||||
Integer code = ResultEnum.ERROR.getCode();
|
||||
return error(code, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作有误,只返回默认错误状态码
|
||||
*/
|
||||
public static ResultVo error() {
|
||||
return error(null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.linln.common.utils;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 获取Spring的ApplicationContext对象工具,可以用静态方法的方式获取spring容器中的bean
|
||||
* @author gion
|
||||
* @date 2018/10/15
|
||||
*/
|
||||
@Component
|
||||
public class SpringContextUtil implements ApplicationContextAware {
|
||||
|
||||
private static ApplicationContext applicationContext;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
SpringContextUtil.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取applicationContext
|
||||
*/
|
||||
public static ApplicationContext getApplicationContext() {
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过name获取 Bean.
|
||||
*/
|
||||
public static Object getBean(String name){
|
||||
return getApplicationContext().getBean(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过class获取Bean.
|
||||
*/
|
||||
public static <T> T getBean(Class<T> clazz){
|
||||
return getApplicationContext().getBean(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过name,以及Clazz返回指定的Bean
|
||||
*/
|
||||
public static <T> T getBean(String name, Class<T> clazz){
|
||||
return getApplicationContext().getBean(name, clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置文件配置项的值
|
||||
* @param key 配置项key
|
||||
*/
|
||||
public static String getEnvironmentProperty(String key){
|
||||
return getApplicationContext().getEnvironment().getProperty(key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.linln.common.utils;
|
||||
|
||||
import com.linln.common.constant.StatusConst;
|
||||
import com.linln.common.enums.ResultEnum;
|
||||
import com.linln.common.enums.StatusEnum;
|
||||
import com.linln.common.exception.ResultException;
|
||||
|
||||
/**
|
||||
* 数据状态工具
|
||||
* @author gion
|
||||
* @date 2019/2/19
|
||||
*/
|
||||
public class StatusUtil {
|
||||
|
||||
/** 逻辑删除语句 */
|
||||
public static final String SLICE_DELETE = " set status=" + StatusConst.DELETE + " WHERE id=?";
|
||||
|
||||
/** 不等于逻辑删除条件语句 */
|
||||
public static final String NOT_DELETE = "status != " + StatusConst.DELETE;
|
||||
|
||||
/**
|
||||
* 获取状态StatusEnum对象
|
||||
* @param param 状态字符参数
|
||||
*/
|
||||
public static StatusEnum getStatusEnum(String param){
|
||||
try {
|
||||
return StatusEnum.valueOf(param.toUpperCase());
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ResultException(ResultEnum.STATUS_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
package com.linln.common.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* 通用方法工具类
|
||||
* @author gion
|
||||
* @date 2018/10/15
|
||||
*/
|
||||
public class ToolUtil {
|
||||
|
||||
/**
|
||||
* 获取随机位数的字符串
|
||||
* @param length 随机位数
|
||||
*/
|
||||
public static String getRandomString(int length) {
|
||||
Random random = new Random();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < length; i++) {
|
||||
// 获取ascii码中的字符 数字48-57 小写65-90 大写97-122
|
||||
int range = random.nextInt(75)+48;
|
||||
range = range<97?(range<65?(range>57?114-range:range):(range>90?180-range:range)):range;
|
||||
sb.append((char)range);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 首字母转小写
|
||||
*/
|
||||
public static String lowerFirst(String word){
|
||||
if(Character.isLowerCase(word.charAt(0))) {
|
||||
return word;
|
||||
} else {
|
||||
return String.valueOf(Character.toLowerCase(word.charAt(0))) + word.substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 首字母转大写
|
||||
*/
|
||||
public static String upperFirst(String word){
|
||||
if(Character.isUpperCase(word.charAt(0))) {
|
||||
return word;
|
||||
} else {
|
||||
return String.valueOf(Character.toUpperCase(word.charAt(0))) + word.substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取项目不同模式下的根路径
|
||||
*/
|
||||
public static String getProjectPath(){
|
||||
String filePath = ToolUtil.class.getResource("").getPath();
|
||||
String projectPath = ToolUtil.class.getClassLoader().getResource("").getPath();
|
||||
StringBuilder path = new StringBuilder();
|
||||
|
||||
if(!filePath.startsWith("file:/")){
|
||||
// 开发模式下根路径
|
||||
char[] filePathArray = filePath.toCharArray();
|
||||
char[] projectPathArray = projectPath.toCharArray();
|
||||
for (int i = 0; i < filePathArray.length; i++) {
|
||||
if(projectPathArray.length > i && filePathArray[i] == projectPathArray[i]){
|
||||
path.append(filePathArray[i]);
|
||||
}else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else if(!projectPath.startsWith("file:/")){
|
||||
// 部署服务器模式下根路径
|
||||
projectPath = projectPath.replace("/WEB-INF/classes/", "");
|
||||
projectPath = projectPath.replace("/target/classes/", "");
|
||||
try {
|
||||
path.append(URLDecoder.decode(projectPath,"UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return projectPath;
|
||||
}
|
||||
}else {
|
||||
// jar包启动模式下根路径
|
||||
String property = System.getProperty("java.class.path");
|
||||
int firstIndex = property.lastIndexOf(System.getProperty("path.separator")) + 1;
|
||||
int lastIndex = property.lastIndexOf(File.separator) + 1;
|
||||
path.append(property, firstIndex, lastIndex);
|
||||
}
|
||||
|
||||
File file = new File(path.toString());
|
||||
String rootPath = "/";
|
||||
try {
|
||||
rootPath = URLDecoder.decode(file.getAbsolutePath(), "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return rootPath.replaceAll("\\\\","/");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件后缀名
|
||||
*/
|
||||
public static String getFileSuffix(String fileName) {
|
||||
if(!fileName.isEmpty()){
|
||||
int lastIndexOf = fileName.lastIndexOf(".");
|
||||
return fileName.substring(lastIndexOf);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 将枚举转成List集合
|
||||
* @param enumClass 枚举类
|
||||
*/
|
||||
public static Map<Long, String> enumToMap(Class<?> enumClass){
|
||||
Map<Long, String> map = new TreeMap<>();
|
||||
try {
|
||||
Object[] objects = enumClass.getEnumConstants();
|
||||
Method getCode = enumClass.getMethod("getCode");
|
||||
Method getMessage = enumClass.getMethod("getMessage");
|
||||
for (Object obj : objects) {
|
||||
Object iCode = getCode.invoke(obj);
|
||||
Object iMessage = getMessage.invoke(obj);
|
||||
map.put(Long.valueOf(String.valueOf(iCode)), String.valueOf(iMessage));
|
||||
}
|
||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) {
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据枚举code获取枚举对象
|
||||
* @param enumClass 枚举类
|
||||
* @param code code值
|
||||
*/
|
||||
public static Object enumCode(Class<?> enumClass, Object code){
|
||||
try {
|
||||
Object[] objects = enumClass.getEnumConstants();
|
||||
Method getCode = enumClass.getMethod("getCode");
|
||||
for (Object obj : objects) {
|
||||
Object iCode = getCode.invoke(obj);
|
||||
if(iCode.equals(code)){
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
package com.linln.common.utils;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 工作日计算工具类
|
||||
* Created by MJ·J on 2019-05-24
|
||||
*/
|
||||
public class WorkDayUtils {
|
||||
|
||||
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||
/**
|
||||
* 获取当前时间之前n个工作日的日期
|
||||
*
|
||||
* @param holidays 节假日(日期格式:2019-01-01,2019-01-04,2019-01-05,......)
|
||||
* @param today 当前日期(日期格式:2019-01-01 08:08:08)
|
||||
* @param num 需要设置的n个工作日
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String getWorkDayStart(String holidays, String today, int num) throws Exception {
|
||||
// 转化为数组
|
||||
String[] dayArr = holidays.split(",");
|
||||
List<String> holidayList = new ArrayList<String>(Arrays.asList(dayArr));
|
||||
// 将字符串转换成日期
|
||||
Date date = sdf.parse(today);
|
||||
|
||||
// 获取工作日
|
||||
Date workDay = getWorkDay(holidayList, num, date, -1);
|
||||
String workDayStr = sdf.format(workDay);
|
||||
long workTime = getTime(today, workDayStr) - 1000; // 减1秒
|
||||
|
||||
return sdf.format(new Date(workTime));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前时间之后n个工作日的日期
|
||||
*
|
||||
* @param holidays 节假日
|
||||
* @param dd 当前日期
|
||||
* @param num 需要设置的n个工作日
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static Date getWorkDayEnd(String holidays, Date dd, int num){
|
||||
try {
|
||||
// 当前时间
|
||||
String today = sdf.format(dd);
|
||||
// 转化为数组
|
||||
String[] dayArr = holidays.split(",");
|
||||
List<String> holidayList = new ArrayList<String>(Arrays.asList(dayArr));
|
||||
|
||||
// 将字符串转换成日期
|
||||
Date date = sdf.parse(today);
|
||||
|
||||
// 获取工作日
|
||||
Date workDay = getWorkDay(holidayList, num, date, 1);
|
||||
String workDayStr = sdf.format(workDay);
|
||||
long workTime = getTime(today, workDayStr) + 1000; // 加1秒
|
||||
return new Date(workTime);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return new Date();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前时间之后n个工作日的日期
|
||||
*
|
||||
* @param holidays 节假日(日期格式:2019-01-01,2019-01-04,2019-01-05,......)
|
||||
* @param today 当前日期(日期格式:2019-01-01 08:08:08)
|
||||
* @param num 需要设置的n个工作日
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String getWorkDayEnd(String holidays, String today, int num) throws Exception {
|
||||
// 转化为数组
|
||||
String[] dayArr = holidays.split(",");
|
||||
List<String> holidayList = new ArrayList<String>(Arrays.asList(dayArr));
|
||||
|
||||
// 将字符串转换成日期
|
||||
Date date = sdf.parse(today);
|
||||
|
||||
// 获取工作日
|
||||
Date workDay = getWorkDay(holidayList, num, date, 1);
|
||||
String workDayStr = sdf.format(workDay);
|
||||
long workTime = getTime(today, workDayStr) + 1000; // 加1秒
|
||||
|
||||
return sdf.format(new Date(workTime));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取工作日
|
||||
*
|
||||
* @param holidayList 节假日(日期格式:2019-01-01,2019-01-04,2019-01-05,......)
|
||||
* @param num 需要设置的n个工作日
|
||||
* @param day 目标日期
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static Date getWorkDay(List<String> holidayList, int num, Date day, int n) throws Exception {
|
||||
int delay = 1;
|
||||
while (delay <= num) {
|
||||
// 获取前一天或后一天日期
|
||||
Date endDay = getDate(day, n);
|
||||
String time = sdf.format(endDay);
|
||||
|
||||
//当前日期+1即tomorrow,判断是否是节假日,同时要判断是否是周末,都不是则将scheduleActiveDate日期+1,直到循环num次即可
|
||||
if (!isWeekend(time) && !isHoliday(time, holidayList)) {
|
||||
delay++;
|
||||
}/* else if (isWeekend(time)) {
|
||||
System.out.println(time + "::是周末");
|
||||
} else if (isHoliday(time, holidayList)) {
|
||||
System.out.println(time + "::是节假日");
|
||||
}*/
|
||||
day = endDay;
|
||||
}
|
||||
return day;
|
||||
}
|
||||
|
||||
/**
|
||||
* yyyy-MM-dd HH:mm:ss格式日期---获取时间戳精确到秒
|
||||
*
|
||||
* @param start 开始日期(日期格式:2019-01-01 08:08:08)
|
||||
* @param end 结束日期(日期格式:2019-01-01 08:08:08)
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static long getTime(String start, String end) throws Exception {
|
||||
if (StrUtil.isBlank(start) || StrUtil.isBlank(end)) {
|
||||
throw new RuntimeException("today is empty");
|
||||
}
|
||||
|
||||
long time1 = sdf.parse(start).getTime();
|
||||
long time2 = sdf.parse(start).getTime();
|
||||
long time3 = sdf.parse(end).getTime();
|
||||
|
||||
long time = time3 + (time1 - time2);
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取前一天或后一天日期
|
||||
*
|
||||
* @param date 日期
|
||||
* @param n 判断参数
|
||||
* @return
|
||||
*/
|
||||
public static Date getDate(Date date, int n) {
|
||||
if (n > 0) { // 获取前一天
|
||||
date = getTomorrow(date);
|
||||
}
|
||||
if (n < 0) { // 获取后一天
|
||||
date = getYesterday(date);
|
||||
}
|
||||
return date;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取后一天的日期
|
||||
*
|
||||
* @param date
|
||||
* @return
|
||||
*/
|
||||
public static Date getTomorrow(Date date) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
calendar.add(Calendar.DAY_OF_MONTH, +1);
|
||||
date = calendar.getTime();
|
||||
return date;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取前一天的日期
|
||||
*
|
||||
* @param date
|
||||
* @return
|
||||
*/
|
||||
public static Date getYesterday(Date date) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
calendar.add(Calendar.DAY_OF_MONTH, -1);
|
||||
date = calendar.getTime();
|
||||
return date;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是周末
|
||||
*
|
||||
* @param sdate
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static boolean isWeekend(String sdate) throws Exception {
|
||||
Date date = sdf.parse(sdate);
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(date);
|
||||
if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是节假日
|
||||
*
|
||||
* @param sdate
|
||||
* @param list
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static boolean isHoliday(String sdate, List<String> list) throws Exception {
|
||||
if (list.size() > 0) {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (sdate.equals(list.get(i))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.linln.common.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 响应数据(结果)最外层对象
|
||||
* @author gion
|
||||
* @date 2018/10/15
|
||||
*/
|
||||
@Data
|
||||
@ApiModel("响应结果")
|
||||
public class ResultVo<T> {
|
||||
|
||||
/** 状态码 */
|
||||
@ApiModelProperty(notes = "状态码(200成功、400错误)")
|
||||
private Integer code;
|
||||
|
||||
/** 提示信息 */
|
||||
@ApiModelProperty(notes = "提示信息")
|
||||
private String msg;
|
||||
|
||||
/** 响应数据 */
|
||||
@ApiModelProperty(notes = "响应数据")
|
||||
private T data;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.linln.common.xss;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Xss防护过滤器
|
||||
* @author gion
|
||||
* @date 2018/12/9
|
||||
*/
|
||||
public class XssFilter implements Filter{
|
||||
|
||||
/**
|
||||
* 忽略规则列表
|
||||
*/
|
||||
private List<String> excludes = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
|
||||
String temp = filterConfig.getInitParameter("excludes");
|
||||
if (temp != null) {
|
||||
String[] url = temp.split(",");
|
||||
for (int i = 0; url != null && i < url.length; i++) {
|
||||
excludes.add(url[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException,ServletException {
|
||||
|
||||
HttpServletRequest req = (HttpServletRequest) request;
|
||||
HttpServletResponse resp = (HttpServletResponse) response;
|
||||
if(handleExcludeURL(req, resp)){
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
|
||||
filterChain.doFilter(xssRequest, response);
|
||||
}
|
||||
|
||||
private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) {
|
||||
|
||||
if (excludes == null || excludes.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String url = request.getServletPath();
|
||||
for (String pattern : excludes) {
|
||||
Pattern p = Pattern.compile("^" + pattern);
|
||||
Matcher m = p.matcher(url);
|
||||
if (m.find()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.linln.common.xss;
|
||||
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.safety.Whitelist;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
|
||||
/**
|
||||
* Xss防护过滤处理
|
||||
* @author gion
|
||||
* @date 2018/12/9
|
||||
*/
|
||||
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
|
||||
|
||||
public XssHttpServletRequestWrapper(HttpServletRequest request) {
|
||||
super(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getParameterValues(String name) {
|
||||
Whitelist whitelist = Whitelist.relaxed();
|
||||
|
||||
String[] params = super.getParameterValues(name);
|
||||
if(params != null){
|
||||
for (int i=0; i<params.length; i++) {
|
||||
params[i] = Jsoup.clean(params[i], whitelist).trim();
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
com.linln.common.config.CommonAutoConfig
|
||||
Reference in New Issue
Block a user