若依框架想必大家都了解得不少,不可否认这是一款及其简便易用的框架。
在某种情况下(比如私活)使用起来可谓是快得一匹。
在这里小兵结合自身实际使用情况,记录一下我对若依框架的使用和改造情况。
一、源码下载
前往码云进行下载。(vue前后端分离版)
RuoYi-Vue: 🎉 基于SpringBoot,Spring Security,JWT,Vue & Element 的前后端分离权限管理系统,同时提供了 Vue3 的版本
下载后是下面图片的样子,除了 ruoyi-ui 是前端项目外,其它都是后端代码。
可以自行创建两个 git 项目如 ry-admin 、 ry-web,将后端源代码、前端源代码分别上传到自己的git 项目中方便后面管理。
二、源码启动
2.1 修改数据库连接
查看: ruoyi-admin\src\main\resources\application-druid.yml 中的配置,可看到其默认配置如下。
master:url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8username: rootpassword: password
把 库名 ry-vue 和 密码 password 换成自己的库名和密码.
然后执行项目初始化sql: sql/ry_20240629.sql
2.2 启动后端服务
修改完数据库连接/redis连接并初始化sql后,找到 com/ruoyi/RuoYiApplication.java 右键启动
启动成功后,可以访问 8080 端口进行验证。
2.3 启动前端服务
先安装依赖 npm i
安装完成后启动 npm run dev
访问 localhost 使用 admin/admin123 可以看到初版页面。
默认的首页是若依框架的介绍页面,一般不会使用。可以先用若依提供的 views/index_v1.vue 中的内容替换 views/index.vue 的内容,有点首页的样子先。
右上角的工具栏,一般只需要保留全屏功能即可。
全局搜索“源码地址”,将无关功能注释或删掉,保留所需即可。
若依官网的菜单也通过 系统管理-菜单管理 删除。
验证码可以在application.yml中将方式修改为字符验证 captchaType: char
前端换名:搜索“若依”关键字,将其替换为自身项目名字,如erp管理系统。
后端换名:在主目录pom.xml中将后端源项目名改为自身项目名字,如将 com.ruoyi 改成 com.erp
三、原始CURD使用
若依提供了基本的代码生成功能。
以如下测试表 demo1 为例
CREATE TABLE `demo1` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',`name` varchar(255) DEFAULT NULL COMMENT '用户名',`age` int(11) DEFAULT NULL COMMENT '年龄',`birthday` date DEFAULT NULL COMMENT '出生日期',`create_time` datetime DEFAULT NULL,`create_by` varchar(255) DEFAULT NULL,`update_time` datetime DEFAULT NULL,`update_by` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='测试示例表1';
执行以上sql后,在前端页面 系统工具-代码生成 中生成对应代码,并使用。
将生成的 controller/service/mapper/domain/js/vue 代码复制到相应位置,并执行对应sql后,重启项目,可以使用对该表在页面中进行增删改查功能的使用。
四、使用mybatisPlus
一般项目中可以使用 mybatisPlus 和 lombok 来加速开发,代码更为简便和优雅。若依中未进行使用。可以对其进行改造。
在 ruoyi-common/pom.xml 中导入相关依赖:
<lombok.version>1.18.20</lombok.version><mybatis-plus.version>3.5.1</mybatis-plus.version><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>${mybatis-plus.version}</version></dependency>
将mybatis改为mybatisPlus:
修改com/ruoyi/framework/config/MyBatisConfig.java 中的 SqlSessionFactoryBean 为 MybatisSqlSessionFactoryBean
final MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
再以上示测试表复制为 demo2 为例,对应实体如下:
package com.ruoyi.system.domain;import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import com.ruoyi.common.annotation.Excel;/*** 测试示例2对象 demo2** @author ruoyi* @date 2025-01-28*/
@Data
public class Demo2
{private static final long serialVersionUID = 1L;/** id */private Long id;/** 用户名 */@Excel(name = "用户名")private String name;/** 年龄 */@Excel(name = "年龄")private Long age;/** 出生日期 */@JsonFormat(pattern = "yyyy-MM-dd")@Excel(name = "出生日期", width = 30, dateFormat = "yyyy-MM-dd")private Date birthday;/** 创建者 */private String createBy;/** 创建时间 */@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private Date createTime;/** 更新者 */private String updateBy;/** 更新时间 */@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private Date updateTime;}
对应mapper.xml 多继承 BaseMapper:
public interface Demo2Mapper extends BaseMapper<Demo2> {...
}
对应 service.java 多继承 IService:
public interface IDemo2Service extends IService<Demo2> {...
}
对应 serviceImpl.java 多继承 ServiceImpl:
public class Demo2ServiceImpl extends ServiceImpl<Demo2Mapper, Demo2> implements IDemo2Service {....
}
为了使自动生成的代码也达到使用mybatisPlus的效果,需要修改 ruoyi-generator\src\main\resources\vm 对应的生成代码模板。
最终为自动生成代码改动的类有:
GenConstants、GenUtils、SecurityUtils、MyBatisConfig、MybatisPlusConfig、
generator.yml、controller.java.vm、domain.java.vm、mapper.java.vm、service.java.vm、serviceImpl.java.vm
GenConstants.java 如下:
package com.ruoyi.common.constant;/*** 代码生成通用常量** @author ruoyi*/
public class GenConstants
{/** 单表(增删改查) */public static final String TPL_CRUD = "crud";/** 树表(增删改查) */public static final String TPL_TREE = "tree";/** 主子表(增删改查) */public static final String TPL_SUB = "sub";/** 树编码字段 */public static final String TREE_CODE = "treeCode";/** 树父编码字段 */public static final String TREE_PARENT_CODE = "treeParentCode";/** 树名称字段 */public static final String TREE_NAME = "treeName";/** 上级菜单ID字段 */public static final String PARENT_MENU_ID = "parentMenuId";/** 上级菜单名称字段 */public static final String PARENT_MENU_NAME = "parentMenuName";/** 数据库字符串类型 */public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };/** 数据库文本类型 */public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" };/** 数据库时间类型 */public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" };/** 数据库数字类型 */public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer","bit", "bigint", "float", "double", "decimal" };/** 数据库int类型 */public static final String[] COLUMNTYPE_INT = { "tinyint", "smallint", "mediumint", "int", "integer", "bigint"};/** 页面不需要编辑字段 */public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" };/** 页面不需要显示的列表字段 */public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by","update_time" };/** 页面不需要查询字段 */public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by","update_time", "remark" };/** Entity基类字段 */public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" };/** Tree基类字段 */public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors", "children" };/** 文本框 */public static final String HTML_INPUT = "input";/** 文本域 */public static final String HTML_TEXTAREA = "textarea";/** 下拉框 */public static final String HTML_SELECT = "select";/** 单选框 */public static final String HTML_RADIO = "radio";/** 复选框 */public static final String HTML_CHECKBOX = "checkbox";/** 日期控件 */public static final String HTML_DATETIME = "datetime";/** 图片上传控件 */public static final String HTML_IMAGE_UPLOAD = "imageUpload";/** 文件上传控件 */public static final String HTML_FILE_UPLOAD = "fileUpload";/** 富文本控件 */public static final String HTML_EDITOR = "editor";/** 字符串类型 */public static final String TYPE_STRING = "String";/** 整型 */public static final String TYPE_INTEGER = "Integer";/** 长整型 */public static final String TYPE_LONG = "Long";/** 浮点型 */public static final String TYPE_DOUBLE = "Double";/** 高精度计算类型 */public static final String TYPE_BIGDECIMAL = "BigDecimal";/** 时间类型 */public static final String TYPE_DATE = "Date";/** 模糊查询 */public static final String QUERY_LIKE = "LIKE";/** 相等查询 */public static final String QUERY_EQ = "EQ";/** 需要 */public static final String REQUIRE = "1";
}
GenUtils.java
package com.ruoyi.generator.util;import java.util.Arrays;
import org.apache.commons.lang3.RegExUtils;
import com.ruoyi.common.constant.GenConstants;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.generator.config.GenConfig;
import com.ruoyi.generator.domain.GenTable;
import com.ruoyi.generator.domain.GenTableColumn;/*** 代码生成器 工具类** @author ruoyi*/
public class GenUtils
{/*** 初始化表信息*/public static void initTable(GenTable genTable, String operName){genTable.setClassName(convertClassName(genTable.getTableName()));genTable.setPackageName(GenConfig.getPackageName());genTable.setModuleName(getModuleName(GenConfig.getPackageName()));genTable.setBusinessName(getBusinessName(genTable.getTableName()));genTable.setFunctionName(replaceText(genTable.getTableComment()));genTable.setFunctionAuthor(GenConfig.getAuthor());genTable.setCreateBy(operName);}/*** 初始化列属性字段*/public static void initColumnField(GenTableColumn column, GenTable table){String dataType = getDbType(column.getColumnType());String columnName = column.getColumnName();column.setTableId(table.getTableId());column.setCreateBy(table.getCreateBy());// 设置java字段名column.setJavaField(StringUtils.toCamelCase(columnName));// 设置默认类型column.setJavaType(GenConstants.TYPE_STRING);column.setQueryType(GenConstants.QUERY_EQ);if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType)){// 字符串长度超过500设置为文本域Integer columnLength = getColumnLength(column.getColumnType());String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;column.setHtmlType(htmlType);}else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType)){column.setJavaType(GenConstants.TYPE_DATE);column.setHtmlType(GenConstants.HTML_DATETIME);}else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType)){column.setHtmlType(GenConstants.HTML_INPUT);// 如果是浮点型 统一用BigDecimalString[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0){column.setJavaType(GenConstants.TYPE_BIGDECIMAL);}//常用int 对应 Integer / Longelse if (arraysContains(GenConstants.COLUMNTYPE_INT, dataType)) {if (dataType.equals(GenConstants.COLUMNTYPE_INT[GenConstants.COLUMNTYPE_INT.length - 1])) {column.setJavaType(GenConstants.TYPE_LONG);} else {column.setJavaType(GenConstants.TYPE_INTEGER);}}// 如果是整形else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10){column.setJavaType(GenConstants.TYPE_INTEGER);}// 长整形else{column.setJavaType(GenConstants.TYPE_LONG);}}// 插入字段(默认所有字段都需要插入)column.setIsInsert(GenConstants.REQUIRE);// 编辑字段if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk()){column.setIsEdit(GenConstants.REQUIRE);}// 列表字段if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk()){column.setIsList(GenConstants.REQUIRE);}// 查询字段if (!arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk()){column.setIsQuery(GenConstants.REQUIRE);}// 查询字段类型if (StringUtils.endsWithIgnoreCase(columnName, "name")){column.setQueryType(GenConstants.QUERY_LIKE);}// 状态字段设置单选框if (StringUtils.endsWithIgnoreCase(columnName, "status")){column.setHtmlType(GenConstants.HTML_RADIO);}// 类型&性别字段设置下拉框else if (StringUtils.endsWithIgnoreCase(columnName, "type")|| StringUtils.endsWithIgnoreCase(columnName, "sex")){column.setHtmlType(GenConstants.HTML_SELECT);}// 图片字段设置图片上传控件else if (StringUtils.endsWithIgnoreCase(columnName, "image")){column.setHtmlType(GenConstants.HTML_IMAGE_UPLOAD);}// 文件字段设置文件上传控件else if (StringUtils.endsWithIgnoreCase(columnName, "file")){column.setHtmlType(GenConstants.HTML_FILE_UPLOAD);}// 内容字段设置富文本控件else if (StringUtils.endsWithIgnoreCase(columnName, "content")){column.setHtmlType(GenConstants.HTML_EDITOR);}}/*** 校验数组是否包含指定值** @param arr 数组* @param targetValue 值* @return 是否包含*/public static boolean arraysContains(String[] arr, String targetValue){return Arrays.asList(arr).contains(targetValue);}/*** 获取模块名** @param packageName 包名* @return 模块名*/public static String getModuleName(String packageName){int lastIndex = packageName.lastIndexOf(".");int nameLength = packageName.length();return StringUtils.substring(packageName, lastIndex + 1, nameLength);}/*** 获取业务名** @param tableName 表名* @return 业务名*/public static String getBusinessName(String tableName){int lastIndex = tableName.lastIndexOf("_");int nameLength = tableName.length();return StringUtils.substring(tableName, lastIndex + 1, nameLength);}/*** 表名转换成Java类名** @param tableName 表名称* @return 类名*/public static String convertClassName(String tableName){boolean autoRemovePre = GenConfig.getAutoRemovePre();String tablePrefix = GenConfig.getTablePrefix();if (autoRemovePre && StringUtils.isNotEmpty(tablePrefix)){String[] searchList = StringUtils.split(tablePrefix, ",");tableName = replaceFirst(tableName, searchList);}return StringUtils.convertToCamelCase(tableName);}/*** 批量替换前缀** @param replacementm 替换值* @param searchList 替换列表* @return*/public static String replaceFirst(String replacementm, String[] searchList){String text = replacementm;for (String searchString : searchList){if (replacementm.startsWith(searchString)){text = replacementm.replaceFirst(searchString, "");break;}}return text;}/*** 关键字替换** @param text 需要被替换的名字* @return 替换后的名字*/public static String replaceText(String text){return RegExUtils.replaceAll(text, "(?:表|若依)", "");}/*** 获取数据库类型字段** @param columnType 列类型* @return 截取后的列类型*/public static String getDbType(String columnType){if (StringUtils.indexOf(columnType, "(") > 0){return StringUtils.substringBefore(columnType, "(");}else{return columnType;}}/*** 获取字段长度** @param columnType 列类型* @return 截取后的列类型*/public static Integer getColumnLength(String columnType){if (StringUtils.indexOf(columnType, "(") > 0){String length = StringUtils.substringBetween(columnType, "(", ")");return Integer.valueOf(length);}else{return 0;}}
}
SecurityUtils.java
package com.ruoyi.common.utils;import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.PatternMatchUtils;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ServiceException;/*** 安全服务工具类** @author ruoyi*/
public class SecurityUtils
{/*** 用户ID**/public static Long getUserId(){try{return getLoginUser().getUserId();}catch (Exception e){throw new ServiceException("获取用户ID异常", HttpStatus.UNAUTHORIZED);}}/*** 获取部门ID**/public static Long getDeptId(){try{return getLoginUser().getDeptId();}catch (Exception e){throw new ServiceException("获取部门ID异常", HttpStatus.UNAUTHORIZED);}}public static String getOperator() {LoginUser loginUser = getLoginUser();return String.format("{\"userId\":%s,\"userName\":\"%s\"}", loginUser.getUser().getUserId(), loginUser.getUser().getUserName());}/*** 获取用户账户**/public static String getUsername(){try{return getLoginUser().getUsername();}catch (Exception e){throw new ServiceException("获取用户账户异常", HttpStatus.UNAUTHORIZED);}}/*** 获取用户**/public static LoginUser getLoginUser(){try{return (LoginUser) getAuthentication().getPrincipal();}catch (Exception e){throw new ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED);}}/*** 获取Authentication*/public static Authentication getAuthentication(){return SecurityContextHolder.getContext().getAuthentication();}/*** 生成BCryptPasswordEncoder密码** @param password 密码* @return 加密字符串*/public static String encryptPassword(String password){BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();return passwordEncoder.encode(password);}/*** 判断密码是否相同** @param rawPassword 真实密码* @param encodedPassword 加密后字符* @return 结果*/public static boolean matchesPassword(String rawPassword, String encodedPassword){BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();return passwordEncoder.matches(rawPassword, encodedPassword);}/*** 是否为管理员** @param userId 用户ID* @return 结果*/public static boolean isAdmin(Long userId){return userId != null && 1L == userId;}/*** 验证用户是否具备某权限** @param permission 权限字符串* @return 用户是否具备某权限*/public static boolean hasPermi(String permission){return hasPermi(getLoginUser().getPermissions(), permission);}/*** 判断是否包含权限** @param authorities 权限列表* @param permission 权限字符串* @return 用户是否具备某权限*/public static boolean hasPermi(Collection<String> authorities, String permission){return authorities.stream().filter(StringUtils::hasText).anyMatch(x -> Constants.ALL_PERMISSION.equals(x) || PatternMatchUtils.simpleMatch(x, permission));}/*** 验证用户是否拥有某个角色** @param role 角色标识* @return 用户是否具备某角色*/public static boolean hasRole(String role){List<SysRole> roleList = getLoginUser().getUser().getRoles();Collection<String> roles = roleList.stream().map(SysRole::getRoleKey).collect(Collectors.toSet());return hasRole(roles, role);}/*** 判断是否包含角色** @param roles 角色列表* @param role 角色* @return 用户是否具备某角色权限*/public static boolean hasRole(Collection<String> roles, String role){return roles.stream().filter(StringUtils::hasText).anyMatch(x -> Constants.SUPER_ADMIN.equals(x) || PatternMatchUtils.simpleMatch(x, role));}}
MyBatisConfig.java
package com.ruoyi.framework.config;import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import javax.sql.DataSource;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.io.VFS;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.ClassUtils;
import com.ruoyi.common.utils.StringUtils;/*** Mybatis支持*匹配扫描包** @author ruoyi*/
@Configuration
public class MyBatisConfig {@Autowiredprivate Environment env;static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";public static String setTypeAliasesPackage(String typeAliasesPackage) {ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver();MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);List<String> allResult = new ArrayList<String>();try {for (String aliasesPackage : typeAliasesPackage.split(",")) {List<String> result = new ArrayList<String>();aliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX+ ClassUtils.convertClassNameToResourcePath(aliasesPackage.trim()) + "/" + DEFAULT_RESOURCE_PATTERN;Resource[] resources = resolver.getResources(aliasesPackage);if (resources != null && resources.length > 0) {MetadataReader metadataReader = null;for (Resource resource : resources) {if (resource.isReadable()) {metadataReader = metadataReaderFactory.getMetadataReader(resource);try {result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName());} catch (ClassNotFoundException e) {e.printStackTrace();}}}}if (result.size() > 0) {HashSet<String> hashResult = new HashSet<String>(result);allResult.addAll(hashResult);}}if (allResult.size() > 0) {typeAliasesPackage = String.join(",", (String[]) allResult.toArray(new String[0]));} else {throw new RuntimeException("mybatis typeAliasesPackage 路径扫描错误,参数typeAliasesPackage:" + typeAliasesPackage + "未找到任何包");}} catch (IOException e) {e.printStackTrace();}return typeAliasesPackage;}public Resource[] resolveMapperLocations(String[] mapperLocations) {ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();List<Resource> resources = new ArrayList<Resource>();if (mapperLocations != null) {for (String mapperLocation : mapperLocations) {try {Resource[] mappers = resourceResolver.getResources(mapperLocation);resources.addAll(Arrays.asList(mappers));} catch (IOException e) {// ignore}}}return resources.toArray(new Resource[resources.size()]);}@Beanpublic SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {String typeAliasesPackage = env.getProperty("mybatis.typeAliasesPackage");String mapperLocations = env.getProperty("mybatis.mapperLocations");String configLocation = env.getProperty("mybatis.configLocation");typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);VFS.addImplClass(SpringBootVFS.class);// final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();final MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();sessionFactory.setDataSource(dataSource);sessionFactory.setTypeAliasesPackage(typeAliasesPackage);sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ",")));sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));//mp全局配置GlobalConfig globalConfig = new GlobalConfig();GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig();dbConfig .setIdType(IdType.AUTO);globalConfig.setDbConfig(dbConfig);globalConfig.setMetaObjectHandler(new MybatisPlusConfig());sessionFactory.setGlobalConfig(globalConfig);return sessionFactory.getObject();}
}
MybatisPlusConfig.java
package com.ruoyi.framework.config;import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.ruoyi.common.utils.SecurityUtils;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.context.annotation.Configuration;import java.util.Date;/*** MybatisPlus配置类* 实现插入/修改时自动修改时间、操作人(实体类上使用 @TableField(fill = FieldFill.INSERT/INSERT_UPDATE))*/
@Configuration
public class MybatisPlusConfig implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {this.fillStrategy(metaObject, "createTime", new Date());if (ObjectUtil.isNotEmpty(SecurityUtils.getUserId())) {this.fillStrategy(metaObject, "createBy", SecurityUtils.getOperator());}}@Overridepublic void updateFill(MetaObject metaObject) {this.fillStrategy(metaObject, "updateTime", new Date());if (ObjectUtil.isNotEmpty(SecurityUtils.getUserId())) {this.fillStrategy(metaObject, "updateBy", SecurityUtils.getOperator());}}}
controller.java.vm
package ${packageName}.controller;import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
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.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
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.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import ${packageName}.domain.${ClassName};
import ${packageName}.service.I${ClassName}Service;
import com.ruoyi.common.utils.poi.ExcelUtil;
#if($table.crud || $table.sub)
import com.ruoyi.common.core.page.TableDataInfo;
#elseif($table.tree)
#end/*** ${functionName}Controller** @author ${author}* @date ${datetime}*/
@RestController
@RequestMapping("/${moduleName}/${businessName}")
public class ${ClassName}Controller extends BaseController {@Autowiredprivate I${ClassName}Service ${className}Service;/*** 查询${functionName}列表*/@PreAuthorize("@ss.hasPermi('${permissionPrefix}:list')")@GetMapping("/list")
#if($table.crud || $table.sub)public TableDataInfo list(${ClassName} ${className}){startPage();List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});return getDataTable(list);}
#elseif($table.tree)public AjaxResult list(${ClassName} ${className}){List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});return success(list);}
#end/*** 导出${functionName}列表*/@PreAuthorize("@ss.hasPermi('${permissionPrefix}:export')")@Log(title = "${functionName}", businessType = BusinessType.EXPORT)@PostMapping("/export")public void export(HttpServletResponse response, ${ClassName} ${className}){List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});ExcelUtil<${ClassName}> util = new ExcelUtil<${ClassName}>(${ClassName}.class);util.exportExcel(response, list, "${functionName}数据");}/*** 获取${functionName}详细信息*/@PreAuthorize("@ss.hasPermi('${permissionPrefix}:query')")@GetMapping(value = "/{${pkColumn.javaField}}")public AjaxResult getInfo(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField}){return success(${className}Service.select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField}));}/*** 新增${functionName}*/@PreAuthorize("@ss.hasPermi('${permissionPrefix}:add')")@Log(title = "${functionName}", businessType = BusinessType.INSERT)@PostMappingpublic AjaxResult add(@RequestBody ${ClassName} ${className}){return toAjax(${className}Service.insert${ClassName}(${className}));}/*** 修改${functionName}*/@PreAuthorize("@ss.hasPermi('${permissionPrefix}:edit')")@Log(title = "${functionName}", businessType = BusinessType.UPDATE)@PutMappingpublic AjaxResult edit(@RequestBody ${ClassName} ${className}){return toAjax(${className}Service.update${ClassName}(${className}));}/*** 删除${functionName}*/@PreAuthorize("@ss.hasPermi('${permissionPrefix}:remove')")@Log(title = "${functionName}", businessType = BusinessType.DELETE)@DeleteMapping("/{${pkColumn.javaField}s}")public AjaxResult remove(@PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s){return toAjax(${className}Service.delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaField}s));}
}
domain.java.vm
package ${packageName}.domain;import java.util.Date;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.IdType;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.ToString;
import com.ruoyi.common.annotation.Excel;/*** ${functionName}对象 ${tableName}** @author ${author}* @date ${datetime}*/
@Data
@ToString
public class ${ClassName} {private static final long serialVersionUID = 1L;#foreach ($column in $columns)/** $column.columnComment */#set($parentheseIndex=$column.columnComment.indexOf("("))#if($parentheseIndex != -1)#set($comment=$column.columnComment.substring(0, $parentheseIndex))#else#set($comment=$column.columnComment)#end#if($parentheseIndex != -1)@Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")#elseif($column.columnType == "date")@JsonFormat(pattern = "yyyy-MM-dd")@Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd")#elseif($column.columnType == "datetime")@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")@Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")#else@Excel(name = "${comment}")#end#if($column.javaField == "createTime")@TableField(fill = FieldFill.INSERT)#elseif($column.javaField == "createBy")@TableField(fill = FieldFill.INSERT)#end#if($column.javaField == "updateTime")@TableField(fill = FieldFill.UPDATE)#elseif($column.javaField == "updateBy")@TableField(fill = FieldFill.UPDATE)#end#if($column.isPk == 1)@TableId(type = IdType.AUTO)#endprivate $column.javaType $column.javaField;#end
}
mapper.java.vm
package ${packageName}.mapper;import java.util.List;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import ${packageName}.domain.${ClassName};
#if($table.sub)
import ${packageName}.domain.${subClassName};
#end/*** ${functionName}Mapper接口** @author ${author}* @date ${datetime}*/
public interface ${ClassName}Mapper extends BaseMapper<${ClassName}> {/*** 查询${functionName}列表** @param ${className} ${functionName}* @return ${functionName}集合*/public List<${ClassName}> select${ClassName}List(${ClassName} ${className});}
service.java.vm
package ${packageName}.service;import java.util.List;import com.baomidou.mybatisplus.extension.service.IService;
import ${packageName}.domain.${ClassName};/*** ${functionName}Service接口** @author ${author}* @date ${datetime}*/
public interface I${ClassName}Service extends IService<${ClassName}> {/*** 查询${functionName}** @param ${pkColumn.javaField} ${functionName}主键* @return ${functionName}*/public ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});/*** 查询${functionName}列表** @param ${className} ${functionName}* @return ${functionName}集合*/public List<${ClassName}> select${ClassName}List(${ClassName} ${className});/*** 新增${functionName}** @param ${className} ${functionName}* @return 结果*/public int insert${ClassName}(${ClassName} ${className});/*** 修改${functionName}** @param ${className} ${functionName}* @return 结果*/public int update${ClassName}(${ClassName} ${className});/*** 批量删除${functionName}** @param ${pkColumn.javaField}s 需要删除的${functionName}主键集合* @return 结果*/public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s);/*** 删除${functionName}信息** @param ${pkColumn.javaField} ${functionName}主键* @return 结果*/public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});
}
serviceImpl.java.vm
package ${packageName}.service.impl;import java.util.Arrays;
import java.util.List;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
#foreach ($column in $columns)
#if($column.javaField == 'createTime' || $column.javaField == 'updateTime')
import com.ruoyi.common.utils.DateUtils;
#break
#end
#end
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#if($table.sub)
import java.util.List;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import ${packageName}.domain.${subClassName};
#end
import ${packageName}.mapper.${ClassName}Mapper;
import ${packageName}.domain.${ClassName};
import ${packageName}.service.I${ClassName}Service;/*** ${functionName}Service业务层处理** @author ${author}* @date ${datetime}*/
@Service
public class ${ClassName}ServiceImpl extends ServiceImpl<${ClassName}Mapper, ${ClassName}> implements I${ClassName}Service {@Autowiredprivate ${ClassName}Mapper ${className}Mapper;/*** 查询${functionName}** @param ${pkColumn.javaField} ${functionName}主键* @return ${functionName}*/@Overridepublic ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField}) {return getById(${pkColumn.javaField});}/*** 查询${functionName}列表** @param ${className} ${functionName}* @return ${functionName}*/@Overridepublic List<${ClassName}> select${ClassName}List(${ClassName} ${className}) {return ${className}Mapper.select${ClassName}List(${className});}/*** 新增${functionName}** @param ${className} ${functionName}* @return 结果*/
#if($table.sub)@Transactional
#end@Overridepublic int insert${ClassName}(${ClassName} ${className}) {save(${className});#foreach ($column in $columns)#if($column.isPk == '1')return ${className}.get${column.capJavaField}();#end#end}/*** 修改${functionName}** @param ${className} ${functionName}* @return 结果*/
#if($table.sub)@Transactional
#end@Overridepublic int update${ClassName}(${ClassName} ${className}) {return updateById(${className}) ? 1 : 0;}/*** 批量删除${functionName}** @param ${pkColumn.javaField}s 需要删除的${functionName}主键* @return 结果*/@Overridepublic int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s) {return removeBatchByIds(Arrays.asList(${pkColumn.javaField}s)) ? 1 : 0;}/*** 删除${functionName}信息** @param ${pkColumn.javaField} ${functionName}主键* @return 结果*/@Overridepublic int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField}) {return removeById(${pkColumn.javaField}) ? 1 : 0;}
#if($table.sub)/*** 新增${subTable.functionName}信息** @param ${className} ${functionName}对象*/public void insert${subClassName}(${ClassName} ${className}) {List<${subClassName}> ${subclassName}List = ${className}.get${subClassName}List();${pkColumn.javaType} ${pkColumn.javaField} = ${className}.get${pkColumn.capJavaField}();if (StringUtils.isNotNull(${subclassName}List)){List<${subClassName}> list = new ArrayList<${subClassName}>();for (${subClassName} ${subclassName} : ${subclassName}List){${subclassName}.set${subTableFkClassName}(${pkColumn.javaField});list.add(${subclassName});}if (list.size() > 0){${className}Mapper.batch${subClassName}(list);}}}
#end
}