人车物
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