| @@ -1,11 +1,17 @@ | |||||
| package com.ruoyi.web.controller.system; | package com.ruoyi.web.controller.system; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.web.bind.annotation.GetMapping; | |||||
| import org.springframework.web.bind.annotation.RequestMapping; | import org.springframework.web.bind.annotation.RequestMapping; | ||||
| import org.springframework.web.bind.annotation.RestController; | import org.springframework.web.bind.annotation.RestController; | ||||
| import com.ruoyi.common.config.RuoYiConfig; | import com.ruoyi.common.config.RuoYiConfig; | ||||
| import com.ruoyi.common.utils.StringUtils; | import com.ruoyi.common.utils.StringUtils; | ||||
| import javax.servlet.ServletException; | |||||
| import javax.servlet.http.HttpServletRequest; | |||||
| import javax.servlet.http.HttpServletResponse; | |||||
| import java.io.IOException; | |||||
| /** | /** | ||||
| * 首页 | * 首页 | ||||
| * | * | ||||
| @@ -22,8 +28,9 @@ public class SysIndexController | |||||
| * 访问首页,提示语 | * 访问首页,提示语 | ||||
| */ | */ | ||||
| @RequestMapping("/") | @RequestMapping("/") | ||||
| public String index() | |||||
| public void index(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException | |||||
| { | { | ||||
| return StringUtils.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion()); | |||||
| //return "redirect:/index.html"; | |||||
| request.getRequestDispatcher("/index.html").forward(request, response); | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,13 +1,20 @@ | |||||
| package com.ruoyi.web.controller.system; | package com.ruoyi.web.controller.system; | ||||
| import com.alibaba.fastjson2.JSON; | |||||
| import com.ruoyi.common.constant.Constants; | import com.ruoyi.common.constant.Constants; | ||||
| import com.ruoyi.common.core.domain.AjaxResult; | import com.ruoyi.common.core.domain.AjaxResult; | ||||
| import com.ruoyi.common.core.domain.entity.SysMenu; | import com.ruoyi.common.core.domain.entity.SysMenu; | ||||
| import com.ruoyi.common.core.domain.entity.SysUser; | import com.ruoyi.common.core.domain.entity.SysUser; | ||||
| import com.ruoyi.common.core.domain.model.LoginBody; | import com.ruoyi.common.core.domain.model.LoginBody; | ||||
| import com.ruoyi.common.core.domain.model.LoginUser; | |||||
| import com.ruoyi.common.utils.SecurityUtils; | import com.ruoyi.common.utils.SecurityUtils; | ||||
| import com.ruoyi.common.utils.ServletUtils; | |||||
| import com.ruoyi.common.utils.StringUtils; | |||||
| import com.ruoyi.framework.manager.AsyncManager; | |||||
| import com.ruoyi.framework.manager.factory.AsyncFactory; | |||||
| import com.ruoyi.framework.web.service.SysLoginService; | import com.ruoyi.framework.web.service.SysLoginService; | ||||
| import com.ruoyi.framework.web.service.SysPermissionService; | import com.ruoyi.framework.web.service.SysPermissionService; | ||||
| import com.ruoyi.framework.web.service.TokenService; | |||||
| import com.ruoyi.system.service.ISysMenuService; | import com.ruoyi.system.service.ISysMenuService; | ||||
| import io.swagger.annotations.Api; | import io.swagger.annotations.Api; | ||||
| import io.swagger.annotations.ApiOperation; | import io.swagger.annotations.ApiOperation; | ||||
| @@ -17,6 +24,8 @@ import org.springframework.web.bind.annotation.PostMapping; | |||||
| import org.springframework.web.bind.annotation.RequestBody; | import org.springframework.web.bind.annotation.RequestBody; | ||||
| import org.springframework.web.bind.annotation.RestController; | import org.springframework.web.bind.annotation.RestController; | ||||
| import javax.servlet.http.HttpServletRequest; | |||||
| import javax.servlet.http.HttpServletResponse; | |||||
| import java.util.List; | import java.util.List; | ||||
| import java.util.Set; | import java.util.Set; | ||||
| @@ -37,6 +46,8 @@ public class SysLoginController | |||||
| @Autowired | @Autowired | ||||
| private SysPermissionService permissionService; | private SysPermissionService permissionService; | ||||
| @Autowired | |||||
| private TokenService tokenService; | |||||
| /** | /** | ||||
| * 登录方法 | * 登录方法 | ||||
| @@ -91,4 +102,20 @@ public class SysLoginController | |||||
| List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId); | List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId); | ||||
| return AjaxResult.success(menuService.buildMenus(menus)); | return AjaxResult.success(menuService.buildMenus(menus)); | ||||
| } | } | ||||
| @ApiOperation("登出") | |||||
| @PostMapping("/adminLogout") | |||||
| public AjaxResult adminLogout(HttpServletRequest request, HttpServletResponse response) | |||||
| { | |||||
| LoginUser loginUser = tokenService.getLoginUser(request); | |||||
| if (StringUtils.isNotNull(loginUser)) | |||||
| { | |||||
| String userName = loginUser.getUsername(); | |||||
| // 删除用户缓存记录 | |||||
| tokenService.delLoginUser(loginUser.getToken()); | |||||
| // 记录用户退出日志 | |||||
| AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, "退出成功")); | |||||
| } | |||||
| return AjaxResult.success("退出成功"); | |||||
| } | |||||
| } | } | ||||
| @@ -88,6 +88,8 @@ spring: | |||||
| max-active: 8 | max-active: 8 | ||||
| # #连接池最大阻塞等待时间(使用负值表示没有限制) | # #连接池最大阻塞等待时间(使用负值表示没有限制) | ||||
| max-wait: -1ms | max-wait: -1ms | ||||
| # key前缀 | |||||
| keyPrefix: file_transfer | |||||
| # 开发环境配置 | # 开发环境配置 | ||||
| server: | server: | ||||
| @@ -88,6 +88,8 @@ spring: | |||||
| max-active: 8 | max-active: 8 | ||||
| # #连接池最大阻塞等待时间(使用负值表示没有限制) | # #连接池最大阻塞等待时间(使用负值表示没有限制) | ||||
| max-wait: -1ms | max-wait: -1ms | ||||
| # key前缀 | |||||
| keyPrefix: file_transfer | |||||
| # token配置 | # token配置 | ||||
| @@ -88,6 +88,8 @@ spring: | |||||
| max-active: 8 | max-active: 8 | ||||
| # #连接池最大阻塞等待时间(使用负值表示没有限制) | # #连接池最大阻塞等待时间(使用负值表示没有限制) | ||||
| max-wait: -1ms | max-wait: -1ms | ||||
| # key前缀 | |||||
| keyPrefix: file_transfer | |||||
| # 生产环境配置 | # 生产环境配置 | ||||
| server: | server: | ||||
| @@ -88,6 +88,8 @@ spring: | |||||
| max-active: 8 | max-active: 8 | ||||
| # #连接池最大阻塞等待时间(使用负值表示没有限制) | # #连接池最大阻塞等待时间(使用负值表示没有限制) | ||||
| max-wait: -1ms | max-wait: -1ms | ||||
| # key前缀 | |||||
| keyPrefix: file_transfer | |||||
| # 预发环境配置 | # 预发环境配置 | ||||
| server: | server: | ||||
| @@ -88,6 +88,8 @@ spring: | |||||
| max-active: 8 | max-active: 8 | ||||
| # #连接池最大阻塞等待时间(使用负值表示没有限制) | # #连接池最大阻塞等待时间(使用负值表示没有限制) | ||||
| max-wait: -1ms | max-wait: -1ms | ||||
| # key前缀 | |||||
| keyPrefix: file_transfer | |||||
| # 测试环境配置 | # 测试环境配置 | ||||
| server: | server: | ||||
| @@ -0,0 +1,37 @@ | |||||
| package com.ruoyi.file.config; | |||||
| import com.ruoyi.common.core.domain.AjaxResult; | |||||
| import com.ruoyi.file.object.UploadException; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.core.annotation.Order; | |||||
| import org.springframework.web.bind.annotation.ExceptionHandler; | |||||
| import org.springframework.web.bind.annotation.RestControllerAdvice; | |||||
| import javax.servlet.http.HttpServletRequest; | |||||
| import javax.servlet.http.HttpServletResponse; | |||||
| /** | |||||
| * 外部文件上传异常处理器 | |||||
| * | |||||
| * @author ruoyi | |||||
| */ | |||||
| @RestControllerAdvice | |||||
| @Order(Integer.MIN_VALUE) | |||||
| public class UploadExceptionHandler | |||||
| { | |||||
| private static final Logger log = LoggerFactory.getLogger(UploadExceptionHandler.class); | |||||
| /** | |||||
| * 拦截文件上传异常 | |||||
| */ | |||||
| @ExceptionHandler(UploadException.class) | |||||
| public AjaxResult handleUploadException(UploadException e, HttpServletRequest request, HttpServletResponse response) | |||||
| { | |||||
| String requestURI = request.getRequestURI(); | |||||
| log.error("外部文件上传异常: 请求地址'{}',发生异常 {} = '{}'.", requestURI, e.code, e.getMessage()); | |||||
| response.setStatus(e.code); | |||||
| return AjaxResult.error(e.getMessage()); | |||||
| } | |||||
| } | |||||
| @@ -58,7 +58,7 @@ public class FileService | |||||
| UploadResult result = FileUploadFunc.Upload(task); | UploadResult result = FileUploadFunc.Upload(task); | ||||
| if(!result.isSuccess()) | if(!result.isSuccess()) | ||||
| throw new UploadException(HttpStatus.INTERNAL_SERVER_ERROR.value(), "禁止上传"); | |||||
| throw new UploadException(HttpStatus.INTERNAL_SERVER_ERROR.value(), "上传失败"); | |||||
| UploadSession session = new UploadSession(project, task, result); | UploadSession session = new UploadSession(project, task, result); | ||||
| DumpUpload(session); | DumpUpload(session); | ||||
| @@ -213,7 +213,7 @@ public class FileService | |||||
| { | { | ||||
| e.printStackTrace(); | e.printStackTrace(); | ||||
| UploadLog.Appendln("异常"); | UploadLog.Appendln("异常"); | ||||
| throw new UploadException(HttpServletResponse.SC_MOVED_PERMANENTLY, "重定向错误", e); | |||||
| throw new UploadException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "重定向错误", e); | |||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| @@ -1,5 +1,7 @@ | |||||
| package com.ruoyi.framework.config; | package com.ruoyi.framework.config; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.beans.factory.annotation.Value; | |||||
| import org.springframework.cache.annotation.CachingConfigurerSupport; | import org.springframework.cache.annotation.CachingConfigurerSupport; | ||||
| import org.springframework.cache.annotation.EnableCaching; | import org.springframework.cache.annotation.EnableCaching; | ||||
| import org.springframework.context.annotation.Bean; | import org.springframework.context.annotation.Bean; | ||||
| @@ -7,7 +9,15 @@ import org.springframework.context.annotation.Configuration; | |||||
| import org.springframework.data.redis.connection.RedisConnectionFactory; | import org.springframework.data.redis.connection.RedisConnectionFactory; | ||||
| import org.springframework.data.redis.core.RedisTemplate; | import org.springframework.data.redis.core.RedisTemplate; | ||||
| import org.springframework.data.redis.core.script.DefaultRedisScript; | import org.springframework.data.redis.core.script.DefaultRedisScript; | ||||
| import org.springframework.data.redis.serializer.RedisSerializer; | |||||
| import org.springframework.data.redis.serializer.StringRedisSerializer; | import org.springframework.data.redis.serializer.StringRedisSerializer; | ||||
| import org.springframework.lang.Nullable; | |||||
| import org.springframework.stereotype.Component; | |||||
| import org.springframework.util.Assert; | |||||
| import java.nio.charset.Charset; | |||||
| import java.nio.charset.StandardCharsets; | |||||
| import java.util.function.Supplier; | |||||
| /** | /** | ||||
| * redis配置 | * redis配置 | ||||
| @@ -18,6 +28,9 @@ import org.springframework.data.redis.serializer.StringRedisSerializer; | |||||
| @EnableCaching | @EnableCaching | ||||
| public class RedisConfig extends CachingConfigurerSupport | public class RedisConfig extends CachingConfigurerSupport | ||||
| { | { | ||||
| @Value("${spring.redis.keyPrefix}") | |||||
| private String keyPrefix; | |||||
| @Bean | @Bean | ||||
| @SuppressWarnings(value = { "unchecked", "rawtypes" }) | @SuppressWarnings(value = { "unchecked", "rawtypes" }) | ||||
| public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) | public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) | ||||
| @@ -27,12 +40,16 @@ public class RedisConfig extends CachingConfigurerSupport | |||||
| FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class); | FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class); | ||||
| Supplier<RedisSerializer<?>> keySerializer = () -> { | |||||
| return new PrefixStringRedisSerializer(keyPrefix); | |||||
| //return new StringRedisSerializer(); | |||||
| }; | |||||
| // 使用StringRedisSerializer来序列化和反序列化redis的key值 | // 使用StringRedisSerializer来序列化和反序列化redis的key值 | ||||
| template.setKeySerializer(new StringRedisSerializer()); | |||||
| template.setKeySerializer(keySerializer.get()); | |||||
| template.setValueSerializer(serializer); | template.setValueSerializer(serializer); | ||||
| // Hash的key也采用StringRedisSerializer的序列化方式 | // Hash的key也采用StringRedisSerializer的序列化方式 | ||||
| template.setHashKeySerializer(new StringRedisSerializer()); | |||||
| template.setHashKeySerializer(keySerializer.get()); | |||||
| template.setHashValueSerializer(serializer); | template.setHashValueSerializer(serializer); | ||||
| template.afterPropertiesSet(); | template.afterPropertiesSet(); | ||||
| @@ -66,4 +83,57 @@ public class RedisConfig extends CachingConfigurerSupport | |||||
| "end\n" + | "end\n" + | ||||
| "return tonumber(current);"; | "return tonumber(current);"; | ||||
| } | } | ||||
| @Component | |||||
| public static class PrefixStringRedisSerializer extends StringRedisSerializer | |||||
| { | |||||
| private final String keyPrefix; | |||||
| private final Charset charset; | |||||
| public PrefixStringRedisSerializer() { | |||||
| this(StandardCharsets.UTF_8); | |||||
| } | |||||
| public PrefixStringRedisSerializer(Charset charset) { | |||||
| Assert.notNull(charset, "Charset must not be null!"); | |||||
| this.charset = charset; | |||||
| keyPrefix = null; | |||||
| } | |||||
| public PrefixStringRedisSerializer(String keyPrefix) { | |||||
| this(keyPrefix, StandardCharsets.UTF_8); | |||||
| } | |||||
| public PrefixStringRedisSerializer(String keyPrefix, Charset charset) { | |||||
| Assert.notNull(charset, "Charset must not be null!"); | |||||
| this.charset = charset; | |||||
| this.keyPrefix = keyPrefix; | |||||
| } | |||||
| private boolean keyPrefixEnabled() | |||||
| { | |||||
| return null != keyPrefix && !keyPrefix.isEmpty(); | |||||
| } | |||||
| public String deserialize(@Nullable byte[] bytes) { | |||||
| if(null == bytes) | |||||
| return null; | |||||
| String key = new String(bytes, this.charset); | |||||
| if(keyPrefixEnabled()) | |||||
| { | |||||
| Assert.isTrue(key.startsWith(keyPrefix), "Redis key must start with '" + keyPrefix + "'!"); | |||||
| return key.substring(keyPrefix.length()); | |||||
| } | |||||
| else | |||||
| return key; | |||||
| } | |||||
| public byte[] serialize(@Nullable String string) { | |||||
| if(null == string) | |||||
| return null; | |||||
| if(keyPrefixEnabled()) | |||||
| string = keyPrefix + ':' + string; | |||||
| return string.getBytes(this.charset); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -1,10 +1,10 @@ | |||||
| # 代码生成 | # 代码生成 | ||||
| gen: | gen: | ||||
| # 作者 | # 作者 | ||||
| author: rongxin | |||||
| author: zhao | |||||
| # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool | # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool | ||||
| packageName: com.ruoyi.score | |||||
| packageName: com.ruoyi.xxx | |||||
| # 自动去除表前缀,默认是false | # 自动去除表前缀,默认是false | ||||
| autoRemovePre: true | autoRemovePre: true | ||||
| # 表前缀(生成类名不会包含表前缀,多个用逗号分隔) | # 表前缀(生成类名不会包含表前缀,多个用逗号分隔) | ||||
| tablePrefix: td_ | |||||
| tablePrefix: t_ | |||||
| @@ -41,7 +41,7 @@ export function getInfo() { | |||||
| // 退出方法 | // 退出方法 | ||||
| export function logout() { | export function logout() { | ||||
| return request({ | return request({ | ||||
| url: '/logout', | |||||
| url: '/adminLogout', // '/logout', | |||||
| method: 'post' | method: 'post' | ||||
| }) | }) | ||||
| } | } | ||||
| @@ -56,4 +56,4 @@ export function getCodeImg() { | |||||
| method: 'get', | method: 'get', | ||||
| timeout: 20000 | timeout: 20000 | ||||
| }) | }) | ||||
| } | |||||
| } | |||||
| @@ -35,7 +35,7 @@ | |||||
| <el-table-column v-for="(item, index) in columns" width="auto" resizable :label="item.name" header-align="center" align="left" :prop="item.name" /> | <el-table-column v-for="(item, index) in columns" width="auto" resizable :label="item.name" header-align="center" align="left" :prop="item.name" /> | ||||
| <el-table-column fixed="right" label="操作" align="center"> | <el-table-column fixed="right" label="操作" align="center"> | ||||
| <template slot-scope="scope"> | <template slot-scope="scope"> | ||||
| <el-button size="mini" type="text" icon="el-icon-view" @click="handleLook(scope.row)" v-hasPermi="['score:farmerEvalMonth:query']">查看</el-button> | |||||
| <el-button size="mini" type="text" icon="el-icon-view" @click="handleLook(scope.row)" v-hasPermi="['admin:xxx:xxx']">查看</el-button> | |||||
| </template> | </template> | ||||
| </el-table-column> | </el-table-column> | ||||
| </el-table> | </el-table> | ||||