ruoyi-vue-pro 后台管理系统模板文档
一、简介
ruoyi-vue-pro
是一款基于 SpringBoot2.x 全家桶、Vue 和 Element UI 实现的后台管理系统模板,提供模板功能和 CRUD 代码生成,并且支持多租户系统、多数据源系统,可实现浏览器缓存、工作流、排行榜、代码生成等常用开发功能。
在本章节中,我们将介绍该系统的基本架构和运行环境。
二、系统架构
本系统的架构基于传统的前后端分离架构模式,采用以下技术栈:
- 前端采用 Vue + Element + Axios + Webpack;
- 后端采用 SpringBoot2.x + MyBatis-Plus + Shiro + Swagger-UI + Log4j2。
三、运行环境
运行该项目需要满足以下环境:
- JDK8+
- Maven 3.0+
- MySQL 5.5+
- Node.js 10+
四、项目结构
本系统的项目结构如下:
ruoyi-vue-pro/
├── ruoyi-admin/ 后台管理模块
├── ruoyi-common/ 客户端、服务端公共模块
├── ruoyi-framework/ 框架核心模块
├── ruoyi-generator/ java代码自动生成模块
├── ruoyi-quartz/ 定时任务模块
├── ruoyi-system/ 后台管理业务模块
├── ruoyi-tools/ 系统工具模块
└── src/ Vue前端代码
五、代码示例
1. Mybatis-Plus 更改系统默认表名确定方法
在项目中使用 Mybatis-Plus 的时候,默认情况下表名和实体类名必须一一对应,否则会出现"无法找到该实体"的错误。在系统多数据源的时候,这种情况更加明显。
/**
* 代码生成前缀配置,表名以sys_开头才生成代码
*/
strategy.setTablePrefix(new String[] { "sys_" });
/**
* 根据数据库表获取对应实体类
*/
@Override
public String tableToJava(String tableName) {
if (tableName.startsWith("sys_")) {
return upperTableName2Camel(tableName.replaceFirst("sys_", ""));
} else if (tableName.startsWith("gen_")) {
return upperTableName2Camel(tableName.replaceFirst("gen_", "Gen"));
} else if (tableName.startsWith("qrtz_")) {
return upperTableName2Camel(tableName.replaceFirst("qrtz_", "Qrtz"));
} else {
return upperTableName2Camel(tableName);
}
}
2. 自定义异常处理
异常处理是 Web 应用开发中非常重要的一环,当系统出现异常时,我们需要有一个统一的异常处理机制。在本项目中,我们通过继承 DefaultHandlerExceptionResolver
,并重写它的 resolveException()
方法实现异常处理。
@RestControllerAdvice
public class GlobalExceptionHandler extends DefaultHandlerExceptionResolver {
@Autowired
private MessageSource messageSource;
/**
* 处理业务异常
*/
@ExceptionHandler(BusinessException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public R businessException(BusinessException e) {
String message = messageSource.getMessage(e.getMessage(), null, LocaleContextHolder.getLocale());
return R.error(message);
}
/**
* 处理未知异常
*/
@Override
protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
logger.error("系统内部异常,异常信息:", ex);
/**
* 对于未知异常,只返回“系统内部异常”这个提示信息
*/
String message = messageSource.getMessage("error.internal.server", null, LocaleContextHolder.getLocale());
return new ResponseEntity<>(R.error(message), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
3. 多租户系统实现
本系统支持多租户,在开发过程中每个公司可以使用一个数据库,将每个公司的相关数据存放在各自的数据库中。我们在引入 Mybatis-Plus 后,通过继承 MybatisSqlInterceptor
实现多租户的切换。
@Configuration
@MapperScan("com.ruoyi.system.mapper")
public class MybatisPlusConfig {
@Autowired
private RuoYiConfig ruoyiConfig;
/**
* 多租户方案之一:schema模式
*/
@Bean
public MybatisSqlInterceptor mybatisSqlInterceptor() {
return new MybatisSqlInterceptor() {
@Override
public void prepare(SqlMappedStatement mappedStatement, Object parameter) {
if (SecurityUtils.getMultiTenantId() != null) {
final String tenantId = SecurityUtils.getMultiTenantId();
if (StringUtils.isNotBlank(tenantId)) {
String originalSql = mappedStatement.getSql();
StringBuilder sqlBuilder = new StringBuilder("SET SCHEMA '")
.append(tenantId.toLowerCase())
.append("';");
sqlBuilder.append(originalSql);
setPreparedSql(originalSql);
setTargetSql(sqlBuilder.toString());
}
}
}
};
}
/**
* 多租户方案之二:动态表名
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new DynamicTableNameInnerInterceptor());
return interceptor;
}
}
4. Vue + Element UI 实现图标操作
Vue + Element UI 可以通过依赖 fontawesome 实现图标操作。在这里我们可以选择几种方式来实现图标的引用:
- 引用 CDN 上面的 fontawesome 图标库
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
- 下载 fontawesome 文件到本地,然后引用本地文件
<link rel="stylesheet" href="~/fontawesome/css/font-awesome.min.css">
- 使用 vue-awesome 作为插件,安装这个插件,就可以很方便地在 vue 中使用 fontawesome 图标库的各种图标了。
npm install --save @fortawesome/fontawesome-svg-core
npm install --save @fortawesome/free-solid-svg-icons
npm install --save @fortawesome/vue-fontawesome
<template>
<font-awesome-icon :icon="['fas', 'user']" />
</template>
<script>
import Vue from 'vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import { faUser } from '@fortawesome/free-solid-svg-icons'
// 通过 library 方法引入想要使用的图标
library.add(faUser)
Vue.component('font-awesome-icon', FontAwesomeIcon)
</script>
5. Swagger-UI 自动生成 API 文档
Swagger-UI 可以根据我们代码中的注解自动生成 API 文档。在本项目中,我们可以通过以下配置实现:
/**
* swagger配置
*/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
/**
* 注入系统基础配置
*/
@Autowired
private RuoYiConfig ruoyiConfig;
@Bean
public Docket createRestApi() {
// 添加全局头部信息
ParameterBuilder parameterBuilder = new ParameterBuilder();
List<Parameter> parameters = new ArrayList<>();
parameterBuilder.name("Authorization")
.description("令牌")
.modelRef(new ModelRef("string"))
.parameterType("header")
.required(false).build();
parameters.add(parameterBuilder.build());
// API文档基本信息配置
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
.paths(PathSelectors.any())
.build()
.globalOperationParameters(parameters)
.securityContexts(Collections.singletonList(securityContext()))
.securitySchemes(Collections.singletonList(securityScheme()));
}
/**
* API文档基本信息配置
*/
public ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("若依系统接口文档")
.description("若依管理系统后台接口文档")
.contact(new Contact(ruoyiConfig.getName(), null, null))
.version("版本号:" + ruoyiConfig.getVersion())
.build();
}
/**
* 通过 Swagger 解决 token 问题
*/
public SecurityScheme securityScheme() {
return new ApiKey("Token", "token", "header");
}
/**
* 通过 Swagger 解决 token 问题
*/
private SecurityContext securityContext() {
return SecurityContext.builder()
.securityReferences(Arrays.asList(new SecurityReference("Token", new AuthorizationScope[]{new AuthorizationScope("global", "")})))
.build();
}
}
六、总结
本文主要介绍了 ruoyi-vue-pro
的基本架构和运行环境、项目结构以及多个方面的代码示例。通过学习以上内容,我们可以更好地理解和使用该系统,从而提高我们的开发效率和协同工作能力。