├── .gitignore ├── LICENSE ├── README.md ├── pom.xml ├── sql ├── scaffold-data.sql └── scaffold.sql └── src ├── main ├── java │ └── com │ │ └── xkcoding │ │ └── scaffold │ │ ├── ScaffoldApplication.java │ │ ├── aspectj │ │ ├── LogAspect.java │ │ ├── annotation │ │ │ └── Log.java │ │ └── constant │ │ │ ├── ActionType.java │ │ │ └── OperateStatus.java │ │ ├── common │ │ ├── Api.java │ │ ├── BaseEnum.java │ │ ├── MyMapper.java │ │ ├── PageResponse.java │ │ ├── constant │ │ │ ├── ContentType.java │ │ │ ├── FileSuffix.java │ │ │ └── ScaffoldConst.java │ │ ├── property │ │ │ ├── CodeProperties.java │ │ │ ├── CommonProperties.java │ │ │ ├── ImageCodeProperties.java │ │ │ ├── ScaffoldProperties.java │ │ │ ├── ScaffoldSecurityProperties.java │ │ │ ├── ServerProperties.java │ │ │ └── SmsCodeProperties.java │ │ ├── status │ │ │ ├── DeleteStatus.java │ │ │ ├── LogStatus.java │ │ │ ├── MenuVisibleStatus.java │ │ │ ├── Status.java │ │ │ └── UserStatus.java │ │ └── type │ │ │ ├── CodeType.java │ │ │ └── MenuType.java │ │ ├── config │ │ ├── ModelMapperConfig.java │ │ └── security │ │ │ ├── SecurityConfig.java │ │ │ ├── code │ │ │ ├── CodeController.java │ │ │ ├── CodeFilter.java │ │ │ ├── CodeProcessorHolder.java │ │ │ ├── base │ │ │ │ ├── AbstractCodeProcessor.java │ │ │ │ ├── Code.java │ │ │ │ ├── CodeGenerator.java │ │ │ │ └── CodeProcessor.java │ │ │ ├── config │ │ │ │ ├── CodeBeanConfig.java │ │ │ │ └── ScaffoldSecurityCodeConfig.java │ │ │ └── image │ │ │ │ ├── ImageCode.java │ │ │ │ ├── ImageCodeGenerator.java │ │ │ │ └── ImageCodeProcessor.java │ │ │ ├── handler │ │ │ ├── ScaffoldAccessDecisionManager.java │ │ │ ├── ScaffoldAccessDeniedHandler.java │ │ │ ├── ScaffoldAuthenticationFailureHandler.java │ │ │ ├── ScaffoldAuthenticationSuccessHandler.java │ │ │ ├── ScaffoldDaoAuthenticationProvider.java │ │ │ ├── ScaffoldFilterInvocationSecurityMetadataSource.java │ │ │ └── ScaffoldLogoutSuccessHandler.java │ │ │ └── service │ │ │ └── UserDetailsServiceImpl.java │ │ ├── controller │ │ ├── AuthenticationController.java │ │ └── TestController.java │ │ ├── exception │ │ └── ScaffoldException.java │ │ ├── handler │ │ └── GlobalExceptionHandler.java │ │ ├── mapper │ │ ├── SysConfigMapper.java │ │ ├── SysDeptMapper.java │ │ ├── SysDictDataMapper.java │ │ ├── SysDictTypeMapper.java │ │ ├── SysLoginLogMapper.java │ │ ├── SysMenuMapper.java │ │ ├── SysOperationLogMapper.java │ │ ├── SysRoleMapper.java │ │ ├── SysRoleMenuMapper.java │ │ ├── SysUserMapper.java │ │ ├── SysUserRoleMapper.java │ │ ├── SysUserWorkMapper.java │ │ └── SysWorkMapper.java │ │ ├── model │ │ ├── SysConfig.java │ │ ├── SysDept.java │ │ ├── SysDictData.java │ │ ├── SysDictType.java │ │ ├── SysLoginLog.java │ │ ├── SysMenu.java │ │ ├── SysOperationLog.java │ │ ├── SysRole.java │ │ ├── SysRoleMenu.java │ │ ├── SysUser.java │ │ ├── SysUserRole.java │ │ ├── SysUserWork.java │ │ ├── SysWork.java │ │ └── dto │ │ │ ├── SysMenuDTO.java │ │ │ └── SysUserDTO.java │ │ ├── service │ │ ├── SysMenuService.java │ │ ├── SysOperationLogService.java │ │ ├── SysRoleService.java │ │ ├── SysUserService.java │ │ └── impl │ │ │ ├── SysMenuServiceImpl.java │ │ │ ├── SysOperationLogServiceImpl.java │ │ │ ├── SysRoleServiceImpl.java │ │ │ └── SysUserServiceImpl.java │ │ └── util │ │ ├── EnumUtil.java │ │ ├── Ip2AddressUtil.java │ │ ├── IpUtil.java │ │ ├── LoginLogUtil.java │ │ ├── SecurityUtil.java │ │ ├── ServletUtil.java │ │ └── SpringContextHolderUtil.java └── resources │ ├── application.yml │ ├── banner.txt │ ├── ip │ └── ip2region.db │ ├── logback-spring.xml │ └── mybatis │ ├── generator │ ├── datasource.properties │ └── generatorConfig.xml │ └── mapper │ ├── SysConfigMapper.xml │ ├── SysDeptMapper.xml │ ├── SysDictDataMapper.xml │ ├── SysDictTypeMapper.xml │ ├── SysLoginLogMapper.xml │ ├── SysMenuMapper.xml │ ├── SysOperationLogMapper.xml │ ├── SysRoleMapper.xml │ ├── SysRoleMenuMapper.xml │ ├── SysUserMapper.xml │ ├── SysUserRoleMapper.xml │ ├── SysUserWorkMapper.xml │ └── SysWorkMapper.xml └── test └── java └── com └── xkcoding └── scaffold ├── ScaffoldApplicationTests.java ├── ip └── Ip2AddressTest.java └── user └── PasswordEncoderTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ 26 | 27 | ### LOGS ### 28 | logs/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Yangkai.Shen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # scaffold 2 | ## 平台简介 3 | 4 | 平时开发管理平台项目,通常都会有用户管理,权限管理,日志管理等通用模块。虽然功能不多难度不大,但是开发起来也会消耗不少精力。 5 | 6 | 网上也有很多快速开发的脚手架项目,但是有些又夹杂了一些别的功能,显得不是那么纯粹,有些功能刚好,但是简单的功能又过度封装,使得像我这样的 **7流** 程序员看起来略有些困难。。。(PS:还不就是为了满足一下自己造轮子的装逼想法!) 7 | 8 | 取名:`scaffold`,翻译也是:`脚手架;给……搭脚手架;用支架支撑` 9 | 10 | ## 技术栈 11 | ### 后端技术栈 12 | 13 | 1. Spring Boot 2.0.3.RELEASE 14 | 2. Mybatis 15 | 3. 通用 Mapper 16 | 4. PageHelper 17 | 5. Spring Security 18 | 6. Quartz 19 | 7. Swagger 20 | 8. HikariCP 21 | 9. ...... 22 | 23 | > 用到别的再补充,暂时不知道脚手架后期会支持到什么程度,万一后面想写一个大而全的脚手架了呢,嘿嘿嘿~ 24 | 25 | ### 前端技术栈 26 | 27 | 暂时考虑会做两套,一套基于模板引擎,一套前后端分离。 28 | 29 | **模板引擎** 30 | 1. Beetl 引擎 31 | 2. Jquery 32 | 33 | **前后端分离** 34 | 1. Vue 全家桶,Vue / VueRouter / Vuex 35 | 2. axios 36 | 3. iView 37 | 4. iView-admin 38 | 39 | ## 内置功能(计划) 40 | 41 | 1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。 42 | 2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现。 43 | 3. 岗位管理:配置系统用户所属担任职务。 44 | 4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。 45 | 5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 46 | 6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。 47 | 7. 参数管理:对系统动态配置常用参数。 48 | 8. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 49 | 9. 登录日志:系统登录日志记录查询包含登录异常。 50 | 10. 在线用户:当前系统中活跃用户状态监控。 51 | 11. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。 52 | 12. 系统接口:根据业务代码自动生成相关的api接口文档。 53 | 54 | ## 演示 55 | ### 在线体验 56 | 57 | 开发 ing,别急嘛 58 | 59 | ### 演示图 60 | 61 | 占个位先 62 | 63 | ## 交流 64 | ### 交流群 65 | 66 | 还没开发,你咋啥都准备好了? 67 | 68 | ### 联系我 69 | 70 | - Email: 237497819@qq.com 71 | - QQ: 237497819 72 | 73 | ## License 74 | [MIT](http://opensource.org/licenses/MIT) 75 | 76 | Copyright (c) 2018 Yangkai.Shen 77 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/ScaffoldApplication.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import tk.mybatis.spring.annotation.MapperScan; 6 | 7 | /** 8 | *

9 | * 启动类 10 | *

