Initial commit
This commit is contained in:
@@ -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>
|
||||
@@ -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": []
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user