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
+134
View File
@@ -0,0 +1,134 @@
<?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="module" module-name="common" />
<orderEntry type="module" module-name="system" />
<orderEntry type="module" module-name="excel" />
<orderEntry type="library" name="Maven: org.apache.poi:poi-ooxml:4.0.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.poi:poi:4.0.0" level="project" />
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.11" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-collections4:4.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.poi:poi-ooxml-schemas:4.0.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.xmlbeans:xmlbeans:3.0.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-compress:1.18" level="project" />
<orderEntry type="library" name="Maven: com.github.virtuald:curvesapi:1.04" level="project" />
<orderEntry type="module" module-name="shiro" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-spring:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-lang:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-crypto-hash:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-crypto-core:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-crypto-cipher:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-config-core:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-config-ogdl:1.4.0" level="project" />
<orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.9.3" level="project" />
<orderEntry type="library" name="Maven: commons-collections:commons-collections:3.2.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-event:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-web:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-ehcache:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-cache:1.4.0" level="project" />
<orderEntry type="library" name="Maven: net.sf.ehcache:ehcache-core:2.6.11" level="project" />
<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>
+35
View File
@@ -0,0 +1,35 @@
<?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>
<groupId>com.cwhelp.component</groupId>
<artifactId>actionLog</artifactId>
<packaging>jar</packaging>
<name>组件:行为日志</name>
<parent>
<groupId>com.cwhelp</groupId>
<artifactId>component</artifactId>
<version>2.0.1</version>
</parent>
<dependencies>
<dependency>
<groupId>com.cwhelp</groupId>
<artifactId>common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.cwhelp.modules</groupId>
<artifactId>system</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.cwhelp.component</groupId>
<artifactId>shiro</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,45 @@
package com.cwhelp.component.actionLog.action;
import com.cwhelp.component.actionLog.action.base.ActionMap;
import com.cwhelp.component.actionLog.action.base.ResetLog;
import com.cwhelp.component.actionLog.action.model.BusinessMethod;
import com.cwhelp.modules.system.domain.Role;
import javax.persistence.Table;
/**
* 角色日志行为
* @author yan.y
*/
public class RoleAction extends ActionMap {
public static final String ROLE_SAVE = "role_save";
public static final String ROLE_AUTH = "role_auth";
@Override
public void init() {
// 保存日志行为
putMethod(ROLE_SAVE, new BusinessMethod("日志管理","roleSave"));
// 角色授权行为
putMethod(ROLE_AUTH, new BusinessMethod("角色授权","roleAuth"));
}
// 保存用户行为方法
public void roleSave(ResetLog resetLog){
resetLog.getActionLog().setMessage("日志成功:${title}");
SaveAction.defaultMethod(resetLog);
}
// 角色授权行为方法
public void roleAuth(ResetLog resetLog){
Role role = (Role) resetLog.getParam("role");
Table table = Role.class.getAnnotation(Table.class);
resetLog.getActionLog().setModel(table.name());
resetLog.getActionLog().setRecordId(role.getId());
if (resetLog.isSuccess()){
resetLog.getActionLog().setMessage("角色授权成功:"+role.getTitle());
}else {
resetLog.getActionLog().setMessage("角色授权失败:"+role.getTitle());
}
}
}
@@ -0,0 +1,60 @@
package com.cwhelp.component.actionLog.action;
import com.cwhelp.common.utils.EntityBeanUtil;
import com.cwhelp.common.utils.HttpServletUtil;
import com.cwhelp.component.actionLog.action.base.ActionMap;
import com.cwhelp.component.actionLog.action.base.ResetLog;
import com.cwhelp.modules.system.domain.ActionLog;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import javax.persistence.Table;
/**
* 通用:记录保存数据的行为
*
* @author yan.y
*/
@Slf4j
public class SaveAction extends ActionMap {
@Override
public void init() {
// 记录数据保存日志
putMethod("default", "defaultMethod");
}
/**
* 重新包装保存的数据行为方法
*
* @param resetLog ResetLog对象数据
*/
public static void defaultMethod(ResetLog resetLog) {
ActionLog actionLog = resetLog.getActionLog();
Object entity = resetLog.getEntityParam();
Assert.notNull(entity, "日志记录失败:未发现@EntityParam注解参数,将不做数据日志记录");
// 获取实体类的@Table表名
Table table = entity.getClass().getAnnotation(Table.class);
Assert.notNull(table, "该对象不存在" + Table.class.getName() + "注解!请检查!");
actionLog.setModel(table.name());
// 获取实体对象数据ID
Object[] idInfo = EntityBeanUtil.getId(entity);
Assert.notNull(idInfo, "无法获取该实体对象的主键ID字段!");
actionLog.setRecordId(Long.valueOf(String.valueOf(idInfo[1])));
// 日志消息
String idParam = HttpServletUtil.getParameter(String.valueOf(idInfo[0]));
String message = "数据成功";
if (!actionLog.getMessage().isEmpty()) {
message = resetLog.fillRule(entity, actionLog.getMessage());
}
if (idParam == null) {
actionLog.setMessage("添加" + message);
} else {
actionLog.setMessage("更新" + message);
}
}
}
@@ -0,0 +1,37 @@
package com.cwhelp.component.actionLog.action;
import com.cwhelp.common.utils.StatusUtil;
import com.cwhelp.component.actionLog.action.base.ActionMap;
import com.cwhelp.component.actionLog.action.base.ResetLog;
import com.cwhelp.common.enums.StatusEnum;
import java.util.List;
/**
* 通用:记录数据状态的行为
*
* @author yan.y
*/
public class StatusAction extends ActionMap {
@Override
public void init() {
// 记录数据状态改变日志
putMethod("default", "defaultMethod");
}
/**
* 重新包装保存的数据行为方法
*
* @param resetLog ResetLog对象数据
*/
@SuppressWarnings("unchecked")
public static void defaultMethod(ResetLog resetLog) {
if(resetLog.isSuccessRecord()){
String param = (String) resetLog.getParam("param");
StatusEnum statusEnum = StatusUtil.getStatusEnum(param);
List<Long> ids = (List<Long>) resetLog.getParam("ids");
resetLog.getActionLog().setMessage(statusEnum.getMessage() + "ID:" + ids.toString());
}
}
}
@@ -0,0 +1,34 @@
package com.cwhelp.component.actionLog.action;
import com.cwhelp.component.actionLog.action.base.ActionMap;
import com.cwhelp.component.actionLog.action.base.ResetLog;
import com.cwhelp.component.actionLog.action.model.SystemMethod;
import com.cwhelp.modules.system.domain.ActionLog;
/**
* @author yan.y
*/
public class SystemAction extends ActionMap {
public static final String RUNTIME_EXCEPTION = "runtime_exception";
@Override
public void init() {
// 系统异常行为
putMethod(RUNTIME_EXCEPTION, new SystemMethod("系统异常","runtimeException"));
}
// 系统异常行为方法
public void runtimeException(ResetLog resetLog){
RuntimeException runtime = (RuntimeException) resetLog.getParam("e");
StringBuilder message = new StringBuilder();
message.append(runtime.toString());
StackTraceElement[] stackTrace = runtime.getStackTrace();
for (StackTraceElement stack : stackTrace) {
message.append("\n\t").append(stack.toString());
}
ActionLog actionLog = resetLog.getActionLog();
actionLog.setOperName("系统");
actionLog.setMessage(String.valueOf(message));
}
}
@@ -0,0 +1,95 @@
package com.cwhelp.component.actionLog.action;
import com.cwhelp.common.vo.ResultVo;
import com.cwhelp.component.actionLog.action.base.ActionMap;
import com.cwhelp.component.actionLog.action.base.ResetLog;
import com.cwhelp.component.actionLog.action.model.BusinessMethod;
import com.cwhelp.component.actionLog.action.model.LoginMethod;
import com.cwhelp.modules.system.domain.ActionLog;
import com.cwhelp.modules.system.domain.User;
import com.cwhelp.modules.system.service.ActionLogService;
import com.cwhelp.common.utils.SpringContextUtil;
import org.springframework.beans.BeanUtils;
import javax.persistence.Table;
import java.util.List;
/**
* 用户日志行为
* @author yan.y
*/
public class UserAction extends ActionMap {
public static final String USER_LOGIN = "user_login";
public static final String USER_SAVE = "user_save";
public static final String EDIT_PWD = "edit_pwd";
public static final String EDIT_ROLE = "edit_role";
@Override
public void init() {
// 用户登录行为
putMethod(USER_LOGIN, new LoginMethod("用户登录","userLogin"));
// 保存用户行为
putMethod(USER_SAVE, new BusinessMethod("用户管理","userSave"));
// 修改用户密码行为
putMethod(EDIT_PWD, new BusinessMethod("用户密码","editPwd"));
// 角色分配行为
putMethod(EDIT_ROLE, new BusinessMethod("角色分配","editRole"));
}
// 用户登录行为方法
public void userLogin(ResetLog resetLog){
ActionLog actionLog = resetLog.getActionLog();
if (resetLog.isSuccess()){
actionLog.setMessage("后台登录成功");
}else {
String username = (String) resetLog.getParam("username");
ResultVo resultVo = (ResultVo) resetLog.getRetValue();
actionLog.setOperName(username);
actionLog.setMessage(String.format("后台登录失败:[%s]%s", username, resultVo.getMsg()));
}
}
// 保存用户行为方法
public void userSave(ResetLog resetLog){
resetLog.getActionLog().setMessage("用户成功:${username}");
SaveAction.defaultMethod(resetLog);
}
// 修改用户密码行为方法
public void editPwd(ResetLog resetLog){
List<User> users = (List<User>) resetLog.getParam("users");
Table table = User.class.getAnnotation(Table.class);
String message = "修改用户密码成功";
if(!resetLog.isSuccess()){
message = "修改用户密码失败";
}
ActionLogService actionLogService = SpringContextUtil.getBean(ActionLogService.class);
String finalMessage = message;
users.forEach(user -> {
ActionLog actionLog = new ActionLog();
BeanUtils.copyProperties(resetLog.getActionLog(), actionLog);
actionLog.setModel(table.name());
actionLog.setRecordId(user.getId());
actionLog.setMessage(finalMessage + user.getUsername());
// 保存日志
actionLogService.save(actionLog);
});
resetLog.setRecord(false);
}
// 角色分配行为方法
public void editRole(ResetLog resetLog){
User user = (User) resetLog.getParam("user");
Table table = User.class.getAnnotation(Table.class);
resetLog.getActionLog().setModel(table.name());
resetLog.getActionLog().setRecordId(user.getId());
if (resetLog.isSuccess()){
resetLog.getActionLog().setMessage("角色分配成功:"+user.getUsername());
}else {
resetLog.getActionLog().setMessage("角色分配失败:"+user.getUsername());
}
}
}
@@ -0,0 +1,89 @@
package com.cwhelp.component.actionLog.action.base;
import com.cwhelp.component.actionLog.action.model.BusinessMethod;
import com.cwhelp.component.actionLog.action.model.BusinessType;
import java.util.HashMap;
/**
* @author yan.y
*/
public abstract class ActionMap {
protected HashMap<String, Object> dictory = new HashMap<>();
public ActionMap(){
init();
}
/**
* 初始化行为列表
*/
public abstract void init();
/**
* 获取指定的行为
* @param key 行为key
*/
public Object get(String key) {
return this.dictory.get(key);
}
/**
* 添加行为
* @param key 行为key
* @param modelType 模型类型对象
*/
public void put(String key, Object modelType) {
this.dictory.put(key, modelType);
}
/**
* 添加行为-默认类型(业务)
* @param key 行为key
* @param message 日志消息
*/
public void put(String key, String message) {
this.dictory.put(key, new BusinessType(message));
}
/**
* 添加行为-默认类型(业务)
* @param key 行为key
* @param name 日志名称
* @param message 日志消息
*/
public void put(String key, String name, String message) {
this.dictory.put(key, new BusinessType(name, message));
}
/**
* 添加行为方法名
* @param key 行为key
* @param modelMethod 模型方法名对象
*/
public void putMethod(String key, Object modelMethod) {
this.dictory.put(key, modelMethod);
}
/**
* 添加行为方法名-默认类型(业务)
* @param key 行为key
* @param method 方法名
*/
public void putMethod(String key, String method) {
this.dictory.put(key, new BusinessMethod(method));
}
/**
* 添加行为方法名-默认类型(业务)
* @param key 行为key
* @param name 日志名称
* @param method 方法名
*/
public void putMethod(String key, String name, String method) {
this.dictory.put(key, new BusinessMethod(name, method));
}
}
@@ -0,0 +1,121 @@
package com.cwhelp.component.actionLog.action.base;
import com.cwhelp.common.enums.ResultEnum;
import com.cwhelp.common.utils.EntityBeanUtil;
import com.cwhelp.common.vo.ResultVo;
import com.cwhelp.component.actionLog.annotation.EntityParam;
import com.cwhelp.component.shiro.ShiroUtil;
import com.cwhelp.modules.system.domain.ActionLog;
import lombok.Data;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 自定义日志数据
* @author yan.y
*/
@Data
public class ResetLog {
/** 封装操作对象 */
// 注解日志的方法返回值
private Object retValue;
// 获取日志实体对象
private ActionLog actionLog;
// Aop连接点信息对象
private JoinPoint joinPoint;
// 是否记录日志(默认记录)
private Boolean record = true;
/** 辅助方法 */
// 判断返回值是否为ResultVo对象
public boolean isResultVo(){
return retValue instanceof ResultVo;
}
// 判断ResultVo状态码是否为成功
public boolean isSuccess(){
return retValue instanceof ResultVo &&
((ResultVo) retValue).getCode().equals(ResultEnum.SUCCESS.getCode());
}
// 判断ResultVo状态码是否为成功,且设置是否记录日志
public boolean isSuccessRecord(){
return record = retValue instanceof ResultVo &&
((ResultVo) retValue).getCode().equals(ResultEnum.SUCCESS.getCode());
}
// 获取切入点方法指定名称的参数值
public Object getParam(String name){
Object[] args = joinPoint.getArgs();
if(args.length > 0){
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = methodSignature.getParameterNames();
for (int i = 0; i < parameterNames.length; i++) {
if(parameterNames[i].equals(name)){
return args[i];
}
}
}
return null;
}
// 获取切入点参数注解@EntityParam的对象
public Object getEntityParam(){
Object[] args = joinPoint.getArgs();
if(args.length > 0){
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
for (int i = 0; i < parameterAnnotations.length; i++) {
for (int j = 0; j < parameterAnnotations[i].length; j++) {
if(parameterAnnotations[i][j] instanceof EntityParam){
return args[i];
}
}
}
}
return null;
}
// 内容填充规则
public String fillRule(Object beanObject, String content){
Pattern pattern = Pattern.compile("\\$\\{[a-zA-Z0-9]+\\}");
Matcher matcher = pattern.matcher(content);
while(matcher.find()){
String matchWord = matcher.group(0);
String property = matchWord.substring(2, matchWord.length()-1);
String fill = null;
try {
fill = String.valueOf(EntityBeanUtil.getField(beanObject, property));
} catch (InvocationTargetException | IllegalAccessException e) {
} finally {
content = content.replace(matchWord, fill);
}
}
return content;
}
/** 快捷数据 */
// 获取用户名
public String getUsername(){
return ShiroUtil.getSubject().getUsername();
}
// 获取用户昵称
public String getNickname(){
return ShiroUtil.getSubject().getNickname();
}
// 获取当前时间
public String getDatetime(){
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return df.format(new Date());
}
// 获取当前时间(自定义时间格式)
public String getDatetime(String pattern){
SimpleDateFormat df = new SimpleDateFormat(pattern);
return df.format(new Date());
}
}
@@ -0,0 +1,14 @@
package com.cwhelp.component.actionLog.action.model;
import lombok.Getter;
/**
* @author yan.y
*/
@Getter
public class ActionModel {
// 日志名称
protected String name;
// 日志类型
protected Byte type;
}
@@ -0,0 +1,35 @@
package com.cwhelp.component.actionLog.action.model;
import com.cwhelp.modules.system.enums.ActionLogEnum;
import lombok.Getter;
/**
* @author yan.y
*/
@Getter
public class BusinessMethod extends ActionModel{
// 日志名称
protected String name;
// 行为方法名
protected String method;
// 日志类型
protected Byte type = ActionLogEnum.BUSINESS.getCode();
/**
* 只构建行为方法名,日志名称由日志注解name定义
* @param method 行为方法名
*/
public BusinessMethod(String method) {
this.method = method;
}
/**
* 构建日志名称和行为方法名
* @param name 日志名称
* @param method 行为方法名
*/
public BusinessMethod(String name, String method) {
this.name = name;
this.method = method;
}
}
@@ -0,0 +1,35 @@
package com.cwhelp.component.actionLog.action.model;
import com.cwhelp.modules.system.enums.ActionLogEnum;
import lombok.Getter;
/**
* @author yan.y
*/
@Getter
public class BusinessType extends ActionModel{
// 日志名称
protected String name;
// 日志消息
protected String message;
// 日志类型
protected Byte type = ActionLogEnum.BUSINESS.getCode();
/**
* 只构建日志消息,日志名称有日志注解name定义
* @param message 日志消息
*/
public BusinessType(String message) {
this.message = message;
}
/**
* 构建日志名称和日志消息
* @param name 日志名称
* @param message 日志消息
*/
public BusinessType(String name, String message) {
this.name = name;
this.message = message;
}
}
@@ -0,0 +1,21 @@
package com.cwhelp.component.actionLog.action.model;
import com.cwhelp.modules.system.enums.ActionLogEnum;
import lombok.Getter;
/**
* @author yan.y
*/
@Getter
public class LoginMethod extends BusinessMethod{
// 日志类型
protected Byte type = ActionLogEnum.LOGIN.getCode();
public LoginMethod(String method) {
super(method);
}
public LoginMethod(String name, String method) {
super(name, method);
}
}
@@ -0,0 +1,21 @@
package com.cwhelp.component.actionLog.action.model;
import com.cwhelp.modules.system.enums.ActionLogEnum;
import lombok.Getter;
/**
* @author yan.y
*/
@Getter
public class LoginType extends BusinessType{
// 日志类型
protected Byte type = ActionLogEnum.LOGIN.getCode();
public LoginType(String message) {
super(message);
}
public LoginType(String name, String message) {
super(name, message);
}
}
@@ -0,0 +1,21 @@
package com.cwhelp.component.actionLog.action.model;
import com.cwhelp.modules.system.enums.ActionLogEnum;
import lombok.Getter;
/**
* @author yan.y
*/
@Getter
public class SystemMethod extends BusinessMethod{
// 日志类型
protected Byte type = ActionLogEnum.SYSTEM.getCode();
public SystemMethod(String method) {
super(method);
}
public SystemMethod(String name, String method) {
super(name, method);
}
}
@@ -0,0 +1,21 @@
package com.cwhelp.component.actionLog.action.model;
import com.cwhelp.modules.system.enums.ActionLogEnum;
import lombok.Getter;
/**
* @author yan.y
*/
@Getter
public class SystemType extends BusinessType{
// 日志类型
protected Byte type = ActionLogEnum.SYSTEM.getCode();
public SystemType(String message) {
super(message);
}
public SystemType(String name, String message) {
super(name, message);
}
}
@@ -0,0 +1,25 @@
package com.cwhelp.component.actionLog.annotation;
import com.cwhelp.component.actionLog.action.base.ActionMap;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 行为日志注解
* @author yan.y
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface ActionLog {
// 日志名称
String name() default "";
// 日志消息
String message() default "";
// 行为key
String key() default "";
// 行为类
Class<? extends ActionMap> action() default ActionMap.class;
}
@@ -0,0 +1,98 @@
package com.cwhelp.component.actionLog.annotation;
import com.cwhelp.common.utils.SpringContextUtil;
import com.cwhelp.component.actionLog.action.base.ActionMap;
import com.cwhelp.component.actionLog.action.base.ResetLog;
import com.cwhelp.component.actionLog.action.model.ActionModel;
import com.cwhelp.component.actionLog.action.model.BusinessMethod;
import com.cwhelp.component.actionLog.action.model.BusinessType;
import com.cwhelp.component.shiro.ShiroUtil;
import com.cwhelp.modules.system.domain.ActionLog;
import com.cwhelp.modules.system.service.ActionLogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.lang.reflect.Method;
/**
* 行为日志注解AOP
* @author yan.y
*/
@Aspect
@Component
@Slf4j
public class ActionLogAop {
private final static String defaultActionName = "default";
@Pointcut("@annotation(com.cwhelp.component.actionLog.annotation.ActionLog)")
public void actionLog() {};
@Around("actionLog()")
public Object recordLog(ProceedingJoinPoint point) throws Throwable {
// 先执行切入点,获取返回值
Object proceed = point.proceed();
/* 读取ActionLog注解消息 */
Method targetMethod = ((MethodSignature)(point.getSignature())).getMethod();
com.cwhelp.component.actionLog.annotation.ActionLog anno =
targetMethod.getAnnotation(com.cwhelp.component.actionLog.annotation.ActionLog.class);
// 获取name值
String name = anno.name();
// 获取message值
String message = anno.message();
// 获取key值
String key = anno.key();
// 获取行为模型
Class<? extends ActionMap> action = anno.action();
ActionMap instance = action.newInstance();
Object actionModel = instance.get(!key.isEmpty() ? key : defaultActionName);
Assert.notNull(actionModel, "无法获取日志的行为方法,请检查:"+point.getSignature());
// 封装日志实例对象
ActionLog actionLog = new ActionLog();
actionLog.setIpaddr(ShiroUtil.getIp());
actionLog.setClazz(point.getTarget().getClass().getName());
actionLog.setMethod(targetMethod.getName());
actionLog.setType(((ActionModel) actionModel).getType());
actionLog.setName(!name.isEmpty() ? name : ((ActionModel) actionModel).getName());
actionLog.setMessage(message);
actionLog.setOperBy(ShiroUtil.getSubject());
if(ShiroUtil.getSubject() != null){
actionLog.setOperName(ShiroUtil.getSubject().getNickname());
}
//判断是否为普通实例对象
if(actionModel instanceof BusinessType){
actionLog.setMessage(((BusinessType) actionModel).getMessage());
}else {
// 重置日志-自定义日志数据
ResetLog resetLog = new ResetLog();
resetLog.setActionLog(actionLog);
resetLog.setRetValue(proceed);
resetLog.setJoinPoint(point);
try {
Method method = action.getDeclaredMethod(((BusinessMethod)actionModel).getMethod(), ResetLog.class);
method.invoke(instance, resetLog);
if(!resetLog.getRecord()) return proceed;
} catch (NoSuchMethodException e) {
log.error("获取行为对象方法错误!请检查方法名称是否正确!", e);
e.printStackTrace();
}
}
// 保存日志
ActionLogService actionLogService = SpringContextUtil.getBean(ActionLogService.class);
actionLogService.save(actionLog);
return proceed;
}
}
@@ -0,0 +1,13 @@
package com.cwhelp.component.actionLog.annotation;
import java.lang.annotation.*;
/**
* 控制器实体参数注解
* @author yan.y
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Documented
public @interface EntityParam {
}
@@ -0,0 +1,16 @@
package com.cwhelp.component.actionLog.exception;
import com.cwhelp.common.exception.advice.ExceptionAdvice;
import com.cwhelp.component.actionLog.action.SystemAction;
import com.cwhelp.component.actionLog.annotation.ActionLog;
/**
* 运行时抛出的异常进行日志记录
* @author yan.y
*/
public class ActionLogProceedAdvice implements ExceptionAdvice {
@Override
@ActionLog(key = SystemAction.RUNTIME_EXCEPTION, action = SystemAction.class)
public void run(RuntimeException e) {}
}
@@ -0,0 +1,20 @@
package com.cwhelp.component.actionLog.exception;
import com.cwhelp.common.exception.advice.ResultExceptionAdvice;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 将异常切入程序添加到异常通知器中
* @author yan.y
*/
@Configuration
public class ActionLogProceedAdviceConfig {
@Bean
public ActionLogProceedAdvice actionLogProceedAdvice(ResultExceptionAdvice advice) {
ActionLogProceedAdvice authorization = new ActionLogProceedAdvice();
advice.putProceed(authorization);
return authorization;
}
}
+96
View File
@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<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$">
<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>
+116
View File
@@ -0,0 +1,116 @@
<?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="module" module-name="common" />
<orderEntry type="library" name="Maven: org.apache.poi:poi-ooxml:4.0.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.poi:poi:4.0.0" level="project" />
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.11" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-collections4:4.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.poi:poi-ooxml-schemas:4.0.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.xmlbeans:xmlbeans:3.0.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-compress:1.18" level="project" />
<orderEntry type="library" name="Maven: com.github.virtuald:curvesapi:1.04" level="project" />
<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>
+33
View File
@@ -0,0 +1,33 @@
<?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>
<groupId>com.cwhelp.component</groupId>
<artifactId>excel</artifactId>
<packaging>jar</packaging>
<name>组件:Excel</name>
<parent>
<groupId>com.cwhelp</groupId>
<artifactId>component</artifactId>
<version>2.0.1</version>
</parent>
<dependencies>
<dependency>
<groupId>com.cwhelp</groupId>
<artifactId>common</artifactId>
<version>${project.version}</version>
</dependency>
<!-- excel工具框架 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,401 @@
package com.cwhelp.component.excel;
import com.cwhelp.component.excel.enums.ExcelType;
import com.cwhelp.component.excel.annotation.Excel;
import com.cwhelp.common.utils.EhCacheUtil;
import com.cwhelp.common.utils.HttpServletUtil;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.beans.BeanUtils;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletResponse;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* @author yan.y
*/
public class ExcelUtil {
private static int dataRow = 2;
private static Cache dictCache = EhCacheUtil.getDictCache();
/**
* 获取通用样式
*/
private static XSSFCellStyle getCellStyle(XSSFWorkbook workbook) {
XSSFCellStyle cellStyle = workbook.createCellStyle();
cellStyle.setBorderTop(BorderStyle.THIN);
cellStyle.setBorderLeft(BorderStyle.THIN);
cellStyle.setBorderRight(BorderStyle.THIN);
cellStyle.setBorderBottom(BorderStyle.THIN);
cellStyle.setAlignment(HorizontalAlignment.LEFT);
XSSFFont font = workbook.createFont();
font.setFontName("Microsoft YaHei UI");
cellStyle.setFont(font);
return cellStyle;
}
/**
* 功能模板(标题及表头)
*/
private static XSSFWorkbook getCommon(String sheetTitle, List<Field> fields) {
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet(sheetTitle);
// 设置列宽度
for (int i = 0; i < fields.size(); i++) {
sheet.setColumnWidth(i, 16 * 256);
}
// 通用样式
XSSFCellStyle cellStyle = getCellStyle(workbook);
// 标题样式
XSSFCellStyle titleStyle = workbook.createCellStyle();
titleStyle.cloneStyleFrom(cellStyle);
titleStyle.setAlignment(HorizontalAlignment.CENTER);
titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
XSSFFont titleFont = workbook.createFont();
titleFont.setFontName(cellStyle.getFont().getFontName());
titleFont.setBold(true);
titleFont.setFontHeight(14);
titleStyle.setFont(titleFont);
// 表头样式
XSSFCellStyle thStyle = workbook.createCellStyle();
thStyle.cloneStyleFrom(titleStyle);
thStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
thStyle .setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex());
XSSFFont thFont = workbook.createFont();
thFont.setFontName(cellStyle.getFont().getFontName());
thFont.setBold(titleFont.getBold());
thFont.setColor(IndexedColors.WHITE.getIndex());
thStyle.setFont(thFont);
// 创建标题样式、表格表头
XSSFRow titleRow = sheet.createRow(0);
XSSFRow thsRow = sheet.createRow(1);
for (int i = 0; i < fields.size(); i++) {
Excel excel = fields.get(i).getAnnotation(Excel.class);
XSSFCell title = titleRow.createCell(i);
title.setCellStyle(titleStyle);
XSSFCell th = thsRow.createCell(i);
th.setCellValue(excel.value());
th.setCellStyle(thStyle);
}
// 绘制标题
titleRow.setHeight((short) (26 * 20));
XSSFCell titleCell = titleRow.createCell(0);
titleCell.setCellValue(sheetTitle);
titleCell.setCellStyle(titleStyle);
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, fields.size() - 1));
return workbook;
}
/**
* 获取实体类带有@Excel的属性
*/
private static List<Field> getExcelList(Class<?> entity, ExcelType type) {
List<Field> list = new ArrayList<>();
Field[] fields = entity.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Excel.class)) {
ExcelType fieldType = field.getAnnotation(Excel.class).type();
if(fieldType.equals(ExcelType.ALL) || fieldType.equals(type)){
list.add(field);
}
}
}
return list;
}
/**
* 获取实体类带有@Excel字段名
*/
private static List<String> getFieldName(List<Field> fields) {
List<String> list = new ArrayList<>();
for (Field field : fields) {
list.add(field.getName());
}
return list;
}
/**
* 下载操作
*/
private static void download(XSSFWorkbook workbook, String fileName) {
try {
fileName = URLEncoder.encode(fileName + ".xlsx", "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
HttpServletResponse response = HttpServletUtil.getResponse();
response.setCharacterEncoding("utf-8");
response.setContentType("multipart/form-data");
response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
OutputStream ros = null;
try {
ros = response.getOutputStream();
workbook.write(ros);
ros.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(ros != null){
try {
ros.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(workbook != null){
try {
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 获取Excel模板
* @param entity 实体类Class
*/
public static void genTemplate(Class<?> entity) {
Excel excel = entity.getAnnotation(Excel.class);
if (excel != null) {
genTemplate(entity, excel.value());
} else {
genTemplate(entity, entity.getSimpleName());
}
}
/**
* 获取Excel模板
* @param entity 实体类Class
* @param sheetTitle 工作组标题(文件名称)
*/
public static void genTemplate(Class<?> entity, String sheetTitle) {
XSSFWorkbook workbook = getCommon(sheetTitle, getExcelList(entity, ExcelType.IMPORT));
download(workbook, sheetTitle + "模板");
}
/**
* 导出Excel数据
* @param entity 实体类Class
* @param list 导出的数据列表
*/
public static <T> void exportExcel(Class<?> entity, List<T> list) {
Excel excel = entity.getAnnotation(Excel.class);
if (excel != null) {
exportExcel(entity, list, excel.value());
} else {
exportExcel(entity, list, entity.getSimpleName());
}
}
/**
* 导出Excel数据
* @param entity 实体类Class
* @param list 导出的数据列表
* @param sheetTitle 工作组标题(文件名称)
*/
public static <T> void exportExcel(Class<?> entity, List<T> list, String sheetTitle) {
List<Field> fields = getExcelList(entity, ExcelType.EXPORT);
List<String> fns = getFieldName(fields);
XSSFWorkbook workbook = getCommon(sheetTitle, fields);
XSSFSheet sheet = workbook.getSheet(sheetTitle);
XSSFCellStyle cellStyle = getCellStyle(workbook);
// 时间样式
XSSFCellStyle dateStyle = workbook.createCellStyle();
dateStyle.cloneStyleFrom(cellStyle);
XSSFDataFormat format = workbook.createDataFormat();
dateStyle.setDataFormat(format.getFormat("yyyy-MM-dd HH:mm:ss"));
for (int i = 0; i < list.size(); i++) {
XSSFRow row = sheet.createRow(i + dataRow);
T item = list.get(i);
// 通过反射机制获取实体对象的状态
try {
final BeanInfo bi = Introspector.getBeanInfo(item.getClass());
for (final PropertyDescriptor pd : bi.getPropertyDescriptors()) {
if (fns.contains(pd.getName())) {
Object value = pd.getReadMethod().invoke(item, (Object[]) null);
int index = fns.indexOf(pd.getName());
XSSFCell cell = row.createCell(index);
if (value != null) {
Excel excel = fields.get(index).getAnnotation(Excel.class);
// 字典值转换
String dict = excel.dict();
if (!dict.isEmpty()){
Element dictEle = dictCache.get(dict);
if(dictEle != null){
Map<String, String> dictValue = (Map<String, String>) dictEle.getObjectValue();
value = dictValue.get(String.valueOf(value));
}
}
// 获取关联对象指定的值
String joinField = excel.joinField();
if (!joinField.isEmpty()){
PropertyDescriptor sourcePd = BeanUtils.getPropertyDescriptor(value.getClass(), joinField);
value = sourcePd.getReadMethod().invoke(value, (Object[]) null);
}
// 给单元格赋值
if (value instanceof Number) {
cell.setCellValue((Double.valueOf(String.valueOf(value))));
} else if (value instanceof Date) {
cell.setCellValue((Date) value);
cell.setCellStyle(dateStyle);
continue;
} else {
cell.setCellValue(String.valueOf(value));
}
}
cell.setCellStyle(cellStyle);
}
}
} catch (InvocationTargetException | IntrospectionException | IllegalAccessException e) {
String message = "导入失败:字段名称匹配失败!";
throw new IllegalArgumentException(message, e);
}
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
download(workbook, sheetTitle + dateFormat.format(new Date()));
}
/**
* 读取Excel文件数据
* @param entity 实体类
* @param inputStream Excel文件输入流
* @return 返回数据集合
*/
public static <T> List<T> importExcel(Class<T> entity, InputStream inputStream){
List<T> list = new ArrayList<>();
List<String> fns = getFieldName(getExcelList(entity, ExcelType.IMPORT));
// 读取Excel文件
XSSFWorkbook workbook = null;
try {
ZipSecureFile.setMinInflateRatio(-1.0d);
workbook = new XSSFWorkbook(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
Assert.notNull(workbook, "该取Excel文件失败,请检查文件!");
XSSFSheet sheet = workbook.getSheetAt(0);
Assert.notNull(sheet, "该Excel文件没有工作区,无法读取数据!");
int count = 0;
for (Row row : sheet) {
// 通过非数据行
if(count < dataRow ) {
count++;
continue;
}
// 读取当前行数据
int end = row.getLastCellNum();
String[] rowData = new String[end];
for (int i = 0; i < end; i++) {
Cell cell = row.getCell(i);
if(cell != null){
if(cell.getCellType() == CellType.NUMERIC && HSSFDateUtil.isCellDateFormatted(cell)){
Date date = cell.getDateCellValue();
rowData[i] = String.valueOf(date.getTime());
}else {
// 强制其他类型为STRING字符串类型
cell.setCellType(CellType.STRING);
rowData[i] = cell.getStringCellValue();
}
}else {
rowData[i] = null;
}
}
// 将数据添加到数据列表中
try {
T newInstance = entity.newInstance();
final BeanInfo bi = Introspector.getBeanInfo(entity);
for (final PropertyDescriptor pd : bi.getPropertyDescriptors()) {
if (fns.contains(pd.getName())) {
Method writeMethod = pd.getWriteMethod();
if(writeMethod != null){
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
writeMethod.setAccessible(true);
}
String value = rowData[fns.indexOf(pd.getName())];
if(!StringUtils.isEmpty(value)){
Class<?> propertyType = pd.getPropertyType();
if (String.class == propertyType){
writeMethod.invoke(newInstance, value);
}else if(Integer.class == propertyType){
writeMethod.invoke(newInstance, Integer.valueOf(value));
}else if(Long.class == propertyType){
writeMethod.invoke(newInstance, Double.valueOf(value).longValue());
}else if(Float.class == propertyType){
writeMethod.invoke(newInstance, Float.valueOf(value));
}else if(Short.class == propertyType){
writeMethod.invoke(newInstance, Short.valueOf(value));
}else if(Double.class == propertyType){
writeMethod.invoke(newInstance, Double.valueOf(value));
}else if(Character.class == propertyType){
if ((value != null) && (value.length() > 0)){
writeMethod.invoke(newInstance, Character.valueOf(value.charAt(0)));
}
}else if(Date.class == propertyType){
writeMethod.invoke(newInstance, new Date(Long.parseLong(value)));
}else if(BigDecimal.class == propertyType){
writeMethod.invoke(newInstance, new BigDecimal(value));
}
}
}
}
}
list.add(newInstance);
} catch (InvocationTargetException | IntrospectionException | IllegalAccessException e) {
String message = "导入失败:字段名称匹配失败!";
throw new IllegalArgumentException(message, e);
} catch (InstantiationException e) {
e.printStackTrace();
}
}
return list;
}
}
@@ -0,0 +1,24 @@
package com.cwhelp.component.excel.annotation;
import com.cwhelp.component.excel.enums.ExcelType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author yan.y
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface Excel {
// 字段标题名称或文件名称
public String value();
// excel操作类型ExcelType
public ExcelType type() default ExcelType.ALL;
// 字段字典标识,用于导入导出时进行字典转换(只支持导出操作)
public String dict() default "";
// 关联操作实体对象字段名称,用于获取关联数据(只支持导出操作)
public String joinField() default "";
}
@@ -0,0 +1,10 @@
package com.cwhelp.component.excel.enums;
/**
* Excel操作类型
* @author yan.y
*/
public enum ExcelType {
// ALL表示全部操作,IMPORT只导入操作,EXPORT只导出操作
ALL, IMPORT, EXPORT;
}
+118
View File
@@ -0,0 +1,118 @@
<?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="module" module-name="common" />
<orderEntry type="module" module-name="system" />
<orderEntry type="module" module-name="excel" />
<orderEntry type="library" name="Maven: org.apache.poi:poi-ooxml:4.0.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.poi:poi:4.0.0" level="project" />
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.11" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-collections4:4.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.poi:poi-ooxml-schemas:4.0.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.xmlbeans:xmlbeans:3.0.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-compress:1.18" level="project" />
<orderEntry type="library" name="Maven: com.github.virtuald:curvesapi:1.04" level="project" />
<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>
+32
View File
@@ -0,0 +1,32 @@
<?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>
<groupId>com.cwhelp.component</groupId>
<artifactId>fileUpload</artifactId>
<packaging>jar</packaging>
<name>组件:文件上传</name>
<parent>
<groupId>com.cwhelp</groupId>
<artifactId>component</artifactId>
<version>2.0.1</version>
</parent>
<dependencies>
<dependency>
<groupId>com.cwhelp</groupId>
<artifactId>common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.cwhelp.modules</groupId>
<artifactId>system</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,154 @@
package com.cwhelp.component.fileUpload;
import com.cwhelp.common.exception.ResultException;
import com.cwhelp.common.utils.SpringContextUtil;
import com.cwhelp.common.utils.ToolUtil;
import com.cwhelp.component.fileUpload.config.properties.UploadProjectProperties;
import com.cwhelp.component.fileUpload.enums.UploadResultEnum;
import com.cwhelp.modules.system.domain.Upload;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.nio.file.Files;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;
/**
* 文件上传处理工具
* @author yan.y
*/
public class FileUpload {
/**
* 创建一个Upload实体对象
* @param multipartFile MultipartFile对象
* @param modulePath 文件模块路径
*/
public static Upload getFile(MultipartFile multipartFile, String modulePath){
if (multipartFile.getSize() == 0){
throw new ResultException(UploadResultEnum.NO_FILE_NULL);
}
Upload upload = new Upload();
upload.setMime(multipartFile.getContentType());
upload.setSize(multipartFile.getSize());
upload.setName(FileUpload.genFileName(multipartFile.getOriginalFilename()));
upload.setPath(getPathPattern() + modulePath + FileUpload.genDateMkdir("yyyyMMdd") + upload.getName());
return upload;
}
/**
* 判断文件是否为支持的格式
* @param multipartFile MultipartFile对象
* @param types 支持的文件类型数组
*/
public static boolean isContentType(MultipartFile multipartFile, String[] types){
List<String> typeList = Arrays.asList(types);
return typeList.contains(multipartFile.getContentType());
}
/**
* 获取文件上传保存路径
*/
public static String getUploadPath(){
UploadProjectProperties properties = SpringContextUtil.getBean(UploadProjectProperties.class);
return properties.getFilePath();
}
/**
* 获取文件上传目录的静态资源路径
*/
public static String getPathPattern(){
UploadProjectProperties properties = SpringContextUtil.getBean(UploadProjectProperties.class);
return properties.getStaticPath().replace("/**", "");
}
/**
* 生成随机且唯一的文件名
*/
public static String genFileName(String originalFilename){
String fileSuffix = ToolUtil.getFileSuffix(originalFilename);
return UUID.randomUUID().toString().replace("-", "") + fileSuffix;
}
/**
* 生成指定格式的目录名称(日期格式)
*/
public static String genDateMkdir(String format){
SimpleDateFormat sdf = new SimpleDateFormat(format);
return "/" + sdf.format(new Date()) + "/";
}
/**
* 获取目标文件对象
* @param upload 上传实体类
*/
public static File getDestFile(Upload upload) throws IOException {
// 创建保存文件对象
String path = upload.getPath().replace(getPathPattern(), "");
String filePath = getUploadPath() + path;
File dest = new File(filePath.replace("//", "/"));
if(!dest.exists()){
dest.getParentFile().mkdirs();
dest.createNewFile();
}
return dest;
}
/**
* 保存文件及获取文件MD5值和SHA1值
* @param multipartFile MultipartFile对象
* @param upload Upload
*/
public static void transferTo(MultipartFile multipartFile, Upload upload) throws IOException, NoSuchAlgorithmException {
byte[] buffer = new byte[4096];
MessageDigest md5 = MessageDigest.getInstance("MD5");
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
try (OutputStream fos = Files.newOutputStream(getDestFile(upload).toPath()); InputStream fis = multipartFile.getInputStream()) {
int len = 0;
while ((len = fis.read(buffer)) != -1) {
fos.write(buffer, 0, len);
md5.update(buffer, 0, len);
sha1.update(buffer, 0, len);
}
fos.flush();
}
BigInteger MD5Bi = new BigInteger(1, md5.digest());
BigInteger SHA1Bi = new BigInteger(1, sha1.digest());
upload.setMd5(MD5Bi.toString(16));
upload.setSha1(SHA1Bi.toString(16));
}
/**
* 获取文件的SHA1值
*/
public static String getFileSHA1(MultipartFile multipartFile) {
if (multipartFile.getSize() == 0){
throw new ResultException(UploadResultEnum.NO_FILE_NULL);
}
byte[] buffer = new byte[4096];
try (InputStream fis = multipartFile.getInputStream()) {
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
int len = 0;
while ((len = fis.read(buffer)) != -1) {
sha1.update(buffer, 0, len);
}
BigInteger SHA1Bi = new BigInteger(1, sha1.digest());
return SHA1Bi.toString(16);
} catch (IOException | NoSuchAlgorithmException e) {
return null;
}
}
}
@@ -0,0 +1,21 @@
package com.cwhelp.component.fileUpload.config;
import com.cwhelp.common.utils.SpringContextUtil;
import com.cwhelp.component.fileUpload.FileUpload;
import com.cwhelp.component.fileUpload.config.properties.UploadProjectProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author yan.y
*/
@Configuration
public class UploadFileConfigurer implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
UploadProjectProperties properties = SpringContextUtil.getBean(UploadProjectProperties.class);
registry.addResourceHandler(properties.getStaticPath()).addResourceLocations("file:" + FileUpload.getUploadPath());
}
}
@@ -0,0 +1,27 @@
package com.cwhelp.component.fileUpload.config.properties;
import com.cwhelp.common.utils.ToolUtil;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 项目-文件上传配置项
* @author yan.y
*/
@Data
@Component
@ConfigurationProperties(prefix = "project.upload")
public class UploadProjectProperties {
// 上传文件路径
private String filePath;
// 上传文件静态访问路径
private String staticPath = "/upload/**";
public String getFilePath() {
if(filePath == null){
return ToolUtil.getProjectPath() + "/upload/";
}
return filePath;
}
}
@@ -0,0 +1,29 @@
package com.cwhelp.component.fileUpload.enums;
import com.cwhelp.common.exception.interfaces.ResultInterface;
import lombok.Getter;
/**
* 后台返回结果集枚举
* @author yan.y
*/
@Getter
public enum UploadResultEnum implements ResultInterface {
/**
* 文件操作
*/
NO_FILE_NULL(401, "文件不能为空"),
NO_FILE_TYPE(402, "不支持该文件类型"),
;
private Integer code;
private String message;
UploadResultEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
}
@@ -0,0 +1,23 @@
{
"groups": [
{
"name": "project.upload",
"type": "com.cwhelp.component.fileUpload.config.properties.UploadProjectProperties",
"sourceType": "com.cwhelp.component.fileUpload.config.properties.UploadProjectProperties"
}
],
"properties": [
{
"name": "project.upload.file-path",
"type": "java.lang.String",
"sourceType": "com.cwhelp.component.fileUpload.config.properties.UploadProjectProperties"
},
{
"name": "project.upload.static-path",
"type": "java.lang.String",
"sourceType": "com.cwhelp.component.fileUpload.config.properties.UploadProjectProperties",
"defaultValue": "\/upload\/**"
}
],
"hints": []
}
+119
View File
@@ -0,0 +1,119 @@
<?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="module" module-name="common" />
<orderEntry type="module" module-name="system" />
<orderEntry type="module" module-name="excel" />
<orderEntry type="library" name="Maven: org.apache.poi:poi-ooxml:4.0.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.poi:poi:4.0.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-collections4:4.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.poi:poi-ooxml-schemas:4.0.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.xmlbeans:xmlbeans:3.0.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-compress:1.18" level="project" />
<orderEntry type="library" name="Maven: com.github.virtuald:curvesapi:1.04" level="project" />
<orderEntry type="library" name="Maven: com.auth0:java-jwt:3.4.0" 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: commons-codec:commons-codec:1.11" level="project" />
<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.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>
+36
View File
@@ -0,0 +1,36 @@
<?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>
<groupId>com.cwhelp.component</groupId>
<artifactId>jwt</artifactId>
<packaging>jar</packaging>
<name>组件:jwt</name>
<parent>
<groupId>com.cwhelp</groupId>
<artifactId>component</artifactId>
<version>2.0.1</version>
</parent>
<dependencies>
<dependency>
<groupId>com.cwhelp</groupId>
<artifactId>common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.cwhelp.modules</groupId>
<artifactId>system</artifactId>
<version>${project.version}</version>
</dependency>
<!-- jwt处理框架-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>${jwt.version}</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,15 @@
package com.cwhelp.component.jwt.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 忽略jwt权限验证注解(只在拦截的地址内有效)
* @author yan.y
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface IgnorePermissions {
}
@@ -0,0 +1,15 @@
package com.cwhelp.component.jwt.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* jwt权限注解(需要权限)
* @author yan.y
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface JwtPermissions {
}
@@ -0,0 +1,54 @@
package com.cwhelp.component.jwt.annotation;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.cwhelp.common.exception.ResultException;
import com.cwhelp.component.jwt.config.properties.JwtProjectProperties;
import com.cwhelp.component.jwt.enums.JwtResultEnums;
import com.cwhelp.component.jwt.utlis.JwtUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/**
* Jwt权限注解AOP
* @author yan.y
*/
@Aspect
@Component
@ConditionalOnProperty(name = "project.jwt.pattern-anno", havingValue = "true", matchIfMissing = true)
public class JwtPermissionsAop {
@Autowired
private JwtProjectProperties jwtProperties;
@Autowired
private HttpServletRequest request;
@Pointcut("@annotation(com.cwhelp.component.jwt.annotation.JwtPermissions)")
public void jwtPermissions() {}
@Around("jwtPermissions()")
public Object doPermission(ProceedingJoinPoint point) throws Throwable {
// 获取请求对象头部token数据
String token = JwtUtil.getRequestToken(request);
// 验证token数据是否正确
try {
JwtUtil.verifyToken(token, jwtProperties.getSecret());
} catch (TokenExpiredException e) {
throw new ResultException(JwtResultEnums.TOKEN_EXPIRED);
} catch (JWTVerificationException e) {
throw new ResultException(JwtResultEnums.TOKEN_ERROR);
}
return point.proceed();
}
}
@@ -0,0 +1,25 @@
package com.cwhelp.component.jwt.config;
import com.cwhelp.component.jwt.interceptor.AuthenticationInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* jwt权限配置拦截器
* @author yan.y
*/
@Configuration
@ConditionalOnProperty(name = "project.jwt.pattern-path", havingValue = "true", matchIfMissing = false)
public class JwtInterceptorConfig implements WebMvcConfigurer {
@Autowired
private AuthenticationInterceptor authenticationInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authenticationInterceptor).addPathPatterns("/api/**");
}
}
@@ -0,0 +1,23 @@
package com.cwhelp.component.jwt.config.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* jwt配置项
* @author yan.y
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "project.jwt")
public class JwtProjectProperties {
// jwt秘钥
private String secret = "mySecret";
// 过期时间(天),默认3天
private Integer expired = 3;
// 权限模式-路径拦截
private boolean patternPath = false;
// 权限模式-注解拦截
private boolean patternAnno = true;
}
@@ -0,0 +1,53 @@
package com.cwhelp.component.jwt.controller;
import com.cwhelp.common.enums.StatusEnum;
import com.cwhelp.common.exception.ResultException;
import com.cwhelp.common.utils.EncryptUtil;
import com.cwhelp.common.utils.ResultVoUtil;
import com.cwhelp.common.vo.ResultVo;
import com.cwhelp.component.jwt.annotation.IgnorePermissions;
import com.cwhelp.component.jwt.config.properties.JwtProjectProperties;
import com.cwhelp.component.jwt.enums.JwtResultEnums;
import com.cwhelp.component.jwt.utlis.JwtUtil;
import com.cwhelp.modules.system.domain.User;
import com.cwhelp.modules.system.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 默认登录验证控制器
* 说明:默认采用系统用户进行登录验证
* @author yan.y
*/
@RestController
public class AuthController {
@Autowired
private JwtProjectProperties properties;
@Autowired
private UserService userService;
@IgnorePermissions
@PostMapping("/api/auth")
public ResultVo auth(String username, String password){
// 根据用户名获取系统用户数据
User user = userService.getByName(username);
if (user == null) {
throw new ResultException(JwtResultEnums.AUTH_REQUEST_ERROR);
} else if (user.getStatus().equals(StatusEnum.FREEZED.getCode())){
throw new ResultException(JwtResultEnums.AUTH_REQUEST_LOCKED);
} else {
// 对明文密码加密处理
String encrypt = EncryptUtil.encrypt(password, user.getSalt());
// 判断密码是否正确
if (encrypt.equals(user.getPassword())) {
String token = JwtUtil.getToken(username, properties.getSecret(), properties.getExpired());
return ResultVoUtil.success("登录成功", token);
} else {
throw new ResultException(JwtResultEnums.AUTH_REQUEST_ERROR);
}
}
}
}
@@ -0,0 +1,34 @@
package com.cwhelp.component.jwt.enums;
import com.cwhelp.common.exception.interfaces.ResultInterface;
import lombok.Getter;
/**
* jwt结果集枚举
* @author yan.y
*/
@Getter
public enum JwtResultEnums implements ResultInterface {
/**
* token问题
*/
TOKEN_ERROR(301, "token无效"),
TOKEN_EXPIRED(302, "token已过期"),
/**
* 账号问题
*/
AUTH_REQUEST_ERROR(401, "用户名或密码错误"),
AUTH_REQUEST_LOCKED(402, "该账号已被冻结"),
;
private Integer code;
private String message;
JwtResultEnums(Integer code, String message) {
this.code = code;
this.message = message;
}
}
@@ -0,0 +1,68 @@
package com.cwhelp.component.jwt.interceptor;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.cwhelp.common.exception.ResultException;
import com.cwhelp.component.jwt.annotation.IgnorePermissions;
import com.cwhelp.component.jwt.config.properties.JwtProjectProperties;
import com.cwhelp.component.jwt.enums.JwtResultEnums;
import com.cwhelp.component.jwt.utlis.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
/**
* jwt权限拦截器
* @author yan.y
*/
@Component
public class AuthenticationInterceptor implements HandlerInterceptor {
@Autowired
private JwtProjectProperties jwtProperties;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 如果不是映射到方法直接通过
if (!(handler instanceof HandlerMethod)) {
return true;
}
// 判断请求映射的方式是否忽略权限验证
HandlerMethod handlerMethod=(HandlerMethod) handler;
Method method=handlerMethod.getMethod();
if (method.isAnnotationPresent(IgnorePermissions.class)) {
return true;
}
// 获取请求对象头部token数据
String token = JwtUtil.getRequestToken(request);
// 验证token数据是否正确
try {
JwtUtil.verifyToken(token, jwtProperties.getSecret());
} catch (TokenExpiredException e) {
throw new ResultException(JwtResultEnums.TOKEN_EXPIRED);
} catch (JWTVerificationException e) {
throw new ResultException(JwtResultEnums.TOKEN_ERROR);
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
@@ -0,0 +1,105 @@
package com.cwhelp.component.jwt.utlis;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.cwhelp.common.exception.ResultException;
import com.cwhelp.common.utils.HttpServletUtil;
import com.cwhelp.common.utils.ToolUtil;
import com.cwhelp.component.jwt.enums.JwtResultEnums;
import com.cwhelp.modules.system.domain.User;
import javax.servlet.http.HttpServletRequest;
import java.util.Calendar;
import java.util.Date;
/**
* @author yan.y
*/
public class JwtUtil {
/**
* 生成JwtToken
* @param username 用户名
* @param secret 秘钥
* @param amount 过期天数
*/
public static String getToken(String username, String secret, int amount){
User user = new User();
user.setUsername(username);
return getToken(user, secret, amount);
}
/**
* 生成JwtToken
* @param user 用户对象
* @param secret 秘钥
* @param amount 过期天数
*/
public static String getToken(User user, String secret, int amount){
// 过期时间
Calendar ca = Calendar.getInstance();
ca.add(Calendar.DATE, amount);
// 随机Claim
String random = ToolUtil.getRandomString(6);
// 创建JwtToken对象
String token="";
token= JWT.create()
.withSubject(user.getUsername()) // 用户名
.withIssuedAt(new Date()) // 发布时间
.withExpiresAt(ca.getTime()) // 过期时间
.withClaim("ran", random) // 自定义随机Claim
.sign(getSecret(secret, random));
return token;
}
/**
* 获取请求对象中的token数据
*/
public static String getRequestToken(HttpServletRequest request){
// 获取JwtTokens失败
String authorization = request.getHeader("Authorization");
if (authorization == null || !authorization.startsWith("Bearer ")) {
throw new ResultException(JwtResultEnums.TOKEN_ERROR);
}
return authorization.substring(7);
}
/**
* 获取当前token中的用户名
*/
public static String getSubject(){
HttpServletRequest request = HttpServletUtil.getRequest();
String token = getRequestToken(request);
return JWT.decode(token).getSubject();
}
/**
* 验证JwtToken
* @param token JwtToken数据
* @return true 验证通过
* @exception TokenExpiredException Token过期
* @exception JWTVerificationException 令牌无效(验证不通过)
*/
public static void verifyToken(String token, String secret) throws JWTVerificationException {
String ran = JWT.decode(token).getClaim("ran").asString();
JWTVerifier jwtVerifier = JWT.require(getSecret(secret, ran)).build();
jwtVerifier.verify(token);
}
/**
* 生成Secret混淆数据
*/
private static Algorithm getSecret(String secret, String random){
String salt = "君不见黄河之水天上来,奔流到海不复回。君不见高堂明镜悲白发,朝如青丝暮成雪。";
//String salt = "元嘉草草,封狼居胥,赢得仓皇北顾。四十三年,望中犹记,烽火扬州路。可堪回首,佛狸祠下,一片神鸦社鼓。凭谁问、廉颇老矣,尚能饭否?";
//String salt = "安能摧眉折腰事权贵,使我不得开心颜。";
//String salt = "大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。江山如画,一时多少豪杰。";
return Algorithm.HMAC256(secret + salt + "(ノ ̄▽ ̄)ノ 皮一下" + random);
}
}
@@ -0,0 +1,36 @@
{
"groups": [
{
"name": "project.jwt",
"type": "com.cwhelp.component.jwt.config.properties.JwtProjectProperties",
"sourceType": "com.cwhelp.component.jwt.config.properties.JwtProjectProperties"
}
],
"properties": [
{
"name": "project.jwt.expired",
"type": "java.lang.Integer",
"sourceType": "com.cwhelp.component.jwt.config.properties.JwtProjectProperties",
"defaultValue": 3
},
{
"name": "project.jwt.pattern-anno",
"type": "java.lang.Boolean",
"sourceType": "com.cwhelp.component.jwt.config.properties.JwtProjectProperties",
"defaultValue": true
},
{
"name": "project.jwt.pattern-path",
"type": "java.lang.Boolean",
"sourceType": "com.cwhelp.component.jwt.config.properties.JwtProjectProperties",
"defaultValue": false
},
{
"name": "project.jwt.secret",
"type": "java.lang.String",
"sourceType": "com.cwhelp.component.jwt.config.properties.JwtProjectProperties",
"defaultValue": "mySecret"
}
],
"hints": []
}
+25
View File
@@ -0,0 +1,25 @@
<?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>component</artifactId>
<packaging>pom</packaging>
<name>组件模块</name>
<modules>
<module>excel</module>
<module>actionLog</module>
<module>shiro</module>
<module>thymeleaf</module>
<module>fileUpload</module>
<module>jwt</module>
</modules>
<parent>
<groupId>com.cwhelp</groupId>
<artifactId>cwhelp</artifactId>
<version>2.0.1</version>
</parent>
</project>
+44
View File
@@ -0,0 +1,44 @@
<?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>
<groupId>com.cwhelp.component</groupId>
<artifactId>shiro</artifactId>
<packaging>jar</packaging>
<name>组件:Shiro权限</name>
<parent>
<groupId>com.cwhelp</groupId>
<artifactId>component</artifactId>
<version>2.0.1</version>
</parent>
<dependencies>
<dependency>
<groupId>com.cwhelp</groupId>
<artifactId>common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.cwhelp.modules</groupId>
<artifactId>system</artifactId>
<version>${project.version}</version>
</dependency>
<!--shiro权限管理框架-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>${shiro.version}</version>
</dependency>
</dependencies>
</project>
+133
View File
@@ -0,0 +1,133 @@
<?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="module" module-name="common" />
<orderEntry type="module" module-name="system" />
<orderEntry type="module" module-name="excel" />
<orderEntry type="library" name="Maven: org.apache.poi:poi-ooxml:4.0.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.poi:poi:4.0.0" level="project" />
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.11" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-collections4:4.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.poi:poi-ooxml-schemas:4.0.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.xmlbeans:xmlbeans:3.0.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-compress:1.18" level="project" />
<orderEntry type="library" name="Maven: com.github.virtuald:curvesapi:1.04" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-spring:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-lang:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-crypto-hash:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-crypto-core:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-crypto-cipher:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-config-core:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-config-ogdl:1.4.0" level="project" />
<orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.9.3" level="project" />
<orderEntry type="library" name="Maven: commons-collections:commons-collections:3.2.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-event:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-web:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-ehcache:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-cache:1.4.0" level="project" />
<orderEntry type="library" name="Maven: net.sf.ehcache:ehcache-core:2.6.11" level="project" />
<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,109 @@
package com.cwhelp.component.shiro;
import com.cwhelp.common.constant.AdminConst;
import com.cwhelp.common.enums.StatusEnum;
import com.cwhelp.modules.system.domain.User;
import com.cwhelp.modules.system.service.RoleService;
import com.cwhelp.modules.system.service.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.codec.CodecSupport;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import javax.annotation.PostConstruct;
/**
* @author yan.y
*/
public class AuthRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
@Autowired
private RoleService roleService;
/**
* 授权逻辑
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 获取用户Principal对象
User user = (User) principal.getPrimaryPrincipal();
// 管理员拥有所有权限
if(user.getId().equals(AdminConst.ADMIN_ID)){
info.addRole(AdminConst.ADMIN_ROLE_NAME);
info.addStringPermission("*:*:*");
return info;
}
// 获取角色和资源(JPA延迟加载超时,通过用户ID获取角色列表)
user.setRoles(roleService.getUserOkRoleList(user.getId()));
// 赋予角色和资源授权
user.getRoles().forEach(role -> {
info.addRole(role.getName());
role.getMenus().forEach(menu -> {
String perms = menu.getPerms();
if(menu.getStatus().equals(StatusEnum.OK.getCode())
&& !StringUtils.isEmpty(perms) && !perms.contains("*")){
info.addStringPermission(perms);
}
});
});
return info;
}
/**
* 认证逻辑
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
// 获取数据库中的用户名密码
User user = userService.getByName(token.getUsername());
// 判断用户名是否存在
if(user == null){
throw new UnknownAccountException();
}else if(user.getStatus().equals(StatusEnum.FREEZED.getCode())){
throw new LockedAccountException();
}
// 对盐进行加密处理
ByteSource salt = ByteSource.Util.bytes(user.getSalt());
/* 传入密码自动判断是否正确
* 参数1:传入对象给Principal
* 参数2:正确的用户密码
* 参数3:加盐处理
* 参数4:固定写法
*/
return new SimpleAuthenticationInfo(user, user.getPassword(), salt, getName());
}
/**
* 自定义密码验证匹配器
*/
@PostConstruct
public void initCredentialsMatcher() {
setCredentialsMatcher(new SimpleCredentialsMatcher() {
@Override
public boolean doCredentialsMatch(AuthenticationToken authenticationToken, AuthenticationInfo authenticationInfo) {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
SimpleAuthenticationInfo info = (SimpleAuthenticationInfo) authenticationInfo;
// 获取明文密码及密码盐
String password = String.valueOf(token.getPassword());
String salt = CodecSupport.toString(info.getCredentialsSalt().getBytes());
return equals(ShiroUtil.encrypt(password, salt), info.getCredentials());
}
});
}
}
@@ -0,0 +1,76 @@
package com.cwhelp.component.shiro;
import com.cwhelp.common.utils.EncryptUtil;
import com.cwhelp.common.utils.SpringContextUtil;
import com.cwhelp.modules.system.domain.Role;
import com.cwhelp.modules.system.domain.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.RememberMeManager;
import java.util.Set;
/**
* Shiro工具类
* @author yan.y
*/
public class ShiroUtil {
/**
* 加密算法
*/
public final static String hashAlgorithmName = EncryptUtil.hashAlgorithmName;
/**
* 循环次数
*/
public final static int hashIterations = EncryptUtil.hashIterations;
/**
* 加密处理
* 备注:采用自定义的密码加密方式,其原理与SimpleHash一致,
* 为的是在多个模块间可以使用同一套加密方式,方便共用系统用户。
* @param password 密码
* @param salt 密码盐
*/
public static String encrypt(String password, String salt) {
return EncryptUtil.encrypt(password, salt, hashAlgorithmName, hashIterations);
}
/**
* 获取随机盐值
*/
public static String getRandomSalt(){
return EncryptUtil.getRandomSalt();
}
/**
* 获取ShiroUser对象
*/
public static User getSubject(){
return (User) SecurityUtils.getSubject().getPrincipal();
}
/**
* 获取用户IP地址
*/
public static String getIp(){
return SecurityUtils.getSubject().getSession().getHost();
}
/**
* 重置Cookie“记住我”序列化信息
*/
public static void resetCookieRememberMe(){
Set<Role> roles = getSubject().getRoles();
getSubject().setRoles(null);
RememberMeManager meManager = SpringContextUtil.getBean(RememberMeManager.class);
UsernamePasswordToken token = new UsernamePasswordToken();
token.setRememberMe(true);
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo();
info.setPrincipals(SecurityUtils.getSubject().getPrincipals());
meManager.onSuccessfulLogin(SecurityUtils.getSubject(), token, info);
getSubject().setRoles(roles);
}
}
@@ -0,0 +1,40 @@
package com.cwhelp.component.shiro;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.http.HttpStatus;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 处理session超时问题拦截器
* @author yan.y
*/
public class UserAuthFilter extends AccessControlFilter {
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
if (isLoginRequest(request, response)) {
return true;
} else {
Subject subject = getSubject(request, response);
return subject.getPrincipal() != null;
}
}
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpRequest = WebUtils.toHttp(request);
HttpServletResponse httpResponse = WebUtils.toHttp(response);
if (httpRequest.getHeader("X-Requested-With") != null
&& httpRequest.getHeader("X-Requested-With").equalsIgnoreCase("XMLHttpRequest")) {
httpResponse.sendError(HttpStatus.UNAUTHORIZED.value());
} else {
redirectToLogin(request, response);
}
return false;
}
}
@@ -0,0 +1,23 @@
package com.cwhelp.component.shiro.config;
import com.cwhelp.modules.system.domain.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.AuditorAware;
import java.util.Optional;
/**
* 审核员自动赋值配置
* @author yan.y
*/
@Configuration
public class AuditorConfig implements AuditorAware<User> {
@Override
public Optional<User> getCurrentAuditor() {
Subject subject = SecurityUtils.getSubject();
User user = (User) subject.getPrincipal();
return Optional.ofNullable(user);
}
}
@@ -0,0 +1,151 @@
package com.cwhelp.component.shiro.config;
import com.cwhelp.component.shiro.AuthRealm;
import com.cwhelp.component.shiro.UserAuthFilter;
import com.cwhelp.component.shiro.config.properties.ShiroProjectProperties;
import net.sf.ehcache.CacheManager;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
/**
* @author yan.y
*/
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
/**
* 添加自定义拦截器,重写user认证方式,处理session超时问题
*/
HashMap<String, Filter> myFilters = new HashMap<>();
myFilters.put("userAuth", new UserAuthFilter());
shiroFilterFactoryBean.setFilters(myFilters);
/**
* 过滤规则(注意优先级)
* —anon 无需认证(登录)可访问
* —authc 必须认证才可访问
* —perms[标识] 拥有资源权限才可访问
* —role 拥有角色权限才可访问
* —user 认证和自动登录可访问
*/
LinkedHashMap<String, String> filterMap = new LinkedHashMap<>();
filterMap.put("/login", "anon");
filterMap.put("/logout", "anon");
filterMap.put("/captcha", "anon");
filterMap.put("/noAuth", "anon");
filterMap.put("/css/**", "anon");
filterMap.put("/js/**", "anon");
filterMap.put("/images/**", "anon");
filterMap.put("/lib/**", "anon");
filterMap.put("/favicon.ico", "anon");
filterMap.put("/**", "userAuth");
// 设置过滤规则
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
// 设置登录页面
shiroFilterFactoryBean.setLoginUrl("/login");
// 未授权错误页面
shiroFilterFactoryBean.setUnauthorizedUrl("/noAuth");
return shiroFilterFactoryBean;
}
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(AuthRealm authRealm,
DefaultWebSessionManager sessionManager,
CookieRememberMeManager rememberMeManager) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(authRealm);
securityManager.setSessionManager(sessionManager);
securityManager.setRememberMeManager(rememberMeManager);
return securityManager;
}
/**
* 自定义的Realm
*/
@Bean
public AuthRealm getRealm(EhCacheManager ehCacheManager) {
AuthRealm authRealm = new AuthRealm();
authRealm.setCacheManager(ehCacheManager);
return authRealm;
}
/**
* 缓存管理器-使用Ehcache实现缓存
*/
@Bean
public EhCacheManager ehCacheManager(CacheManager cacheManager) {
EhCacheManager ehCacheManager = new EhCacheManager();
ehCacheManager.setCacheManager(cacheManager);
return ehCacheManager;
}
/**
* session管理器
*/
@Bean
public DefaultWebSessionManager getDefaultWebSessionManager(EhCacheManager cacheManager, ShiroProjectProperties properties) {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setCacheManager(cacheManager);
sessionManager.setGlobalSessionTimeout(properties.getGlobalSessionTimeout() * 1000);
sessionManager.setSessionValidationInterval(properties.getSessionValidationInterval() * 1000);
sessionManager.setDeleteInvalidSessions(true);
sessionManager.validateSessions();
// 去掉登录页面地址栏jsessionid
sessionManager.setSessionIdUrlRewritingEnabled(false);
return sessionManager;
}
/**
* rememberMe管理器
*/
@Bean
public CookieRememberMeManager rememberMeManager(SimpleCookie rememberMeCookie) {
CookieRememberMeManager manager = new CookieRememberMeManager();
manager.setCipherKey(Base64.decode("WcfHGU25gNnTxTlmJMeSpw=="));
manager.setCookie(rememberMeCookie);
return manager;
}
/**
* 创建一个简单的Cookie对象
*/
@Bean
public SimpleCookie rememberMeCookie(ShiroProjectProperties properties) {
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
simpleCookie.setHttpOnly(true);
// cookie记住登录信息时间,默认7天
simpleCookie.setMaxAge(properties.getRememberMeTimeout() * 24 * 60 * 60);
return simpleCookie;
}
/**
* 启用shrio授权注解拦截方式,AOP式方法级权限检查
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor =
new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
@@ -0,0 +1,21 @@
package com.cwhelp.component.shiro.config.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 项目-shiro会话配置项
* @author yan.y
*/
@Data
@Component
@ConfigurationProperties(prefix = "project.shiro")
public class ShiroProjectProperties {
// cookie记住登录信息时间,默认7天
private Integer rememberMeTimeout = 7;
// Session会话超时时间,默认30分钟
private Integer globalSessionTimeout = 1800;
// Session会话检测间隔时间,默认15分钟
private Integer sessionValidationInterval = 900;
}
@@ -0,0 +1,52 @@
package com.cwhelp.component.shiro.exception;
import com.cwhelp.common.enums.ResultEnum;
import com.cwhelp.common.utils.ResultVoUtil;
import com.cwhelp.common.utils.SpringContextUtil;
import com.cwhelp.common.vo.ResultVo;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 拦截访问权限异常处理
* @author yan.y
*/
@ControllerAdvice
@Order(-1)
public class AuthorizationExceptionHandler {
// 拦截访问权限异常
@ExceptionHandler(AuthorizationException.class)
@ResponseBody
public ResultVo authorizationException(AuthorizationException e, HttpServletRequest request,
HttpServletResponse response){
Integer code = ResultEnum.NO_PERMISSIONS.getCode();
String msg = ResultEnum.NO_PERMISSIONS.getMessage();
// 获取异常信息
Throwable cause = e.getCause();
String message = cause.getMessage();
Class<ResultVo> resultVoClass = ResultVo.class;
// 判断无权限访问的方法返回对象是否为ResultVo
if(!message.contains(resultVoClass.getName())){
try {
// 重定向到无权限页面
String contextPath = request.getContextPath();
ShiroFilterFactoryBean shiroFilter = SpringContextUtil.getBean(ShiroFilterFactoryBean.class);
response.sendRedirect(contextPath+shiroFilter.getUnauthorizedUrl());
} catch (IOException e1) {
return ResultVoUtil.error(code, msg);
}
}
return ResultVoUtil.error(code, msg);
}
}
@@ -0,0 +1,30 @@
{
"groups": [
{
"name": "project.shiro",
"type": "com.cwhelp.component.shiro.config.properties.ShiroProjectProperties",
"sourceType": "com.cwhelp.component.shiro.config.properties.ShiroProjectProperties"
}
],
"properties": [
{
"name": "project.shiro.global-session-timeout",
"type": "java.lang.Integer",
"sourceType": "com.cwhelp.component.shiro.config.properties.ShiroProjectProperties",
"defaultValue": 1800
},
{
"name": "project.shiro.remember-me-timeout",
"type": "java.lang.Integer",
"sourceType": "com.cwhelp.component.shiro.config.properties.ShiroProjectProperties",
"defaultValue": 7
},
{
"name": "project.shiro.session-validation-interval",
"type": "java.lang.Integer",
"sourceType": "com.cwhelp.component.shiro.config.properties.ShiroProjectProperties",
"defaultValue": 900
}
],
"hints": []
}

Some files were not shown because too many files have changed in this diff Show More