人车物
commit
9d866913c5
|
|
@ -0,0 +1,63 @@
|
||||||
|
# Created by .ignore support plugin (hsz.mobi)
|
||||||
|
### JetBrains template
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**
|
||||||
|
|
||||||
|
*.iml
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
### Java template
|
||||||
|
# Compiled class file
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Log file
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# BlueJ files
|
||||||
|
*.ctxt
|
||||||
|
|
||||||
|
# Mobile Tools for Java (J2ME)
|
||||||
|
.mtj.tmp/
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.nar
|
||||||
|
*.ear
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
*.rar
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
hs_err_pid*
|
||||||
|
|
||||||
|
#maven ignore
|
||||||
|
target/
|
||||||
|
|
@ -0,0 +1,163 @@
|
||||||
|
<?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">
|
||||||
|
<parent>
|
||||||
|
<artifactId>basepro-manager</artifactId>
|
||||||
|
<groupId>guo.ping.e3mall</groupId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../e3-parent/pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>basepro-framework</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<description>
|
||||||
|
framework框架核心
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>guo.ping.e3mall</groupId>
|
||||||
|
<artifactId>e3-common</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>guo.ping.e3mall</groupId>
|
||||||
|
<artifactId>basepro-manager-interface</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>guo.ping.e3mall</groupId>
|
||||||
|
<artifactId>basepro-manager-pojo</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>guo.ping.e3mall</groupId>
|
||||||
|
<artifactId>basepro-manager-service</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- SpringBoot Web容器 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- SpringBoot 拦截器 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-aop</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mybatis.spring.boot</groupId>
|
||||||
|
<artifactId>mybatis-spring-boot-autoconfigure</artifactId>
|
||||||
|
<version>1.2.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>druid</artifactId>
|
||||||
|
<version>1.1.14</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mybatis</groupId>
|
||||||
|
<artifactId>mybatis</artifactId>
|
||||||
|
<version>3.4.5</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-jdbc</artifactId>
|
||||||
|
<version>4.3.13.RELEASE</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.aspectj</groupId>
|
||||||
|
<artifactId>aspectjweaver</artifactId>
|
||||||
|
<version>1.8.14</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--阿里数据库连接池 -->
|
||||||
|
<!--<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>druid-spring-boot-starter</artifactId>
|
||||||
|
</dependency>-->
|
||||||
|
|
||||||
|
<!--验证码 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.penggle</groupId>
|
||||||
|
<artifactId>kaptcha</artifactId>
|
||||||
|
<version>2.3.2</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>javax.servlet-api</artifactId>
|
||||||
|
<groupId>javax.servlet</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Shiro使用Srping框架 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.shiro</groupId>
|
||||||
|
<artifactId>shiro-spring</artifactId>
|
||||||
|
<version>1.4.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Shiro使用EhCache缓存框架 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.shiro</groupId>
|
||||||
|
<artifactId>shiro-ehcache</artifactId>
|
||||||
|
<version>1.4.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- thymeleaf模板引擎和shiro框架的整合 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.theborakompanioni</groupId>
|
||||||
|
<artifactId>thymeleaf-extras-shiro</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 解析客户端操作系统、浏览器等 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>eu.bitwalker</groupId>
|
||||||
|
<artifactId>UserAgentUtils</artifactId>
|
||||||
|
<version>1.19</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.crazycake</groupId>
|
||||||
|
<artifactId>shiro-redis</artifactId>
|
||||||
|
<version>2.4.2.1-RELEASE</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.axet</groupId>
|
||||||
|
<artifactId>kaptcha</artifactId>
|
||||||
|
<version>0.0.9</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- 系统模块-->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 获取系统信息 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.oshi</groupId>
|
||||||
|
<artifactId>oshi-core</artifactId>
|
||||||
|
<version>3.9.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.java.dev.jna</groupId>
|
||||||
|
<artifactId>jna</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.java.dev.jna</groupId>
|
||||||
|
<artifactId>jna-platform</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mybatis</groupId>
|
||||||
|
<artifactId>mybatis-spring</artifactId>
|
||||||
|
<version>1.3.0</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.basepro.framework;
|
||||||
|
|
||||||
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
@MapperScan("basepro.manager.mapper")
|
||||||
|
public class Application {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(Application.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,162 @@
|
||||||
|
package com.basepro.framework.aspectj;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import basepro.manager.pojo.SysRole;
|
||||||
|
import basepro.manager.pojo.SysUser;
|
||||||
|
import guo.ping.e3mall.common.annotation.DataScope;
|
||||||
|
import guo.ping.e3mall.common.pojo.BaseEntity;
|
||||||
|
import guo.ping.e3mall.common.utils.StringUtils;
|
||||||
|
import org.aspectj.lang.JoinPoint;
|
||||||
|
import org.aspectj.lang.Signature;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.annotation.Before;
|
||||||
|
import org.aspectj.lang.annotation.Pointcut;
|
||||||
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import com.basepro.framework.util.ShiroUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据过滤处理
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
@Component
|
||||||
|
public class DataScopeAspect
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 全部数据权限
|
||||||
|
*/
|
||||||
|
public static final String DATA_SCOPE_ALL = "1";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定数据权限
|
||||||
|
*/
|
||||||
|
public static final String DATA_SCOPE_CUSTOM = "2";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门数据权限
|
||||||
|
*/
|
||||||
|
public static final String DATA_SCOPE_DEPT = "3";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门及以下数据权限
|
||||||
|
*/
|
||||||
|
public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 仅本人数据权限
|
||||||
|
*/
|
||||||
|
public static final String DATA_SCOPE_SELF = "5";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据权限过滤关键字
|
||||||
|
*/
|
||||||
|
public static final String DATA_SCOPE = "dataScope";
|
||||||
|
|
||||||
|
// 配置织入点
|
||||||
|
@Pointcut("@annotation(guo.ping.e3mall.common.annotation.DataScope)")
|
||||||
|
public void dataScopePointCut()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before("dataScopePointCut()")
|
||||||
|
public void doBefore(JoinPoint point) throws Throwable
|
||||||
|
{
|
||||||
|
handleDataScope(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleDataScope(final JoinPoint joinPoint)
|
||||||
|
{
|
||||||
|
// 获得注解
|
||||||
|
DataScope controllerDataScope = getAnnotationLog(joinPoint);
|
||||||
|
if (controllerDataScope == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 获取当前的用户
|
||||||
|
SysUser currentUser = ShiroUtils.getSysUser();
|
||||||
|
if (currentUser != null)
|
||||||
|
{
|
||||||
|
// 如果是超级管理员,则不过滤数据
|
||||||
|
if (!currentUser.isAdmin())
|
||||||
|
{
|
||||||
|
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
|
||||||
|
controllerDataScope.userAlias());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据范围过滤
|
||||||
|
*
|
||||||
|
* @param joinPoint 切点
|
||||||
|
* @param user 用户
|
||||||
|
* @param alias 别名
|
||||||
|
*/
|
||||||
|
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias)
|
||||||
|
{
|
||||||
|
StringBuilder sqlString = new StringBuilder();
|
||||||
|
|
||||||
|
for (SysRole role : user.getRoles())
|
||||||
|
{
|
||||||
|
String dataScope = role.getDataScope();
|
||||||
|
if (DATA_SCOPE_ALL.equals(dataScope))
|
||||||
|
{
|
||||||
|
sqlString = new StringBuilder();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (DATA_SCOPE_CUSTOM.equals(dataScope))
|
||||||
|
{
|
||||||
|
sqlString.append(StringUtils.format(
|
||||||
|
" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,
|
||||||
|
role.getRoleId()));
|
||||||
|
}
|
||||||
|
else if (DATA_SCOPE_DEPT.equals(dataScope))
|
||||||
|
{
|
||||||
|
sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));
|
||||||
|
}
|
||||||
|
else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
|
||||||
|
{
|
||||||
|
sqlString.append(StringUtils.format(
|
||||||
|
" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
|
||||||
|
deptAlias, user.getDeptId(), user.getDeptId()));
|
||||||
|
}
|
||||||
|
else if (DATA_SCOPE_SELF.equals(dataScope))
|
||||||
|
{
|
||||||
|
if (StringUtils.isNotBlank(userAlias))
|
||||||
|
{
|
||||||
|
sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 数据权限为仅本人且没有userAlias别名不查询任何数据
|
||||||
|
sqlString.append(" OR 1=0 ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(sqlString.toString()))
|
||||||
|
{
|
||||||
|
BaseEntity baseEntity = (BaseEntity) joinPoint.getArgs()[0];
|
||||||
|
baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否存在注解,如果存在就获取
|
||||||
|
*/
|
||||||
|
private DataScope getAnnotationLog(JoinPoint joinPoint)
|
||||||
|
{
|
||||||
|
Signature signature = joinPoint.getSignature();
|
||||||
|
MethodSignature methodSignature = (MethodSignature) signature;
|
||||||
|
Method method = methodSignature.getMethod();
|
||||||
|
|
||||||
|
if (method != null)
|
||||||
|
{
|
||||||
|
return method.getAnnotation(DataScope.class);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
package com.basepro.framework.aspectj;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import guo.ping.e3mall.common.annotation.DataSource;
|
||||||
|
import guo.ping.e3mall.common.config.DynamicDataSourceContextHolder;
|
||||||
|
import guo.ping.e3mall.common.utils.StringUtils;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.annotation.Pointcut;
|
||||||
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多数据源处理
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
@Order(1)
|
||||||
|
@Component
|
||||||
|
public class DataSourceAspect
|
||||||
|
{
|
||||||
|
protected Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
|
@Pointcut("@annotation(guo.ping.e3mall.common.annotation.DataSource)"
|
||||||
|
+ "|| @within(guo.ping.e3mall.common.annotation.DataSource)")
|
||||||
|
public void dsPointCut()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Around("dsPointCut()")
|
||||||
|
public Object around(ProceedingJoinPoint point) throws Throwable
|
||||||
|
{
|
||||||
|
DataSource dataSource = getDataSource(point);
|
||||||
|
|
||||||
|
if (StringUtils.isNotNull(dataSource))
|
||||||
|
{
|
||||||
|
DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return point.proceed();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// 销毁数据源 在执行方法之后
|
||||||
|
DynamicDataSourceContextHolder.clearDataSourceType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取需要切换的数据源
|
||||||
|
*/
|
||||||
|
public DataSource getDataSource(ProceedingJoinPoint point)
|
||||||
|
{
|
||||||
|
MethodSignature signature = (MethodSignature) point.getSignature();
|
||||||
|
Class<? extends Object> targetClass = point.getTarget().getClass();
|
||||||
|
DataSource targetDataSource = targetClass.getAnnotation(DataSource.class);
|
||||||
|
if (StringUtils.isNotNull(targetDataSource))
|
||||||
|
{
|
||||||
|
return targetDataSource;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Method method = signature.getMethod();
|
||||||
|
DataSource dataSource = method.getAnnotation(DataSource.class);
|
||||||
|
return dataSource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,178 @@
|
||||||
|
package com.basepro.framework.aspectj;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import basepro.manager.pojo.SysOperLog;
|
||||||
|
import basepro.manager.pojo.SysUser;
|
||||||
|
import guo.ping.e3mall.common.annotation.Log;
|
||||||
|
import guo.ping.e3mall.common.enums.BusinessStatus;
|
||||||
|
import guo.ping.e3mall.common.json.JSON;
|
||||||
|
import guo.ping.e3mall.common.utils.ServletUtils;
|
||||||
|
import guo.ping.e3mall.common.utils.StringUtils;
|
||||||
|
import org.aspectj.lang.JoinPoint;
|
||||||
|
import org.aspectj.lang.Signature;
|
||||||
|
import org.aspectj.lang.annotation.AfterReturning;
|
||||||
|
import org.aspectj.lang.annotation.AfterThrowing;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.annotation.Pointcut;
|
||||||
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import com.basepro.framework.manager.AsyncManager;
|
||||||
|
import com.basepro.framework.manager.factory.AsyncFactory;
|
||||||
|
import com.basepro.framework.util.ShiroUtils;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作日志记录处理
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
@Component
|
||||||
|
public class LogAspect
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
|
||||||
|
|
||||||
|
// 配置织入点
|
||||||
|
@Pointcut("@annotation(guo.ping.e3mall.common.annotation.Log)")
|
||||||
|
public void logPointCut()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理完请求后执行
|
||||||
|
*
|
||||||
|
* @param joinPoint 切点
|
||||||
|
*/
|
||||||
|
@AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
|
||||||
|
public void doAfterReturning(JoinPoint joinPoint, Object jsonResult)
|
||||||
|
{
|
||||||
|
handleLog(joinPoint, null, jsonResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拦截异常操作
|
||||||
|
*
|
||||||
|
* @param joinPoint 切点
|
||||||
|
* @param e 异常
|
||||||
|
*/
|
||||||
|
@AfterThrowing(value = "logPointCut()", throwing = "e")
|
||||||
|
public void doAfterThrowing(JoinPoint joinPoint, Exception e)
|
||||||
|
{
|
||||||
|
handleLog(joinPoint, e, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 获得注解
|
||||||
|
Log controllerLog = getAnnotationLog(joinPoint);
|
||||||
|
if (controllerLog == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前的用户
|
||||||
|
SysUser currentUser = ShiroUtils.getSysUser();
|
||||||
|
|
||||||
|
// *========数据库日志=========*//
|
||||||
|
SysOperLog operLog = new SysOperLog();
|
||||||
|
operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
|
||||||
|
// 请求的地址
|
||||||
|
String ip = ShiroUtils.getIp();
|
||||||
|
operLog.setOperIp(ip);
|
||||||
|
// 返回参数
|
||||||
|
operLog.setJsonResult(JSON.marshal(jsonResult));
|
||||||
|
|
||||||
|
operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
|
||||||
|
if (currentUser != null)
|
||||||
|
{
|
||||||
|
operLog.setOperName(currentUser.getLoginName());
|
||||||
|
if (StringUtils.isNotNull(currentUser.getDept())
|
||||||
|
&& StringUtils.isNotEmpty(currentUser.getDept().getDeptName()))
|
||||||
|
{
|
||||||
|
operLog.setDeptName(currentUser.getDept().getDeptName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e != null)
|
||||||
|
{
|
||||||
|
operLog.setStatus(BusinessStatus.FAIL.ordinal());
|
||||||
|
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
|
||||||
|
}
|
||||||
|
// 设置方法名称
|
||||||
|
String className = joinPoint.getTarget().getClass().getName();
|
||||||
|
String methodName = joinPoint.getSignature().getName();
|
||||||
|
operLog.setMethod(className + "." + methodName + "()");
|
||||||
|
// 设置请求方式
|
||||||
|
operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
|
||||||
|
// 处理设置注解上的参数
|
||||||
|
getControllerMethodDescription(controllerLog, operLog);
|
||||||
|
// 保存数据库
|
||||||
|
AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
|
||||||
|
}
|
||||||
|
catch (Exception exp)
|
||||||
|
{
|
||||||
|
// 记录本地异常日志
|
||||||
|
log.error("==前置通知异常==");
|
||||||
|
log.error("异常信息:{}", exp.getMessage());
|
||||||
|
exp.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取注解中对方法的描述信息 用于Controller层注解
|
||||||
|
*
|
||||||
|
* @param log 日志
|
||||||
|
* @param operLog 操作日志
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public void getControllerMethodDescription(Log log, SysOperLog operLog) throws Exception
|
||||||
|
{
|
||||||
|
// 设置action动作
|
||||||
|
operLog.setBusinessType(log.businessType().ordinal());
|
||||||
|
// 设置标题
|
||||||
|
operLog.setTitle(log.title());
|
||||||
|
// 设置操作人类别
|
||||||
|
operLog.setOperatorType(log.operatorType().ordinal());
|
||||||
|
// 是否需要保存request,参数和值
|
||||||
|
if (log.isSaveRequestData())
|
||||||
|
{
|
||||||
|
// 获取参数的信息,传入到数据库中。
|
||||||
|
setRequestValue(operLog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取请求的参数,放到log中
|
||||||
|
*
|
||||||
|
* @param operLog 操作日志
|
||||||
|
* @throws Exception 异常
|
||||||
|
*/
|
||||||
|
private void setRequestValue(SysOperLog operLog) throws Exception
|
||||||
|
{
|
||||||
|
Map<String, String[]> map = ServletUtils.getRequest().getParameterMap();
|
||||||
|
String params = JSON.marshal(map);
|
||||||
|
operLog.setOperParam(StringUtils.substring(params, 0, 2000));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否存在注解,如果存在就获取
|
||||||
|
*/
|
||||||
|
private Log getAnnotationLog(JoinPoint joinPoint) throws Exception
|
||||||
|
{
|
||||||
|
Signature signature = joinPoint.getSignature();
|
||||||
|
MethodSignature methodSignature = (MethodSignature) signature;
|
||||||
|
Method method = methodSignature.getMethod();
|
||||||
|
|
||||||
|
if (method != null)
|
||||||
|
{
|
||||||
|
return method.getAnnotation(Log.class);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.basepro.framework.config;
|
||||||
|
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 程序注解配置
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
// 表示通过aop框架暴露该代理对象,AopContext能够访问
|
||||||
|
@EnableAspectJAutoProxy(exposeProxy = true)
|
||||||
|
// 指定要扫描的Mapper类的包的路径
|
||||||
|
//@MapperScan("basepro.manager.mapper")
|
||||||
|
public class ApplicationConfig
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
package com.basepro.framework.config;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import com.google.code.kaptcha.impl.DefaultKaptcha;
|
||||||
|
import com.google.code.kaptcha.util.Config;
|
||||||
|
import static com.google.code.kaptcha.Constants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码配置
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class CaptchaConfig
|
||||||
|
{
|
||||||
|
@Bean(name = "captchaProducer")
|
||||||
|
public DefaultKaptcha getKaptchaBean()
|
||||||
|
{
|
||||||
|
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
|
||||||
|
Properties properties = new Properties();
|
||||||
|
// 是否有边框 默认为true 我们可以自己设置yes,no
|
||||||
|
properties.setProperty(KAPTCHA_BORDER, "yes");
|
||||||
|
// 验证码文本字符颜色 默认为Color.BLACK
|
||||||
|
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
|
||||||
|
// 验证码图片宽度 默认为200
|
||||||
|
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
|
||||||
|
// 验证码图片高度 默认为50
|
||||||
|
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
|
||||||
|
// 验证码文本字符大小 默认为40
|
||||||
|
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
|
||||||
|
// KAPTCHA_SESSION_KEY
|
||||||
|
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
|
||||||
|
// 验证码文本字符长度 默认为5
|
||||||
|
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
|
||||||
|
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
|
||||||
|
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
|
||||||
|
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
|
||||||
|
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
|
||||||
|
Config config = new Config(properties);
|
||||||
|
defaultKaptcha.setConfig(config);
|
||||||
|
return defaultKaptcha;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean(name = "captchaProducerMath")
|
||||||
|
public DefaultKaptcha getKaptchaBeanMath()
|
||||||
|
{
|
||||||
|
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
|
||||||
|
Properties properties = new Properties();
|
||||||
|
// 是否有边框 默认为true 我们可以自己设置yes,no
|
||||||
|
properties.setProperty(KAPTCHA_BORDER, "yes");
|
||||||
|
// 边框颜色 默认为Color.BLACK
|
||||||
|
properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
|
||||||
|
// 验证码文本字符颜色 默认为Color.BLACK
|
||||||
|
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
|
||||||
|
// 验证码图片宽度 默认为200
|
||||||
|
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
|
||||||
|
// 验证码图片高度 默认为50
|
||||||
|
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
|
||||||
|
// 验证码文本字符大小 默认为40
|
||||||
|
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");
|
||||||
|
// KAPTCHA_SESSION_KEY
|
||||||
|
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
|
||||||
|
// 验证码文本生成器
|
||||||
|
properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.basepro.framework.config.KaptchaTextCreator");
|
||||||
|
// 验证码文本字符间距 默认为2
|
||||||
|
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
|
||||||
|
// 验证码文本字符长度 默认为5
|
||||||
|
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
|
||||||
|
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
|
||||||
|
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
|
||||||
|
// 验证码噪点颜色 默认为Color.BLACK
|
||||||
|
properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
|
||||||
|
// 干扰实现类
|
||||||
|
properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
|
||||||
|
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
|
||||||
|
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
|
||||||
|
Config config = new Config(properties);
|
||||||
|
defaultKaptcha.setConfig(config);
|
||||||
|
return defaultKaptcha;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
package com.basepro.framework.config;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.servlet.Filter;
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.ServletResponse;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import guo.ping.e3mall.common.enums.DataSourceType;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Primary;
|
||||||
|
import com.alibaba.druid.pool.DruidDataSource;
|
||||||
|
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
|
||||||
|
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
|
||||||
|
import com.alibaba.druid.util.Utils;
|
||||||
|
import com.basepro.framework.config.properties.DruidProperties;
|
||||||
|
import com.basepro.framework.datasource.DynamicDataSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* druid 配置多数据源
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class DruidConfig
|
||||||
|
{
|
||||||
|
@Bean
|
||||||
|
@ConfigurationProperties("spring.datasource.druid.master")
|
||||||
|
public DataSource masterDataSource(DruidProperties druidProperties)
|
||||||
|
{
|
||||||
|
DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
|
||||||
|
return druidProperties.dataSource(dataSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConfigurationProperties("spring.datasource.druid.slave")
|
||||||
|
@ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true")
|
||||||
|
public DataSource slaveDataSource(DruidProperties druidProperties)
|
||||||
|
{
|
||||||
|
DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
|
||||||
|
return druidProperties.dataSource(dataSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean(name = "dynamicDataSource")
|
||||||
|
@Primary
|
||||||
|
public DynamicDataSource dataSource(DataSource masterDataSource, DataSource slaveDataSource)
|
||||||
|
{
|
||||||
|
Map<Object, Object> targetDataSources = new HashMap<>();
|
||||||
|
targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
|
||||||
|
targetDataSources.put(DataSourceType.SLAVE.name(), slaveDataSource);
|
||||||
|
return new DynamicDataSource(masterDataSource, targetDataSources);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 去除监控页面底部的广告
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true")
|
||||||
|
public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties)
|
||||||
|
{
|
||||||
|
// 获取web监控页面的参数
|
||||||
|
DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
|
||||||
|
// 提取common.js的配置路径
|
||||||
|
String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
|
||||||
|
String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
|
||||||
|
final String filePath = "support/http/resources/js/common.js";
|
||||||
|
// 创建filter进行过滤
|
||||||
|
Filter filter = new Filter()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void init(javax.servlet.FilterConfig filterConfig) throws ServletException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||||
|
throws IOException, ServletException
|
||||||
|
{
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
// 重置缓冲区,响应头不会被重置
|
||||||
|
response.resetBuffer();
|
||||||
|
// 获取common.js
|
||||||
|
String text = Utils.readFromResource(filePath);
|
||||||
|
// 正则替换banner, 除去底部的广告信息
|
||||||
|
text = text.replaceAll("<a.*?banner\"></a><br/>", "");
|
||||||
|
text = text.replaceAll("powered.*?shrek.wang</a>", "");
|
||||||
|
response.getWriter().write(text);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void destroy()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
|
||||||
|
registrationBean.setFilter(filter);
|
||||||
|
registrationBean.addUrlPatterns(commonJsPattern);
|
||||||
|
return registrationBean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.basepro.framework.config;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.servlet.DispatcherType;
|
||||||
|
|
||||||
|
import guo.ping.e3mall.common.utils.StringUtils;
|
||||||
|
import guo.ping.e3mall.common.xss.XssFilter;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter配置
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class FilterConfig
|
||||||
|
{
|
||||||
|
@Value("${xss.enabled}")
|
||||||
|
private String enabled;
|
||||||
|
|
||||||
|
@Value("${xss.excludes}")
|
||||||
|
private String excludes;
|
||||||
|
|
||||||
|
@Value("${xss.urlPatterns}")
|
||||||
|
private String urlPatterns;
|
||||||
|
|
||||||
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
|
@Bean
|
||||||
|
public FilterRegistrationBean xssFilterRegistration()
|
||||||
|
{
|
||||||
|
FilterRegistrationBean registration = new FilterRegistrationBean();
|
||||||
|
registration.setDispatcherTypes(DispatcherType.REQUEST);
|
||||||
|
registration.setFilter(new XssFilter());
|
||||||
|
registration.addUrlPatterns(StringUtils.split(urlPatterns, ","));
|
||||||
|
registration.setName("xssFilter");
|
||||||
|
registration.setOrder(Integer.MAX_VALUE);
|
||||||
|
Map<String, String> initParameters = new HashMap<String, String>();
|
||||||
|
initParameters.put("excludes", excludes);
|
||||||
|
initParameters.put("enabled", enabled);
|
||||||
|
registration.setInitParameters(initParameters);
|
||||||
|
return registration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.basepro.framework.config;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.LocaleResolver;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
|
||||||
|
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源文件配置加载
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class I18nConfig implements WebMvcConfigurer
|
||||||
|
{
|
||||||
|
@Bean
|
||||||
|
public LocaleResolver localeResolver()
|
||||||
|
{
|
||||||
|
SessionLocaleResolver slr = new SessionLocaleResolver();
|
||||||
|
// 默认语言
|
||||||
|
slr.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
|
||||||
|
return slr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public LocaleChangeInterceptor localeChangeInterceptor()
|
||||||
|
{
|
||||||
|
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
|
||||||
|
// 参数名
|
||||||
|
lci.setParamName("lang");
|
||||||
|
return lci;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addInterceptors(InterceptorRegistry registry)
|
||||||
|
{
|
||||||
|
registry.addInterceptor(localeChangeInterceptor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
package com.basepro.framework.config;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.Random;
|
||||||
|
import com.google.code.kaptcha.text.impl.DefaultTextCreator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码文本生成器
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class KaptchaTextCreator extends DefaultTextCreator
|
||||||
|
{
|
||||||
|
private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getText()
|
||||||
|
{
|
||||||
|
Integer result = 0;
|
||||||
|
Random random = new SecureRandom();
|
||||||
|
int x = random.nextInt(10);
|
||||||
|
int y = random.nextInt(10);
|
||||||
|
StringBuilder suChinese = new StringBuilder();
|
||||||
|
int randomoperands = (int) Math.round(Math.random() * 2);
|
||||||
|
if (randomoperands == 0)
|
||||||
|
{
|
||||||
|
result = x * y;
|
||||||
|
suChinese.append(CNUMBERS[x]);
|
||||||
|
suChinese.append("*");
|
||||||
|
suChinese.append(CNUMBERS[y]);
|
||||||
|
}
|
||||||
|
else if (randomoperands == 1)
|
||||||
|
{
|
||||||
|
if (!(x == 0) && y % x == 0)
|
||||||
|
{
|
||||||
|
result = y / x;
|
||||||
|
suChinese.append(CNUMBERS[y]);
|
||||||
|
suChinese.append("/");
|
||||||
|
suChinese.append(CNUMBERS[x]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = x + y;
|
||||||
|
suChinese.append(CNUMBERS[x]);
|
||||||
|
suChinese.append("+");
|
||||||
|
suChinese.append(CNUMBERS[y]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (randomoperands == 2)
|
||||||
|
{
|
||||||
|
if (x >= y)
|
||||||
|
{
|
||||||
|
result = x - y;
|
||||||
|
suChinese.append(CNUMBERS[x]);
|
||||||
|
suChinese.append("-");
|
||||||
|
suChinese.append(CNUMBERS[y]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = y - x;
|
||||||
|
suChinese.append(CNUMBERS[y]);
|
||||||
|
suChinese.append("-");
|
||||||
|
suChinese.append(CNUMBERS[x]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = x + y;
|
||||||
|
suChinese.append(CNUMBERS[x]);
|
||||||
|
suChinese.append("+");
|
||||||
|
suChinese.append(CNUMBERS[y]);
|
||||||
|
}
|
||||||
|
suChinese.append("=?@" + result);
|
||||||
|
return suChinese.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
package com.basepro.framework.config;
|
||||||
|
|
||||||
|
import org.apache.ibatis.io.VFS;
|
||||||
|
import org.apache.ibatis.session.SqlSessionFactory;
|
||||||
|
import org.mybatis.spring.SqlSessionFactoryBean;
|
||||||
|
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.core.io.DefaultResourceLoader;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||||
|
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||||
|
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
||||||
|
import org.springframework.core.type.classreading.MetadataReader;
|
||||||
|
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mybatis支持*匹配扫描包
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class MyBatisConfig
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private Environment env;
|
||||||
|
|
||||||
|
static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
|
||||||
|
|
||||||
|
public static String setTypeAliasesPackage(String typeAliasesPackage)
|
||||||
|
{
|
||||||
|
ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver();
|
||||||
|
MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
|
||||||
|
List<String> allResult = new ArrayList<String>();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (String aliasesPackage : typeAliasesPackage.split(","))
|
||||||
|
{
|
||||||
|
List<String> result = new ArrayList<String>();
|
||||||
|
aliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
|
||||||
|
+ ClassUtils.convertClassNameToResourcePath(aliasesPackage.trim()) + "/" + DEFAULT_RESOURCE_PATTERN;
|
||||||
|
Resource[] resources = resolver.getResources(aliasesPackage);
|
||||||
|
if (resources != null && resources.length > 0)
|
||||||
|
{
|
||||||
|
MetadataReader metadataReader = null;
|
||||||
|
for (Resource resource : resources)
|
||||||
|
{
|
||||||
|
if (resource.isReadable())
|
||||||
|
{
|
||||||
|
metadataReader = metadataReaderFactory.getMetadataReader(resource);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName());
|
||||||
|
}
|
||||||
|
catch (ClassNotFoundException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result.size() > 0)
|
||||||
|
{
|
||||||
|
HashSet<String> hashResult = new HashSet<String>(result);
|
||||||
|
allResult.addAll(hashResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allResult.size() > 0)
|
||||||
|
{
|
||||||
|
typeAliasesPackage = String.join(",", (String[]) allResult.toArray(new String[0]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new RuntimeException("mybatis typeAliasesPackage 路径扫描错误,参数typeAliasesPackage:" + typeAliasesPackage + "未找到任何包");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return typeAliasesPackage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception
|
||||||
|
{
|
||||||
|
String typeAliasesPackage = env.getProperty("mybatis.typeAliasesPackage");
|
||||||
|
String mapperLocations = env.getProperty("mybatis.mapperLocations");
|
||||||
|
String configLocation = env.getProperty("mybatis.configLocation");
|
||||||
|
typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
|
||||||
|
VFS.addImplClass(SpringBootVFS.class);
|
||||||
|
|
||||||
|
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
|
||||||
|
sessionFactory.setDataSource(dataSource);
|
||||||
|
sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
|
||||||
|
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
|
||||||
|
sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
|
||||||
|
return sessionFactory.getObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
package com.basepro.framework.config;
|
||||||
|
|
||||||
|
import guo.ping.e3mall.common.config.Global;
|
||||||
|
import guo.ping.e3mall.common.constant.Constants;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
import com.basepro.framework.interceptor.RepeatSubmitInterceptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用配置
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class ResourcesConfig implements WebMvcConfigurer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 首页地址
|
||||||
|
*/
|
||||||
|
@Value("${shiro.user.indexUrl}")
|
||||||
|
private String indexUrl;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RepeatSubmitInterceptor repeatSubmitInterceptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认首页的设置,当输入域名是可以自动跳转到默认指定的网页
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void addViewControllers(ViewControllerRegistry registry)
|
||||||
|
{
|
||||||
|
registry.addViewController("/").setViewName("forward:" + indexUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addResourceHandlers(ResourceHandlerRegistry registry)
|
||||||
|
{
|
||||||
|
/** 本地文件上传路径 */
|
||||||
|
registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**").addResourceLocations("file:" + Global.getProfile() + "/");
|
||||||
|
|
||||||
|
/** swagger配置 */
|
||||||
|
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
|
||||||
|
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义拦截规则
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void addInterceptors(InterceptorRegistry registry)
|
||||||
|
{
|
||||||
|
registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
package com.basepro.framework.config.properties;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import com.alibaba.druid.pool.DruidDataSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* druid 配置属性
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class DruidProperties
|
||||||
|
{
|
||||||
|
@Value("${spring.datasource.druid.initialSize}")
|
||||||
|
private int initialSize;
|
||||||
|
|
||||||
|
@Value("${spring.datasource.druid.minIdle}")
|
||||||
|
private int minIdle;
|
||||||
|
|
||||||
|
@Value("${spring.datasource.druid.maxActive}")
|
||||||
|
private int maxActive;
|
||||||
|
|
||||||
|
@Value("${spring.datasource.druid.maxWait}")
|
||||||
|
private int maxWait;
|
||||||
|
|
||||||
|
@Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}")
|
||||||
|
private int timeBetweenEvictionRunsMillis;
|
||||||
|
|
||||||
|
@Value("${spring.datasource.druid.minEvictableIdleTimeMillis}")
|
||||||
|
private int minEvictableIdleTimeMillis;
|
||||||
|
|
||||||
|
@Value("${spring.datasource.druid.maxEvictableIdleTimeMillis}")
|
||||||
|
private int maxEvictableIdleTimeMillis;
|
||||||
|
|
||||||
|
@Value("${spring.datasource.druid.validationQuery}")
|
||||||
|
private String validationQuery;
|
||||||
|
|
||||||
|
@Value("${spring.datasource.druid.testWhileIdle}")
|
||||||
|
private boolean testWhileIdle;
|
||||||
|
|
||||||
|
@Value("${spring.datasource.druid.testOnBorrow}")
|
||||||
|
private boolean testOnBorrow;
|
||||||
|
|
||||||
|
@Value("${spring.datasource.druid.testOnReturn}")
|
||||||
|
private boolean testOnReturn;
|
||||||
|
|
||||||
|
public DruidDataSource dataSource(DruidDataSource datasource)
|
||||||
|
{
|
||||||
|
/** 配置初始化大小、最小、最大 */
|
||||||
|
datasource.setInitialSize(initialSize);
|
||||||
|
datasource.setMaxActive(maxActive);
|
||||||
|
datasource.setMinIdle(minIdle);
|
||||||
|
|
||||||
|
/** 配置获取连接等待超时的时间 */
|
||||||
|
datasource.setMaxWait(maxWait);
|
||||||
|
|
||||||
|
/** 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 */
|
||||||
|
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
|
||||||
|
|
||||||
|
/** 配置一个连接在池中最小、最大生存的时间,单位是毫秒 */
|
||||||
|
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
|
||||||
|
datasource.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。
|
||||||
|
*/
|
||||||
|
datasource.setValidationQuery(validationQuery);
|
||||||
|
/** 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 */
|
||||||
|
datasource.setTestWhileIdle(testWhileIdle);
|
||||||
|
/** 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */
|
||||||
|
datasource.setTestOnBorrow(testOnBorrow);
|
||||||
|
/** 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */
|
||||||
|
datasource.setTestOnReturn(testOnReturn);
|
||||||
|
return datasource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.basepro.framework.datasource;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
import guo.ping.e3mall.common.config.DynamicDataSourceContextHolder;
|
||||||
|
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动态数据源
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class DynamicDataSource extends AbstractRoutingDataSource
|
||||||
|
{
|
||||||
|
public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources)
|
||||||
|
{
|
||||||
|
super.setDefaultTargetDataSource(defaultTargetDataSource);
|
||||||
|
super.setTargetDataSources(targetDataSources);
|
||||||
|
super.afterPropertiesSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object determineCurrentLookupKey()
|
||||||
|
{
|
||||||
|
return DynamicDataSourceContextHolder.getDataSourceType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
package com.basepro.framework.interceptor;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import guo.ping.e3mall.common.annotation.RepeatSubmit;
|
||||||
|
import guo.ping.e3mall.common.json.JSON;
|
||||||
|
import guo.ping.e3mall.common.pojo.AjaxResult;
|
||||||
|
import guo.ping.e3mall.common.utils.ServletUtils;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.method.HandlerMethod;
|
||||||
|
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 防止重复提交拦截器
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public abstract class RepeatSubmitInterceptor extends HandlerInterceptorAdapter
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
|
||||||
|
{
|
||||||
|
if (handler instanceof HandlerMethod)
|
||||||
|
{
|
||||||
|
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
||||||
|
Method method = handlerMethod.getMethod();
|
||||||
|
RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
|
||||||
|
if (annotation != null)
|
||||||
|
{
|
||||||
|
if (this.isRepeatSubmit(request))
|
||||||
|
{
|
||||||
|
AjaxResult ajaxResult = AjaxResult.error("不允许重复提交,请稍后再试");
|
||||||
|
ServletUtils.renderString(response, JSON.marshal(ajaxResult));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return super.preHandle(request, response, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证是否重复提交由子类实现具体的防重复提交的规则
|
||||||
|
*
|
||||||
|
* @param httpServletRequest
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public abstract boolean isRepeatSubmit(HttpServletRequest request) throws Exception;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
package com.basepro.framework.interceptor.impl;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
|
import guo.ping.e3mall.common.json.JSON;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import com.basepro.framework.interceptor.RepeatSubmitInterceptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断请求url和数据是否和上一次相同,
|
||||||
|
* 如果和上次相同,则是重复提交表单。 有效时间为10秒内。
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
|
||||||
|
{
|
||||||
|
public final String REPEAT_PARAMS = "repeatParams";
|
||||||
|
|
||||||
|
public final String REPEAT_TIME = "repeatTime";
|
||||||
|
|
||||||
|
public final String SESSION_REPEAT_KEY = "repeatData";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 间隔时间,单位:秒 默认10秒
|
||||||
|
*
|
||||||
|
* 两次相同参数的请求,如果间隔时间大于该参数,系统不会认定为重复提交的数据
|
||||||
|
*/
|
||||||
|
private int intervalTime = 10;
|
||||||
|
|
||||||
|
public void setIntervalTime(int intervalTime)
|
||||||
|
{
|
||||||
|
this.intervalTime = intervalTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public boolean isRepeatSubmit(HttpServletRequest request) throws Exception
|
||||||
|
{
|
||||||
|
// 本次参数及系统时间
|
||||||
|
String nowParams = JSON.marshal(request.getParameterMap());
|
||||||
|
Map<String, Object> nowDataMap = new HashMap<String, Object>();
|
||||||
|
nowDataMap.put(REPEAT_PARAMS, nowParams);
|
||||||
|
nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
|
||||||
|
|
||||||
|
// 请求地址(作为存放session的key值)
|
||||||
|
String url = request.getRequestURI();
|
||||||
|
|
||||||
|
HttpSession session = request.getSession();
|
||||||
|
Object sessionObj = session.getAttribute(SESSION_REPEAT_KEY);
|
||||||
|
if (sessionObj != null)
|
||||||
|
{
|
||||||
|
Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
|
||||||
|
if (sessionMap.containsKey(url))
|
||||||
|
{
|
||||||
|
Map<String, Object> preDataMap = (Map<String, Object>) sessionMap.get(url);
|
||||||
|
if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Map<String, Object> sessionMap = new HashMap<String, Object>();
|
||||||
|
sessionMap.put(url, nowDataMap);
|
||||||
|
session.setAttribute(SESSION_REPEAT_KEY, sessionMap);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断参数是否相同
|
||||||
|
*/
|
||||||
|
private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap)
|
||||||
|
{
|
||||||
|
String nowParams = (String) nowMap.get(REPEAT_PARAMS);
|
||||||
|
String preParams = (String) preMap.get(REPEAT_PARAMS);
|
||||||
|
return nowParams.equals(preParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断两次间隔时间
|
||||||
|
*/
|
||||||
|
private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap)
|
||||||
|
{
|
||||||
|
long time1 = (Long) nowMap.get(REPEAT_TIME);
|
||||||
|
long time2 = (Long) preMap.get(REPEAT_TIME);
|
||||||
|
if ((time1 - time2) < (this.intervalTime * 1000))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
package com.basepro.framework.manager;
|
||||||
|
|
||||||
|
import java.util.TimerTask;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import guo.ping.e3mall.common.utils.SpringUtils;
|
||||||
|
import guo.ping.e3mall.common.utils.Threads;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步任务管理器
|
||||||
|
*
|
||||||
|
* @author liuhulu
|
||||||
|
*/
|
||||||
|
public class AsyncManager
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 操作延迟10毫秒
|
||||||
|
*/
|
||||||
|
private final int OPERATE_DELAY_TIME = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步操作任务调度线程池
|
||||||
|
*/
|
||||||
|
private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单例模式
|
||||||
|
*/
|
||||||
|
private AsyncManager(){}
|
||||||
|
|
||||||
|
private static AsyncManager me = new AsyncManager();
|
||||||
|
|
||||||
|
public static AsyncManager me()
|
||||||
|
{
|
||||||
|
return me;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行任务
|
||||||
|
*
|
||||||
|
* @param task 任务
|
||||||
|
*/
|
||||||
|
public void execute(TimerTask task)
|
||||||
|
{
|
||||||
|
executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 停止任务线程池
|
||||||
|
*/
|
||||||
|
public void shutdown()
|
||||||
|
{
|
||||||
|
Threads.shutdownAndAwaitTermination(executor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
package com.basepro.framework.manager;
|
||||||
|
|
||||||
|
import com.basepro.framework.shiro.web.session.SpringSessionValidationScheduler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import javax.annotation.PreDestroy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确保应用退出时能关闭后台线程
|
||||||
|
*
|
||||||
|
* @author cj
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class ShutdownManager
|
||||||
|
{
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger("sys-user");
|
||||||
|
|
||||||
|
|
||||||
|
private SpringSessionValidationScheduler springSessionValidationScheduler;
|
||||||
|
|
||||||
|
public void setSpringSessionValidationScheduler(SpringSessionValidationScheduler springSessionValidationScheduler) {
|
||||||
|
this.springSessionValidationScheduler = springSessionValidationScheduler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreDestroy
|
||||||
|
public void destroy()
|
||||||
|
{
|
||||||
|
shutdownSpringSessionValidationScheduler();
|
||||||
|
shutdownAsyncManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 停止Seesion会话检查
|
||||||
|
*/
|
||||||
|
private void shutdownSpringSessionValidationScheduler()
|
||||||
|
{
|
||||||
|
if (springSessionValidationScheduler != null && springSessionValidationScheduler.isEnabled())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
logger.info("====关闭会话验证任务====");
|
||||||
|
springSessionValidationScheduler.disableSessionValidation();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 停止异步执行任务
|
||||||
|
*/
|
||||||
|
private void shutdownAsyncManager()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
logger.info("====关闭后台任务任务线程池====");
|
||||||
|
AsyncManager.me().shutdown();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,136 @@
|
||||||
|
package com.basepro.framework.manager.factory;
|
||||||
|
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
import basepro.manager.pojo.SysLogininfor;
|
||||||
|
import basepro.manager.pojo.SysOperLog;
|
||||||
|
import basepro.manager.pojo.SysUserOnline;
|
||||||
|
import basepro.manager.service.ISysOperLogService;
|
||||||
|
import basepro.manager.service.ISysUserOnlineService;
|
||||||
|
import basepro.manager.service.impl.SysLogininforServiceImpl;
|
||||||
|
import guo.ping.e3mall.common.constant.Constants;
|
||||||
|
import guo.ping.e3mall.common.utils.AddressUtils;
|
||||||
|
import guo.ping.e3mall.common.utils.ServletUtils;
|
||||||
|
import guo.ping.e3mall.common.utils.SpringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import com.basepro.framework.shiro.session.OnlineSession;
|
||||||
|
import com.basepro.framework.util.LogUtils;
|
||||||
|
import com.basepro.framework.util.ShiroUtils;
|
||||||
|
import eu.bitwalker.useragentutils.UserAgent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步工厂(产生任务用)
|
||||||
|
*
|
||||||
|
* @author liuhulu
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class AsyncFactory
|
||||||
|
{
|
||||||
|
private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步session到数据库
|
||||||
|
*
|
||||||
|
* @param session 在线用户会话
|
||||||
|
* @return 任务task
|
||||||
|
*/
|
||||||
|
public static TimerTask syncSessionToDb(final OnlineSession session)
|
||||||
|
{
|
||||||
|
return new TimerTask()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
SysUserOnline online = new SysUserOnline();
|
||||||
|
online.setSessionId(String.valueOf(session.getId()));
|
||||||
|
online.setDeptName(session.getDeptName());
|
||||||
|
online.setLoginName(session.getLoginName());
|
||||||
|
online.setStartTimestamp(session.getStartTimestamp());
|
||||||
|
online.setLastAccessTime(session.getLastAccessTime());
|
||||||
|
online.setExpireTime(session.getTimeout());
|
||||||
|
online.setIpaddr(session.getHost());
|
||||||
|
online.setLoginLocation(AddressUtils.getRealAddressByIP(session.getHost()));
|
||||||
|
online.setBrowser(session.getBrowser());
|
||||||
|
online.setOs(session.getOs());
|
||||||
|
online.setStatus(session.getStatus());
|
||||||
|
SpringUtils.getBean(ISysUserOnlineService.class).saveOnline(online);
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作日志记录
|
||||||
|
*
|
||||||
|
* @param operLog 操作日志信息
|
||||||
|
* @return 任务task
|
||||||
|
*/
|
||||||
|
public static TimerTask recordOper(final SysOperLog operLog)
|
||||||
|
{
|
||||||
|
return new TimerTask()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
// 远程查询操作地点
|
||||||
|
operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
|
||||||
|
SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录登陆信息
|
||||||
|
*
|
||||||
|
* @param username 用户名
|
||||||
|
* @param status 状态
|
||||||
|
* @param message 消息
|
||||||
|
* @param args 列表
|
||||||
|
* @return 任务task
|
||||||
|
*/
|
||||||
|
public static TimerTask recordLogininfor(final String username, final String status, final String message, final Object... args)
|
||||||
|
{
|
||||||
|
final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
|
||||||
|
//final String ip = ShiroUtils.getIp();
|
||||||
|
return new TimerTask()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
//String address = AddressUtils.getRealAddressByIP(ip);
|
||||||
|
StringBuilder s = new StringBuilder();
|
||||||
|
//s.append(LogUtils.getBlock(ip));
|
||||||
|
// s.append(address);
|
||||||
|
s.append(LogUtils.getBlock(username));
|
||||||
|
s.append(LogUtils.getBlock(status));
|
||||||
|
s.append(LogUtils.getBlock(message));
|
||||||
|
// 打印信息到日志
|
||||||
|
sys_user_logger.info(s.toString(), args);
|
||||||
|
// 获取客户端操作系统
|
||||||
|
String os = userAgent.getOperatingSystem().getName();
|
||||||
|
// 获取客户端浏览器
|
||||||
|
String browser = userAgent.getBrowser().getName();
|
||||||
|
// 封装对象
|
||||||
|
SysLogininfor logininfor = new SysLogininfor();
|
||||||
|
logininfor.setLoginName(username);
|
||||||
|
//logininfor.setIpaddr(ip);
|
||||||
|
//logininfor.setLoginLocation(address);
|
||||||
|
logininfor.setBrowser(browser);
|
||||||
|
logininfor.setOs(os);
|
||||||
|
logininfor.setMsg(message);
|
||||||
|
// 日志状态
|
||||||
|
if (Constants.LOGIN_SUCCESS.equals(status) || Constants.LOGOUT.equals(status))
|
||||||
|
{
|
||||||
|
logininfor.setStatus(Constants.SUCCESS);
|
||||||
|
}
|
||||||
|
else if (Constants.LOGIN_FAIL.equals(status))
|
||||||
|
{
|
||||||
|
logininfor.setStatus(Constants.FAIL);
|
||||||
|
}
|
||||||
|
// 插入数据
|
||||||
|
SpringUtils.getBean(SysLogininforServiceImpl.class).insertLogininfor(logininfor);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
package com.basepro.framework.shiro.service;
|
||||||
|
|
||||||
|
import basepro.manager.pojo.SysUser;
|
||||||
|
import basepro.manager.service.ISysUserOnlineService;
|
||||||
|
import basepro.manager.service.ISysUserService;
|
||||||
|
import guo.ping.e3mall.common.constant.Constants;
|
||||||
|
import guo.ping.e3mall.common.constant.ShiroConstants;
|
||||||
|
import guo.ping.e3mall.common.constant.UserConstants;
|
||||||
|
import guo.ping.e3mall.common.enums.UserStatus;
|
||||||
|
import guo.ping.e3mall.common.exception.user.*;
|
||||||
|
import guo.ping.e3mall.common.utils.DateUtils;
|
||||||
|
import guo.ping.e3mall.common.utils.MessageUtils;
|
||||||
|
import guo.ping.e3mall.common.utils.ServletUtils;
|
||||||
|
import guo.ping.e3mall.common.utils.SpringUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import com.basepro.framework.manager.AsyncManager;
|
||||||
|
import com.basepro.framework.manager.factory.AsyncFactory;
|
||||||
|
import com.basepro.framework.util.ShiroUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录校验方法
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class SysLoginService
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private SysPasswordService passwordService;
|
||||||
|
|
||||||
|
/* @Autowired
|
||||||
|
private ISysUserService userService;*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录
|
||||||
|
*/
|
||||||
|
public SysUser login(String username, String password)
|
||||||
|
{
|
||||||
|
// 验证码校验
|
||||||
|
if (!StringUtils.isEmpty(ServletUtils.getRequest().getAttribute(ShiroConstants.CURRENT_CAPTCHA)))
|
||||||
|
{
|
||||||
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
|
||||||
|
throw new CaptchaException();
|
||||||
|
}
|
||||||
|
// 用户名或密码为空 错误
|
||||||
|
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))
|
||||||
|
{
|
||||||
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
|
||||||
|
throw new UserNotExistsException();
|
||||||
|
}
|
||||||
|
// 密码如果不在指定范围内 错误
|
||||||
|
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|
||||||
|
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH)
|
||||||
|
{
|
||||||
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
|
||||||
|
throw new UserPasswordNotMatchException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户名不在指定范围内 错误
|
||||||
|
if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|
||||||
|
|| username.length() > UserConstants.USERNAME_MAX_LENGTH)
|
||||||
|
{
|
||||||
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
|
||||||
|
throw new UserPasswordNotMatchException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询用户信息
|
||||||
|
SysUser user = SpringUtils.getBean(ISysUserService.class).selectUserByLoginName(username);
|
||||||
|
|
||||||
|
if (user == null && maybeMobilePhoneNumber(username))
|
||||||
|
{
|
||||||
|
user = SpringUtils.getBean(ISysUserService.class).selectUserByPhoneNumber(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user == null && maybeEmail(username))
|
||||||
|
{
|
||||||
|
user = SpringUtils.getBean(ISysUserService.class).selectUserByEmail(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.not.exists")));
|
||||||
|
throw new UserNotExistsException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
|
||||||
|
{
|
||||||
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.delete")));
|
||||||
|
throw new UserDeleteException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
|
||||||
|
{
|
||||||
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.blocked", user.getRemark())));
|
||||||
|
throw new UserBlockedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
passwordService.validate(user, password);
|
||||||
|
|
||||||
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
|
||||||
|
recordLoginInfo(user);
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean maybeEmail(String username)
|
||||||
|
{
|
||||||
|
if (!username.matches(UserConstants.EMAIL_PATTERN))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean maybeMobilePhoneNumber(String username)
|
||||||
|
{
|
||||||
|
if (!username.matches(UserConstants.MOBILE_PHONE_NUMBER_PATTERN))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录登录信息
|
||||||
|
*/
|
||||||
|
public void recordLoginInfo(SysUser user)
|
||||||
|
{
|
||||||
|
user.setLoginIp(ShiroUtils.getIp());
|
||||||
|
user.setLoginDate(DateUtils.getNowDate());
|
||||||
|
SpringUtils.getBean(ISysUserService.class).updateUserInfo(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
package com.basepro.framework.shiro.service;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
|
||||||
|
import basepro.manager.pojo.SysUser;
|
||||||
|
import guo.ping.e3mall.common.constant.Constants;
|
||||||
|
import guo.ping.e3mall.common.constant.ShiroConstants;
|
||||||
|
import guo.ping.e3mall.common.exception.user.*;
|
||||||
|
import guo.ping.e3mall.common.utils.MessageUtils;
|
||||||
|
import org.apache.shiro.cache.Cache;
|
||||||
|
import org.apache.shiro.cache.CacheManager;
|
||||||
|
import org.apache.shiro.crypto.hash.Md5Hash;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import com.basepro.framework.manager.AsyncManager;
|
||||||
|
import com.basepro.framework.manager.factory.AsyncFactory;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录密码方法
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class SysPasswordService
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private CacheManager cacheManager;
|
||||||
|
|
||||||
|
private Cache<String, AtomicInteger> loginRecordCache;
|
||||||
|
|
||||||
|
@Value(value = "5")
|
||||||
|
private String maxRetryCount;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
loginRecordCache = cacheManager.getCache(ShiroConstants.LOGINRECORDCACHE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validate(SysUser user, String password)
|
||||||
|
{
|
||||||
|
String loginName = user.getLoginName();
|
||||||
|
|
||||||
|
AtomicInteger retryCount = loginRecordCache.get(loginName);
|
||||||
|
|
||||||
|
if (retryCount == null)
|
||||||
|
{
|
||||||
|
retryCount = new AtomicInteger(0);
|
||||||
|
loginRecordCache.put(loginName, retryCount);
|
||||||
|
}
|
||||||
|
if (retryCount.incrementAndGet() > Integer.valueOf(maxRetryCount).intValue())
|
||||||
|
{
|
||||||
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginName, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.exceed", maxRetryCount)));
|
||||||
|
throw new UserPasswordRetryLimitExceedException(Integer.valueOf(maxRetryCount).intValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!matches(user, password))
|
||||||
|
{
|
||||||
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginName, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.count", retryCount)));
|
||||||
|
loginRecordCache.put(loginName, retryCount);
|
||||||
|
throw new UserPasswordNotMatchException();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clearLoginRecordCache(loginName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean matches(SysUser user, String newPassword)
|
||||||
|
{
|
||||||
|
return user.getPassword().equals(encryptPassword(user.getLoginName(), newPassword, user.getSalt()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearLoginRecordCache(String username)
|
||||||
|
{
|
||||||
|
loginRecordCache.remove(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String encryptPassword(String username, String password, String salt)
|
||||||
|
{
|
||||||
|
return new Md5Hash(username + password + salt).toHex().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unlock(String loginName){
|
||||||
|
loginRecordCache.remove(loginName);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
package com.basepro.framework.shiro.service;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import basepro.manager.pojo.SysUserOnline;
|
||||||
|
import basepro.manager.service.ISysUserOnlineService;
|
||||||
|
import guo.ping.e3mall.common.utils.StringUtils;
|
||||||
|
import org.apache.shiro.session.Session;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import com.basepro.framework.shiro.session.OnlineSession;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会话db操作处理
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class SysShiroService
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private ISysUserOnlineService onlineService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除会话
|
||||||
|
*
|
||||||
|
* @param onlineSession 会话信息
|
||||||
|
*/
|
||||||
|
public void deleteSession(OnlineSession onlineSession)
|
||||||
|
{
|
||||||
|
onlineService.deleteOnlineById(String.valueOf(onlineSession.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取会话信息
|
||||||
|
*
|
||||||
|
* @param sessionId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Session getSession(Serializable sessionId)
|
||||||
|
{
|
||||||
|
SysUserOnline userOnline = onlineService.selectOnlineById(String.valueOf(sessionId));
|
||||||
|
return StringUtils.isNull(userOnline) ? null : createSession(userOnline);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Session createSession(SysUserOnline userOnline)
|
||||||
|
{
|
||||||
|
OnlineSession onlineSession = new OnlineSession();
|
||||||
|
if (StringUtils.isNotNull(userOnline))
|
||||||
|
{
|
||||||
|
onlineSession.setId(userOnline.getSessionId());
|
||||||
|
onlineSession.setHost(userOnline.getIpaddr());
|
||||||
|
onlineSession.setBrowser(userOnline.getBrowser());
|
||||||
|
onlineSession.setOs(userOnline.getOs());
|
||||||
|
onlineSession.setDeptName(userOnline.getDeptName());
|
||||||
|
onlineSession.setLoginName(userOnline.getLoginName());
|
||||||
|
onlineSession.setStartTimestamp(userOnline.getStartTimestamp());
|
||||||
|
onlineSession.setLastAccessTime(userOnline.getLastAccessTime());
|
||||||
|
onlineSession.setTimeout(userOnline.getExpireTime());
|
||||||
|
}
|
||||||
|
return onlineSession;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,148 @@
|
||||||
|
package com.basepro.framework.shiro.session;
|
||||||
|
|
||||||
|
import guo.ping.e3mall.common.enums.OnlineStatus;
|
||||||
|
import org.apache.shiro.session.mgt.SimpleSession;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在线用户会话属性
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class OnlineSession extends SimpleSession
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 用户ID */
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/** 用户名称 */
|
||||||
|
private String loginName;
|
||||||
|
|
||||||
|
/** 部门名称 */
|
||||||
|
private String deptName;
|
||||||
|
|
||||||
|
/** 用户头像 */
|
||||||
|
private String avatar;
|
||||||
|
|
||||||
|
/** 登录IP地址 */
|
||||||
|
private String host;
|
||||||
|
|
||||||
|
/** 浏览器类型 */
|
||||||
|
private String browser;
|
||||||
|
|
||||||
|
/** 操作系统 */
|
||||||
|
private String os;
|
||||||
|
|
||||||
|
/** 在线状态 */
|
||||||
|
private OnlineStatus status = OnlineStatus.on_line;
|
||||||
|
|
||||||
|
/** 属性是否改变 优化session数据同步 */
|
||||||
|
private transient boolean attributeChanged = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHost()
|
||||||
|
{
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHost(String host)
|
||||||
|
{
|
||||||
|
this.host = host;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBrowser()
|
||||||
|
{
|
||||||
|
return browser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBrowser(String browser)
|
||||||
|
{
|
||||||
|
this.browser = browser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOs()
|
||||||
|
{
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOs(String os)
|
||||||
|
{
|
||||||
|
this.os = os;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getUserId()
|
||||||
|
{
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(Long userId)
|
||||||
|
{
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLoginName()
|
||||||
|
{
|
||||||
|
return loginName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoginName(String loginName)
|
||||||
|
{
|
||||||
|
this.loginName = loginName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeptName()
|
||||||
|
{
|
||||||
|
return deptName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeptName(String deptName)
|
||||||
|
{
|
||||||
|
this.deptName = deptName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OnlineStatus getStatus()
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(OnlineStatus status)
|
||||||
|
{
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void markAttributeChanged()
|
||||||
|
{
|
||||||
|
this.attributeChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetAttributeChanged()
|
||||||
|
{
|
||||||
|
this.attributeChanged = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAttributeChanged()
|
||||||
|
{
|
||||||
|
return attributeChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAvatar() {
|
||||||
|
return avatar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAvatar(String avatar) {
|
||||||
|
this.avatar = avatar;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAttribute(Object key, Object value)
|
||||||
|
{
|
||||||
|
super.setAttribute(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object removeAttribute(Object key)
|
||||||
|
{
|
||||||
|
return super.removeAttribute(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
package com.basepro.framework.shiro.session;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import guo.ping.e3mall.common.enums.OnlineStatus;
|
||||||
|
import org.apache.shiro.session.Session;
|
||||||
|
import org.apache.shiro.session.UnknownSessionException;
|
||||||
|
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import com.basepro.framework.manager.AsyncManager;
|
||||||
|
import com.basepro.framework.manager.factory.AsyncFactory;
|
||||||
|
import com.basepro.framework.shiro.service.SysShiroService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 针对自定义的ShiroSession的db操作
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class OnlineSessionDAO extends EnterpriseCacheSessionDAO
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 同步session到数据库的周期 单位为毫秒(默认1分钟)
|
||||||
|
*/
|
||||||
|
@Value("${shiro.session.dbSyncPeriod}")
|
||||||
|
private int dbSyncPeriod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上次同步数据库的时间戳
|
||||||
|
*/
|
||||||
|
private static final String LAST_SYNC_DB_TIMESTAMP = OnlineSessionDAO.class.getName() + "LAST_SYNC_DB_TIMESTAMP";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SysShiroService sysShiroService;
|
||||||
|
|
||||||
|
public OnlineSessionDAO()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public OnlineSessionDAO(long expireTime)
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据会话ID获取会话
|
||||||
|
*
|
||||||
|
* @param sessionId 会话ID
|
||||||
|
* @return ShiroSession
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Session doReadSession(Serializable sessionId)
|
||||||
|
{
|
||||||
|
return sysShiroService.getSession(sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(Session session) throws UnknownSessionException
|
||||||
|
{
|
||||||
|
super.update(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新会话;如更新会话最后访问时间/停止会话/设置超时时间/设置移除属性等会调用
|
||||||
|
*/
|
||||||
|
public void syncToDb(OnlineSession onlineSession)
|
||||||
|
{
|
||||||
|
Date lastSyncTimestamp = (Date) onlineSession.getAttribute(LAST_SYNC_DB_TIMESTAMP);
|
||||||
|
if (lastSyncTimestamp != null)
|
||||||
|
{
|
||||||
|
boolean needSync = true;
|
||||||
|
long deltaTime = onlineSession.getLastAccessTime().getTime() - lastSyncTimestamp.getTime();
|
||||||
|
if (deltaTime < dbSyncPeriod * 60 * 1000)
|
||||||
|
{
|
||||||
|
// 时间差不足 无需同步
|
||||||
|
needSync = false;
|
||||||
|
}
|
||||||
|
// isGuest = true 访客
|
||||||
|
boolean isGuest = onlineSession.getUserId() == null || onlineSession.getUserId() == 0L;
|
||||||
|
|
||||||
|
// session 数据变更了 同步
|
||||||
|
if (isGuest == false && onlineSession.isAttributeChanged())
|
||||||
|
{
|
||||||
|
needSync = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needSync == false)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 更新上次同步数据库时间
|
||||||
|
onlineSession.setAttribute(LAST_SYNC_DB_TIMESTAMP, onlineSession.getLastAccessTime());
|
||||||
|
// 更新完后 重置标识
|
||||||
|
if (onlineSession.isAttributeChanged())
|
||||||
|
{
|
||||||
|
onlineSession.resetAttributeChanged();
|
||||||
|
}
|
||||||
|
AsyncManager.me().execute(AsyncFactory.syncSessionToDb(onlineSession));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当会话过期/停止(如用户退出时)属性等会调用
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void doDelete(Session session)
|
||||||
|
{
|
||||||
|
OnlineSession onlineSession = (OnlineSession) session;
|
||||||
|
if (null == onlineSession)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onlineSession.setStatus(OnlineStatus.off_line);
|
||||||
|
sysShiroService.deleteSession(onlineSession);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.basepro.framework.shiro.session;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import guo.ping.e3mall.common.utils.IpUtils;
|
||||||
|
import guo.ping.e3mall.common.utils.ServletUtils;
|
||||||
|
import org.apache.shiro.session.Session;
|
||||||
|
import org.apache.shiro.session.mgt.SessionContext;
|
||||||
|
import org.apache.shiro.session.mgt.SessionFactory;
|
||||||
|
import org.apache.shiro.web.session.mgt.WebSessionContext;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import eu.bitwalker.useragentutils.UserAgent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义sessionFactory会话
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class OnlineSessionFactory implements SessionFactory
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Session createSession(SessionContext initData)
|
||||||
|
{
|
||||||
|
OnlineSession session = new OnlineSession();
|
||||||
|
if (initData != null && initData instanceof WebSessionContext)
|
||||||
|
{
|
||||||
|
WebSessionContext sessionContext = (WebSessionContext) initData;
|
||||||
|
HttpServletRequest request = (HttpServletRequest) sessionContext.getServletRequest();
|
||||||
|
if (request != null)
|
||||||
|
{
|
||||||
|
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
|
||||||
|
// 获取客户端操作系统
|
||||||
|
String os = userAgent.getOperatingSystem().getName();
|
||||||
|
// 获取客户端浏览器
|
||||||
|
String browser = userAgent.getBrowser().getName();
|
||||||
|
session.setHost(IpUtils.getIpAddr(request));
|
||||||
|
session.setBrowser(browser);
|
||||||
|
session.setOs(os);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
package com.basepro.framework.shiro.web.filter;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Deque;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.ServletResponse;
|
||||||
|
|
||||||
|
import basepro.manager.pojo.SysUser;
|
||||||
|
import guo.ping.e3mall.common.constant.Constants;
|
||||||
|
import guo.ping.e3mall.common.constant.ShiroConstants;
|
||||||
|
import guo.ping.e3mall.common.utils.MessageUtils;
|
||||||
|
import guo.ping.e3mall.common.utils.StringUtils;
|
||||||
|
import org.apache.shiro.cache.Cache;
|
||||||
|
import org.apache.shiro.cache.CacheManager;
|
||||||
|
import org.apache.shiro.session.SessionException;
|
||||||
|
import org.apache.shiro.subject.Subject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import com.basepro.framework.manager.AsyncManager;
|
||||||
|
import com.basepro.framework.manager.factory.AsyncFactory;
|
||||||
|
import com.basepro.framework.util.ShiroUtils;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退出过滤器
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(LogoutFilter.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退出后重定向的地址
|
||||||
|
*/
|
||||||
|
private String loginUrl;
|
||||||
|
|
||||||
|
private Cache<String, Deque<Serializable>> cache;
|
||||||
|
|
||||||
|
public String getLoginUrl()
|
||||||
|
{
|
||||||
|
return loginUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoginUrl(String loginUrl)
|
||||||
|
{
|
||||||
|
this.loginUrl = loginUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Subject subject = getSubject(request, response);
|
||||||
|
String redirectUrl = getRedirectUrl(request, response, subject);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SysUser user = ShiroUtils.getSysUser();
|
||||||
|
if (StringUtils.isNotNull(user))
|
||||||
|
{
|
||||||
|
String loginName = user.getLoginName();
|
||||||
|
// 记录用户退出日志
|
||||||
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginName, Constants.LOGOUT, MessageUtils.message("user.logout.success")));
|
||||||
|
// 清理缓存
|
||||||
|
cache.remove(loginName);
|
||||||
|
}
|
||||||
|
// 退出登录
|
||||||
|
subject.logout();
|
||||||
|
}
|
||||||
|
catch (SessionException ise)
|
||||||
|
{
|
||||||
|
log.error("logout fail.", ise);
|
||||||
|
}
|
||||||
|
issueRedirect(request, response, redirectUrl);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.error("Encountered session exception during logout. This can generally safely be ignored.", e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退出跳转URL
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected String getRedirectUrl(ServletRequest request, ServletResponse response, Subject subject)
|
||||||
|
{
|
||||||
|
String url = getLoginUrl();
|
||||||
|
if (StringUtils.isNotEmpty(url))
|
||||||
|
{
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
return super.getRedirectUrl(request, response, subject);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置Cache的key的前缀
|
||||||
|
public void setCacheManager(CacheManager cacheManager)
|
||||||
|
{
|
||||||
|
// 必须和ehcache缓存配置中的缓存name一致
|
||||||
|
this.cache = cacheManager.getCache(ShiroConstants.SYS_USERCACHE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
package com.basepro.framework.shiro.web.filter.captcha;
|
||||||
|
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.ServletResponse;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import guo.ping.e3mall.common.constant.ShiroConstants;
|
||||||
|
import guo.ping.e3mall.common.utils.StringUtils;
|
||||||
|
import org.apache.shiro.web.filter.AccessControlFilter;
|
||||||
|
import com.google.code.kaptcha.Constants;
|
||||||
|
import com.basepro.framework.util.ShiroUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码过滤器
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class CaptchaValidateFilter extends AccessControlFilter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 是否开启验证码
|
||||||
|
*/
|
||||||
|
private boolean captchaEnabled = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码类型
|
||||||
|
*/
|
||||||
|
private String captchaType = "math";
|
||||||
|
|
||||||
|
public void setCaptchaEnabled(boolean captchaEnabled)
|
||||||
|
{
|
||||||
|
this.captchaEnabled = captchaEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCaptchaType(String captchaType)
|
||||||
|
{
|
||||||
|
this.captchaType = captchaType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception
|
||||||
|
{
|
||||||
|
request.setAttribute(ShiroConstants.CURRENT_ENABLED, captchaEnabled);
|
||||||
|
request.setAttribute(ShiroConstants.CURRENT_TYPE, captchaType);
|
||||||
|
return super.onPreHandle(request, response, mappedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
|
||||||
|
// 验证码禁用 或不是表单提交 允许访问
|
||||||
|
if (captchaEnabled == false || !"post".equals(httpServletRequest.getMethod().toLowerCase()))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return validateResponse(httpServletRequest, httpServletRequest.getParameter(ShiroConstants.CURRENT_VALIDATECODE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean validateResponse(HttpServletRequest request, String validateCode)
|
||||||
|
{
|
||||||
|
Object obj = ShiroUtils.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
|
||||||
|
String code = String.valueOf(obj != null ? obj : "");
|
||||||
|
if (StringUtils.isEmpty(validateCode) || !validateCode.equalsIgnoreCase(code))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception
|
||||||
|
{
|
||||||
|
request.setAttribute(ShiroConstants.CURRENT_CAPTCHA, ShiroConstants.CAPTCHA_ERROR);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,188 @@
|
||||||
|
package com.basepro.framework.shiro.web.filter.kickout;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Deque;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.ServletResponse;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import basepro.manager.pojo.SysUser;
|
||||||
|
import guo.ping.e3mall.common.constant.ShiroConstants;
|
||||||
|
import guo.ping.e3mall.common.pojo.AjaxResult;
|
||||||
|
import guo.ping.e3mall.common.utils.ServletUtils;
|
||||||
|
import org.apache.shiro.cache.Cache;
|
||||||
|
import org.apache.shiro.cache.CacheManager;
|
||||||
|
import org.apache.shiro.session.Session;
|
||||||
|
import org.apache.shiro.session.mgt.DefaultSessionKey;
|
||||||
|
import org.apache.shiro.session.mgt.SessionManager;
|
||||||
|
import org.apache.shiro.subject.Subject;
|
||||||
|
import org.apache.shiro.web.filter.AccessControlFilter;
|
||||||
|
import org.apache.shiro.web.util.WebUtils;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.basepro.framework.util.ShiroUtils;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录帐号控制过滤器
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class KickoutSessionFilter extends AccessControlFilter
|
||||||
|
{
|
||||||
|
private final static ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同一个用户最大会话数
|
||||||
|
**/
|
||||||
|
private int maxSession = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 踢出之前登录的/之后登录的用户 默认false踢出之前登录的用户
|
||||||
|
**/
|
||||||
|
private Boolean kickoutAfter = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 踢出后到的地址
|
||||||
|
**/
|
||||||
|
private String kickoutUrl;
|
||||||
|
|
||||||
|
private SessionManager sessionManager;
|
||||||
|
private Cache<String, Deque<Serializable>> cache;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception
|
||||||
|
{
|
||||||
|
Subject subject = getSubject(request, response);
|
||||||
|
if (!subject.isAuthenticated() && !subject.isRemembered() || maxSession == -1)
|
||||||
|
{
|
||||||
|
// 如果没有登录或用户最大会话数为-1,直接进行之后的流程
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Session session = subject.getSession();
|
||||||
|
// 当前登录用户
|
||||||
|
SysUser user = ShiroUtils.getSysUser();
|
||||||
|
String loginName = user.getLoginName();
|
||||||
|
Serializable sessionId = session.getId();
|
||||||
|
|
||||||
|
// 读取缓存用户 没有就存入
|
||||||
|
Deque<Serializable> deque = cache.get(loginName);
|
||||||
|
if (deque == null)
|
||||||
|
{
|
||||||
|
// 初始化队列
|
||||||
|
deque = new ArrayDeque<Serializable>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果队列里没有此sessionId,且用户没有被踢出;放入队列
|
||||||
|
if (!deque.contains(sessionId) && session.getAttribute("kickout") == null)
|
||||||
|
{
|
||||||
|
// 将sessionId存入队列
|
||||||
|
deque.push(sessionId);
|
||||||
|
// 将用户的sessionId队列缓存
|
||||||
|
cache.put(loginName, deque);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果队列里的sessionId数超出最大会话数,开始踢人
|
||||||
|
while (deque.size() > maxSession)
|
||||||
|
{
|
||||||
|
Serializable kickoutSessionId = null;
|
||||||
|
// 是否踢出后来登录的,默认是false;即后者登录的用户踢出前者登录的用户;
|
||||||
|
if (kickoutAfter)
|
||||||
|
{
|
||||||
|
// 踢出后者
|
||||||
|
kickoutSessionId = deque.removeFirst();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 踢出前者
|
||||||
|
kickoutSessionId = deque.removeLast();
|
||||||
|
}
|
||||||
|
// 踢出后再更新下缓存队列
|
||||||
|
cache.put(loginName, deque);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 获取被踢出的sessionId的session对象
|
||||||
|
Session kickoutSession = sessionManager.getSession(new DefaultSessionKey(kickoutSessionId));
|
||||||
|
if (null != kickoutSession)
|
||||||
|
{
|
||||||
|
// 设置会话的kickout属性表示踢出了
|
||||||
|
kickoutSession.setAttribute("kickout", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// 面对异常,我们选择忽略
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果被踢出了,(前者或后者)直接退出,重定向到踢出后的地址
|
||||||
|
if ((Boolean) session.getAttribute("kickout") != null && (Boolean) session.getAttribute("kickout") == true)
|
||||||
|
{
|
||||||
|
// 退出登录
|
||||||
|
subject.logout();
|
||||||
|
saveRequest(request);
|
||||||
|
return isAjaxResponse(request, response);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return isAjaxResponse(request, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isAjaxResponse(ServletRequest request, ServletResponse response) throws IOException
|
||||||
|
{
|
||||||
|
HttpServletRequest req = (HttpServletRequest) request;
|
||||||
|
HttpServletResponse res = (HttpServletResponse) response;
|
||||||
|
if (ServletUtils.isAjaxRequest(req))
|
||||||
|
{
|
||||||
|
AjaxResult ajaxResult = AjaxResult.error("您已在别处登录,请您修改密码或重新登录");
|
||||||
|
ServletUtils.renderString(res, objectMapper.writeValueAsString(ajaxResult));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WebUtils.issueRedirect(request, response, kickoutUrl);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxSession(int maxSession)
|
||||||
|
{
|
||||||
|
this.maxSession = maxSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKickoutAfter(boolean kickoutAfter)
|
||||||
|
{
|
||||||
|
this.kickoutAfter = kickoutAfter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKickoutUrl(String kickoutUrl)
|
||||||
|
{
|
||||||
|
this.kickoutUrl = kickoutUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSessionManager(SessionManager sessionManager)
|
||||||
|
{
|
||||||
|
this.sessionManager = sessionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置Cache的key的前缀
|
||||||
|
public void setCacheManager(CacheManager cacheManager)
|
||||||
|
{
|
||||||
|
// 必须和ehcache缓存配置中的缓存name一致
|
||||||
|
this.cache = cacheManager.getCache(ShiroConstants.SYS_USERCACHE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
package com.basepro.framework.shiro.web.filter.online;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.ServletResponse;
|
||||||
|
|
||||||
|
import basepro.manager.pojo.SysUser;
|
||||||
|
import guo.ping.e3mall.common.constant.ShiroConstants;
|
||||||
|
import guo.ping.e3mall.common.enums.OnlineStatus;
|
||||||
|
import org.apache.shiro.session.Session;
|
||||||
|
import org.apache.shiro.subject.Subject;
|
||||||
|
import org.apache.shiro.web.filter.AccessControlFilter;
|
||||||
|
import org.apache.shiro.web.util.WebUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import com.basepro.framework.shiro.session.OnlineSession;
|
||||||
|
import com.basepro.framework.shiro.session.OnlineSessionDAO;
|
||||||
|
import com.basepro.framework.util.ShiroUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义访问控制
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class OnlineSessionFilter extends AccessControlFilter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 强制退出后重定向的地址
|
||||||
|
*/
|
||||||
|
@Value("${shiro.user.loginUrl}")
|
||||||
|
private String loginUrl;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private OnlineSessionDAO onlineSessionDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表示是否允许访问;mappedValue就是[urls]配置中拦截器参数部分,如果允许访问返回true,否则false;
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
Subject subject = getSubject(request, response);
|
||||||
|
if (subject == null || subject.getSession() == null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Session session = onlineSessionDAO.readSession(subject.getSession().getId());
|
||||||
|
if (session != null && session instanceof OnlineSession)
|
||||||
|
{
|
||||||
|
OnlineSession onlineSession = (OnlineSession) session;
|
||||||
|
request.setAttribute(ShiroConstants.ONLINE_SESSION, onlineSession);
|
||||||
|
// 把user对象设置进去
|
||||||
|
boolean isGuest = onlineSession.getUserId() == null || onlineSession.getUserId() == 0L;
|
||||||
|
if (isGuest == true)
|
||||||
|
{
|
||||||
|
SysUser user = ShiroUtils.getSysUser();
|
||||||
|
if (user != null)
|
||||||
|
{
|
||||||
|
onlineSession.setUserId(user.getUserId());
|
||||||
|
onlineSession.setLoginName(user.getLoginName());
|
||||||
|
onlineSession.setAvatar(user.getAvatar());
|
||||||
|
onlineSession.setDeptName(user.getDept().getDeptName());
|
||||||
|
onlineSession.markAttributeChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onlineSession.getStatus() == OnlineStatus.off_line)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表示当访问拒绝时是否已经处理了;如果返回true表示需要继续处理;如果返回false表示该拦截器实例已经处理了,将直接返回即可。
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception
|
||||||
|
{
|
||||||
|
Subject subject = getSubject(request, response);
|
||||||
|
if (subject != null)
|
||||||
|
{
|
||||||
|
subject.logout();
|
||||||
|
}
|
||||||
|
saveRequestAndRedirectToLogin(request, response);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转到登录页
|
||||||
|
@Override
|
||||||
|
protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException
|
||||||
|
{
|
||||||
|
WebUtils.issueRedirect(request, response, loginUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
package com.basepro.framework.shiro.web.filter.sync;
|
||||||
|
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.ServletResponse;
|
||||||
|
|
||||||
|
import guo.ping.e3mall.common.constant.ShiroConstants;
|
||||||
|
import org.apache.shiro.web.filter.PathMatchingFilter;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import com.basepro.framework.shiro.session.OnlineSession;
|
||||||
|
import com.basepro.framework.shiro.session.OnlineSessionDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步Session数据到Db
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class SyncOnlineSessionFilter extends PathMatchingFilter
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private OnlineSessionDAO onlineSessionDAO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步会话数据到DB 一次请求最多同步一次 防止过多处理 需要放到Shiro过滤器之前
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception
|
||||||
|
{
|
||||||
|
OnlineSession session = (OnlineSession) request.getAttribute(ShiroConstants.ONLINE_SESSION);
|
||||||
|
// 如果session stop了 也不同步
|
||||||
|
// session停止时间,如果stopTimestamp不为null,则代表已停止
|
||||||
|
if (session != null && session.getUserId() != null && session.getStopTimestamp() == null)
|
||||||
|
{
|
||||||
|
onlineSessionDAO.syncToDb(session);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,170 @@
|
||||||
|
package com.basepro.framework.shiro.web.session;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import basepro.manager.pojo.SysUserOnline;
|
||||||
|
import basepro.manager.service.ISysUserOnlineService;
|
||||||
|
import guo.ping.e3mall.common.constant.ShiroConstants;
|
||||||
|
import guo.ping.e3mall.common.utils.BeanUtils;
|
||||||
|
import guo.ping.e3mall.common.utils.SpringUtils;
|
||||||
|
import guo.ping.e3mall.common.utils.StringUtils;
|
||||||
|
import org.apache.commons.lang3.time.DateUtils;
|
||||||
|
import org.apache.shiro.session.ExpiredSessionException;
|
||||||
|
import org.apache.shiro.session.InvalidSessionException;
|
||||||
|
import org.apache.shiro.session.Session;
|
||||||
|
import org.apache.shiro.session.mgt.DefaultSessionKey;
|
||||||
|
import org.apache.shiro.session.mgt.SessionKey;
|
||||||
|
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import com.basepro.framework.shiro.session.OnlineSession;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主要是在此如果会话的属性修改了 就标识下其修改了 然后方便 OnlineSessionDao同步
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class OnlineWebSessionManager extends DefaultWebSessionManager
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(OnlineWebSessionManager.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAttribute(SessionKey sessionKey, Object attributeKey, Object value) throws InvalidSessionException
|
||||||
|
{
|
||||||
|
super.setAttribute(sessionKey, attributeKey, value);
|
||||||
|
if (value != null && needMarkAttributeChanged(attributeKey))
|
||||||
|
{
|
||||||
|
OnlineSession session = getOnlineSession(sessionKey);
|
||||||
|
session.markAttributeChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean needMarkAttributeChanged(Object attributeKey)
|
||||||
|
{
|
||||||
|
if (attributeKey == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String attributeKeyStr = attributeKey.toString();
|
||||||
|
// 优化 flash属性没必要持久化
|
||||||
|
if (attributeKeyStr.startsWith("org.springframework"))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (attributeKeyStr.startsWith("javax.servlet"))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (attributeKeyStr.equals(ShiroConstants.CURRENT_USERNAME))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object removeAttribute(SessionKey sessionKey, Object attributeKey) throws InvalidSessionException
|
||||||
|
{
|
||||||
|
Object removed = super.removeAttribute(sessionKey, attributeKey);
|
||||||
|
if (removed != null)
|
||||||
|
{
|
||||||
|
OnlineSession s = getOnlineSession(sessionKey);
|
||||||
|
s.markAttributeChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OnlineSession getOnlineSession(SessionKey sessionKey)
|
||||||
|
{
|
||||||
|
OnlineSession session = null;
|
||||||
|
Object obj = doGetSession(sessionKey);
|
||||||
|
if (StringUtils.isNotNull(obj))
|
||||||
|
{
|
||||||
|
session = new OnlineSession();
|
||||||
|
BeanUtils.copyBeanProp(session, obj);
|
||||||
|
}
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证session是否有效 用于删除过期session
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void validateSessions()
|
||||||
|
{
|
||||||
|
if (log.isInfoEnabled())
|
||||||
|
{
|
||||||
|
log.info("invalidation sessions...");
|
||||||
|
}
|
||||||
|
|
||||||
|
int invalidCount = 0;
|
||||||
|
|
||||||
|
int timeout = (int) this.getGlobalSessionTimeout();
|
||||||
|
Date expiredDate = DateUtils.addMilliseconds(new Date(), 0 - timeout);
|
||||||
|
ISysUserOnlineService userOnlineService = SpringUtils.getBean(ISysUserOnlineService.class);
|
||||||
|
List<SysUserOnline> userOnlineList = userOnlineService.selectOnlineByExpired(expiredDate);
|
||||||
|
// 批量过期删除
|
||||||
|
List<String> needOfflineIdList = new ArrayList<String>();
|
||||||
|
for (SysUserOnline userOnline : userOnlineList)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SessionKey key = new DefaultSessionKey(userOnline.getSessionId());
|
||||||
|
Session session = retrieveSession(key);
|
||||||
|
if (session != null)
|
||||||
|
{
|
||||||
|
throw new InvalidSessionException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (InvalidSessionException e)
|
||||||
|
{
|
||||||
|
if (log.isDebugEnabled())
|
||||||
|
{
|
||||||
|
boolean expired = (e instanceof ExpiredSessionException);
|
||||||
|
String msg = "Invalidated session with id [" + userOnline.getSessionId() + "]"
|
||||||
|
+ (expired ? " (expired)" : " (stopped)");
|
||||||
|
log.debug(msg);
|
||||||
|
}
|
||||||
|
invalidCount++;
|
||||||
|
needOfflineIdList.add(userOnline.getSessionId());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (needOfflineIdList.size() > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
userOnlineService.batchDeleteOnline(needOfflineIdList);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.error("batch delete db session error.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log.isInfoEnabled())
|
||||||
|
{
|
||||||
|
String msg = "Finished invalidation session.";
|
||||||
|
if (invalidCount > 0)
|
||||||
|
{
|
||||||
|
msg += " [" + invalidCount + "] sessions were stopped.";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msg += " No sessions were stopped.";
|
||||||
|
}
|
||||||
|
log.info(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Collection<Session> getActiveSessions()
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException("getActiveSessions method not supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
package com.basepro.framework.shiro.web.session;
|
||||||
|
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import guo.ping.e3mall.common.utils.Threads;
|
||||||
|
import org.apache.shiro.session.mgt.DefaultSessionManager;
|
||||||
|
import org.apache.shiro.session.mgt.SessionValidationScheduler;
|
||||||
|
import org.apache.shiro.session.mgt.ValidatingSessionManager;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义任务调度器完成
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class SpringSessionValidationScheduler implements SessionValidationScheduler
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SpringSessionValidationScheduler.class);
|
||||||
|
|
||||||
|
public static final long DEFAULT_SESSION_VALIDATION_INTERVAL = DefaultSessionManager.DEFAULT_SESSION_VALIDATION_INTERVAL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定时器,用于处理超时的挂起请求,也用于连接断开时的重连。
|
||||||
|
*/
|
||||||
|
@Autowired
|
||||||
|
@Qualifier("scheduledExecutorService")
|
||||||
|
private ScheduledExecutorService executorService;
|
||||||
|
|
||||||
|
public void setExecutorService(ScheduledExecutorService executorService) {
|
||||||
|
this.executorService = executorService;
|
||||||
|
}
|
||||||
|
|
||||||
|
private volatile boolean enabled = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会话验证管理器
|
||||||
|
*/
|
||||||
|
@Autowired
|
||||||
|
@Qualifier("sessionManager")
|
||||||
|
private ValidatingSessionManager sessionManager;
|
||||||
|
|
||||||
|
// 相隔多久检查一次session的有效性,单位毫秒,默认就是10分钟
|
||||||
|
@Value("${shiro.session.validationInterval}")
|
||||||
|
private long sessionValidationInterval;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled()
|
||||||
|
{
|
||||||
|
return this.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies how frequently (in milliseconds) this Scheduler will call the
|
||||||
|
* {@link org.apache.shiro.session.mgt.ValidatingSessionManager#validateSessions()
|
||||||
|
* ValidatingSessionManager#validateSessions()} method.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Unless this method is called, the default value is {@link #DEFAULT_SESSION_VALIDATION_INTERVAL}.
|
||||||
|
*
|
||||||
|
* @param sessionValidationInterval
|
||||||
|
*/
|
||||||
|
public void setSessionValidationInterval(long sessionValidationInterval)
|
||||||
|
{
|
||||||
|
this.sessionValidationInterval = sessionValidationInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts session validation by creating a spring PeriodicTrigger.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void enableSessionValidation()
|
||||||
|
{
|
||||||
|
|
||||||
|
enabled = true;
|
||||||
|
|
||||||
|
if (log.isDebugEnabled())
|
||||||
|
{
|
||||||
|
log.debug("Scheduling session validation job using Spring Scheduler with "
|
||||||
|
+ "session validation interval of [" + sessionValidationInterval + "]ms...");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
executorService.scheduleAtFixedRate(new Runnable()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
sessionManager.validateSessions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 1000, sessionValidationInterval * 60 * 1000, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
|
this.enabled = true;
|
||||||
|
|
||||||
|
if (log.isDebugEnabled())
|
||||||
|
{
|
||||||
|
log.debug("Session validation job successfully scheduled with Spring Scheduler.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
if (log.isErrorEnabled())
|
||||||
|
{
|
||||||
|
log.error("Error starting the Spring Scheduler session validation job. Session validation may not occur.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disableSessionValidation()
|
||||||
|
{
|
||||||
|
if (log.isDebugEnabled())
|
||||||
|
{
|
||||||
|
log.debug("Stopping Spring Scheduler session validation job...");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.enabled)
|
||||||
|
{
|
||||||
|
Threads.shutdownAndAwaitTermination(executorService);
|
||||||
|
}
|
||||||
|
this.enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
package com.basepro.framework.util;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import guo.ping.e3mall.common.json.JSON;
|
||||||
|
import guo.ping.e3mall.common.utils.IpUtils;
|
||||||
|
import org.apache.shiro.SecurityUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理并记录日志文件
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class LogUtils
|
||||||
|
{
|
||||||
|
public static final Logger ERROR_LOG = LoggerFactory.getLogger("sys-error");
|
||||||
|
public static final Logger ACCESS_LOG = LoggerFactory.getLogger("sys-access");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录访问日志 [username][jsessionid][ip][accept][UserAgent][url][params][Referer]
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static void logAccess(HttpServletRequest request) throws Exception
|
||||||
|
{
|
||||||
|
String username = getUsername();
|
||||||
|
String jsessionId = request.getRequestedSessionId();
|
||||||
|
String ip = IpUtils.getIpAddr(request);
|
||||||
|
String accept = request.getHeader("accept");
|
||||||
|
String userAgent = request.getHeader("User-Agent");
|
||||||
|
String url = request.getRequestURI();
|
||||||
|
String params = getParams(request);
|
||||||
|
|
||||||
|
StringBuilder s = new StringBuilder();
|
||||||
|
s.append(getBlock(username));
|
||||||
|
s.append(getBlock(jsessionId));
|
||||||
|
s.append(getBlock(ip));
|
||||||
|
s.append(getBlock(accept));
|
||||||
|
s.append(getBlock(userAgent));
|
||||||
|
s.append(getBlock(url));
|
||||||
|
s.append(getBlock(params));
|
||||||
|
s.append(getBlock(request.getHeader("Referer")));
|
||||||
|
getAccessLog().info(s.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录异常错误 格式 [exception]
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
* @param e
|
||||||
|
*/
|
||||||
|
public static void logError(String message, Throwable e)
|
||||||
|
{
|
||||||
|
String username = getUsername();
|
||||||
|
StringBuilder s = new StringBuilder();
|
||||||
|
s.append(getBlock("exception"));
|
||||||
|
s.append(getBlock(username));
|
||||||
|
s.append(getBlock(message));
|
||||||
|
ERROR_LOG.error(s.toString(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录页面错误 错误日志记录 [page/eception][username][statusCode][errorMessage][servletName][uri][exceptionName][ip][exception]
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
*/
|
||||||
|
public static void logPageError(HttpServletRequest request)
|
||||||
|
{
|
||||||
|
String username = getUsername();
|
||||||
|
|
||||||
|
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
|
||||||
|
String message = (String) request.getAttribute("javax.servlet.error.message");
|
||||||
|
String uri = (String) request.getAttribute("javax.servlet.error.request_uri");
|
||||||
|
Throwable t = (Throwable) request.getAttribute("javax.servlet.error.exception");
|
||||||
|
|
||||||
|
if (statusCode == null)
|
||||||
|
{
|
||||||
|
statusCode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder s = new StringBuilder();
|
||||||
|
s.append(getBlock(t == null ? "page" : "exception"));
|
||||||
|
s.append(getBlock(username));
|
||||||
|
s.append(getBlock(statusCode));
|
||||||
|
s.append(getBlock(message));
|
||||||
|
s.append(getBlock(IpUtils.getIpAddr(request)));
|
||||||
|
|
||||||
|
s.append(getBlock(uri));
|
||||||
|
s.append(getBlock(request.getHeader("Referer")));
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
|
||||||
|
while (t != null)
|
||||||
|
{
|
||||||
|
t.printStackTrace(new PrintWriter(sw));
|
||||||
|
t = t.getCause();
|
||||||
|
}
|
||||||
|
s.append(getBlock(sw.toString()));
|
||||||
|
getErrorLog().error(s.toString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getBlock(Object msg)
|
||||||
|
{
|
||||||
|
if (msg == null)
|
||||||
|
{
|
||||||
|
msg = "";
|
||||||
|
}
|
||||||
|
return "[" + msg.toString() + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static String getParams(HttpServletRequest request) throws Exception
|
||||||
|
{
|
||||||
|
Map<String, String[]> params = request.getParameterMap();
|
||||||
|
return JSON.marshal(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static String getUsername()
|
||||||
|
{
|
||||||
|
return (String) SecurityUtils.getSubject().getPrincipal();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Logger getAccessLog()
|
||||||
|
{
|
||||||
|
return ACCESS_LOG;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Logger getErrorLog()
|
||||||
|
{
|
||||||
|
return ERROR_LOG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
package com.basepro.framework.util;
|
||||||
|
|
||||||
|
import basepro.manager.pojo.SysUser;
|
||||||
|
import guo.ping.e3mall.common.utils.BeanUtils;
|
||||||
|
import guo.ping.e3mall.common.utils.StringUtils;
|
||||||
|
import org.apache.shiro.SecurityUtils;
|
||||||
|
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
|
||||||
|
import org.apache.shiro.mgt.RealmSecurityManager;
|
||||||
|
import org.apache.shiro.session.Session;
|
||||||
|
import org.apache.shiro.subject.Subject;
|
||||||
|
import org.apache.shiro.subject.PrincipalCollection;
|
||||||
|
import org.apache.shiro.subject.SimplePrincipalCollection;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shiro 工具类
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class ShiroUtils
|
||||||
|
{
|
||||||
|
public static Subject getSubject()
|
||||||
|
{
|
||||||
|
return SecurityUtils.getSubject();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Session getSession()
|
||||||
|
{
|
||||||
|
return SecurityUtils.getSubject().getSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void logout()
|
||||||
|
{
|
||||||
|
getSubject().logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SysUser getSysUser()
|
||||||
|
{
|
||||||
|
SysUser user = null;
|
||||||
|
Object obj = getSubject().getPrincipal();
|
||||||
|
if (StringUtils.isNotNull(obj))
|
||||||
|
{
|
||||||
|
user = new SysUser();
|
||||||
|
BeanUtils.copyBeanProp(user, obj);
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSysUser(SysUser user)
|
||||||
|
{
|
||||||
|
Subject subject = getSubject();
|
||||||
|
PrincipalCollection principalCollection = subject.getPrincipals();
|
||||||
|
String realmName = principalCollection.getRealmNames().iterator().next();
|
||||||
|
PrincipalCollection newPrincipalCollection = new SimplePrincipalCollection(user, realmName);
|
||||||
|
// 重新加载Principal
|
||||||
|
subject.runAs(newPrincipalCollection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* public static void clearCachedAuthorizationInfo()
|
||||||
|
{
|
||||||
|
RealmSecurityManager rsm = (RealmSecurityManager) SecurityUtils.getSecurityManager();
|
||||||
|
UserRealm realm = (UserRealm) rsm.getRealms().iterator().next();
|
||||||
|
realm.clearCachedAuthorizationInfo();
|
||||||
|
}*/
|
||||||
|
|
||||||
|
public static Long getUserId()
|
||||||
|
{
|
||||||
|
return getSysUser().getUserId().longValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getLoginName()
|
||||||
|
{
|
||||||
|
return getSysUser().getLoginName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getIp()
|
||||||
|
{
|
||||||
|
return getSubject().getSession().getHost();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSessionId()
|
||||||
|
{
|
||||||
|
return String.valueOf(getSubject().getSession().getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成随机盐
|
||||||
|
*/
|
||||||
|
public static String randomSalt()
|
||||||
|
{
|
||||||
|
// 一个Byte占两个字节,此处生成的3字节,字符串长度为6
|
||||||
|
SecureRandomNumberGenerator secureRandom = new SecureRandomNumberGenerator();
|
||||||
|
String hex = secureRandom.nextBytes(3).toHex();
|
||||||
|
return hex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,241 @@
|
||||||
|
package com.basepro.framework.web.domain;
|
||||||
|
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
import com.basepro.framework.web.domain.server.Cpu;
|
||||||
|
import com.basepro.framework.web.domain.server.Jvm;
|
||||||
|
import com.basepro.framework.web.domain.server.Mem;
|
||||||
|
import com.basepro.framework.web.domain.server.Sys;
|
||||||
|
import com.basepro.framework.web.domain.server.SysFile;
|
||||||
|
import guo.ping.e3mall.common.utils.Arith;
|
||||||
|
import guo.ping.e3mall.common.utils.IpUtils;
|
||||||
|
import oshi.SystemInfo;
|
||||||
|
import oshi.hardware.CentralProcessor;
|
||||||
|
import oshi.hardware.CentralProcessor.TickType;
|
||||||
|
import oshi.hardware.GlobalMemory;
|
||||||
|
import oshi.hardware.HardwareAbstractionLayer;
|
||||||
|
import oshi.software.os.FileSystem;
|
||||||
|
import oshi.software.os.OSFileStore;
|
||||||
|
import oshi.software.os.OperatingSystem;
|
||||||
|
import oshi.util.Util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务器相关信息
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class Server
|
||||||
|
{
|
||||||
|
|
||||||
|
private static final int OSHI_WAIT_SECOND = 1000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CPU相关信息
|
||||||
|
*/
|
||||||
|
private Cpu cpu = new Cpu();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 內存相关信息
|
||||||
|
*/
|
||||||
|
private Mem mem = new Mem();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JVM相关信息
|
||||||
|
*/
|
||||||
|
private Jvm jvm = new Jvm();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务器相关信息
|
||||||
|
*/
|
||||||
|
private Sys sys = new Sys();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 磁盘相关信息
|
||||||
|
*/
|
||||||
|
private List<SysFile> sysFiles = new LinkedList<SysFile>();
|
||||||
|
|
||||||
|
public Cpu getCpu()
|
||||||
|
{
|
||||||
|
return cpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCpu(Cpu cpu)
|
||||||
|
{
|
||||||
|
this.cpu = cpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mem getMem()
|
||||||
|
{
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMem(Mem mem)
|
||||||
|
{
|
||||||
|
this.mem = mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Jvm getJvm()
|
||||||
|
{
|
||||||
|
return jvm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJvm(Jvm jvm)
|
||||||
|
{
|
||||||
|
this.jvm = jvm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Sys getSys()
|
||||||
|
{
|
||||||
|
return sys;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSys(Sys sys)
|
||||||
|
{
|
||||||
|
this.sys = sys;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SysFile> getSysFiles()
|
||||||
|
{
|
||||||
|
return sysFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSysFiles(List<SysFile> sysFiles)
|
||||||
|
{
|
||||||
|
this.sysFiles = sysFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void copyTo() throws Exception
|
||||||
|
{
|
||||||
|
SystemInfo si = new SystemInfo();
|
||||||
|
HardwareAbstractionLayer hal = si.getHardware();
|
||||||
|
|
||||||
|
setCpuInfo(hal.getProcessor());
|
||||||
|
|
||||||
|
setMemInfo(hal.getMemory());
|
||||||
|
|
||||||
|
setSysInfo();
|
||||||
|
|
||||||
|
setJvmInfo();
|
||||||
|
|
||||||
|
setSysFiles(si.getOperatingSystem());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置CPU信息
|
||||||
|
*/
|
||||||
|
private void setCpuInfo(CentralProcessor processor)
|
||||||
|
{
|
||||||
|
// CPU信息
|
||||||
|
long[] prevTicks = processor.getSystemCpuLoadTicks();
|
||||||
|
Util.sleep(OSHI_WAIT_SECOND);
|
||||||
|
long[] ticks = processor.getSystemCpuLoadTicks();
|
||||||
|
long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()];
|
||||||
|
long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()];
|
||||||
|
long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()];
|
||||||
|
long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()];
|
||||||
|
long cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()];
|
||||||
|
long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()];
|
||||||
|
long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()];
|
||||||
|
long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()];
|
||||||
|
long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
|
||||||
|
cpu.setCpuNum(processor.getLogicalProcessorCount());
|
||||||
|
cpu.setTotal(totalCpu);
|
||||||
|
cpu.setSys(cSys);
|
||||||
|
cpu.setUsed(user);
|
||||||
|
cpu.setWait(iowait);
|
||||||
|
cpu.setFree(idle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置内存信息
|
||||||
|
*/
|
||||||
|
private void setMemInfo(GlobalMemory memory)
|
||||||
|
{
|
||||||
|
mem.setTotal(memory.getTotal());
|
||||||
|
mem.setUsed(memory.getTotal() - memory.getAvailable());
|
||||||
|
mem.setFree(memory.getAvailable());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置服务器信息
|
||||||
|
*/
|
||||||
|
private void setSysInfo()
|
||||||
|
{
|
||||||
|
Properties props = System.getProperties();
|
||||||
|
sys.setComputerName(IpUtils.getHostName());
|
||||||
|
sys.setComputerIp(IpUtils.getHostIp());
|
||||||
|
sys.setOsName(props.getProperty("os.name"));
|
||||||
|
sys.setOsArch(props.getProperty("os.arch"));
|
||||||
|
sys.setUserDir(props.getProperty("user.dir"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置Java虚拟机
|
||||||
|
*/
|
||||||
|
private void setJvmInfo() throws UnknownHostException
|
||||||
|
{
|
||||||
|
Properties props = System.getProperties();
|
||||||
|
jvm.setTotal(Runtime.getRuntime().totalMemory());
|
||||||
|
jvm.setMax(Runtime.getRuntime().maxMemory());
|
||||||
|
jvm.setFree(Runtime.getRuntime().freeMemory());
|
||||||
|
jvm.setVersion(props.getProperty("java.version"));
|
||||||
|
jvm.setHome(props.getProperty("java.home"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置磁盘信息
|
||||||
|
*/
|
||||||
|
private void setSysFiles(OperatingSystem os)
|
||||||
|
{
|
||||||
|
FileSystem fileSystem = os.getFileSystem();
|
||||||
|
OSFileStore[] fsArray = fileSystem.getFileStores();
|
||||||
|
for (OSFileStore fs : fsArray)
|
||||||
|
{
|
||||||
|
long free = fs.getUsableSpace();
|
||||||
|
long total = fs.getTotalSpace();
|
||||||
|
long used = total - free;
|
||||||
|
SysFile sysFile = new SysFile();
|
||||||
|
sysFile.setDirName(fs.getMount());
|
||||||
|
sysFile.setSysTypeName(fs.getType());
|
||||||
|
sysFile.setTypeName(fs.getName());
|
||||||
|
sysFile.setTotal(convertFileSize(total));
|
||||||
|
sysFile.setFree(convertFileSize(free));
|
||||||
|
sysFile.setUsed(convertFileSize(used));
|
||||||
|
sysFile.setUsage(Arith.mul(Arith.div(used, total, 4), 100));
|
||||||
|
sysFiles.add(sysFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字节转换
|
||||||
|
*
|
||||||
|
* @param size 字节大小
|
||||||
|
* @return 转换后值
|
||||||
|
*/
|
||||||
|
public String convertFileSize(long size)
|
||||||
|
{
|
||||||
|
long kb = 1024;
|
||||||
|
long mb = kb * 1024;
|
||||||
|
long gb = mb * 1024;
|
||||||
|
if (size >= gb)
|
||||||
|
{
|
||||||
|
return String.format("%.1f GB", (float) size / gb);
|
||||||
|
}
|
||||||
|
else if (size >= mb)
|
||||||
|
{
|
||||||
|
float f = (float) size / mb;
|
||||||
|
return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f);
|
||||||
|
}
|
||||||
|
else if (size >= kb)
|
||||||
|
{
|
||||||
|
float f = (float) size / kb;
|
||||||
|
return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return String.format("%d B", size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
package com.basepro.framework.web.domain.server;
|
||||||
|
|
||||||
|
|
||||||
|
import guo.ping.e3mall.common.utils.Arith;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CPU相关信息
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class Cpu
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 核心数
|
||||||
|
*/
|
||||||
|
private int cpuNum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CPU总的使用率
|
||||||
|
*/
|
||||||
|
private double total;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CPU系统使用率
|
||||||
|
*/
|
||||||
|
private double sys;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CPU用户使用率
|
||||||
|
*/
|
||||||
|
private double used;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CPU当前等待率
|
||||||
|
*/
|
||||||
|
private double wait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CPU当前空闲率
|
||||||
|
*/
|
||||||
|
private double free;
|
||||||
|
|
||||||
|
public int getCpuNum()
|
||||||
|
{
|
||||||
|
return cpuNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCpuNum(int cpuNum)
|
||||||
|
{
|
||||||
|
this.cpuNum = cpuNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getTotal()
|
||||||
|
{
|
||||||
|
return Arith.round(Arith.mul(total, 100), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTotal(double total)
|
||||||
|
{
|
||||||
|
this.total = total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getSys()
|
||||||
|
{
|
||||||
|
return Arith.round(Arith.mul(sys / total, 100), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSys(double sys)
|
||||||
|
{
|
||||||
|
this.sys = sys;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getUsed()
|
||||||
|
{
|
||||||
|
return Arith.round(Arith.mul(used / total, 100), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsed(double used)
|
||||||
|
{
|
||||||
|
this.used = used;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getWait()
|
||||||
|
{
|
||||||
|
return Arith.round(Arith.mul(wait / total, 100), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWait(double wait)
|
||||||
|
{
|
||||||
|
this.wait = wait;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getFree()
|
||||||
|
{
|
||||||
|
return Arith.round(Arith.mul(free / total, 100), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFree(double free)
|
||||||
|
{
|
||||||
|
this.free = free;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,122 @@
|
||||||
|
package com.basepro.framework.web.domain.server;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import guo.ping.e3mall.common.utils.Arith;
|
||||||
|
import guo.ping.e3mall.common.utils.DateUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JVM相关信息
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class Jvm
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 当前JVM占用的内存总数(M)
|
||||||
|
*/
|
||||||
|
private double total;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JVM最大可用内存总数(M)
|
||||||
|
*/
|
||||||
|
private double max;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JVM空闲内存(M)
|
||||||
|
*/
|
||||||
|
private double free;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JDK版本
|
||||||
|
*/
|
||||||
|
private String version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JDK路径
|
||||||
|
*/
|
||||||
|
private String home;
|
||||||
|
|
||||||
|
public double getTotal()
|
||||||
|
{
|
||||||
|
return Arith.div(total, (1024 * 1024), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTotal(double total)
|
||||||
|
{
|
||||||
|
this.total = total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getMax()
|
||||||
|
{
|
||||||
|
return Arith.div(max, (1024 * 1024), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMax(double max)
|
||||||
|
{
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getFree()
|
||||||
|
{
|
||||||
|
return Arith.div(free, (1024 * 1024), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFree(double free)
|
||||||
|
{
|
||||||
|
this.free = free;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getUsed()
|
||||||
|
{
|
||||||
|
return Arith.div(total - free, (1024 * 1024), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getUsage()
|
||||||
|
{
|
||||||
|
return Arith.mul(Arith.div(total - free, total, 4), 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取JDK名称
|
||||||
|
*/
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return ManagementFactory.getRuntimeMXBean().getVmName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVersion()
|
||||||
|
{
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVersion(String version)
|
||||||
|
{
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHome()
|
||||||
|
{
|
||||||
|
return home;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHome(String home)
|
||||||
|
{
|
||||||
|
this.home = home;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JDK启动时间
|
||||||
|
*/
|
||||||
|
public String getStartTime()
|
||||||
|
{
|
||||||
|
return DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.getServerStartDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JDK运行时间
|
||||||
|
*/
|
||||||
|
public String getRunTime()
|
||||||
|
{
|
||||||
|
return DateUtils.getDatePoor(DateUtils.getNowDate(), DateUtils.getServerStartDate());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
package com.basepro.framework.web.domain.server;
|
||||||
|
|
||||||
|
import guo.ping.e3mall.common.utils.Arith;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 內存相关信息
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class Mem
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 内存总量
|
||||||
|
*/
|
||||||
|
private double total;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已用内存
|
||||||
|
*/
|
||||||
|
private double used;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 剩余内存
|
||||||
|
*/
|
||||||
|
private double free;
|
||||||
|
|
||||||
|
public double getTotal()
|
||||||
|
{
|
||||||
|
return Arith.div(total, (1024 * 1024 * 1024), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTotal(long total)
|
||||||
|
{
|
||||||
|
this.total = total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getUsed()
|
||||||
|
{
|
||||||
|
return Arith.div(used, (1024 * 1024 * 1024), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsed(long used)
|
||||||
|
{
|
||||||
|
this.used = used;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getFree()
|
||||||
|
{
|
||||||
|
return Arith.div(free, (1024 * 1024 * 1024), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFree(long free)
|
||||||
|
{
|
||||||
|
this.free = free;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getUsage()
|
||||||
|
{
|
||||||
|
return Arith.mul(Arith.div(used, total, 4), 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
package com.basepro.framework.web.domain.server;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统相关信息
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class Sys
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 服务器名称
|
||||||
|
*/
|
||||||
|
private String computerName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务器Ip
|
||||||
|
*/
|
||||||
|
private String computerIp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 项目路径
|
||||||
|
*/
|
||||||
|
private String userDir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作系统
|
||||||
|
*/
|
||||||
|
private String osName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统架构
|
||||||
|
*/
|
||||||
|
private String osArch;
|
||||||
|
|
||||||
|
public String getComputerName()
|
||||||
|
{
|
||||||
|
return computerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setComputerName(String computerName)
|
||||||
|
{
|
||||||
|
this.computerName = computerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getComputerIp()
|
||||||
|
{
|
||||||
|
return computerIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setComputerIp(String computerIp)
|
||||||
|
{
|
||||||
|
this.computerIp = computerIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserDir()
|
||||||
|
{
|
||||||
|
return userDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserDir(String userDir)
|
||||||
|
{
|
||||||
|
this.userDir = userDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOsName()
|
||||||
|
{
|
||||||
|
return osName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOsName(String osName)
|
||||||
|
{
|
||||||
|
this.osName = osName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOsArch()
|
||||||
|
{
|
||||||
|
return osArch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOsArch(String osArch)
|
||||||
|
{
|
||||||
|
this.osArch = osArch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
package com.basepro.framework.web.domain.server;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统文件相关信息
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class SysFile
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 盘符路径
|
||||||
|
*/
|
||||||
|
private String dirName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 盘符类型
|
||||||
|
*/
|
||||||
|
private String sysTypeName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件类型
|
||||||
|
*/
|
||||||
|
private String typeName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 总大小
|
||||||
|
*/
|
||||||
|
private String total;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 剩余大小
|
||||||
|
*/
|
||||||
|
private String free;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已经使用量
|
||||||
|
*/
|
||||||
|
private String used;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源的使用率
|
||||||
|
*/
|
||||||
|
private double usage;
|
||||||
|
|
||||||
|
public String getDirName()
|
||||||
|
{
|
||||||
|
return dirName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDirName(String dirName)
|
||||||
|
{
|
||||||
|
this.dirName = dirName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSysTypeName()
|
||||||
|
{
|
||||||
|
return sysTypeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSysTypeName(String sysTypeName)
|
||||||
|
{
|
||||||
|
this.sysTypeName = sysTypeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTypeName()
|
||||||
|
{
|
||||||
|
return typeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTypeName(String typeName)
|
||||||
|
{
|
||||||
|
this.typeName = typeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTotal()
|
||||||
|
{
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTotal(String total)
|
||||||
|
{
|
||||||
|
this.total = total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFree()
|
||||||
|
{
|
||||||
|
return free;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFree(String free)
|
||||||
|
{
|
||||||
|
this.free = free;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsed()
|
||||||
|
{
|
||||||
|
return used;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsed(String used)
|
||||||
|
{
|
||||||
|
this.used = used;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getUsage()
|
||||||
|
{
|
||||||
|
return usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsage(double usage)
|
||||||
|
{
|
||||||
|
this.usage = usage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
package com.basepro.framework.web.exception;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import guo.ping.e3mall.common.exception.BusinessException;
|
||||||
|
import guo.ping.e3mall.common.exception.DemoModeException;
|
||||||
|
import guo.ping.e3mall.common.pojo.AjaxResult;
|
||||||
|
import guo.ping.e3mall.common.utils.PermissionUtils;
|
||||||
|
import guo.ping.e3mall.common.utils.ServletUtils;
|
||||||
|
import org.apache.shiro.authz.AuthorizationException;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.validation.BindException;
|
||||||
|
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局异常处理器
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@RestControllerAdvice
|
||||||
|
public class GlobalExceptionHandler
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 权限校验失败 如果请求为ajax返回json,普通请求跳转页面
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(AuthorizationException.class)
|
||||||
|
public Object handleAuthorizationException(HttpServletRequest request, AuthorizationException e)
|
||||||
|
{
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
if (ServletUtils.isAjaxRequest(request))
|
||||||
|
{
|
||||||
|
return AjaxResult.error(PermissionUtils.getMsg(e.getMessage()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ModelAndView modelAndView = new ModelAndView();
|
||||||
|
modelAndView.setViewName("error/unauth");
|
||||||
|
return modelAndView;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求方式不支持
|
||||||
|
*/
|
||||||
|
@ExceptionHandler({ HttpRequestMethodNotSupportedException.class })
|
||||||
|
public AjaxResult handleException(HttpRequestMethodNotSupportedException e)
|
||||||
|
{
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return AjaxResult.error("不支持' " + e.getMethod() + "'请求");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拦截未知的运行时异常
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(RuntimeException.class)
|
||||||
|
public AjaxResult notFount(RuntimeException e)
|
||||||
|
{
|
||||||
|
log.error("运行时异常:", e);
|
||||||
|
return AjaxResult.error("运行时异常:" + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统异常
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(Exception.class)
|
||||||
|
public AjaxResult handleException(Exception e)
|
||||||
|
{
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return AjaxResult.error("服务器错误,请联系管理员");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务异常
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(BusinessException.class)
|
||||||
|
public Object businessException(HttpServletRequest request, BusinessException e)
|
||||||
|
{
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
if (ServletUtils.isAjaxRequest(request))
|
||||||
|
{
|
||||||
|
return AjaxResult.error(e.getMessage());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ModelAndView modelAndView = new ModelAndView();
|
||||||
|
modelAndView.addObject("errorMessage", e.getMessage());
|
||||||
|
modelAndView.setViewName("error/business");
|
||||||
|
return modelAndView;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义验证异常
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(BindException.class)
|
||||||
|
public AjaxResult validatedBindException(BindException e)
|
||||||
|
{
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
String message = e.getAllErrors().get(0).getDefaultMessage();
|
||||||
|
return AjaxResult.error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 演示模式异常
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(DemoModeException.class)
|
||||||
|
public AjaxResult demoModeException(DemoModeException e)
|
||||||
|
{
|
||||||
|
return AjaxResult.error("演示模式,不允许操作");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,264 @@
|
||||||
|
package com.basepro.framework.web.service;
|
||||||
|
|
||||||
|
import java.beans.BeanInfo;
|
||||||
|
import java.beans.Introspector;
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
|
||||||
|
import guo.ping.e3mall.common.utils.StringUtils;
|
||||||
|
import org.apache.shiro.SecurityUtils;
|
||||||
|
import org.apache.shiro.subject.Subject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RuoYi首创 js调用 thymeleaf 实现按钮权限可见性
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Service("permission")
|
||||||
|
public class PermissionService
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(PermissionService.class);
|
||||||
|
|
||||||
|
/** 没有权限,hidden用于前端隐藏按钮 */
|
||||||
|
public static final String NOACCESS = "hidden";
|
||||||
|
|
||||||
|
private static final String ROLE_DELIMETER = ",";
|
||||||
|
|
||||||
|
private static final String PERMISSION_DELIMETER = ",";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证用户是否具备某权限,无权限返回hidden用于前端隐藏(如需返回Boolean使用isPermitted)
|
||||||
|
*
|
||||||
|
* @param permission 权限字符串
|
||||||
|
* @return 用户是否具备某权限
|
||||||
|
*/
|
||||||
|
public String hasPermi(String permission)
|
||||||
|
{
|
||||||
|
return isPermitted(permission) ? StringUtils.EMPTY : NOACCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证用户是否不具备某权限,与 hasPermi逻辑相反。无权限返回hidden用于前端隐藏(如需返回Boolean使用isLacksPermitted)
|
||||||
|
*
|
||||||
|
* @param permission 权限字符串
|
||||||
|
* @return 用户是否不具备某权限
|
||||||
|
*/
|
||||||
|
public String lacksPermi(String permission)
|
||||||
|
{
|
||||||
|
return isLacksPermitted(permission) ? StringUtils.EMPTY : NOACCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证用户是否具有以下任意一个权限,无权限返回hidden用于隐藏(如需返回Boolean使用hasAnyPermissions)
|
||||||
|
*
|
||||||
|
* @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表
|
||||||
|
* @return 用户是否具有以下任意一个权限
|
||||||
|
*/
|
||||||
|
public String hasAnyPermi(String permissions)
|
||||||
|
{
|
||||||
|
return hasAnyPermissions(permissions, PERMISSION_DELIMETER) ? StringUtils.EMPTY : NOACCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证用户是否具备某角色,无权限返回hidden用于隐藏(如需返回Boolean使用isRole)
|
||||||
|
*
|
||||||
|
* @param role 角色字符串
|
||||||
|
* @return 用户是否具备某角色
|
||||||
|
*/
|
||||||
|
public String hasRole(String role)
|
||||||
|
{
|
||||||
|
return isRole(role) ? StringUtils.EMPTY : NOACCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证用户是否不具备某角色,与hasRole逻辑相反。无权限返回hidden用于隐藏(如需返回Boolean使用isLacksRole)
|
||||||
|
*
|
||||||
|
* @param role 角色字符串
|
||||||
|
* @return 用户是否不具备某角色
|
||||||
|
*/
|
||||||
|
public String lacksRole(String role)
|
||||||
|
{
|
||||||
|
return isLacksRole(role) ? StringUtils.EMPTY : NOACCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证用户是否具有以下任意一个角色,无权限返回hidden用于隐藏(如需返回Boolean使用isAnyRoles)
|
||||||
|
*
|
||||||
|
* @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表
|
||||||
|
* @return 用户是否具有以下任意一个角色
|
||||||
|
*/
|
||||||
|
public String hasAnyRoles(String roles)
|
||||||
|
{
|
||||||
|
return isAnyRoles(roles, ROLE_DELIMETER) ? StringUtils.EMPTY : NOACCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证用户是否认证通过或已记住的用户。
|
||||||
|
*
|
||||||
|
* @return 用户是否认证通过或已记住的用户
|
||||||
|
*/
|
||||||
|
public boolean isUser()
|
||||||
|
{
|
||||||
|
Subject subject = SecurityUtils.getSubject();
|
||||||
|
return subject != null && subject.getPrincipal() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断用户是否拥有某个权限
|
||||||
|
*
|
||||||
|
* @param permission 权限字符串
|
||||||
|
* @return 用户是否具备某权限
|
||||||
|
*/
|
||||||
|
public boolean isPermitted(String permission)
|
||||||
|
{
|
||||||
|
return SecurityUtils.getSubject().isPermitted(permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断用户是否不具备某权限,与 isPermitted逻辑相反。
|
||||||
|
*
|
||||||
|
* @param permission 权限名称
|
||||||
|
* @return 用户是否不具备某权限
|
||||||
|
*/
|
||||||
|
public boolean isLacksPermitted(String permission)
|
||||||
|
{
|
||||||
|
return isPermitted(permission) != true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证用户是否具有以下任意一个权限。
|
||||||
|
*
|
||||||
|
* @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表
|
||||||
|
* @return 用户是否具有以下任意一个权限
|
||||||
|
*/
|
||||||
|
public boolean hasAnyPermissions(String permissions)
|
||||||
|
{
|
||||||
|
return hasAnyPermissions(permissions, PERMISSION_DELIMETER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证用户是否具有以下任意一个权限。
|
||||||
|
*
|
||||||
|
* @param permissions 以 delimeter 为分隔符的权限列表
|
||||||
|
* @param delimeter 权限列表分隔符
|
||||||
|
* @return 用户是否具有以下任意一个权限
|
||||||
|
*/
|
||||||
|
public boolean hasAnyPermissions(String permissions, String delimeter)
|
||||||
|
{
|
||||||
|
Subject subject = SecurityUtils.getSubject();
|
||||||
|
|
||||||
|
if (subject != null)
|
||||||
|
{
|
||||||
|
if (delimeter == null || delimeter.length() == 0)
|
||||||
|
{
|
||||||
|
delimeter = PERMISSION_DELIMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String permission : permissions.split(delimeter))
|
||||||
|
{
|
||||||
|
if (permission != null && subject.isPermitted(permission.trim()) == true)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断用户是否拥有某个角色
|
||||||
|
*
|
||||||
|
* @param role 角色字符串
|
||||||
|
* @return 用户是否具备某角色
|
||||||
|
*/
|
||||||
|
public boolean isRole(String role)
|
||||||
|
{
|
||||||
|
return SecurityUtils.getSubject().hasRole(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证用户是否不具备某角色,与 isRole逻辑相反。
|
||||||
|
*
|
||||||
|
* @param role 角色名称
|
||||||
|
* @return 用户是否不具备某角色
|
||||||
|
*/
|
||||||
|
public boolean isLacksRole(String role)
|
||||||
|
{
|
||||||
|
return isRole(role) != true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证用户是否具有以下任意一个角色。
|
||||||
|
*
|
||||||
|
* @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表
|
||||||
|
* @return 用户是否具有以下任意一个角色
|
||||||
|
*/
|
||||||
|
public boolean isAnyRoles(String roles)
|
||||||
|
{
|
||||||
|
return isAnyRoles(roles, ROLE_DELIMETER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证用户是否具有以下任意一个角色。
|
||||||
|
*
|
||||||
|
* @param roles 以 delimeter 为分隔符的角色列表
|
||||||
|
* @param delimeter 角色列表分隔符
|
||||||
|
* @return 用户是否具有以下任意一个角色
|
||||||
|
*/
|
||||||
|
public boolean isAnyRoles(String roles, String delimeter)
|
||||||
|
{
|
||||||
|
Subject subject = SecurityUtils.getSubject();
|
||||||
|
if (subject != null)
|
||||||
|
{
|
||||||
|
if (delimeter == null || delimeter.length() == 0)
|
||||||
|
{
|
||||||
|
delimeter = ROLE_DELIMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String role : roles.split(delimeter))
|
||||||
|
{
|
||||||
|
if (subject.hasRole(role.trim()) == true)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回用户属性值
|
||||||
|
*
|
||||||
|
* @param property 属性名称
|
||||||
|
* @return 用户属性值
|
||||||
|
*/
|
||||||
|
public Object getPrincipalProperty(String property)
|
||||||
|
{
|
||||||
|
Subject subject = SecurityUtils.getSubject();
|
||||||
|
if (subject != null)
|
||||||
|
{
|
||||||
|
Object principal = subject.getPrincipal();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
BeanInfo bi = Introspector.getBeanInfo(principal.getClass());
|
||||||
|
for (PropertyDescriptor pd : bi.getPropertyDescriptors())
|
||||||
|
{
|
||||||
|
if (pd.getName().equals(property) == true)
|
||||||
|
{
|
||||||
|
return pd.getReadMethod().invoke(principal, (Object[]) null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.error("Error reading property [{}] from principal of type [{}]", property, principal.getClass().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
# 开发环境配置
|
||||||
|
server:
|
||||||
|
# 服务器的HTTP端口,默认为80
|
||||||
|
port: 88
|
||||||
|
servlet:
|
||||||
|
# 应用的访问路径
|
||||||
|
context-path: /
|
||||||
|
tomcat:
|
||||||
|
# tomcat的URI编码
|
||||||
|
uri-encoding: UTF-8
|
||||||
|
# tomcat最大线程数,默认为200
|
||||||
|
max-threads: 800
|
||||||
|
# Tomcat启动初始化的线程数,默认值25
|
||||||
|
min-spare-threads: 30
|
||||||
|
|
||||||
|
# 日志配置
|
||||||
|
logging:
|
||||||
|
level:
|
||||||
|
com.basepro: debug
|
||||||
|
org.springframework: warn
|
||||||
|
|
||||||
|
# 用户配置
|
||||||
|
user:
|
||||||
|
password:
|
||||||
|
# 密码错误{maxRetryCount}次锁定10分钟
|
||||||
|
maxRetryCount: 50
|
||||||
|
|
||||||
|
# Spring配置
|
||||||
|
spring:
|
||||||
|
# 模板引擎
|
||||||
|
thymeleaf:
|
||||||
|
mode: HTML
|
||||||
|
encoding: utf-8
|
||||||
|
# 禁用缓存
|
||||||
|
cache: false
|
||||||
|
# 资源信息
|
||||||
|
messages:
|
||||||
|
# 国际化资源文件路径
|
||||||
|
basename: static/i18n/messages
|
||||||
|
jackson:
|
||||||
|
time-zone: GMT+8
|
||||||
|
date-format: yyyy-MM-dd HH:mm:ss
|
||||||
|
profiles:
|
||||||
|
active: druid
|
||||||
|
# 文件上传
|
||||||
|
servlet:
|
||||||
|
multipart:
|
||||||
|
# 单个文件大小
|
||||||
|
max-file-size: 100MB
|
||||||
|
# 设置总上传的文件大小
|
||||||
|
max-request-size: 200MB
|
||||||
|
# 服务模块
|
||||||
|
devtools:
|
||||||
|
restart:
|
||||||
|
# 热部署开关
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# MyBatis
|
||||||
|
mybatis:
|
||||||
|
# 搜索指定包别名
|
||||||
|
typeAliasesPackage: com.basepro.**.domain
|
||||||
|
# 配置mapper的扫描,找到所有的mapper.xml映射文件
|
||||||
|
mapperLocations: classpath*:mapper/**/*Mapper.xml
|
||||||
|
# 加载全局的配置文件
|
||||||
|
configLocation: classpath:mybatis/mybatis-config.xml
|
||||||
|
|
||||||
|
# PageHelper分页插件
|
||||||
|
pagehelper:
|
||||||
|
helperDialect: mysql
|
||||||
|
reasonable: true
|
||||||
|
supportMethodsArguments: true
|
||||||
|
params: count=countSql
|
||||||
|
|
||||||
|
# Shiro
|
||||||
|
shiro:
|
||||||
|
user:
|
||||||
|
# 登录地址
|
||||||
|
loginUrl: /login
|
||||||
|
# 权限认证失败地址
|
||||||
|
unauthorizedUrl: /unauth
|
||||||
|
# 首页地址
|
||||||
|
indexUrl: /index
|
||||||
|
# 验证码开关
|
||||||
|
captchaEnabled: true
|
||||||
|
# 验证码类型 math 数组计算 char 字符
|
||||||
|
captchaType: math
|
||||||
|
cookie:
|
||||||
|
# 设置Cookie的域名 默认空,即当前访问的域名
|
||||||
|
domain:
|
||||||
|
# 设置cookie的有效访问路径
|
||||||
|
path: /
|
||||||
|
# 设置HttpOnly属性
|
||||||
|
httpOnly: true
|
||||||
|
# 设置Cookie的过期时间,天为单位
|
||||||
|
maxAge: 30
|
||||||
|
session:
|
||||||
|
# Session超时时间,-1代表永不过期(默认30分钟)
|
||||||
|
expireTime: 30
|
||||||
|
# 同步session到数据库的周期(默认1分钟)
|
||||||
|
dbSyncPeriod: 1
|
||||||
|
# 相隔多久检查一次session的有效性,默认就是10分钟
|
||||||
|
validationInterval: 10
|
||||||
|
# 同一个用户最大会话数,比如2的意思是同一个账号允许最多同时两个人登录(默认-1不限制)
|
||||||
|
maxSession: -1
|
||||||
|
# 踢出之前登录的/之后登录的用户,默认踢出之前登录的用户
|
||||||
|
kickoutAfter: false
|
||||||
|
|
||||||
|
# 防止XSS攻击
|
||||||
|
xss:
|
||||||
|
# 过滤开关
|
||||||
|
enabled: true
|
||||||
|
# 排除链接(多个用逗号分隔)
|
||||||
|
excludes: /system/notice/*
|
||||||
|
# 匹配链接
|
||||||
|
urlPatterns: /system/*,/monitor/*,/tool/*
|
||||||
|
|
||||||
|
#rabbitmq
|
||||||
|
rabbitmq:
|
||||||
|
host: localhost
|
||||||
|
port: 5672
|
||||||
|
username: zhang
|
||||||
|
password: zhang
|
||||||
|
|
||||||
|
#消息确认配置项
|
||||||
|
#确认消息已发送到交换机(Exchange)
|
||||||
|
publisher-confirms: true
|
||||||
|
#确认消息已发送到队列(Queue)
|
||||||
|
publisher-returns: true
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
ITEM_INFO_KEY=ITEM_INFO
|
||||||
|
ITEM_INFO_BASE_KEY=BASE
|
||||||
|
ITEM_INFO_DESC_KEY=DESC
|
||||||
|
ITEM_INFO_EXPIRE=24
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ehcache name="basepro" updateCheck="false">
|
||||||
|
|
||||||
|
<!-- 磁盘缓存位置 -->
|
||||||
|
<diskStore path="java.io.tmpdir"/>
|
||||||
|
|
||||||
|
<!-- maxEntriesLocalHeap:堆内存中最大缓存对象数,0没有限制 -->
|
||||||
|
<!-- maxElementsInMemory: 在内存中缓存的element的最大数目。-->
|
||||||
|
<!-- eternal:elements是否永久有效,如果为true,timeouts将被忽略,element将永不过期 -->
|
||||||
|
<!-- timeToIdleSeconds:失效前的空闲秒数,当eternal为false时,这个属性才有效,0为不限制 -->
|
||||||
|
<!-- timeToLiveSeconds:失效前的存活秒数,创建时间到失效时间的间隔为存活时间,当eternal为false时,这个属性才有效,0为不限制 -->
|
||||||
|
<!-- overflowToDisk: 如果内存中数据超过内存限制,是否要缓存到磁盘上 -->
|
||||||
|
<!-- statistics:是否收集统计信息。如果需要监控缓存使用情况,应该打开这个选项。默认为关闭(统计会影响性能)。设置statistics="true"开启统计 -->
|
||||||
|
|
||||||
|
<!-- 默认缓存 -->
|
||||||
|
<defaultCache
|
||||||
|
maxEntriesLocalHeap="1000"
|
||||||
|
eternal="false"
|
||||||
|
timeToIdleSeconds="3600"
|
||||||
|
timeToLiveSeconds="3600"
|
||||||
|
overflowToDisk="false">
|
||||||
|
</defaultCache>
|
||||||
|
|
||||||
|
<!-- 登录记录缓存 锁定10分钟 -->
|
||||||
|
<cache name="loginRecordCache"
|
||||||
|
maxEntriesLocalHeap="2000"
|
||||||
|
eternal="false"
|
||||||
|
timeToIdleSeconds="600"
|
||||||
|
timeToLiveSeconds="0"
|
||||||
|
overflowToDisk="false"
|
||||||
|
statistics="true">
|
||||||
|
</cache>
|
||||||
|
|
||||||
|
<!-- 系统活跃用户缓存 -->
|
||||||
|
<cache name="sys-userCache"
|
||||||
|
maxEntriesLocalHeap="10000"
|
||||||
|
overflowToDisk="false"
|
||||||
|
eternal="false"
|
||||||
|
diskPersistent="false"
|
||||||
|
timeToLiveSeconds="0"
|
||||||
|
timeToIdleSeconds="0"
|
||||||
|
statistics="true">
|
||||||
|
</cache>
|
||||||
|
|
||||||
|
<!-- 系统会话缓存 -->
|
||||||
|
<cache name="shiro-activeSessionCache"
|
||||||
|
maxElementsInMemory="10000"
|
||||||
|
overflowToDisk="true"
|
||||||
|
eternal="true"
|
||||||
|
timeToLiveSeconds="0"
|
||||||
|
timeToIdleSeconds="0"
|
||||||
|
diskPersistent="true"
|
||||||
|
diskExpiryThreadIntervalSeconds="600">
|
||||||
|
</cache>
|
||||||
|
|
||||||
|
</ehcache>
|
||||||
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE configuration
|
||||||
|
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-config.dtd">
|
||||||
|
|
||||||
|
<configuration>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
<!-- com.github.pagehelper为PageHelper类所在包名 -->
|
||||||
|
<plugin interceptor="com.github.pagehelper.PageHelper">
|
||||||
|
<!-- 设置数据库类型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六种数据库-->
|
||||||
|
<property name="dialect" value="mysql"/>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
|
||||||
|
</configuration>
|
||||||
|
|
@ -0,0 +1,141 @@
|
||||||
|
<?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">
|
||||||
|
<parent>
|
||||||
|
<artifactId>basepro-manager</artifactId>
|
||||||
|
<groupId>guo.ping.e3mall</groupId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>basepro-common</artifactId>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
common通用工具
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- Spring框架基本的核心工具 -->
|
||||||
|
<!--<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-context-support</artifactId>
|
||||||
|
</dependency>-->
|
||||||
|
|
||||||
|
<!-- SpringWeb模块 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--Shiro核心框架 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.shiro</groupId>
|
||||||
|
<artifactId>shiro-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- pagehelper 分页插件 -->
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.pagehelper</groupId>
|
||||||
|
<artifactId>pagehelper</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- 自定义验证注解 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.validation</groupId>
|
||||||
|
<artifactId>validation-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--常用工具类 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- JSON工具类 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 阿里JSON解析器 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>fastjson</artifactId>
|
||||||
|
<version>1.2.46</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- io常用工具类 -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 文件上传工具类 -->
|
||||||
|
<!--<dependency>
|
||||||
|
<groupId>commons-fileupload</groupId>
|
||||||
|
<artifactId>commons-fileupload</artifactId>
|
||||||
|
</dependency>-->
|
||||||
|
|
||||||
|
<!-- excel工具 -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- yml解析器 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.yaml</groupId>
|
||||||
|
<artifactId>snakeyaml</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.poi</groupId>
|
||||||
|
<artifactId>poi</artifactId>
|
||||||
|
<version>3.17</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.poi</groupId>
|
||||||
|
<artifactId>poi-ooxml</artifactId>
|
||||||
|
<version>3.17</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.poi</groupId>
|
||||||
|
<artifactId>poi-ooxml-schemas</artifactId>
|
||||||
|
<version>3.17</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- Shiro使用Srping框架 -->
|
||||||
|
<!--<dependency>
|
||||||
|
<groupId>org.apache.shiro</groupId>
|
||||||
|
<artifactId>shiro-spring</artifactId>
|
||||||
|
<version>1.4.1</version>
|
||||||
|
</dependency>-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-fileupload</groupId>
|
||||||
|
<artifactId>commons-fileupload</artifactId>
|
||||||
|
<version>1.3.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
<version>2.5</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-pool2</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-aop</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.servlet</groupId>
|
||||||
|
<artifactId>servlet-api</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- servlet包 -->
|
||||||
|
|
||||||
|
<!--fastdfs-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.bestwu</groupId>
|
||||||
|
<artifactId>fastdfs-client-java</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package basepro.manager.common.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据权限过滤注解
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface DataScope
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 部门表的别名
|
||||||
|
*/
|
||||||
|
public String deptAlias() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户表的别名
|
||||||
|
*/
|
||||||
|
public String userAlias() default "";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package basepro.manager.common.annotation;
|
||||||
|
|
||||||
|
import basepro.manager.common.enums.DataSourceType;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Inherited;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义多数据源切换注解
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Inherited
|
||||||
|
public @interface DataSource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 切换数据源名称
|
||||||
|
*/
|
||||||
|
public DataSourceType value() default DataSourceType.MASTER;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
package basepro.manager.common.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义导出Excel数据注解
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
public @interface Excel
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 导出到Excel中的名字.
|
||||||
|
*/
|
||||||
|
public String name() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期格式, 如: yyyy-MM-dd
|
||||||
|
*/
|
||||||
|
public String dateFormat() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取内容转表达式 (如: 0=男,1=女,2=未知)
|
||||||
|
*/
|
||||||
|
public String readConverterExp() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出类型(0数字 1字符串)
|
||||||
|
*/
|
||||||
|
public ColumnType cellType() default ColumnType.STRING;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出时在excel中每个列的高度 单位为字符
|
||||||
|
*/
|
||||||
|
public double height() default 14;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出时在excel中每个列的宽 单位为字符
|
||||||
|
*/
|
||||||
|
public double width() default 16;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文字后缀,如% 90 变成90%
|
||||||
|
*/
|
||||||
|
public String suffix() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当值为空时,字段的默认值
|
||||||
|
*/
|
||||||
|
public String defaultValue() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提示信息
|
||||||
|
*/
|
||||||
|
public String prompt() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置只能选择不能输入的列内容.
|
||||||
|
*/
|
||||||
|
public String[] combo() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
|
||||||
|
*/
|
||||||
|
public boolean isExport() default true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 另一个类中的属性名称,支持多级获取,以小数点隔开
|
||||||
|
*/
|
||||||
|
public String targetAttr() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字段类型(0:导出导入;1:仅导出;2:仅导入)
|
||||||
|
*/
|
||||||
|
Type type() default Type.ALL;
|
||||||
|
|
||||||
|
public enum Type
|
||||||
|
{
|
||||||
|
ALL(0), EXPORT(1), IMPORT(2);
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
Type(int value)
|
||||||
|
{
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int value()
|
||||||
|
{
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ColumnType
|
||||||
|
{
|
||||||
|
NUMERIC(0), STRING(1);
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
ColumnType(int value)
|
||||||
|
{
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int value()
|
||||||
|
{
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package basepro.manager.common.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Excel注解集
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Excels
|
||||||
|
{
|
||||||
|
Excel[] value();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package basepro.manager.common.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import basepro.manager.common.enums.BusinessType;
|
||||||
|
import basepro.manager.common.enums.OperatorType;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义操作日志记录注解
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
@Target({ ElementType.PARAMETER, ElementType.METHOD })
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
public @interface Log
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 模块
|
||||||
|
*/
|
||||||
|
public String title() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 功能
|
||||||
|
*/
|
||||||
|
public BusinessType businessType() default BusinessType.OTHER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作人类别
|
||||||
|
*/
|
||||||
|
public OperatorType operatorType() default OperatorType.MANAGE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否保存请求的参数
|
||||||
|
*/
|
||||||
|
public boolean isSaveRequestData() default true;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
package basepro.manager.common.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Inherited;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义注解防止表单重复提交
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Inherited
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
public @interface RepeatSubmit
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,144 @@
|
||||||
|
package basepro.manager.common.config;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import basepro.manager.common.utils.StringUtils;
|
||||||
|
import basepro.manager.common.utils.YamlUtil;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局配置类
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class Global
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(Global.class);
|
||||||
|
|
||||||
|
private static String NAME = "application.yml";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前对象实例
|
||||||
|
*/
|
||||||
|
private static Global global;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存全局属性值
|
||||||
|
*/
|
||||||
|
private static Map<String, String> map = new HashMap<String, String>();
|
||||||
|
|
||||||
|
private Global()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 静态工厂方法
|
||||||
|
*/
|
||||||
|
public static synchronized Global getInstance()
|
||||||
|
{
|
||||||
|
if (global == null)
|
||||||
|
{
|
||||||
|
global = new Global();
|
||||||
|
}
|
||||||
|
return global;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取配置
|
||||||
|
*/
|
||||||
|
public static String getConfig(String key)
|
||||||
|
{
|
||||||
|
String value = map.get(key);
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
Map<?, ?> yamlMap = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
yamlMap = YamlUtil.loadYaml(NAME);
|
||||||
|
value = String.valueOf(YamlUtil.getProperty(yamlMap, key));
|
||||||
|
map.put(key, value != null ? value : StringUtils.EMPTY);
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException e)
|
||||||
|
{
|
||||||
|
log.error("获取全局配置异常 {}", key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取项目名称
|
||||||
|
*/
|
||||||
|
public static String getName()
|
||||||
|
{
|
||||||
|
return StringUtils.nvl(getConfig("basepro.name"), "RuoYi");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取项目版本
|
||||||
|
*/
|
||||||
|
public static String getVersion()
|
||||||
|
{
|
||||||
|
return StringUtils.nvl(getConfig("basepro.version"), "4.1.0");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取版权年份
|
||||||
|
*/
|
||||||
|
public static String getCopyrightYear()
|
||||||
|
{
|
||||||
|
return StringUtils.nvl(getConfig("basepro.copyrightYear"), "2019");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实例演示开关
|
||||||
|
*/
|
||||||
|
public static String isDemoEnabled()
|
||||||
|
{
|
||||||
|
return StringUtils.nvl(getConfig("basepro.demoEnabled"), "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取ip地址开关
|
||||||
|
*/
|
||||||
|
public static Boolean isAddressEnabled()
|
||||||
|
{
|
||||||
|
return Boolean.valueOf(getConfig("basepro.addressEnabled"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文件上传路径
|
||||||
|
*/
|
||||||
|
public static String getProfile()
|
||||||
|
{
|
||||||
|
return getConfig("basepro.profile");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取头像上传路径
|
||||||
|
*/
|
||||||
|
public static String getAvatarPath()
|
||||||
|
{
|
||||||
|
return getProfile() + "/avatar";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取下载路径
|
||||||
|
*/
|
||||||
|
public static String getDownloadPath()
|
||||||
|
{
|
||||||
|
return getProfile() + "/download/";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取上传路径
|
||||||
|
*/
|
||||||
|
public static String getUploadPath()
|
||||||
|
{
|
||||||
|
return getProfile() + "/upload";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
package basepro.manager.common.config;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import basepro.manager.common.utils.ServletUtils;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务相关配置
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class ServerConfig
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取完整的请求路径,包括:域名,端口,上下文访问路径
|
||||||
|
*
|
||||||
|
* @return 服务地址
|
||||||
|
*/
|
||||||
|
public String getUrl()
|
||||||
|
{
|
||||||
|
HttpServletRequest request = ServletUtils.getRequest();
|
||||||
|
return getDomain(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getDomain(HttpServletRequest request)
|
||||||
|
{
|
||||||
|
StringBuffer url = request.getRequestURL();
|
||||||
|
String contextPath = request.getContextPath();
|
||||||
|
return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
package basepro.manager.common.config.datasource;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据源切换处理
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class DynamicDataSourceContextHolder
|
||||||
|
{
|
||||||
|
public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
|
||||||
|
* 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
|
||||||
|
*/
|
||||||
|
private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置数据源的变量
|
||||||
|
*/
|
||||||
|
public static void setDataSourceType(String dsType)
|
||||||
|
{
|
||||||
|
log.info("切换到{}数据源", dsType);
|
||||||
|
CONTEXT_HOLDER.set(dsType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得数据源的变量
|
||||||
|
*/
|
||||||
|
public static String getDataSourceType()
|
||||||
|
{
|
||||||
|
return CONTEXT_HOLDER.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空数据源变量
|
||||||
|
*/
|
||||||
|
public static void clearDataSourceType()
|
||||||
|
{
|
||||||
|
CONTEXT_HOLDER.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
package basepro.manager.common.config.thread;
|
||||||
|
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
|
import basepro.manager.common.utils.Threads;
|
||||||
|
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 线程池配置
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
**/
|
||||||
|
@Configuration
|
||||||
|
public class ThreadPoolConfig
|
||||||
|
{
|
||||||
|
// 核心线程池大小
|
||||||
|
private int corePoolSize = 50;
|
||||||
|
|
||||||
|
// 最大可创建的线程数
|
||||||
|
private int maxPoolSize = 200;
|
||||||
|
|
||||||
|
// 队列最大长度
|
||||||
|
private int queueCapacity = 1000;
|
||||||
|
|
||||||
|
// 线程池维护线程所允许的空闲时间
|
||||||
|
private int keepAliveSeconds = 300;
|
||||||
|
|
||||||
|
@Bean(name = "threadPoolTaskExecutor")
|
||||||
|
public ThreadPoolTaskExecutor threadPoolTaskExecutor()
|
||||||
|
{
|
||||||
|
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||||
|
executor.setMaxPoolSize(maxPoolSize);
|
||||||
|
executor.setCorePoolSize(corePoolSize);
|
||||||
|
executor.setQueueCapacity(queueCapacity);
|
||||||
|
executor.setKeepAliveSeconds(keepAliveSeconds);
|
||||||
|
// 线程池对拒绝任务(无线程可用)的处理策略
|
||||||
|
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行周期性或定时任务
|
||||||
|
*/
|
||||||
|
//@Bean(name = "scheduledExecutorService")
|
||||||
|
protected ScheduledExecutorService scheduledExecutorService()
|
||||||
|
{
|
||||||
|
return new ScheduledThreadPoolExecutor(corePoolSize,
|
||||||
|
new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build())
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void afterExecute(Runnable r, Throwable t)
|
||||||
|
{
|
||||||
|
super.afterExecute(r, t);
|
||||||
|
Threads.printException(r, t);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
package basepro.manager.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用常量信息
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class Constants
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* UTF-8 字符集
|
||||||
|
*/
|
||||||
|
public static final String UTF8 = "UTF-8";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用成功标识
|
||||||
|
*/
|
||||||
|
public static final String SUCCESS = "0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用失败标识
|
||||||
|
*/
|
||||||
|
public static final String FAIL = "1";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录成功
|
||||||
|
*/
|
||||||
|
public static final String LOGIN_SUCCESS = "Success";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注销
|
||||||
|
*/
|
||||||
|
public static final String LOGOUT = "Logout";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录失败
|
||||||
|
*/
|
||||||
|
public static final String LOGIN_FAIL = "Error";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动去除表前缀
|
||||||
|
*/
|
||||||
|
public static final String AUTO_REOMVE_PRE = "true";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前记录起始索引
|
||||||
|
*/
|
||||||
|
public static final String PAGE_NUM = "pageNum";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每页显示记录数
|
||||||
|
*/
|
||||||
|
public static final String PAGE_SIZE = "pageSize";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序列
|
||||||
|
*/
|
||||||
|
public static final String ORDER_BY_COLUMN = "orderByColumn";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序的方向 "desc" 或者 "asc".
|
||||||
|
*/
|
||||||
|
public static final String IS_ASC = "isAsc";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源映射路径 前缀
|
||||||
|
*/
|
||||||
|
public static final String RESOURCE_PREFIX = "/profile";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
package basepro.manager.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 代码生成通用常量
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class GenConstants
|
||||||
|
{
|
||||||
|
/** 单表(增删改查) */
|
||||||
|
public static final String TPL_CRUD = "crud";
|
||||||
|
|
||||||
|
/** 树表(增删改查) */
|
||||||
|
public static final String TPL_TREE = "tree";
|
||||||
|
|
||||||
|
/** 树编码字段 */
|
||||||
|
public static final String TREE_CODE = "treeCode";
|
||||||
|
|
||||||
|
/** 树父编码字段 */
|
||||||
|
public static final String TREE_PARENT_CODE = "treeParentCode";
|
||||||
|
|
||||||
|
/** 树名称字段 */
|
||||||
|
public static final String TREE_NAME = "treeName";
|
||||||
|
|
||||||
|
/** 数据库字符串类型 */
|
||||||
|
public static final String[] COLUMNTYPE_STR = { "char", "varchar", "narchar", "varchar2", "tinytext", "text",
|
||||||
|
"mediumtext", "longtext" };
|
||||||
|
|
||||||
|
/** 数据库时间类型 */
|
||||||
|
public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" };
|
||||||
|
|
||||||
|
/** 数据库数字类型 */
|
||||||
|
public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
|
||||||
|
"bigint", "float", "float", "double", "decimal" };
|
||||||
|
|
||||||
|
/** 页面不需要编辑字段 */
|
||||||
|
public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" };
|
||||||
|
|
||||||
|
/** 页面不需要显示的列表字段 */
|
||||||
|
public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by",
|
||||||
|
"update_time" };
|
||||||
|
|
||||||
|
/** 页面不需要查询字段 */
|
||||||
|
public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by",
|
||||||
|
"update_time", "remark" };
|
||||||
|
|
||||||
|
/** Entity基类字段 */
|
||||||
|
public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" };
|
||||||
|
|
||||||
|
/** Tree基类字段 */
|
||||||
|
public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors" };
|
||||||
|
|
||||||
|
/** 文本框 */
|
||||||
|
public static final String HTML_INPUT = "input";
|
||||||
|
|
||||||
|
/** 文本域 */
|
||||||
|
public static final String HTML_TEXTAREA = "textarea";
|
||||||
|
|
||||||
|
/** 下拉框 */
|
||||||
|
public static final String HTML_SELECT = "select";
|
||||||
|
|
||||||
|
/** 单选框 */
|
||||||
|
public static final String HTML_RADIO = "radio";
|
||||||
|
|
||||||
|
/** 复选框 */
|
||||||
|
public static final String HTML_CHECKBOX = "checkbox";
|
||||||
|
|
||||||
|
/** 日期控件 */
|
||||||
|
public static final String HTML_DATETIME = "datetime";
|
||||||
|
|
||||||
|
/** 字符串类型 */
|
||||||
|
public static final String TYPE_STRING = "String";
|
||||||
|
|
||||||
|
/** 整型 */
|
||||||
|
public static final String TYPE_INTEGER = "Integer";
|
||||||
|
|
||||||
|
/** 长整型 */
|
||||||
|
public static final String TYPE_LONG = "Long";
|
||||||
|
|
||||||
|
/** 浮点型 */
|
||||||
|
public static final String TYPE_DOUBLE = "Double";
|
||||||
|
|
||||||
|
/** 高精度计算类型 */
|
||||||
|
public static final String TYPE_BIGDECIMAL = "BigDecimal";
|
||||||
|
|
||||||
|
/** 时间类型 */
|
||||||
|
public static final String TYPE_DATE = "Date";
|
||||||
|
|
||||||
|
/** 模糊查询 */
|
||||||
|
public static final String QUERY_LIKE = "LIKE";
|
||||||
|
|
||||||
|
/** 需要 */
|
||||||
|
public static final String REQUIRE = "1";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package basepro.manager.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 权限通用常量
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class PermissionConstants
|
||||||
|
{
|
||||||
|
/** 新增权限 */
|
||||||
|
public static final String ADD_PERMISSION = "add";
|
||||||
|
|
||||||
|
/** 修改权限 */
|
||||||
|
public static final String EDIT_PERMISSION = "edit";
|
||||||
|
|
||||||
|
/** 删除权限 */
|
||||||
|
public static final String REMOVE_PERMISSION = "remove";
|
||||||
|
|
||||||
|
/** 导出权限 */
|
||||||
|
public static final String EXPORT_PERMISSION = "export";
|
||||||
|
|
||||||
|
/** 显示权限 */
|
||||||
|
public static final String VIEW_PERMISSION = "view";
|
||||||
|
|
||||||
|
/** 查询权限 */
|
||||||
|
public static final String LIST_PERMISSION = "list";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
package basepro.manager.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务调度通用常量
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public interface ScheduleConstants
|
||||||
|
{
|
||||||
|
public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME";
|
||||||
|
|
||||||
|
/** 执行目标key */
|
||||||
|
public static final String TASK_PROPERTIES = "TASK_PROPERTIES";
|
||||||
|
|
||||||
|
/** 默认 */
|
||||||
|
public static final String MISFIRE_DEFAULT = "0";
|
||||||
|
|
||||||
|
/** 立即触发执行 */
|
||||||
|
public static final String MISFIRE_IGNORE_MISFIRES = "1";
|
||||||
|
|
||||||
|
/** 触发一次执行 */
|
||||||
|
public static final String MISFIRE_FIRE_AND_PROCEED = "2";
|
||||||
|
|
||||||
|
/** 不触发立即执行 */
|
||||||
|
public static final String MISFIRE_DO_NOTHING = "3";
|
||||||
|
|
||||||
|
public enum Status
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 正常
|
||||||
|
*/
|
||||||
|
NORMAL("0"),
|
||||||
|
/**
|
||||||
|
* 暂停
|
||||||
|
*/
|
||||||
|
PAUSE("1");
|
||||||
|
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
private Status(String value)
|
||||||
|
{
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue()
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
package basepro.manager.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shiro通用常量
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public interface ShiroConstants
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 当前登录的用户
|
||||||
|
*/
|
||||||
|
public static final String CURRENT_USER = "currentUser";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户名
|
||||||
|
*/
|
||||||
|
public static final String CURRENT_USERNAME = "username";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息key
|
||||||
|
*/
|
||||||
|
public static String MESSAGE = "message";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误key
|
||||||
|
*/
|
||||||
|
public static String ERROR = "errorMsg";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编码格式
|
||||||
|
*/
|
||||||
|
public static String ENCODING = "UTF-8";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前在线会话
|
||||||
|
*/
|
||||||
|
public String ONLINE_SESSION = "online_session";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码key
|
||||||
|
*/
|
||||||
|
public static final String CURRENT_CAPTCHA = "captcha";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码开关
|
||||||
|
*/
|
||||||
|
public static final String CURRENT_ENABLED = "captchaEnabled";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码类型
|
||||||
|
*/
|
||||||
|
public static final String CURRENT_TYPE = "captchaType";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码
|
||||||
|
*/
|
||||||
|
public static final String CURRENT_VALIDATECODE = "validateCode";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码错误
|
||||||
|
*/
|
||||||
|
public static final String CAPTCHA_ERROR = "captchaError";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录记录缓存
|
||||||
|
*/
|
||||||
|
public static final String LOGINRECORDCACHE = "loginRecordCache";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统活跃用户缓存
|
||||||
|
*/
|
||||||
|
public static final String SYS_USERCACHE = "sys-userCache";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
package basepro.manager.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户常量信息
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class UserConstants
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 平台内系统用户的唯一标志
|
||||||
|
*/
|
||||||
|
public static final String SYS_USER = "SYS_USER";
|
||||||
|
|
||||||
|
/** 正常状态 */
|
||||||
|
public static final String NORMAL = "0";
|
||||||
|
|
||||||
|
/** 异常状态 */
|
||||||
|
public static final String EXCEPTION = "1";
|
||||||
|
|
||||||
|
/** 用户封禁状态 */
|
||||||
|
public static final String USER_BLOCKED = "1";
|
||||||
|
|
||||||
|
/** 角色封禁状态 */
|
||||||
|
public static final String ROLE_BLOCKED = "1";
|
||||||
|
|
||||||
|
/** 部门正常状态 */
|
||||||
|
public static final String DEPT_NORMAL = "0";
|
||||||
|
|
||||||
|
/** 字典正常状态 */
|
||||||
|
public static final String DICT_NORMAL = "0";
|
||||||
|
|
||||||
|
/** 是否为系统默认(是) */
|
||||||
|
public static final String YES = "Y";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户名长度限制
|
||||||
|
*/
|
||||||
|
public static final int USERNAME_MIN_LENGTH = 2;
|
||||||
|
public static final int USERNAME_MAX_LENGTH = 20;
|
||||||
|
|
||||||
|
/** 登录名称是否唯一的返回结果码 */
|
||||||
|
public final static String USER_NAME_UNIQUE = "0";
|
||||||
|
public final static String USER_NAME_NOT_UNIQUE = "1";
|
||||||
|
|
||||||
|
/** 手机号码是否唯一的返回结果 */
|
||||||
|
public final static String USER_PHONE_UNIQUE = "0";
|
||||||
|
public final static String USER_PHONE_NOT_UNIQUE = "1";
|
||||||
|
|
||||||
|
/** e-mail 是否唯一的返回结果 */
|
||||||
|
public final static String USER_EMAIL_UNIQUE = "0";
|
||||||
|
public final static String USER_EMAIL_NOT_UNIQUE = "1";
|
||||||
|
|
||||||
|
/** 部门名称是否唯一的返回结果码 */
|
||||||
|
public final static String DEPT_NAME_UNIQUE = "0";
|
||||||
|
public final static String DEPT_NAME_NOT_UNIQUE = "1";
|
||||||
|
|
||||||
|
/** 角色名称是否唯一的返回结果码 */
|
||||||
|
public final static String ROLE_NAME_UNIQUE = "0";
|
||||||
|
public final static String ROLE_NAME_NOT_UNIQUE = "1";
|
||||||
|
|
||||||
|
/** 岗位名称是否唯一的返回结果码 */
|
||||||
|
public final static String POST_NAME_UNIQUE = "0";
|
||||||
|
public final static String POST_NAME_NOT_UNIQUE = "1";
|
||||||
|
|
||||||
|
/** 角色权限是否唯一的返回结果码 */
|
||||||
|
public final static String ROLE_KEY_UNIQUE = "0";
|
||||||
|
public final static String ROLE_KEY_NOT_UNIQUE = "1";
|
||||||
|
|
||||||
|
/** 岗位编码是否唯一的返回结果码 */
|
||||||
|
public final static String POST_CODE_UNIQUE = "0";
|
||||||
|
public final static String POST_CODE_NOT_UNIQUE = "1";
|
||||||
|
|
||||||
|
/** 菜单名称是否唯一的返回结果码 */
|
||||||
|
public final static String MENU_NAME_UNIQUE = "0";
|
||||||
|
public final static String MENU_NAME_NOT_UNIQUE = "1";
|
||||||
|
|
||||||
|
/** 字典类型是否唯一的返回结果码 */
|
||||||
|
public final static String DICT_TYPE_UNIQUE = "0";
|
||||||
|
public final static String DICT_TYPE_NOT_UNIQUE = "1";
|
||||||
|
|
||||||
|
/** 参数键名是否唯一的返回结果码 */
|
||||||
|
public final static String CONFIG_KEY_UNIQUE = "0";
|
||||||
|
public final static String CONFIG_KEY_NOT_UNIQUE = "1";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码长度限制
|
||||||
|
*/
|
||||||
|
public static final int PASSWORD_MIN_LENGTH = 5;
|
||||||
|
public static final int PASSWORD_MAX_LENGTH = 20;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号码格式限制
|
||||||
|
*/
|
||||||
|
public static final String MOBILE_PHONE_NUMBER_PATTERN = "^0{0,1}(13[0-9]|15[0-9]|14[0-9]|18[0-9])[0-9]{8}$";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮箱格式限制
|
||||||
|
*/
|
||||||
|
public static final String EMAIL_PATTERN = "^((([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,172 @@
|
||||||
|
package basepro.manager.common.core.controller;
|
||||||
|
|
||||||
|
import java.beans.PropertyEditorSupport;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
|
import basepro.manager.common.core.domain.AjaxResult;
|
||||||
|
import basepro.manager.common.core.page.PageDomain;
|
||||||
|
import basepro.manager.common.core.page.TableDataInfo;
|
||||||
|
import basepro.manager.common.core.page.TableSupport;
|
||||||
|
import basepro.manager.common.utils.DateUtils;
|
||||||
|
import basepro.manager.common.utils.ServletUtils;
|
||||||
|
import basepro.manager.common.utils.StringUtils;
|
||||||
|
import basepro.manager.common.utils.sql.SqlUtil;
|
||||||
|
import com.github.pagehelper.PageInfo;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.web.bind.WebDataBinder;
|
||||||
|
import org.springframework.web.bind.annotation.InitBinder;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* web层通用数据处理
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class BaseController
|
||||||
|
{
|
||||||
|
protected final Logger logger = LoggerFactory.getLogger(BaseController.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将前台传递过来的日期格式的字符串,自动转化为Date类型
|
||||||
|
*/
|
||||||
|
@InitBinder
|
||||||
|
public void initBinder(WebDataBinder binder)
|
||||||
|
{
|
||||||
|
// Date 类型转换
|
||||||
|
binder.registerCustomEditor(Date.class, new PropertyEditorSupport()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void setAsText(String text)
|
||||||
|
{
|
||||||
|
setValue(DateUtils.parseDate(text));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置请求分页数据
|
||||||
|
*/
|
||||||
|
/* protected void startPage()
|
||||||
|
{
|
||||||
|
PageDomain pageDomain = TableSupport.buildPageRequest();
|
||||||
|
Integer pageNum = pageDomain.getPageNum();
|
||||||
|
Integer pageSize = pageDomain.getPageSize();
|
||||||
|
if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize))
|
||||||
|
{
|
||||||
|
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
|
||||||
|
PageHelper.startPage(pageNum, pageSize, orderBy);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取request
|
||||||
|
*/
|
||||||
|
public HttpServletRequest getRequest()
|
||||||
|
{
|
||||||
|
return ServletUtils.getRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取response
|
||||||
|
*/
|
||||||
|
public HttpServletResponse getResponse()
|
||||||
|
{
|
||||||
|
return ServletUtils.getResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取session
|
||||||
|
*/
|
||||||
|
public HttpSession getSession()
|
||||||
|
{
|
||||||
|
return getRequest().getSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 响应请求分页数据
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
|
protected TableDataInfo getDataTable(List<?> list)
|
||||||
|
{
|
||||||
|
TableDataInfo rspData = new TableDataInfo();
|
||||||
|
rspData.setCode(0);
|
||||||
|
rspData.setRows(list);
|
||||||
|
rspData.setTotal(new PageInfo(list).getTotal());
|
||||||
|
return rspData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 响应返回结果
|
||||||
|
*
|
||||||
|
* @param rows 影响行数
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
protected AjaxResult toAjax(int rows)
|
||||||
|
{
|
||||||
|
return rows > 0 ? success() : error();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 响应返回结果
|
||||||
|
*
|
||||||
|
* @param result 结果
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
protected AjaxResult toAjax(boolean result)
|
||||||
|
{
|
||||||
|
return result ? success() : error();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回成功
|
||||||
|
*/
|
||||||
|
public AjaxResult success()
|
||||||
|
{
|
||||||
|
return AjaxResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回失败消息
|
||||||
|
*/
|
||||||
|
public AjaxResult error()
|
||||||
|
{
|
||||||
|
return AjaxResult.error();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回成功消息
|
||||||
|
*/
|
||||||
|
public AjaxResult success(String message)
|
||||||
|
{
|
||||||
|
return AjaxResult.success(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回失败消息
|
||||||
|
*/
|
||||||
|
public AjaxResult error(String message)
|
||||||
|
{
|
||||||
|
return AjaxResult.error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回错误码消息
|
||||||
|
*/
|
||||||
|
public AjaxResult error(AjaxResult.Type type, String message)
|
||||||
|
{
|
||||||
|
return new AjaxResult(type, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 页面跳转
|
||||||
|
*/
|
||||||
|
public String redirect(String url)
|
||||||
|
{
|
||||||
|
return StringUtils.format("redirect:{}", url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,184 @@
|
||||||
|
package basepro.manager.common.core.domain;
|
||||||
|
|
||||||
|
import basepro.manager.common.utils.StringUtils;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作消息提醒
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class AjaxResult extends HashMap<String, Object>
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 状态码 */
|
||||||
|
public static final String CODE_TAG = "code";
|
||||||
|
|
||||||
|
/** 返回内容 */
|
||||||
|
public static final String MSG_TAG = "msg";
|
||||||
|
|
||||||
|
/** 数据对象 */
|
||||||
|
public static final String DATA_TAG = "data";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态类型
|
||||||
|
*/
|
||||||
|
public enum Type
|
||||||
|
{
|
||||||
|
/** 成功 */
|
||||||
|
SUCCESS(0),
|
||||||
|
/** 警告 */
|
||||||
|
WARN(301),
|
||||||
|
/** 错误 */
|
||||||
|
ERROR(500);
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
Type(int value)
|
||||||
|
{
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int value()
|
||||||
|
{
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
|
||||||
|
*/
|
||||||
|
public AjaxResult()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化一个新创建的 AjaxResult 对象
|
||||||
|
*
|
||||||
|
* @param type 状态类型
|
||||||
|
* @param msg 返回内容
|
||||||
|
*/
|
||||||
|
public AjaxResult(Type type, String msg)
|
||||||
|
{
|
||||||
|
super.put(CODE_TAG, type.value);
|
||||||
|
super.put(MSG_TAG, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化一个新创建的 AjaxResult 对象
|
||||||
|
*
|
||||||
|
* @param type 状态类型
|
||||||
|
* @param msg 返回内容
|
||||||
|
* @param data 数据对象
|
||||||
|
*/
|
||||||
|
public AjaxResult(Type type, String msg, Object data)
|
||||||
|
{
|
||||||
|
super.put(CODE_TAG, type.value);
|
||||||
|
super.put(MSG_TAG, msg);
|
||||||
|
if (StringUtils.isNotNull(data))
|
||||||
|
{
|
||||||
|
super.put(DATA_TAG, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回成功消息
|
||||||
|
*
|
||||||
|
* @return 成功消息
|
||||||
|
*/
|
||||||
|
public static AjaxResult success()
|
||||||
|
{
|
||||||
|
return AjaxResult.success("操作成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回成功数据
|
||||||
|
*
|
||||||
|
* @return 成功消息
|
||||||
|
*/
|
||||||
|
public static AjaxResult success(Object data)
|
||||||
|
{
|
||||||
|
return AjaxResult.success("操作成功", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回成功消息
|
||||||
|
*
|
||||||
|
* @param msg 返回内容
|
||||||
|
* @return 成功消息
|
||||||
|
*/
|
||||||
|
public static AjaxResult success(String msg)
|
||||||
|
{
|
||||||
|
return AjaxResult.success(msg, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回成功消息
|
||||||
|
*
|
||||||
|
* @param msg 返回内容
|
||||||
|
* @param data 数据对象
|
||||||
|
* @return 成功消息
|
||||||
|
*/
|
||||||
|
public static AjaxResult success(String msg, Object data)
|
||||||
|
{
|
||||||
|
return new AjaxResult(Type.SUCCESS, msg, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回警告消息
|
||||||
|
*
|
||||||
|
* @param msg 返回内容
|
||||||
|
* @return 警告消息
|
||||||
|
*/
|
||||||
|
public static AjaxResult warn(String msg)
|
||||||
|
{
|
||||||
|
return AjaxResult.warn(msg, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回警告消息
|
||||||
|
*
|
||||||
|
* @param msg 返回内容
|
||||||
|
* @param data 数据对象
|
||||||
|
* @return 警告消息
|
||||||
|
*/
|
||||||
|
public static AjaxResult warn(String msg, Object data)
|
||||||
|
{
|
||||||
|
return new AjaxResult(Type.WARN, msg, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回错误消息
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static AjaxResult error()
|
||||||
|
{
|
||||||
|
return AjaxResult.error("操作失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回错误消息
|
||||||
|
*
|
||||||
|
* @param msg 返回内容
|
||||||
|
* @return 警告消息
|
||||||
|
*/
|
||||||
|
public static AjaxResult error(String msg)
|
||||||
|
{
|
||||||
|
return AjaxResult.error(msg, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回错误消息
|
||||||
|
*
|
||||||
|
* @param msg 返回内容
|
||||||
|
* @param data 数据对象
|
||||||
|
* @return 警告消息
|
||||||
|
*/
|
||||||
|
public static AjaxResult error(String msg, Object data)
|
||||||
|
{
|
||||||
|
return new AjaxResult(Type.ERROR, msg, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
package basepro.manager.common.core.domain;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entity基类
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class BaseEntity implements Serializable
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 搜索值 */
|
||||||
|
private String searchValue;
|
||||||
|
|
||||||
|
/** 创建者 */
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
/** 创建时间 */
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
/** 更新者 */
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
/** 更新时间 */
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
/** 备注 */
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
/** 请求参数 */
|
||||||
|
private Map<String, Object> params;
|
||||||
|
|
||||||
|
public String getSearchValue()
|
||||||
|
{
|
||||||
|
return searchValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSearchValue(String searchValue)
|
||||||
|
{
|
||||||
|
this.searchValue = searchValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreateBy()
|
||||||
|
{
|
||||||
|
return createBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreateBy(String createBy)
|
||||||
|
{
|
||||||
|
this.createBy = createBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCreateTime()
|
||||||
|
{
|
||||||
|
return createTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreateTime(Date createTime)
|
||||||
|
{
|
||||||
|
this.createTime = createTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUpdateBy()
|
||||||
|
{
|
||||||
|
return updateBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdateBy(String updateBy)
|
||||||
|
{
|
||||||
|
this.updateBy = updateBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getUpdateTime()
|
||||||
|
{
|
||||||
|
return updateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdateTime(Date updateTime)
|
||||||
|
{
|
||||||
|
this.updateTime = updateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRemark()
|
||||||
|
{
|
||||||
|
return remark;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRemark(String remark)
|
||||||
|
{
|
||||||
|
this.remark = remark;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> getParams()
|
||||||
|
{
|
||||||
|
if (params == null)
|
||||||
|
{
|
||||||
|
params = new HashMap<>();
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParams(Map<String, Object> params)
|
||||||
|
{
|
||||||
|
this.params = params;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
package basepro.manager.common.core.domain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tree基类
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class TreeEntity extends BaseEntity
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 父菜单名称 */
|
||||||
|
private String parentName;
|
||||||
|
|
||||||
|
/** 父菜单ID */
|
||||||
|
private Long parentId;
|
||||||
|
|
||||||
|
/** 显示顺序 */
|
||||||
|
private Integer orderNum;
|
||||||
|
|
||||||
|
/** 祖级列表 */
|
||||||
|
private String ancestors;
|
||||||
|
|
||||||
|
public String getParentName()
|
||||||
|
{
|
||||||
|
return parentName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParentName(String parentName)
|
||||||
|
{
|
||||||
|
this.parentName = parentName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getParentId()
|
||||||
|
{
|
||||||
|
return parentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParentId(Long parentId)
|
||||||
|
{
|
||||||
|
this.parentId = parentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getOrderNum()
|
||||||
|
{
|
||||||
|
return orderNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrderNum(Integer orderNum)
|
||||||
|
{
|
||||||
|
this.orderNum = orderNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAncestors()
|
||||||
|
{
|
||||||
|
return ancestors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAncestors(String ancestors)
|
||||||
|
{
|
||||||
|
this.ancestors = ancestors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
package basepro.manager.common.core.domain;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ztree树结构实体类
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class Ztree implements Serializable
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 节点ID */
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/** 节点父ID */
|
||||||
|
private Long pId;
|
||||||
|
|
||||||
|
/** 节点名称 */
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/** 节点标题 */
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
/** 是否勾选 */
|
||||||
|
private boolean checked = false;
|
||||||
|
|
||||||
|
/** 是否展开 */
|
||||||
|
private boolean open = false;
|
||||||
|
|
||||||
|
/** 是否能勾选 */
|
||||||
|
private boolean nocheck = false;
|
||||||
|
|
||||||
|
public Long getId()
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id)
|
||||||
|
{
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getpId()
|
||||||
|
{
|
||||||
|
return pId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setpId(Long pId)
|
||||||
|
{
|
||||||
|
this.pId = pId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle()
|
||||||
|
{
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title)
|
||||||
|
{
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isChecked()
|
||||||
|
{
|
||||||
|
return checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChecked(boolean checked)
|
||||||
|
{
|
||||||
|
this.checked = checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOpen()
|
||||||
|
{
|
||||||
|
return open;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOpen(boolean open)
|
||||||
|
{
|
||||||
|
this.open = open;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNocheck()
|
||||||
|
{
|
||||||
|
return nocheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNocheck(boolean nocheck)
|
||||||
|
{
|
||||||
|
this.nocheck = nocheck;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
package basepro.manager.common.core.page;
|
||||||
|
|
||||||
|
|
||||||
|
import basepro.manager.common.utils.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页数据
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class PageDomain
|
||||||
|
{
|
||||||
|
/** 当前记录起始索引 */
|
||||||
|
private Integer pageNum;
|
||||||
|
/** 每页显示记录数 */
|
||||||
|
private Integer pageSize;
|
||||||
|
/** 排序列 */
|
||||||
|
private String orderByColumn;
|
||||||
|
/** 排序的方向 "desc" 或者 "asc". */
|
||||||
|
private String isAsc;
|
||||||
|
|
||||||
|
public String getOrderBy()
|
||||||
|
{
|
||||||
|
if (StringUtils.isEmpty(orderByColumn))
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPageNum()
|
||||||
|
{
|
||||||
|
return pageNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPageNum(Integer pageNum)
|
||||||
|
{
|
||||||
|
this.pageNum = pageNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPageSize()
|
||||||
|
{
|
||||||
|
return pageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPageSize(Integer pageSize)
|
||||||
|
{
|
||||||
|
this.pageSize = pageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOrderByColumn()
|
||||||
|
{
|
||||||
|
return orderByColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrderByColumn(String orderByColumn)
|
||||||
|
{
|
||||||
|
this.orderByColumn = orderByColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIsAsc()
|
||||||
|
{
|
||||||
|
return isAsc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsAsc(String isAsc)
|
||||||
|
{
|
||||||
|
this.isAsc = isAsc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
package basepro.manager.common.core.page;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表格分页数据对象
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class TableDataInfo implements Serializable
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** 总记录数 */
|
||||||
|
private long total;
|
||||||
|
|
||||||
|
/** 列表数据 */
|
||||||
|
private List<?> rows;
|
||||||
|
|
||||||
|
/** 消息状态码 */
|
||||||
|
private int code;
|
||||||
|
|
||||||
|
/** 消息内容 */
|
||||||
|
private int msg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表格数据对象
|
||||||
|
*/
|
||||||
|
public TableDataInfo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页
|
||||||
|
*
|
||||||
|
* @param list 列表数据
|
||||||
|
* @param total 总记录数
|
||||||
|
*/
|
||||||
|
public TableDataInfo(List<?> list, int total)
|
||||||
|
{
|
||||||
|
this.rows = list;
|
||||||
|
this.total = total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTotal()
|
||||||
|
{
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTotal(long total)
|
||||||
|
{
|
||||||
|
this.total = total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<?> getRows()
|
||||||
|
{
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRows(List<?> rows)
|
||||||
|
{
|
||||||
|
this.rows = rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCode()
|
||||||
|
{
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCode(int code)
|
||||||
|
{
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMsg()
|
||||||
|
{
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMsg(int msg)
|
||||||
|
{
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package basepro.manager.common.core.page;
|
||||||
|
|
||||||
|
import basepro.manager.common.constant.Constants;
|
||||||
|
import basepro.manager.common.utils.ServletUtils;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表格数据处理
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class TableSupport
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 封装分页对象
|
||||||
|
*/
|
||||||
|
public static PageDomain getPageDomain()
|
||||||
|
{
|
||||||
|
PageDomain pageDomain = new PageDomain();
|
||||||
|
pageDomain.setPageNum(ServletUtils.getParameterToInt(Constants.PAGE_NUM));
|
||||||
|
pageDomain.setPageSize(ServletUtils.getParameterToInt(Constants.PAGE_SIZE));
|
||||||
|
pageDomain.setOrderByColumn(ServletUtils.getParameter(Constants.ORDER_BY_COLUMN));
|
||||||
|
pageDomain.setIsAsc(ServletUtils.getParameter(Constants.IS_ASC));
|
||||||
|
return pageDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PageDomain buildPageRequest()
|
||||||
|
{
|
||||||
|
return getPageDomain();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
package basepro.manager.common.core.text;
|
||||||
|
|
||||||
|
import basepro.manager.common.utils.StringUtils;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符集工具类
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class CharsetKit
|
||||||
|
{
|
||||||
|
/** ISO-8859-1 */
|
||||||
|
public static final String ISO_8859_1 = "ISO-8859-1";
|
||||||
|
/** UTF-8 */
|
||||||
|
public static final String UTF_8 = "UTF-8";
|
||||||
|
/** GBK */
|
||||||
|
public static final String GBK = "GBK";
|
||||||
|
|
||||||
|
/** ISO-8859-1 */
|
||||||
|
public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
|
||||||
|
/** UTF-8 */
|
||||||
|
public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
|
||||||
|
/** GBK */
|
||||||
|
public static final Charset CHARSET_GBK = Charset.forName(GBK);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换为Charset对象
|
||||||
|
*
|
||||||
|
* @param charset 字符集,为空则返回默认字符集
|
||||||
|
* @return Charset
|
||||||
|
*/
|
||||||
|
public static Charset charset(String charset)
|
||||||
|
{
|
||||||
|
return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换字符串的字符集编码
|
||||||
|
*
|
||||||
|
* @param source 字符串
|
||||||
|
* @param srcCharset 源字符集,默认ISO-8859-1
|
||||||
|
* @param destCharset 目标字符集,默认UTF-8
|
||||||
|
* @return 转换后的字符集
|
||||||
|
*/
|
||||||
|
public static String convert(String source, String srcCharset, String destCharset)
|
||||||
|
{
|
||||||
|
return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换字符串的字符集编码
|
||||||
|
*
|
||||||
|
* @param source 字符串
|
||||||
|
* @param srcCharset 源字符集,默认ISO-8859-1
|
||||||
|
* @param destCharset 目标字符集,默认UTF-8
|
||||||
|
* @return 转换后的字符集
|
||||||
|
*/
|
||||||
|
public static String convert(String source, Charset srcCharset, Charset destCharset)
|
||||||
|
{
|
||||||
|
if (null == srcCharset)
|
||||||
|
{
|
||||||
|
srcCharset = StandardCharsets.ISO_8859_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null == destCharset)
|
||||||
|
{
|
||||||
|
srcCharset = StandardCharsets.UTF_8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))
|
||||||
|
{
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
return new String(source.getBytes(srcCharset), destCharset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 系统字符集编码
|
||||||
|
*/
|
||||||
|
public static String systemCharset()
|
||||||
|
{
|
||||||
|
return Charset.defaultCharset().name();
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,93 @@
|
||||||
|
package basepro.manager.common.core.text;
|
||||||
|
|
||||||
|
|
||||||
|
import basepro.manager.common.utils.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串格式化
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class StrFormatter
|
||||||
|
{
|
||||||
|
public static final String EMPTY_JSON = "{}";
|
||||||
|
public static final char C_BACKSLASH = '\\';
|
||||||
|
public static final char C_DELIM_START = '{';
|
||||||
|
public static final char C_DELIM_END = '}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化字符串<br>
|
||||||
|
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
|
||||||
|
* 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
|
||||||
|
* 例:<br>
|
||||||
|
* 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br>
|
||||||
|
* 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
|
||||||
|
* 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
|
||||||
|
*
|
||||||
|
* @param strPattern 字符串模板
|
||||||
|
* @param argArray 参数列表
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public static String format(final String strPattern, final Object... argArray)
|
||||||
|
{
|
||||||
|
if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray))
|
||||||
|
{
|
||||||
|
return strPattern;
|
||||||
|
}
|
||||||
|
final int strPatternLength = strPattern.length();
|
||||||
|
|
||||||
|
// 初始化定义好的长度以获得更好的性能
|
||||||
|
StringBuilder sbuf = new StringBuilder(strPatternLength + 50);
|
||||||
|
|
||||||
|
int handledPosition = 0;
|
||||||
|
int delimIndex;// 占位符所在位置
|
||||||
|
for (int argIndex = 0; argIndex < argArray.length; argIndex++)
|
||||||
|
{
|
||||||
|
delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
|
||||||
|
if (delimIndex == -1)
|
||||||
|
{
|
||||||
|
if (handledPosition == 0)
|
||||||
|
{
|
||||||
|
return strPattern;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果
|
||||||
|
sbuf.append(strPattern, handledPosition, strPatternLength);
|
||||||
|
return sbuf.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH)
|
||||||
|
{
|
||||||
|
if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH)
|
||||||
|
{
|
||||||
|
// 转义符之前还有一个转义符,占位符依旧有效
|
||||||
|
sbuf.append(strPattern, handledPosition, delimIndex - 1);
|
||||||
|
sbuf.append(Convert.utf8Str(argArray[argIndex]));
|
||||||
|
handledPosition = delimIndex + 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 占位符被转义
|
||||||
|
argIndex--;
|
||||||
|
sbuf.append(strPattern, handledPosition, delimIndex - 1);
|
||||||
|
sbuf.append(C_DELIM_START);
|
||||||
|
handledPosition = delimIndex + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 正常占位符
|
||||||
|
sbuf.append(strPattern, handledPosition, delimIndex);
|
||||||
|
sbuf.append(Convert.utf8Str(argArray[argIndex]));
|
||||||
|
handledPosition = delimIndex + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 加入最后一个占位符后所有的字符
|
||||||
|
sbuf.append(strPattern, handledPosition, strPattern.length());
|
||||||
|
|
||||||
|
return sbuf.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package basepro.manager.common.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作状态
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public enum BusinessStatus
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 成功
|
||||||
|
*/
|
||||||
|
SUCCESS,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 失败
|
||||||
|
*/
|
||||||
|
FAIL,
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
package basepro.manager.common.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务操作类型
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public enum BusinessType
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 其它
|
||||||
|
*/
|
||||||
|
OTHER,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增
|
||||||
|
*/
|
||||||
|
INSERT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改
|
||||||
|
*/
|
||||||
|
UPDATE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
*/
|
||||||
|
DELETE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权
|
||||||
|
*/
|
||||||
|
GRANT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出
|
||||||
|
*/
|
||||||
|
EXPORT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入
|
||||||
|
*/
|
||||||
|
IMPORT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 强退
|
||||||
|
*/
|
||||||
|
FORCE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成代码
|
||||||
|
*/
|
||||||
|
GENCODE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空
|
||||||
|
*/
|
||||||
|
CLEAN,
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package basepro.manager.common.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据源
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public enum DataSourceType
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 主库
|
||||||
|
*/
|
||||||
|
MASTER,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从库
|
||||||
|
*/
|
||||||
|
SLAVE
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package basepro.manager.common.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户会话
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public enum OnlineStatus
|
||||||
|
{
|
||||||
|
/** 用户状态 */
|
||||||
|
on_line("在线"), off_line("离线");
|
||||||
|
|
||||||
|
private final String info;
|
||||||
|
|
||||||
|
private OnlineStatus(String info)
|
||||||
|
{
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInfo()
|
||||||
|
{
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package basepro.manager.common.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作人类别
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public enum OperatorType
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 其它
|
||||||
|
*/
|
||||||
|
OTHER,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 后台用户
|
||||||
|
*/
|
||||||
|
MANAGE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机端用户
|
||||||
|
*/
|
||||||
|
MOBILE
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
package basepro.manager.common.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户状态
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public enum UserStatus
|
||||||
|
{
|
||||||
|
OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除");
|
||||||
|
|
||||||
|
private final String code;
|
||||||
|
private final String info;
|
||||||
|
|
||||||
|
UserStatus(String code, String info)
|
||||||
|
{
|
||||||
|
this.code = code;
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode()
|
||||||
|
{
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInfo()
|
||||||
|
{
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
package basepro.manager.common.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务异常
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class BusinessException extends RuntimeException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
protected final String message;
|
||||||
|
|
||||||
|
public BusinessException(String message)
|
||||||
|
{
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BusinessException(String message, Throwable e)
|
||||||
|
{
|
||||||
|
super(message, e);
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage()
|
||||||
|
{
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package basepro.manager.common.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 演示模式异常
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class DemoModeException extends RuntimeException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public DemoModeException()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
package basepro.manager.common.exception.base;
|
||||||
|
|
||||||
|
|
||||||
|
import basepro.manager.common.utils.MessageUtils;
|
||||||
|
import basepro.manager.common.utils.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基础异常
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class BaseException extends RuntimeException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所属模块
|
||||||
|
*/
|
||||||
|
private String module;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误码
|
||||||
|
*/
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误码对应的参数
|
||||||
|
*/
|
||||||
|
private Object[] args;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误消息
|
||||||
|
*/
|
||||||
|
private String defaultMessage;
|
||||||
|
|
||||||
|
public BaseException(String module, String code, Object[] args, String defaultMessage)
|
||||||
|
{
|
||||||
|
this.module = module;
|
||||||
|
this.code = code;
|
||||||
|
this.args = args;
|
||||||
|
this.defaultMessage = defaultMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseException(String module, String code, Object[] args)
|
||||||
|
{
|
||||||
|
this(module, code, args, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseException(String module, String defaultMessage)
|
||||||
|
{
|
||||||
|
this(module, null, null, defaultMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseException(String code, Object[] args)
|
||||||
|
{
|
||||||
|
this(null, code, args, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseException(String defaultMessage)
|
||||||
|
{
|
||||||
|
this(null, null, null, defaultMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage()
|
||||||
|
{
|
||||||
|
String message = null;
|
||||||
|
if (!StringUtils.isEmpty(code))
|
||||||
|
{
|
||||||
|
message = MessageUtils.message(code, args);
|
||||||
|
}
|
||||||
|
if (message == null)
|
||||||
|
{
|
||||||
|
message = defaultMessage;
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getModule()
|
||||||
|
{
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode()
|
||||||
|
{
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] getArgs()
|
||||||
|
{
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDefaultMessage()
|
||||||
|
{
|
||||||
|
return defaultMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package basepro.manager.common.exception.file;
|
||||||
|
|
||||||
|
|
||||||
|
import basepro.manager.common.exception.base.BaseException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件信息异常类
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class FileException extends BaseException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public FileException(String code, Object[] args)
|
||||||
|
{
|
||||||
|
super("file", code, args, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package basepro.manager.common.exception.file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件名称超长限制异常类
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class FileNameLengthLimitExceededException extends FileException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public FileNameLengthLimitExceededException(int defaultFileNameLength)
|
||||||
|
{
|
||||||
|
super("upload.filename.exceed.length", new Object[] { defaultFileNameLength });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package basepro.manager.common.exception.file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件名大小限制异常类
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class FileSizeLimitExceededException extends FileException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public FileSizeLimitExceededException(long defaultMaxSize)
|
||||||
|
{
|
||||||
|
super("upload.exceed.maxSize", new Object[] { defaultMaxSize });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
package basepro.manager.common.exception.file;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import org.apache.commons.fileupload.FileUploadException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件上传 误异常类
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class InvalidExtensionException extends FileUploadException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private String[] allowedExtension;
|
||||||
|
private String extension;
|
||||||
|
private String filename;
|
||||||
|
|
||||||
|
public InvalidExtensionException(String[] allowedExtension, String extension, String filename)
|
||||||
|
{
|
||||||
|
super("filename : [" + filename + "], extension : [" + extension + "], allowed extension : [" + Arrays.toString(allowedExtension) + "]");
|
||||||
|
this.allowedExtension = allowedExtension;
|
||||||
|
this.extension = extension;
|
||||||
|
this.filename = filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getAllowedExtension()
|
||||||
|
{
|
||||||
|
return allowedExtension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExtension()
|
||||||
|
{
|
||||||
|
return extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFilename()
|
||||||
|
{
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class InvalidImageExtensionException extends InvalidExtensionException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename)
|
||||||
|
{
|
||||||
|
super(allowedExtension, extension, filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class InvalidFlashExtensionException extends InvalidExtensionException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename)
|
||||||
|
{
|
||||||
|
super(allowedExtension, extension, filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class InvalidMediaExtensionException extends InvalidExtensionException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename)
|
||||||
|
{
|
||||||
|
super(allowedExtension, extension, filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
package basepro.manager.common.exception.job;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计划策略异常
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class TaskException extends Exception
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private Code code;
|
||||||
|
|
||||||
|
public TaskException(String msg, Code code)
|
||||||
|
{
|
||||||
|
this(msg, code, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TaskException(String msg, Code code, Exception nestedEx)
|
||||||
|
{
|
||||||
|
super(msg, nestedEx);
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Code getCode()
|
||||||
|
{
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Code
|
||||||
|
{
|
||||||
|
TASK_EXISTS, NO_TASK_EXISTS, TASK_ALREADY_STARTED, UNKNOWN, CONFIG_ERROR, TASK_NODE_NOT_AVAILABLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package basepro.manager.common.exception.user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码错误异常类
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class CaptchaException extends UserException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public CaptchaException()
|
||||||
|
{
|
||||||
|
super("user.jcaptcha.error", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package basepro.manager.common.exception.user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色锁定异常类
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class RoleBlockedException extends UserException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public RoleBlockedException()
|
||||||
|
{
|
||||||
|
super("role.blocked", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package basepro.manager.common.exception.user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户锁定异常类
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class UserBlockedException extends UserException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public UserBlockedException()
|
||||||
|
{
|
||||||
|
super("user.blocked", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package basepro.manager.common.exception.user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户账号已被删除
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class UserDeleteException extends UserException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public UserDeleteException()
|
||||||
|
{
|
||||||
|
super("user.password.delete", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package basepro.manager.common.exception.user;
|
||||||
|
|
||||||
|
|
||||||
|
import basepro.manager.common.exception.base.BaseException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户信息异常类
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class UserException extends BaseException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public UserException(String code, Object[] args)
|
||||||
|
{
|
||||||
|
super("user", code, args, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package basepro.manager.common.exception.user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户不存在异常类
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class UserNotExistsException extends UserException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public UserNotExistsException()
|
||||||
|
{
|
||||||
|
super("user.not.exists", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package basepro.manager.common.exception.user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户密码不正确或不符合规范异常类
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class UserPasswordNotMatchException extends UserException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public UserPasswordNotMatchException()
|
||||||
|
{
|
||||||
|
super("user.password.not.match", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package basepro.manager.common.exception.user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户错误记数异常类
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class UserPasswordRetryLimitCountException extends UserException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public UserPasswordRetryLimitCountException(int retryLimitCount)
|
||||||
|
{
|
||||||
|
super("user.password.retry.limit.count", new Object[] { retryLimitCount });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package basepro.manager.common.exception.user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户错误最大次数异常类
|
||||||
|
*
|
||||||
|
* @author basepro
|
||||||
|
*/
|
||||||
|
public class UserPasswordRetryLimitExceedException extends UserException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public UserPasswordRetryLimitExceedException(int retryLimitCount)
|
||||||
|
{
|
||||||
|
super("user.password.retry.limit.exceed", new Object[] { retryLimitCount });
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue