Java实现递归删除菜单和删除目录及目录下所有文件

目录

一、什么是递归?

二、示例分析


一、什么是递归?

递归调用是一种特殊的嵌套调用,是某个函数调用自己或者是调用其他函数后再次调用自己的,只要函数之间互相调用能产生循环的则一定是递归调用,递归调用一种解决方案,一种是逻辑思想,将一个大工作分为逐渐减小的小工作,比如说一个和尚要搬50块石头,他想,只要先搬走49块,那剩下的一块就能搬完了,然后考虑那49块,只要先搬走48块,那剩下的一块就能搬完了,递归是一种思想,只不过在程序中,就是依靠函数嵌套这个特性来实现了。

递归调用就是在当前的函数中调用当前的函数并传给相应的参数,这是一个动作,这一动作是层层进行的,直到满足一般情况的的时候,才停止递归调用,开始从最后一个递归调用返回。

二、示例分析

案例1:递归删除菜单及其所有子菜单

  • 菜单实体类
java 复制代码
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;
import java.util.Date;

/**
 * 系统菜单
 */
@Data
@TableName(value = "menu")
public class Menu implements Serializable {

    private static final long serialVersionUID = 1L;

    /*** 菜单ID*/
    @TableId(type = IdType.INPUT)
    private Long menuId;

    /*** 父级菜单ID*/
    private Long upMenuId;

    /*** 菜单编码*/
    private String menuCode;

    /*** 菜单名称*/
    private String menuName;

    /*** 菜单级别(默认1级)*/
    private Integer menuLevel;

    /*** 菜单页面打开方式(1-本页面打开 2 新标签页打开 3-新窗口打开)*/
    private Integer pageOpenType;

    /*** 菜单类型(1-菜单 2-权限按钮)*/
    private Integer menuType;

    /*** 菜单图标*/
    private String menuIcon;

    /*** 菜单URL*/
    private String menuUrl;

    /*** 菜单序号*/
    private Integer menuOrder;

    /*** 菜单描述*/
    private String menuDesc;

    /*** 数据状态(0-删除 1-正常) */
    private Integer dataFlag;

    /*** 是否禁用(0-否 1-是)*/
    private Integer isDisable;

    /*** 创建人ID*/
    private Long createId;

    /*** 创建时间*/
    private Date createTime;

}
  • 实现代码
java 复制代码
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.test.java.domain.entity.Menu;
import com.test.java.mapper.MenuMapper;
import com.test.java.service.MenuService;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

public class MenuServiceImpl implements MenuService {

    @Resource
    private MenuMapper menuMapper;

    @Override
    public Integer deleteMenuById(Long menuId) {
        // 校验当前要删除的菜单是否存在
        Menu menu = menuMapper.selectById(menuId);
        if (null == menu) {
            throw new RuntimeException("菜单已删除");
        }

        // 创建list集合,用于封装所有要删除的菜单ID
        List<Long> menuIdList = new ArrayList<>();
        // 向menuIdList集合设置删除菜单id(根据id删除菜单)
        this.queryMenuChildById(menuId, menuIdList);
        // 把当前菜单id封装到idList里面
        menuIdList.add(menuId);

        // 批量删除当前菜单 及其所有子菜单
        return menuMapper.deleteBatchIds(menuIdList);
    }


    // 根据当前菜单id,查询其所有子菜单id,再封装到idList集合
    private void queryMenuChildById(Long menuId, List<Long> idList) {
        // 查询菜单里面子菜单id
        QueryWrapper<Menu> wrapper = new QueryWrapper<>();
        wrapper.eq("up_menu_id", menuId);
        List<Menu> childMenuList = menuMapper.selectList(wrapper);
        if (!CollectionUtils.isEmpty(childMenuList)) {
            // 把childMenuList里面菜单id值获取出来,封装idList里面,做递归查询
            childMenuList.forEach(item -> {
                //封装idList里面
                idList.add(item.getMenuId());
                //递归查询
                this.queryMenuChildById(item.getMenuId(), idList);
            });
        }
    }

}

