Ruoyi若依笔记

目标系统:若依前后分离版 3.8.5,若依不分离版 4.5.0

新建自己的模块与若依代码分隔使用

在根项目下新建模块,比如叫business,组名是com.ruoyi,工件名business特别强调,使用代码生成功能时尽量以纯小写、驼峰命名,不要加-之类的额外字符,容易翻车。
image
创建后的目录结构如下
image

修改business模块的pom.xml,添加ruoyi-framework依赖

<!-- 将依赖添加到新模块的pom.xml-->
    <dependencies>
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-framework</artifactId>
        </dependency>
    </dependencies>

ruoyi-admin中添加business模块的依赖
image
检查根项目ruoyi下的pom.xmlmodules中是否正确添加了新的(包括正确移除了不存在)模块
image

菜单管理与代码生成的“冲突”

菜单管理可以通过非编码方式创建和管理菜单和按钮组件,但以下情况下可能会与代码生成产生冲突:
建目录A,目录A下建菜单A1,建立菜单时会让你填写路由地址、组件路径、权限字符、路由参数等,我不太明白填写后的影响,就填写并生成菜单。之后在代码生成的生成信息部分可选择上级菜单,此时就是冲突的地方。如果选择了目录A,就会在目录A下产生两个菜单A1,如果选择菜单A1,就会在菜单A1(菜单管理创建的)下又有菜单A1(代码生成创建的)。经过分析推测是我的用法不对,猜测这两个功能应该是互相补充、互相配合的关系。

改进使用方式如下:主要思路是通过菜单管理功能建立单纯的如目录这样自身没有后端请求逻辑的菜单,如果目录的下级菜单没有请求逻辑也可以如此。之后使用代码生成功能生成前后端代码,在代码生成时通过在生成信息部分选择上级菜单的方式,将生成的代码绑定到菜单,也就是通过菜单管理创建目录,通过代码生成创建具体菜单,过程举例:
创建目录企业管理
image
生成对应代码
image
image
image
生成代码的对应结构
image
对所生成的前端代码来说,刚才填写的对应关系如下
image
对所生成的后端代码来说,刚才填写的对应关系如下
image

使用生成的代码:解压缩ruoyi.zip,运行生成的Sql脚本,将vue目录下的文件放到前端src目录,将main目录下文件放到自己创建的Java模块下。再次重新分别启动前后端项目(如有意外,可以试试关闭Idea、rebuild、重启电脑)可以看到效果
image

引用
若依管理系统RuoYi-Vue(三):代码生成器原理和实战 https://www.cnblogs.com/kuangdaoyizhimei/p/14452736.html

查询排序(前后分离版)

由前端控制排序比较灵活,也易于实现,有关逻辑若依已经封装,后端如果懒的话都可以不做任何了解,前端实现控制如下

参数指定,在查询参数中提供约定好的参数即可,orderByColumn指定用于排序的字段名,isAsc指定排序规则,如

queryParams: {
pageNum: 1,
pageSize: 10,
orderByColumn: 'id',
isAsc: 'desc'
}

若依框架认识这两个参数,在后台接到查询参数时会自动按要求查询并返回结果,后端开发人员无需额外编写代码。

table组件控制,若依分离版默认使用element-ui组件,表格组件table提供了丰富的api,官方文档中有关于排序的使用描述,此处仅记录关键部分。table组件的排序能力分两种,一种是不需要后端参与的,仅对前端中已经获得的数据进行排序,要达到这个效果对列设置sortable即可,该列就会出现上下小箭头,点击列,显示的数据即会改变排序顺序。

<el-table-column label="Id" align="center" sortable prop="id"/>

第二种,真正的前端请求后端排序,首先将sortable改为sortable=custom,然后给table组件增加sort-change事件的侦听,在事件回调中向后台发起请求,实现“真”排序。

