parent
dddb0b322e
commit
29919cadc3
@ -1,29 +1,62 @@
|
||||
package org.opsli.api.wrapper.system.dict;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.opsli.api.base.warpper.ApiWrapper;
|
||||
import org.opsli.common.annotation.validation.ValidationArgs;
|
||||
import org.opsli.common.annotation.validation.ValidationArgsMax;
|
||||
import org.opsli.common.enums.ValiArgsType;
|
||||
import org.opsli.plugins.excel.annotation.ExcelInfo;
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.modulars.test.entity
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-16 17:33
|
||||
* @Description: 数据字典 - 工具类用
|
||||
* @Description: 数据字典
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class DictModel {
|
||||
public class DictModel extends ApiWrapper {
|
||||
|
||||
/** 类型编号 - 冗余 */
|
||||
|
||||
|
||||
/** 字典类型编号 */
|
||||
@ApiModelProperty(value = "字典类型编号")
|
||||
@ExcelProperty(value = "字典类型编号", order = 1)
|
||||
@ExcelInfo
|
||||
// 验证器
|
||||
@ValidationArgs({ValiArgsType.IS_NOT_NULL, ValiArgsType.IS_GENERAL})
|
||||
@ValidationArgsMax(120)
|
||||
private String typeCode;
|
||||
|
||||
/** 字典名称 */
|
||||
private String dictName;
|
||||
/** 字典类型名称 */
|
||||
@ApiModelProperty(value = "字典类型名称")
|
||||
@ExcelProperty(value = "字典类型名称", order = 2)
|
||||
@ExcelInfo
|
||||
// 验证器
|
||||
@ValidationArgs({ValiArgsType.IS_NOT_NULL, ValiArgsType.IS_GENERAL_WITH_CHINESE})
|
||||
@ValidationArgsMax(120)
|
||||
private String typeName;
|
||||
|
||||
/** 是否内置数据 0是 1否*/
|
||||
@ApiModelProperty(value = "是否内置数据 0是 1否")
|
||||
@ExcelProperty(value = "是否内置数据", order = 3)
|
||||
@ExcelInfo(dictType = "yes_no")
|
||||
// 验证器
|
||||
@ValidationArgs(ValiArgsType.IS_NOT_NULL)
|
||||
@ValidationArgsMax(1)
|
||||
private Character izLock;
|
||||
|
||||
/** 字典值 */
|
||||
private String dictValue;
|
||||
/** 备注 */
|
||||
@ApiModelProperty(value = "备注")
|
||||
@ExcelProperty(value = "备注", order = 4)
|
||||
@ExcelInfo
|
||||
// 验证器
|
||||
@ValidationArgsMax(255)
|
||||
private String remark;
|
||||
|
||||
/** 消息 */
|
||||
private SysDictDetailModel model;
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,29 @@
|
||||
package org.opsli.api.wrapper.system.dict;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.modulars.test.entity
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-16 17:33
|
||||
* @Description: 数据字典 - 工具类用
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class DictWrapper {
|
||||
|
||||
/** 类型编号 - 冗余 */
|
||||
private String typeCode;
|
||||
|
||||
/** 字典名称 */
|
||||
private String dictName;
|
||||
|
||||
/** 字典值 */
|
||||
private String dictValue;
|
||||
|
||||
/** 消息 */
|
||||
private DictDetailModel model;
|
||||
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
package org.opsli.api.wrapper.system.dict;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.opsli.api.base.warpper.ApiWrapper;
|
||||
import org.opsli.common.annotation.validation.ValidationArgs;
|
||||
import org.opsli.common.annotation.validation.ValidationArgsMax;
|
||||
import org.opsli.common.enums.ValiArgsType;
|
||||
import org.opsli.plugins.excel.annotation.CellStyleFormat;
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.modulars.test.entity
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-16 17:33
|
||||
* @Description: 数据字典
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class SysDictModel extends ApiWrapper {
|
||||
|
||||
|
||||
|
||||
/** 字典类型编号 */
|
||||
@ApiModelProperty(value = "字典类型编号")
|
||||
@ExcelProperty(value = "字典类型编号", order = 1)
|
||||
@CellStyleFormat
|
||||
// 验证器
|
||||
@ValidationArgs({ValiArgsType.IS_NOT_NULL, ValiArgsType.IS_GENERAL})
|
||||
@ValidationArgsMax(120)
|
||||
private String typeCode;
|
||||
|
||||
/** 字典类型名称 */
|
||||
@ApiModelProperty(value = "字典类型名称")
|
||||
@ExcelProperty(value = "字典类型名称", order = 2)
|
||||
@CellStyleFormat
|
||||
// 验证器
|
||||
@ValidationArgs({ValiArgsType.IS_NOT_NULL, ValiArgsType.IS_GENERAL_WITH_CHINESE})
|
||||
@ValidationArgsMax(120)
|
||||
private String typeName;
|
||||
|
||||
/** 是否内置数据 */
|
||||
@ApiModelProperty(value = "是否内置数据")
|
||||
@ExcelProperty(value = "是否内置数据", order = 3)
|
||||
@CellStyleFormat
|
||||
// 验证器
|
||||
@ValidationArgs(ValiArgsType.IS_NOT_NULL)
|
||||
private Character izLock;
|
||||
|
||||
/** 备注 */
|
||||
@ApiModelProperty(value = "备注")
|
||||
@ExcelProperty(value = "备注", order = 4)
|
||||
@CellStyleFormat
|
||||
// 验证器
|
||||
@ValidationArgsMax(255)
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package org.opsli.api.wrapper.system.menu;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.opsli.api.base.warpper.ApiWrapper;
|
||||
import org.opsli.common.annotation.validation.ValidationArgs;
|
||||
import org.opsli.common.annotation.validation.ValidationArgsMax;
|
||||
import org.opsli.common.enums.ValiArgsType;
|
||||
import org.opsli.plugins.excel.annotation.ExcelInfo;
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.modulars.test.entity
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-16 17:33
|
||||
* @Description: 菜单表
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class MenuModel extends ApiWrapper {
|
||||
|
||||
/** 父级主键 */
|
||||
@ApiModelProperty(value = "父级主键")
|
||||
@ExcelProperty(value = "父级主键", order = 1)
|
||||
@ExcelInfo
|
||||
// 验证器
|
||||
@ValidationArgs(ValiArgsType.IS_NOT_NULL)
|
||||
@ValidationArgsMax(20)
|
||||
private String parentId;
|
||||
|
||||
/** 菜单编号 */
|
||||
@ApiModelProperty(value = "菜单编号")
|
||||
@ExcelProperty(value = "菜单编号", order = 2)
|
||||
@ExcelInfo
|
||||
// 验证器
|
||||
@ValidationArgs({ValiArgsType.IS_NOT_NULL,ValiArgsType.IS_GENERAL})
|
||||
@ValidationArgsMax(50)
|
||||
private String menuCode;
|
||||
|
||||
/** 菜单名称 */
|
||||
@ApiModelProperty(value = "菜单名称")
|
||||
@ExcelProperty(value = "菜单名称", order = 3)
|
||||
@ExcelInfo
|
||||
// 验证器
|
||||
@ValidationArgs({ValiArgsType.IS_NOT_NULL,ValiArgsType.IS_GENERAL_WITH_CHINESE})
|
||||
@ValidationArgsMax(50)
|
||||
private String menuName;
|
||||
|
||||
/** 图标 */
|
||||
@ApiModelProperty(value = "图标")
|
||||
@ExcelProperty(value = "图标", order = 4)
|
||||
@ExcelInfo
|
||||
// 验证器
|
||||
@ValidationArgsMax(50)
|
||||
private String icon;
|
||||
|
||||
/** 项目类型:1-菜单2-按钮3-链接4-表单 */
|
||||
@ApiModelProperty(value = "项目类型:1-菜单2-按钮3-链接4-表单")
|
||||
@ExcelProperty(value = "项目类型", order = 5)
|
||||
@ExcelInfo(dictType = "menuType")
|
||||
// 验证器
|
||||
@ValidationArgs({ValiArgsType.IS_NOT_NULL})
|
||||
@ValidationArgsMax(20)
|
||||
private String type;
|
||||
|
||||
/** url地址 */
|
||||
@ApiModelProperty(value = "url地址")
|
||||
@ExcelProperty(value = "url地址", order = 6)
|
||||
@ExcelInfo
|
||||
// 验证器
|
||||
@ValidationArgsMax(200)
|
||||
private String url;
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package org.opsli.api.wrapper.system.role;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.opsli.api.base.warpper.ApiWrapper;
|
||||
import org.opsli.common.annotation.validation.ValidationArgs;
|
||||
import org.opsli.common.annotation.validation.ValidationArgsMax;
|
||||
import org.opsli.common.enums.ValiArgsType;
|
||||
import org.opsli.plugins.excel.annotation.ExcelInfo;
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.modulars.test.entity
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-16 17:33
|
||||
* @Description: 角色表
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class RoleModel extends ApiWrapper {
|
||||
|
||||
|
||||
|
||||
/** 角色编码 */
|
||||
@ApiModelProperty(value = "角色编码")
|
||||
@ExcelProperty(value = "角色编码", order = 1)
|
||||
@ExcelInfo
|
||||
// 验证器
|
||||
@ValidationArgs({ValiArgsType.IS_NOT_NULL,ValiArgsType.IS_GENERAL})
|
||||
@ValidationArgsMax(50)
|
||||
private String roleCode;
|
||||
|
||||
/** 角色名称 */
|
||||
@ApiModelProperty(value = "角色编码")
|
||||
@ExcelProperty(value = "角色编码", order = 2)
|
||||
@ExcelInfo
|
||||
// 验证器
|
||||
@ValidationArgs({ValiArgsType.IS_NOT_NULL,ValiArgsType.IS_GENERAL})
|
||||
@ValidationArgsMax(50)
|
||||
private String roleName;
|
||||
|
||||
/** 是否内置数据 0是 1否*/
|
||||
@ApiModelProperty(value = "是否内置数据 0是 1否")
|
||||
@ExcelProperty(value = "是否内置数据", order = 3)
|
||||
@ExcelInfo(dictType = "yes_no")
|
||||
// 验证器
|
||||
@ValidationArgs({ValiArgsType.IS_NOT_NULL,ValiArgsType.IS_GENERAL})
|
||||
@ValidationArgsMax(1)
|
||||
private Character izLock;
|
||||
|
||||
/** 备注 */
|
||||
@ApiModelProperty(value = "备注")
|
||||
@ExcelProperty(value = "备注", order = 4)
|
||||
@ExcelInfo
|
||||
// 验证器
|
||||
@ValidationArgsMax(255)
|
||||
private String remark;
|
||||
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
package org.opsli.api.wrapper.system.user;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnore;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.opsli.api.base.warpper.ApiWrapper;
|
||||
import org.opsli.common.annotation.validation.ValidationArgs;
|
||||
import org.opsli.common.annotation.validation.ValidationArgsMax;
|
||||
import org.opsli.common.enums.ValiArgsType;
|
||||
import org.opsli.plugins.excel.annotation.ExcelInfo;
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.modulars.test.entity
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-16 17:33
|
||||
* @Description: 用户信息表
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class UserModel extends ApiWrapper {
|
||||
|
||||
|
||||
/** 登录账户 */
|
||||
@ApiModelProperty(value = "登录账户")
|
||||
@ExcelIgnore
|
||||
// 验证器
|
||||
@ValidationArgs({ValiArgsType.IS_NOT_NULL,ValiArgsType.IS_GENERAL})
|
||||
@ValidationArgsMax(32)
|
||||
private String username;
|
||||
|
||||
/** 登录密码 */
|
||||
@ApiModelProperty(value = "登录密码")
|
||||
@ExcelIgnore
|
||||
// 验证器
|
||||
@ValidationArgsMax(50)
|
||||
private String password;
|
||||
|
||||
/** 盐值,密码秘钥 */
|
||||
@ApiModelProperty(value = "盐值,密码秘钥")
|
||||
@ExcelIgnore
|
||||
// 验证器
|
||||
@ValidationArgsMax(50)
|
||||
private String secretkey;
|
||||
|
||||
/** 是否锁定 */
|
||||
@ApiModelProperty(value = "是否锁定")
|
||||
@ExcelIgnore
|
||||
// 验证器
|
||||
@ValidationArgs({ValiArgsType.IS_NOT_NULL})
|
||||
@ValidationArgsMax(1)
|
||||
private Character locked;
|
||||
|
||||
/** 真实姓名 */
|
||||
@ApiModelProperty(value = "真实姓名")
|
||||
@ExcelProperty(value = "真实姓名", order = 1)
|
||||
@ExcelInfo
|
||||
// 验证器
|
||||
@ValidationArgs({ValiArgsType.IS_NOT_NULL,ValiArgsType.IS_GENERAL_WITH_CHINESE})
|
||||
@ValidationArgsMax(50)
|
||||
private String realName;
|
||||
|
||||
/** 手机 */
|
||||
@ApiModelProperty(value = "手机")
|
||||
@ExcelProperty(value = "手机", order = 2)
|
||||
@ExcelInfo
|
||||
// 验证器
|
||||
@ValidationArgs({ValiArgsType.IS_MOBILE})
|
||||
private String mobile;
|
||||
|
||||
/** 邮箱 */
|
||||
@ApiModelProperty(value = "邮箱")
|
||||
@ExcelProperty(value = "邮箱", order = 3)
|
||||
@ExcelInfo
|
||||
// 验证器
|
||||
@ValidationArgs({ValiArgsType.IS_EMAIL})
|
||||
private String email;
|
||||
|
||||
/** 工号 */
|
||||
@ApiModelProperty(value = "工号")
|
||||
@ExcelProperty(value = "工号", order = 4)
|
||||
@ExcelInfo
|
||||
// 验证器
|
||||
@ValidationArgs({ValiArgsType.IS_GENERAL})
|
||||
@ValidationArgsMax(32)
|
||||
private String no;
|
||||
|
||||
/** 头像 */
|
||||
@ApiModelProperty(value = "头像")
|
||||
@ExcelIgnore
|
||||
// 验证器
|
||||
@ValidationArgsMax(255)
|
||||
private String avatar;
|
||||
|
||||
/** 最后登陆IP */
|
||||
@ApiModelProperty(value = "最后登陆IP")
|
||||
@ExcelIgnore
|
||||
// 验证器
|
||||
@ValidationArgs(ValiArgsType.IS_IPV4)
|
||||
private String loginIp;
|
||||
|
||||
/** 备注 */
|
||||
@ApiModelProperty(value = "备注")
|
||||
@ExcelProperty(value = "备注", order = 5)
|
||||
@ExcelInfo
|
||||
// 验证器
|
||||
@ValidationArgsMax(255)
|
||||
private String remark;
|
||||
|
||||
|
||||
/** 多租户字段 */
|
||||
@ApiModelProperty(value = "多租户ID")
|
||||
@ExcelIgnore
|
||||
// 验证器
|
||||
@ValidationArgsMax(20)
|
||||
private String tenantId;
|
||||
|
||||
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package org.opsli.common.annotation;
|
||||
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.common.annotation
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-16 16:36
|
||||
* @Description: 字典标示
|
||||
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
@Documented
|
||||
public @interface DictType {
|
||||
|
||||
/** 字典类型 code */
|
||||
String value();
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package org.opsli.common.annotation;
|
||||
package org.opsli.common.annotation.hotdata;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.opsli.common.annotation;
|
||||
package org.opsli.common.annotation.hotdata;
|
||||
|
||||
import org.opsli.common.constants.CacheConstants;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.opsli.common.annotation;
|
||||
package org.opsli.common.annotation.hotdata;
|
||||
|
||||
import org.opsli.common.constants.CacheConstants;
|
||||
|
@ -0,0 +1,30 @@
|
||||
package org.opsli.common.api;
|
||||
|
||||
|
||||
/**
|
||||
* 用于存放当前线程下 Token
|
||||
*
|
||||
* @author parker
|
||||
* @date 2020-09-15
|
||||
*/
|
||||
public class TokenThreadLocal {
|
||||
|
||||
/** 临时线程存储 token 容器 */
|
||||
private static final ThreadLocal<String> tokenData = new ThreadLocal<>();
|
||||
|
||||
public static void put(String token) {
|
||||
if (tokenData.get() == null) {
|
||||
tokenData.set(token);
|
||||
}
|
||||
}
|
||||
|
||||
public static String get() {
|
||||
return tokenData.get();
|
||||
}
|
||||
|
||||
public static void remove() {
|
||||
try {
|
||||
tokenData.remove();
|
||||
}catch (Exception e){}
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package org.opsli.common.constants;
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.common.constants
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-16 17:42
|
||||
* @Description: 签名
|
||||
*/
|
||||
public interface SignConstants {
|
||||
|
||||
/** username */
|
||||
String ACCOUNT = "account";
|
||||
|
||||
/** user Id */
|
||||
String USER_ID = "userId";
|
||||
|
||||
/** 时间戳 */
|
||||
String TIMESTAMP = "timestamp";
|
||||
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package org.opsli.core.aspect;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.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.opsli.common.api.TokenThreadLocal;
|
||||
import org.opsli.common.exception.ServiceException;
|
||||
import org.opsli.core.utils.UserTokenUtil;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import static org.opsli.common.constants.OrderConstants.TOKEN_AOP_SORT;
|
||||
|
||||
/**
|
||||
* 参数校验 拦截处理
|
||||
*
|
||||
* @author parker
|
||||
* @date 2020-09-16
|
||||
*/
|
||||
@Slf4j
|
||||
@Order(TOKEN_AOP_SORT)
|
||||
@Aspect
|
||||
@Component
|
||||
public class TokenAop {
|
||||
|
||||
|
||||
@Pointcut("execution(public * org.opsli.modulars*..*.*Controller*.*(..))")
|
||||
public void requestMapping() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 切如 post 请求
|
||||
* @param point
|
||||
*/
|
||||
@Around("requestMapping()")
|
||||
public Object tokenAop(ProceedingJoinPoint point) throws Throwable {
|
||||
|
||||
// 将 Token放入 线程缓存
|
||||
try {
|
||||
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
|
||||
ServletRequestAttributes sra = (ServletRequestAttributes) ra;
|
||||
HttpServletRequest request = sra.getRequest();
|
||||
String requestToken = UserTokenUtil.getRequestToken(request);
|
||||
if(StringUtils.isNotEmpty(requestToken)){
|
||||
// 放入当前线程缓存中
|
||||
TokenThreadLocal.put(requestToken);
|
||||
}
|
||||
}catch (ServiceException e){
|
||||
throw e;
|
||||
}catch (Exception e){
|
||||
log.error(e.getMessage(),e);
|
||||
}
|
||||
|
||||
// 防止线程抛异常 线程变量不回收 导致oom
|
||||
Object returnValue = null;
|
||||
try {
|
||||
// 执行正常操作
|
||||
Object[] args= point.getArgs();
|
||||
returnValue = point.proceed(args);
|
||||
} finally {
|
||||
// 线程销毁时 删除 token
|
||||
TokenThreadLocal.remove();
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package org.opsli.core.conf;
|
||||
|
||||
import com.google.code.kaptcha.impl.DefaultKaptcha;
|
||||
import com.google.code.kaptcha.util.Config;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
|
||||
/**
|
||||
* 生成验证码配置
|
||||
*
|
||||
* @author 孙志强
|
||||
|
||||
* @date 2017-04-20 19:22
|
||||
*/
|
||||
@Configuration
|
||||
public class KaptchaConfig {
|
||||
|
||||
@Bean
|
||||
public DefaultKaptcha producer() {
|
||||
Properties properties = new Properties();
|
||||
properties.put("kaptcha.border", "no");
|
||||
properties.put("kaptcha.textproducer.font.color", "black");
|
||||
properties.put("kaptcha.textproducer.char.space", "10");
|
||||
properties.put("kaptcha.textproducer.char.string", "1234567890");
|
||||
properties.put("kaptcha.textproducer.char.length", "4");
|
||||
Config config = new Config(properties);
|
||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
|
||||
defaultKaptcha.setConfig(config);
|
||||
return defaultKaptcha;
|
||||
}
|
||||
}
|
@ -0,0 +1,125 @@
|
||||
package org.opsli.core.conf;
|
||||
|
||||
import org.apache.shiro.mgt.SecurityManager;
|
||||
import org.apache.shiro.session.mgt.SessionManager;
|
||||
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
|
||||
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
|
||||
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
|
||||
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
|
||||
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
|
||||
import org.opsli.core.security.shiro.filter.OAuth2Filter;
|
||||
import org.opsli.core.security.shiro.realm.OAuth2Realm;
|
||||
import org.opsli.plugins.redis.conf.RedisPluginConfig;
|
||||
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.DependsOn;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Shiro配置
|
||||
*
|
||||
* 全程用 token认证 所以也就用不着 什么共享缓存 - 无状态
|
||||
*
|
||||
* @author parker
|
||||
* @date 2017-04-20 18:33
|
||||
*/
|
||||
@Configuration
|
||||
@AutoConfigureAfter(RedisPluginConfig.class)
|
||||
public class ShiroConfig {
|
||||
|
||||
|
||||
/**
|
||||
* filer
|
||||
* @param securityManager
|
||||
* @return
|
||||
*/
|
||||
@Bean("shiroFilter")
|
||||
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
|
||||
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
|
||||
shiroFilter.setSecurityManager(securityManager);
|
||||
|
||||
//oauth过滤
|
||||
Map<String, Filter> filters = new HashMap<>();
|
||||
filters.put("oauth2", new OAuth2Filter());
|
||||
shiroFilter.setFilters(filters);
|
||||
|
||||
Map<String, String> filterMap = new LinkedHashMap<>();
|
||||
filterMap.put("/webjars/**", "anon");
|
||||
filterMap.put("/druid/**", "anon");
|
||||
filterMap.put("/app/**", "anon");
|
||||
filterMap.put("/sys/login", "anon");
|
||||
filterMap.put("/swagger/**", "anon");
|
||||
filterMap.put("/v2/api-docs", "anon");
|
||||
filterMap.put("/doc.html", "anon");
|
||||
filterMap.put("/swagger-ui.html", "anon");
|
||||
filterMap.put("/swagger-resources/**", "anon");
|
||||
filterMap.put("/captcha.jpg", "anon");
|
||||
filterMap.put("/ueditor/**", "anon");
|
||||
filterMap.put("/**", "oauth2");
|
||||
shiroFilter.setFilterChainDefinitionMap(filterMap);
|
||||
|
||||
return shiroFilter;
|
||||
}
|
||||
|
||||
@Bean("sessionManager")
|
||||
public SessionManager sessionManager(){
|
||||
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
|
||||
sessionManager.setSessionValidationSchedulerEnabled(true);
|
||||
sessionManager.setSessionIdCookieEnabled(true);
|
||||
return sessionManager;
|
||||
}
|
||||
|
||||
@Bean("securityManager")
|
||||
public DefaultWebSecurityManager securityManager(OAuth2Realm oAuth2Realm, SessionManager sessionManager,LettuceConnectionFactory lettuceConnectionFactory) {
|
||||
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
|
||||
securityManager.setRealm(oAuth2Realm);
|
||||
securityManager.setSessionManager(sessionManager);
|
||||
return securityManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public OAuth2Realm oAuth2Realm() {
|
||||
return new OAuth2Realm();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ===================== 固定三板斧 =====================
|
||||
// 其实 没有 Spring Security 配置起来简单
|
||||
//
|
||||
|
||||
@Bean("lifecycleBeanPostProcessor")
|
||||
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
|
||||
return new LifecycleBeanPostProcessor();
|
||||
}
|
||||
|
||||
@Bean("defaultAdvisorAutoProxyCreator")
|
||||
@DependsOn("lifecycleBeanPostProcessor")
|
||||
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
|
||||
DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
|
||||
proxyCreator.setProxyTargetClass(true);
|
||||
proxyCreator.setUsePrefix(true);
|
||||
proxyCreator.setAdvisorBeanNamePrefix("_no_advisor");
|
||||
return proxyCreator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启shiro权限注解生效
|
||||
* @param securityManager
|
||||
* @return
|
||||
*/
|
||||
@Bean("authorizationAttributeSourceAdvisor")
|
||||
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
|
||||
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
|
||||
advisor.setSecurityManager(securityManager);
|
||||
return advisor;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package org.opsli.core.filter;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.opsli.common.api.TokenThreadLocal;
|
||||
import org.opsli.core.utils.UserTokenUtil;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Token 拦截器 用于存放 token
|
||||
*/
|
||||
public class TokenFilter implements Filter {
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
|
||||
HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
// 获得请求中 Token
|
||||
String requestToken = UserTokenUtil.getRequestToken(request);
|
||||
if(StringUtils.isNotEmpty(requestToken)){
|
||||
// 放入当前线程缓存中
|
||||
TokenThreadLocal.put(requestToken);
|
||||
}
|
||||
|
||||
filterChain.doFilter(servletRequest,servletResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// 线程销毁时 删除 token
|
||||
TokenThreadLocal.remove();
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package org.opsli.core.listener;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.opsli.core.general.StartPrint;
|
||||
import org.springframework.boot.context.event.ApplicationFailedEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 系统启动失败
|
||||
*
|
||||
* @author parker
|
||||
* @date 2020-03-31 13:56
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ApplicationFailedEventListener implements ApplicationListener<ApplicationFailedEvent> {
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationFailedEvent event) {
|
||||
StartPrint.INSTANCE.errorPrint();
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package org.opsli.core.listener;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.opsli.core.general.StartPrint;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 系统启动成功
|
||||
*
|
||||
* @author parker
|
||||
* @date 2020-03-31 13:56
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ApplicationReadyEventListene implements ApplicationListener<ApplicationReadyEvent> {
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationReadyEvent event) {
|
||||
ConfigurableApplicationContext applicationContext = event.getApplicationContext();
|
||||
StartPrint.INSTANCE.successPrint(applicationContext.getEnvironment());
|
||||
}
|
||||
}
|
@ -0,0 +1,256 @@
|
||||
package org.opsli.core.security.shiro.cache;
|
||||
|
||||
|
||||
import org.apache.shiro.cache.Cache;
|
||||
import org.apache.shiro.cache.CacheException;
|
||||
import org.apache.shiro.subject.PrincipalCollection;
|
||||
import org.apache.shiro.util.CollectionUtils;
|
||||
import org.opsli.core.security.shiro.exception.PrincipalIdNullException;
|
||||
import org.opsli.core.security.shiro.exception.PrincipalInstanceException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author: sunzhiqiang
|
||||
* @date: 2018/6/22
|
||||
* @description: 参考 shiro-redis 开源项目 Git地址 https://github.com/alexxiyang/shiro-redis
|
||||
*/
|
||||
public class RedisCache<K, V> implements Cache<K, V> {
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(RedisCache.class);
|
||||
|
||||
private RedisManager redisManager;
|
||||
private String keyPrefix = "";
|
||||
private int expire = 0;
|
||||
private String principalIdFieldName = RedisCacheManager.DEFAULT_PRINCIPAL_ID_FIELD_NAME;
|
||||
|
||||
/**
|
||||
* Construction
|
||||
* @param redisManager
|
||||
*/
|
||||
public RedisCache(RedisManager redisManager, String prefix, int expire, String principalIdFieldName) {
|
||||
if (redisManager == null) {
|
||||
throw new IllegalArgumentException("redisManager cannot be null.");
|
||||
}
|
||||
this.redisManager = redisManager;
|
||||
if (prefix != null && !"".equals(prefix)) {
|
||||
this.keyPrefix = prefix;
|
||||
}
|
||||
if (expire != -1) {
|
||||
this.expire = expire;
|
||||
}
|
||||
if (principalIdFieldName != null && !"".equals(principalIdFieldName)) {
|
||||
this.principalIdFieldName = principalIdFieldName;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(K key) throws CacheException {
|
||||
logger.debug("get key [{}]",key);
|
||||
|
||||
if (key == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
String redisCacheKey = getRedisCacheKey(key);
|
||||
Object rawValue = redisManager.get(redisCacheKey);
|
||||
if (rawValue == null) {
|
||||
return null;
|
||||
}
|
||||
V value = (V) rawValue;
|
||||
return value;
|
||||
} catch (Exception e) {
|
||||
throw new CacheException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public V put(K key, V value) throws CacheException {
|
||||
logger.debug("put key [{}]",key);
|
||||
if (key == null) {
|
||||
logger.warn("Saving a null key is meaningless, return value directly without call Redis.");
|
||||
return value;
|
||||
}
|
||||
try {
|
||||
String redisCacheKey = getRedisCacheKey(key);
|
||||
redisManager.set(redisCacheKey, value != null ? value : null, expire);
|
||||
return value;
|
||||
} catch (Exception e) {
|
||||
throw new CacheException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public V remove(K key) throws CacheException {
|
||||
logger.debug("remove key [{}]",key);
|
||||
if (key == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
String redisCacheKey = getRedisCacheKey(key);
|
||||
Object rawValue = redisManager.get(redisCacheKey);
|
||||
V previous = (V) rawValue;
|
||||
redisManager.del(redisCacheKey);
|
||||
return previous;
|
||||
} catch (Exception e) {
|
||||
throw new CacheException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private String getRedisCacheKey(K key) {
|
||||
if (key == null) {
|
||||
return null;
|
||||
}
|
||||
return this.keyPrefix + getStringRedisKey(key);
|
||||
}
|
||||
|
||||
private String getStringRedisKey(K key) {
|
||||
String redisKey;
|
||||
if (key instanceof PrincipalCollection) {
|
||||
redisKey = getRedisKeyFromPrincipalIdField((PrincipalCollection) key);
|
||||
} else {
|
||||
redisKey = key.toString();
|
||||
}
|
||||
return redisKey;
|
||||
}
|
||||
|
||||
private String getRedisKeyFromPrincipalIdField(PrincipalCollection key) {
|
||||
String redisKey;
|
||||
Object principalObject = key.getPrimaryPrincipal();
|
||||
Method pincipalIdGetter = null;
|
||||
Method[] methods = principalObject.getClass().getDeclaredMethods();
|
||||
for (Method m:methods) {
|
||||
if (RedisCacheManager.DEFAULT_PRINCIPAL_ID_FIELD_NAME.equals(this.principalIdFieldName)
|
||||
&& ("getAuthCacheKey".equals(m.getName()) || "getId".equals(m.getName()))) {
|
||||
pincipalIdGetter = m;
|
||||
break;
|
||||
}
|
||||
if (m.getName().equals("get" + this.principalIdFieldName.substring(0, 1).toUpperCase() + this.principalIdFieldName.substring(1))) {
|
||||
pincipalIdGetter = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pincipalIdGetter == null) {
|
||||
throw new PrincipalInstanceException(principalObject.getClass(), this.principalIdFieldName);
|
||||
}
|
||||
|
||||
try {
|
||||
Object idObj = pincipalIdGetter.invoke(principalObject);
|
||||
if (idObj == null) {
|
||||
throw new PrincipalIdNullException(principalObject.getClass(), this.principalIdFieldName);
|
||||
}
|
||||
redisKey = idObj.toString();
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new PrincipalInstanceException(principalObject.getClass(), this.principalIdFieldName, e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new PrincipalInstanceException(principalObject.getClass(), this.principalIdFieldName, e);
|
||||
}
|
||||
|
||||
return redisKey;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void clear() throws CacheException {
|
||||
logger.debug("clear cache");
|
||||
Set<String> keys = null;
|
||||
try {
|
||||
keys = redisManager.scan(this.keyPrefix + "*");
|
||||
} catch (Exception e) {
|
||||
logger.error("get keys error", e);
|
||||
}
|
||||
if (keys == null || keys.size() == 0) {
|
||||
return;
|
||||
}
|
||||
for (String key: keys) {
|
||||
redisManager.del(key);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
Long longSize = 0L;
|
||||
try {
|
||||
longSize = new Long(redisManager.scanSize(this.keyPrefix + "*"));
|
||||
} catch (Exception e) {
|
||||
logger.error("get keys error", e);
|
||||
}
|
||||
return longSize.intValue();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Set<K> keys() {
|
||||
Set<String> keys = null;
|
||||
try {
|
||||
keys = redisManager.scan(this.keyPrefix + "*");
|
||||
} catch (Exception e) {
|
||||
logger.error("get keys error", e);
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(keys)) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
Set<K> convertedKeys = new HashSet<K>();
|
||||
for (String key:keys) {
|
||||
try {
|
||||
convertedKeys.add((K) key);
|
||||
} catch (Exception e) {
|
||||
logger.error("deserialize keys error", e);
|
||||
}
|
||||
}
|
||||
return convertedKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<V> values() {
|
||||
Set<String> keys = null;
|
||||
try {
|
||||
keys = redisManager.scan(this.keyPrefix + "*");
|
||||
} catch (Exception e) {
|
||||
logger.error("get values error", e);
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(keys)) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
List<V> values = new ArrayList<V>(keys.size());
|
||||
for (String key : keys) {
|
||||
V value = null;
|
||||
try {
|
||||
value = (V) redisManager.get(key);
|
||||
} catch (Exception e) {
|
||||
logger.error("deserialize values= error", e);
|
||||
}
|
||||
if (value != null) {
|
||||
values.add(value);
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableList(values);
|
||||
}
|
||||
|
||||
public String getKeyPrefix() {
|
||||
return keyPrefix;
|
||||
}
|
||||
|
||||
public void setKeyPrefix(String keyPrefix) {
|
||||
this.keyPrefix = keyPrefix;
|
||||
}
|
||||
|
||||
public String getPrincipalIdFieldName() {
|
||||
return principalIdFieldName;
|
||||
}
|
||||
|
||||
public void setPrincipalIdFieldName(String principalIdFieldName) {
|
||||
this.principalIdFieldName = principalIdFieldName;
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package org.opsli.core.security.shiro.cache;
|
||||
|
||||
import org.apache.shiro.cache.Cache;
|
||||
import org.apache.shiro.cache.CacheException;
|
||||
import org.apache.shiro.cache.CacheManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* @description: 参考 shiro-redis 开源项目 Git地址 https://github.com/alexxiyang/shiro-redis
|
||||
*/
|
||||
public class RedisCacheManager implements CacheManager {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(RedisCacheManager.class);
|
||||
|
||||
/**
|
||||
* fast lookup by name map
|
||||
*/
|
||||
private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<String, Cache>();
|
||||
|
||||
private RedisManager redisManager;
|
||||
|
||||
/**
|
||||
* expire time in seconds
|
||||
*/
|
||||
private static final int DEFAULT_EXPIRE = 1800;
|
||||
private int expire = DEFAULT_EXPIRE;
|
||||
|
||||
/**
|
||||
* The Redis key prefix for caches
|
||||
*/
|
||||
public static final String DEFAULT_CACHE_KEY_PREFIX = "shiro:cache:";
|
||||
private String keyPrefix = DEFAULT_CACHE_KEY_PREFIX;
|
||||
|
||||
public static final String DEFAULT_PRINCIPAL_ID_FIELD_NAME = "authCacheKey or id";
|
||||
private String principalIdFieldName = DEFAULT_PRINCIPAL_ID_FIELD_NAME;
|
||||
|
||||
@Override
|
||||
public <K, V> Cache<K, V> getCache(String name) throws CacheException {
|
||||
logger.debug("get cache, name={}",name);
|
||||
|
||||
Cache cache = caches.get(name);
|
||||
|
||||
if (cache == null) {
|
||||
cache = new RedisCache<K, V>(redisManager,keyPrefix + name + ":", expire, principalIdFieldName);
|
||||
caches.put(name, cache);
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
|
||||
public RedisManager getRedisManager() {
|
||||
return redisManager;
|
||||
}
|
||||
|
||||
public void setRedisManager(RedisManager redisManager) {
|
||||
this.redisManager = redisManager;
|
||||
}
|
||||
|
||||
public String getKeyPrefix() {
|
||||
return keyPrefix;
|
||||
}
|
||||
|
||||
public void setKeyPrefix(String keyPrefix) {
|
||||
this.keyPrefix = keyPrefix;
|
||||
}
|
||||
|
||||
public int getExpire() {
|
||||
return expire;
|
||||
}
|
||||
|
||||
public void setExpire(int expire) {
|
||||
this.expire = expire;
|
||||
}
|
||||
|
||||
public String getPrincipalIdFieldName() {
|
||||
return principalIdFieldName;
|
||||
}
|
||||
|
||||
public void setPrincipalIdFieldName(String principalIdFieldName) {
|
||||
this.principalIdFieldName = principalIdFieldName;
|
||||
}
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
package org.opsli.core.security.shiro.cache;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.core.Cursor;
|
||||
import org.springframework.data.redis.core.RedisCallback;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.ScanOptions;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author sunzhiqiang
|
||||
* 基于spring和redis的redisTemplate工具类
|
||||
*/
|
||||
public class RedisManager {
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
//=============================common============================
|
||||
/**
|
||||
* 指定缓存失效时间
|
||||
* @param key 键
|
||||
* @param time 时间(秒)
|
||||
*/
|
||||
public void expire(String key,long time){
|
||||
redisTemplate.expire(key, time, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断key是否存在
|
||||
* @param key 键
|
||||
* @return true 存在 false不存在
|
||||
*/
|
||||
public Boolean hasKey(String key){
|
||||
return redisTemplate.hasKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除缓存
|
||||
* @param key 可以传一个值 或多个
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void del(String ... key){
|
||||
if(key!=null&&key.length>0){
|
||||
if(key.length==1){
|
||||
redisTemplate.delete(key[0]);
|
||||
}else{
|
||||
redisTemplate.delete(CollectionUtils.arrayToList(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除key
|
||||
* @param keys
|
||||
*/
|
||||
public void del(Collection keys){
|
||||
redisTemplate.delete(keys);
|
||||
}
|
||||
|
||||
//============================String=============================
|
||||
/**
|
||||
* 普通缓存获取
|
||||
* @param key 键
|
||||
* @return 值
|
||||
*/
|
||||
public Object get(String key){
|
||||
return redisTemplate.opsForValue().get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 普通缓存放入
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
*/
|
||||
public void set(String key,Object value) {
|
||||
redisTemplate.opsForValue().set(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 普通缓存放入并设置时间
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
|
||||
*/
|
||||
public void set(String key,Object value,long time){
|
||||
if(time>0){
|
||||
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
|
||||
}else{
|
||||
set(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用scan命令 查询某些前缀的key
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public Set<String> scan(String key){
|
||||
Set<String> execute = this.redisTemplate.execute(new RedisCallback<Set<String>>() {
|
||||
|
||||
@Override
|
||||
public Set<String> doInRedis(RedisConnection connection) throws DataAccessException {
|
||||
|
||||
Set<String> binaryKeys = new HashSet<>();
|
||||
|
||||
Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder().match(key).count(1000).build());
|
||||
while (cursor.hasNext()) {
|
||||
binaryKeys.add(new String(cursor.next()));
|
||||
}
|
||||
return binaryKeys;
|
||||
}
|
||||
});
|
||||
return execute;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用scan命令 查询某些前缀的key 有多少个
|
||||
* 用来获取当前session数量,也就是在线用户
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public Long scanSize(String key){
|
||||
long dbSize = this.redisTemplate.execute(new RedisCallback<Long>() {
|
||||
|
||||
@Override
|
||||
public Long doInRedis(RedisConnection connection) throws DataAccessException {
|
||||
long count = 0L;
|
||||
Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions().match(key).count(1000).build());
|
||||
while (cursor.hasNext()) {
|
||||
cursor.next();
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
});
|
||||
return dbSize;
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
package org.opsli.core.security.shiro.cache.serializer;
|
||||
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.data.redis.serializer.SerializationException;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* <p>序列化工具类</p>
|
||||
*
|
||||
* @author sunzhiqiang23
|
||||
* @date 2020-04-27 19:48
|
||||
*/
|
||||
public class SerializeUtils implements RedisSerializer {
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(SerializeUtils.class);
|
||||
|
||||
public static boolean isEmpty(byte[] data) {
|
||||
return (data == null || data.length == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 序列化
|
||||
* @param object
|
||||
* @return
|
||||
* @throws SerializationException
|
||||
*/
|
||||
@Override
|
||||
public byte[] serialize(Object object) throws SerializationException {
|
||||
byte[] result = null;
|
||||
|
||||
if (object == null) {
|
||||
return new byte[0];
|
||||
}
|
||||
try (
|
||||
ByteArrayOutputStream byteStream = new ByteArrayOutputStream(128);
|
||||
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteStream)
|
||||
){
|
||||
|
||||
if (!(object instanceof Serializable)) {
|
||||
throw new IllegalArgumentException(SerializeUtils.class.getSimpleName() + " requires a Serializable payload " +
|
||||
"but received an object of type [" + object.getClass().getName() + "]");
|
||||
}
|
||||
|
||||
objectOutputStream.writeObject(object);
|
||||
objectOutputStream.flush();
|
||||
result = byteStream.toByteArray();
|
||||
} catch (Exception ex) {
|
||||
logger.error("Failed to serialize",ex);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 反序列化
|
||||
* @param bytes
|
||||
* @return
|
||||
* @throws SerializationException
|
||||
*/
|
||||
@Override
|
||||
public Object deserialize(byte[] bytes) throws SerializationException {
|
||||
|
||||
Object result = null;
|
||||
|
||||
if (isEmpty(bytes)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try (
|
||||
ByteArrayInputStream byteStream = new ByteArrayInputStream(bytes);
|
||||
ObjectInputStream objectInputStream = new ObjectInputStream(byteStream)
|
||||
){
|
||||
result = objectInputStream.readObject();
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to deserialize",e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package org.opsli.core.security.shiro.exception;
|
||||
|
||||
public class PrincipalIdNullException extends RuntimeException {
|
||||
|
||||
private static final String MESSAGE = "Principal Id shouldn't be null!";
|
||||
|
||||
public PrincipalIdNullException(Class clazz, String idMethodName) {
|
||||
super(clazz + " id field: " + idMethodName + ", value is null\n" + MESSAGE);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package org.opsli.core.security.shiro.exception;
|
||||
|
||||
public class PrincipalInstanceException extends RuntimeException {
|
||||
|
||||
private static final String MESSAGE = "We need a field to identify this Cache Object in Redis. "
|
||||
+ "So you need to defined an id field which you can get unique id to identify this principal. "
|
||||
+ "For example, if you use UserInfo as Principal class, the id field maybe userId, userName, email, etc. "
|
||||
+ "For example, getUserId(), getUserName(), getEmail(), etc.\n"
|
||||
+ "Default value is \"id\", that means your principal object has a method called \"getId()\"";
|
||||
|
||||
public PrincipalInstanceException(Class clazz, String idMethodName) {
|
||||
super(clazz + " must has getter for field: " + idMethodName + "\n" + MESSAGE);
|
||||
}
|
||||
|
||||
public PrincipalInstanceException(Class clazz, String idMethodName, Exception e) {
|
||||
super(clazz + " must has getter for field: " + idMethodName + "\n" + MESSAGE, e);
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package org.opsli.core.security.shiro.session;
|
||||
|
||||
import org.apache.shiro.session.Session;
|
||||
import org.apache.shiro.session.SessionListener;
|
||||
|
||||
/**
|
||||
* <p></p>
|
||||
*
|
||||
* @author sunzhiqiang23
|
||||
* @date 2020-04-25 17:29
|
||||
*/
|
||||
public class MySessionListener implements SessionListener {
|
||||
|
||||
@Override
|
||||
public void onStart(Session session) {
|
||||
System.out.println("会话创建:" + session.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop(Session session) {
|
||||
System.out.println("会话退出:" + session.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExpiration(Session session) {
|
||||
System.out.println("会话过期:" + session.getId());
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package org.opsli.core.security.shiro.session;
|
||||
|
||||
import org.apache.shiro.session.Session;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <p></p>
|
||||
*
|
||||
* @author sunzhiqiang23
|
||||
* @date 2020-04-27 20:52
|
||||
*/
|
||||
public class SessionInMemory {
|
||||
private Session session;
|
||||
private Date createTime;
|
||||
|
||||
public Session getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
public void setSession(Session session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
public Date getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(Date createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package org.opsli.core.security.shiro.session;
|
||||
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.shiro.session.Session;
|
||||
import org.apache.shiro.session.UnknownSessionException;
|
||||
import org.apache.shiro.session.mgt.SessionKey;
|
||||
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
|
||||
import org.apache.shiro.web.session.mgt.WebSessionKey;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* <p>解决单次请求需要多次访问redis</p>
|
||||
*
|
||||
* @author sunzhiqiang23
|
||||
* @date 2020-04-27 20:58
|
||||
*/
|
||||
@Slf4j
|
||||
public class ShiroSessionManager extends DefaultWebSessionManager {
|
||||
|
||||
/**
|
||||
* 获取session
|
||||
* 优化单次请求需要多次访问redis的问题
|
||||
* @param sessionKey
|
||||
* @return
|
||||
* @throws UnknownSessionException
|
||||
*/
|
||||
@Override
|
||||
protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException {
|
||||
Serializable sessionId = getSessionId(sessionKey);
|
||||
|
||||
ServletRequest request = null;
|
||||
if (sessionKey instanceof WebSessionKey) {
|
||||
request = ((WebSessionKey) sessionKey).getServletRequest();
|
||||
}
|
||||
|
||||
if (request != null && null != sessionId) {
|
||||
Object sessionObj = request.getAttribute(sessionId.toString());
|
||||
if (sessionObj != null) {
|
||||
log.debug("read session from request");
|
||||
return (Session) sessionObj;
|
||||
}
|
||||
}
|
||||
|
||||
Session session = super.retrieveSession(sessionKey);
|
||||
if (request != null && null != sessionId) {
|
||||
request.setAttribute(sessionId.toString(), session);
|
||||
}
|
||||
return session;
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package org.opsli.core.security.shiro.token;
|
||||
|
||||
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
|
||||
/**
|
||||
* jwt token
|
||||
*
|
||||
* @author parker
|
||||
|
||||
* @date 2017-05-20 13:22
|
||||
*/
|
||||
public class JwtToken implements AuthenticationToken {
|
||||
private String token;
|
||||
|
||||
public JwtToken(String token){
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrincipal() {
|
||||
return token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCredentials() {
|
||||
return token;
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package org.opsli.core.security.shiro.token;
|
||||
|
||||
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
|
||||
/**
|
||||
* OAuth2 token
|
||||
*
|
||||
* @author 孙志强
|
||||
|
||||
* @date 2017-05-20 13:22
|
||||
*/
|
||||
public class OAuth2Token implements AuthenticationToken {
|
||||
private String token;
|
||||
|
||||
public OAuth2Token(String token){
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrincipal() {
|
||||
return token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCredentials() {
|
||||
return token;
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright 2018 人人开源 http://www.renren.io
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.opsli.core.security.shiro.utils;
|
||||
|
||||
/**
|
||||
* Redis所有Keys
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
* @since 3.0.0 2017-07-18
|
||||
*/
|
||||
public class RedisKeys {
|
||||
|
||||
public static String getSysConfigKey(String key){
|
||||
return "system:config:" + key;
|
||||
}
|
||||
|
||||
public static String getShiroSessionKey(String key){
|
||||
return "sessionid:" + key;
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Copyright 2018 人人开源 http://www.renren.io
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.opsli.core.security.shiro.utils;
|
||||
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.crypto.hash.SimpleHash;
|
||||
import org.apache.shiro.session.Session;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.opsli.api.wrapper.system.user.UserModel;
|
||||
|
||||
/**
|
||||
* Shiro工具类
|
||||
*
|
||||
* @author 孙志强
|
||||
|
||||
* @date 2016年11月12日 上午9:49:19
|
||||
*/
|
||||
public class ShiroUtils {
|
||||
|
||||
/** 加密算法 */
|
||||
public final static String hashAlgorithmName = "MD5";
|
||||
/** 循环次数 */
|
||||
public final static int hashIterations = 1;
|
||||
|
||||
public static String sha256(String password, String salt) {
|
||||
return new SimpleHash(hashAlgorithmName, password, salt, hashIterations).toString();
|
||||
}
|
||||
|
||||
public static Session getSession() {
|
||||
return SecurityUtils.getSubject().getSession();
|
||||
}
|
||||
|
||||
public static Subject getSubject() {
|
||||
return SecurityUtils.getSubject();
|
||||
}
|
||||
|
||||
public static UserModel getUser() {
|
||||
return (UserModel) SecurityUtils.getSubject().getPrincipal();
|
||||
}
|
||||
|
||||
public static String getUserId() {
|
||||
return getUser().getId();
|
||||
}
|
||||
|
||||
public static void setSessionAttribute(Object key, Object value) {
|
||||
getSession().setAttribute(key, value);
|
||||
}
|
||||
|
||||
public static Object getSessionAttribute(Object key) {
|
||||
return getSession().getAttribute(key);
|
||||
}
|
||||
|
||||
public static boolean isLogin() {
|
||||
return SecurityUtils.getSubject().getPrincipal() != null;
|
||||
}
|
||||
|
||||
public static void logout() {
|
||||
SecurityUtils.getSubject().logout();
|
||||
}
|
||||
|
||||
public static String getKaptcha(String key) throws RuntimeException {
|
||||
Object kaptcha = getSessionAttribute(key);
|
||||
if(kaptcha == null){
|
||||
throw new RuntimeException("验证码已失效");
|
||||
}
|
||||
getSession().removeAttribute(key);
|
||||
return kaptcha.toString();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package org.opsli.core.utils;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* Base64工具
|
||||
* @author 孙志强
|
||||
* @date 2018/11/05 23:10
|
||||
*/
|
||||
public final class Base64ConvertUtil {
|
||||
/**
|
||||
* 加密
|
||||
* @param str
|
||||
* @return java.lang.String
|
||||
*/
|
||||
public static String encode(String str) throws UnsupportedEncodingException {
|
||||
byte[] encodeBytes = Base64.getEncoder().encode(str.getBytes("utf-8"));
|
||||
return new String(encodeBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密
|
||||
* @param str
|
||||
* @return java.lang.String
|
||||
*/
|
||||
public static String decode(String str) throws UnsupportedEncodingException {
|
||||
byte[] decodeBytes = Base64.getDecoder().decode(str.getBytes("utf-8"));
|
||||
return new String(decodeBytes);
|
||||
}
|
||||
|
||||
// ==============
|
||||
private Base64ConvertUtil(){}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package org.opsli.core.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.google.code.kaptcha.Producer;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.opsli.plugins.redis.RedisPlugin;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
*
|
||||
* @author parker
|
||||
* @since 2.0.0 2018-02-10
|
||||
*/
|
||||
@Component
|
||||
public class CaptchaUtil{
|
||||
|
||||
/** 缓存前缀 */
|
||||
private static final String PREFIX = "opsli:temp:captcha:";
|
||||
/** 默认验证码保存 5 分钟 */
|
||||
private static final int TIME_OUT = 300;
|
||||
/** Redis插件 */
|
||||
private static RedisPlugin redisPlugin;
|
||||
/** 谷歌验证码 */
|
||||
private static Producer producer;
|
||||
|
||||
/**
|
||||
* 获得验证码
|
||||
* @param uuid
|
||||
* @return
|
||||
*/
|
||||
public static BufferedImage getCaptcha(String uuid) {
|
||||
if(StringUtils.isBlank(uuid)){
|
||||
throw new RuntimeException("uuid不能为空");
|
||||
}
|
||||
//生成文字验证码
|
||||
String code = producer.createText();
|
||||
|
||||
boolean ret = redisPlugin.put(PREFIX + uuid, code, TIME_OUT);
|
||||
|
||||
if(ret){
|
||||
return producer.createImage(code);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验验证码
|
||||
* @param uuid
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
public static boolean validate(String uuid, String code) {
|
||||
if(StringUtils.isEmpty(uuid)) return false;
|
||||
|
||||
// 验证码
|
||||
String codeTemp = (String) redisPlugin.get(PREFIX + uuid);
|
||||
|
||||
if(StringUtils.isEmpty(codeTemp)){
|
||||
return false;
|
||||
}
|
||||
|
||||
//删除验证码
|
||||
redisPlugin.del(PREFIX + uuid);
|
||||
|
||||
return codeTemp.equalsIgnoreCase(code);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ==========================
|
||||
|
||||
@Autowired
|
||||
public void setRedisPlugin(RedisPlugin redisPlugin) {
|
||||
CaptchaUtil.redisPlugin = redisPlugin;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setProducer(Producer producer) {
|
||||
CaptchaUtil.producer = producer;
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package org.opsli.core.utils;
|
||||
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 生成token
|
||||
*
|
||||
* @author Parker
|
||||
|
||||
* @date 2017-05-20 14:41
|
||||
*/
|
||||
public final class TokenGenerator {
|
||||
|
||||
public static String generateValue() {
|
||||
return generateValue(UUID.randomUUID().toString());
|
||||
}
|
||||
|
||||
private static final char[] hexCode = "0123456789abcdef".toCharArray();
|
||||
|
||||
|
||||
/**
|
||||
* 生成Token
|
||||
* @param param
|
||||
* @return
|
||||
*/
|
||||
public static String generateValue(String param) {
|
||||
try {
|
||||
MessageDigest algorithm = MessageDigest.getInstance("MD5");
|
||||
algorithm.reset();
|
||||
algorithm.update(param.getBytes());
|
||||
byte[] messageDigest = algorithm.digest();
|
||||
return toHexString(messageDigest);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("生成Token失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static String toHexString(byte[] data) {
|
||||
if(data == null) {
|
||||
return null;
|
||||
}
|
||||
StringBuilder r = new StringBuilder(data.length*2);
|
||||
for ( byte b : data) {
|
||||
r.append(hexCode[(b >> 4) & 0xF]);
|
||||
r.append(hexCode[(b & 0xF)]);
|
||||
}
|
||||
return r.toString();
|
||||
}
|
||||
|
||||
|
||||
// =========================
|
||||
private TokenGenerator(){}
|
||||
}
|
@ -0,0 +1 @@
|
||||
123123
|
@ -0,0 +1 @@
|
||||
## 改造微服务时 将Feign 接口写在这里
|
@ -0,0 +1,49 @@
|
||||
/**
|
||||
*
|
||||
* <p>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.opsli.modulars.system.login.entity;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 登录表单
|
||||
*
|
||||
* @author liuzp
|
||||
* @since 2.0.0 2018-01-25
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class LoginForm {
|
||||
|
||||
/** 用户名 */
|
||||
@ApiModelProperty(value = "用户名")
|
||||
private String username;
|
||||
|
||||
/** 密码 */
|
||||
@ApiModelProperty(value = "密码")
|
||||
private String password;
|
||||
|
||||
/** 验证码 */
|
||||
@ApiModelProperty(value = "验证码")
|
||||
private String captcha;
|
||||
|
||||
/** UUID */
|
||||
@ApiModelProperty(value = "UUID")
|
||||
private String uuid;
|
||||
|
||||
}
|
@ -0,0 +1 @@
|
||||
## 改造微服务时 将Feign 接口写在这里
|
@ -0,0 +1,45 @@
|
||||
package org.opsli.modulars.system.menu.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.opsli.core.base.entity.BaseEntity;
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.modulars.test.entity
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-16 17:33
|
||||
* @Description: 菜单表
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class SysMenu extends BaseEntity {
|
||||
|
||||
|
||||
/** 父级主键 */
|
||||
private String parentId;
|
||||
|
||||
/** 菜单编号 */
|
||||
private String menuCode;
|
||||
|
||||
/** 菜单名称 */
|
||||
private String menuName;
|
||||
|
||||
/** 图标 */
|
||||
private String icon;
|
||||
|
||||
/** 项目类型:1-菜单2-按钮3-链接4-表单 */
|
||||
private String type;
|
||||
|
||||
/** url地址 */
|
||||
private String url;
|
||||
|
||||
|
||||
// ========================================
|
||||
|
||||
/** 逻辑删除字段 */
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package org.opsli.modulars.system.menu.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.opsli.modulars.system.menu.entity.SysMenu;
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.modulars.test.mapper
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-17 13:01
|
||||
* @Description: 角色 Mapper
|
||||
*/
|
||||
@Mapper
|
||||
public interface MenuMapper extends BaseMapper<SysMenu> {
|
||||
|
||||
/**
|
||||
* 唯一验证
|
||||
* @param entity
|
||||
* @return
|
||||
*/
|
||||
Integer uniqueVerificationByCode(SysMenu entity);
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.opsli.modulars.system.menu.mapper.MenuMapper">
|
||||
|
||||
<!-- 数据库字段 -->
|
||||
<sql id="SysRoleColumns">
|
||||
a.id as id,
|
||||
|
||||
a.parent_id as parentId,
|
||||
a.menu_code as menuCode,
|
||||
a.menu_name as menuName,
|
||||
a.icon as icon,
|
||||
a.type as type,
|
||||
a.url as url,
|
||||
a.iz_lock as izLock,
|
||||
|
||||
a.create_by as createBy,
|
||||
a.create_time as createTime,
|
||||
a.update_by as updateBy,
|
||||
a.update_time as updateTime,
|
||||
a.version as version,
|
||||
a.deleted as deleted
|
||||
</sql>
|
||||
|
||||
<sql id="SysRoleJoins">
|
||||
</sql>
|
||||
|
||||
<select id="uniqueVerificationByCode" parameterType="SysMenu" resultType="Integer">
|
||||
select
|
||||
count(0)
|
||||
from
|
||||
sys_menu a
|
||||
where
|
||||
a.menu_code = #{menuCode}
|
||||
and a.deleted = 0
|
||||
<if test="id != null and id != ''">
|
||||
AND a.id != #{id}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
</mapper>
|
@ -0,0 +1,18 @@
|
||||
package org.opsli.modulars.system.menu.service;
|
||||
|
||||
import org.opsli.api.wrapper.system.menu.MenuModel;
|
||||
import org.opsli.core.base.service.interfaces.CrudServiceInterface;
|
||||
import org.opsli.modulars.system.menu.entity.SysMenu;
|
||||
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.modulars.test.service
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-17 13:07
|
||||
* @Description: 角色 接口
|
||||
*/
|
||||
public interface IMenuService extends CrudServiceInterface<SysMenu, MenuModel> {
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package org.opsli.modulars.system.menu.service.impl;
|
||||
|
||||
import org.opsli.api.wrapper.system.menu.MenuModel;
|
||||
import org.opsli.common.exception.ServiceException;
|
||||
import org.opsli.common.utils.WrapperUtil;
|
||||
import org.opsli.core.base.service.impl.CrudServiceImpl;
|
||||
import org.opsli.modulars.system.SystemMsg;
|
||||
import org.opsli.modulars.system.menu.entity.SysMenu;
|
||||
import org.opsli.modulars.system.menu.mapper.MenuMapper;
|
||||
import org.opsli.modulars.system.menu.service.IMenuService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.modulars.test.service
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-16 17:34
|
||||
* @Description: 角色 接口实现类
|
||||
*/
|
||||
@Service
|
||||
public class MenuServiceImpl extends CrudServiceImpl<MenuMapper, SysMenu, MenuModel> implements IMenuService {
|
||||
|
||||
@Autowired(required = false)
|
||||
private MenuMapper mapper;
|
||||
|
||||
@Override
|
||||
public MenuModel insert(MenuModel model) {
|
||||
if(model == null) return null;
|
||||
|
||||
SysMenu entity = super.transformM2T(model);
|
||||
// 唯一验证
|
||||
Integer count = mapper.uniqueVerificationByCode(entity);
|
||||
if(count != null && count > 0){
|
||||
// 重复
|
||||
throw new ServiceException(SystemMsg.EXCEPTION_ROLE_UNIQUE);
|
||||
}
|
||||
|
||||
return super.insert(model);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public MenuModel update(MenuModel model) {
|
||||
if(model == null) return null;
|
||||
|
||||
SysMenu entity = super.transformM2T(model);
|
||||
// 唯一验证
|
||||
Integer count = mapper.uniqueVerificationByCode(entity);
|
||||
if(count != null && count > 0){
|
||||
// 重复
|
||||
throw new ServiceException(SystemMsg.EXCEPTION_ROLE_UNIQUE);
|
||||
}
|
||||
|
||||
return super.update(model);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,156 @@
|
||||
package org.opsli.modulars.system.menu.web;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.opsli.api.base.result.ResultVo;
|
||||
import org.opsli.api.web.system.menu.MenuApi;
|
||||
import org.opsli.api.wrapper.system.menu.MenuModel;
|
||||
import org.opsli.common.annotation.ApiRestController;
|
||||
import org.opsli.core.base.concroller.BaseRestController;
|
||||
import org.opsli.core.persistence.Page;
|
||||
import org.opsli.core.persistence.querybuilder.QueryBuilder;
|
||||
import org.opsli.core.persistence.querybuilder.WebQueryBuilder;
|
||||
import org.opsli.modulars.system.menu.entity.SysMenu;
|
||||
import org.opsli.modulars.system.menu.service.IMenuService;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.modulars.test.web
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-13 17:40
|
||||
* @Description: 菜单
|
||||
*/
|
||||
@Slf4j
|
||||
@ApiRestController("/sys/menu")
|
||||
public class MenuRestController extends BaseRestController<SysMenu, MenuModel, IMenuService>
|
||||
implements MenuApi {
|
||||
|
||||
|
||||
/**
|
||||
* 菜单 查一条
|
||||
* @param model 模型
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "获得单条字典明细数据", notes = "获得单条字典明细数据 - ID")
|
||||
@Override
|
||||
public ResultVo<MenuModel> get(MenuModel model) {
|
||||
// 如果系统内部调用 则直接查数据库
|
||||
if(model != null && model.getIzApi() != null && model.getIzApi()){
|
||||
model = IService.get(model);
|
||||
}
|
||||
return ResultVo.success(model);
|
||||
}
|
||||
|
||||
/**
|
||||
* 菜单 查询分页
|
||||
* @param pageNo 当前页
|
||||
* @param pageSize 每页条数
|
||||
* @param request request
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "获得分页数据", notes = "获得分页数据 - 查询构造器")
|
||||
@Override
|
||||
public ResultVo<?> findPage(Integer pageNo, Integer pageSize, HttpServletRequest request) {
|
||||
|
||||
QueryBuilder<SysMenu> queryBuilder = new WebQueryBuilder<>(SysMenu.class, request.getParameterMap());
|
||||
Page<SysMenu, MenuModel> page = new Page<>(pageNo, pageSize);
|
||||
page.setQueryWrapper(queryBuilder.build());
|
||||
page = IService.findPage(page);
|
||||
|
||||
return ResultVo.success(page.getBootstrapData());
|
||||
}
|
||||
|
||||
/**
|
||||
* 菜单 新增
|
||||
* @param model 模型
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "新增字典明细数据", notes = "新增字典明细数据")
|
||||
@Override
|
||||
public ResultVo<?> insert(MenuModel model) {
|
||||
// 调用新增方法
|
||||
IService.insert(model);
|
||||
return ResultVo.success("新增字典明细数据成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 菜单 修改
|
||||
* @param model 模型
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "修改字典明细数据", notes = "修改字典明细数据")
|
||||
@Override
|
||||
public ResultVo<?> update(MenuModel model) {
|
||||
// 调用修改方法
|
||||
IService.update(model);
|
||||
return ResultVo.success("修改字典明细数据成功");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 菜单 删除
|
||||
* @param id ID
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "删除字典明细数据数据", notes = "删除字典明细数据数据")
|
||||
@Override
|
||||
public ResultVo<?> del(String id){
|
||||
IService.delete(id);
|
||||
return ResultVo.success("删除字典明细数据成功");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 菜单 批量删除
|
||||
* @param ids ID 数组
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "批量删除字典明细数据数据", notes = "批量删除字典明细数据数据")
|
||||
@Override
|
||||
public ResultVo<?> delAll(String[] ids){
|
||||
IService.deleteAll(ids);
|
||||
return ResultVo.success("批量删除字典明细数据成功");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 菜单 Excel 导出
|
||||
* @param request request
|
||||
* @param response response
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "导出Excel", notes = "导出Excel")
|
||||
@Override
|
||||
public ResultVo<?> exportExcel(HttpServletRequest request, HttpServletResponse response) {
|
||||
QueryBuilder<SysMenu> queryBuilder = new WebQueryBuilder<>(SysMenu.class, request.getParameterMap());
|
||||
return super.excelExport(MenuApi.TITLE, queryBuilder.build(), response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 菜单 Excel 导入
|
||||
* @param request 文件流 request
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "导入Excel", notes = "导入Excel")
|
||||
@Override
|
||||
public ResultVo<?> excelImport(MultipartHttpServletRequest request) {
|
||||
return super.excelImport(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 菜单 Excel 下载导入模版
|
||||
* @param response response
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "导出Excel模版", notes = "导出Excel模版")
|
||||
@Override
|
||||
public ResultVo<?> importTemplate(HttpServletResponse response) {
|
||||
return super.importTemplate(MenuApi.TITLE, response);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1 @@
|
||||
## 改造微服务时 将Feign 接口写在这里
|
@ -0,0 +1,40 @@
|
||||
package org.opsli.modulars.system.role.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.opsli.core.base.entity.BaseEntity;
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.modulars.test.entity
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-16 17:33
|
||||
* @Description: 角色表
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class SysRole extends BaseEntity {
|
||||
|
||||
|
||||
|
||||
/** 角色编码 */
|
||||
private String roleCode;
|
||||
|
||||
/** 角色名称 */
|
||||
private String roleName;
|
||||
|
||||
/** 是否内置数据 0是 1否*/
|
||||
private Character izLock;
|
||||
|
||||
/** 备注 */
|
||||
private String remark;
|
||||
|
||||
|
||||
// ========================================
|
||||
|
||||
/** 逻辑删除字段 */
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package org.opsli.modulars.system.role.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.opsli.modulars.system.role.entity.SysRole;
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.modulars.test.mapper
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-17 13:01
|
||||
* @Description: 角色 Mapper
|
||||
*/
|
||||
@Mapper
|
||||
public interface RoleMapper extends BaseMapper<SysRole> {
|
||||
|
||||
/**
|
||||
* 唯一验证
|
||||
* @param entity
|
||||
* @return
|
||||
*/
|
||||
Integer uniqueVerificationByCode(SysRole entity);
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.opsli.modulars.system.role.mapper.RoleMapper">
|
||||
|
||||
<!-- 数据库字段 -->
|
||||
<sql id="SysRoleColumns">
|
||||
a.id as id,
|
||||
|
||||
a.role_code as roleCode,
|
||||
a.role_name as roleName,
|
||||
a.iz_lock as izLock,
|
||||
a.remark as remark,
|
||||
|
||||
a.create_by as createBy,
|
||||
a.create_time as createTime,
|
||||
a.update_by as updateBy,
|
||||
a.update_time as updateTime,
|
||||
a.version as version,
|
||||
a.deleted as deleted
|
||||
</sql>
|
||||
|
||||
<sql id="SysRoleJoins">
|
||||
</sql>
|
||||
|
||||
<select id="uniqueVerificationByCode" parameterType="SysRole" resultType="Integer">
|
||||
select
|
||||
count(0)
|
||||
from
|
||||
sys_role a
|
||||
where
|
||||
a.role_code = #{roleCode}
|
||||
and a.deleted = 0
|
||||
<if test="id != null and id != ''">
|
||||
AND a.id != #{id}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
</mapper>
|
@ -0,0 +1,18 @@
|
||||
package org.opsli.modulars.system.role.service;
|
||||
|
||||
import org.opsli.api.wrapper.system.role.RoleModel;
|
||||
import org.opsli.core.base.service.interfaces.CrudServiceInterface;
|
||||
import org.opsli.modulars.system.role.entity.SysRole;
|
||||
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.modulars.test.service
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-17 13:07
|
||||
* @Description: 角色 接口
|
||||
*/
|
||||
public interface IRoleService extends CrudServiceInterface<SysRole, RoleModel> {
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package org.opsli.modulars.system.role.service.impl;
|
||||
|
||||
import org.opsli.api.wrapper.system.role.RoleModel;
|
||||
import org.opsli.common.exception.ServiceException;
|
||||
import org.opsli.core.base.service.impl.CrudServiceImpl;
|
||||
import org.opsli.modulars.system.SystemMsg;
|
||||
import org.opsli.modulars.system.role.entity.SysRole;
|
||||
import org.opsli.modulars.system.role.mapper.RoleMapper;
|
||||
import org.opsli.modulars.system.role.service.IRoleService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.modulars.test.service
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-16 17:34
|
||||
* @Description: 角色 接口实现类
|
||||
*/
|
||||
@Service
|
||||
public class RoleServiceImpl extends CrudServiceImpl<RoleMapper, SysRole, RoleModel> implements IRoleService {
|
||||
|
||||
@Autowired(required = false)
|
||||
private RoleMapper mapper;
|
||||
|
||||
@Override
|
||||
public RoleModel insert(RoleModel model) {
|
||||
if(model == null) return null;
|
||||
|
||||
SysRole entity = super.transformM2T(model);
|
||||
// 唯一验证
|
||||
Integer count = mapper.uniqueVerificationByCode(entity);
|
||||
if(count != null && count > 0){
|
||||
// 重复
|
||||
throw new ServiceException(SystemMsg.EXCEPTION_ROLE_UNIQUE);
|
||||
}
|
||||
|
||||
return super.insert(model);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public RoleModel update(RoleModel model) {
|
||||
if(model == null) return null;
|
||||
|
||||
SysRole entity = super.transformM2T(model);
|
||||
// 唯一验证
|
||||
Integer count = mapper.uniqueVerificationByCode(entity);
|
||||
if(count != null && count > 0){
|
||||
// 重复
|
||||
throw new ServiceException(SystemMsg.EXCEPTION_ROLE_UNIQUE);
|
||||
}
|
||||
|
||||
return super.update(model);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,156 @@
|
||||
package org.opsli.modulars.system.role.web;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.opsli.api.base.result.ResultVo;
|
||||
import org.opsli.api.web.system.role.RoleApi;
|
||||
import org.opsli.api.wrapper.system.role.RoleModel;
|
||||
import org.opsli.common.annotation.ApiRestController;
|
||||
import org.opsli.core.base.concroller.BaseRestController;
|
||||
import org.opsli.core.persistence.Page;
|
||||
import org.opsli.core.persistence.querybuilder.QueryBuilder;
|
||||
import org.opsli.core.persistence.querybuilder.WebQueryBuilder;
|
||||
import org.opsli.modulars.system.role.entity.SysRole;
|
||||
import org.opsli.modulars.system.role.service.IRoleService;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.modulars.test.web
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-13 17:40
|
||||
* @Description: 角色
|
||||
*/
|
||||
@Slf4j
|
||||
@ApiRestController("/sys/role")
|
||||
public class RoleRestController extends BaseRestController<SysRole, RoleModel, IRoleService>
|
||||
implements RoleApi {
|
||||
|
||||
|
||||
/**
|
||||
* 角色 查一条
|
||||
* @param model 模型
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "获得单条字典明细数据", notes = "获得单条字典明细数据 - ID")
|
||||
@Override
|
||||
public ResultVo<RoleModel> get(RoleModel model) {
|
||||
// 如果系统内部调用 则直接查数据库
|
||||
if(model != null && model.getIzApi() != null && model.getIzApi()){
|
||||
model = IService.get(model);
|
||||
}
|
||||
return ResultVo.success(model);
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色 查询分页
|
||||
* @param pageNo 当前页
|
||||
* @param pageSize 每页条数
|
||||
* @param request request
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "获得分页数据", notes = "获得分页数据 - 查询构造器")
|
||||
@Override
|
||||
public ResultVo<?> findPage(Integer pageNo, Integer pageSize, HttpServletRequest request) {
|
||||
|
||||
QueryBuilder<SysRole> queryBuilder = new WebQueryBuilder<>(SysRole.class, request.getParameterMap());
|
||||
Page<SysRole, RoleModel> page = new Page<>(pageNo, pageSize);
|
||||
page.setQueryWrapper(queryBuilder.build());
|
||||
page = IService.findPage(page);
|
||||
|
||||
return ResultVo.success(page.getBootstrapData());
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色 新增
|
||||
* @param model 模型
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "新增字典明细数据", notes = "新增字典明细数据")
|
||||
@Override
|
||||
public ResultVo<?> insert(RoleModel model) {
|
||||
// 调用新增方法
|
||||
IService.insert(model);
|
||||
return ResultVo.success("新增字典明细数据成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色 修改
|
||||
* @param model 模型
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "修改字典明细数据", notes = "修改字典明细数据")
|
||||
@Override
|
||||
public ResultVo<?> update(RoleModel model) {
|
||||
// 调用修改方法
|
||||
IService.update(model);
|
||||
return ResultVo.success("修改字典明细数据成功");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 角色 删除
|
||||
* @param id ID
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "删除字典明细数据数据", notes = "删除字典明细数据数据")
|
||||
@Override
|
||||
public ResultVo<?> del(String id){
|
||||
IService.delete(id);
|
||||
return ResultVo.success("删除字典明细数据成功");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 角色 批量删除
|
||||
* @param ids ID 数组
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "批量删除字典明细数据数据", notes = "批量删除字典明细数据数据")
|
||||
@Override
|
||||
public ResultVo<?> delAll(String[] ids){
|
||||
IService.deleteAll(ids);
|
||||
return ResultVo.success("批量删除字典明细数据成功");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 角色 Excel 导出
|
||||
* @param request request
|
||||
* @param response response
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "导出Excel", notes = "导出Excel")
|
||||
@Override
|
||||
public ResultVo<?> exportExcel(HttpServletRequest request, HttpServletResponse response) {
|
||||
QueryBuilder<SysRole> queryBuilder = new WebQueryBuilder<>(SysRole.class, request.getParameterMap());
|
||||
return super.excelExport(RoleApi.TITLE, queryBuilder.build(), response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色 Excel 导入
|
||||
* @param request 文件流 request
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "导入Excel", notes = "导入Excel")
|
||||
@Override
|
||||
public ResultVo<?> excelImport(MultipartHttpServletRequest request) {
|
||||
return super.excelImport(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色 Excel 下载导入模版
|
||||
* @param response response
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "导出Excel模版", notes = "导出Excel模版")
|
||||
@Override
|
||||
public ResultVo<?> importTemplate(HttpServletResponse response) {
|
||||
return super.importTemplate(RoleApi.TITLE, response);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1 @@
|
||||
## 改造微服务时 将Feign 接口写在这里
|
@ -0,0 +1,62 @@
|
||||
package org.opsli.modulars.system.user.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.opsli.core.base.entity.BaseEntity;
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.modulars.test.entity
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-16 17:33
|
||||
* @Description: 用户信息表
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class SysUser extends BaseEntity {
|
||||
|
||||
|
||||
/** 登录账户 */
|
||||
private String username;
|
||||
|
||||
/** 登录密码 */
|
||||
private String password;
|
||||
|
||||
/** 盐值,密码秘钥 */
|
||||
private String secretKey;
|
||||
|
||||
/** 是否锁定 */
|
||||
private String locked;
|
||||
|
||||
/** 真实姓名 */
|
||||
private String realName;
|
||||
|
||||
/** 手机 */
|
||||
private String mobile;
|
||||
|
||||
/** 邮箱 */
|
||||
private String email;
|
||||
|
||||
/** 工号 */
|
||||
private String no;
|
||||
|
||||
/** 头像 */
|
||||
private String avatar;
|
||||
|
||||
/** 最后登陆IP */
|
||||
private String loginIp;
|
||||
|
||||
/** 备注 */
|
||||
private String remark;
|
||||
|
||||
// ========================================
|
||||
|
||||
/** 逻辑删除字段 */
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
/** 多租户字段 */
|
||||
private String tenantId;
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package org.opsli.modulars.system.user.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.opsli.modulars.system.menu.entity.SysMenu;
|
||||
import org.opsli.modulars.system.user.entity.SysUser;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.modulars.test.mapper
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-17 13:01
|
||||
* @Description: 用户 Mapper
|
||||
*/
|
||||
@Mapper
|
||||
public interface UserMapper extends BaseMapper<SysUser> {
|
||||
|
||||
/**
|
||||
* 唯一验证
|
||||
* @param entity
|
||||
* @return
|
||||
*/
|
||||
Integer uniqueVerificationByUsername(SysUser entity);
|
||||
|
||||
|
||||
/**
|
||||
* 根据用户ID 获得当前角色编码集合
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
List<String> getRoleCodeList(String userId);
|
||||
|
||||
/**
|
||||
* 根据用户ID 获得权限
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
List<String> queryAllPerms(String userId);
|
||||
|
||||
/**
|
||||
* 根据用户ID 获得菜单集合
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
List<SysMenu> findMenuListByUserId(String userId);
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.opsli.modulars.system.user.mapper.UserMapper">
|
||||
|
||||
<!-- 数据库字段 -->
|
||||
<sql id="SysDictColumns">
|
||||
a.id as id,
|
||||
|
||||
a.username as username,
|
||||
a.password as password,
|
||||
a.secret_key as secretKey,
|
||||
a.no as no,
|
||||
a.real_name as realName,
|
||||
a.locked as locked,
|
||||
a.mobile as mobile,
|
||||
a.email as email,
|
||||
a.avatar as avatar,
|
||||
a.login_ip as loginIp,
|
||||
a.remark as remark,
|
||||
a.tenant_id as tenantId,
|
||||
|
||||
a.create_by as createBy,
|
||||
a.create_time as createTime,
|
||||
a.update_by as updateBy,
|
||||
a.update_time as updateTime,
|
||||
a.version as version,
|
||||
a.deleted as deleted
|
||||
</sql>
|
||||
|
||||
<sql id="SysDictJoins">
|
||||
</sql>
|
||||
|
||||
<select id="uniqueVerificationByUsername" parameterType="SysUser" resultType="Integer">
|
||||
select
|
||||
count(0)
|
||||
from
|
||||
sys_user a
|
||||
where
|
||||
a.username = #{username}
|
||||
and a.deleted = 0
|
||||
<if test="id != null and id != ''">
|
||||
AND a.id != #{id}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
|
||||
<select id="queryAllPerms" resultType="String">
|
||||
select
|
||||
a.menu_code
|
||||
from
|
||||
sys_menu a,
|
||||
sys_role_menu_ref b,
|
||||
sys_user_role_ref c
|
||||
where
|
||||
a.id = b.module_id
|
||||
and b.role_id = c.role_id
|
||||
and a.type in ( '2', '3', '4' )
|
||||
and c.user_id = #{userId}
|
||||
where
|
||||
</select>
|
||||
|
||||
<select id="getRoleCodeList" resultType="String">
|
||||
select
|
||||
b.role_code
|
||||
from
|
||||
sys_user_role_ref a,
|
||||
sys_role b
|
||||
where
|
||||
a.role_id = b.id
|
||||
and a.user_id = #{userId}
|
||||
</select>
|
||||
|
||||
<!-- 根据用户id查询菜单列表-->
|
||||
<select id="findMenuListByUserId" resultType="SysMenu">
|
||||
select
|
||||
c.id,
|
||||
c.icon,
|
||||
c.menu_name,
|
||||
c.url,
|
||||
c.parent_Id
|
||||
from
|
||||
sys_user_role_ref a,
|
||||
sys_role_menu_ref b,
|
||||
sys_menu c
|
||||
where
|
||||
a.role_Id = b.role_Id
|
||||
and b.menu_id = c.id
|
||||
and c.parent_id != -1
|
||||
and a.user_id = #{userId}
|
||||
and c.type = '1'
|
||||
order by c.id
|
||||
</select>
|
||||
|
||||
</mapper>
|
@ -0,0 +1,48 @@
|
||||
package org.opsli.modulars.system.user.service;
|
||||
|
||||
import org.opsli.api.wrapper.system.menu.MenuModel;
|
||||
import org.opsli.api.wrapper.system.user.UserModel;
|
||||
import org.opsli.core.base.service.interfaces.CrudServiceInterface;
|
||||
import org.opsli.modulars.system.user.entity.SysUser;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.modulars.test.service
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-17 13:07
|
||||
* @Description: 用户 接口
|
||||
*/
|
||||
public interface IUserService extends CrudServiceInterface<SysUser, UserModel> {
|
||||
|
||||
/**
|
||||
* 根据 用户名 获得当前用户
|
||||
* @param username
|
||||
* @return
|
||||
*/
|
||||
UserModel queryByUserName(String username);
|
||||
|
||||
/**
|
||||
* 根据用户ID 获得当前角色编码集合
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
List<String> getRoleCodeList(String userId);
|
||||
|
||||
/**
|
||||
* 根据用户ID 获得权限
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
List<String> getAllPerms(String userId);
|
||||
|
||||
/**
|
||||
* 根据用户ID 获得菜单集合
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
List<MenuModel> getMenuListByUserId(String userId);
|
||||
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
package org.opsli.modulars.system.user.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import org.opsli.api.wrapper.system.menu.MenuModel;
|
||||
import org.opsli.api.wrapper.system.user.UserModel;
|
||||
import org.opsli.common.exception.ServiceException;
|
||||
import org.opsli.common.utils.HumpUtil;
|
||||
import org.opsli.common.utils.WrapperUtil;
|
||||
import org.opsli.core.base.service.impl.CrudServiceImpl;
|
||||
import org.opsli.core.persistence.querybuilder.GenQueryBuilder;
|
||||
import org.opsli.core.persistence.querybuilder.QueryBuilder;
|
||||
import org.opsli.core.utils.UserUtil;
|
||||
import org.opsli.modulars.system.SystemMsg;
|
||||
import org.opsli.modulars.system.menu.entity.SysMenu;
|
||||
import org.opsli.modulars.system.user.entity.SysUser;
|
||||
import org.opsli.modulars.system.user.mapper.UserMapper;
|
||||
import org.opsli.modulars.system.user.service.IUserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.modulars.test.service
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-16 17:34
|
||||
* @Description: 角色 接口实现类
|
||||
*/
|
||||
@Service
|
||||
public class UserServiceImpl extends CrudServiceImpl<UserMapper, SysUser, UserModel> implements IUserService {
|
||||
|
||||
@Autowired(required = false)
|
||||
private UserMapper mapper;
|
||||
|
||||
@Override
|
||||
public UserModel insert(UserModel model) {
|
||||
if(model == null) return null;
|
||||
|
||||
SysUser entity = super.transformM2T(model);
|
||||
// 唯一验证
|
||||
Integer count = mapper.uniqueVerificationByUsername(entity);
|
||||
if(count != null && count > 0){
|
||||
// 重复
|
||||
throw new ServiceException(SystemMsg.EXCEPTION_USER_UNIQUE);
|
||||
}
|
||||
|
||||
return super.insert(model);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public UserModel update(UserModel model) {
|
||||
if(model == null) return null;
|
||||
|
||||
SysUser entity = super.transformM2T(model);
|
||||
// 唯一验证
|
||||
Integer count = mapper.uniqueVerificationByUsername(entity);
|
||||
if(count != null && count > 0){
|
||||
// 重复
|
||||
throw new ServiceException(SystemMsg.EXCEPTION_USER_UNIQUE);
|
||||
}
|
||||
|
||||
UserModel update = super.update(model);
|
||||
if(update != null){
|
||||
// 刷新用户缓存
|
||||
UserUtil.refreshUser(update);
|
||||
}
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel queryByUserName(String username) {
|
||||
String key = HumpUtil.humpToUnderline("username");
|
||||
QueryBuilder<SysUser> queryBuilder = new GenQueryBuilder<>();
|
||||
QueryWrapper<SysUser> queryWrapper = queryBuilder.build();
|
||||
queryWrapper.eq(key, username);
|
||||
SysUser user = this.getOne(queryWrapper);
|
||||
return super.transformT2M(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRoleCodeList(String userId) {
|
||||
return mapper.getRoleCodeList(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAllPerms(String userId) {
|
||||
return mapper.queryAllPerms(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MenuModel> getMenuListByUserId(String userId) {
|
||||
List<SysMenu> menuList = mapper.findMenuListByUserId(userId);
|
||||
return WrapperUtil.transformInstance(menuList, MenuModel.class);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,206 @@
|
||||
package org.opsli.modulars.system.user.web;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.opsli.api.base.result.ResultVo;
|
||||
import org.opsli.api.web.system.user.UserApi;
|
||||
import org.opsli.api.wrapper.system.menu.MenuModel;
|
||||
import org.opsli.api.wrapper.system.user.UserModel;
|
||||
import org.opsli.common.annotation.ApiRestController;
|
||||
import org.opsli.core.base.concroller.BaseRestController;
|
||||
import org.opsli.core.persistence.Page;
|
||||
import org.opsli.core.persistence.querybuilder.QueryBuilder;
|
||||
import org.opsli.core.persistence.querybuilder.WebQueryBuilder;
|
||||
import org.opsli.modulars.system.user.entity.SysUser;
|
||||
import org.opsli.modulars.system.user.service.IUserService;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* @BelongsProject: opsli-boot
|
||||
* @BelongsPackage: org.opsli.modulars.test.web
|
||||
* @Author: Parker
|
||||
* @CreateTime: 2020-09-13 17:40
|
||||
* @Description: 用户信息
|
||||
*/
|
||||
@Slf4j
|
||||
@ApiRestController("/sys/user")
|
||||
public class UserRestController extends BaseRestController<SysUser, UserModel, IUserService>
|
||||
implements UserApi {
|
||||
|
||||
|
||||
/**
|
||||
* 用户信息 查一条
|
||||
* @param model 模型
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "获得单条字典明细数据", notes = "获得单条字典明细数据 - ID")
|
||||
@Override
|
||||
public ResultVo<UserModel> get(UserModel model) {
|
||||
// 如果系统内部调用 则直接查数据库
|
||||
if(model != null && model.getIzApi() != null && model.getIzApi()){
|
||||
model = IService.get(model);
|
||||
}
|
||||
return ResultVo.success(model);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户信息 查询分页
|
||||
* @param pageNo 当前页
|
||||
* @param pageSize 每页条数
|
||||
* @param request request
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "获得分页数据", notes = "获得分页数据 - 查询构造器")
|
||||
@Override
|
||||
public ResultVo<?> findPage(Integer pageNo, Integer pageSize, HttpServletRequest request) {
|
||||
|
||||
QueryBuilder<SysUser> queryBuilder = new WebQueryBuilder<>(SysUser.class, request.getParameterMap());
|
||||
Page<SysUser, UserModel> page = new Page<>(pageNo, pageSize);
|
||||
page.setQueryWrapper(queryBuilder.build());
|
||||
page = IService.findPage(page);
|
||||
|
||||
return ResultVo.success(page.getBootstrapData());
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户信息 新增
|
||||
* @param model 模型
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "新增字典明细数据", notes = "新增字典明细数据")
|
||||
@Override
|
||||
public ResultVo<?> insert(UserModel model) {
|
||||
// 调用新增方法
|
||||
IService.insert(model);
|
||||
return ResultVo.success("新增字典明细数据成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户信息 修改
|
||||
* @param model 模型
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "修改字典明细数据", notes = "修改字典明细数据")
|
||||
@Override
|
||||
public ResultVo<?> update(UserModel model) {
|
||||
// 调用修改方法
|
||||
IService.update(model);
|
||||
return ResultVo.success("修改字典明细数据成功");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 用户信息 删除
|
||||
* @param id ID
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "删除字典明细数据数据", notes = "删除字典明细数据数据")
|
||||
@Override
|
||||
public ResultVo<?> del(String id){
|
||||
IService.delete(id);
|
||||
return ResultVo.success("删除字典明细数据成功");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 用户信息 批量删除
|
||||
* @param ids ID 数组
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "批量删除字典明细数据数据", notes = "批量删除字典明细数据数据")
|
||||
@Override
|
||||
public ResultVo<?> delAll(String[] ids){
|
||||
IService.deleteAll(ids);
|
||||
return ResultVo.success("批量删除字典明细数据成功");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 用户信息 Excel 导出
|
||||
* @param request request
|
||||
* @param response response
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "导出Excel", notes = "导出Excel")
|
||||
@Override
|
||||
public ResultVo<?> exportExcel(HttpServletRequest request, HttpServletResponse response) {
|
||||
QueryBuilder<SysUser> queryBuilder = new WebQueryBuilder<>(SysUser.class, request.getParameterMap());
|
||||
return super.excelExport(UserApi.TITLE, queryBuilder.build(), response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户信息 Excel 导入
|
||||
* @param request 文件流 request
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "导入Excel", notes = "导入Excel")
|
||||
@Override
|
||||
public ResultVo<?> excelImport(MultipartHttpServletRequest request) {
|
||||
return super.excelImport(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户信息 Excel 下载导入模版
|
||||
* @param response response
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "导出Excel模版", notes = "导出Excel模版")
|
||||
@Override
|
||||
public ResultVo<?> importTemplate(HttpServletResponse response) {
|
||||
return super.importTemplate(UserApi.TITLE, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 username 获得用户
|
||||
* @param username 用户名
|
||||
* @return ResultVo
|
||||
*/
|
||||
@ApiOperation(value = "根据 username 获得用户", notes = "根据 username 获得用户")
|
||||
@Override
|
||||
public ResultVo<UserModel> getUserByUsername(String username) {
|
||||
UserModel userModel = IService.queryByUserName(username);
|
||||
if(userModel != null){
|
||||
return ResultVo.success(userModel);
|
||||
}
|
||||
return ResultVo.error("没有该用户");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 userId 获得用户角色
|
||||
* @param userId 用户Id
|
||||
* @return ResultVo
|
||||
*/
|
||||
@Override
|
||||
public ResultVo<List<String>> getRolesByUserId(String userId) {
|
||||
List<String> roleCodeList = IService.getRoleCodeList(userId);
|
||||
return ResultVo.success(roleCodeList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 userId 获得用户权限
|
||||
* @param userId 用户Id
|
||||
* @return ResultVo
|
||||
*/
|
||||
@Override
|
||||
public ResultVo<List<String>> getAllPerms(String userId) {
|
||||
List<String> allPerms = IService.getAllPerms(userId);
|
||||
return ResultVo.success(allPerms);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据 userId 获得用户菜单
|
||||
* @param userId 用户Id
|
||||
* @return ResultVo
|
||||
*/
|
||||
@Override
|
||||
public ResultVo<List<MenuModel>> getMenuListByUserId(String userId) {
|
||||
List<MenuModel> menuModelList = IService.getMenuListByUserId(userId);
|
||||
return ResultVo.success(menuModelList);
|
||||
}
|
||||
}
|
@ -1,19 +1,14 @@
|
||||
package org.opsli;
|
||||
|
||||
import org.opsli.general.StartPrint;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
|
||||
|
||||
@SpringBootApplication()
|
||||
public class OpsliApplication {
|
||||
|
||||
public static void main(String[] args){
|
||||
ConfigurableApplicationContext application = SpringApplication.run(OpsliApplication.class, args);
|
||||
// 打印启动日志
|
||||
StartPrint.INSTANCE.print(application.getEnvironment());
|
||||
SpringApplication.run(OpsliApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue