more enhancement

This commit is contained in:
rongqian.xu 2021-10-11 18:40:15 +08:00
parent f47bea66ff
commit 1ca0840994
45 changed files with 637 additions and 480 deletions

4
.gitignore vendored
View File

@ -42,3 +42,7 @@ nbdist/
!*/build/*.java !*/build/*.java
!*/build/*.html !*/build/*.html
!*/build/*.xml !*/build/*.xml
ruoyi-ui/node/
ruoyi-ui/node_modules/
ruoyi-admin/src/main/resources/public/

View File

@ -42,6 +42,14 @@
演示地址http://vue.ruoyi.vip 演示地址http://vue.ruoyi.vip
文档地址http://doc.ruoyi.vip 文档地址http://doc.ruoyi.vip
## 快速开始
1. 准备好mysql和redis
2. mysql导入sql目录下的所有sql文件
3. 修改ruoyi-admin/src/main/resources/application.yml的redis连接信息
4. 修改ruoyi-admin/src/main/resources/application-druid.yml的mysql连接信息
5. 执行maven命令构建 ```mvn clean package```
6. 执行命令启动 ```java -jar ruoyi-admin/target/ruoyi-admin.jar```
## 演示图 ## 演示图
<table> <table>

View File

@ -205,6 +205,14 @@
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
<!-- 前端代码 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-ui</artifactId>
<version>${ruoyi.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
@ -215,6 +223,7 @@
<module>ruoyi-quartz</module> <module>ruoyi-quartz</module>
<module>ruoyi-generator</module> <module>ruoyi-generator</module>
<module>ruoyi-common</module> <module>ruoyi-common</module>
<module>ruoyi-ui</module>
</modules> </modules>
<packaging>pom</packaging> <packaging>pom</packaging>

View File

@ -61,6 +61,12 @@
<artifactId>ruoyi-generator</artifactId> <artifactId>ruoyi-generator</artifactId>
</dependency> </dependency>
<!-- 前端代码 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-ui</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -88,7 +94,47 @@
<failOnMissingWebXml>false</failOnMissingWebXml> <failOnMissingWebXml>false</failOnMissingWebXml>
<warName>${project.artifactId}</warName> <warName>${project.artifactId}</warName>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<filesets>
<fileset>
<directory>src/main/resources/public</directory>
</fileset>
</filesets>
</configuration>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<id>copy Vue.js frontend content</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>src/main/resources/public</outputDirectory>
<overwrite>true</overwrite>
<resources>
<resource>
<directory>${project.parent.basedir}/ruoyi-ui/dist</directory>
<includes>
<include>static/</include>
<include>html/</include>
<include>index.html</include>
<include>favicon.ico</include>
<include>robots.txt</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins> </plugins>
<finalName>${project.artifactId}</finalName> <finalName>${project.artifactId}</finalName>
</build> </build>

View File

@ -10,6 +10,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.FastByteArrayOutputStream; import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.google.code.kaptcha.Producer; import com.google.code.kaptcha.Producer;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
@ -25,6 +26,7 @@ import com.ruoyi.system.service.ISysConfigService;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/api")
public class CaptchaController public class CaptchaController
{ {
@Resource(name = "captchaProducer") @Resource(name = "captchaProducer")

View File

@ -8,6 +8,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.config.RuoYiConfig;
@ -24,6 +25,7 @@ import com.ruoyi.framework.config.ServerConfig;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/api")
public class CommonController public class CommonController
{ {
private static final Logger log = LoggerFactory.getLogger(CommonController.class); private static final Logger log = LoggerFactory.getLogger(CommonController.class);

View File

@ -21,7 +21,7 @@ import com.ruoyi.common.utils.StringUtils;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/monitor/cache") @RequestMapping("/api/monitor/cache")
public class CacheController public class CacheController
{ {
@Autowired @Autowired

View File

@ -13,7 +13,7 @@ import com.ruoyi.framework.web.domain.Server;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/monitor/server") @RequestMapping("/api/monitor/server")
public class ServerController public class ServerController
{ {
@PreAuthorize("@ss.hasPermi('monitor:server:list')") @PreAuthorize("@ss.hasPermi('monitor:server:list')")

View File

@ -23,7 +23,7 @@ import com.ruoyi.system.service.ISysLogininforService;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/monitor/logininfor") @RequestMapping("/api/monitor/logininfor")
public class SysLogininforController extends BaseController public class SysLogininforController extends BaseController
{ {
@Autowired @Autowired

View File

@ -23,7 +23,7 @@ import com.ruoyi.system.service.ISysOperLogService;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/monitor/operlog") @RequestMapping("/api/monitor/operlog")
public class SysOperlogController extends BaseController public class SysOperlogController extends BaseController
{ {
@Autowired @Autowired

View File

@ -29,7 +29,7 @@ import com.ruoyi.system.service.ISysUserOnlineService;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/monitor/online") @RequestMapping("/api/monitor/online")
public class SysUserOnlineController extends BaseController public class SysUserOnlineController extends BaseController
{ {
@Autowired @Autowired

View File

@ -29,7 +29,7 @@ import com.ruoyi.system.service.ISysConfigService;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/system/config") @RequestMapping("/api/system/config")
public class SysConfigController extends BaseController public class SysConfigController extends BaseController
{ {
@Autowired @Autowired

View File

@ -29,7 +29,7 @@ import com.ruoyi.system.service.ISysDeptService;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/system/dept") @RequestMapping("/api/system/dept")
public class SysDeptController extends BaseController public class SysDeptController extends BaseController
{ {
@Autowired @Autowired

View File

@ -30,7 +30,7 @@ import com.ruoyi.system.service.ISysDictTypeService;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/system/dict/data") @RequestMapping("/api/system/dict/data")
public class SysDictDataController extends BaseController public class SysDictDataController extends BaseController
{ {
@Autowired @Autowired

View File

@ -28,7 +28,7 @@ import com.ruoyi.system.service.ISysDictTypeService;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/system/dict/type") @RequestMapping("/api/system/dict/type")
public class SysDictTypeController extends BaseController public class SysDictTypeController extends BaseController
{ {
@Autowired @Autowired

View File

@ -12,6 +12,7 @@ import com.ruoyi.common.utils.StringUtils;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/api")
public class SysIndexController public class SysIndexController
{ {
/** 系统基础配置 */ /** 系统基础配置 */
@ -21,7 +22,7 @@ public class SysIndexController
/** /**
* 访问首页提示语 * 访问首页提示语
*/ */
@RequestMapping("/") @RequestMapping("/info")
public String index() public String index()
{ {
return StringUtils.format("欢迎使用{}后台管理框架当前版本v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion()); return StringUtils.format("欢迎使用{}后台管理框架当前版本v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion());

View File

@ -3,10 +3,7 @@ package com.ruoyi.web.controller.system;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
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.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
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;
@ -23,6 +20,7 @@ import com.ruoyi.system.service.ISysMenuService;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/api")
public class SysLoginController public class SysLoginController
{ {
@Autowired @Autowired

View File

@ -27,7 +27,7 @@ import com.ruoyi.system.service.ISysMenuService;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/system/menu") @RequestMapping("/api/system/menu")
public class SysMenuController extends BaseController public class SysMenuController extends BaseController
{ {
@Autowired @Autowired

View File

@ -26,7 +26,7 @@ import com.ruoyi.system.service.ISysNoticeService;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/system/notice") @RequestMapping("/api/system/notice")
public class SysNoticeController extends BaseController public class SysNoticeController extends BaseController
{ {
@Autowired @Autowired

View File

@ -28,7 +28,7 @@ import com.ruoyi.system.service.ISysPostService;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/system/post") @RequestMapping("/api/system/post")
public class SysPostController extends BaseController public class SysPostController extends BaseController
{ {
@Autowired @Autowired

View File

@ -30,7 +30,7 @@ import com.ruoyi.system.service.ISysUserService;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/system/user/profile") @RequestMapping("/api/system/user/profile")
public class SysProfileController extends BaseController public class SysProfileController extends BaseController
{ {
@Autowired @Autowired

View File

@ -4,6 +4,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping; 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.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
@ -17,6 +18,7 @@ import com.ruoyi.system.service.ISysConfigService;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/api")
public class SysRegisterController extends BaseController public class SysRegisterController extends BaseController
{ {
@Autowired @Autowired

View File

@ -35,7 +35,7 @@ import com.ruoyi.system.service.ISysUserService;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/system/role") @RequestMapping("/api/system/role")
public class SysRoleController extends BaseController public class SysRoleController extends BaseController
{ {
@Autowired @Autowired

View File

@ -36,7 +36,7 @@ import com.ruoyi.system.service.ISysUserService;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/system/user") @RequestMapping("/api/system/user")
public class SysUserController extends BaseController public class SysUserController extends BaseController
{ {
@Autowired @Autowired

View File

@ -12,7 +12,7 @@ import com.ruoyi.common.core.controller.BaseController;
* @author ruoyi * @author ruoyi
*/ */
@Controller @Controller
@RequestMapping("/tool/swagger") @RequestMapping("/api/tool/swagger")
public class SwaggerController extends BaseController public class SwaggerController extends BaseController
{ {
@PreAuthorize("@ss.hasPermi('tool:swagger:view')") @PreAuthorize("@ss.hasPermi('tool:swagger:view')")

View File

@ -29,7 +29,7 @@ import io.swagger.annotations.ApiOperation;
*/ */
@Api("用户信息管理") @Api("用户信息管理")
@RestController @RestController
@RequestMapping("/test/user") @RequestMapping("/api/test/user")
public class TestController extends BaseController public class TestController extends BaseController
{ {
private final static Map<Integer, UserEntity> users = new LinkedHashMap<Integer, UserEntity>(); private final static Map<Integer, UserEntity> users = new LinkedHashMap<Integer, UserEntity>();

View File

@ -56,10 +56,10 @@ public class SwaggerConfig
// 设置哪些接口暴露给Swagger展示 // 设置哪些接口暴露给Swagger展示
.select() .select()
// 扫描所有有注解的api用这种方式更灵活 // 扫描所有有注解的api用这种方式更灵活
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) //.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
// 扫描指定包中的swagger注解 // 扫描指定包中的swagger注解
// .apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger")) // .apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger"))
// 扫描所有 .apis(RequestHandlerSelectors.any()) .apis(RequestHandlerSelectors.any()) //扫描所有
.paths(PathSelectors.any()) .paths(PathSelectors.any())
.build() .build()
/* 设置安全模式swagger可以设置访问token */ /* 设置安全模式swagger可以设置访问token */

View File

@ -6,9 +6,9 @@ spring:
druid: druid:
# 主库数据源 # 主库数据源
master: master:
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 url: jdbc:mysql://localhost:3306/ruoyi?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root username: root
password: password password: root
# 从库数据源 # 从库数据源
slave: slave:
# 从数据源开关/默认关闭 # 从数据源开关/默认关闭
@ -41,7 +41,7 @@ spring:
enabled: true enabled: true
# 设置白名单,不填则允许所有访问 # 设置白名单,不填则允许所有访问
allow: allow:
url-pattern: /druid/* url-pattern: /api/druid/*
# 控制台管理用户名和密码 # 控制台管理用户名和密码
login-username: ruoyi login-username: ruoyi
login-password: 123456 login-password: 123456

View File

@ -33,8 +33,8 @@ server:
# 日志配置 # 日志配置
logging: logging:
level: level:
com.ruoyi: debug com.ruoyi: info
org.springframework: warn org.springframework: info
# Spring配置 # Spring配置
spring: spring:
@ -59,7 +59,7 @@ spring:
# redis 配置 # redis 配置
redis: redis:
# 地址 # 地址
host: localhost host: 192.168.56.101
# 端口默认为6379 # 端口默认为6379
port: 6379 port: 6379
# 数据库索引 # 数据库索引
@ -108,13 +108,13 @@ swagger:
# 是否开启swagger # 是否开启swagger
enabled: true enabled: true
# 请求前缀 # 请求前缀
pathMapping: /dev-api pathMapping: /
# 防止XSS攻击 # 防止XSS攻击
xss: xss:
# 过滤开关 # 过滤开关
enabled: true enabled: true
# 排除链接(多个用逗号分隔) # 排除链接(多个用逗号分隔)
excludes: /system/notice excludes: /api/system/notice
# 匹配链接 # 匹配链接
urlPatterns: /system/*,/monitor/*,/tool/* urlPatterns: /api/system/*,/api/monitor/*,/api/tool/*

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration> <configuration>
<!-- 日志存放路径 --> <!-- 日志存放路径 -->
<property name="log.path" value="/home/ruoyi/logs" /> <property name="log.path" value="${log.dir}" />
<!-- 日志输出格式 --> <!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" /> <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
@ -74,7 +74,7 @@
<!-- 系统模块日志级别控制 --> <!-- 系统模块日志级别控制 -->
<logger name="com.ruoyi" level="info" /> <logger name="com.ruoyi" level="info" />
<!-- Spring日志级别控制 --> <!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" /> <logger name="org.springframework" level="info" />
<root level="info"> <root level="info">
<appender-ref ref="console" /> <appender-ref ref="console" />

View File

@ -1,152 +1,149 @@
package com.ruoyi.common.utils; package com.ruoyi.common.utils;
import java.io.IOException; import com.ruoyi.common.constant.HttpStatus;
import javax.servlet.http.HttpServletRequest; import com.ruoyi.common.core.text.Convert;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.context.request.ServletRequestAttributes;
import com.ruoyi.common.core.text.Convert;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/** /**
* 客户端工具类 * 客户端工具类
* *
* @author ruoyi * @author ruoyi
*/ */
public class ServletUtils public class ServletUtils {
{
/** /**
* 获取String参数 * 获取String参数
*/ */
public static String getParameter(String name) public static String getParameter(String name) {
{
return getRequest().getParameter(name); return getRequest().getParameter(name);
} }
/** /**
* 获取String参数 * 获取String参数
*/ */
public static String getParameter(String name, String defaultValue) public static String getParameter(String name, String defaultValue) {
{
return Convert.toStr(getRequest().getParameter(name), defaultValue); return Convert.toStr(getRequest().getParameter(name), defaultValue);
} }
/** /**
* 获取Integer参数 * 获取Integer参数
*/ */
public static Integer getParameterToInt(String name) public static Integer getParameterToInt(String name) {
{
return Convert.toInt(getRequest().getParameter(name)); return Convert.toInt(getRequest().getParameter(name));
} }
/** /**
* 获取Integer参数 * 获取Integer参数
*/ */
public static Integer getParameterToInt(String name, Integer defaultValue) public static Integer getParameterToInt(String name, Integer defaultValue) {
{
return Convert.toInt(getRequest().getParameter(name), defaultValue); return Convert.toInt(getRequest().getParameter(name), defaultValue);
} }
/** /**
* 获取Boolean参数 * 获取Boolean参数
*/ */
public static Boolean getParameterToBool(String name) public static Boolean getParameterToBool(String name) {
{
return Convert.toBool(getRequest().getParameter(name)); return Convert.toBool(getRequest().getParameter(name));
} }
/** /**
* 获取Boolean参数 * 获取Boolean参数
*/ */
public static Boolean getParameterToBool(String name, Boolean defaultValue) public static Boolean getParameterToBool(String name, Boolean defaultValue) {
{
return Convert.toBool(getRequest().getParameter(name), defaultValue); return Convert.toBool(getRequest().getParameter(name), defaultValue);
} }
/** /**
* 获取request * 获取request
*/ */
public static HttpServletRequest getRequest() public static HttpServletRequest getRequest() {
{
return getRequestAttributes().getRequest(); return getRequestAttributes().getRequest();
} }
/** /**
* 获取response * 获取response
*/ */
public static HttpServletResponse getResponse() public static HttpServletResponse getResponse() {
{
return getRequestAttributes().getResponse(); return getRequestAttributes().getResponse();
} }
/** /**
* 获取session * 获取session
*/ */
public static HttpSession getSession() public static HttpSession getSession() {
{
return getRequest().getSession(); return getRequest().getSession();
} }
public static ServletRequestAttributes getRequestAttributes() public static ServletRequestAttributes getRequestAttributes() {
{
RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
return (ServletRequestAttributes) attributes; return (ServletRequestAttributes) attributes;
} }
/** /**
* 将字符串渲染到客户端 * 将字符串渲染到客户端
* *
* @param response 渲染对象 * @param response 渲染对象
* @param string 待渲染的字符串 * @param string 待渲染的字符串
* @return null * @return null
*/ */
public static String renderString(HttpServletResponse response, String string) public static void renderString(HttpServletResponse response, String string) {
{ renderString(response, HttpStatus.SUCCESS, string);
try }
{
response.setStatus(200); /**
* 将字符串渲染到客户端
*
* @param response 渲染对象
* @param status 状态码
* @param string 待渲染的字符串
* @return null
*/
public static void renderString(HttpServletResponse response, int status, String string) {
try {
response.setStatus(status);
response.setContentType("application/json"); response.setContentType("application/json");
response.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8");
response.getWriter().print(string); response.getWriter().print(string);
} catch (IOException e) {
throw new RuntimeException(e);
} }
catch (IOException e)
{
e.printStackTrace();
}
return null;
} }
/** /**
* 是否是Ajax异步请求 * 是否是Ajax异步请求
* *
* @param request * @param request
*/ */
public static boolean isAjaxRequest(HttpServletRequest request) public static boolean isAjaxRequest(HttpServletRequest request) {
{
String accept = request.getHeader("accept"); String accept = request.getHeader("accept");
if (accept != null && accept.indexOf("application/json") != -1) if (accept != null && accept.indexOf("application/json") != -1) {
{
return true; return true;
} }
String xRequestedWith = request.getHeader("X-Requested-With"); String xRequestedWith = request.getHeader("X-Requested-With");
if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1) if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1) {
{
return true; return true;
} }
String uri = request.getRequestURI(); String uri = request.getRequestURI();
if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml")) if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml")) {
{
return true; return true;
} }
String ajax = request.getParameter("__ajax"); String ajax = request.getParameter("__ajax");
if (StringUtils.inStringIgnoreCase(ajax, "json", "xml")) if (StringUtils.inStringIgnoreCase(ajax, "json", "xml")) {
{
return true; return true;
} }
return false; return false;
} }
public static boolean isApiRequest(HttpServletRequest request){
return request.getRequestURI().startsWith("/api");
}
} }

View File

@ -1,45 +1,63 @@
package com.ruoyi.framework.config; package com.ruoyi.framework.config;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;
import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter; import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.ruoyi.common.config.RuoYiConfig; import org.springframework.web.servlet.resource.PathResourceResolver;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor; import java.io.IOException;
/** /**
* 通用配置 * 通用配置
* *
* @author ruoyi * @author ruoyi
*/ */
@Configuration @Configuration
public class ResourcesConfig implements WebMvcConfigurer public class ResourcesConfig implements WebMvcConfigurer {
{
@Autowired @Autowired
private RepeatSubmitInterceptor repeatSubmitInterceptor; private RepeatSubmitInterceptor repeatSubmitInterceptor;
@Override @Override
public void addResourceHandlers(ResourceHandlerRegistry registry) public void addResourceHandlers(ResourceHandlerRegistry registry) {
{
/** 本地文件上传路径 */ /** 本地文件上传路径 */
registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**").addResourceLocations("file:" + RuoYiConfig.getProfile() + "/"); registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**").addResourceLocations("file:" + RuoYiConfig.getProfile() + "/");
/** swagger配置 */ /** swagger配置 */
registry.addResourceHandler("/swagger-ui/**").addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/"); registry.addResourceHandler("/swagger-ui/**").addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
registry.addResourceHandler("/**/*")
.addResourceLocations("classpath:/public/")
.resourceChain(true)
.addResolver(new PathResourceResolver() {
@Override
protected Resource getResource(String resourcePath,
Resource location) throws IOException {
Resource requestedResource = location.createRelative(resourcePath);
return requestedResource.exists() && requestedResource.isReadable() ? requestedResource
: new ClassPathResource("/public/index.html");
}
});
} }
/** /**
* 自定义拦截规则 * 自定义拦截规则
*/ */
@Override @Override
public void addInterceptors(InterceptorRegistry registry) public void addInterceptors(InterceptorRegistry registry) {
{
registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**"); registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
} }
@ -47,8 +65,7 @@ public class ResourcesConfig implements WebMvcConfigurer
* 跨域配置 * 跨域配置
*/ */
@Bean @Bean
public CorsFilter corsFilter() public CorsFilter corsFilter() {
{
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration(); CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true); config.setAllowCredentials(true);

View File

@ -1,6 +1,10 @@
package com.ruoyi.framework.config; package com.ruoyi.framework.config;
import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter;
import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl;
import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
@ -14,24 +18,20 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter; import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.filter.CorsFilter; import org.springframework.web.filter.CorsFilter;
import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter;
import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl;
import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl;
/** /**
* spring security配置 * spring security配置
* *
* @author ruoyi * @author ruoyi
*/ */
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter public class SecurityConfig extends WebSecurityConfigurerAdapter {
{
/** /**
* 自定义用户认证逻辑 * 自定义用户认证逻辑
*/ */
@Autowired @Autowired
private UserDetailsService userDetailsService; private UserDetailsService userDetailsService;
/** /**
* 认证失败处理类 * 认证失败处理类
*/ */
@ -49,13 +49,13 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
*/ */
@Autowired @Autowired
private JwtAuthenticationTokenFilter authenticationTokenFilter; private JwtAuthenticationTokenFilter authenticationTokenFilter;
/** /**
* 跨域过滤器 * 跨域过滤器
*/ */
@Autowired @Autowired
private CorsFilter corsFilter; private CorsFilter corsFilter;
/** /**
* 解决 无法直接注入 AuthenticationManager * 解决 无法直接注入 AuthenticationManager
* *
@ -64,8 +64,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
*/ */
@Bean @Bean
@Override @Override
public AuthenticationManager authenticationManagerBean() throws Exception public AuthenticationManager authenticationManagerBean() throws Exception {
{
return super.authenticationManagerBean(); return super.authenticationManagerBean();
} }
@ -85,8 +84,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
* authenticated | 用户登录后可访问 * authenticated | 用户登录后可访问
*/ */
@Override @Override
protected void configure(HttpSecurity httpSecurity) throws Exception protected void configure(HttpSecurity httpSecurity) throws Exception {
{
httpSecurity httpSecurity
// CSRF禁用因为不使用session // CSRF禁用因为不使用session
.csrf().disable() .csrf().disable()
@ -97,7 +95,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
// 过滤请求 // 过滤请求
.authorizeRequests() .authorizeRequests()
// 对于登录login 注册register 验证码captchaImage 允许匿名访问 // 对于登录login 注册register 验证码captchaImage 允许匿名访问
.antMatchers("/login", "/register", "/captchaImage").anonymous() .antMatchers("/login", "/api/login", "/api/register", "/api/captchaImage", "/error").permitAll()
.antMatchers( .antMatchers(
HttpMethod.GET, HttpMethod.GET,
"/", "/",
@ -105,18 +103,22 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
"/**/*.html", "/**/*.html",
"/**/*.css", "/**/*.css",
"/**/*.js", "/**/*.js",
"/**/*.ico",
"/static/**",
"/html/**",
"/profile/**" "/profile/**"
).permitAll() ).permitAll()
.antMatchers("/swagger-ui.html").anonymous() .antMatchers("/swagger-ui.html").permitAll()
.antMatchers("/swagger-resources/**").anonymous() .antMatchers("/swagger-resources/**").permitAll()
.antMatchers("/webjars/**").anonymous() .antMatchers("/webjars/**").permitAll()
.antMatchers("/*/api-docs").anonymous() .antMatchers("/*/api-docs").permitAll()
.antMatchers("/druid/**").anonymous() .antMatchers( "/api/druid/**").permitAll()
.antMatchers( "/public/**").permitAll()
// 除上面外的所有请求全部需要鉴权认证 // 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated() .anyRequest().authenticated()
.and() .and()
.headers().frameOptions().disable(); .headers().frameOptions().disable();
httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler); httpSecurity.logout().logoutUrl("/api/logout").logoutSuccessHandler(logoutSuccessHandler);
// 添加JWT filter // 添加JWT filter
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
// 添加CORS filter // 添加CORS filter
@ -128,8 +130,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
* 强散列哈希加密实现 * 强散列哈希加密实现
*/ */
@Bean @Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() public BCryptPasswordEncoder bCryptPasswordEncoder() {
{
return new BCryptPasswordEncoder(); return new BCryptPasswordEncoder();
} }
@ -137,8 +138,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
* 身份认证接口 * 身份认证接口
*/ */
@Override @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception protected void configure(AuthenticationManagerBuilder auth) throws Exception {
{
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder()); auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
} }
} }

View File

@ -1,34 +1,38 @@
package com.ruoyi.framework.security.handle; package com.ruoyi.framework.security.handle;
import java.io.IOException;
import java.io.Serializable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.ruoyi.common.constant.HttpStatus; import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Serializable;
import java.net.URLEncoder;
/** /**
* 认证失败处理类 返回未授权 * 认证失败处理类 返回未授权
* *
* @author ruoyi * @author ruoyi
*/ */
@Component @Component
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable {
{
private static final long serialVersionUID = -8970718410437077606L; private static final long serialVersionUID = -8970718410437077606L;
@Override @Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e)
throws IOException throws IOException {
{
int code = HttpStatus.UNAUTHORIZED;
String msg = StringUtils.format("请求访问:{},认证失败,无法访问系统资源", request.getRequestURI()); String msg = StringUtils.format("请求访问:{},认证失败,无法访问系统资源", request.getRequestURI());
ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg))); int code = HttpStatus.UNAUTHORIZED;
if (ServletUtils.isAjaxRequest(request) || ServletUtils.isApiRequest(request)) {
ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg)));
} else {
response.sendRedirect("/login?redirect=" + URLEncoder.encode(request.getRequestURI(), "utf8"));
}
} }
} }

View File

@ -1,12 +1,5 @@
package com.ruoyi.framework.web.service; package com.ruoyi.framework.web.service;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.core.redis.RedisCache;
@ -19,6 +12,16 @@ import eu.bitwalker.useragentutils.UserAgent;
import io.jsonwebtoken.Claims; import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts; import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
/** /**
* token验证处理 * token验证处理
@ -26,8 +29,8 @@ import io.jsonwebtoken.SignatureAlgorithm;
* @author ruoyi * @author ruoyi
*/ */
@Component @Component
public class TokenService public class TokenService {
{ public static final String COOKIE_TOKEN_NAME = "Admin-Token";
// 令牌自定义标识 // 令牌自定义标识
@Value("${token.header}") @Value("${token.header}")
private String header; private String header;
@ -54,23 +57,18 @@ public class TokenService
* *
* @return 用户信息 * @return 用户信息
*/ */
public LoginUser getLoginUser(HttpServletRequest request) public LoginUser getLoginUser(HttpServletRequest request) {
{
// 获取请求携带的令牌 // 获取请求携带的令牌
String token = getToken(request); String token = getToken(request);
if (StringUtils.isNotEmpty(token)) if (StringUtils.isNotEmpty(token)) {
{ try {
try
{
Claims claims = parseToken(token); Claims claims = parseToken(token);
// 解析对应的权限以及用户信息 // 解析对应的权限以及用户信息
String uuid = (String) claims.get(Constants.LOGIN_USER_KEY); String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
String userKey = getTokenKey(uuid); String userKey = getTokenKey(uuid);
LoginUser user = redisCache.getCacheObject(userKey); LoginUser user = redisCache.getCacheObject(userKey);
return user; return user;
} } catch (Exception e) {
catch (Exception e)
{
} }
} }
return null; return null;
@ -79,10 +77,8 @@ public class TokenService
/** /**
* 设置用户身份信息 * 设置用户身份信息
*/ */
public void setLoginUser(LoginUser loginUser) public void setLoginUser(LoginUser loginUser) {
{ if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken())) {
if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken()))
{
refreshToken(loginUser); refreshToken(loginUser);
} }
} }
@ -90,10 +86,8 @@ public class TokenService
/** /**
* 删除用户身份信息 * 删除用户身份信息
*/ */
public void delLoginUser(String token) public void delLoginUser(String token) {
{ if (StringUtils.isNotEmpty(token)) {
if (StringUtils.isNotEmpty(token))
{
String userKey = getTokenKey(token); String userKey = getTokenKey(token);
redisCache.deleteObject(userKey); redisCache.deleteObject(userKey);
} }
@ -105,8 +99,7 @@ public class TokenService
* @param loginUser 用户信息 * @param loginUser 用户信息
* @return 令牌 * @return 令牌
*/ */
public String createToken(LoginUser loginUser) public String createToken(LoginUser loginUser) {
{
String token = IdUtils.fastUUID(); String token = IdUtils.fastUUID();
loginUser.setToken(token); loginUser.setToken(token);
setUserAgent(loginUser); setUserAgent(loginUser);
@ -123,12 +116,10 @@ public class TokenService
* @param loginUser * @param loginUser
* @return 令牌 * @return 令牌
*/ */
public void verifyToken(LoginUser loginUser) public void verifyToken(LoginUser loginUser) {
{
long expireTime = loginUser.getExpireTime(); long expireTime = loginUser.getExpireTime();
long currentTime = System.currentTimeMillis(); long currentTime = System.currentTimeMillis();
if (expireTime - currentTime <= MILLIS_MINUTE_TEN) if (expireTime - currentTime <= MILLIS_MINUTE_TEN) {
{
refreshToken(loginUser); refreshToken(loginUser);
} }
} }
@ -138,8 +129,7 @@ public class TokenService
* *
* @param loginUser 登录信息 * @param loginUser 登录信息
*/ */
public void refreshToken(LoginUser loginUser) public void refreshToken(LoginUser loginUser) {
{
loginUser.setLoginTime(System.currentTimeMillis()); loginUser.setLoginTime(System.currentTimeMillis());
loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE); loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
// 根据uuid将loginUser缓存 // 根据uuid将loginUser缓存
@ -152,8 +142,7 @@ public class TokenService
* *
* @param loginUser 登录信息 * @param loginUser 登录信息
*/ */
public void setUserAgent(LoginUser loginUser) public void setUserAgent(LoginUser loginUser) {
{
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
loginUser.setIpaddr(ip); loginUser.setIpaddr(ip);
@ -168,8 +157,7 @@ public class TokenService
* @param claims 数据声明 * @param claims 数据声明
* @return 令牌 * @return 令牌
*/ */
private String createToken(Map<String, Object> claims) private String createToken(Map<String, Object> claims) {
{
String token = Jwts.builder() String token = Jwts.builder()
.setClaims(claims) .setClaims(claims)
.signWith(SignatureAlgorithm.HS512, secret).compact(); .signWith(SignatureAlgorithm.HS512, secret).compact();
@ -182,8 +170,7 @@ public class TokenService
* @param token 令牌 * @param token 令牌
* @return 数据声明 * @return 数据声明
*/ */
private Claims parseToken(String token) private Claims parseToken(String token) {
{
return Jwts.parser() return Jwts.parser()
.setSigningKey(secret) .setSigningKey(secret)
.parseClaimsJws(token) .parseClaimsJws(token)
@ -196,8 +183,7 @@ public class TokenService
* @param token 令牌 * @param token 令牌
* @return 用户名 * @return 用户名
*/ */
public String getUsernameFromToken(String token) public String getUsernameFromToken(String token) {
{
Claims claims = parseToken(token); Claims claims = parseToken(token);
return claims.getSubject(); return claims.getSubject();
} }
@ -208,18 +194,35 @@ public class TokenService
* @param request * @param request
* @return token * @return token
*/ */
private String getToken(HttpServletRequest request) private String getToken(HttpServletRequest request) {
{
String token = request.getHeader(header); String token = request.getHeader(header);
if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) {
{
token = token.replace(Constants.TOKEN_PREFIX, ""); token = token.replace(Constants.TOKEN_PREFIX, "");
} }
if (StringUtils.isEmpty(token)) {
Optional<String> tokenOpt = getCookie(request, COOKIE_TOKEN_NAME);
if (tokenOpt.isPresent()) {
token = tokenOpt.get();
}
}
return token; return token;
} }
private String getTokenKey(String uuid)
{ private Optional<String> getCookie(HttpServletRequest request, String name) {
if (request.getCookies() == null) {
return Optional.empty();
}
for (Cookie cookie : request.getCookies()) {
if (StringUtils.equals(name, cookie.getName())) {
return Optional.of(cookie.getValue());
}
}
return Optional.empty();
}
private String getTokenKey(String uuid) {
return Constants.LOGIN_TOKEN_KEY + uuid; return Constants.LOGIN_TOKEN_KEY + uuid;
} }
} }

View File

@ -34,7 +34,7 @@ import com.ruoyi.generator.service.IGenTableService;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/tool/gen") @RequestMapping("/api/tool/gen")
public class GenController extends BaseController public class GenController extends BaseController
{ {
@Autowired @Autowired

View File

@ -31,7 +31,7 @@ import com.ruoyi.quartz.util.CronUtils;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/monitor/job") @RequestMapping("/api/monitor/job")
public class SysJobController extends BaseController public class SysJobController extends BaseController
{ {
@Autowired @Autowired

View File

@ -23,7 +23,7 @@ import com.ruoyi.quartz.service.ISysJobLogService;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/monitor/jobLog") @RequestMapping("/api/monitor/jobLog")
public class SysJobLogController extends BaseController public class SysJobLogController extends BaseController
{ {
@Autowired @Autowired

View File

@ -1,11 +1,11 @@
# 页面标题 # 页面标题
VUE_APP_TITLE = 若依管理系统 VUE_APP_TITLE = 若依管理系统
# 开发环境配置 # 开发环境配置
ENV = 'development' ENV = 'development'
# 若依管理系统/开发环境 # 若依管理系统/开发环境
VUE_APP_BASE_API = '/dev-api' VUE_APP_BASE_API = '/api'
# 路由懒加载 # 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true VUE_CLI_BABEL_TRANSPILE_MODULES = true

View File

@ -1,8 +1,8 @@
# 页面标题 # 页面标题
VUE_APP_TITLE = 若依管理系统 VUE_APP_TITLE = 若依管理系统
# 生产环境配置 # 生产环境配置
ENV = 'production' ENV = 'production'
# 若依管理系统/生产环境 # 若依管理系统/生产环境
VUE_APP_BASE_API = '/prod-api' VUE_APP_BASE_API = '/api'

View File

@ -1,88 +1,88 @@
{ {
"name": "ruoyi", "name": "ruoyi",
"version": "3.7.0", "version": "3.7.0",
"description": "若依管理系统", "description": "若依管理系统",
"author": "若依", "author": "若依",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"dev": "vue-cli-service serve", "dev": "vue-cli-service serve",
"build:prod": "vue-cli-service build", "build:prod": "vue-cli-service build",
"build:stage": "vue-cli-service build --mode staging", "build:stage": "vue-cli-service build --mode staging",
"preview": "node build/index.js --preview", "preview": "node build/index.js --preview",
"lint": "eslint --ext .js,.vue src" "lint": "eslint --ext .js,.vue src"
}, },
"husky": { "husky": {
"hooks": { "hooks": {
"pre-commit": "lint-staged" "pre-commit": "lint-staged"
} }
}, },
"lint-staged": { "lint-staged": {
"src/**/*.{js,vue}": [ "src/**/*.{js,vue}": [
"eslint --fix", "eslint --fix",
"git add" "git add"
] ]
}, },
"keywords": [ "keywords": [
"vue", "vue",
"admin", "admin",
"dashboard", "dashboard",
"element-ui", "element-ui",
"boilerplate", "boilerplate",
"admin-template", "admin-template",
"management-system" "management-system"
], ],
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://gitee.com/y_project/RuoYi-Vue.git" "url": "https://gitee.com/y_project/RuoYi-Vue.git"
}, },
"dependencies": { "dependencies": {
"@riophae/vue-treeselect": "0.4.0", "@riophae/vue-treeselect": "0.4.0",
"axios": "0.21.0", "axios": "0.21.0",
"clipboard": "2.0.6", "clipboard": "2.0.6",
"core-js": "3.8.1", "core-js": "3.8.1",
"echarts": "4.9.0", "echarts": "4.9.0",
"element-ui": "2.15.6", "element-ui": "2.15.6",
"file-saver": "2.0.5", "file-saver": "2.0.5",
"fuse.js": "6.4.3", "fuse.js": "6.4.3",
"highlight.js": "9.18.5", "highlight.js": "9.18.5",
"js-beautify": "1.13.0", "js-beautify": "1.13.0",
"js-cookie": "2.2.1", "js-cookie": "2.2.1",
"jsencrypt": "3.0.0-rc.1", "jsencrypt": "3.0.0-rc.1",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"quill": "1.3.7", "quill": "1.3.7",
"screenfull": "5.0.2", "screenfull": "5.0.2",
"sortablejs": "1.10.2", "sortablejs": "1.10.2",
"vue": "2.6.12", "vue": "2.6.12",
"vue-count-to": "1.0.13", "vue-count-to": "1.0.13",
"vue-cropper": "0.5.5", "vue-cropper": "0.5.5",
"vue-meta": "^2.4.0", "vue-meta": "^2.4.0",
"vue-router": "3.4.9", "vue-router": "3.4.9",
"vuedraggable": "2.24.3", "vuedraggable": "2.24.3",
"vuex": "3.6.0" "vuex": "3.6.0"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "4.4.6", "@vue/cli-plugin-babel": "4.4.6",
"@vue/cli-plugin-eslint": "4.4.6", "@vue/cli-plugin-eslint": "4.4.6",
"@vue/cli-service": "4.4.6", "@vue/cli-service": "4.4.6",
"babel-eslint": "10.1.0", "babel-eslint": "10.1.0",
"chalk": "4.1.0", "chalk": "4.1.0",
"connect": "3.6.6", "connect": "3.6.6",
"eslint": "7.15.0", "eslint": "7.15.0",
"eslint-plugin-vue": "7.2.0", "eslint-plugin-vue": "7.2.0",
"lint-staged": "10.5.3", "lint-staged": "10.5.3",
"runjs": "4.4.2", "runjs": "4.4.2",
"sass": "1.32.13", "sass": "1.32.13",
"sass-loader": "10.1.1", "sass-loader": "10.1.1",
"script-ext-html-webpack-plugin": "2.1.5", "script-ext-html-webpack-plugin": "2.1.5",
"svg-sprite-loader": "5.1.1", "svg-sprite-loader": "5.1.1",
"vue-template-compiler": "2.6.12" "vue-template-compiler": "2.6.12"
}, },
"engines": { "engines": {
"node": ">=8.9", "node": ">=8.9",
"npm": ">= 3.0.0" "npm": ">= 3.0.0"
}, },
"browserslist": [ "browserslist": [
"> 1%", "> 1%",
"last 2 versions" "last 2 versions"
] ]
} }

64
ruoyi-ui/pom.xml Normal file
View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>3.7.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-ui</artifactId>
<description>
UI前端项目
</description>
<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<!-- Use the latest released version:
https://repo1.maven.org/maven2/com/github/eirslett/frontend-maven-plugin/ -->
<version>1.9.1</version>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<nodeVersion>v9.11.1</nodeVersion>
</configuration>
</execution>
<!-- Install all project dependencies -->
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<!-- optional: default phase is "generate-resources" -->
<phase>generate-resources</phase>
<!-- Optional configuration which provides for running any npm command -->
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<!-- Build and minify static files -->
<execution>
<id>npm run build</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run build:prod</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,53 +1,53 @@
import request from '@/utils/request' import request from '@/utils/request'
// 登录方法 // 登录方法
export function login(username, password, code, uuid) { export function login(username, password, code, uuid) {
const data = { const data = {
username, username,
password, password,
code, code,
uuid uuid
} }
return request({ return request({
url: '/login', url: '/login',
method: 'post', method: 'post',
data: data data: data
}) })
} }
// 注册方法 // 注册方法
export function register(data) { export function register(data) {
return request({ return request({
url: '/register', url: '/register',
headers: { headers: {
isToken: false isToken: false
}, },
method: 'post', method: 'post',
data: data data: data
}) })
} }
// 获取用户详细信息 // 获取用户详细信息
export function getInfo() { export function getInfo() {
return request({ return request({
url: '/getInfo', url: '/getInfo',
method: 'get' method: 'get'
}) })
} }
// 退出方法 // 退出方法
export function logout() { export function logout() {
return request({ return request({
url: '/logout', url: '/logout',
method: 'post' method: 'post'
}) })
} }
// 获取验证码 // 获取验证码
export function getCodeImg() { export function getCodeImg() {
return request({ return request({
url: '/captchaImage', url: '/captchaImage',
method: 'get', method: 'get',
timeout: 20000 timeout: 20000
}) })
} }

View File

@ -1,15 +1,15 @@
<template> <template>
<i-frame :src="url" /> <i-frame :src="url" />
</template> </template>
<script> <script>
import iFrame from "@/components/iFrame/index"; import iFrame from "@/components/iFrame/index";
export default { export default {
name: "Swagger", name: "Swagger",
components: { iFrame }, components: { iFrame },
data() { data() {
return { return {
url: process.env.VUE_APP_BASE_API + "/swagger-ui/index.html" url: "/swagger-ui/index.html"
}; };
}, },
}; };
</script> </script>

View File

@ -1,117 +1,117 @@
'use strict' 'use strict'
const path = require('path') const path = require('path')
function resolve(dir) { function resolve(dir) {
return path.join(__dirname, dir) return path.join(__dirname, dir)
} }
const name = process.env.VUE_APP_TITLE || '若依管理系统' // 网页标题 const name = process.env.VUE_APP_TITLE || '若依管理系统' // 网页标题
const port = process.env.port || process.env.npm_config_port || 80 // 端口 const port = process.env.port || process.env.npm_config_port || 80 // 端口
// vue.config.js 配置说明 // vue.config.js 配置说明
//官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions //官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions
// 这里只列一部分,具体配置参考文档 // 这里只列一部分,具体配置参考文档
module.exports = { module.exports = {
// 部署生产环境和开发环境下的URL。 // 部署生产环境和开发环境下的URL。
// 默认情况下Vue CLI 会假设你的应用是被部署在一个域名的根路径上 // 默认情况下Vue CLI 会假设你的应用是被部署在一个域名的根路径上
// 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。 // 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。
publicPath: process.env.NODE_ENV === "production" ? "/" : "/", publicPath: process.env.NODE_ENV === "production" ? "/" : "/",
// 在npm run build 或 yarn build 时 生成文件的目录名称要和baseUrl的生产环境路径一致默认dist // 在npm run build 或 yarn build 时 生成文件的目录名称要和baseUrl的生产环境路径一致默认dist
outputDir: 'dist', outputDir: 'dist',
// 用于放置生成的静态资源 (js、css、img、fonts) 的;(项目打包之后,静态资源会放在这个文件夹下) // 用于放置生成的静态资源 (js、css、img、fonts) 的;(项目打包之后,静态资源会放在这个文件夹下)
assetsDir: 'static', assetsDir: 'static',
// 是否开启eslint保存检测有效值ture | false | 'error' // 是否开启eslint保存检测有效值ture | false | 'error'
lintOnSave: process.env.NODE_ENV === 'development', lintOnSave: process.env.NODE_ENV === 'development',
// 如果你不需要生产环境的 source map可以将其设置为 false 以加速生产环境构建。 // 如果你不需要生产环境的 source map可以将其设置为 false 以加速生产环境构建。
productionSourceMap: false, productionSourceMap: false,
// webpack-dev-server 相关配置 // webpack-dev-server 相关配置
devServer: { devServer: {
host: '0.0.0.0', host: '0.0.0.0',
port: port, port: port,
open: true, open: true,
proxy: { proxy: {
// detail: https://cli.vuejs.org/config/#devserver-proxy // detail: https://cli.vuejs.org/config/#devserver-proxy
[process.env.VUE_APP_BASE_API]: { [process.env.VUE_APP_BASE_API]: {
target: `http://localhost:8080`, target: `http://localhost:8080`,
changeOrigin: true, changeOrigin: true
pathRewrite: { //pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: '' // ['^' + process.env.VUE_APP_BASE_API]: ''
} // }
} }
}, },
disableHostCheck: true disableHostCheck: true
}, },
configureWebpack: { configureWebpack: {
name: name, name: name,
resolve: { resolve: {
alias: { alias: {
'@': resolve('src') '@': resolve('src')
} }
} }
}, },
chainWebpack(config) { chainWebpack(config) {
config.plugins.delete('preload') // TODO: need test config.plugins.delete('preload') // TODO: need test
config.plugins.delete('prefetch') // TODO: need test config.plugins.delete('prefetch') // TODO: need test
// set svg-sprite-loader // set svg-sprite-loader
config.module config.module
.rule('svg') .rule('svg')
.exclude.add(resolve('src/assets/icons')) .exclude.add(resolve('src/assets/icons'))
.end() .end()
config.module config.module
.rule('icons') .rule('icons')
.test(/\.svg$/) .test(/\.svg$/)
.include.add(resolve('src/assets/icons')) .include.add(resolve('src/assets/icons'))
.end() .end()
.use('svg-sprite-loader') .use('svg-sprite-loader')
.loader('svg-sprite-loader') .loader('svg-sprite-loader')
.options({ .options({
symbolId: 'icon-[name]' symbolId: 'icon-[name]'
}) })
.end() .end()
config config
.when(process.env.NODE_ENV !== 'development', .when(process.env.NODE_ENV !== 'development',
config => { config => {
config config
.plugin('ScriptExtHtmlWebpackPlugin') .plugin('ScriptExtHtmlWebpackPlugin')
.after('html') .after('html')
.use('script-ext-html-webpack-plugin', [{ .use('script-ext-html-webpack-plugin', [{
// `runtime` must same as runtimeChunk name. default is `runtime` // `runtime` must same as runtimeChunk name. default is `runtime`
inline: /runtime\..*\.js$/ inline: /runtime\..*\.js$/
}]) }])
.end() .end()
config config
.optimization.splitChunks({ .optimization.splitChunks({
chunks: 'all', chunks: 'all',
cacheGroups: { cacheGroups: {
libs: { libs: {
name: 'chunk-libs', name: 'chunk-libs',
test: /[\\/]node_modules[\\/]/, test: /[\\/]node_modules[\\/]/,
priority: 10, priority: 10,
chunks: 'initial' // only package third parties that are initially dependent chunks: 'initial' // only package third parties that are initially dependent
}, },
elementUI: { elementUI: {
name: 'chunk-elementUI', // split elementUI into a single package name: 'chunk-elementUI', // split elementUI into a single package
priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
}, },
commons: { commons: {
name: 'chunk-commons', name: 'chunk-commons',
test: resolve('src/components'), // can customize your rules test: resolve('src/components'), // can customize your rules
minChunks: 3, // minimum common number minChunks: 3, // minimum common number
priority: 5, priority: 5,
reuseExistingChunk: true reuseExistingChunk: true
} }
} }
}) })
config.optimization.runtimeChunk('single'), config.optimization.runtimeChunk('single'),
{ {
from: path.resolve(__dirname, './public/robots.txt'), //防爬虫文件 from: path.resolve(__dirname, './public/robots.txt'), //防爬虫文件
to: './' //到根目录下 to: './' //到根目录下
} }
} }
) )
} }
} }