<el-table @sort-change="handleSortChange">
<el-table-column label="Id" align="center" sortable="custom" prop="id"/>
</el-table>
...
methods: {
   // options.prop: 引发排序事件的列绑定的 prop 属性
   // options.order: 排序顺序,null-默认/不正不反/没有箭头被点亮,ascending-正序/箭头向上,descending-倒序/箭头向下
   handleSortChange(options){
      // 向后端发起请求
   }
}

image

多数据源配置

首先,在配置文件spring:datasource:druid中增加数据源配置

spring:
  datasource:
    druid:
	  master: xxx
	  slavebi:
	    enabled: true
		url: jdbc:sqlserver://19.19.19.19:1433;DatabaseName=mydb;
		username: root
		password: 123456

image

ruoyi-common\enums\DataSourceType文件中增加对应枚举声明

public enum DataSourceType{
 MASTER,
 SLAVEBI
}

image

ruoyi-framework\config\properties\DruidConfig文件中增加对应方法

    @Bean
    @ConfigurationProperties("spring.datasource.druid.slave")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true")
    public DataSource slavebiDataSource(DruidProperties druidProperties)
    {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }
	
	@Bean(name = "dynamicDataSource")
    @Primary
    public DynamicDataSource dataSource(DataSource masterDataSource)
    {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
        setDataSource(targetDataSources, DataSourceType.SLAVEBI.name(), "slavebiDataSource");
        return new DynamicDataSource(masterDataSource, targetDataSources);
    }
	
	 /**
     * 设置数据源
     * 
     * @param targetDataSources 备选数据源集合
     * @param sourceName 数据源名称
     * @param beanName bean名称
     */
    public void setDataSource(Map<Object, Object> targetDataSources, String sourceName, String beanName)
    {
        try
        {
            DataSource dataSource = SpringUtils.getBean(beanName);
            targetDataSources.put(sourceName, dataSource);
        }
        catch (Exception e)
        {
        }
    }

image

在Service、Mapper或方法上使用@DataSource注解的方式切换数据源来使用

/**
 * SmartBI 查询相关Mapper接口
 * @author
 */
@Repository
@DataSource(value = DataSourceType.SLAVEBI)
public interface ContractSmartBIMapper {
    /**
     * 从SmartBI查询采购订单和相关预算信息
     * @param purchaseOrderDocNo 合同(采购订单)号
     * @return
     */
    public List<ContractBudgetBo> selectContractBudgetBoList(String purchaseOrderDocNo);
}

自定义拦截器

Spring Boot 拦截器

首先自定义类实现HandlerInterceptor,在实现WebMvcConfigurer的实现类的addInterceptors方法中加入自定义拦截器实现类的实例即可

package com.ruoyi.framework.interceptor;

import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

/**
 * 自定义拦截器
 */
@Component
public class CustomInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler) throws Exception {
        System.out.println("调用Controller方法之前");

        if(handler instanceof HandlerMethod){
            System.out.println("CustomInterceptor preHandle: do preHandle");
            if(1==1){
                return false;
            }
        }else{
            System.out.println("CustomInterceptor preHandle: super preHandle");
            return HandlerInterceptor.super.preHandle(request, response, handler);
        }

        return true;
    }
    
    @Override
    public void postHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, Object modelAndView) throws Exception {
        System.out.println("调用Controller方法之后页面渲染之前执行");
    }
    
    @Override
    public void afterCompletion(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("调用Controller方法之后页面渲染之后执行");
    }
}

配置拦截器

@Configuration
public class ResourcesConfig implements WebMvcConfigurer
{
	@Autowired
    private RepeatSubmitInterceptor repeatSubmitInterceptor;

    @Autowired
    private CustomInterceptor myInterceptor;
	
    @Override
    public void addInterceptors(InterceptorRegistry registry)
    {
        registry.addInterceptor(myInterceptor).addPathPatterns("/**");
        registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
    }
}

控制台输出效果
image

posted @ 2023-01-26 14:45  试试手气  阅读(375)  评论(0编辑  收藏  举报