案例2:递归删除目录及其目录中所有文件

  • 实现代码
java 复制代码
import lombok.extern.slf4j.Slf4j;

import java.io.File;

/**
 * 文件相关工具类
 */
@Slf4j
public class FileUtils {

    /**
     * 删除文件或文件夹
     *
     * @param path 文件路径
     * @return 返回true(删除成功), 返回false(删除失败)
     */
    public static boolean deleteFileOrDirectory(String path) {
        File file = new File(path);
        // 判断文件是否存在
        if (file.exists()) {
            // 判断是否为文件
            if (file.isFile()) {
                // 删除文件
                return deleteFile(path);
            } else {
                // 删除文件夹
                return deleteDirectory(path);
            }
        } else {
            return false;
        }
    }

    /**
     * 删除文件
     *
     * @param path 文件路径
     * @return 返回true(删除成功), 返回false(删除失败)
     */
    public static boolean deleteFile(String path) {

        boolean result = false;

        File file = new File(path);
        if (file.isFile() && file.exists()) {
            result = file.delete();
            log.info("删除文件成功:{}", path);
            return result;
        } else {
            log.info("删除文件失败:{}", path);
            return result;
        }
    }

    /**
     * 删除文件夹(先删文件再删目录)
     *
     * @param path 文件夹路径
     * @return 返回true(删除成功), 返回false(删除失败/文件夹不存在)
     */
    public static boolean deleteDirectory(String path) {
        if (!path.endsWith(File.separator)) {
            // 补齐文件分隔符
            path = path + File.separator;
        }
        File directoryFile = new File(path);
        // 文件不存在、不是一个目录就打印退出返回false
        if (!directoryFile.exists() || !directoryFile.isDirectory()) {
            log.info("文件夹不存在,{}", path);
            return false;
        }

        boolean flag = true;
        // 获取所有的子文件及子文件夹
        File[] files = directoryFile.listFiles();
        if (files != null) {
            // 循环删除
            for (File file : files) {
                // 删除子文件
                if (file.isFile()) {
                    flag = deleteFile(file.getAbsolutePath());
                    if (!flag) {
                        break;
                    }
                } else {// 删除子文件夹
                    flag = deleteDirectory(file.getAbsolutePath());
                    if (!flag) {
                        break;
                    }
                }
            }
        }
        if (!flag) {
            log.info("删除文件夹失败");
            return false;
        }
        // 最后删除当前文件夹
        if (directoryFile.delete()) {
            log.info("删除文件夹成功,{}", path);
            return true;
        } else {
            log.info("删除文件夹失败,{}", path);
            return false;
        }
    }

}

以上代码直接粘贴复制即可直接使用。

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、评论、收藏➕关注,您的支持是我坚持写作最大的动力。

相关推荐
神仙别闹7 分钟前
基于C#和Sql Server 2008实现的(WinForm)订单生成系统
开发语言·c#
XINGTECODE8 分钟前
海盗王集成网关和商城服务端功能golang版
开发语言·后端·golang
alphaTao10 分钟前
LeetCode 每日一题 2024/11/18-2024/11/24
算法·leetcode
天天扭码13 分钟前
五天SpringCloud计划——DAY2之单体架构和微服务架构的选择和转换原则
java·spring cloud·微服务·架构
程序猿进阶14 分钟前
堆外内存泄露排查经历
java·jvm·后端·面试·性能优化·oom·内存泄露
FIN技术铺18 分钟前
Spring Boot框架Starter组件整理
java·spring boot·后端
kitesxian19 分钟前
Leetcode448. 找到所有数组中消失的数字(HOT100)+Leetcode139. 单词拆分(HOT100)
数据结构·算法·leetcode
zwjapple24 分钟前
typescript里面正则的使用
开发语言·javascript·正则表达式
小五Five25 分钟前
TypeScript项目中Axios的封装
开发语言·前端·javascript
小曲程序26 分钟前
vue3 封装request请求
java·前端·typescript·vue