diff --git a/pom.xml b/pom.xml
index 78eb9e4cf..158cba652 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,6 +29,7 @@
2.13.0
4.1.2
2.3
+ 2.5.0
@@ -142,6 +143,13 @@
${oshi.version}
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ ${springdoc.version}
+
+
commons-io
diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml
index e2a5dbcd4..53df70040 100644
--- a/ruoyi-admin/pom.xml
+++ b/ruoyi-admin/pom.xml
@@ -30,6 +30,12 @@
true
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+
+
com.mysql
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java
index 14abba1c2..b56a09766 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java
@@ -1,183 +1,175 @@
-//package com.ruoyi.web.controller.tool;
-//
-//import java.util.ArrayList;
-//import java.util.LinkedHashMap;
-//import java.util.List;
-//import java.util.Map;
-//import org.springframework.web.bind.annotation.DeleteMapping;
-//import org.springframework.web.bind.annotation.GetMapping;
-//import org.springframework.web.bind.annotation.PathVariable;
-//import org.springframework.web.bind.annotation.PostMapping;
-//import org.springframework.web.bind.annotation.PutMapping;
-//import org.springframework.web.bind.annotation.RequestBody;
-//import org.springframework.web.bind.annotation.RequestMapping;
-//import org.springframework.web.bind.annotation.RestController;
-//import com.ruoyi.common.core.controller.BaseController;
-//import com.ruoyi.common.core.domain.R;
-//import com.ruoyi.common.utils.StringUtils;
-//import io.swagger.annotations.Api;
-//import io.swagger.annotations.ApiImplicitParam;
-//import io.swagger.annotations.ApiImplicitParams;
-//import io.swagger.annotations.ApiModel;
-//import io.swagger.annotations.ApiModelProperty;
-//import io.swagger.annotations.ApiOperation;
-//
-///**
-// * swagger 用户测试方法
-// *
-// * @author ruoyi
-// */
-//@Api("用户信息管理")
-//@RestController
-//@RequestMapping("/test/user")
-//public class TestController extends BaseController
-//{
-// private final static Map users = new LinkedHashMap();
-// {
-// users.put(1, new UserEntity(1, "admin", "admin123", "15888888888"));
-// users.put(2, new UserEntity(2, "ry", "admin123", "15666666666"));
-// }
-//
-// @ApiOperation("获取用户列表")
-// @GetMapping("/list")
-// public R> userList()
-// {
-// List userList = new ArrayList(users.values());
-// return R.ok(userList);
-// }
-//
-// @ApiOperation("获取用户详细")
-// @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
-// @GetMapping("/{userId}")
-// public R getUser(@PathVariable Integer userId)
-// {
-// if (!users.isEmpty() && users.containsKey(userId))
-// {
-// return R.ok(users.get(userId));
-// }
-// else
-// {
-// return R.fail("用户不存在");
-// }
-// }
-//
-// @ApiOperation("新增用户")
-// @ApiImplicitParams({
-// @ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer", dataTypeClass = Integer.class),
-// @ApiImplicitParam(name = "username", value = "用户名称", dataType = "String", dataTypeClass = String.class),
-// @ApiImplicitParam(name = "password", value = "用户密码", dataType = "String", dataTypeClass = String.class),
-// @ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String", dataTypeClass = String.class)
-// })
-// @PostMapping("/save")
-// public R save(UserEntity user)
-// {
-// if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
-// {
-// return R.fail("用户ID不能为空");
-// }
-// users.put(user.getUserId(), user);
-// return R.ok();
-// }
-//
-// @ApiOperation("更新用户")
-// @PutMapping("/update")
-// public R update(@RequestBody UserEntity user)
-// {
-// if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
-// {
-// return R.fail("用户ID不能为空");
-// }
-// if (users.isEmpty() || !users.containsKey(user.getUserId()))
-// {
-// return R.fail("用户不存在");
-// }
-// users.remove(user.getUserId());
-// users.put(user.getUserId(), user);
-// return R.ok();
-// }
-//
-// @ApiOperation("删除用户信息")
-// @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
-// @DeleteMapping("/{userId}")
-// public R delete(@PathVariable Integer userId)
-// {
-// if (!users.isEmpty() && users.containsKey(userId))
-// {
-// users.remove(userId);
-// return R.ok();
-// }
-// else
-// {
-// return R.fail("用户不存在");
-// }
-// }
-//}
-//
-//@ApiModel(value = "UserEntity", description = "用户实体")
-//class UserEntity
-//{
-// @ApiModelProperty("用户ID")
-// private Integer userId;
-//
-// @ApiModelProperty("用户名称")
-// private String username;
-//
-// @ApiModelProperty("用户密码")
-// private String password;
-//
-// @ApiModelProperty("用户手机")
-// private String mobile;
-//
-// public UserEntity()
-// {
-//
-// }
-//
-// public UserEntity(Integer userId, String username, String password, String mobile)
-// {
-// this.userId = userId;
-// this.username = username;
-// this.password = password;
-// this.mobile = mobile;
-// }
-//
-// public Integer getUserId()
-// {
-// return userId;
-// }
-//
-// public void setUserId(Integer userId)
-// {
-// this.userId = userId;
-// }
-//
-// public String getUsername()
-// {
-// return username;
-// }
-//
-// public void setUsername(String username)
-// {
-// this.username = username;
-// }
-//
-// public String getPassword()
-// {
-// return password;
-// }
-//
-// public void setPassword(String password)
-// {
-// this.password = password;
-// }
-//
-// public String getMobile()
-// {
-// return mobile;
-// }
-//
-// public void setMobile(String mobile)
-// {
-// this.mobile = mobile;
-// }
-//}
+package com.ruoyi.web.controller.tool;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.utils.StringUtils;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.tags.Tag;
+
+/**
+ * swagger 用户测试方法
+ *
+ * @author ruoyi
+ */
+@Tag(name = "用户信息管理")
+@RestController
+@RequestMapping("/test/user")
+public class TestController extends BaseController
+{
+ private final static Map users = new LinkedHashMap();
+ {
+ users.put(1, new UserEntity(1, "admin", "admin123", "15888888888"));
+ users.put(2, new UserEntity(2, "ry", "admin123", "15666666666"));
+ }
+
+ @Operation(summary = "获取用户列表")
+ @GetMapping("/list")
+ public R> userList()
+ {
+ List userList = new ArrayList(users.values());
+ return R.ok(userList);
+ }
+
+ @Operation(summary = "获取用户详细")
+ @GetMapping("/{userId}")
+ public R getUser(@PathVariable(name = "userId")
+ Integer userId)
+ {
+ if (!users.isEmpty() && users.containsKey(userId))
+ {
+ return R.ok(users.get(userId));
+ }
+ else
+ {
+ return R.fail("用户不存在");
+ }
+ }
+
+ @Operation(summary = "新增用户")
+ @PostMapping("/save")
+ public R save(UserEntity user)
+ {
+ if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
+ {
+ return R.fail("用户ID不能为空");
+ }
+ users.put(user.getUserId(), user);
+ return R.ok();
+ }
+
+ @Operation(summary = "更新用户")
+ @PutMapping("/update")
+ public R update(@RequestBody
+ UserEntity user)
+ {
+ if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
+ {
+ return R.fail("用户ID不能为空");
+ }
+ if (users.isEmpty() || !users.containsKey(user.getUserId()))
+ {
+ return R.fail("用户不存在");
+ }
+ users.remove(user.getUserId());
+ users.put(user.getUserId(), user);
+ return R.ok();
+ }
+
+ @Operation(summary = "删除用户信息")
+ @DeleteMapping("/{userId}")
+ public R delete(@PathVariable(name = "userId")
+ Integer userId)
+ {
+ if (!users.isEmpty() && users.containsKey(userId))
+ {
+ users.remove(userId);
+ return R.ok();
+ }
+ else
+ {
+ return R.fail("用户不存在");
+ }
+ }
+}
+
+@Schema(description = "用户实体")
+class UserEntity
+{
+ @Schema(title = "用户ID")
+ private Integer userId;
+
+ @Schema(title = "用户名称")
+ private String username;
+
+ @Schema(title = "用户密码")
+ private String password;
+
+ @Schema(title = "用户手机")
+ private String mobile;
+
+ public UserEntity()
+ {
+
+ }
+
+ public UserEntity(Integer userId, String username, String password, String mobile)
+ {
+ this.userId = userId;
+ this.username = username;
+ this.password = password;
+ this.mobile = mobile;
+ }
+
+ public Integer getUserId()
+ {
+ return userId;
+ }
+
+ public void setUserId(Integer userId)
+ {
+ this.userId = userId;
+ }
+
+ public String getUsername()
+ {
+ return username;
+ }
+
+ public void setUsername(String username)
+ {
+ this.username = username;
+ }
+
+ public String getPassword()
+ {
+ return password;
+ }
+
+ public void setPassword(String password)
+ {
+ this.password = password;
+ }
+
+ public String getMobile()
+ {
+ return mobile;
+ }
+
+ public void setMobile(String mobile)
+ {
+ this.mobile = mobile;
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java
index 7874a2967..8d2de2f7a 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java
@@ -1,67 +1,65 @@
-//package com.ruoyi.web.core.config;
-//
-//import org.springframework.beans.factory.annotation.Value;
-//import org.springframework.context.annotation.Bean;
-//import org.springframework.context.annotation.Configuration;
-//import com.ruoyi.common.config.RuoYiConfig;
-//import io.swagger.annotations.ApiOperation;
-//import springfox.documentation.builders.ApiInfoBuilder;
-//import springfox.documentation.builders.PathSelectors;
-//import springfox.documentation.builders.RequestHandlerSelectors;
-//import springfox.documentation.service.ApiInfo;
-//import springfox.documentation.service.Contact;
-//import springfox.documentation.spi.DocumentationType;
-//import springfox.documentation.spring.web.plugins.Docket;
-//
-///**
-// * Swagger2的接口配置
-// *
-// * @author ruoyi
-// */
-//@Configuration
-//public class SwaggerConfig
-//{
-// /** 是否开启swagger */
-// @Value("${swagger.enabled}")
-// private boolean enabled;
-//
-// /**
-// * 创建API
-// */
-// @Bean
-// public Docket createRestApi()
-// {
-// return new Docket(DocumentationType.OAS_30)
-// // 是否启用Swagger
-// .enable(enabled)
-// // 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
-// .apiInfo(apiInfo())
-// // 设置哪些接口暴露给Swagger展示
-// .select()
-// // 扫描所有有注解的api,用这种方式更灵活
-// .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
-// // 扫描指定包中的swagger注解
-// //.apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger"))
-// // 扫描所有 .apis(RequestHandlerSelectors.any())
-// .paths(PathSelectors.any())
-// .build();
-// }
-//
-// /**
-// * 添加摘要信息
-// */
-// private ApiInfo apiInfo()
-// {
-// // 用ApiInfoBuilder进行定制
-// return new ApiInfoBuilder()
-// // 设置标题
-// .title("标题:若依管理系统_接口文档")
-// // 描述
-// .description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
-// // 作者信息
-// .contact(new Contact(RuoYiConfig.getName(), null, null))
-// // 版本
-// .version("版本号:" + RuoYiConfig.getVersion())
-// .build();
-// }
-//}
+package com.ruoyi.web.core.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import com.ruoyi.common.config.RuoYiConfig;
+import io.swagger.v3.oas.models.Components;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.info.Contact;
+import io.swagger.v3.oas.models.info.Info;
+import io.swagger.v3.oas.models.security.SecurityRequirement;
+import io.swagger.v3.oas.models.security.SecurityScheme;
+
+/**
+ * Swagger2的接口配置
+ *
+ * @author ruoyi
+ */
+@Configuration
+public class SwaggerConfig
+{
+ /** 系统基础配置 */
+ @Autowired
+ private RuoYiConfig ruoyiConfig;
+
+ /**
+ * 自定义的 OpenAPI 对象
+ */
+ @Bean
+ public OpenAPI customOpenApi()
+ {
+ return new OpenAPI().components(new Components()
+ // 设置认证的请求头
+ .addSecuritySchemes("apikey", securityScheme()))
+ .addSecurityItem(new SecurityRequirement().addList("apikey"))
+ .info(getApiInfo());
+ }
+
+ @Bean
+ public SecurityScheme securityScheme()
+ {
+ return new SecurityScheme()
+ .type(SecurityScheme.Type.APIKEY)
+ .name("Authorization")
+ .in(SecurityScheme.In.HEADER)
+ .scheme("Bearer");
+ }
+
+ /**
+ * 添加摘要信息
+ */
+ @SuppressWarnings("static-access")
+ public Info getApiInfo()
+ {
+ return new Info()
+ // 设置标题
+ .title("标题:若依管理系统_接口文档")
+ // 描述
+ .description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
+ // 作者信息
+ .contact(new Contact().name(ruoyiConfig.getName()))
+ // 版本
+ .version("版本号:" + ruoyiConfig.getVersion());
+ }
+}
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index dd7fc6e30..e9a01b1d7 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -127,6 +127,20 @@ shiro:
# 是否开启记住我
enabled: true
+# Springdoc配置
+springdoc:
+ api-docs:
+ path: /v3/api-docs
+ swagger-ui:
+ enabled: true
+ path: /swagger-ui.html
+ tags-sorter: alpha
+ group-configs:
+ - group: 'default'
+ display-name: '测试模块'
+ paths-to-match: '/**'
+ packages-to-scan: com.ruoyi.web.controller.tool
+
# 防止XSS攻击
xss:
# 过滤开关
diff --git a/ruoyi-framework/pom.xml b/ruoyi-framework/pom.xml
index c8cc13ea8..819d049df 100644
--- a/ruoyi-framework/pom.xml
+++ b/ruoyi-framework/pom.xml
@@ -42,7 +42,7 @@
servlet-api
- jakarta.servlet
+ javax.servlet
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java
index 76afb7211..b957e84fd 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java
@@ -4,7 +4,6 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
-import java.util.List;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.apache.shiro.cache.ehcache.EhCacheManager;
@@ -25,7 +24,6 @@ import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.security.CipherUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
-import com.ruoyi.framework.config.properties.PermitAllUrlProperties;
import com.ruoyi.framework.shiro.realm.UserRealm;
import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
import com.ruoyi.framework.shiro.session.OnlineSessionFactory;
@@ -290,12 +288,6 @@ public class ShiroConfig
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/ruoyi/**", "anon");
filterChainDefinitionMap.put("/captcha/captchaImage**", "anon");
- // 匿名访问不鉴权注解列表
- List permitAllUrl = SpringUtils.getBean(PermitAllUrlProperties.class).getUrls();
- if (StringUtils.isNotEmpty(permitAllUrl))
- {
- permitAllUrl.forEach(url -> filterChainDefinitionMap.put(url, "anon"));
- }
// 退出 logout地址,shiro去清除session
filterChainDefinitionMap.put("/logout", "logout");
// 不需要拦截的访问
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java
deleted file mode 100644
index 068310246..000000000
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package com.ruoyi.framework.config.properties;
-
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import org.springframework.aop.framework.Advised;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import com.ruoyi.common.annotation.Anonymous;
-
-/**
- * 设置Anonymous注解允许匿名访问的url
- *
- * @author ruoyi
- */
-@Configuration
-public class PermitAllUrlProperties implements InitializingBean, ApplicationContextAware
-{
- private List urls = new ArrayList<>();
-
- private ApplicationContext applicationContext;
-
- @Override
- public void afterPropertiesSet() throws Exception
- {
- Map controllers = applicationContext.getBeansWithAnnotation(Controller.class);
- for (Object bean : controllers.values())
- {
- if (!(bean instanceof Advised))
- {
- continue;
- }
- Class> beanClass = ((Advised) bean).getTargetSource().getTarget().getClass();
- RequestMapping base = beanClass.getAnnotation(RequestMapping.class);
- String[] baseUrl = {};
- if (Objects.nonNull(base))
- {
- baseUrl = base.value();
- }
- Method[] methods = beanClass.getDeclaredMethods();
- for (Method method : methods)
- {
- if (method.isAnnotationPresent(Anonymous.class) && method.isAnnotationPresent(RequestMapping.class))
- {
- RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
- String[] uri = requestMapping.value();
- urls.addAll(rebuildUrl(baseUrl, uri));
- }
- else if (method.isAnnotationPresent(Anonymous.class) && method.isAnnotationPresent(GetMapping.class))
- {
- GetMapping requestMapping = method.getAnnotation(GetMapping.class);
- String[] uri = requestMapping.value();
- urls.addAll(rebuildUrl(baseUrl, uri));
- }
- else if (method.isAnnotationPresent(Anonymous.class) && method.isAnnotationPresent(PostMapping.class))
- {
- PostMapping requestMapping = method.getAnnotation(PostMapping.class);
- String[] uri = requestMapping.value();
- urls.addAll(rebuildUrl(baseUrl, uri));
- }
- else if (method.isAnnotationPresent(Anonymous.class) && method.isAnnotationPresent(PutMapping.class))
- {
- PutMapping requestMapping = method.getAnnotation(PutMapping.class);
- String[] uri = requestMapping.value();
- urls.addAll(rebuildUrl(baseUrl, uri));
- }
- else if (method.isAnnotationPresent(Anonymous.class) && method.isAnnotationPresent(DeleteMapping.class))
- {
- DeleteMapping requestMapping = method.getAnnotation(DeleteMapping.class);
- String[] uri = requestMapping.value();
- urls.addAll(rebuildUrl(baseUrl, uri));
- }
- }
-
- }
- }
-
- private List rebuildUrl(String[] bases, String[] uris)
- {
- List urls = new ArrayList<>();
- for (String base : bases)
- {
- for (String uri : uris)
- {
- urls.add(prefix(base) + prefix(uri));
- }
- }
- return urls;
- }
-
- private String prefix(String seg)
- {
- return seg.startsWith("/") ? seg : "/" + seg;
- }
-
- @Override
- public void setApplicationContext(ApplicationContext context) throws BeansException
- {
- this.applicationContext = context;
- }
-
- public List getUrls()
- {
- return urls;
- }
-
- public void setUrls(List urls)
- {
- this.urls = urls;
- }
-}