11 | * 12 | * @package: com.xkcoding.scaffold 13 | * @description: 启动类 14 | * @author: yangkai.shen 15 | * @date: Created in 2018/7/27 下午2:36 16 | * @copyright: Copyright (c) 2018 17 | * @version: V1.0 18 | * @modified: yangkai.shen 19 | */ 20 | @SpringBootApplication 21 | @MapperScan(basePackages = {"com.xkcoding.scaffold.mapper"}) 22 | public class ScaffoldApplication { 23 | 24 | public static void main(String[] args) { 25 | SpringApplication.run(ScaffoldApplication.class, args); 26 | System.out.println("\n(♥◠‿◠)ノ゙ scaffold 启动成功 ლ(´ڡ`ლ)゙\n"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/aspectj/LogAspect.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.aspectj; 2 | 3 | import cn.hutool.core.util.ObjectUtil; 4 | import cn.hutool.core.util.StrUtil; 5 | import cn.hutool.json.JSONUtil; 6 | import com.xkcoding.scaffold.aspectj.annotation.Log; 7 | import com.xkcoding.scaffold.aspectj.constant.OperateStatus; 8 | import com.xkcoding.scaffold.mapper.SysDeptMapper; 9 | import com.xkcoding.scaffold.model.SysDept; 10 | import com.xkcoding.scaffold.model.SysOperationLog; 11 | import com.xkcoding.scaffold.model.dto.SysUserDTO; 12 | import com.xkcoding.scaffold.service.SysOperationLogService; 13 | import com.xkcoding.scaffold.util.Ip2AddressUtil; 14 | import com.xkcoding.scaffold.util.SecurityUtil; 15 | import com.xkcoding.scaffold.util.ServletUtil; 16 | import lombok.extern.slf4j.Slf4j; 17 | import org.aspectj.lang.JoinPoint; 18 | import org.aspectj.lang.Signature; 19 | import org.aspectj.lang.annotation.AfterReturning; 20 | import org.aspectj.lang.annotation.AfterThrowing; 21 | import org.aspectj.lang.annotation.Aspect; 22 | import org.aspectj.lang.annotation.Pointcut; 23 | import org.aspectj.lang.reflect.MethodSignature; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.scheduling.annotation.Async; 26 | import org.springframework.scheduling.annotation.EnableAsync; 27 | import org.springframework.stereotype.Component; 28 | 29 | import java.lang.reflect.Method; 30 | import java.util.Date; 31 | import java.util.Map; 32 | 33 | /** 34 | *

35 | * 操作日志记录处理切面 36 | *

37 | * 38 | * @package: com.xkcoding.scaffold.aspectj 39 | * @description: 操作日志记录处理切面 40 | * @author: yangkai.shen 41 | * @date: Created in 2018/8/6 下午2:06 42 | * @copyright: Copyright (c) 2018 43 | * @version: V1.0 44 | * @modified: yangkai.shen 45 | */ 46 | @Aspect 47 | @Component 48 | @EnableAsync 49 | @Slf4j 50 | public class LogAspect { 51 | @Autowired 52 | private SysOperationLogService sysOperationLogService; 53 | 54 | @Autowired 55 | private SysDeptMapper sysDeptMapper; 56 | 57 | /** 58 | * 切入点 59 | */ 60 | @Pointcut("@annotation(com.xkcoding.scaffold.aspectj.annotation.Log)") 61 | public void logPointCut() { 62 | 63 | } 64 | 65 | /** 66 | * 前置通知 用于拦截操作 67 | * 68 | * @param joinPoint 切入点 69 | */ 70 | @AfterReturning(pointcut = "logPointCut()") 71 | public void doBefore(JoinPoint joinPoint) { 72 | handleLog(joinPoint, null); 73 | } 74 | 75 | /** 76 | * 拦截异常操作 77 | * 78 | * @param joinPoint 切入点 79 | * @param e 异常 80 | */ 81 | @AfterThrowing(pointcut = "logPointCut()", throwing = "e") 82 | public void doAfter(JoinPoint joinPoint, Exception e) { 83 | handleLog(joinPoint, e); 84 | } 85 | 86 | /** 87 | * 记录处理日志信息 88 | * 89 | * @param joinPoint 切入点 90 | * @param e 异常 91 | */ 92 | @Async 93 | protected void handleLog(JoinPoint joinPoint, Exception e) { 94 | Log controllerLog = getAnnotationLog(joinPoint); 95 | 96 | // 如果没有 @Log,不记录操作日志 97 | if (ObjectUtil.isNull(controllerLog)) { 98 | return; 99 | } 100 | 101 | // 获取当前登录用户 102 | SysUserDTO currentUser = SecurityUtil.getCurrentUser(); 103 | 104 | // 构造操作日志对象 105 | SysOperationLog operationLog = new SysOperationLog(); 106 | operationLog.setStatus(OperateStatus.SUCCESS); 107 | 108 | // 获取登录用户 IP 109 | String ip = SecurityUtil.getIp(); 110 | operationLog.setOperationIp(ip); 111 | 112 | // 根据 IP 获取地址 113 | operationLog.setOperationLocation(Ip2AddressUtil.getAddressInLocal(ip)); 114 | // 设置请求地址 115 | operationLog.setOperationUrl(ServletUtil.getRequest().getRequestURI()); 116 | if (currentUser != null) { 117 | operationLog.setOperationName(currentUser.getUsername()); 118 | if (ObjectUtil.isNotNull(currentUser.getDeptId())) { 119 | SysDept sysDept = sysDeptMapper.selectByPrimaryKey(currentUser.getDeptId()); 120 | operationLog.setDeptName(sysDept.getDeptName()); 121 | } 122 | } 123 | 124 | // 如果存在异常,操作日志填充异常信息 125 | if (e != null) { 126 | operationLog.setStatus(OperateStatus.FAIL); 127 | operationLog.setErrorMsg(StrUtil.sub(e.getMessage(), 0, 2000)); 128 | } 129 | // 设置方法名称 130 | String className = joinPoint.getTarget().getClass().getName(); 131 | String methodName = joinPoint.getSignature().getName(); 132 | operationLog.setMethod(className + "." + methodName + "()"); 133 | // 处理设置注解上的参数 134 | getControllerMethodDescription(controllerLog, operationLog); 135 | // 设置操作时间 136 | operationLog.setOperationTime(new Date()); 137 | // 保存数据库 138 | sysOperationLogService.insert(operationLog); 139 | } 140 | 141 | /** 142 | * 获取注解中对方法的描述信息 用于Controller层注解 143 | * 144 | * @param controllerLog Controller 层 @Log 注解 145 | * @param operationLog 操作日志对象 146 | */ 147 | private void getControllerMethodDescription(Log controllerLog, SysOperationLog operationLog) { 148 | // 设置模块名 149 | operationLog.setTitle(controllerLog.title()); 150 | // 设置功能请求 151 | operationLog.setAction(controllerLog.action()); 152 | if (controllerLog.keepRequestData()) { 153 | setRequestData(operationLog); 154 | } 155 | 156 | } 157 | 158 | /** 159 | * 获取请求的参数,放到操作日志中 160 | * 161 | * @param operationLog 操作日志对象 162 | */ 163 | private void setRequestData(SysOperationLog operationLog) { 164 | Map map = ServletUtil.getRequest().getParameterMap(); 165 | String params = JSONUtil.toJsonStr(map); 166 | operationLog.setOperationParam(StrUtil.sub(params, 0, 255)); 167 | } 168 | 169 | /** 170 | * 是否存在 @Log,存在就获取 Log,不存在就返回 171 | * 172 | * @param joinPoint 切入点 173 | * @return Log 注解 174 | */ 175 | private Log getAnnotationLog(JoinPoint joinPoint) { 176 | Signature signature = joinPoint.getSignature(); 177 | MethodSignature methodSignature = (MethodSignature) signature; 178 | Method method = methodSignature.getMethod(); 179 | if (ObjectUtil.isNotNull(method)) { 180 | return method.getAnnotation(Log.class); 181 | } 182 | return null; 183 | } 184 | 185 | } 186 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/aspectj/annotation/Log.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.aspectj.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | *

7 | * 操作记录日志注解 8 | *

9 | * 10 | * @package: com.xkcoding.scaffold.aspectj.annotation 11 | * @description: 操作记录日志注解 12 | * @author: yangkai.shen 13 | * @date: Created in 2018/8/6 下午1:58 14 | * @copyright: Copyright (c) 2018 15 | * @version: V1.0 16 | * @modified: yangkai.shen 17 | */ 18 | @Target({ElementType.METHOD}) 19 | @Retention(RetentionPolicy.RUNTIME) 20 | @Documented 21 | public @interface Log { 22 | /** 23 | * 模块名 24 | */ 25 | String title() default ""; 26 | 27 | /** 28 | * 功能 29 | */ 30 | String action() default ""; 31 | 32 | /** 33 | * 是否保存请求参数 34 | */ 35 | boolean keepRequestData() default true; 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/aspectj/constant/ActionType.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.aspectj.constant; 2 | 3 | /** 4 | *

5 | * 操作类型 6 | *

7 | * 8 | * @package: com.xkcoding.scaffold.common.constant 9 | * @description: 操作类型 10 | * @author: yangkai.shen 11 | * @date: Created in 2018/8/6 下午6:43 12 | * @copyright: Copyright (c) 2018 13 | * @version: V1.0 14 | * @modified: yangkai.shen 15 | */ 16 | public class ActionType { 17 | /** 18 | * 其它 19 | */ 20 | public static final String OTHER = "其他"; 21 | 22 | /** 23 | * 新增 24 | */ 25 | public static final String INSERT = "新增"; 26 | 27 | /** 28 | * 修改 29 | */ 30 | public static final String UPDATE = "修改"; 31 | 32 | /** 33 | * 删除 34 | */ 35 | public static final String DELETE = "删除"; 36 | 37 | /** 38 | * 授权 39 | */ 40 | public static final String GRANT = "授权"; 41 | 42 | /** 43 | * 导出 44 | */ 45 | public static final String EXPORT = "导出"; 46 | 47 | /** 48 | * 导入 49 | */ 50 | public static final String IMPORT = "导入"; 51 | 52 | /** 53 | * 启用 54 | */ 55 | public static final String ENABLE = "启用"; 56 | 57 | /** 58 | * 禁用 59 | */ 60 | public static final String DISABLE = "禁用"; 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/aspectj/constant/OperateStatus.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.aspectj.constant; 2 | 3 | /** 4 | *

5 | * 操作状态 6 | *

7 | * 8 | * @package: com.xkcoding.scaffold.aspectj.constant 9 | * @description: 操作状态 10 | * @author: yangkai.shen 11 | * @date: Created in 2018/8/6 下午2:40 12 | * @copyright: Copyright (c) 2018 13 | * @version: V1.0 14 | * @modified: yangkai.shen 15 | */ 16 | public class OperateStatus { 17 | /** 18 | * 成功 19 | */ 20 | public static final Integer SUCCESS = 1; 21 | 22 | /** 23 | * 失败 24 | */ 25 | public static final Integer FAIL = 0; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/common/Api.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.common; 2 | 3 | import com.xkcoding.scaffold.common.status.Status; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | *

10 | * API 统一返回格式封装 11 | *

12 | * 13 | * @package: com.xkcoding.scaffold.common 14 | * @description: API 统一返回格式封装 15 | * @author: yangkai.shen 16 | * @date: Created in 2018/8/2 下午6:15 17 | * @copyright: Copyright (c) 2018 18 | * @version: V1.0 19 | * @modified: yangkai.shen 20 | */ 21 | @Data 22 | public class Api implements Serializable { 23 | 24 | private static final long serialVersionUID = 1672493411204459264L; 25 | 26 | /** 27 | * 返回码 28 | */ 29 | private Integer code; 30 | 31 | /** 32 | * 返回信息 33 | */ 34 | private String msg; 35 | 36 | /** 37 | * 返回数据 38 | */ 39 | private Object data; 40 | 41 | /** 42 | * 默认构造 43 | */ 44 | public Api() { 45 | this.code = Status.SUCCESS.getCode(); 46 | this.msg = Status.SUCCESS.getMsg(); 47 | } 48 | 49 | /** 50 | * 构造 API 返回对象 51 | * 52 | * @param code 返回码 53 | * @param msg 返回信息 54 | * @param data 数据 55 | */ 56 | public Api(Integer code, String msg, Object data) { 57 | this.code = code; 58 | this.msg = msg; 59 | this.data = data; 60 | } 61 | 62 | /** 63 | * 通用构造包含返回信息的 Api
64 | * 主要用于只包含返回信息,不包含数据时的返回 65 | * 66 | * @param code 状态码 67 | * @param msg 信息 68 | * @return Api 69 | */ 70 | public static Api of(int code, String msg, Object data) { 71 | return new Api(code, msg, data); 72 | } 73 | 74 | /** 75 | * 通用构造包含返回信息的 Api
76 | * 主要用于只包含返回信息,不包含数据时的返回 77 | * 78 | * @param code 状态码 79 | * @param msg 信息 80 | * @return Api 81 | */ 82 | public static Api ofMessage(int code, String msg) { 83 | return new Api(code, msg, null); 84 | } 85 | 86 | /** 87 | * 通用构造包含返回信息的 Api
88 | * 主要用于只包含返回信息,不包含数据时的返回 89 | * 90 | * @param msg 信息 91 | * @return Api 92 | */ 93 | public static Api ofMessage(String msg) { 94 | return new Api(Status.SUCCESS.getCode(), msg, null); 95 | } 96 | 97 | /** 98 | * 通用构造包含返回数据的 Api
99 | * 主要用于操作成功时的返回(不带数据) 100 | * 101 | * @return Api 102 | */ 103 | public static Api ofSuccess() { 104 | return new Api(Status.SUCCESS.getCode(), Status.SUCCESS.getMsg(), null); 105 | } 106 | 107 | /** 108 | * 通用构造包含返回数据的 Api
109 | * 主要用于操作成功时的返回 110 | * 111 | * @param data 操作成功时需要返回的数据 112 | * @return Api 113 | */ 114 | public static Api ofSuccess(Object data) { 115 | return new Api(Status.SUCCESS.getCode(), Status.SUCCESS.getMsg(), data); 116 | } 117 | 118 | /** 119 | * 通过 Status 构造 Api
120 | * 主要用于出现异常时的返回 121 | * 122 | * @param status {@link Status} 123 | * @return Api 124 | */ 125 | public static Api ofStatus(Status status) { 126 | return new Api(status.getCode(), status.getMsg(), null); 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/common/BaseEnum.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.common; 2 | 3 | /** 4 | *

5 | * 基础状态 6 | *

7 | * 8 | * @package: com.xkcoding.scaffold.common.status 9 | * @description: 基础状态 10 | * @author: yangkai.shen 11 | * @date: Created in 2018/8/8 上午10:27 12 | * @copyright: Copyright (c) 2018 13 | * @version: V1.0 14 | * @modified: yangkai.shen 15 | */ 16 | public interface BaseEnum { 17 | /** 18 | * 获取状态码 19 | * 20 | * @return 状态码 21 | */ 22 | Integer getCode(); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/common/MyMapper.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.common; 2 | 3 | import tk.mybatis.mapper.common.Mapper; 4 | import tk.mybatis.mapper.common.MySqlMapper; 5 | 6 | /** 7 | *

8 | * 通用 Mapper 9 | *

10 | * 11 | * @package: com.xkcoding.scaffold.common 12 | * @description: 通用 Mapper 13 | * @author: yangkai.shen 14 | * @date: Created in 2018/8/6 下午5:51 15 | * @copyright: Copyright (c) 2018 16 | * @version: V1.0 17 | * @modified: yangkai.shen 18 | */ 19 | public interface MyMapper extends Mapper, MySqlMapper { 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/common/PageResponse.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.common; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.io.Serializable; 8 | import java.util.List; 9 | 10 | /** 11 | *

12 | * 分页格式封装 13 | *

14 | * 15 | * @package: com.xkcoding.scaffold.common 16 | * @description: 分页格式封装 17 | * @author: yangkai.shen 18 | * @date: Created in 2018/8/2 下午7:52 19 | * @copyright: Copyright (c) 2018 20 | * @version: V1.0 21 | * @modified: yangkai.shen 22 | */ 23 | @Data 24 | @NoArgsConstructor 25 | @AllArgsConstructor 26 | public class PageResponse implements Serializable { 27 | 28 | private static final long serialVersionUID = 7829232095276966115L; 29 | 30 | /** 31 | * 数据总条数 32 | */ 33 | private Long total; 34 | 35 | /** 36 | * 数据列表 37 | */ 38 | private List list; 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/common/constant/ContentType.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.common.constant; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | *

7 | * 常用Content-Type类型枚举 8 | *

9 | * 10 | * @package: com.xkcoding.scaffold.common.constant 11 | * @description: 常用Content-Type类型枚举 12 | * @author: yangkai.shen 13 | * @date: Created in 2018/8/6 下午4:40 14 | * @copyright: Copyright (c) 2018 15 | * @version: V1.0 16 | * @modified: yangkai.shen 17 | */ 18 | @Getter 19 | public enum ContentType { 20 | 21 | /** 22 | * 标准表单编码,当action为get时候,浏览器用x-www-form-urlencoded的编码方式把form数据转换成一个字串(name1=value1&name2=value2…) 23 | */ 24 | FORM_URLENCODED("application/x-www-form-urlencoded"), 25 | 26 | /** 27 | * 文件上传编码,浏览器会把整个表单以控件为单位分割,并为每个部分加上Content-Disposition,并加上分割符(boundary) 28 | */ 29 | MULTIPART("multipart/form-data"), 30 | 31 | /** 32 | * Rest请求JSON编码 33 | */ 34 | JSON("application/json"), 35 | 36 | /** 37 | * Rest请求XML编码 38 | */ 39 | XML("application/xml"), 40 | 41 | /** 42 | * JS ajax 提交 43 | */ 44 | XML_HTTP_REQUEST("XMLHttpRequest"); 45 | 46 | private String value; 47 | 48 | ContentType(String value) { 49 | this.value = value; 50 | }} 51 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/common/constant/FileSuffix.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.common.constant; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | *

7 | * 常见文件后缀类型枚举 8 | *

9 | * 10 | * @package: com.xkcoding.scaffold.common.constant 11 | * @description: 常见文件后缀类型枚举 12 | * @author: yangkai.shen 13 | * @date: Created in 2018/8/6 下午4:45 14 | * @copyright: Copyright (c) 2018 15 | * @version: V1.0 16 | * @modified: yangkai.shen 17 | */ 18 | @Getter 19 | public enum FileSuffix { 20 | /** 21 | * JPEG (jpg) 22 | */ 23 | JPG(".jpg"), 24 | 25 | /** 26 | * PNG (png) 27 | */ 28 | PNG(".png"), 29 | 30 | /** 31 | * GIF (gif) 32 | */ 33 | GIF(".gif"), 34 | 35 | /** 36 | * TIFF (tif) 37 | */ 38 | TIFF(".tif"), 39 | 40 | /** 41 | * 位图(bmp) 42 | */ 43 | BMP(".bmp"), 44 | 45 | /** 46 | * CAD (dwg) 47 | */ 48 | CAD(".dwg"), 49 | 50 | /** 51 | * HTML (html) 52 | */ 53 | HTML(".html"), 54 | 55 | /** 56 | * HTM (htm) 57 | */ 58 | HTM(".htm"), 59 | 60 | /** 61 | * css 62 | */ 63 | CSS(".css"), 64 | 65 | /** 66 | * js 67 | */ 68 | JS(".js"), 69 | 70 | /** 71 | * json 72 | */ 73 | JSON(".json"), 74 | 75 | /** 76 | * Rich Text Format (rtf) 77 | */ 78 | RTF(".rtf"), 79 | 80 | /** 81 | * Photoshop (psd) 82 | */ 83 | PSD(".psd"), 84 | 85 | /** 86 | * Email [Outlook Express 6] (eml) 87 | */ 88 | EML(".eml"), 89 | 90 | /** 91 | * doc文件 92 | */ 93 | DOC(".doc"), 94 | 95 | /** 96 | * docx文件 97 | */ 98 | DOCX(".docx"), 99 | 100 | /** 101 | * Visio 绘图 102 | */ 103 | VSD(".vsd"), 104 | 105 | /** 106 | * MS Access (mdb) 107 | */ 108 | MDB(".mdb"), 109 | 110 | /** 111 | * Adobe Acrobat (pdf) 112 | */ 113 | PDF(".pdf"), 114 | 115 | /** 116 | * rmvb/rm相同 117 | */ 118 | RMVB(".rmvb"), 119 | 120 | /** 121 | * flv与f4v相同 122 | */ 123 | FLV(".flv"), 124 | 125 | /** 126 | * mp4 127 | */ 128 | MP4(".mp4"), 129 | 130 | /** 131 | * mp3 132 | */ 133 | MP3(".mp3"), 134 | 135 | /** 136 | * mpg 137 | */ 138 | MPG(".mpg"), 139 | 140 | /** 141 | * wmv与asf相同 142 | */ 143 | WMV(".wmv"), 144 | 145 | /** 146 | * Wave (wav) 147 | */ 148 | WAV(".wav"), 149 | 150 | /** 151 | * avi 152 | */ 153 | AVI(".avi"), 154 | 155 | /** 156 | * MIDI(mid) 157 | */ 158 | MID(".mid"), 159 | 160 | /** 161 | * WinRAR 162 | */ 163 | RAR(".rar"), 164 | 165 | /** 166 | * ini 167 | */ 168 | INI(".ini"), 169 | 170 | /** 171 | * jar 172 | */ 173 | JAR(".jar"), 174 | 175 | /** 176 | * xls文件 177 | */ 178 | XLS(".xls"), 179 | 180 | /** 181 | * xlsx文件 182 | */ 183 | XLSX(".xlsx"), 184 | 185 | /** 186 | * zip 压缩文件 187 | */ 188 | ZIP(".zip"), 189 | 190 | /** 191 | * 可执行文件 192 | */ 193 | EXE(".exe"), 194 | 195 | /** 196 | * jsp文件 197 | */ 198 | JSP(".jsp"), 199 | 200 | /** 201 | * MF文件 202 | */ 203 | MF(".mf"), 204 | 205 | /** 206 | * xml文件 207 | */ 208 | XML(".xml"), 209 | 210 | /** 211 | * sql文件 212 | */ 213 | SQL(".sql"), 214 | 215 | /** 216 | * java文件 217 | */ 218 | JAVA(".java"), 219 | 220 | /** 221 | * bat文件 222 | */ 223 | BAT(".bat"), 224 | 225 | /** 226 | * gz文件 227 | */ 228 | GZ(".gz"), 229 | 230 | /** 231 | * properties文件 232 | */ 233 | PROPERTIES(".properties"), 234 | 235 | /** 236 | * class文件 237 | */ 238 | CLASS(".class"), 239 | 240 | /** 241 | * chm文件 242 | */ 243 | CHM(".chm"), 244 | 245 | /** 246 | * mxp文件 247 | */ 248 | MXP(".mxp"), 249 | 250 | /** 251 | * WPS文字wps、表格et、演示dps都是一样的 252 | */ 253 | WPS(".wps"), 254 | 255 | /** 256 | * torrent文件 257 | */ 258 | TORRENT(".torrent"), 259 | 260 | /** 261 | * Quicktime(mov) 262 | */ 263 | MOV(".mov"), 264 | 265 | /** 266 | * WordPerfect (wpd) 267 | */ 268 | WPD(".wpd"), 269 | 270 | /** 271 | * Outlook Express (dbx) 272 | */ 273 | DBX(".dbx"), 274 | 275 | /** 276 | * Outlook (pst) 277 | */ 278 | PST(".pst"), 279 | 280 | /** 281 | * Quicken (qdf) 282 | */ 283 | QDF(".qdf"), 284 | 285 | /** 286 | * Windows Password (pwl) 287 | */ 288 | PWL(".pwl"), 289 | 290 | /** 291 | * Real Audio(ram) 292 | */ 293 | RAM(".ram"); 294 | 295 | private String value; 296 | 297 | FileSuffix(String value) { 298 | this.value = value; 299 | } 300 | 301 | } 302 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/common/constant/ScaffoldConst.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.common.constant; 2 | 3 | /** 4 | *

5 | * Scaffold 常量池 6 | *

7 | * 8 | * @package: com.xkcoding.scaffold.common.constant 9 | * @description: Scaffold 常量池 10 | * @author: yangkai.shen 11 | * @date: Created in 2018/8/17 上午10:05 12 | * @copyright: Copyright (c) 2018 13 | * @version: V1.0 14 | * @modified: yangkai.shen 15 | */ 16 | public interface ScaffoldConst { 17 | /** 18 | * 逗号 19 | */ 20 | String COMMA = ","; 21 | 22 | /** 23 | * 默认的处理验证码的url前缀 24 | */ 25 | String DEFAULT_VALIDATE_CODE_URL_PREFIX = "/code"; 26 | 27 | /** 28 | * 登录页面地址 29 | */ 30 | String AUTHENTICATION_LOGIN_PAGE = "/authentication/require"; 31 | 32 | /** 33 | * 默认的用户名密码登录请求处理url 34 | */ 35 | String DEFAULT_LOGIN_PROCESSING_URL_FORM = "/authentication/login"; 36 | 37 | /** 38 | * 验证图片验证码时,http请求中默认的携带图片验证码信息的参数的名称 39 | */ 40 | String DEFAULT_PARAMETER_NAME_CODE_IMAGE = "imageCode"; 41 | 42 | /** 43 | * 验证短信验证码时,http请求中默认的携带短信验证码信息的参数的名称 44 | */ 45 | String DEFAULT_PARAMETER_NAME_CODE_SMS = "smsCode"; 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/common/property/CodeProperties.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.common.property; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | *

7 | * 验证码配置 8 | *

9 | * 10 | * @package: com.xkcoding.scaffold.common.property 11 | * @description: 验证码配置 12 | * @author: yangkai.shen 13 | * @date: Created in 2018/8/18 上午11:11 14 | * @copyright: Copyright (c) 2018 15 | * @version: V1.0 16 | * @modified: yangkai.shen 17 | */ 18 | @Data 19 | public class CodeProperties { 20 | /** 21 | * 图片验证码配置 22 | */ 23 | private ImageCodeProperties image = new ImageCodeProperties(); 24 | 25 | /** 26 | * 短信验证码配置 27 | */ 28 | private SmsCodeProperties sms = new SmsCodeProperties(); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/common/property/CommonProperties.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.common.property; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | *

7 | * 通用配置 8 | *

9 | * 10 | * @package: com.xkcoding.scaffold.common.property 11 | * @description: 通用配置 12 | * @author: yangkai.shen 13 | * @date: Created in 2018/8/18 上午11:23 14 | * @copyright: Copyright (c) 2018 15 | * @version: V1.0 16 | * @modified: yangkai.shen 17 | */ 18 | @Data 19 | public class CommonProperties { 20 | /** 21 | * 应用名 22 | */ 23 | private String name; 24 | 25 | /** 26 | * 应用版本 27 | */ 28 | private String version; 29 | 30 | /** 31 | * 版权年份 32 | */ 33 | private String copyrightYear; 34 | 35 | /** 36 | * 开发者 37 | */ 38 | private String developer; 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/common/property/ImageCodeProperties.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.common.property; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | 6 | /** 7 | *

8 | * 图片验证码配置 9 | *

10 | * 11 | * @package: com.xkcoding.scaffold.common.property 12 | * @description: 图片验证码配置 13 | * @author: yangkai.shen 14 | * @date: Created in 2018/8/18 上午11:12 15 | * @copyright: Copyright (c) 2018 16 | * @version: V1.0 17 | * @modified: yangkai.shen 18 | */ 19 | @Data 20 | @EqualsAndHashCode(callSuper = true) 21 | public class ImageCodeProperties extends SmsCodeProperties { 22 | /** 23 | * 宽度 24 | */ 25 | private int width = 100; 26 | 27 | /** 28 | * 高度 29 | */ 30 | private int height = 40; 31 | 32 | /** 33 | * 默认长度为4位 34 | */ 35 | public ImageCodeProperties() { 36 | setLength(4); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/common/property/ScaffoldProperties.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.common.property; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | 6 | /** 7 | *

8 | * Scaffold配置类 9 | *

10 | * 11 | * @package: com.xkcoding.scaffold.common.property 12 | * @description: Scaffold配置类 13 | * @author: yangkai.shen 14 | * @date: Created in 2018/8/17 上午10:09 15 | * @copyright: Copyright (c) 2018 16 | * @version: V1.0 17 | * @modified: yangkai.shen 18 | */ 19 | @ConfigurationProperties(prefix = "scaffold") 20 | @Data 21 | public class ScaffoldProperties { 22 | /** 23 | * Common 配置 24 | */ 25 | private CommonProperties common = new CommonProperties(); 26 | 27 | /** 28 | * Security 配置 29 | */ 30 | private ScaffoldSecurityProperties security = new ScaffoldSecurityProperties(); 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/common/property/ScaffoldSecurityProperties.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.common.property; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | *

7 | * Security 配置 8 | *

9 | * 10 | * @package: com.xkcoding.scaffold.common.property 11 | * @description: Security 配置 12 | * @author: yangkai.shen 13 | * @date: Created in 2018/8/18 上午11:21 14 | * @copyright: Copyright (c) 2018 15 | * @version: V1.0 16 | * @modified: yangkai.shen 17 | */ 18 | @Data 19 | public class ScaffoldSecurityProperties { 20 | /** 21 | * 验证码配置 22 | */ 23 | private CodeProperties code = new CodeProperties(); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/common/property/ServerProperties.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.common.property; 2 | 3 | import lombok.Data; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | /** 8 | *

9 | * 服务器配置 10 | *

11 | * 12 | * @package: com.xkcoding.scaffold.common.property 13 | * @description: 服务器配置 14 | * @author: yangkai.shen 15 | * @date: Created in 2018/8/18 下午10:18 16 | * @copyright: Copyright (c) 2018 17 | * @version: V1.0 18 | * @modified: yangkai.shen 19 | */ 20 | @Configuration 21 | @Data 22 | public class ServerProperties { 23 | /** 24 | * 上下文路径 25 | */ 26 | @Value("${server.servlet.context-path:/}") 27 | private String contextPath; 28 | 29 | /** 30 | * 端口号 31 | */ 32 | @Value("${server.port:8080}") 33 | private String port; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/common/property/SmsCodeProperties.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.common.property; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | *

7 | * 短信验证码配置 8 | *

9 | * 10 | * @package: com.xkcoding.scaffold.common.property 11 | * @description: 短信验证码配置 12 | * @author: yangkai.shen 13 | * @date: Created in 2018/8/18 上午11:13 14 | * @copyright: Copyright (c) 2018 15 | * @version: V1.0 16 | * @modified: yangkai.shen 17 | */ 18 | @Data 19 | public class SmsCodeProperties { 20 | /** 21 | * 长度,默认长度为6位 22 | */ 23 | private int length = 6; 24 | 25 | /** 26 | * 过期时间,默认过期时间 60s 27 | */ 28 | private int expireIn = 60; 29 | 30 | /** 31 | * url 32 | */ 33 | private String url; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/common/status/DeleteStatus.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.common.status; 2 | 3 | import com.xkcoding.scaffold.common.BaseEnum; 4 | import lombok.Getter; 5 | 6 | /** 7 | *

8 | * 逻辑删除状态枚举 9 | *

10 | * 11 | * @package: com.xkcoding.scaffold.common.status 12 | * @description: 逻辑删除状态枚举 13 | * @author: yangkai.shen 14 | * @date: Created in 2018/8/8 上午10:42 15 | * @copyright: Copyright (c) 2018 16 | * @version: V1.0 17 | * @modified: yangkai.shen 18 | */ 19 | @Getter 20 | public enum DeleteStatus implements BaseEnum { 21 | /** 22 | * 已删除 23 | */ 24 | DELETED(1, "已删除"), 25 | 26 | /** 27 | * 未删除 28 | */ 29 | NOT_DELETED(0, "未删除"); 30 | 31 | private Integer code; 32 | private String msg; 33 | 34 | DeleteStatus(Integer code, String msg) { 35 | this.code = code; 36 | this.msg = msg; 37 | }} 38 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/common/status/LogStatus.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.common.status; 2 | 3 | import com.xkcoding.scaffold.common.BaseEnum; 4 | import lombok.Getter; 5 | 6 | /** 7 | *

8 | * 日志状态枚举 9 | *

10 | * 11 | * @package: com.xkcoding.scaffold.common.status 12 | * @description: 日志状态枚举 13 | * @author: yangkai.shen 14 | * @date: Created in 2018/8/8 上午10:26 15 | * @copyright: Copyright (c) 2018 16 | * @version: V1.0 17 | * @modified: yangkai.shen 18 | */ 19 | @Getter 20 | public enum LogStatus implements BaseEnum { 21 | /** 22 | * 成功 23 | */ 24 | SUCCESS(1, "成功"), 25 | 26 | /** 27 | * 失败 28 | */ 29 | ERROR(0, "失败"); 30 | 31 | private Integer code; 32 | private String msg; 33 | 34 | LogStatus(Integer code, String msg) { 35 | this.code = code; 36 | this.msg = msg; 37 | }} 38 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/common/status/MenuVisibleStatus.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.common.status; 2 | 3 | import com.xkcoding.scaffold.common.BaseEnum; 4 | import lombok.Getter; 5 | 6 | /** 7 | *

8 | * 菜单显示状态枚举 9 | *

10 | * 11 | * @package: com.xkcoding.scaffold.common.status 12 | * @description: 菜单显示状态枚举 13 | * @author: yangkai.shen 14 | * @date: Created in 2018/8/8 下午9:56 15 | * @copyright: Copyright (c) 2018 16 | * @version: V1.0 17 | * @modified: yangkai.shen 18 | */ 19 | @Getter 20 | public enum MenuVisibleStatus implements BaseEnum { 21 | /** 22 | * 隐藏 23 | */ 24 | HIDE(0, "隐藏"), 25 | 26 | /** 27 | * 显示 28 | */ 29 | SHOW(1, "显示"); 30 | 31 | private Integer code; 32 | private String msg; 33 | 34 | MenuVisibleStatus(Integer code, String msg) { 35 | this.code = code; 36 | this.msg = msg; 37 | }} 38 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/common/status/Status.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.common.status; 2 | 3 | import com.xkcoding.scaffold.common.BaseEnum; 4 | import lombok.Getter; 5 | 6 | /** 7 | *

8 | * 状态码枚举 9 | *

10 | * 11 | * @package: com.xkcoding.scaffold.common 12 | * @description: 状态码枚举 13 | * @author: yangkai.shen 14 | * @date: Created in 2018/8/2 下午7:49 15 | * @copyright: Copyright (c) 2018 16 | * @version: V1.0 17 | * @modified: yangkai.shen 18 | */ 19 | @Getter 20 | public enum Status implements BaseEnum { 21 | /** 22 | * 成功 23 | */ 24 | SUCCESS(200, "成功"), 25 | 26 | /** 27 | * 请求错误 28 | */ 29 | BAD_REQUEST(400, "请求错误"), 30 | 31 | /** 32 | * 尚未登录 33 | */ 34 | UNAUTHORIZED(401, "尚未登录"), 35 | 36 | /** 37 | * 权限不够 38 | */ 39 | FORBIDDEN(403, "权限不够"), 40 | 41 | /** 42 | * 请求不存在 43 | */ 44 | REQUEST_NOT_FOUND(404, "请求不存在"), 45 | 46 | /** 47 | * 服务器内部错误 48 | */ 49 | INTERNAL_SERVER_ERROR(500, "服务器内部错误"), 50 | 51 | /** 52 | * 用户名或密码错误 53 | */ 54 | USERNAME_OR_PASSWORD_ERROR(50000, "用户名或密码错误"), 55 | 56 | /** 57 | * 用户不存在 58 | */ 59 | USER_NOT_EXIST(50001, "账号不存在"), 60 | 61 | /** 62 | * 用户已被禁用 63 | */ 64 | USER_DISABLE(50002, "账号已被禁用"), 65 | 66 | /** 67 | * 账号已删除 68 | */ 69 | USER_DELETED(50003, "账号已删除"), 70 | 71 | /** 72 | * 验证码错误 73 | */ 74 | VERIFY_CODE_ERROR(50004, "验证码错误"), 75 | 76 | /** 77 | * 登录成功 78 | */ 79 | LOGIN_SUCCESS(50005, "登录成功"), 80 | 81 | /** 82 | * 退出成功 83 | */ 84 | LOGOUT_SUCCESS(50006, "退出成功"), 85 | 86 | /** 87 | * 验证码异常 88 | */ 89 | CODE_ERROR(50007, "验证码异常"), 90 | 91 | /** 92 | * 获取验证码的值失败 93 | */ 94 | CODE_GET_ERROR(50008, "获取验证码的值失败"), 95 | 96 | /** 97 | * 验证码的值不能为空 98 | */ 99 | CODE_VALUE_NOT_NULL(50009, "验证码的值不能为空"), 100 | 101 | /** 102 | * 验证码不存在 103 | */ 104 | CODE_NOT_FOUND(50010, "验证码不存在"), 105 | 106 | /** 107 | * 验证码已过期 108 | */ 109 | CODE_IS_EXPIRED(50011, "验证码已过期"), 110 | 111 | /** 112 | * 验证码不匹配 113 | */ 114 | CODE_NOT_MATCH(50012, "验证码不匹配"), 115 | 116 | /** 117 | * 验证码发送异常 118 | */ 119 | CODE_SEND_ERROR(50012, "验证码发送异常"); 120 | 121 | private Integer code; 122 | private String msg; 123 | 124 | Status(Integer code, String msg) { 125 | this.code = code; 126 | this.msg = msg; 127 | }} 128 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/common/status/UserStatus.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.common.status; 2 | 3 | import com.xkcoding.scaffold.common.BaseEnum; 4 | import lombok.Getter; 5 | 6 | /** 7 | *

8 | * 用户状态枚举 9 | *

10 | * 11 | * @package: com.xkcoding.scaffold.common.status 12 | * @description: 用户状态枚举 13 | * @author: yangkai.shen 14 | * @date: Created in 2018/8/8 上午10:26 15 | * @copyright: Copyright (c) 2018 16 | * @version: V1.0 17 | * @modified: yangkai.shen 18 | */ 19 | @Getter 20 | public enum UserStatus implements BaseEnum { 21 | /** 22 | * 启用 23 | */ 24 | ENABLE(1, "启用"), 25 | 26 | /** 27 | * 禁用 28 | */ 29 | DISABLE(0, "禁用"); 30 | 31 | private Integer code; 32 | private String msg; 33 | 34 | UserStatus(Integer code, String msg) { 35 | this.code = code; 36 | this.msg = msg; 37 | }} 38 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/common/type/CodeType.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.common.type; 2 | 3 | import com.xkcoding.scaffold.common.constant.ScaffoldConst; 4 | 5 | /** 6 | *

7 | * 验证码类型 8 | *

9 | * 10 | * @package: com.xkcoding.scaffold.common.type 11 | * @description: 验证码类型 12 | * @author: yangkai.shen 13 | * @date: Created in 2018/8/18 上午11:44 14 | * @copyright: Copyright (c) 2018 15 | * @version: V1.0 16 | * @modified: yangkai.shen 17 | */ 18 | public enum CodeType { 19 | /** 20 | * 短信验证码 21 | */ 22 | SMS { 23 | @Override 24 | public String getParamNameOnValidate() { 25 | return ScaffoldConst.DEFAULT_PARAMETER_NAME_CODE_SMS; 26 | } 27 | }, 28 | /** 29 | * 图片验证码 30 | */ 31 | IMAGE { 32 | @Override 33 | public String getParamNameOnValidate() { 34 | return ScaffoldConst.DEFAULT_PARAMETER_NAME_CODE_IMAGE; 35 | } 36 | }; 37 | 38 | /** 39 | * 校验时从请求中获取的参数的名字 40 | * 41 | * @return 参数名 42 | */ 43 | public abstract String getParamNameOnValidate();} 44 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/common/type/MenuType.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.common.type; 2 | 3 | import com.xkcoding.scaffold.common.BaseEnum; 4 | import lombok.Getter; 5 | 6 | /** 7 | *

8 | * 菜单类型枚举 9 | *

10 | * 11 | * @package: com.xkcoding.scaffold.common.status 12 | * @description: 菜单类型枚举 13 | * @author: yangkai.shen 14 | * @date: Created in 2018/8/8 下午9:56 15 | * @copyright: Copyright (c) 2018 16 | * @version: V1.0 17 | * @modified: yangkai.shen 18 | */ 19 | @Getter 20 | public enum MenuType implements BaseEnum { 21 | /** 22 | * 目录 23 | */ 24 | directory(0, "目录"), 25 | 26 | /** 27 | * 菜单 28 | */ 29 | menu(1, "菜单"), 30 | 31 | /** 32 | * 按钮 33 | */ 34 | button(2, "按钮"); 35 | 36 | private Integer code; 37 | private String msg; 38 | 39 | MenuType(Integer code, String msg) { 40 | this.code = code; 41 | this.msg = msg; 42 | }} 43 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/ModelMapperConfig.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config; 2 | 3 | import org.modelmapper.ModelMapper; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | /** 8 | *

9 | * ModelMapper 配置类 10 | *

11 | * 12 | * @package: com.xkcoding.scaffold.config 13 | * @description: ModelMapper 配置类 14 | * @author: yangkai.shen 15 | * @date: Created in 2018/8/8 下午4:28 16 | * @copyright: Copyright (c) 2018 17 | * @version: V1.0 18 | * @modified: yangkai.shen 19 | */ 20 | @Configuration 21 | public class ModelMapperConfig { 22 | @Bean 23 | public ModelMapper modelMapper() { 24 | return new ModelMapper(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/security/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config.security; 2 | 3 | import com.xkcoding.scaffold.common.constant.ScaffoldConst; 4 | import com.xkcoding.scaffold.common.property.ScaffoldProperties; 5 | import com.xkcoding.scaffold.config.security.code.config.ScaffoldSecurityCodeConfig; 6 | import com.xkcoding.scaffold.config.security.handler.*; 7 | import com.xkcoding.scaffold.config.security.service.UserDetailsServiceImpl; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | import org.springframework.security.config.annotation.ObjectPostProcessor; 13 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 14 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 15 | import org.springframework.security.config.annotation.web.builders.WebSecurity; 16 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 17 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 18 | import org.springframework.security.core.session.SessionRegistry; 19 | import org.springframework.security.core.session.SessionRegistryImpl; 20 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 21 | import org.springframework.security.crypto.password.PasswordEncoder; 22 | import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; 23 | 24 | /** 25 | *

26 | * Spring Security 配置类 27 | *

28 | * 29 | * @package: com.xkcoding.scaffold.config 30 | * @description: Spring Security 配置类 31 | * @author: yangkai.shen 32 | * @date: Created in 2018/8/7 下午6:36 33 | * @copyright: Copyright (c) 2018 34 | * @version: V1.0 35 | * @modified: yangkai.shen 36 | */ 37 | @Configuration 38 | @EnableConfigurationProperties(ScaffoldProperties.class) 39 | @EnableWebSecurity 40 | public class SecurityConfig extends WebSecurityConfigurerAdapter { 41 | @Autowired 42 | private ScaffoldAuthenticationSuccessHandler successHandler; 43 | 44 | @Autowired 45 | private ScaffoldAuthenticationFailureHandler failureHandler; 46 | 47 | @Autowired 48 | private ScaffoldAccessDeniedHandler accessDeniedHandler; 49 | 50 | @Autowired 51 | private ScaffoldLogoutSuccessHandler logoutSuccessHandler; 52 | 53 | @Autowired 54 | private ScaffoldAccessDecisionManager accessDecisionManager; 55 | 56 | @Autowired 57 | private ScaffoldFilterInvocationSecurityMetadataSource securityMetadataSource; 58 | 59 | @Autowired 60 | private UserDetailsServiceImpl userDetailsService; 61 | 62 | @Autowired 63 | private ScaffoldSecurityCodeConfig scaffoldSecurityCodeConfig; 64 | 65 | /** 66 | * 构造一个 BCryptPasswordEncoder,放入 Spring 容器 67 | * 68 | * @return {@link BCryptPasswordEncoder} 69 | */ 70 | @Bean 71 | public PasswordEncoder passwordEncoder() { 72 | return new BCryptPasswordEncoder(); 73 | } 74 | 75 | /** 76 | * 自定义数据库账号认证 77 | * 78 | * @return {@link ScaffoldDaoAuthenticationProvider} 79 | */ 80 | @Bean 81 | public ScaffoldDaoAuthenticationProvider scaffoldDaoAuthenticationProvider() { 82 | ScaffoldDaoAuthenticationProvider scaffoldDaoAuthenticationProvider = new ScaffoldDaoAuthenticationProvider(); 83 | scaffoldDaoAuthenticationProvider.setHideUserNotFoundExceptions(false); 84 | scaffoldDaoAuthenticationProvider.setUserDetailsService(userDetailsService); 85 | scaffoldDaoAuthenticationProvider.setPasswordEncoder(passwordEncoder()); 86 | return scaffoldDaoAuthenticationProvider; 87 | } 88 | 89 | /** 90 | * 启用自定义认证器 91 | * 92 | * @param auth 认证管理器 93 | */ 94 | @Override 95 | protected void configure(AuthenticationManagerBuilder auth) { 96 | auth.authenticationProvider(scaffoldDaoAuthenticationProvider()); 97 | } 98 | 99 | @Override 100 | public void configure(WebSecurity web) { 101 | // 忽略指定资源 102 | web.ignoring() 103 | .antMatchers(ScaffoldConst.AUTHENTICATION_LOGIN_PAGE, ScaffoldConst.DEFAULT_VALIDATE_CODE_URL_PREFIX + "/*"); 104 | } 105 | 106 | /** 107 | * 自定义 Spring Security 配置 108 | * 109 | * @param http http 配置 110 | * @throws Exception 异常 111 | */ 112 | @Override 113 | protected void configure(HttpSecurity http) throws Exception { 114 | // 验证码配置 115 | http.apply(scaffoldSecurityCodeConfig); 116 | 117 | // 允许iframe 嵌套 118 | http.headers().frameOptions().disable(); 119 | 120 | // 配置 登录成功、登录失败、退出登录 处理器 121 | http.formLogin() 122 | .loginPage(ScaffoldConst.AUTHENTICATION_LOGIN_PAGE) 123 | .loginProcessingUrl(ScaffoldConst.DEFAULT_LOGIN_PROCESSING_URL_FORM) 124 | .successHandler(successHandler) 125 | .failureHandler(failureHandler) 126 | .and() 127 | .logout() 128 | .logoutUrl("/logout") 129 | .logoutSuccessHandler(logoutSuccessHandler) 130 | .deleteCookies("JSESSIONID") 131 | .permitAll(); 132 | 133 | // 一个自定义的filter,必须包含 authenticationManager,accessDecisionManager,securityMetadataSource三个属性, 134 | // 我们的所有控制将在这三个类中实现,解释详见具体配置 135 | http.authorizeRequests().withObjectPostProcessor(new ObjectPostProcessor() { 136 | @Override 137 | public O postProcess(O object) { 138 | object.setSecurityMetadataSource(securityMetadataSource); 139 | object.setAccessDecisionManager(accessDecisionManager); 140 | return object; 141 | } 142 | }); 143 | 144 | // 关闭 csrf 145 | http.csrf().disable(); 146 | 147 | // 拒绝访问 处理器 148 | http.exceptionHandling().accessDeniedHandler(accessDeniedHandler); 149 | 150 | // session管理 151 | http.sessionManagement().maximumSessions(1).sessionRegistry(getSessionRegistry()); 152 | 153 | } 154 | 155 | 156 | @Bean 157 | public SessionRegistry getSessionRegistry() { 158 | return new SessionRegistryImpl(); 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/security/code/CodeController.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config.security.code; 2 | 3 | import com.xkcoding.scaffold.exception.ScaffoldException; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.social.connect.web.HttpSessionSessionStrategy; 7 | import org.springframework.social.connect.web.SessionStrategy; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.PathVariable; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | import org.springframework.web.context.request.ServletWebRequest; 13 | 14 | import javax.servlet.http.HttpServletRequest; 15 | import javax.servlet.http.HttpServletResponse; 16 | 17 | /** 18 | *

19 | * 验证码 Controller 20 | *

21 | * 22 | * @package: com.xkcoding.scaffold.config.security.code 23 | * @description: 验证码 Controller 24 | * @author: yangkai.shen 25 | * @date: Created in 2018/8/13 上午10:42 26 | * @copyright: Copyright (c) 2018 27 | * @version: V1.0 28 | * @modified: yangkai.shen 29 | */ 30 | @RestController 31 | @RequestMapping("/code") 32 | @Slf4j 33 | public class CodeController { 34 | @Autowired 35 | private CodeProcessorHolder codeProcessorHolder; 36 | 37 | @GetMapping("/{type}") 38 | public void createImageCode(HttpServletRequest request, HttpServletResponse response, @PathVariable String type) throws ScaffoldException { 39 | codeProcessorHolder.findCodeProcessor(type).create(new ServletWebRequest(request, response)); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/security/code/CodeFilter.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config.security.code; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import com.google.common.collect.Maps; 5 | import com.xkcoding.scaffold.common.constant.ScaffoldConst; 6 | import com.xkcoding.scaffold.common.property.ScaffoldProperties; 7 | import com.xkcoding.scaffold.common.property.ServerProperties; 8 | import com.xkcoding.scaffold.common.type.CodeType; 9 | import com.xkcoding.scaffold.config.security.handler.ScaffoldAuthenticationFailureHandler; 10 | import com.xkcoding.scaffold.exception.ScaffoldException; 11 | import lombok.extern.slf4j.Slf4j; 12 | import org.springframework.beans.factory.InitializingBean; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.core.env.Environment; 15 | import org.springframework.http.HttpMethod; 16 | import org.springframework.security.authentication.BadCredentialsException; 17 | import org.springframework.stereotype.Component; 18 | import org.springframework.util.AntPathMatcher; 19 | import org.springframework.web.context.request.ServletWebRequest; 20 | import org.springframework.web.filter.OncePerRequestFilter; 21 | 22 | import javax.servlet.FilterChain; 23 | import javax.servlet.ServletException; 24 | import javax.servlet.http.HttpServletRequest; 25 | import javax.servlet.http.HttpServletResponse; 26 | import java.io.IOException; 27 | import java.util.Map; 28 | import java.util.Set; 29 | 30 | /** 31 | *

32 | * 验证码拦截器 33 | *

34 | * 35 | * @package: com.xkcoding.scaffold.config.security.code 36 | * @description: 验证码拦截器 37 | * @author: yangkai.shen 38 | * @date: Created in 2018/8/18 下午9:29 39 | * @copyright: Copyright (c) 2018 40 | * @version: V1.0 41 | * @modified: yangkai.shen 42 | */ 43 | @Component("codeFilter") 44 | @Slf4j 45 | public class CodeFilter extends OncePerRequestFilter implements InitializingBean { 46 | 47 | /** 48 | * 验证码校验失败处理器 49 | */ 50 | @Autowired 51 | private ScaffoldAuthenticationFailureHandler scaffoldAuthenticationFailureHandler; 52 | 53 | /** 54 | * 系统中的验证码处理器 55 | */ 56 | @Autowired 57 | private CodeProcessorHolder codeProcessorHolder; 58 | 59 | /** 60 | * 系统配置信息 61 | */ 62 | @Autowired 63 | private ScaffoldProperties scaffoldProperties; 64 | 65 | /** 66 | * 服务器配置 67 | */ 68 | @Autowired 69 | private ServerProperties serverProperties; 70 | 71 | @Autowired 72 | private Environment env; 73 | 74 | /** 75 | * 存放所有需要校验验证码的url 76 | */ 77 | private Map urlMap = Maps.newHashMap(); 78 | 79 | /** 80 | * 验证请求url与配置的url是否匹配的工具类 81 | */ 82 | private AntPathMatcher pathMatcher = new AntPathMatcher(); 83 | 84 | /** 85 | * 配置项设置完毕,初始化要拦截的url配置信息 86 | */ 87 | @Override 88 | public void afterPropertiesSet() throws ServletException { 89 | super.afterPropertiesSet(); 90 | 91 | urlMap.put(adjustUrl(serverProperties.getContextPath() + ScaffoldConst.DEFAULT_LOGIN_PROCESSING_URL_FORM), CodeType.IMAGE); 92 | addUrlToMap(scaffoldProperties.getSecurity().getCode().getImage().getUrl(), CodeType.IMAGE); 93 | 94 | } 95 | 96 | /** 97 | * 将系统中配置的需要校验验证码的URL根据校验的类型放入map 98 | * 99 | * @param urlString url 100 | * @param type 验证码类型 101 | */ 102 | protected void addUrlToMap(String urlString, CodeType type) { 103 | if (StrUtil.isNotEmpty(urlString)) { 104 | String[] urls = StrUtil.split(urlString, ","); 105 | for (String url : urls) { 106 | urlMap.put(adjustUrl(serverProperties.getContextPath() + url), type); 107 | } 108 | } 109 | } 110 | 111 | /** 112 | * 调整 URL,比如:
113 | * /scaffold/user -> /scaffold/user
114 | * //user -> /user 115 | * 116 | * @param url 原先字符串 117 | * @return 118 | */ 119 | private String adjustUrl(String url) { 120 | return StrUtil.replace(url, "//", "/"); 121 | } 122 | 123 | @Override 124 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 125 | CodeType type = getCodeType(request); 126 | if (type != null) { 127 | log.info("校验请求(" + request.getRequestURI() + ")中的验证码,验证码类型" + type); 128 | try { 129 | codeProcessorHolder.findCodeProcessor(type).validate(new ServletWebRequest(request, response)); 130 | log.info("验证码校验通过"); 131 | } catch (ScaffoldException exception) { 132 | scaffoldAuthenticationFailureHandler.onAuthenticationFailure(request, response, new BadCredentialsException(exception 133 | .getCode() + "")); 134 | return; 135 | } 136 | } 137 | 138 | filterChain.doFilter(request, response); 139 | } 140 | 141 | /** 142 | * 获取校验码的类型,如果当前请求不需要校验,则返回null 143 | * 144 | * @param request HttpServletRequest 145 | * @return 验证码类型 146 | */ 147 | private CodeType getCodeType(HttpServletRequest request) { 148 | CodeType result = null; 149 | if (!StrUtil.equalsIgnoreCase(request.getMethod(), HttpMethod.GET.name())) { 150 | Set urls = urlMap.keySet(); 151 | for (String url : urls) { 152 | if (pathMatcher.match(request.getRequestURI(), url)) { 153 | result = urlMap.get(url); 154 | } 155 | } 156 | } 157 | return result; 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/security/code/CodeProcessorHolder.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config.security.code; 2 | 3 | import com.xkcoding.scaffold.common.status.Status; 4 | import com.xkcoding.scaffold.common.type.CodeType; 5 | import com.xkcoding.scaffold.config.security.code.base.CodeProcessor; 6 | import com.xkcoding.scaffold.exception.ScaffoldException; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.util.Map; 11 | 12 | /** 13 | *

14 | * 验证码处理器持有者 15 | *

16 | * 17 | * @package: com.xkcoding.scaffold.config.security.code 18 | * @description: 验证码处理器持有者 19 | * @author: yangkai.shen 20 | * @date: Created in 2018/8/18 下午12:11 21 | * @copyright: Copyright (c) 2018 22 | * @version: V1.0 23 | * @modified: yangkai.shen 24 | */ 25 | @Component 26 | public class CodeProcessorHolder { 27 | @Autowired 28 | private Map codeProcessors; 29 | 30 | public CodeProcessor findCodeProcessor(CodeType type) throws ScaffoldException { 31 | return findCodeProcessor(type.toString().toLowerCase()); 32 | } 33 | 34 | public CodeProcessor findCodeProcessor(String type) throws ScaffoldException { 35 | String name = type.toLowerCase() + CodeProcessor.class.getSimpleName(); 36 | CodeProcessor processor = codeProcessors.get(name); 37 | if (processor == null) { 38 | throw new ScaffoldException(Status.INTERNAL_SERVER_ERROR.getCode(), "验证码生成器" + name + "不存在"); 39 | } 40 | return processor; 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/security/code/base/AbstractCodeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config.security.code.base; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import com.xkcoding.scaffold.common.status.Status; 5 | import com.xkcoding.scaffold.common.type.CodeType; 6 | import com.xkcoding.scaffold.exception.ScaffoldException; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.social.connect.web.HttpSessionSessionStrategy; 9 | import org.springframework.social.connect.web.SessionStrategy; 10 | import org.springframework.web.bind.ServletRequestBindingException; 11 | import org.springframework.web.bind.ServletRequestUtils; 12 | import org.springframework.web.context.request.ServletWebRequest; 13 | 14 | import java.util.Map; 15 | 16 | /** 17 | *

18 | * 抽象验证码处理接口 19 | *

20 | * 21 | * @package: com.xkcoding.scaffold.config.security.code.base 22 | * @description: 抽象验证码处理接口 23 | * @author: yangkai.shen 24 | * @date: Created in 2018/8/18 上午11:39 25 | * @copyright: Copyright (c) 2018 26 | * @version: V1.0 27 | * @modified: yangkai.shen 28 | */ 29 | public abstract class AbstractCodeProcessor implements CodeProcessor { 30 | /** 31 | * 操作session的工具类 32 | */ 33 | private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy(); 34 | 35 | /** 36 | * 收集系统中所有的 {@link CodeGenerator} 接口的实现。 37 | */ 38 | @Autowired 39 | private Map codeGenerators; 40 | 41 | /** 42 | * 创建校验码 43 | * 44 | * @param request {@link ServletWebRequest} 这个类同时封装了request {@link javax.servlet.http.HttpServletRequest} 和 response {@link javax.servlet.http.HttpServletResponse} 45 | */ 46 | @Override 47 | public void create(ServletWebRequest request) throws ScaffoldException { 48 | C validateCode = generate(request); 49 | save(request, validateCode); 50 | send(request, validateCode); 51 | } 52 | 53 | /** 54 | * 生成验证码 55 | * 56 | * @param request {@link ServletWebRequest} 这个类同时封装了request {@link javax.servlet.http.HttpServletRequest} 和 response {@link javax.servlet.http.HttpServletResponse} 57 | * @return 验证码 58 | * @throws ScaffoldException 全局异常 59 | */ 60 | private C generate(ServletWebRequest request) throws ScaffoldException { 61 | String type = getCodeType().toString().toLowerCase(); 62 | String generatorName = type + CodeGenerator.class.getSimpleName(); 63 | CodeGenerator validateCodeGenerator = codeGenerators.get(generatorName); 64 | if (validateCodeGenerator == null) { 65 | throw new ScaffoldException(Status.INTERNAL_SERVER_ERROR.getCode(), "验证码生成器" + generatorName + "不存在"); 66 | } 67 | return (C) validateCodeGenerator.generate(request); 68 | } 69 | 70 | /** 71 | * 保存验证码 72 | * 73 | * @param request {@link ServletWebRequest} 这个类同时封装了request {@link javax.servlet.http.HttpServletRequest} 和 response {@link javax.servlet.http.HttpServletResponse} 74 | * @param validateCode 验证码 75 | */ 76 | private void save(ServletWebRequest request, C validateCode) { 77 | sessionStrategy.setAttribute(request, getSessionKey(), validateCode); 78 | } 79 | 80 | /** 81 | * 构建验证码放入session时的key 82 | * 83 | * @return sessionKey 84 | */ 85 | private String getSessionKey() { 86 | return SESSION_KEY_PREFIX + getCodeType().toString().toUpperCase(); 87 | } 88 | 89 | /** 90 | * 发送校验码,由子类实现 91 | * 92 | * @param request {@link ServletWebRequest} 这个类同时封装了request {@link javax.servlet.http.HttpServletRequest} 和 response {@link javax.servlet.http.HttpServletResponse} 93 | * @param code 验证码 94 | * @throws ScaffoldException 全局异常 95 | */ 96 | protected abstract void send(ServletWebRequest request, C code) throws ScaffoldException; 97 | 98 | /** 99 | * 根据请求的url获取校验码的类型 100 | * 101 | * @return 验证码类型 102 | */ 103 | private CodeType getCodeType() { 104 | String type = StrUtil.subBefore(getClass().getSimpleName(), "CodeProcessor", true); 105 | return CodeType.valueOf(type.toUpperCase()); 106 | } 107 | 108 | /** 109 | * 校验验证码 110 | * 111 | * @param request {@link ServletWebRequest} 这个类同时封装了request {@link javax.servlet.http.HttpServletRequest} 和 response {@link javax.servlet.http.HttpServletResponse} 112 | * @throws ScaffoldException 全局异常 113 | */ 114 | @Override 115 | public void validate(ServletWebRequest request) throws ScaffoldException { 116 | 117 | CodeType processorType = getCodeType(); 118 | String sessionKey = getSessionKey(); 119 | 120 | C codeInSession = (C) sessionStrategy.getAttribute(request, sessionKey); 121 | 122 | String codeInRequest; 123 | try { 124 | codeInRequest = ServletRequestUtils.getStringParameter(request.getRequest(), processorType.getParamNameOnValidate()); 125 | } catch (ServletRequestBindingException e) { 126 | throw new ScaffoldException(Status.CODE_GET_ERROR); 127 | } 128 | 129 | if (StrUtil.isEmpty(codeInRequest)) { 130 | throw new ScaffoldException(Status.CODE_VALUE_NOT_NULL); 131 | } 132 | 133 | if (codeInSession == null) { 134 | throw new ScaffoldException(Status.CODE_NOT_FOUND); 135 | } 136 | 137 | if (codeInSession.isExpried()) { 138 | sessionStrategy.removeAttribute(request, sessionKey); 139 | throw new ScaffoldException(Status.CODE_IS_EXPIRED); 140 | } 141 | 142 | if (!StrUtil.equals(codeInSession.getCode(), codeInRequest)) { 143 | throw new ScaffoldException(Status.CODE_NOT_MATCH); 144 | } 145 | 146 | sessionStrategy.removeAttribute(request, sessionKey); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/security/code/base/Code.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config.security.code.base; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | 7 | /** 8 | *

9 | * 验证码基类 10 | *

11 | * 12 | * @package: com.xkcoding.scaffold.config.security.code.base 13 | * @description: 验证码基类 14 | * @author: yangkai.shen 15 | * @date: Created in 2018/8/18 上午10:52 16 | * @copyright: Copyright (c) 2018 17 | * @version: V1.0 18 | * @modified: yangkai.shen 19 | */ 20 | @Data 21 | public class Code { 22 | /** 23 | * 验证码 24 | */ 25 | private String code; 26 | 27 | /** 28 | * 过期时间 29 | */ 30 | private LocalDateTime expireTime; 31 | 32 | public Code() { 33 | } 34 | 35 | public Code(String code, int expireIn) { 36 | this.code = code; 37 | this.expireTime = LocalDateTime.now().plusSeconds(expireIn); 38 | } 39 | 40 | public Code(String code, LocalDateTime expireTime) { 41 | this.code = code; 42 | this.expireTime = expireTime; 43 | } 44 | 45 | /** 46 | * 是否过期 47 | */ 48 | public boolean isExpried() { 49 | return LocalDateTime.now().isAfter(expireTime); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/security/code/base/CodeGenerator.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config.security.code.base; 2 | 3 | import org.springframework.web.context.request.ServletWebRequest; 4 | 5 | /** 6 | *

7 | * 验证码生成器 8 | *

9 | * 10 | * @package: com.xkcoding.scaffold.config.security.code.base 11 | * @description: 验证码生成器 12 | * @author: yangkai.shen 13 | * @date: Created in 2018/8/18 上午10:59 14 | * @copyright: Copyright (c) 2018 15 | * @version: V1.0 16 | * @modified: yangkai.shen 17 | */ 18 | public interface CodeGenerator { 19 | /** 20 | * 验证码生成器接口 21 | * 22 | * @param request {@link ServletWebRequest} 这个类同时封装了request {@link javax.servlet.http.HttpServletRequest} 和 response {@link javax.servlet.http.HttpServletResponse} 23 | * @return 验证码 24 | */ 25 | Code generate(ServletWebRequest request); 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/security/code/base/CodeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config.security.code.base; 2 | 3 | import com.xkcoding.scaffold.exception.ScaffoldException; 4 | import org.springframework.web.context.request.ServletWebRequest; 5 | 6 | /** 7 | *

8 | * 验证码处理器,封装不同验证码的处理逻辑 9 | *

10 | * 11 | * @package: com.xkcoding.scaffold.config.security.code.base 12 | * @description: 验证码处理器,封装不同验证码的处理逻辑 13 | * @author: yangkai.shen 14 | * @date: Created in 2018/8/18 上午11:05 15 | * @copyright: Copyright (c) 2018 16 | * @version: V1.0 17 | * @modified: yangkai.shen 18 | */ 19 | public interface CodeProcessor { 20 | /** 21 | * 验证码放入session时的前缀 22 | */ 23 | String SESSION_KEY_PREFIX = "SCAFFOLD_SESSION_KEY_FOR_CODE_"; 24 | 25 | /** 26 | * 创建校验码 27 | * 28 | * @param request {@link ServletWebRequest} 这个类同时封装了request {@link javax.servlet.http.HttpServletRequest} 和 response {@link javax.servlet.http.HttpServletResponse} 29 | * @throws ScaffoldException 全局异常 30 | */ 31 | void create(ServletWebRequest request) throws ScaffoldException; 32 | 33 | /** 34 | * 校验验证码 35 | * 36 | * @param request {@link ServletWebRequest} 这个类同时封装了request {@link javax.servlet.http.HttpServletRequest} 和 response {@link javax.servlet.http.HttpServletResponse} 37 | * @throws ScaffoldException 全局异常 38 | */ 39 | void validate(ServletWebRequest request) throws ScaffoldException; 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/security/code/config/CodeBeanConfig.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config.security.code.config; 2 | 3 | import com.xkcoding.scaffold.common.property.ScaffoldProperties; 4 | import com.xkcoding.scaffold.config.security.code.base.CodeGenerator; 5 | import com.xkcoding.scaffold.config.security.code.image.ImageCodeGenerator; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | 11 | /** 12 | *

13 | * 验证码 Bean 配置类 14 | *

15 | * 16 | * @package: com.xkcoding.scaffold.config.security.code.config 17 | * @description: 验证码 Bean 配置类 18 | * @author: yangkai.shen 19 | * @date: Created in 2018/8/18 下午12:17 20 | * @copyright: Copyright (c) 2018 21 | * @version: V1.0 22 | * @modified: yangkai.shen 23 | */ 24 | @Configuration 25 | public class CodeBeanConfig { 26 | @Autowired 27 | private ScaffoldProperties scaffoldProperties; 28 | 29 | @Bean 30 | @ConditionalOnMissingBean(name = "imageGenerator") 31 | public CodeGenerator imageCodeGenerator() { 32 | ImageCodeGenerator imageCodeGenerator = new ImageCodeGenerator(); 33 | imageCodeGenerator.setScaffoldProperties(scaffoldProperties); 34 | return imageCodeGenerator; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/security/code/config/ScaffoldSecurityCodeConfig.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config.security.code.config; 2 | 3 | import com.xkcoding.scaffold.config.security.code.CodeFilter; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.security.config.annotation.SecurityConfigurerAdapter; 6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 7 | import org.springframework.security.web.DefaultSecurityFilterChain; 8 | import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; 9 | import org.springframework.stereotype.Component; 10 | 11 | /** 12 | *

13 | * 验证码配置类 14 | *

15 | * 16 | * @package: com.xkcoding.scaffold.config.security.code.config 17 | * @description: 验证码配置类 18 | * @author: yangkai.shen 19 | * @date: Created in 2018/8/18 下午12:24 20 | * @copyright: Copyright (c) 2018 21 | * @version: V1.0 22 | * @modified: yangkai.shen 23 | */ 24 | @Component("scaffoldSecurityCodeConfig") 25 | public class ScaffoldSecurityCodeConfig extends SecurityConfigurerAdapter { 26 | @Autowired 27 | private CodeFilter codeFilter; 28 | 29 | @Override 30 | public void configure(HttpSecurity http) throws Exception { 31 | http.addFilterBefore(codeFilter, AbstractPreAuthenticatedProcessingFilter.class); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/security/code/image/ImageCode.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config.security.code.image; 2 | 3 | import com.xkcoding.scaffold.config.security.code.base.Code; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | 7 | import java.awt.image.BufferedImage; 8 | import java.time.LocalDateTime; 9 | 10 | /** 11 | *

12 | * 图片验证码 13 | *

14 | * 15 | * @package: com.xkcoding.scaffold.config.security.code.image 16 | * @description: 图片验证码 17 | * @author: yangkai.shen 18 | * @date: Created in 2018/8/18 上午10:56 19 | * @copyright: Copyright (c) 2018 20 | * @version: V1.0 21 | * @modified: yangkai.shen 22 | */ 23 | @Data 24 | @EqualsAndHashCode(callSuper = true) 25 | public class ImageCode extends Code { 26 | /** 27 | * 验证码图片 28 | */ 29 | private BufferedImage image; 30 | 31 | public ImageCode(BufferedImage image) { 32 | this.image = image; 33 | } 34 | 35 | public ImageCode(BufferedImage image, String code, int expireIn) { 36 | super(code, expireIn); 37 | this.image = image; 38 | } 39 | 40 | public ImageCode(BufferedImage image, String code, LocalDateTime expireTime) { 41 | super(code, expireTime); 42 | this.image = image; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/security/code/image/ImageCodeGenerator.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config.security.code.image; 2 | 3 | import cn.hutool.captcha.CaptchaUtil; 4 | import cn.hutool.core.util.RandomUtil; 5 | import cn.hutool.core.util.StrUtil; 6 | import com.xkcoding.scaffold.common.property.ScaffoldProperties; 7 | import com.xkcoding.scaffold.config.security.code.base.Code; 8 | import com.xkcoding.scaffold.config.security.code.base.CodeGenerator; 9 | import lombok.Data; 10 | import org.springframework.web.bind.ServletRequestUtils; 11 | import org.springframework.web.context.request.ServletWebRequest; 12 | 13 | import javax.servlet.http.HttpServletRequest; 14 | import javax.servlet.http.HttpServletResponse; 15 | import java.awt.image.BufferedImage; 16 | 17 | /** 18 | *

19 | * 图片验证码生成器 20 | *

21 | * 22 | * @package: com.xkcoding.scaffold.config.security.code.image 23 | * @description: 图片验证码生成器 24 | * @author: yangkai.shen 25 | * @date: Created in 2018/8/18 上午11:08 26 | * @copyright: Copyright (c) 2018 27 | * @version: V1.0 28 | * @modified: yangkai.shen 29 | */ 30 | @Data 31 | public class ImageCodeGenerator implements CodeGenerator { 32 | private ScaffoldProperties scaffoldProperties; 33 | 34 | /** 35 | * 验证码生成器接口 36 | * 37 | * @param request {@link ServletWebRequest} 这个类同时封装了request {@link HttpServletRequest} 和 response {@link HttpServletResponse} 38 | * @return 验证码 39 | */ 40 | @Override 41 | public Code generate(ServletWebRequest request) { 42 | // 获取请求中的验证码宽高 43 | int width = ServletRequestUtils.getIntParameter(request.getRequest(), "width", scaffoldProperties.getSecurity() 44 | .getCode() 45 | .getImage() 46 | .getWidth()); 47 | int height = ServletRequestUtils.getIntParameter(request.getRequest(), "height", scaffoldProperties.getSecurity() 48 | .getCode() 49 | .getImage() 50 | .getHeight()); 51 | 52 | // 生成随机验证码 53 | int length = scaffoldProperties.getSecurity().getCode().getImage().getLength(); 54 | String randomCode = ""; 55 | for (int i = 0; i < length; i++) { 56 | randomCode = StrUtil.concat(true, randomCode, String.valueOf(RandomUtil.randomChar())); 57 | } 58 | BufferedImage image = (BufferedImage) CaptchaUtil.createLineCaptcha(width, height, length, 0) 59 | .createImage(randomCode); 60 | return new ImageCode(image, randomCode, scaffoldProperties.getSecurity().getCode().getImage().getExpireIn()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/security/code/image/ImageCodeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config.security.code.image; 2 | 3 | import com.xkcoding.scaffold.common.status.Status; 4 | import com.xkcoding.scaffold.config.security.code.base.AbstractCodeProcessor; 5 | import com.xkcoding.scaffold.exception.ScaffoldException; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.web.context.request.ServletWebRequest; 8 | 9 | import javax.imageio.ImageIO; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | import java.io.IOException; 13 | 14 | /** 15 | *

16 | * 图片验证码处理器 17 | *

18 | * 19 | * @package: com.xkcoding.scaffold.config.security.code.image 20 | * @description: 图片验证码处理器 21 | * @author: yangkai.shen 22 | * @date: Created in 2018/8/18 上午11:38 23 | * @copyright: Copyright (c) 2018 24 | * @version: V1.0 25 | * @modified: yangkai.shen 26 | */ 27 | @Component("imageCodeProcessor") 28 | public class ImageCodeProcessor extends AbstractCodeProcessor { 29 | 30 | /** 31 | * 发送校验码,由子类实现,图片验证码就是写入 response 中 32 | * 33 | * @param request {@link ServletWebRequest} 这个类同时封装了request {@link HttpServletRequest} 和 response {@link HttpServletResponse} 34 | * @param code 验证码 35 | * @throws ScaffoldException 全局异常 36 | */ 37 | @Override 38 | protected void send(ServletWebRequest request, ImageCode code) throws ScaffoldException { 39 | try { 40 | ImageIO.write(code.getImage(), "JPEG", request.getResponse().getOutputStream()); 41 | } catch (IOException e) { 42 | throw new ScaffoldException(Status.CODE_SEND_ERROR); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/security/handler/ScaffoldAccessDecisionManager.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config.security.handler; 2 | 3 | import cn.hutool.core.collection.CollUtil; 4 | import cn.hutool.core.util.StrUtil; 5 | import com.xkcoding.scaffold.common.status.Status; 6 | import org.springframework.security.access.AccessDecisionManager; 7 | import org.springframework.security.access.AccessDeniedException; 8 | import org.springframework.security.access.ConfigAttribute; 9 | import org.springframework.security.authentication.AnonymousAuthenticationToken; 10 | import org.springframework.security.authentication.BadCredentialsException; 11 | import org.springframework.security.authentication.InsufficientAuthenticationException; 12 | import org.springframework.security.core.Authentication; 13 | import org.springframework.security.core.GrantedAuthority; 14 | import org.springframework.stereotype.Component; 15 | 16 | import java.util.Collection; 17 | 18 | /** 19 | *

20 | * 自定义鉴权决策管理 21 | *

22 | * 23 | * @package: com.xkcoding.scaffold.config.security.handler 24 | * @description: 自定义鉴权决策管理 25 | * @author: yangkai.shen 26 | * @date: Created in 2018/8/8 下午8:36 27 | * @copyright: Copyright (c) 2018 28 | * @version: V1.0 29 | * @modified: yangkai.shen 30 | */ 31 | @Component 32 | public class ScaffoldAccessDecisionManager implements AccessDecisionManager { 33 | @Override 34 | public void decide(Authentication authentication, Object object, Collection configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { 35 | if (CollUtil.isEmpty(configAttributes)) { 36 | return; 37 | } 38 | for (ConfigAttribute configAttribute : configAttributes) { 39 | String needPermission = configAttribute.getAttribute(); 40 | 41 | if ("ROLE_LOGIN".equals(needPermission)) { 42 | if (authentication instanceof AnonymousAuthenticationToken) { 43 | throw new BadCredentialsException(Status.UNAUTHORIZED.getCode() + ""); 44 | } 45 | return; 46 | } 47 | 48 | Collection authorities = authentication.getAuthorities(); 49 | for (GrantedAuthority authority : authorities) { 50 | if (StrUtil.equals(StrUtil.trim(needPermission), authority.getAuthority())) { 51 | return; 52 | } 53 | } 54 | } 55 | throw new AccessDeniedException(Status.FORBIDDEN.getMsg()); 56 | } 57 | 58 | @Override 59 | public boolean supports(ConfigAttribute attribute) { 60 | return true; 61 | } 62 | 63 | @Override 64 | public boolean supports(Class clazz) { 65 | return true; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/security/handler/ScaffoldAccessDeniedHandler.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config.security.handler; 2 | 3 | import com.xkcoding.scaffold.common.Api; 4 | import com.xkcoding.scaffold.common.status.Status; 5 | import com.xkcoding.scaffold.util.ServletUtil; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.security.access.AccessDeniedException; 8 | import org.springframework.security.web.access.AccessDeniedHandler; 9 | import org.springframework.stereotype.Component; 10 | 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | 14 | /** 15 | *

16 | * 自定义拒绝访问处理器 17 | *

18 | * 19 | * @package: com.xkcoding.scaffold.config.security.handler 20 | * @description: 自定义拒绝访问处理器 21 | * @author: yangkai.shen 22 | * @date: Created in 2018/8/8 下午6:54 23 | * @copyright: Copyright (c) 2018 24 | * @version: V1.0 25 | * @modified: yangkai.shen 26 | */ 27 | @Component 28 | @Slf4j 29 | public class ScaffoldAccessDeniedHandler implements AccessDeniedHandler { 30 | 31 | /** 32 | * 权限不够时触发 33 | */ 34 | @Override 35 | public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException exception) { 36 | log.error("【鉴权操作】权限不够!", exception); 37 | ServletUtil.renderJson(response, Api.ofStatus(Status.FORBIDDEN)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/security/handler/ScaffoldAuthenticationFailureHandler.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config.security.handler; 2 | 3 | import cn.hutool.core.convert.Convert; 4 | import com.xkcoding.scaffold.common.Api; 5 | import com.xkcoding.scaffold.common.status.Status; 6 | import com.xkcoding.scaffold.util.EnumUtil; 7 | import com.xkcoding.scaffold.util.ServletUtil; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.security.core.AuthenticationException; 10 | import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; 11 | import org.springframework.stereotype.Component; 12 | 13 | import javax.servlet.http.HttpServletRequest; 14 | import javax.servlet.http.HttpServletResponse; 15 | import java.util.Objects; 16 | 17 | /** 18 | *

19 | * 自定义认证失败处理器 20 | *

21 | * 22 | * @package: com.xkcoding.scaffold.config.security 23 | * @description: 自定义认证失败处理器 24 | * @author: yangkai.shen 25 | * @date: Created in 2018/8/7 下午7:48 26 | * @copyright: Copyright (c) 2018 27 | * @version: V1.0 28 | * @modified: yangkai.shen 29 | */ 30 | @Component 31 | @Slf4j 32 | public class ScaffoldAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { 33 | 34 | /** 35 | * 认证失败时触发 36 | */ 37 | @Override 38 | public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) { 39 | log.error("【登录认证】登录失败!", exception); 40 | 41 | Integer errorCode = Convert.toInt(exception.getMessage(), 500); 42 | Status status = EnumUtil.getStatusByCode(errorCode, Status.class); 43 | ServletUtil.renderJson(response, Api.ofStatus(Objects.requireNonNull(status))); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/security/handler/ScaffoldAuthenticationSuccessHandler.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config.security.handler; 2 | 3 | import com.xkcoding.scaffold.common.Api; 4 | import com.xkcoding.scaffold.common.status.LogStatus; 5 | import com.xkcoding.scaffold.common.status.Status; 6 | import com.xkcoding.scaffold.mapper.SysUserMapper; 7 | import com.xkcoding.scaffold.model.SysUser; 8 | import com.xkcoding.scaffold.model.dto.SysUserDTO; 9 | import com.xkcoding.scaffold.util.LoginLogUtil; 10 | import com.xkcoding.scaffold.util.SecurityUtil; 11 | import com.xkcoding.scaffold.util.ServletUtil; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.modelmapper.ModelMapper; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.security.core.Authentication; 16 | import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; 17 | import org.springframework.stereotype.Component; 18 | 19 | import javax.servlet.http.HttpServletRequest; 20 | import javax.servlet.http.HttpServletResponse; 21 | import java.util.Date; 22 | 23 | /** 24 | *

25 | * 自定义认证成功处理器 26 | *

27 | * 28 | * @package: com.xkcoding.scaffold.config.security 29 | * @description: 自定义认证成功处理器 30 | * @author: yangkai.shen 31 | * @date: Created in 2018/8/7 下午8:12 32 | * @copyright: Copyright (c) 2018 33 | * @version: V1.0 34 | * @modified: yangkai.shen 35 | */ 36 | @Component 37 | @Slf4j 38 | public class ScaffoldAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { 39 | @Autowired 40 | private ModelMapper modelMapper; 41 | 42 | @Autowired 43 | private SysUserMapper sysUserMapper; 44 | 45 | /** 46 | * 认证成功时触发 47 | */ 48 | @Override 49 | public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { 50 | log.info("【登录认证】{} 登录成功!", authentication.getPrincipal()); 51 | 52 | // 保存登录成功日志 53 | LoginLogUtil.saveLog(authentication.getName(), Status.LOGIN_SUCCESS, LogStatus.SUCCESS); 54 | 55 | // 登录成功修改用户表登录ip和登录时间 56 | SysUserDTO principal = (SysUserDTO) authentication.getPrincipal(); 57 | SysUser sysUser = modelMapper.map(principal, SysUser.class); 58 | sysUser.setLoginIp(SecurityUtil.getIp()); 59 | sysUser.setLoginDate(new Date()); 60 | sysUserMapper.updateByPrimaryKeySelective(sysUser); 61 | 62 | ServletUtil.renderJson(response, Api.ofMessage(Status.LOGIN_SUCCESS.getMsg())); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/security/handler/ScaffoldDaoAuthenticationProvider.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config.security.handler; 2 | 3 | import cn.hutool.core.util.ObjectUtil; 4 | import com.xkcoding.scaffold.common.status.LogStatus; 5 | import com.xkcoding.scaffold.common.status.Status; 6 | import com.xkcoding.scaffold.util.LoginLogUtil; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.security.authentication.BadCredentialsException; 9 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 10 | import org.springframework.security.authentication.dao.DaoAuthenticationProvider; 11 | import org.springframework.security.core.AuthenticationException; 12 | import org.springframework.security.core.userdetails.UserDetails; 13 | 14 | /** 15 | *

16 | * 自定义认证 17 | *

18 | * 19 | * @package: com.xkcoding.scaffold.config.security 20 | * @description: 自定义认证 21 | * @author: yangkai.shen 22 | * @date: Created in 2018/8/10 下午1:51 23 | * @copyright: Copyright (c) 2018 24 | * @version: V1.0 25 | * @modified: yangkai.shen 26 | */ 27 | @Slf4j 28 | public class ScaffoldDaoAuthenticationProvider extends DaoAuthenticationProvider { 29 | 30 | /** 31 | * 校验密码,如果登录失败,记录日志 32 | * 33 | * @param userDetails 数据库保存的用户信息 34 | * @param authentication 表单提交的用户信息 35 | */ 36 | @Override 37 | protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { 38 | if (ObjectUtil.isNull(authentication.getCredentials())) { 39 | LoginLogUtil.saveLog(authentication.getName(), Status.USERNAME_OR_PASSWORD_ERROR, LogStatus.ERROR); 40 | throw new BadCredentialsException(Status.USERNAME_OR_PASSWORD_ERROR.getCode() + ""); 41 | } 42 | 43 | String presentedPassword = authentication.getCredentials().toString(); 44 | 45 | if (!getPasswordEncoder().matches(presentedPassword, userDetails.getPassword())) { 46 | LoginLogUtil.saveLog(authentication.getName(), Status.USERNAME_OR_PASSWORD_ERROR, LogStatus.ERROR); 47 | throw new BadCredentialsException(Status.USERNAME_OR_PASSWORD_ERROR.getCode() + ""); 48 | } 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/security/handler/ScaffoldFilterInvocationSecurityMetadataSource.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config.security.handler; 2 | 3 | import cn.hutool.core.map.MapUtil; 4 | import cn.hutool.core.util.StrUtil; 5 | import com.google.common.base.Splitter; 6 | import com.google.common.collect.Lists; 7 | import com.google.common.collect.Maps; 8 | import com.xkcoding.scaffold.common.constant.ScaffoldConst; 9 | import com.xkcoding.scaffold.common.status.MenuVisibleStatus; 10 | import com.xkcoding.scaffold.model.SysMenu; 11 | import com.xkcoding.scaffold.model.dto.SysMenuDTO; 12 | import com.xkcoding.scaffold.service.SysMenuService; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.security.access.ConfigAttribute; 15 | import org.springframework.security.access.SecurityConfig; 16 | import org.springframework.security.web.FilterInvocation; 17 | import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; 18 | import org.springframework.security.web.util.matcher.AntPathRequestMatcher; 19 | import org.springframework.stereotype.Component; 20 | import org.springframework.util.AntPathMatcher; 21 | 22 | import javax.servlet.http.HttpServletRequest; 23 | import java.util.Collection; 24 | import java.util.HashMap; 25 | import java.util.List; 26 | import java.util.Map; 27 | import java.util.stream.Collectors; 28 | 29 | /** 30 | *

31 | * 过滤器权限元数据 32 | *

33 | * 34 | * @package: com.xkcoding.scaffold.config.security.service 35 | * @description: 过滤器权限元数据 36 | * @author: yangkai.shen 37 | * @date: Created in 2018/8/8 下午9:41 38 | * @copyright: Copyright (c) 2018 39 | * @version: V1.0 40 | * @modified: yangkai.shen 41 | */ 42 | @Component 43 | public class ScaffoldFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource { 44 | @Autowired 45 | private SysMenuService sysMenuService; 46 | 47 | private static final HashMap> cache = Maps.newHashMap(); 48 | 49 | /** 50 | * 为了判定用户请求的url 是否在权限表中,如果在权限表中,则返回给 decide 方法,用来判定用户是否有此权限。如果不在权限表中则放行。 51 | */ 52 | @Override 53 | public Collection getAttributes(Object object) throws IllegalArgumentException { 54 | if (MapUtil.isEmpty(cache)) { 55 | loadSysMenuList(); 56 | } 57 | 58 | //object 中包含用户请求的request 信息 59 | HttpServletRequest request = ((FilterInvocation) object).getHttpRequest(); 60 | String requestUrl = ((FilterInvocation) object).getRequestUrl(); 61 | 62 | if (StrUtil.equals(ScaffoldConst.AUTHENTICATION_LOGIN_PAGE, requestUrl)) { 63 | return null; 64 | } 65 | 66 | for (Map.Entry> cacheEntry : cache.entrySet()) { 67 | String menuUrl = cacheEntry.getKey(); 68 | AntPathRequestMatcher matcher = new AntPathRequestMatcher(menuUrl); 69 | if (matcher.matches(request)) { 70 | return cache.get(menuUrl); 71 | } 72 | } 73 | 74 | //没有匹配上的资源,都是登录访问 75 | return SecurityConfig.createList("ROLE_LOGIN"); 76 | } 77 | 78 | public void loadSysMenuList() { 79 | List sysMenuDTOList = sysMenuService.listAllSysMenu(MenuVisibleStatus.SHOW.getCode()); 80 | 81 | for (SysMenuDTO sysMenuDTO : sysMenuDTOList) { 82 | if (StrUtil.equals(sysMenuDTO.getUrl(), "#")) { 83 | continue; 84 | } 85 | 86 | List configAttributes = Lists.newArrayList(); 87 | // 将菜单的权限表达式和菜单类型添加进权限信息 88 | if (StrUtil.isNotBlank(sysMenuDTO.getRoleKey())) { 89 | List rolesConfig = Splitter.on(ScaffoldConst.COMMA) 90 | .trimResults() 91 | .splitToList(sysMenuDTO.getRoleKey()) 92 | .stream() 93 | .map(s -> new SecurityConfig("ROLE_" + s)) 94 | .collect(Collectors.toList()); 95 | configAttributes.addAll(rolesConfig); 96 | } 97 | cache.put(sysMenuDTO.getUrl(), configAttributes); 98 | } 99 | } 100 | 101 | @Override 102 | public Collection getAllConfigAttributes() { 103 | Collection configAttributes = Lists.newArrayList(); 104 | for (Collection value : cache.values()) { 105 | configAttributes.addAll(value); 106 | } 107 | return configAttributes; 108 | } 109 | 110 | @Override 111 | public boolean supports(Class clazz) { 112 | return FilterInvocation.class.isAssignableFrom(clazz); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/security/handler/ScaffoldLogoutSuccessHandler.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config.security.handler; 2 | 3 | import cn.hutool.core.util.ObjectUtil; 4 | import com.xkcoding.scaffold.common.Api; 5 | import com.xkcoding.scaffold.common.status.LogStatus; 6 | import com.xkcoding.scaffold.common.status.Status; 7 | import com.xkcoding.scaffold.util.LoginLogUtil; 8 | import com.xkcoding.scaffold.util.ServletUtil; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.springframework.security.core.Authentication; 11 | import org.springframework.security.core.userdetails.UserDetails; 12 | import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; 13 | import org.springframework.stereotype.Component; 14 | 15 | import javax.servlet.http.HttpServletRequest; 16 | import javax.servlet.http.HttpServletResponse; 17 | 18 | /** 19 | *

20 | * 自定义登出成功处理器 21 | *

22 | * 23 | * @package: com.xkcoding.scaffold.config.security 24 | * @description: 自定义登出成功处理器 25 | * @author: yangkai.shen 26 | * @date: Created in 2018/8/7 下午9:12 27 | * @copyright: Copyright (c) 2018 28 | * @version: V1.0 29 | * @modified: yangkai.shen 30 | */ 31 | @Component 32 | @Slf4j 33 | public class ScaffoldLogoutSuccessHandler implements LogoutSuccessHandler { 34 | 35 | /** 36 | * 登出成功时触发 37 | */ 38 | @Override 39 | public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { 40 | if (ObjectUtil.isNotNull(authentication)) { 41 | log.info("【退出登录】{} 登出成功!", ((UserDetails) authentication.getPrincipal()).getUsername()); 42 | 43 | LoginLogUtil.saveLog(authentication.getName(), Status.LOGOUT_SUCCESS, LogStatus.SUCCESS); 44 | ServletUtil.renderJson(response, Api.ofMessage(Status.LOGOUT_SUCCESS.getMsg())); 45 | } else { 46 | ServletUtil.renderJson(response, Api.ofStatus(Status.UNAUTHORIZED)); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/config/security/service/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.config.security.service; 2 | 3 | import cn.hutool.core.util.ObjectUtil; 4 | import com.google.common.collect.Sets; 5 | import com.xkcoding.scaffold.common.status.DeleteStatus; 6 | import com.xkcoding.scaffold.common.status.LogStatus; 7 | import com.xkcoding.scaffold.common.status.Status; 8 | import com.xkcoding.scaffold.common.status.UserStatus; 9 | import com.xkcoding.scaffold.model.SysMenu; 10 | import com.xkcoding.scaffold.model.SysRole; 11 | import com.xkcoding.scaffold.model.SysUser; 12 | import com.xkcoding.scaffold.model.dto.SysUserDTO; 13 | import com.xkcoding.scaffold.service.SysMenuService; 14 | import com.xkcoding.scaffold.service.SysRoleService; 15 | import com.xkcoding.scaffold.service.SysUserService; 16 | import com.xkcoding.scaffold.util.EnumUtil; 17 | import com.xkcoding.scaffold.util.LoginLogUtil; 18 | import org.modelmapper.ModelMapper; 19 | import org.springframework.beans.factory.annotation.Autowired; 20 | import org.springframework.security.authentication.DisabledException; 21 | import org.springframework.security.authentication.LockedException; 22 | import org.springframework.security.core.userdetails.UserDetails; 23 | import org.springframework.security.core.userdetails.UserDetailsService; 24 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 25 | import org.springframework.stereotype.Service; 26 | 27 | import java.util.List; 28 | 29 | /** 30 | *

31 | * 自定义用户验证 32 | *

33 | * 34 | * @package: com.xkcoding.scaffold.config.security.service 35 | * @description: 自定义用户验证 36 | * @author: yangkai.shen 37 | * @date: Created in 2018/8/8 下午3:59 38 | * @copyright: Copyright (c) 2018 39 | * @version: V1.0 40 | * @modified: yangkai.shen 41 | */ 42 | @Service 43 | public class UserDetailsServiceImpl implements UserDetailsService { 44 | @Autowired 45 | private ModelMapper modelMapper; 46 | 47 | @Autowired 48 | private SysUserService sysUserService; 49 | 50 | @Autowired 51 | private SysRoleService sysRoleService; 52 | 53 | @Autowired 54 | private SysMenuService sysMenuService; 55 | 56 | /** 57 | * 根据登录名查询用户信息,账号异常时保存日志信息 58 | * 59 | * @param username 用户名 60 | * @return {@link SysUserDTO} 61 | * @throws UsernameNotFoundException 账号不存在 62 | */ 63 | @Override 64 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 65 | // 根据登录名查询用户 66 | SysUser loginUser = sysUserService.getUserByLoginName(username); 67 | 68 | // 账号不存在 69 | if (ObjectUtil.isNull(loginUser)) { 70 | throw new UsernameNotFoundException(Status.USER_NOT_EXIST.getCode() + ""); 71 | } 72 | 73 | // 账号逻辑删除 74 | DeleteStatus deleteStatus = EnumUtil.getStatusByCode(loginUser.getDelFlag(), DeleteStatus.class); 75 | if (ObjectUtil.equal(deleteStatus, DeleteStatus.DELETED)) { 76 | LoginLogUtil.saveLog(username, Status.USER_DELETED, LogStatus.ERROR); 77 | throw new DisabledException(Status.USER_DELETED.getCode() + ""); 78 | } 79 | 80 | // 账号禁用 81 | UserStatus userStatus = EnumUtil.getStatusByCode(loginUser.getStatus(), UserStatus.class); 82 | if (ObjectUtil.equal(userStatus, UserStatus.DISABLE)) { 83 | LoginLogUtil.saveLog(username, Status.USER_DISABLE, LogStatus.ERROR); 84 | throw new LockedException(Status.USER_DISABLE.getCode() + ""); 85 | } 86 | 87 | // 根据用户查询对应角色 88 | List sysRoleList = sysRoleService.listSysRolesByUserId(loginUser.getId()); 89 | 90 | // 根据角色查询对应菜单 91 | List sysMenuList = sysMenuService.listSysMenusByRoleList(sysRoleList); 92 | 93 | // 对象转换 94 | SysUserDTO sysUserDTO = modelMapper.map(loginUser, SysUserDTO.class); 95 | sysUserDTO.setRoles(Sets.newHashSet(sysRoleList)); 96 | sysUserDTO.setMenus(Sets.newHashSet(sysMenuList)); 97 | return sysUserDTO; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/controller/AuthenticationController.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.controller; 2 | 3 | import com.xkcoding.scaffold.common.Api; 4 | import com.xkcoding.scaffold.common.status.Status; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | /** 10 | *

11 | * 认证 Controller 12 | *

13 | * 14 | * @package: com.xkcoding.scaffold.controller 15 | * @description: 认证 Controller 16 | * @author: yangkai.shen 17 | * @date: Created in 2018/8/7 下午8:06 18 | * @copyright: Copyright (c) 2018 19 | * @version: V1.0 20 | * @modified: yangkai.shen 21 | */ 22 | @RestController 23 | @RequestMapping("/authentication") 24 | public class AuthenticationController { 25 | 26 | /** 27 | * 需要授权 28 | * 29 | * @return {@link Status#UNAUTHORIZED} 30 | */ 31 | @GetMapping("/require") 32 | public Api require() { 33 | return Api.ofStatus(Status.UNAUTHORIZED); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/controller/TestController.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.controller; 2 | 3 | import cn.hutool.core.util.ObjectUtil; 4 | import com.xkcoding.scaffold.aspectj.annotation.Log; 5 | import com.xkcoding.scaffold.aspectj.constant.ActionType; 6 | import com.xkcoding.scaffold.common.Api; 7 | import com.xkcoding.scaffold.common.status.Status; 8 | import com.xkcoding.scaffold.exception.ScaffoldException; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.springframework.web.bind.annotation.GetMapping; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | /** 15 | *

16 | * 测试 Controller 17 | *

18 | * 19 | * @package: com.xkcoding.scaffold.controller 20 | * @description: 测试 Controller 21 | * @author: yangkai.shen 22 | * @date: Created in 2018/8/6 下午6:37 23 | * @copyright: Copyright (c) 2018 24 | * @version: V1.0 25 | * @modified: yangkai.shen 26 | */ 27 | @RestController 28 | @RequestMapping("/test") 29 | @Slf4j 30 | public class TestController { 31 | 32 | /** 33 | * 测试 AOP 记录操作日志 34 | * 35 | * @param hasError 是否有错误 36 | * @return {@link Api} 37 | * @throws ScaffoldException 全局异常 38 | */ 39 | @Log(title = "测试模块-操作日志", action = ActionType.INSERT) 40 | @GetMapping("/operate/log") 41 | public Api testOperateLog(Boolean hasError) throws ScaffoldException { 42 | log.info("【测试】AOP 记录操作日志"); 43 | if (ObjectUtil.isNotNull(hasError) && hasError) { 44 | simulateException(); 45 | } 46 | return Api.ofSuccess(); 47 | } 48 | 49 | /** 50 | * 模拟异常 51 | * 52 | * @throws ScaffoldException 全局异常{@link Status#INTERNAL_SERVER_ERROR} 53 | */ 54 | private void simulateException() throws ScaffoldException { 55 | log.error("【测试】AOP 记录操作日志,发生异常!"); 56 | throw new ScaffoldException(Status.INTERNAL_SERVER_ERROR); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/exception/ScaffoldException.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.exception; 2 | 3 | import com.xkcoding.scaffold.common.status.Status; 4 | import lombok.Getter; 5 | 6 | /** 7 | *

8 | * 通用全局异常 9 | *

10 | * 11 | * @package: com.xkcoding.scaffold.exception 12 | * @description: 通用全局异常 13 | * @author: yangkai.shen 14 | * @date: Created in 2018/8/2 下午7:59 15 | * @copyright: Copyright (c) 2018 16 | * @version: V1.0 17 | * @modified: yangkai.shen 18 | */ 19 | @Getter 20 | public class ScaffoldException extends Exception { 21 | /** 22 | * 异常码 23 | */ 24 | private Integer code; 25 | 26 | /** 27 | * 返回信息 28 | */ 29 | private String msg; 30 | 31 | /** 32 | * 返回内容 33 | */ 34 | private Object data; 35 | 36 | public ScaffoldException(Integer code, String msg) { 37 | super(msg); 38 | this.code = code; 39 | this.msg = msg; 40 | } 41 | 42 | public ScaffoldException(Integer code, String msg, Object data) { 43 | super(msg); 44 | this.code = code; 45 | this.msg = msg; 46 | this.data = data; 47 | } 48 | 49 | public ScaffoldException(Status status) { 50 | super(status.getMsg()); 51 | this.code = status.getCode(); 52 | this.msg = status.getMsg(); 53 | } 54 | 55 | public ScaffoldException(Status status, Object data) { 56 | super(status.getMsg()); 57 | this.code = status.getCode(); 58 | this.msg = status.getMsg(); 59 | this.data = data; 60 | } 61 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/handler/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.handler; 2 | 3 | import com.xkcoding.scaffold.common.Api; 4 | import com.xkcoding.scaffold.common.status.Status; 5 | import com.xkcoding.scaffold.exception.ScaffoldException; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.security.access.AccessDeniedException; 8 | import org.springframework.web.bind.annotation.ControllerAdvice; 9 | import org.springframework.web.bind.annotation.ExceptionHandler; 10 | import org.springframework.web.bind.annotation.ResponseBody; 11 | import org.springframework.web.servlet.NoHandlerFoundException; 12 | 13 | /** 14 | *

15 | * 全局异常处理 16 | *

17 | * 18 | * @package: com.xkcoding.scaffold.handler 19 | * @description: 全局异常处理 20 | * @author: yangkai.shen 21 | * @date: Created in 2018/8/2 下午8:05 22 | * @copyright: Copyright (c) 2018 23 | * @version: V1.0 24 | * @modified: yangkai.shen 25 | */ 26 | @Slf4j 27 | @ControllerAdvice 28 | public class GlobalExceptionHandler { 29 | 30 | @ExceptionHandler(value = Exception.class) 31 | @ResponseBody 32 | public Api handlerException(Exception e) { 33 | if (e instanceof NoHandlerFoundException) { 34 | log.error("【全局异常拦截】NoHandlerFoundException: 请求方法 {}, 请求路径 {}", ((NoHandlerFoundException) e).getRequestURL(), ((NoHandlerFoundException) e) 35 | .getHttpMethod()); 36 | return Api.ofStatus(Status.REQUEST_NOT_FOUND); 37 | } else if (e instanceof ScaffoldException) { 38 | log.error("【全局异常拦截】ScaffoldException: 状态码 {}, 异常信息 {}", ((ScaffoldException) e).getCode(), e.getMessage()); 39 | return new Api(((ScaffoldException) e).getCode(), e.getMessage(), ((ScaffoldException) e).getData()); 40 | } else if (e instanceof AccessDeniedException) { 41 | log.error("【全局异常拦截】AccessDeniedException: 异常信息 {}", e.getMessage()); 42 | return Api.ofStatus(Status.FORBIDDEN); 43 | } 44 | 45 | log.error("【全局异常拦截】: 异常信息 {} ", e.getMessage()); 46 | return Api.ofStatus(Status.INTERNAL_SERVER_ERROR); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/mapper/SysConfigMapper.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.mapper; 2 | 3 | import com.xkcoding.scaffold.common.MyMapper; 4 | import com.xkcoding.scaffold.model.SysConfig; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | *

9 | * 参数配置Mapper 10 | *

11 | * 12 | * @package: com.xkcoding.scaffold.mapper 13 | * @description: 参数配置Mapper 14 | * @author: yangkai.shen 15 | * @date: Created in 2018/7/31 上午10:44 16 | * @copyright: Copyright (c) 2018 17 | * @version: V1.0 18 | * @modified: yangkai.shen 19 | */ 20 | @Repository 21 | public interface SysConfigMapper extends MyMapper { 22 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/mapper/SysDeptMapper.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.mapper; 2 | 3 | import com.xkcoding.scaffold.common.MyMapper; 4 | import com.xkcoding.scaffold.model.SysDept; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | *

9 | * 部门Mapper 10 | *

11 | * 12 | * @package: com.xkcoding.scaffold.mapper 13 | * @description: 部门Mapper 14 | * @author: yangkai.shen 15 | * @date: Created in 2018/7/31 上午10:49 16 | * @copyright: Copyright (c) 2018 17 | * @version: V1.0 18 | * @modified: yangkai.shen 19 | */ 20 | @Repository 21 | public interface SysDeptMapper extends MyMapper { 22 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/mapper/SysDictDataMapper.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.mapper; 2 | 3 | import com.xkcoding.scaffold.common.MyMapper; 4 | import com.xkcoding.scaffold.model.SysDictData; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | *

9 | * 字典数据Mapper 10 | *

11 | * 12 | * @package: com.xkcoding.scaffold.mapper 13 | * @description: 字典数据Mapper 14 | * @author: yangkai.shen 15 | * @date: Created in 2018/7/31 上午10:49 16 | * @copyright: Copyright (c) 2018 17 | * @version: V1.0 18 | * @modified: yangkai.shen 19 | */ 20 | @Repository 21 | public interface SysDictDataMapper extends MyMapper { 22 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/mapper/SysDictTypeMapper.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.mapper; 2 | 3 | import com.xkcoding.scaffold.common.MyMapper; 4 | import com.xkcoding.scaffold.model.SysDictType; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | *

9 | * 字典类型Mapper 10 | *

11 | * 12 | * @package: com.xkcoding.scaffold.mapper 13 | * @description: 字典类型Mapper 14 | * @author: yangkai.shen 15 | * @date: Created in 2018/7/31 上午10:50 16 | * @copyright: Copyright (c) 2018 17 | * @version: V1.0 18 | * @modified: yangkai.shen 19 | */ 20 | @Repository 21 | public interface SysDictTypeMapper extends MyMapper { 22 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/mapper/SysLoginLogMapper.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.mapper; 2 | 3 | import com.xkcoding.scaffold.common.MyMapper; 4 | import com.xkcoding.scaffold.model.SysLoginLog; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | *

9 | * 系统访问记录Mapper 10 | *

11 | * 12 | * @package: com.xkcoding.scaffold.mapper 13 | * @description: 系统访问记录Mapper 14 | * @author: yangkai.shen 15 | * @date: Created in 2018/7/31 上午10:50 16 | * @copyright: Copyright (c) 2018 17 | * @version: V1.0 18 | * @modified: yangkai.shen 19 | */ 20 | @Repository 21 | public interface SysLoginLogMapper extends MyMapper { 22 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/mapper/SysMenuMapper.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.mapper; 2 | 3 | import com.xkcoding.scaffold.common.MyMapper; 4 | import com.xkcoding.scaffold.model.SysMenu; 5 | import com.xkcoding.scaffold.model.dto.SysMenuDTO; 6 | import org.apache.ibatis.annotations.Param; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | *

13 | * 菜单权限Mapper 14 | *

15 | * 16 | * @package: com.xkcoding.scaffold.mapper 17 | * @description: 菜单权限Mapper 18 | * @author: yangkai.shen 19 | * @date: Created in 2018/7/31 上午10:51 20 | * @copyright: Copyright (c) 2018 21 | * @version: V1.0 22 | * @modified: yangkai.shen 23 | */ 24 | @Repository 25 | public interface SysMenuMapper extends MyMapper { 26 | 27 | /** 28 | * 根据角色 id 列表查询菜单列表 29 | * 30 | * @param roleIdList 用户 id 列表 31 | * @return 菜单列表 32 | */ 33 | List selectSysMenuByRoleList(@Param("roleIdList") List roleIdList); 34 | 35 | /** 36 | * 所有菜单列表,包含权限基础信息 37 | * 38 | * @param visible 菜单是否可见 39 | * @return 所有菜单列表,包含权限基础信息 40 | */ 41 | List selectSysMenuList(@Param("visible") Integer visible); 42 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/mapper/SysOperationLogMapper.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.mapper; 2 | 3 | import com.xkcoding.scaffold.common.MyMapper; 4 | import com.xkcoding.scaffold.model.SysOperationLog; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | *

9 | * 操作日志记录Mapper 10 | *

11 | * 12 | * @package: com.xkcoding.scaffold.mapper 13 | * @description: 操作日志记录Mapper 14 | * @author: yangkai.shen 15 | * @date: Created in 2018/7/31 上午10:51 16 | * @copyright: Copyright (c) 2018 17 | * @version: V1.0 18 | * @modified: yangkai.shen 19 | */ 20 | @Repository 21 | public interface SysOperationLogMapper extends MyMapper { 22 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/mapper/SysRoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.mapper; 2 | 3 | import com.xkcoding.scaffold.common.MyMapper; 4 | import com.xkcoding.scaffold.model.SysRole; 5 | import org.apache.ibatis.annotations.Param; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | *

12 | * 角色信息Mapper 13 | *

14 | * 15 | * @package: com.xkcoding.scaffold.mapper 16 | * @description: 角色信息Mapper 17 | * @author: yangkai.shen 18 | * @date: Created in 2018/7/31 上午10:51 19 | * @copyright: Copyright (c) 2018 20 | * @version: V1.0 21 | * @modified: yangkai.shen 22 | */ 23 | @Repository 24 | public interface SysRoleMapper extends MyMapper { 25 | 26 | /** 27 | * 根据角色 id 列表查询角色列表 28 | * 29 | * @param roleIdList 用户 id 列表 30 | * @return 角色列表 31 | */ 32 | List selectSysRoleByRoleList(@Param("roleIdList") List roleIdList); 33 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/mapper/SysRoleMenuMapper.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.mapper; 2 | 3 | import com.xkcoding.scaffold.common.MyMapper; 4 | import com.xkcoding.scaffold.model.SysRoleMenu; 5 | import org.apache.ibatis.annotations.Param; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | *

12 | * 角色和菜单关联Mapper 13 | *

14 | * 15 | * @package: com.xkcoding.scaffold.mapper 16 | * @description: 角色和菜单关联Mapper 17 | * @author: yangkai.shen 18 | * @date: Created in 2018/7/31 上午10:52 19 | * @copyright: Copyright (c) 2018 20 | * @version: V1.0 21 | * @modified: yangkai.shen 22 | */ 23 | @Repository 24 | public interface SysRoleMenuMapper extends MyMapper { 25 | 26 | /** 27 | * 根据角色 id 列表查询角色菜单关系列表 28 | * 29 | * @param roleIdList 角色 id 列表 30 | * @return 角色菜单关系列表 31 | */ 32 | List selectSysRoleMenuByRoleIdList(@Param("roleIdList") List roleIdList); 33 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/mapper/SysUserMapper.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.mapper; 2 | 3 | import com.xkcoding.scaffold.common.MyMapper; 4 | import com.xkcoding.scaffold.model.SysUser; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | *

9 | * 用户信息Mapper 10 | *

11 | * 12 | * @package: com.xkcoding.scaffold.mapper 13 | * @description: 用户信息Mapper 14 | * @author: yangkai.shen 15 | * @date: Created in 2018/7/31 上午10:52 16 | * @copyright: Copyright (c) 2018 17 | * @version: V1.0 18 | * @modified: yangkai.shen 19 | */ 20 | @Repository 21 | public interface SysUserMapper extends MyMapper { 22 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/mapper/SysUserRoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.mapper; 2 | 3 | import com.xkcoding.scaffold.common.MyMapper; 4 | import com.xkcoding.scaffold.model.SysUserRole; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | *

9 | * 用户和角色关联Mapper 10 | *

11 | * 12 | * @package: com.xkcoding.scaffold.mapper 13 | * @description: 用户和角色关联Mapper 14 | * @author: yangkai.shen 15 | * @date: Created in 2018/7/31 上午10:52 16 | * @copyright: Copyright (c) 2018 17 | * @version: V1.0 18 | * @modified: yangkai.shen 19 | */ 20 | @Repository 21 | public interface SysUserRoleMapper extends MyMapper { 22 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/mapper/SysUserWorkMapper.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.mapper; 2 | 3 | import com.xkcoding.scaffold.common.MyMapper; 4 | import com.xkcoding.scaffold.model.SysUserWork; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | *

9 | * 用户与岗位关联Mapper 10 | *

11 | * 12 | * @package: com.xkcoding.scaffold.mapper 13 | * @description: 用户与岗位关联Mapper 14 | * @author: yangkai.shen 15 | * @date: Created in 2018/7/31 上午10:53 16 | * @copyright: Copyright (c) 2018 17 | * @version: V1.0 18 | * @modified: yangkai.shen 19 | */ 20 | @Repository 21 | public interface SysUserWorkMapper extends MyMapper { 22 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/mapper/SysWorkMapper.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.mapper; 2 | 3 | import com.xkcoding.scaffold.common.MyMapper; 4 | import com.xkcoding.scaffold.model.SysWork; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | *

9 | * 岗位信息Mapper 10 | *

11 | * 12 | * @package: com.xkcoding.scaffold.mapper 13 | * @description: 岗位信息Mapper 14 | * @author: yangkai.shen 15 | * @date: Created in 2018/7/31 上午10:53 16 | * @copyright: Copyright (c) 2018 17 | * @version: V1.0 18 | * @modified: yangkai.shen 19 | */ 20 | @Repository 21 | public interface SysWorkMapper extends MyMapper { 22 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/model/SysConfig.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.model; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.GeneratedValue; 5 | import javax.persistence.Id; 6 | import javax.persistence.Table; 7 | import java.util.Date; 8 | 9 | /** 10 | *

11 | * 参数配置表 12 | *

13 | * 14 | * @package: com.xkcoding.scaffold.model 15 | * @description: 参数配置表 16 | * @author: yangkai.shen 17 | * @date: Created in 2018/7/31 上午10:27 18 | * @copyright: Copyright (c) 2018 19 | * @version: V1.0 20 | * @modified: yangkai.shen 21 | */ 22 | @Table(name = "sys_config") 23 | public class SysConfig { 24 | /** 25 | * 参数主键 26 | */ 27 | @Id 28 | @Column(name = "id") 29 | @GeneratedValue(generator = "JDBC") 30 | private Integer id; 31 | 32 | /** 33 | * 参数名称 34 | */ 35 | @Column(name = "config_name") 36 | private String configName; 37 | 38 | /** 39 | * 参数键名 40 | */ 41 | @Column(name = "config_key") 42 | private String configKey; 43 | 44 | /** 45 | * 参数键值 46 | */ 47 | @Column(name = "config_value") 48 | private String configValue; 49 | 50 | /** 51 | * 系统内置(0否 1是) 52 | */ 53 | @Column(name = "config_type") 54 | private Integer configType; 55 | 56 | /** 57 | * 创建者 58 | */ 59 | @Column(name = "create_by") 60 | private String createBy; 61 | 62 | /** 63 | * 创建时间 64 | */ 65 | @Column(name = "create_time") 66 | private Date createTime; 67 | 68 | /** 69 | * 更新者 70 | */ 71 | @Column(name = "update_by") 72 | private String updateBy; 73 | 74 | /** 75 | * 更新时间 76 | */ 77 | @Column(name = "update_time") 78 | private Date updateTime; 79 | 80 | /** 81 | * 备注 82 | */ 83 | @Column(name = "remark") 84 | private String remark; 85 | 86 | /** 87 | * 获取参数主键 88 | * 89 | * @return id - 参数主键 90 | */ 91 | public Integer getId() { 92 | return id; 93 | } 94 | 95 | /** 96 | * 设置参数主键 97 | * 98 | * @param id 参数主键 99 | */ 100 | public void setId(Integer id) { 101 | this.id = id; 102 | } 103 | 104 | /** 105 | * 获取参数名称 106 | * 107 | * @return config_name - 参数名称 108 | */ 109 | public String getConfigName() { 110 | return configName; 111 | } 112 | 113 | /** 114 | * 设置参数名称 115 | * 116 | * @param configName 参数名称 117 | */ 118 | public void setConfigName(String configName) { 119 | this.configName = configName; 120 | } 121 | 122 | /** 123 | * 获取参数键名 124 | * 125 | * @return config_key - 参数键名 126 | */ 127 | public String getConfigKey() { 128 | return configKey; 129 | } 130 | 131 | /** 132 | * 设置参数键名 133 | * 134 | * @param configKey 参数键名 135 | */ 136 | public void setConfigKey(String configKey) { 137 | this.configKey = configKey; 138 | } 139 | 140 | /** 141 | * 获取参数键值 142 | * 143 | * @return config_value - 参数键值 144 | */ 145 | public String getConfigValue() { 146 | return configValue; 147 | } 148 | 149 | /** 150 | * 设置参数键值 151 | * 152 | * @param configValue 参数键值 153 | */ 154 | public void setConfigValue(String configValue) { 155 | this.configValue = configValue; 156 | } 157 | 158 | /** 159 | * 获取系统内置(0否 1是) 160 | * 161 | * @return config_type - 系统内置(0否 1是) 162 | */ 163 | public Integer getConfigType() { 164 | return configType; 165 | } 166 | 167 | /** 168 | * 设置系统内置(0否 1是) 169 | * 170 | * @param configType 系统内置(0否 1是) 171 | */ 172 | public void setConfigType(Integer configType) { 173 | this.configType = configType; 174 | } 175 | 176 | /** 177 | * 获取创建者 178 | * 179 | * @return create_by - 创建者 180 | */ 181 | public String getCreateBy() { 182 | return createBy; 183 | } 184 | 185 | /** 186 | * 设置创建者 187 | * 188 | * @param createBy 创建者 189 | */ 190 | public void setCreateBy(String createBy) { 191 | this.createBy = createBy; 192 | } 193 | 194 | /** 195 | * 获取创建时间 196 | * 197 | * @return create_time - 创建时间 198 | */ 199 | public Date getCreateTime() { 200 | return createTime; 201 | } 202 | 203 | /** 204 | * 设置创建时间 205 | * 206 | * @param createTime 创建时间 207 | */ 208 | public void setCreateTime(Date createTime) { 209 | this.createTime = createTime; 210 | } 211 | 212 | /** 213 | * 获取更新者 214 | * 215 | * @return update_by - 更新者 216 | */ 217 | public String getUpdateBy() { 218 | return updateBy; 219 | } 220 | 221 | /** 222 | * 设置更新者 223 | * 224 | * @param updateBy 更新者 225 | */ 226 | public void setUpdateBy(String updateBy) { 227 | this.updateBy = updateBy; 228 | } 229 | 230 | /** 231 | * 获取更新时间 232 | * 233 | * @return update_time - 更新时间 234 | */ 235 | public Date getUpdateTime() { 236 | return updateTime; 237 | } 238 | 239 | /** 240 | * 设置更新时间 241 | * 242 | * @param updateTime 更新时间 243 | */ 244 | public void setUpdateTime(Date updateTime) { 245 | this.updateTime = updateTime; 246 | } 247 | 248 | /** 249 | * 获取备注 250 | * 251 | * @return remark - 备注 252 | */ 253 | public String getRemark() { 254 | return remark; 255 | } 256 | 257 | /** 258 | * 设置备注 259 | * 260 | * @param remark 备注 261 | */ 262 | public void setRemark(String remark) { 263 | this.remark = remark; 264 | } 265 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/model/SysDept.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.model; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.GeneratedValue; 5 | import javax.persistence.Id; 6 | import javax.persistence.Table; 7 | import java.util.Date; 8 | 9 | /** 10 | *

11 | * 部门表 12 | *

13 | * 14 | * @package: com.xkcoding.scaffold.model 15 | * @description: 部门表 16 | * @author: yangkai.shen 17 | * @date: Created in 2018/7/31 上午10:28 18 | * @copyright: Copyright (c) 2018 19 | * @version: V1.0 20 | * @modified: yangkai.shen 21 | */ 22 | @Table(name = "sys_dept") 23 | public class SysDept { 24 | /** 25 | * 部门id 26 | */ 27 | @Id 28 | @Column(name = "id") 29 | @GeneratedValue(generator = "JDBC") 30 | private Integer id; 31 | 32 | /** 33 | * 父部门id 34 | */ 35 | @Column(name = "parent_id") 36 | private Integer parentId; 37 | 38 | /** 39 | * 部门名称 40 | */ 41 | @Column(name = "dept_name") 42 | private String deptName; 43 | 44 | /** 45 | * 显示顺序 46 | */ 47 | @Column(name = "order_num") 48 | private Integer orderNum; 49 | 50 | /** 51 | * 负责人 52 | */ 53 | @Column(name = "leader") 54 | private String leader; 55 | 56 | /** 57 | * 联系电话 58 | */ 59 | @Column(name = "phone") 60 | private String phone; 61 | 62 | /** 63 | * 邮箱 64 | */ 65 | @Column(name = "email") 66 | private String email; 67 | 68 | /** 69 | * 部门状态(0停用 1正常) 70 | */ 71 | @Column(name = "status") 72 | private Integer status; 73 | 74 | /** 75 | * 创建者 76 | */ 77 | @Column(name = "create_by") 78 | private String createBy; 79 | 80 | /** 81 | * 创建时间 82 | */ 83 | @Column(name = "create_time") 84 | private Date createTime; 85 | 86 | /** 87 | * 更新者 88 | */ 89 | @Column(name = "update_by") 90 | private String updateBy; 91 | 92 | /** 93 | * 更新时间 94 | */ 95 | @Column(name = "update_time") 96 | private Date updateTime; 97 | 98 | /** 99 | * 获取部门id 100 | * 101 | * @return id - 部门id 102 | */ 103 | public Integer getId() { 104 | return id; 105 | } 106 | 107 | /** 108 | * 设置部门id 109 | * 110 | * @param id 部门id 111 | */ 112 | public void setId(Integer id) { 113 | this.id = id; 114 | } 115 | 116 | /** 117 | * 获取父部门id 118 | * 119 | * @return parent_id - 父部门id 120 | */ 121 | public Integer getParentId() { 122 | return parentId; 123 | } 124 | 125 | /** 126 | * 设置父部门id 127 | * 128 | * @param parentId 父部门id 129 | */ 130 | public void setParentId(Integer parentId) { 131 | this.parentId = parentId; 132 | } 133 | 134 | /** 135 | * 获取部门名称 136 | * 137 | * @return dept_name - 部门名称 138 | */ 139 | public String getDeptName() { 140 | return deptName; 141 | } 142 | 143 | /** 144 | * 设置部门名称 145 | * 146 | * @param deptName 部门名称 147 | */ 148 | public void setDeptName(String deptName) { 149 | this.deptName = deptName; 150 | } 151 | 152 | /** 153 | * 获取显示顺序 154 | * 155 | * @return order_num - 显示顺序 156 | */ 157 | public Integer getOrderNum() { 158 | return orderNum; 159 | } 160 | 161 | /** 162 | * 设置显示顺序 163 | * 164 | * @param orderNum 显示顺序 165 | */ 166 | public void setOrderNum(Integer orderNum) { 167 | this.orderNum = orderNum; 168 | } 169 | 170 | /** 171 | * 获取负责人 172 | * 173 | * @return leader - 负责人 174 | */ 175 | public String getLeader() { 176 | return leader; 177 | } 178 | 179 | /** 180 | * 设置负责人 181 | * 182 | * @param leader 负责人 183 | */ 184 | public void setLeader(String leader) { 185 | this.leader = leader; 186 | } 187 | 188 | /** 189 | * 获取联系电话 190 | * 191 | * @return phone - 联系电话 192 | */ 193 | public String getPhone() { 194 | return phone; 195 | } 196 | 197 | /** 198 | * 设置联系电话 199 | * 200 | * @param phone 联系电话 201 | */ 202 | public void setPhone(String phone) { 203 | this.phone = phone; 204 | } 205 | 206 | /** 207 | * 获取邮箱 208 | * 209 | * @return email - 邮箱 210 | */ 211 | public String getEmail() { 212 | return email; 213 | } 214 | 215 | /** 216 | * 设置邮箱 217 | * 218 | * @param email 邮箱 219 | */ 220 | public void setEmail(String email) { 221 | this.email = email; 222 | } 223 | 224 | /** 225 | * 获取部门状态(0停用 1正常) 226 | * 227 | * @return status - 部门状态(0停用 1正常) 228 | */ 229 | public Integer getStatus() { 230 | return status; 231 | } 232 | 233 | /** 234 | * 设置部门状态(0停用 1正常) 235 | * 236 | * @param status 部门状态(0停用 1正常) 237 | */ 238 | public void setStatus(Integer status) { 239 | this.status = status; 240 | } 241 | 242 | /** 243 | * 获取创建者 244 | * 245 | * @return create_by - 创建者 246 | */ 247 | public String getCreateBy() { 248 | return createBy; 249 | } 250 | 251 | /** 252 | * 设置创建者 253 | * 254 | * @param createBy 创建者 255 | */ 256 | public void setCreateBy(String createBy) { 257 | this.createBy = createBy; 258 | } 259 | 260 | /** 261 | * 获取创建时间 262 | * 263 | * @return create_time - 创建时间 264 | */ 265 | public Date getCreateTime() { 266 | return createTime; 267 | } 268 | 269 | /** 270 | * 设置创建时间 271 | * 272 | * @param createTime 创建时间 273 | */ 274 | public void setCreateTime(Date createTime) { 275 | this.createTime = createTime; 276 | } 277 | 278 | /** 279 | * 获取更新者 280 | * 281 | * @return update_by - 更新者 282 | */ 283 | public String getUpdateBy() { 284 | return updateBy; 285 | } 286 | 287 | /** 288 | * 设置更新者 289 | * 290 | * @param updateBy 更新者 291 | */ 292 | public void setUpdateBy(String updateBy) { 293 | this.updateBy = updateBy; 294 | } 295 | 296 | /** 297 | * 获取更新时间 298 | * 299 | * @return update_time - 更新时间 300 | */ 301 | public Date getUpdateTime() { 302 | return updateTime; 303 | } 304 | 305 | /** 306 | * 设置更新时间 307 | * 308 | * @param updateTime 更新时间 309 | */ 310 | public void setUpdateTime(Date updateTime) { 311 | this.updateTime = updateTime; 312 | } 313 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/model/SysDictType.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.model; 2 | 3 | import java.util.Date; 4 | import javax.persistence.*; 5 | 6 | /** 7 | *

8 | * 字典类型表 9 | *

10 | * 11 | * @package: com.xkcoding.scaffold.model 12 | * @description: 字典类型表 13 | * @author: yangkai.shen 14 | * @date: Created in 2018/7/31 上午10:31 15 | * @copyright: Copyright (c) 2018 16 | * @version: V1.0 17 | * @modified: yangkai.shen 18 | */ 19 | @Table(name = "sys_dict_type") 20 | public class SysDictType { 21 | /** 22 | * 字典主键 23 | */ 24 | @Id 25 | @Column(name = "id") 26 | @GeneratedValue(generator = "JDBC") 27 | private Integer id; 28 | 29 | /** 30 | * 字典名称 31 | */ 32 | @Column(name = "dict_name") 33 | private String dictName; 34 | 35 | /** 36 | * 字典类型 37 | */ 38 | @Column(name = "dict_type") 39 | private String dictType; 40 | 41 | /** 42 | * 状态(0停用 1正常) 43 | */ 44 | @Column(name = "status") 45 | private Integer status; 46 | 47 | /** 48 | * 创建者 49 | */ 50 | @Column(name = "create_by") 51 | private String createBy; 52 | 53 | /** 54 | * 创建时间 55 | */ 56 | @Column(name = "create_time") 57 | private Date createTime; 58 | 59 | /** 60 | * 更新者 61 | */ 62 | @Column(name = "update_by") 63 | private String updateBy; 64 | 65 | /** 66 | * 更新时间 67 | */ 68 | @Column(name = "update_time") 69 | private Date updateTime; 70 | 71 | /** 72 | * 备注 73 | */ 74 | @Column(name = "remark") 75 | private String remark; 76 | 77 | /** 78 | * 获取字典主键 79 | * 80 | * @return id - 字典主键 81 | */ 82 | public Integer getId() { 83 | return id; 84 | } 85 | 86 | /** 87 | * 设置字典主键 88 | * 89 | * @param id 字典主键 90 | */ 91 | public void setId(Integer id) { 92 | this.id = id; 93 | } 94 | 95 | /** 96 | * 获取字典名称 97 | * 98 | * @return dict_name - 字典名称 99 | */ 100 | public String getDictName() { 101 | return dictName; 102 | } 103 | 104 | /** 105 | * 设置字典名称 106 | * 107 | * @param dictName 字典名称 108 | */ 109 | public void setDictName(String dictName) { 110 | this.dictName = dictName; 111 | } 112 | 113 | /** 114 | * 获取字典类型 115 | * 116 | * @return dict_type - 字典类型 117 | */ 118 | public String getDictType() { 119 | return dictType; 120 | } 121 | 122 | /** 123 | * 设置字典类型 124 | * 125 | * @param dictType 字典类型 126 | */ 127 | public void setDictType(String dictType) { 128 | this.dictType = dictType; 129 | } 130 | 131 | /** 132 | * 获取状态(0停用 1正常) 133 | * 134 | * @return status - 状态(0停用 1正常) 135 | */ 136 | public Integer getStatus() { 137 | return status; 138 | } 139 | 140 | /** 141 | * 设置状态(0停用 1正常) 142 | * 143 | * @param status 状态(0停用 1正常) 144 | */ 145 | public void setStatus(Integer status) { 146 | this.status = status; 147 | } 148 | 149 | /** 150 | * 获取创建者 151 | * 152 | * @return create_by - 创建者 153 | */ 154 | public String getCreateBy() { 155 | return createBy; 156 | } 157 | 158 | /** 159 | * 设置创建者 160 | * 161 | * @param createBy 创建者 162 | */ 163 | public void setCreateBy(String createBy) { 164 | this.createBy = createBy; 165 | } 166 | 167 | /** 168 | * 获取创建时间 169 | * 170 | * @return create_time - 创建时间 171 | */ 172 | public Date getCreateTime() { 173 | return createTime; 174 | } 175 | 176 | /** 177 | * 设置创建时间 178 | * 179 | * @param createTime 创建时间 180 | */ 181 | public void setCreateTime(Date createTime) { 182 | this.createTime = createTime; 183 | } 184 | 185 | /** 186 | * 获取更新者 187 | * 188 | * @return update_by - 更新者 189 | */ 190 | public String getUpdateBy() { 191 | return updateBy; 192 | } 193 | 194 | /** 195 | * 设置更新者 196 | * 197 | * @param updateBy 更新者 198 | */ 199 | public void setUpdateBy(String updateBy) { 200 | this.updateBy = updateBy; 201 | } 202 | 203 | /** 204 | * 获取更新时间 205 | * 206 | * @return update_time - 更新时间 207 | */ 208 | public Date getUpdateTime() { 209 | return updateTime; 210 | } 211 | 212 | /** 213 | * 设置更新时间 214 | * 215 | * @param updateTime 更新时间 216 | */ 217 | public void setUpdateTime(Date updateTime) { 218 | this.updateTime = updateTime; 219 | } 220 | 221 | /** 222 | * 获取备注 223 | * 224 | * @return remark - 备注 225 | */ 226 | public String getRemark() { 227 | return remark; 228 | } 229 | 230 | /** 231 | * 设置备注 232 | * 233 | * @param remark 备注 234 | */ 235 | public void setRemark(String remark) { 236 | this.remark = remark; 237 | } 238 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/model/SysLoginLog.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.model; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.GeneratedValue; 5 | import javax.persistence.Id; 6 | import javax.persistence.Table; 7 | import java.util.Date; 8 | 9 | /** 10 | *

11 | * 系统访问记录 12 | *

13 | * 14 | * @package: com.xkcoding.scaffold.model 15 | * @description: 系统访问记录 16 | * @author: yangkai.shen 17 | * @date: Created in 2018/7/31 上午10:33 18 | * @copyright: Copyright (c) 2018 19 | * @version: V1.0 20 | * @modified: yangkai.shen 21 | */ 22 | @Table(name = "sys_login_log") 23 | public class SysLoginLog { 24 | /** 25 | * 访问ID 26 | */ 27 | @Id 28 | @Column(name = "id") 29 | @GeneratedValue(generator = "JDBC") 30 | private Integer id; 31 | 32 | /** 33 | * 登录账号 34 | */ 35 | @Column(name = "login_name") 36 | private String loginName; 37 | 38 | /** 39 | * 登录IP地址 40 | */ 41 | @Column(name = "ip_address") 42 | private String ipAddress; 43 | 44 | /** 45 | * 登录地点 46 | */ 47 | @Column(name = "login_location") 48 | private String loginLocation; 49 | 50 | /** 51 | * 浏览器类型 52 | */ 53 | @Column(name = "browser") 54 | private String browser; 55 | 56 | /** 57 | * 操作系统 58 | */ 59 | @Column(name = "os") 60 | private String os; 61 | 62 | /** 63 | * 登录状态(0失败 1成功) 64 | */ 65 | @Column(name = "status") 66 | private Integer status; 67 | 68 | /** 69 | * 提示消息 70 | */ 71 | @Column(name = "msg") 72 | private String msg; 73 | 74 | /** 75 | * 访问时间 76 | */ 77 | @Column(name = "login_time") 78 | private Date loginTime; 79 | 80 | /** 81 | * 获取访问ID 82 | * 83 | * @return id - 访问ID 84 | */ 85 | public Integer getId() { 86 | return id; 87 | } 88 | 89 | /** 90 | * 设置访问ID 91 | * 92 | * @param id 访问ID 93 | */ 94 | public void setId(Integer id) { 95 | this.id = id; 96 | } 97 | 98 | /** 99 | * 获取登录账号 100 | * 101 | * @return login_name - 登录账号 102 | */ 103 | public String getLoginName() { 104 | return loginName; 105 | } 106 | 107 | /** 108 | * 设置登录账号 109 | * 110 | * @param loginName 登录账号 111 | */ 112 | public void setLoginName(String loginName) { 113 | this.loginName = loginName; 114 | } 115 | 116 | /** 117 | * 获取登录IP地址 118 | * 119 | * @return ip_address - 登录IP地址 120 | */ 121 | public String getIpAddress() { 122 | return ipAddress; 123 | } 124 | 125 | /** 126 | * 设置登录IP地址 127 | * 128 | * @param ipAddress 登录IP地址 129 | */ 130 | public void setIpAddress(String ipAddress) { 131 | this.ipAddress = ipAddress; 132 | } 133 | 134 | /** 135 | * 获取登录地点 136 | * 137 | * @return login_location - 登录地点 138 | */ 139 | public String getLoginLocation() { 140 | return loginLocation; 141 | } 142 | 143 | /** 144 | * 设置登录地点 145 | * 146 | * @param loginLocation 登录地点 147 | */ 148 | public void setLoginLocation(String loginLocation) { 149 | this.loginLocation = loginLocation; 150 | } 151 | 152 | /** 153 | * 获取浏览器类型 154 | * 155 | * @return browser - 浏览器类型 156 | */ 157 | public String getBrowser() { 158 | return browser; 159 | } 160 | 161 | /** 162 | * 设置浏览器类型 163 | * 164 | * @param browser 浏览器类型 165 | */ 166 | public void setBrowser(String browser) { 167 | this.browser = browser; 168 | } 169 | 170 | /** 171 | * 获取操作系统 172 | * 173 | * @return os - 操作系统 174 | */ 175 | public String getOs() { 176 | return os; 177 | } 178 | 179 | /** 180 | * 设置操作系统 181 | * 182 | * @param os 操作系统 183 | */ 184 | public void setOs(String os) { 185 | this.os = os; 186 | } 187 | 188 | /** 189 | * 获取登录状态(0失败 1成功) 190 | * 191 | * @return status - 登录状态(0失败 1成功) 192 | */ 193 | public Integer getStatus() { 194 | return status; 195 | } 196 | 197 | /** 198 | * 设置登录状态(0失败 1成功) 199 | * 200 | * @param status 登录状态(0失败 1成功) 201 | */ 202 | public void setStatus(Integer status) { 203 | this.status = status; 204 | } 205 | 206 | /** 207 | * 获取提示消息 208 | * 209 | * @return msg - 提示消息 210 | */ 211 | public String getMsg() { 212 | return msg; 213 | } 214 | 215 | /** 216 | * 设置提示消息 217 | * 218 | * @param msg 提示消息 219 | */ 220 | public void setMsg(String msg) { 221 | this.msg = msg; 222 | } 223 | 224 | /** 225 | * 获取访问时间 226 | * 227 | * @return login_time - 访问时间 228 | */ 229 | public Date getLoginTime() { 230 | return loginTime; 231 | } 232 | 233 | /** 234 | * 设置访问时间 235 | * 236 | * @param loginTime 访问时间 237 | */ 238 | public void setLoginTime(Date loginTime) { 239 | this.loginTime = loginTime; 240 | } 241 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/model/SysRoleMenu.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.model; 2 | 3 | import javax.persistence.*; 4 | 5 | /** 6 | *

7 | * 角色和菜单关联表 角色1-N菜单 8 | *

9 | * 10 | * @package: com.xkcoding.scaffold.model 11 | * @description: 角色和菜单关联表 角色1-N菜单 12 | * @author: yangkai.shen 13 | * @date: Created in 2018/7/31 上午10:34 14 | * @copyright: Copyright (c) 2018 15 | * @version: V1.0 16 | * @modified: yangkai.shen 17 | */ 18 | @Table(name = "sys_role_menu") 19 | public class SysRoleMenu { 20 | /** 21 | * 角色ID 22 | */ 23 | @Id 24 | @Column(name = "role_id") 25 | private Integer roleId; 26 | 27 | /** 28 | * 菜单ID 29 | */ 30 | @Id 31 | @Column(name = "menu_id") 32 | private Integer menuId; 33 | 34 | /** 35 | * 获取角色ID 36 | * 37 | * @return role_id - 角色ID 38 | */ 39 | public Integer getRoleId() { 40 | return roleId; 41 | } 42 | 43 | /** 44 | * 设置角色ID 45 | * 46 | * @param roleId 角色ID 47 | */ 48 | public void setRoleId(Integer roleId) { 49 | this.roleId = roleId; 50 | } 51 | 52 | /** 53 | * 获取菜单ID 54 | * 55 | * @return menu_id - 菜单ID 56 | */ 57 | public Integer getMenuId() { 58 | return menuId; 59 | } 60 | 61 | /** 62 | * 设置菜单ID 63 | * 64 | * @param menuId 菜单ID 65 | */ 66 | public void setMenuId(Integer menuId) { 67 | this.menuId = menuId; 68 | } 69 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/model/SysUserRole.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.model; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.Id; 5 | import javax.persistence.Table; 6 | 7 | /** 8 | *

9 | * 用户和角色关联表 用户N-1角色 10 | *

11 | * 12 | * @package: com.xkcoding.scaffold.model 13 | * @description: 用户和角色关联表 用户N-1角色 14 | * @author: yangkai.shen 15 | * @date: Created in 2018/7/31 上午10:35 16 | * @copyright: Copyright (c) 2018 17 | * @version: V1.0 18 | * @modified: yangkai.shen 19 | */ 20 | @Table(name = "sys_user_role") 21 | public class SysUserRole { 22 | /** 23 | * 用户ID 24 | */ 25 | @Id 26 | @Column(name = "user_id") 27 | private Integer userId; 28 | 29 | /** 30 | * 角色ID 31 | */ 32 | @Id 33 | @Column(name = "role_id") 34 | private Integer roleId; 35 | 36 | /** 37 | * 获取用户ID 38 | * 39 | * @return user_id - 用户ID 40 | */ 41 | public Integer getUserId() { 42 | return userId; 43 | } 44 | 45 | /** 46 | * 设置用户ID 47 | * 48 | * @param userId 用户ID 49 | */ 50 | public void setUserId(Integer userId) { 51 | this.userId = userId; 52 | } 53 | 54 | /** 55 | * 获取角色ID 56 | * 57 | * @return role_id - 角色ID 58 | */ 59 | public Integer getRoleId() { 60 | return roleId; 61 | } 62 | 63 | /** 64 | * 设置角色ID 65 | * 66 | * @param roleId 角色ID 67 | */ 68 | public void setRoleId(Integer roleId) { 69 | this.roleId = roleId; 70 | } 71 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/model/SysUserWork.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.model; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.Id; 5 | import javax.persistence.Table; 6 | 7 | /** 8 | *

9 | * 用户与岗位关联表 用户1-N岗位 10 | *

11 | * 12 | * @package: com.xkcoding.scaffold.model 13 | * @description: 用户与岗位关联表 用户1-N岗位 14 | * @author: yangkai.shen 15 | * @date: Created in 2018/7/31 上午10:35 16 | * @copyright: Copyright (c) 2018 17 | * @version: V1.0 18 | * @modified: yangkai.shen 19 | */ 20 | @Table(name = "sys_user_work") 21 | public class SysUserWork { 22 | /** 23 | * 用户ID 24 | */ 25 | @Id 26 | @Column(name = "user_id") 27 | private String userId; 28 | 29 | /** 30 | * 岗位ID 31 | */ 32 | @Id 33 | @Column(name = "work_id") 34 | private String workId; 35 | 36 | /** 37 | * 获取用户ID 38 | * 39 | * @return user_id - 用户ID 40 | */ 41 | public String getUserId() { 42 | return userId; 43 | } 44 | 45 | /** 46 | * 设置用户ID 47 | * 48 | * @param userId 用户ID 49 | */ 50 | public void setUserId(String userId) { 51 | this.userId = userId; 52 | } 53 | 54 | /** 55 | * 获取岗位ID 56 | * 57 | * @return work_id - 岗位ID 58 | */ 59 | public String getWorkId() { 60 | return workId; 61 | } 62 | 63 | /** 64 | * 设置岗位ID 65 | * 66 | * @param workId 岗位ID 67 | */ 68 | public void setWorkId(String workId) { 69 | this.workId = workId; 70 | } 71 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/model/SysWork.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.model; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.GeneratedValue; 5 | import javax.persistence.Id; 6 | import javax.persistence.Table; 7 | import java.util.Date; 8 | 9 | /** 10 | *

11 | * 岗位信息表 12 | *

13 | * 14 | * @package: com.xkcoding.scaffold.model 15 | * @description: 岗位信息表 16 | * @author: yangkai.shen 17 | * @date: Created in 2018/7/31 上午10:35 18 | * @copyright: Copyright (c) 2018 19 | * @version: V1.0 20 | * @modified: yangkai.shen 21 | */ 22 | @Table(name = "sys_work") 23 | public class SysWork { 24 | /** 25 | * 岗位ID 26 | */ 27 | @Id 28 | @Column(name = "id") 29 | @GeneratedValue(generator = "JDBC") 30 | private Integer id; 31 | 32 | /** 33 | * 岗位编码 34 | */ 35 | @Column(name = "job_code") 36 | private String jobCode; 37 | 38 | /** 39 | * 岗位名称 40 | */ 41 | @Column(name = "job_name") 42 | private String jobName; 43 | 44 | /** 45 | * 显示顺序 46 | */ 47 | @Column(name = "job_sort") 48 | private Integer jobSort; 49 | 50 | /** 51 | * 状态(0停用 1正常) 52 | */ 53 | @Column(name = "status") 54 | private Integer status; 55 | 56 | /** 57 | * 创建者 58 | */ 59 | @Column(name = "create_by") 60 | private String createBy; 61 | 62 | /** 63 | * 创建时间 64 | */ 65 | @Column(name = "create_time") 66 | private Date createTime; 67 | 68 | /** 69 | * 更新者 70 | */ 71 | @Column(name = "update_by") 72 | private String updateBy; 73 | 74 | /** 75 | * 更新时间 76 | */ 77 | @Column(name = "update_time") 78 | private Date updateTime; 79 | 80 | /** 81 | * 备注 82 | */ 83 | @Column(name = "remark") 84 | private String remark; 85 | 86 | /** 87 | * 获取岗位ID 88 | * 89 | * @return id - 岗位ID 90 | */ 91 | public Integer getId() { 92 | return id; 93 | } 94 | 95 | /** 96 | * 设置岗位ID 97 | * 98 | * @param id 岗位ID 99 | */ 100 | public void setId(Integer id) { 101 | this.id = id; 102 | } 103 | 104 | /** 105 | * 获取岗位编码 106 | * 107 | * @return job_code - 岗位编码 108 | */ 109 | public String getJobCode() { 110 | return jobCode; 111 | } 112 | 113 | /** 114 | * 设置岗位编码 115 | * 116 | * @param jobCode 岗位编码 117 | */ 118 | public void setJobCode(String jobCode) { 119 | this.jobCode = jobCode; 120 | } 121 | 122 | /** 123 | * 获取岗位名称 124 | * 125 | * @return job_name - 岗位名称 126 | */ 127 | public String getJobName() { 128 | return jobName; 129 | } 130 | 131 | /** 132 | * 设置岗位名称 133 | * 134 | * @param jobName 岗位名称 135 | */ 136 | public void setJobName(String jobName) { 137 | this.jobName = jobName; 138 | } 139 | 140 | /** 141 | * 获取显示顺序 142 | * 143 | * @return job_sort - 显示顺序 144 | */ 145 | public Integer getJobSort() { 146 | return jobSort; 147 | } 148 | 149 | /** 150 | * 设置显示顺序 151 | * 152 | * @param jobSort 显示顺序 153 | */ 154 | public void setJobSort(Integer jobSort) { 155 | this.jobSort = jobSort; 156 | } 157 | 158 | /** 159 | * 获取状态(0停用 1正常) 160 | * 161 | * @return status - 状态(0停用 1正常) 162 | */ 163 | public Integer getStatus() { 164 | return status; 165 | } 166 | 167 | /** 168 | * 设置状态(0停用 1正常) 169 | * 170 | * @param status 状态(0停用 1正常) 171 | */ 172 | public void setStatus(Integer status) { 173 | this.status = status; 174 | } 175 | 176 | /** 177 | * 获取创建者 178 | * 179 | * @return create_by - 创建者 180 | */ 181 | public String getCreateBy() { 182 | return createBy; 183 | } 184 | 185 | /** 186 | * 设置创建者 187 | * 188 | * @param createBy 创建者 189 | */ 190 | public void setCreateBy(String createBy) { 191 | this.createBy = createBy; 192 | } 193 | 194 | /** 195 | * 获取创建时间 196 | * 197 | * @return create_time - 创建时间 198 | */ 199 | public Date getCreateTime() { 200 | return createTime; 201 | } 202 | 203 | /** 204 | * 设置创建时间 205 | * 206 | * @param createTime 创建时间 207 | */ 208 | public void setCreateTime(Date createTime) { 209 | this.createTime = createTime; 210 | } 211 | 212 | /** 213 | * 获取更新者 214 | * 215 | * @return update_by - 更新者 216 | */ 217 | public String getUpdateBy() { 218 | return updateBy; 219 | } 220 | 221 | /** 222 | * 设置更新者 223 | * 224 | * @param updateBy 更新者 225 | */ 226 | public void setUpdateBy(String updateBy) { 227 | this.updateBy = updateBy; 228 | } 229 | 230 | /** 231 | * 获取更新时间 232 | * 233 | * @return update_time - 更新时间 234 | */ 235 | public Date getUpdateTime() { 236 | return updateTime; 237 | } 238 | 239 | /** 240 | * 设置更新时间 241 | * 242 | * @param updateTime 更新时间 243 | */ 244 | public void setUpdateTime(Date updateTime) { 245 | this.updateTime = updateTime; 246 | } 247 | 248 | /** 249 | * 获取备注 250 | * 251 | * @return remark - 备注 252 | */ 253 | public String getRemark() { 254 | return remark; 255 | } 256 | 257 | /** 258 | * 设置备注 259 | * 260 | * @param remark 备注 261 | */ 262 | public void setRemark(String remark) { 263 | this.remark = remark; 264 | } 265 | } -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/model/dto/SysMenuDTO.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.model.dto; 2 | 3 | import lombok.Data; 4 | 5 | import javax.persistence.Column; 6 | import java.util.Date; 7 | 8 | /** 9 | *

10 | * 菜单 DTO 11 | *

12 | * 13 | * @package: com.xkcoding.scaffold.model.dto 14 | * @description: 菜单 DTO 15 | * @author: yangkai.shen 16 | * @date: Created in 2018/8/17 上午10:39 17 | * @copyright: Copyright (c) 2018 18 | * @version: V1.0 19 | * @modified: yangkai.shen 20 | */ 21 | @Data 22 | public class SysMenuDTO { 23 | /** 24 | * 菜单ID 25 | */ 26 | private Integer id; 27 | 28 | /** 29 | * 菜单名称 30 | */ 31 | private String menuName; 32 | 33 | /** 34 | * 父菜单ID 35 | */ 36 | private Integer parentId; 37 | 38 | /** 39 | * 显示顺序 40 | */ 41 | private Integer orderNum; 42 | 43 | /** 44 | * 请求地址 45 | */ 46 | private String url; 47 | 48 | /** 49 | * 菜单类型(0目录 1菜单 2按钮) 50 | */ 51 | private Integer menuType; 52 | 53 | /** 54 | * 菜单状态(0隐藏 1显示) 55 | */ 56 | private Integer visible; 57 | 58 | /** 59 | * vue路由 60 | */ 61 | @Column(name = "path") 62 | private String path; 63 | 64 | /** 65 | * vue组件 66 | */ 67 | @Column(name = "component") 68 | private String component; 69 | 70 | /** 71 | * 菜单图标 72 | */ 73 | private String icon; 74 | 75 | /** 76 | * 创建者 77 | */ 78 | private String createBy; 79 | 80 | /** 81 | * 创建时间 82 | */ 83 | private Date createTime; 84 | 85 | /** 86 | * 更新者 87 | */ 88 | private String updateBy; 89 | 90 | /** 91 | * 更新时间 92 | */ 93 | private Date updateTime; 94 | 95 | /** 96 | * 备注 97 | */ 98 | private String remark; 99 | 100 | /** 101 | * 角色Id列表字符串 102 | */ 103 | private String roleId; 104 | 105 | /** 106 | * 角色名称列表字符串 107 | */ 108 | private String roleName; 109 | 110 | /** 111 | * 角色键列表字符串 112 | */ 113 | private String roleKey; 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/model/dto/SysUserDTO.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.model.dto; 2 | 3 | import cn.hutool.core.util.ObjectUtil; 4 | import cn.hutool.core.util.StrUtil; 5 | import com.google.common.base.Objects; 6 | import com.google.common.collect.Sets; 7 | import com.xkcoding.scaffold.common.status.DeleteStatus; 8 | import com.xkcoding.scaffold.common.status.UserStatus; 9 | import com.xkcoding.scaffold.model.SysMenu; 10 | import com.xkcoding.scaffold.model.SysRole; 11 | import com.xkcoding.scaffold.util.EnumUtil; 12 | import lombok.Data; 13 | import org.springframework.security.core.GrantedAuthority; 14 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 15 | import org.springframework.security.core.userdetails.UserDetails; 16 | 17 | import java.util.Collection; 18 | import java.util.Date; 19 | import java.util.Set; 20 | 21 | /** 22 | *

23 | * 用户 DTO 24 | *

25 | * 26 | * @package: com.xkcoding.scaffold.model.dto 27 | * @description: 用户 DTO 28 | * @author: yangkai.shen 29 | * @date: Created in 2018/8/8 上午10:18 30 | * @copyright: Copyright (c) 2018 31 | * @version: V1.0 32 | * @modified: yangkai.shen 33 | */ 34 | @Data 35 | public class SysUserDTO implements UserDetails { 36 | /** 37 | * 用户ID 38 | */ 39 | private Integer id; 40 | 41 | /** 42 | * 部门ID 43 | */ 44 | private Integer deptId; 45 | 46 | /** 47 | * 登录账号 48 | */ 49 | private String loginName; 50 | 51 | /** 52 | * 用户昵称 53 | */ 54 | private String userName; 55 | 56 | /** 57 | * 用户类型(00系统用户) 58 | */ 59 | private String userType; 60 | 61 | /** 62 | * 用户邮箱 63 | */ 64 | private String email; 65 | 66 | /** 67 | * 手机号码 68 | */ 69 | private String phonenumber; 70 | 71 | /** 72 | * 用户性别(0男 1女 2未知) 73 | */ 74 | private Integer sex; 75 | 76 | /** 77 | * 头像路径 78 | */ 79 | private String avatar; 80 | 81 | /** 82 | * 密码 83 | */ 84 | private String password; 85 | 86 | /** 87 | * 帐号状态(0停用 1正常) 88 | */ 89 | private Integer status; 90 | 91 | /** 92 | * 删除标志(0代表存在 1代表删除) 93 | */ 94 | private Integer delFlag; 95 | 96 | /** 97 | * 最后登陆IP 98 | */ 99 | private String loginIp; 100 | 101 | /** 102 | * 最后登陆时间 103 | */ 104 | private Date loginDate; 105 | 106 | /** 107 | * 创建者 108 | */ 109 | private String createBy; 110 | 111 | /** 112 | * 创建时间 113 | */ 114 | private Date createTime; 115 | 116 | /** 117 | * 更新者 118 | */ 119 | private String updateBy; 120 | 121 | /** 122 | * 更新时间 123 | */ 124 | private Date updateTime; 125 | 126 | /** 127 | * 备注 128 | */ 129 | private String remark; 130 | 131 | /** 132 | * 角色列表 133 | */ 134 | private Set roles; 135 | 136 | /** 137 | * 菜单列表 138 | */ 139 | private Set menus; 140 | 141 | /** 142 | * 权限列表 143 | */ 144 | @Override 145 | public Collection getAuthorities() { 146 | Set authorities = Sets.newHashSet(); 147 | for (SysRole role : roles) { 148 | if (StrUtil.isNotBlank(role.getRoleKey())) { 149 | authorities.add(new SimpleGrantedAuthority("ROLE_" + StrUtil.trim(role.getRoleKey()))); 150 | } 151 | } 152 | return authorities; 153 | } 154 | 155 | @Override 156 | public String getPassword() { 157 | return password; 158 | } 159 | 160 | @Override 161 | public String getUsername() { 162 | return loginName; 163 | } 164 | 165 | /** 166 | * 账户是否未过期 167 | */ 168 | @Override 169 | public boolean isAccountNonExpired() { 170 | return true; 171 | } 172 | 173 | /** 174 | * 账户是否未锁定 175 | */ 176 | @Override 177 | public boolean isAccountNonLocked() { 178 | UserStatus userStatus = EnumUtil.getStatusByCode(status, UserStatus.class); 179 | return ObjectUtil.equal(userStatus, UserStatus.ENABLE); 180 | } 181 | 182 | /** 183 | * 密码是否未过期 184 | */ 185 | @Override 186 | public boolean isCredentialsNonExpired() { 187 | return true; 188 | } 189 | 190 | /** 191 | * 账户是否可用 192 | */ 193 | @Override 194 | public boolean isEnabled() { 195 | DeleteStatus deleteStatus = EnumUtil.getStatusByCode(delFlag, DeleteStatus.class); 196 | return ObjectUtil.equal(deleteStatus, DeleteStatus.NOT_DELETED); 197 | } 198 | 199 | @Override 200 | public boolean equals(Object o) { 201 | if (this == o) { 202 | return true; 203 | } 204 | if (!(o instanceof SysUserDTO)) { 205 | return false; 206 | } 207 | SysUserDTO that = (SysUserDTO) o; 208 | return Objects.equal(getId(), that.getId()) && Objects.equal(getDeptId(), that.getDeptId()) && Objects.equal(getLoginName(), that 209 | .getLoginName()) && Objects.equal(userName, that.userName) && Objects.equal(getUserType(), that.getUserType()) && Objects 210 | .equal(getEmail(), that.getEmail()) && Objects.equal(getPhonenumber(), that.getPhonenumber()) && Objects 211 | .equal(getSex(), that.getSex()) && Objects.equal(getAvatar(), that.getAvatar()) && Objects.equal(getPassword(), that 212 | .getPassword()) && Objects.equal(getStatus(), that.getStatus()) && Objects.equal(getDelFlag(), that.getDelFlag()) && Objects 213 | .equal(getLoginIp(), that.getLoginIp()) && Objects.equal(getLoginDate(), that.getLoginDate()) && Objects 214 | .equal(getCreateBy(), that.getCreateBy()) && Objects.equal(getCreateTime(), that.getCreateTime()) && Objects 215 | .equal(getUpdateBy(), that.getUpdateBy()) && Objects.equal(getUpdateTime(), that.getUpdateTime()) && Objects 216 | .equal(getRemark(), that.getRemark()); 217 | } 218 | 219 | @Override 220 | public int hashCode() { 221 | return Objects.hashCode(getId(), getDeptId(), getLoginName(), userName, getUserType(), getEmail(), getPhonenumber(), getSex(), getAvatar(), getPassword(), getStatus(), getDelFlag(), getLoginIp(), getLoginDate(), getCreateBy(), getCreateTime(), getUpdateBy(), getUpdateTime(), getRemark()); 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/service/SysMenuService.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.service; 2 | 3 | import com.xkcoding.scaffold.model.SysMenu; 4 | import com.xkcoding.scaffold.model.SysRole; 5 | import com.xkcoding.scaffold.model.dto.SysMenuDTO; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | *

11 | * 系统菜单 Service 12 | *

13 | * 14 | * @package: com.xkcoding.scaffold.service 15 | * @description: 系统菜单 Service 16 | * @author: yangkai.shen 17 | * @date: Created in 2018/8/8 下午4:37 18 | * @copyright: Copyright (c) 2018 19 | * @version: V1.0 20 | * @modified: yangkai.shen 21 | */ 22 | public interface SysMenuService { 23 | 24 | /** 25 | * 根据角色 id 获取菜单列表 26 | * 27 | * @param roleId 角色 id 28 | * @return 菜单列表 29 | */ 30 | List listSysMenusByRoleId(Integer roleId); 31 | 32 | /** 33 | * 根据角色列表获取菜单列表 34 | * 35 | * @param roleList 角色列表 36 | * @return 菜单列表 37 | */ 38 | List listSysMenusByRoleList(List roleList); 39 | 40 | /** 41 | * 菜单列表 包含权限基础信息 42 | * 43 | * @param visible 菜单是否可见 44 | * @return 菜单列表 45 | */ 46 | List listAllSysMenu(Integer visible); 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/service/SysOperationLogService.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.service; 2 | 3 | import com.xkcoding.scaffold.model.SysOperationLog; 4 | 5 | /** 6 | *

7 | * 系统操作日志接口 8 | *

9 | * 10 | * @package: com.xkcoding.scaffold.service 11 | * @description: 系统操作日志接口 12 | * @author: yangkai.shen 13 | * @date: Created in 2018/8/6 下午5:42 14 | * @copyright: Copyright (c) 2018 15 | * @version: V1.0 16 | * @modified: yangkai.shen 17 | */ 18 | public interface SysOperationLogService { 19 | /** 20 | * 新增一条操作记录 21 | * 22 | * @param operationLog 操作记录对象 23 | */ 24 | void insert(SysOperationLog operationLog); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/service/SysRoleService.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.service; 2 | 3 | import com.xkcoding.scaffold.model.SysRole; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | *

9 | * 系统角色 Service 10 | *

11 | * 12 | * @package: com.xkcoding.scaffold.service 13 | * @description: 系统角色 Service 14 | * @author: yangkai.shen 15 | * @date: Created in 2018/8/8 下午4:37 16 | * @copyright: Copyright (c) 2018 17 | * @version: V1.0 18 | * @modified: yangkai.shen 19 | */ 20 | public interface SysRoleService { 21 | 22 | /** 23 | * 根据用户 id 获取角色列表 24 | * 25 | * @param userId 用户 id 26 | * @return 角色列表 27 | */ 28 | List listSysRolesByUserId(Integer userId); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/service/SysUserService.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.service; 2 | 3 | import com.xkcoding.scaffold.model.SysUser; 4 | 5 | /** 6 | *

7 | * 系统用户 Service 8 | *

9 | * 10 | * @package: com.xkcoding.scaffold.service 11 | * @description: 系统用户 Service 12 | * @author: yangkai.shen 13 | * @date: Created in 2018/8/8 下午3:49 14 | * @copyright: Copyright (c) 2018 15 | * @version: V1.0 16 | * @modified: yangkai.shen 17 | */ 18 | public interface SysUserService { 19 | 20 | /** 21 | * 根据用户名(登录名)获取用户信息 22 | * 23 | * @param loginName 登录名 24 | * @return 用户对象 25 | */ 26 | SysUser getUserByLoginName(String loginName); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/service/impl/SysMenuServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.service.impl; 2 | 3 | import cn.hutool.core.collection.CollUtil; 4 | import com.google.common.collect.Lists; 5 | import com.xkcoding.scaffold.mapper.SysMenuMapper; 6 | import com.xkcoding.scaffold.mapper.SysRoleMenuMapper; 7 | import com.xkcoding.scaffold.model.SysMenu; 8 | import com.xkcoding.scaffold.model.SysRole; 9 | import com.xkcoding.scaffold.model.SysRoleMenu; 10 | import com.xkcoding.scaffold.model.dto.SysMenuDTO; 11 | import com.xkcoding.scaffold.service.SysMenuService; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Service; 14 | 15 | import java.util.List; 16 | import java.util.stream.Collectors; 17 | 18 | /** 19 | *

20 | * 系统菜单 Service 21 | *

22 | * 23 | * @package: com.xkcoding.scaffold.service.impl 24 | * @description: 系统菜单 Service 25 | * @author: yangkai.shen 26 | * @date: Created in 2018/8/8 下午5:09 27 | * @copyright: Copyright (c) 2018 28 | * @version: V1.0 29 | * @modified: yangkai.shen 30 | */ 31 | @Service 32 | public class SysMenuServiceImpl implements SysMenuService { 33 | @Autowired 34 | private SysMenuMapper sysMenuMapper; 35 | 36 | @Autowired 37 | private SysRoleMenuMapper sysRoleMenuMapper; 38 | 39 | /** 40 | * 根据角色 id 获取菜单列表 41 | * 42 | * @param roleId 角色 id 43 | * @return 菜单列表 44 | */ 45 | @Override 46 | public List listSysMenusByRoleId(Integer roleId) { 47 | // 根据 roleId 查 menu-role 的对应关系 48 | SysRoleMenu query = new SysRoleMenu(); 49 | query.setRoleId(roleId); 50 | List relations = sysRoleMenuMapper.select(query); 51 | 52 | // 根据对应关系,获取角色 id 列表,查询所有role 53 | return getMenusByRelations(relations); 54 | } 55 | 56 | /** 57 | * 根据角色列表获取菜单列表 58 | * 59 | * @param roleList 角色列表 60 | * @return 菜单列表 61 | */ 62 | @Override 63 | public List listSysMenusByRoleList(List roleList) { 64 | List roleIdList = roleList.stream().map(SysRole::getId).collect(Collectors.toList()); 65 | 66 | // 根据角色 id 列表查询 menu-role 的对应关系 67 | List relations = Lists.newArrayList(); 68 | if (CollUtil.isNotEmpty(roleIdList)) { 69 | relations.addAll(sysRoleMenuMapper.selectSysRoleMenuByRoleIdList(roleIdList)); 70 | } 71 | 72 | // 根据对应关系,获取角色 id 列表,查询所有role 73 | return getMenusByRelations(relations); 74 | } 75 | 76 | /** 77 | * 菜单列表 包含权限基础信息 78 | * 79 | * @param visible 菜单是否可见 80 | * @return 菜单列表 81 | */ 82 | @Override 83 | public List listAllSysMenu(Integer visible) { 84 | return sysMenuMapper.selectSysMenuList(visible); 85 | } 86 | 87 | /** 88 | * 根据 role-menu 的对应关系获取菜单列表 89 | * 90 | * @param relations 对应关系 91 | * @return 菜单列表 92 | */ 93 | private List getMenusByRelations(List relations) { 94 | if (CollUtil.isEmpty(relations)) { 95 | return Lists.newArrayList(); 96 | } 97 | // 根据对应关系,获取角色 id 列表,查询所有role 98 | List menuIdList = relations.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList()); 99 | return sysMenuMapper.selectSysMenuByRoleList(menuIdList); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/service/impl/SysOperationLogServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.service.impl; 2 | 3 | import com.xkcoding.scaffold.mapper.SysOperationLogMapper; 4 | import com.xkcoding.scaffold.model.SysOperationLog; 5 | import com.xkcoding.scaffold.service.SysOperationLogService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | *

11 | * 系统操作日志接口 12 | *

13 | * 14 | * @package: com.xkcoding.scaffold.service.impl 15 | * @description: 系统操作日志接口 16 | * @author: yangkai.shen 17 | * @date: Created in 2018/8/6 下午5:44 18 | * @copyright: Copyright (c) 2018 19 | * @version: V1.0 20 | * @modified: yangkai.shen 21 | */ 22 | @Service 23 | public class SysOperationLogServiceImpl implements SysOperationLogService { 24 | @Autowired 25 | private SysOperationLogMapper sysOperationLogMapper; 26 | 27 | /** 28 | * 新增一条操作记录 29 | * 30 | * @param operationLog 操作记录对象 31 | */ 32 | @Override 33 | public void insert(SysOperationLog operationLog) { 34 | sysOperationLogMapper.insertUseGeneratedKeys(operationLog); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/service/impl/SysRoleServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.service.impl; 2 | 3 | import com.xkcoding.scaffold.mapper.SysRoleMapper; 4 | import com.xkcoding.scaffold.mapper.SysUserRoleMapper; 5 | import com.xkcoding.scaffold.model.SysRole; 6 | import com.xkcoding.scaffold.model.SysUserRole; 7 | import com.xkcoding.scaffold.service.SysRoleService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | 11 | import java.util.List; 12 | import java.util.stream.Collectors; 13 | 14 | /** 15 | *

16 | * 系统角色 Service 17 | *

18 | * 19 | * @package: com.xkcoding.scaffold.service.impl 20 | * @description: 系统角色 Service 21 | * @author: yangkai.shen 22 | * @date: Created in 2018/8/8 下午4:43 23 | * @copyright: Copyright (c) 2018 24 | * @version: V1.0 25 | * @modified: yangkai.shen 26 | */ 27 | @Service 28 | public class SysRoleServiceImpl implements SysRoleService { 29 | @Autowired 30 | private SysRoleMapper sysRoleMapper; 31 | 32 | @Autowired 33 | private SysUserRoleMapper sysUserRoleMapper; 34 | 35 | /** 36 | * 根据用户 id 获取角色列表 37 | * 38 | * @param userId 用户 id 39 | * @return 角色列表 40 | */ 41 | @Override 42 | public List listSysRolesByUserId(Integer userId) { 43 | // 根据 userId 查 user-role 的对应关系 44 | SysUserRole query = new SysUserRole(); 45 | query.setUserId(userId); 46 | List relations = sysUserRoleMapper.select(query); 47 | 48 | // 根据对应关系,获取角色 id 列表,查询所有role 49 | List roleIdList = relations.stream().map(SysUserRole::getRoleId).collect(Collectors.toList()); 50 | List sysRoleList = sysRoleMapper.selectSysRoleByRoleList(roleIdList); 51 | 52 | return sysRoleList; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/service/impl/SysUserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.service.impl; 2 | 3 | import com.xkcoding.scaffold.mapper.SysUserMapper; 4 | import com.xkcoding.scaffold.model.SysUser; 5 | import com.xkcoding.scaffold.service.SysUserService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | *

11 | * 系统用户 Service 12 | *

13 | * 14 | * @package: com.xkcoding.scaffold.service.impl 15 | * @description: 系统用户 Service 16 | * @author: yangkai.shen 17 | * @date: Created in 2018/8/8 下午3:53 18 | * @copyright: Copyright (c) 2018 19 | * @version: V1.0 20 | * @modified: yangkai.shen 21 | */ 22 | @Service 23 | public class SysUserServiceImpl implements SysUserService { 24 | @Autowired 25 | private SysUserMapper sysUserMapper; 26 | 27 | /** 28 | * 根据用户名(登录名)获取用户信息 29 | * 30 | * @param loginName 登录名 31 | * @return 用户对象 32 | */ 33 | @Override 34 | public SysUser getUserByLoginName(String loginName) { 35 | SysUser query = new SysUser(); 36 | query.setLoginName(loginName); 37 | return sysUserMapper.selectOne(query); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/util/EnumUtil.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.util; 2 | 3 | import com.xkcoding.scaffold.common.BaseEnum; 4 | 5 | /** 6 | *

7 | * 状态工具类 8 | *

9 | * 10 | * @package: com.xkcoding.scaffold.util 11 | * @description: 状态工具类 12 | * @author: yangkai.shen 13 | * @date: Created in 2018/8/8 上午10:25 14 | * @copyright: Copyright (c) 2018 15 | * @version: V1.0 16 | * @modified: yangkai.shen 17 | */ 18 | public class EnumUtil { 19 | 20 | /** 21 | * 根据状态码获取状态枚举 22 | * 23 | * @param code 状态码 24 | * @param enumClass 枚举类 25 | * @param 泛型 {@link BaseEnum} 26 | * @return 状态枚举 27 | */ 28 | public static T getStatusByCode(Integer code, Class enumClass) { 29 | for (T each : enumClass.getEnumConstants()) { 30 | if (code.equals(each.getCode())) { 31 | return each; 32 | } 33 | } 34 | return null; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/util/Ip2AddressUtil.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.util; 2 | 3 | import cn.hutool.core.io.resource.ResourceUtil; 4 | import cn.hutool.core.util.ObjectUtil; 5 | import cn.hutool.core.util.StrUtil; 6 | import cn.hutool.http.HttpUtil; 7 | import cn.hutool.json.JSONObject; 8 | import cn.hutool.json.JSONUtil; 9 | import com.google.common.base.Joiner; 10 | import com.google.common.base.Splitter; 11 | import com.google.common.collect.Lists; 12 | import com.google.common.collect.Maps; 13 | import lombok.extern.slf4j.Slf4j; 14 | import org.lionsoul.ip2region.DataBlock; 15 | import org.lionsoul.ip2region.DbConfig; 16 | import org.lionsoul.ip2region.DbSearcher; 17 | import org.lionsoul.ip2region.Util; 18 | 19 | import java.util.List; 20 | import java.util.Map; 21 | import java.util.stream.Collectors; 22 | 23 | /** 24 | *

25 | * 根据 IP 进行地理位置转换 26 | *

27 | * 28 | * @package: com.xkcoding.scaffold.util 29 | * @description: 根据 IP 进行地理位置转换 30 | * @author: yangkai.shen 31 | * @date: Created in 2018/8/9 下午4:46 32 | * @copyright: Copyright (c) 2018 33 | * @version: V1.0 34 | * @modified: yangkai.shen 35 | */ 36 | @Slf4j 37 | public class Ip2AddressUtil { 38 | 39 | /** 40 | * 淘宝在线 IP 地址库 41 | */ 42 | public static final String IP_URL = "http://ip.taobao.com/service/getIpInfo.php"; 43 | 44 | /** 45 | * 利用 ip2region 库进行 IP 地理位置转换 46 | * 47 | * @param ip IP地址 48 | * @return 地址信息 49 | */ 50 | public static String getAddressInLocal(String ip) { 51 | if (StrUtil.equals(ip, IpUtil.LOCAL_INNER_LOOP_IP)) { 52 | ip = IpUtil.LOCAL_IP; 53 | } 54 | String address = ""; 55 | boolean ipAddress = Util.isIpAddress(ip); 56 | if (!ipAddress) { 57 | return address; 58 | } 59 | try { 60 | DbConfig config = new DbConfig(); 61 | DbSearcher searcher = new DbSearcher(config, ResourceUtil.getResource("ip/ip2region.db").getFile()); 62 | DataBlock dataBlock = searcher.memorySearch(ip); 63 | 64 | // dataBlock格式:城市Id|国家|区域|省份|城市|ISP 65 | // region格式:国家|区域|省份|城市|ISP 66 | // region例如:中国|0|浙江省|杭州市|电信 67 | String region = dataBlock.getRegion(); 68 | 69 | // 按 | 切分 70 | List regionList = Splitter.on("|").splitToList(region); 71 | // 过滤为 0 的数据 72 | List regionListFilter = regionList.stream() 73 | .filter(s -> !StrUtil.equals("0", s)) 74 | .distinct() 75 | .collect(Collectors.toList()); 76 | // 再用 | 拼接回来 77 | address = Joiner.on("|").join(regionListFilter); 78 | } catch (Exception e) { 79 | log.error("【获取地理位置】发生异常:", e); 80 | } 81 | return address; 82 | } 83 | 84 | /** 85 | * 利用淘宝在线 ip 地址库进行 IP 地理位置转换 86 | * 87 | * @param ip IP地址 88 | * @return 地址信息 89 | */ 90 | public static String getAddressOnNetByTaoBao(String ip) { 91 | String address = ""; 92 | try { 93 | // 发请求 94 | Map params = Maps.newHashMap(); 95 | params.put("ip", ip); 96 | String ret = HttpUtil.get(IP_URL, params, 2000); 97 | 98 | JSONObject json = JSONUtil.parseObj(ret); 99 | Integer code = json.getInt("code"); 100 | if (ObjectUtil.equal(code, 0)) { 101 | JSONObject data = json.getJSONObject("data"); 102 | // 国家|区域|省份|城市|ISP 103 | String country = data.getStr("country"); 104 | String area = data.getStr("area"); 105 | String region = data.getStr("region"); 106 | String city = data.getStr("city"); 107 | String isp = data.getStr("isp"); 108 | 109 | List addressInfo = Lists.newArrayList(country, area, region, city, isp); 110 | // 过滤为 XX 以及为空的数据 111 | List addressInfoFilter = addressInfo.stream() 112 | .filter(s -> StrUtil.isNotBlank(s) && !StrUtil.equals("XX", s)) 113 | .distinct() 114 | .collect(Collectors.toList()); 115 | // 用 | 拼接回来 116 | address = Joiner.on("|").join(addressInfoFilter); 117 | } 118 | } catch (Exception e) { 119 | log.error("【获取地理位置】发生异常:", e); 120 | } 121 | return address; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/util/IpUtil.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.util; 2 | 3 | import cn.hutool.core.lang.Validator; 4 | import cn.hutool.core.util.StrUtil; 5 | import lombok.extern.slf4j.Slf4j; 6 | 7 | import javax.servlet.http.HttpServletRequest; 8 | import java.net.InetAddress; 9 | import java.net.UnknownHostException; 10 | 11 | /** 12 | *

13 | * IP 工具类 14 | *

15 | * 16 | * @package: com.xkcoding.scaffold.util 17 | * @description: IP 工具类 18 | * @author: yangkai.shen 19 | * @date: Created in 2018/8/10 下午4:59 20 | * @copyright: Copyright (c) 2018 21 | * @version: V1.0 22 | * @modified: yangkai.shen 23 | */ 24 | @Slf4j 25 | public class IpUtil { 26 | 27 | /** 28 | * 本机回环地址 29 | */ 30 | public static final String LOCAL_INNER_LOOP_IP = "0:0:0:0:0:0:0:1"; 31 | 32 | /** 33 | * 本机IP地址 34 | */ 35 | public static final String LOCAL_IP = "127.0.0.1"; 36 | 37 | /** 38 | * 取外网IP 39 | */ 40 | public static String getRemoteIp(HttpServletRequest request) { 41 | String ip = request.getHeader("x-real-ip"); 42 | if (ip == null) { 43 | ip = request.getRemoteAddr(); 44 | } 45 | 46 | //过滤反向代理的ip 47 | String[] stemps = ip.split(","); 48 | if (stemps != null && stemps.length >= 1) { 49 | //得到第一个IP,即客户端真实IP 50 | ip = stemps[0]; 51 | } 52 | 53 | ip = ip.trim(); 54 | if (ip.length() > 23) { 55 | ip = ip.substring(0, 23); 56 | } 57 | 58 | return ip; 59 | } 60 | 61 | /** 62 | * 获取用户的真实ip 63 | */ 64 | public static String getUserIP(HttpServletRequest request) { 65 | 66 | // 优先取X-Real-IP 67 | String ip = request.getHeader("X-Real-IP"); 68 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 69 | ip = request.getHeader("x-forwarded-for"); 70 | } 71 | 72 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 73 | ip = request.getRemoteAddr(); 74 | if (LOCAL_INNER_LOOP_IP.equals(ip)) { 75 | ip = LOCAL_IP; 76 | } 77 | } 78 | 79 | if ("unknown".equalsIgnoreCase(ip)) { 80 | ip = LOCAL_IP; 81 | return ip; 82 | } 83 | 84 | int pos = ip.indexOf(','); 85 | if (pos >= 0) { 86 | ip = ip.substring(0, pos); 87 | } 88 | 89 | return ip; 90 | } 91 | 92 | public static String getLastIpSegment(HttpServletRequest request) { 93 | String ip = getUserIP(request); 94 | if (ip != null) { 95 | ip = ip.substring(ip.lastIndexOf('.') + 1); 96 | } else { 97 | ip = "0"; 98 | } 99 | return ip; 100 | } 101 | 102 | public static boolean isValidIP(HttpServletRequest request) { 103 | String ip = getUserIP(request); 104 | return isValidIP(ip); 105 | } 106 | 107 | /** 108 | * 判断我们获取的ip是否是一个符合规则ip 109 | */ 110 | public static boolean isValidIP(String ip) { 111 | if (StrUtil.isBlank(ip)) { 112 | return false; 113 | } 114 | 115 | return Validator.isIpv4(ip); 116 | } 117 | 118 | public static String getLastServerIpSegment() { 119 | String ip = getServerIP(); 120 | if (ip != null) { 121 | ip = ip.substring(ip.lastIndexOf('.') + 1); 122 | } else { 123 | ip = "0"; 124 | } 125 | return ip; 126 | } 127 | 128 | public static String getServerIP() { 129 | try { 130 | InetAddress inetAddress = InetAddress.getLocalHost(); 131 | return inetAddress.getHostAddress(); 132 | } catch (UnknownHostException e) { 133 | log.error("获取服务器 IP 发生异常!", e); 134 | } 135 | return LOCAL_IP; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/util/LoginLogUtil.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.util; 2 | 3 | import cn.hutool.core.util.ObjectUtil; 4 | import com.xkcoding.scaffold.common.status.LogStatus; 5 | import com.xkcoding.scaffold.common.status.Status; 6 | import com.xkcoding.scaffold.mapper.SysLoginLogMapper; 7 | import com.xkcoding.scaffold.model.SysLoginLog; 8 | import eu.bitwalker.useragentutils.UserAgent; 9 | import lombok.extern.slf4j.Slf4j; 10 | 11 | import java.util.Date; 12 | 13 | /** 14 | *

15 | * 日志操作任务创建工厂 16 | *

17 | * 18 | * @package: com.xkcoding.scaffold.util.log.factory 19 | * @description: 日志操作任务创建工厂 20 | * @author: yangkai.shen 21 | * @date: Created in 2018/8/9 下午7:23 22 | * @copyright: Copyright (c) 2018 23 | * @version: V1.0 24 | * @modified: yangkai.shen 25 | */ 26 | @Slf4j 27 | public class LoginLogUtil { 28 | 29 | private static SysLoginLogMapper sysLoginLogMapper = SpringContextHolderUtil.getBean(SysLoginLogMapper.class); 30 | 31 | public static void saveLog(String username, Status message, LogStatus status) { 32 | try { 33 | UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtil.getRequest().getHeader("User-Agent")); 34 | // 获取客户端操作系统 35 | String os = userAgent.getOperatingSystem().getName(); 36 | // 获取客户端浏览器 37 | String browser = userAgent.getBrowser().getName(); 38 | 39 | SysLoginLog sysLoginLog = new SysLoginLog(); 40 | sysLoginLog.setLoginName(username); 41 | sysLoginLog.setStatus(status.getCode()); 42 | if (ObjectUtil.equal(status, LogStatus.ERROR) || ObjectUtil.equal(message, Status.LOGOUT_SUCCESS)) { 43 | sysLoginLog.setIpAddress(ServletUtil.getIp()); 44 | sysLoginLog.setLoginLocation(Ip2AddressUtil.getAddressInLocal(ServletUtil.getIp())); 45 | } else { 46 | sysLoginLog.setIpAddress(SecurityUtil.getIp()); 47 | sysLoginLog.setLoginLocation(Ip2AddressUtil.getAddressInLocal(SecurityUtil.getIp())); 48 | } 49 | sysLoginLog.setBrowser(browser); 50 | sysLoginLog.setOs(os); 51 | sysLoginLog.setMsg(message.getMsg()); 52 | sysLoginLog.setLoginTime(new Date()); 53 | sysLoginLogMapper.insertUseGeneratedKeys(sysLoginLog); 54 | } catch (Exception e) { 55 | log.error("创建登录日志异常!", e); 56 | } 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/util/SecurityUtil.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.util; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import com.xkcoding.scaffold.model.dto.SysUserDTO; 5 | import org.springframework.security.core.Authentication; 6 | import org.springframework.security.core.context.SecurityContextHolder; 7 | import org.springframework.security.web.authentication.WebAuthenticationDetails; 8 | import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; 9 | 10 | /** 11 | *

12 | * Spring Security 工具类 13 | *

14 | * 15 | * @package: com.xkcoding.scaffold.util 16 | * @description: Spring Security 工具类 17 | * @author: yangkai.shen 18 | * @date: Created in 2018/8/7 下午9:24 19 | * @copyright: Copyright (c) 2018 20 | * @version: V1.0 21 | * @modified: yangkai.shen 22 | */ 23 | public class SecurityUtil { 24 | /** 25 | * 获取当前上下文的认证信息 26 | * 27 | * @return 获取当前上下文的认证信息 28 | */ 29 | public static Authentication getAuthentication() { 30 | return SecurityContextHolder.getContext().getAuthentication(); 31 | } 32 | 33 | /** 34 | * 获取当前上下文的认证信息的细节 35 | * 36 | * @return 获取当前上下文的认证信息的细节 37 | */ 38 | public static WebAuthenticationDetails getWebAuthenticationDetails() { 39 | return (WebAuthenticationDetails) getAuthentication().getDetails(); 40 | } 41 | 42 | /** 43 | * 获取登录用户的 SessionId 44 | * 45 | * @return SessionId 46 | */ 47 | public static String getSessionId() { 48 | return getWebAuthenticationDetails().getSessionId(); 49 | } 50 | 51 | /** 52 | * 获取登录用户的 IP 53 | * 54 | * @return IP 55 | */ 56 | public static String getIp() { 57 | String ip = getWebAuthenticationDetails().getRemoteAddress(); 58 | if (StrUtil.equals(ip, IpUtil.LOCAL_INNER_LOOP_IP)) { 59 | return IpUtil.LOCAL_IP; 60 | } 61 | return ip; 62 | } 63 | 64 | /** 65 | * 获取当前登录用户 66 | * 67 | * @return 当前登录用户 68 | */ 69 | public static SysUserDTO getCurrentUser() { 70 | Object principal = getAuthentication().getPrincipal(); 71 | if (principal instanceof SysUserDTO) { 72 | return (SysUserDTO) principal; 73 | } 74 | return null; 75 | } 76 | 77 | /** 78 | * 登出当前登录用户 79 | */ 80 | public static void logout() { 81 | new SecurityContextLogoutHandler().logout(ServletUtil.getRequest(), ServletUtil.getResponse(), getAuthentication()); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/util/ServletUtil.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.util; 2 | 3 | import cn.hutool.core.convert.Convert; 4 | import cn.hutool.core.util.StrUtil; 5 | import cn.hutool.json.JSONObject; 6 | import cn.hutool.json.JSONUtil; 7 | import com.xkcoding.scaffold.common.constant.ContentType; 8 | import com.xkcoding.scaffold.common.constant.FileSuffix; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.springframework.web.context.request.RequestAttributes; 11 | import org.springframework.web.context.request.RequestContextHolder; 12 | import org.springframework.web.context.request.ServletRequestAttributes; 13 | 14 | import javax.servlet.http.HttpServletRequest; 15 | import javax.servlet.http.HttpServletResponse; 16 | import javax.servlet.http.HttpSession; 17 | import java.io.IOException; 18 | 19 | /** 20 | *

21 | * Servlet 工具类 22 | *

23 | * 24 | * @package: com.xkcoding.scaffold.util 25 | * @description: Servlet 工具类 26 | * @author: yangkai.shen 27 | * @date: Created in 2018/8/6 下午4:18 28 | * @copyright: Copyright (c) 2018 29 | * @version: V1.0 30 | * @modified: yangkai.shen 31 | */ 32 | @Slf4j 33 | public class ServletUtil { 34 | /** 35 | * 获取当前请求的 RequestAttributes 36 | */ 37 | public static ServletRequestAttributes getRequestAttributes() { 38 | RequestAttributes attributes = RequestContextHolder.currentRequestAttributes(); 39 | return (ServletRequestAttributes) attributes; 40 | } 41 | 42 | /** 43 | * 获取 IP 44 | */ 45 | public static String getIp() { 46 | return IpUtil.getUserIP(getRequest()); 47 | } 48 | 49 | /** 50 | * 获取 Request 51 | */ 52 | public static HttpServletRequest getRequest() { 53 | return getRequestAttributes().getRequest(); 54 | } 55 | 56 | /** 57 | * 获取 Response 58 | */ 59 | public static HttpServletResponse getResponse() { 60 | return getRequestAttributes().getResponse(); 61 | } 62 | 63 | /** 64 | * 获取 Session 65 | */ 66 | public static HttpSession getSession() { 67 | return getRequest().getSession(); 68 | } 69 | 70 | /** 71 | * 获取String参数 72 | */ 73 | public static String getParameter(String name) { 74 | return getRequest().getParameter(name); 75 | } 76 | 77 | /** 78 | * 获取String参数 79 | */ 80 | public static String getParameter(String name, String defaultValue) { 81 | return Convert.toStr(getRequest().getParameter(name), defaultValue); 82 | } 83 | 84 | /** 85 | * 获取Integer参数 86 | */ 87 | public static Integer getParameterToInt(String name) { 88 | return Convert.toInt(getRequest().getParameter(name)); 89 | } 90 | 91 | /** 92 | * 获取Integer参数 93 | */ 94 | public static Integer getParameterToInt(String name, Integer defaultValue) { 95 | return Convert.toInt(getRequest().getParameter(name), defaultValue); 96 | } 97 | 98 | /** 99 | * 使用 Response 渲染 json 数据到客户端 100 | * 101 | * @param response 输出流 102 | * @param data 渲染数据 103 | */ 104 | public static void renderJson(HttpServletResponse response, Object data) { 105 | try { 106 | response.setContentType("application/json"); 107 | response.setCharacterEncoding("utf-8"); 108 | JSONObject jsonData = JSONUtil.parseObj(data, false); 109 | String json = JSONUtil.toJsonStr(jsonData); 110 | response.getWriter().print(json); 111 | } catch (IOException e) { 112 | log.error("【JSON 渲染】使用 Response 渲染 json 数据到客户端,[json]:{}", JSONUtil.toJsonStr(data)); 113 | log.error("【JSON 渲染】发生异常!", e); 114 | } 115 | } 116 | 117 | /** 118 | * 是否是Ajax异步请求 119 | * 120 | * @param request 请求 121 | */ 122 | public static boolean isAjaxRequest(HttpServletRequest request) { 123 | 124 | String accept = request.getHeader("accept"); 125 | if (StrUtil.containsIgnoreCase(accept, ContentType.JSON.getValue())) { 126 | return true; 127 | } 128 | 129 | String xRequestedWith = request.getHeader("X-Requested-With"); 130 | if (StrUtil.containsIgnoreCase(xRequestedWith, ContentType.XML_HTTP_REQUEST.getValue())) { 131 | return true; 132 | } 133 | 134 | String uri = request.getRequestURI(); 135 | if (StrUtil.containsAnyIgnoreCase(uri, FileSuffix.JSON.getValue(), FileSuffix.XML.getValue())) { 136 | return true; 137 | } 138 | 139 | String ajax = request.getParameter("__ajax"); 140 | if (StrUtil.containsAnyIgnoreCase(ajax, FileSuffix.JSON.getValue(), FileSuffix.XML.getValue())) { 141 | return true; 142 | } 143 | 144 | return false; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/com/xkcoding/scaffold/util/SpringContextHolderUtil.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.util; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.ApplicationContextAware; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | *

10 | * Spring的ApplicationContext的持有者,可以用静态方法的方式获取spring容器中的bean 11 | *

12 | * 13 | * @package: com.xkcoding.scaffold.util 14 | * @description: Spring的ApplicationContext的持有者, 可以用静态方法的方式获取spring容器中的bean 15 | * @author: yangkai.shen 16 | * @date: Created in 2018/8/2 下午7:56 17 | * @copyright: Copyright (c) 2018 18 | * @version: V1.0 19 | * @modified: yangkai.shen 20 | */ 21 | @Component 22 | public class SpringContextHolderUtil implements ApplicationContextAware { 23 | 24 | private static ApplicationContext applicationContext; 25 | 26 | @Override 27 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 28 | SpringContextHolderUtil.applicationContext = applicationContext; 29 | } 30 | 31 | public static ApplicationContext getApplicationContext() { 32 | assertApplicationContext(); 33 | return applicationContext; 34 | } 35 | 36 | @SuppressWarnings("unchecked") 37 | public static T getBean(String beanName) { 38 | assertApplicationContext(); 39 | return (T) applicationContext.getBean(beanName); 40 | } 41 | 42 | public static T getBean(Class requiredType) { 43 | assertApplicationContext(); 44 | return applicationContext.getBean(requiredType); 45 | } 46 | 47 | private static void assertApplicationContext() { 48 | if (SpringContextHolderUtil.applicationContext == null) { 49 | throw new RuntimeException("applicaitonContext属性为null,请检查是否注入了SpringContextHolder!"); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | ### 自定义配置 ### 2 | scaffold: 3 | ### 通用配置 ### 4 | common: 5 | ### 名称 ### 6 | name: ${spring.application.name} 7 | ### 版本 ### 8 | version: 0.0.1 9 | ### 版权年份 ### 10 | copyrightYear: 2018 11 | ### 作者 ### 12 | developer: Yangkai.Shen 13 | ### 安全配置 ### 14 | security: 15 | ### 登录页配置 ### 16 | login-page: /authentication/require 17 | 18 | ### 服务器配置 ### 19 | server: 20 | ### 端口号 ### 21 | port: 8080 22 | servlet: 23 | ### 上下文路径 ### 24 | context-path: /scaffold 25 | tomcat: 26 | uri-encoding: utf-8 27 | 28 | ### 日志配置 ### 29 | logging: 30 | level: 31 | com.xkcoding: debug 32 | org.springframework: WARN 33 | com.xkcoding.scaffold.mapper: debug 34 | 35 | ### Spring 配置 ### 36 | spring: 37 | application: 38 | name: scaffold 39 | ### 数据源配置 ### 40 | datasource: 41 | url: jdbc:mysql://localhost:3306/scaffold?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false 42 | username: root 43 | password: root 44 | driver-class-name: com.mysql.jdbc.Driver 45 | type: com.zaxxer.hikari.HikariDataSource 46 | hikari: 47 | minimum-idle: 5 48 | connection-test-query: SELECT 1 FROM DUAL 49 | maximum-pool-size: 20 50 | auto-commit: true 51 | idle-timeout: 30000 52 | pool-name: ScaffoldHikariCP 53 | max-lifetime: 60000 54 | connection-timeout: 30000 55 | ### 开启404异常抛出 ### 56 | mvc: 57 | throw-exception-if-no-handler-found: true 58 | ### 关闭静态资源映射 ### 59 | resources: 60 | add-mappings: false 61 | 62 | ### mybatis 配置 ### 63 | mybatis: 64 | type-aliases-package: com.xkcoding.scaffold.model 65 | mapper-locations: classpath:mybatis/mapper/*.xml 66 | configuration: 67 | map-underscore-to-camel-case: true 68 | 69 | ### 通用 Mapper 配置 ### 70 | mapper: 71 | mappers: com.xkcoding.scaffold.common.MyMapper 72 | notEmpty: true 73 | 74 | ### PageHelper 配置 ### 75 | pagehelper: 76 | helper-dialect: mysql 77 | reasonable: true 78 | support-methods-arguments: true 79 | params: count=countSql -------------------------------------------------------------------------------- /src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | ${AnsiColor.BRIGHT_GREEN} 2 | 3 | ###### ###### ### ######## ######## ####### ## ######## 4 | ## ## ## ## ## ## ## ## ## ## ## ## ## 5 | ## ## ## ## ## ## ## ## ## ## ## 6 | ###### ## ## ## ###### ###### ## ## ## ## ## 7 | ## ## ######### ## ## ## ## ## ## ## 8 | ## ## ## ## ## ## ## ## ## ## ## ## ## 9 | ###### ###### ## ## ## ## ####### ######## ######## 10 | 11 | ${AnsiColor.BRIGHT_RED} 12 | Application 版本: ${scaffold.common.name} - ${scaffold.common.version} 13 | Application 开发: ${scaffold.common.developer} 14 | Application 时间: ${scaffold.common.copyrightYear} 15 | Spring Boot 版本: ${spring-boot.version} 16 | ${AnsiColor.BRIGHT_WHITE} -------------------------------------------------------------------------------- /src/main/resources/ip/ip2region.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xkcoding/scaffold-demo/f8e89c656dde90c49c25f3c61439db6f3e3829ee/src/main/resources/ip/ip2region.db -------------------------------------------------------------------------------- /src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | INFO 7 | 8 | 9 | %date [%thread] %-5level [%logger{50}] %file:%line - %msg%n 10 | UTF-8 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | ERROR 19 | 20 | DENY 21 | 22 | ACCEPT 23 | 24 | 25 | 26 | 27 | 28 | 29 | logs/scaffold/info.created_on_%d{yyyy-MM-dd}.part_%i.log 30 | 31 | 90 32 | 33 | 34 | 35 | 36 | 2MB 37 | 38 | 39 | 40 | 41 | 42 | 43 | %date [%thread] %-5level [%logger{50}] %file:%line - %msg%n 44 | UTF-8 45 | 46 | 47 | 48 | 49 | 50 | 51 | Error 52 | 53 | 54 | 55 | 56 | 57 | 58 | logs/scaffold/error.created_on_%d{yyyy-MM-dd}.part_%i.log 59 | 60 | 90 61 | 62 | 63 | 2MB 64 | 65 | 66 | 67 | %date [%thread] %-5level [%logger{50}] %file:%line - %msg%n 68 | UTF-8 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/generator/datasource.properties: -------------------------------------------------------------------------------- 1 | jdbc.url=jdbc:mysql://localhost:3306/scaffold?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false 2 | jdbc.user=root 3 | jdbc.password=root 4 | jdbc.driverClass=com.mysql.jdbc.Driver -------------------------------------------------------------------------------- /src/main/resources/mybatis/generator/generatorConfig.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 22 | 23 | 24 | 26 | 27 | 29 | 30 | 33 | 34 |
35 |
36 |
-------------------------------------------------------------------------------- /src/main/resources/mybatis/mapper/SysConfigMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/mapper/SysDeptMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/mapper/SysDictDataMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/mapper/SysDictTypeMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/mapper/SysLoginLogMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/mapper/SysMenuMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 34 | 35 | 89 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/mapper/SysOperationLogMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/mapper/SysRoleMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 29 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/mapper/SysRoleMenuMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 21 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/mapper/SysUserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/mapper/SysUserRoleMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/mapper/SysUserWorkMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/mapper/SysWorkMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/test/java/com/xkcoding/scaffold/ScaffoldApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ScaffoldApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/com/xkcoding/scaffold/ip/Ip2AddressTest.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.ip; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.xkcoding.scaffold.ScaffoldApplicationTests; 5 | import com.xkcoding.scaffold.util.Ip2AddressUtil; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.junit.Test; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | *

13 | * 测试 ip2region 14 | *

15 | * 16 | * @package: com.xkcoding.scaffold.ip 17 | * @description: 测试 ip2region 18 | * @author: yangkai.shen 19 | * @date: Created in 2018/8/9 下午3:58 20 | * @copyright: Copyright (c) 2018 21 | * @version: V1.0 22 | * @modified: yangkai.shen 23 | */ 24 | @Slf4j 25 | public class Ip2AddressTest extends ScaffoldApplicationTests { 26 | @Test 27 | public void test1() { 28 | String ip0 = "122.233.48.34"; 29 | String ip1 = "42.200.112.232"; 30 | String ip2 = "127.0.0.1"; 31 | String ip3 = "47.95.196.158"; 32 | String ip4 = "101.105.35.57"; 33 | String ip5 = "101.105.35.57"; 34 | String ip6 = "101.47.19.139"; 35 | List ipList = Lists.newArrayList(ip0, ip1, ip2, ip3, ip4, ip5, ip6); 36 | 37 | for (String ip : ipList) { 38 | String addressInfo1 = Ip2AddressUtil.getAddressInLocal(ip); 39 | String addressInfo2 = Ip2AddressUtil.getAddressOnNetByTaoBao(ip); 40 | log.info("[{}] 本地地理解码 [{}]", ip, addressInfo1); 41 | log.info("[{}] 在线地理解码 [{}]", ip, addressInfo2); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/com/xkcoding/scaffold/user/PasswordEncoderTest.java: -------------------------------------------------------------------------------- 1 | package com.xkcoding.scaffold.user; 2 | 3 | import com.xkcoding.scaffold.ScaffoldApplicationTests; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.junit.Test; 6 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 7 | 8 | /** 9 | *

10 | * 密码测试 11 | *

12 | * 13 | * @package: com.xkcoding.scaffold.com.xkcoding.scaffold.user 14 | * @description: 密码测试 15 | * @author: yangkai.shen 16 | * @date: Created in 2018/8/6 上午9:15 17 | * @copyright: Copyright (c) 2018 18 | * @version: V1.0 19 | * @modified: yangkai.shen 20 | */ 21 | @Slf4j 22 | public class PasswordEncoderTest extends ScaffoldApplicationTests { 23 | 24 | @Test 25 | public void testGetPassword() { 26 | String rawPassword = "123456"; 27 | String encodePassword1 = "$2a$10$NG9t0BI6ZxOuoB4GjQI8aeiD4KFbXH.bauTZTuquCjJpZnUeCq0fm"; 28 | String encodePassword2 = "$2a$10$OCGlv4ACVYO7aMearTHff.cqNmt1yJYujan7U4q2bGqYpEN3o5Bxy"; 29 | String encodePassword3 = "$2a$10$6N2Fn/HnV0hXiOeuJKEc3e/G.PIftVwmtmv48w8i467N1U0yPO0Ci"; 30 | 31 | BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); 32 | String encode = encoder.encode(rawPassword); 33 | 34 | log.info("rawPassword is [{}] , encode is [{}]", rawPassword, encode); 35 | log.debug("does [{}] match [{}] ? " + "{}", rawPassword, encodePassword1, encoder.matches(rawPassword, encodePassword1)); 36 | log.debug("does [{}] match [{}] ? " + "{}", rawPassword, encodePassword2, encoder.matches(rawPassword, encodePassword2)); 37 | log.debug("does [{}] match [{}] ? " + "{}", rawPassword, encodePassword3, encoder.matches(rawPassword, encodePassword3)); 38 | } 39 | } 40 | --------------------------------------------------------------------------------