Initial commit

This commit is contained in:
易焱
2019-07-30 18:14:32 +08:00
commit daa60cf523
1624 changed files with 90832 additions and 0 deletions
+107
View File
@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="Spring" name="Spring">
<configuration />
</facet>
<facet type="web" name="Web">
<configuration>
<webroots />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:2.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:2.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.2.3" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.2.3" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-to-slf4j:2.11.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.11.2" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.26" level="project" />
<orderEntry type="library" name="Maven: javax.annotation:javax.annotation-api:1.3.2" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: org.yaml:snakeyaml:1.23" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-json:2.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.9.8" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.9.0" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.9.8" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.9.8" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.8" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.9.8" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:2.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:9.0.17" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:9.0.17" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:9.0.17" level="project" />
<orderEntry type="library" name="Maven: org.hibernate.validator:hibernate-validator:6.0.16.Final" level="project" />
<orderEntry type="library" name="Maven: javax.validation:validation-api:2.0.1.Final" level="project" />
<orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.3.2.Final" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml:classmate:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-web:5.1.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.1.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-webmvc:5.1.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.1.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.1.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.1.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-data-jpa:2.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-aop:2.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.aspectj:aspectjweaver:1.9.2" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:2.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.zaxxer:HikariCP:3.2.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jdbc:5.1.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: javax.transaction:javax.transaction-api:1.3" level="project" />
<orderEntry type="library" name="Maven: javax.xml.bind:jaxb-api:2.3.1" level="project" />
<orderEntry type="library" name="Maven: javax.activation:javax.activation-api:1.2.0" level="project" />
<orderEntry type="library" name="Maven: org.hibernate:hibernate-core:5.3.9.Final" level="project" />
<orderEntry type="library" name="Maven: javax.persistence:javax.persistence-api:2.2" level="project" />
<orderEntry type="library" name="Maven: org.javassist:javassist:3.23.1-GA" level="project" />
<orderEntry type="library" name="Maven: net.bytebuddy:byte-buddy:1.9.12" level="project" />
<orderEntry type="library" name="Maven: antlr:antlr:2.7.7" level="project" />
<orderEntry type="library" name="Maven: org.jboss:jandex:2.0.5.Final" level="project" />
<orderEntry type="library" name="Maven: org.dom4j:dom4j:2.1.1" level="project" />
<orderEntry type="library" name="Maven: org.hibernate.common:hibernate-commons-annotations:5.0.4.Final" level="project" />
<orderEntry type="library" name="Maven: org.springframework.data:spring-data-jpa:2.1.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.data:spring-data-commons:2.1.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-orm:5.1.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-tx:5.1.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-aspects:5.1.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-configuration-processor:2.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-cache:2.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context-support:5.1.6.RELEASE" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: org.springframework.boot:spring-boot-devtools:2.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:2.1.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.1.4.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-starter-test:2.1.4.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test:2.1.4.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test-autoconfigure:2.1.4.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.jayway.jsonpath:json-path:2.4.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.minidev:json-smart:2.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.minidev:accessors-smart:1.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.ow2.asm:asm:5.0.4" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.assertj:assertj-core:3.11.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-core:2.23.4" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy-agent:1.9.12" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:2.6" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-library:1.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.skyscreamer:jsonassert:1.5.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.vaadin.external.google:android-json:0.0.20131108.vaadin1" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.1.6.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.1.6.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework:spring-test:5.1.6.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.xmlunit:xmlunit-core:2.6.2" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: mysql:mysql-connector-java:5.1.46" level="project" />
<orderEntry type="library" name="Maven: org.projectlombok:lombok:1.18.2" level="project" />
<orderEntry type="library" name="Maven: net.sf.ehcache:ehcache:2.10.5" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.26" level="project" />
<orderEntry type="library" name="Maven: org.jsoup:jsoup:1.11.3" level="project" />
</component>
</module>
+16
View File
@@ -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.cwhelp</groupId>
<artifactId>cwhelp</artifactId>
<version>2.0.1</version>
</parent>
</project>
@@ -0,0 +1,33 @@
package com.cwhelp.common.config;
import com.cwhelp.common.config.properties.ProjectProperties;
import com.cwhelp.common.xss.XssFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* xss过滤拦截器
* @author yan.y
*/
@Configuration
public class XssFilterConfig {
private static final int FILTER_ORDER = 1;
@Bean
public FilterRegistrationBean xssFilterRegistrationBean(ProjectProperties properties) {
ProjectProperties.Xxs propertiesXxs = properties.getXxs();
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new XssFilter());
registration.setOrder(FILTER_ORDER);
registration.setEnabled(propertiesXxs.isEnabled());
registration.addUrlPatterns(propertiesXxs.getUrlPatterns().split(","));
Map<String, String> initParameters = new HashMap<>();
initParameters.put("excludes", propertiesXxs.getExcludes());
registration.setInitParameters(initParameters);
return registration;
}
}
@@ -0,0 +1,32 @@
package com.cwhelp.common.config.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 项目配置项
* @author yan.y
*/
@Data
@Component
@ConfigurationProperties(prefix = "project")
public class ProjectProperties {
// 是否开启验证码
private boolean captchaOpen = false;
// xss防护设置
private ProjectProperties.Xxs xxs = new ProjectProperties.Xxs();
/**
* xss防护设置
*/
@Data
public static class Xxs {
// xss防护开关
private boolean enabled = true;
// 拦截规则,可通过“,”隔开多个
private String urlPatterns = "/*";
// 忽略规则,可通过“,”隔开多个
private String excludes = "/favicon.ico,/img/*,/js/*,/css/*,/lib/*";
}
}
@@ -0,0 +1,29 @@
package com.cwhelp.common.constant;
/**
* 超级管理员常量
* @author yan.y
*/
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,16 @@
package com.cwhelp.common.constant;
/**
* 数据状态常量
* @author yan.y
*/
public class StatusConst {
// 正常状态码
public static final byte OK = 1;
// 冻结状态码
public static final byte FREEZED = 2;
// 删除状态码
public static final byte DELETE = 3;
}
@@ -0,0 +1,55 @@
package com.cwhelp.common.data;
import com.cwhelp.common.utils.HttpServletUtil;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
/**
* 分页排序数据
* @author yan.y
*/
public class PageSort {
private static final Integer pageSizeDef = 10;
private static final String orderByColumnDef = "createDate";
private static final Sort.Direction sortDirection = Sort.Direction.DESC;
/**
* 创建分页排序对象
*/
public static PageRequest pageRequest(){
return pageRequest(pageSizeDef, orderByColumnDef, sortDirection);
}
/**
* 创建分页排序对象
* @param sortDirection 排序方式默认值
*/
public static PageRequest pageRequest(Sort.Direction sortDirection){
return pageRequest(pageSizeDef, orderByColumnDef, sortDirection);
}
/**
* 创建分页排序对象
* @param orderByColumnDef 排序字段名称默认值
* @param sortDirection 排序方式默认值
*/
public static PageRequest pageRequest(String orderByColumnDef, Sort.Direction sortDirection){
return pageRequest(pageSizeDef, 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 = new Sort(Sort.Direction.fromString(direction), orderByColumn);
return PageRequest.of(pageIndex-1, pageSize, sort);
}
}
@@ -0,0 +1,234 @@
package com.cwhelp.common.data;
import com.cwhelp.common.enums.ResultEnum;
import com.cwhelp.common.enums.StatusEnum;
import com.cwhelp.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 yan.y
*/
public class QuerySpec {
// 查询规则
public static final Long EQUAL = 0L; //精确查询(=)
public static final Long LIKE = 1L; //模糊查询(*XX*)
public static final Long LEFT_LIKE = 2L; //左模糊查询(*XX)
public static final Long RIGHT_LIKE = 3L; //右模糊查询(XX*)
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; //小于等于(<=)
public static final Long IN = 9L; //多值(in)
public static final Long BETWEEN = 10L; //区间查询(between)
// 字段规则列表
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,28 @@
package com.cwhelp.common.data;
import com.cwhelp.common.utils.HttpServletUtil;
/**
* 封装URL地址,自动添加应用上下文路径
* @author yan.y
*/
public class URL {
private String url;
public URL(){ }
/**
* 封装URL地址,自动添加应用上下文路径
* @param url URL地址
*/
public URL(String url){
this.url = HttpServletUtil.getRequest().getContextPath() + url;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
@@ -0,0 +1,69 @@
package com.cwhelp.common.enums;
import com.cwhelp.common.exception.interfaces.ResultInterface;
import lombok.Getter;
/**
* 后台返回结果集枚举
* @author yan.y
*/
@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_PWD_STRENGTH_ERROR(407, "密码强度不够"),
/**
* 角色问题
*/
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, "不能修改管理员角色状态"),
;
private Integer code;
private String message;
ResultEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
}
@@ -0,0 +1,26 @@
package com.cwhelp.common.enums;
import com.cwhelp.common.constant.StatusConst;
import lombok.Getter;
/**
* 数据库字段状态枚举
* @author yan.y
*/
@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,44 @@
package com.cwhelp.common.exception;
import com.cwhelp.common.enums.ResultEnum;
import com.cwhelp.common.exception.interfaces.ResultInterface;
import lombok.Getter;
/**
* 自定义异常对象
* @author yan.y
*/
@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,48 @@
package com.cwhelp.common.exception;
import com.cwhelp.common.exception.advice.ResultExceptionAdvice;
import com.cwhelp.common.utils.ResultVoUtil;
import com.cwhelp.common.utils.SpringContextUtil;
import com.cwhelp.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 yan.y
*/
@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,9 @@
package com.cwhelp.common.exception.advice;
/**
* 异常通知器接口
* @author yan.y
*/
public interface ExceptionAdvice {
public void run(RuntimeException e);
}
@@ -0,0 +1,30 @@
package com.cwhelp.common.exception.advice;
import com.cwhelp.common.utils.SpringContextUtil;
import org.springframework.web.bind.annotation.ControllerAdvice;
import java.util.ArrayList;
import java.util.List;
/**
* 异常通知器
* @author yan.y
*/
@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,13 @@
package com.cwhelp.common.exception.interfaces;
/**
* 结果枚举接口
* @author yan.y
*/
public interface ResultInterface {
public Integer getCode();
public String getMessage();
}
@@ -0,0 +1,15 @@
package com.cwhelp.common.mysql;
import org.hibernate.dialect.MySQL5Dialect;
/**
* 重写数据库方言,设置默认字符集为utf8
* @author yan.y
*/
public class MySQLDialectUTF8 extends MySQL5Dialect {
@Override
public String getTableTypeString() {
return " ENGINE=InnoDB DEFAULT CHARSET=utf8";
}
}
@@ -0,0 +1,94 @@
package com.cwhelp.common.utils;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;
/**
* 验证码生成工具
* @author yan.y
*/
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 exChars = "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))&&(exChars==null||exChars.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,33 @@
package com.cwhelp.common.utils;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
/**
* EhCache缓存操作工具
* @author yan.y
*/
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");
}
}
@@ -0,0 +1,96 @@
package com.cwhelp.common.utils;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* 加密工具
* @author yan.y
*/
public class EncryptUtil {
// 加密算法
public final static String hashAlgorithmName = "SHA-256";
// 加密循环次数
public final static int hashIterations = 1024;
// 字符编码
private final static String charset = "UTF-8";
/**
* 加密处理
* @param password 密码
* @param salt 密码盐
*/
public static String encrypt(String password, String salt) {
return encrypt(password, salt, hashAlgorithmName, hashIterations);
}
/**
* 加密处理
* @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,155 @@
package com.cwhelp.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 yan.y
*/
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 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[] jointIgnoreProperties = new String[defaultFields.length + fields.length];
System.arraycopy(defaultFields, 0, jointIgnoreProperties, 0, defaultFields.length);
System.arraycopy(fields, 0, jointIgnoreProperties, defaultFields.length, fields.length);
EntityBeanUtil.copyProperties(source, target, null, jointIgnoreProperties);
}
/**
* 复制实体对象指定字段的数据
* {用于保留部分原始数据}
* {代码基于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);
}
}
}
}
}
}
}
@@ -0,0 +1,65 @@
package com.cwhelp.common.utils;
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 yan.y
*/
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)));
}
}
@@ -0,0 +1,82 @@
package com.cwhelp.common.utils;
import com.cwhelp.common.enums.ResultEnum;
import com.cwhelp.common.vo.ResultVo;
import com.cwhelp.common.data.URL;
/**
* 响应数据(结果)最外层对象工具
* @author yan.y
*/
public class ResultVoUtil {
public static ResultVo SAVE_SUCCESS = success("保存成功");
/**
* 操作成功
* @param msg 提示信息
* @param object 对象
*/
public static ResultVo success(String msg, Object object){
ResultVo resultVo = new ResultVo();
resultVo.setMsg(msg);
resultVo.setCode(ResultEnum.SUCCESS.getCode());
resultVo.setData(object);
return resultVo;
}
/**
* 操作成功,返回url地址
* @param msg 提示信息
* @param url URL包装对象
*/
public static ResultVo success(String msg, URL url){
return success(msg, url.getUrl());
}
/**
* 操作成功,使用默认的提示信息
* @param object 对象
*/
public static ResultVo success(Object object){
String message = ResultEnum.SUCCESS.getMessage();
return success(message,object);
}
/**
* 操作成功,返回提示信息,不返回数据
*/
public static ResultVo success(String msg){
Object object = null;
return success(msg,object);
}
/**
* 操作成功,不返回数据
*/
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);
}
}
@@ -0,0 +1,57 @@
package com.cwhelp.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 yan.y
*/
@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,31 @@
package com.cwhelp.common.utils;
import com.cwhelp.common.constant.StatusConst;
import com.cwhelp.common.enums.ResultEnum;
import com.cwhelp.common.enums.StatusEnum;
import com.cwhelp.common.exception.ResultException;
/**
* 数据状态工具
* @author yan.y
*/
public class StatusUtil {
// 逻辑删除语句
public static final String sliceDelete = " set status=" + StatusConst.DELETE + " WHERE id=?";
// 不等于逻辑删除条件语句
public static final String notDelete = "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,150 @@
package com.cwhelp.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 yan.y
*/
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,18 @@
package com.cwhelp.common.vo;
import lombok.Data;
/**
* 响应数据(结果)最外层对象
* @author yan.y
*/
@Data
public class ResultVo<T> {
// 状态码
private Integer code;
// 提示信息
private String msg;
// 响应数据
private T data;
}
@@ -0,0 +1,69 @@
package com.cwhelp.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 yan.y
*/
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,31 @@
package com.cwhelp.common.xss;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* Xss防护过滤处理
* @author yan.y
*/
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,41 @@
{
"groups": [
{
"name": "project",
"type": "com.cwhelp.common.config.properties.ProjectProperties",
"sourceType": "com.cwhelp.common.config.properties.ProjectProperties"
},
{
"name": "project.xxs",
"type": "com.cwhelp.common.config.properties.ProjectProperties$Xxs",
"sourceType": "com.cwhelp.common.config.properties.ProjectProperties"
}
],
"properties": [
{
"name": "project.captcha-open",
"type": "java.lang.Boolean",
"sourceType": "com.cwhelp.common.config.properties.ProjectProperties",
"defaultValue": false
},
{
"name": "project.xxs.enabled",
"type": "java.lang.Boolean",
"sourceType": "com.cwhelp.common.config.properties.ProjectProperties$Xxs",
"defaultValue": true
},
{
"name": "project.xxs.excludes",
"type": "java.lang.String",
"sourceType": "com.cwhelp.common.config.properties.ProjectProperties$Xxs",
"defaultValue": "\/favicon.ico,\/img\/*,\/js\/*,\/css\/*,\/lib\/*"
},
{
"name": "project.xxs.url-patterns",
"type": "java.lang.String",
"sourceType": "com.cwhelp.common.config.properties.ProjectProperties$Xxs",
"defaultValue": "\/*"
}
],
"hints": []
}