首页 > 其他分享 >关于数据同步的探索(一)

关于数据同步的探索(一)

时间:2023-12-02 12:33:17浏览次数:18  
标签:同步 remote 探索 remoteInfo local 关于 items var localInfo

开发过程中,自己经常会弄一些小工具。
考虑到数据的同步,经常会用自己云服务器上的数据库。
但是采用这种方式的缺点是,如果网络环境比较差的时候,比方说,在客户单位,用手机流量来访问,有时候信号还不是特别好的时候,体验就不是特别好。
甚至有时候,希望离线能操作。
其实我最喜欢的方式还是【离线操作】+【数据同步】的功能。
所以有时候就觉得GIT真的非常方便,平常完全可以离线操作,需要的时候进行同步。
然后开始对数据的同步方式加了各种探索。

最开始的方式是:
对每个数据都加一个DataGuid,数据被初次创建的时候自动生成,一旦创建后就不会变,作为这个数据的唯一标识。
然后每个数据再加一个DataVersionGuid,每次对数据进行修改的时候进行更新,用于同步时对同一个DataGuid的数据进行是否相同的比较。
仅仅知道两个数据是否相同还不够,还需要知道两个DataVersionGuid之间的关系。
所以又弄了一个VersionHistory的类

using FreeSql.DataAnnotations;

namespace NugetManager.Models;

[Table(Name = "ng_version_history")]
public class VersionHistory : IBaseInfo
{
    [Column(IsIdentity = true, IsPrimary = true)]
    public int ID { get; set; }

    [Column(IsNullable = false)]
    public string HistoryGuid { get; set; }

    public string DataType { get; set; }
    public OperationType Operation { get; set; }

    [Column(IsNullable = false)]
    public string DataGuid { get; set; }

    [Column(IsNullable = false)]
    public string NewVersionGuid { get; set; }

    [Column(IsNullable = false)]
    public string OldVersionGuid { get; set; }

    public DateTime CreateTime { get; set; }

    public VersionHistory()
    {
        CreateTime = DateTime.Now;
        HistoryGuid = System.Guid.NewGuid().ToString();
    }

    public VersionHistory(string dataType, OperationType operation, string dataGuid, string oldVersionGuid, string newVersionGuid) : this()
    {
        DataType = dataType;
        Operation = operation;
        DataGuid = dataGuid;
        OldVersionGuid = oldVersionGuid;
        NewVersionGuid = newVersionGuid;
    }
}

public enum OperationType
{
    Add,
    Edit,
    Delete
}

HistoryGuid:VersionHistory数据本身的Guid,作为VersionHistory数据的唯一标识,创建数据时自动生成。
DataType:用来标识这个是哪种数据的历史数据,作为过滤条件用。
DataGuid: 发生变更的数据的DataGuid
Operation:操作类型,主要是增删改这三种操作
NewVersionGuid:变更前的DataVersionGuid
OldVersionGuid:变更后的DataVersionGuid

相当于对数据增删改的时候,都生成一条VersionHistory记录。
后续需要同步的时候,根据VersionHistory来决定如何进行数据操作。

这种方式的缺点:
1、对数据的准确要求很高,必须都是通过这种方式生成的。对于像我一样,拿之前的工具和数据来改的,比较容易因为版本数据不对,导致同步出错。
2、多了很多的版本数据,相当于每进行一次操作都必须严格记录。
3、还是会有冲突的问题,相当于一个版本A,一个终端把A改成了B,另一个终端把A改成了C,然后进行同步的时候,B和C是没有继承关系的,所以还是需要人为决定以哪个为准。
4、逻辑步骤有点多,出错的概念相对会更高。

因为跟理想的方便安全还是有点差距,于是我又开始进一步的探索,看我的下一个帖子。

下面是我用来操作数据的类:

using NugetManager;

namespace CgdataBase;

public partial class DataHelper : IDisposable
{
    public int AddNugetInfo(NugetInfo info)
    {
        var versionGuid = Guid.NewGuid().ToString();
        var version = new VersionHistory(nameof(NugetInfo), OperationType.Add, info.NugetGuid, null, versionGuid);
        AddDataInfo(version);

        info.VersionGuid = versionGuid;
        info.UpdateTime = DateTime.Now;
        return AddDataInfo(info);
    }

    public void AddNugetInfos(IEnumerable<NugetInfo> items)
    {
        var versionList = new List<VersionHistory>();
        items.ForEach(s =>
        {
            var versionGuid = Guid.NewGuid().ToString();
            versionList.Add(new VersionHistory(nameof(NugetInfo), OperationType.Add, s.NugetGuid, null, versionGuid));

            s.VersionGuid = versionGuid;
            s.UpdateTime = DateTime.Now;
        });
        AddDataInfos(versionList);

        AddDataInfos(items);
    }

    public void UpdateNugetInfo(NugetInfo info)
    {
        var versionGuid = Guid.NewGuid().ToString();
        var version = new VersionHistory(nameof(NugetInfo), OperationType.Edit, info.NugetGuid, info.VersionGuid, versionGuid);
        AddDataInfo(version);

        info.VersionGuid = versionGuid;
        info.UpdateTime = DateTime.Now;
        UpdateDataInfo(info);
    }

    public void UpdateNugetInfos(IEnumerable<NugetInfo> items)
    {
        var versionList = new List<VersionHistory>();
        items.ForEach(s =>
        {
            var versionGuid = Guid.NewGuid().ToString();
            versionList.Add(new VersionHistory(nameof(NugetInfo), OperationType.Edit, s.NugetGuid, s.VersionGuid, versionGuid));

            s.VersionGuid = versionGuid;
            s.UpdateTime = DateTime.Now;
        });
        AddDataInfos(versionList);

        UpdateDataInfos(items);
    }

    public void DeleteNugetInfos(IEnumerable<NugetInfo> items)
    {
        var versionList = new List<VersionHistory>();
        items.ForEach(item =>
        {
            versionList.Add(new VersionHistory(nameof(NugetInfo), OperationType.Delete, item.NugetGuid, item.VersionGuid, null));
        });
        AddDataInfos(versionList);

        DeleteDataInfos(items);
    }

    public int AddGroupInfo(GroupInfo info)
    {
        var versionGuid = Guid.NewGuid().ToString();
        var version = new VersionHistory(nameof(GroupInfo), OperationType.Add, info.GroupGuid, null, versionGuid);
        AddDataInfo(version);

        info.VersionGuid = versionGuid;
        info.UpdateTime = DateTime.Now;
        return AddDataInfo(info);
    }

    public void AddGroupInfos(IEnumerable<GroupInfo> items)
    {
        var versionList = new List<VersionHistory>();
        items.ForEach(s =>
        {
            var versionGuid = Guid.NewGuid().ToString();
            versionList.Add(new VersionHistory(nameof(GroupInfo), OperationType.Add, s.GroupGuid, null, versionGuid));

            s.VersionGuid = versionGuid;
            s.UpdateTime = DateTime.Now;
        });
        AddDataInfos(versionList);

        AddDataInfos(items);
    }

    public void UpdateGroupInfo(GroupInfo info)
    {
        var versionGuid = Guid.NewGuid().ToString();
        var version = new VersionHistory(nameof(GroupInfo), OperationType.Edit, info.GroupGuid, info.VersionGuid, versionGuid);
        AddDataInfo(version);

        info.VersionGuid = versionGuid;
        info.UpdateTime = DateTime.Now;
        UpdateDataInfo(info);
    }

    public void UpdateGroupInfos(IEnumerable<GroupInfo> items)
    {
        var versionList = new List<VersionHistory>();
        items.ForEach(s =>
        {
            var versionGuid = Guid.NewGuid().ToString();
            versionList.Add(new VersionHistory(nameof(GroupInfo), OperationType.Edit, s.GroupGuid, s.VersionGuid, versionGuid));

            s.VersionGuid = versionGuid;
            s.UpdateTime = DateTime.Now;
        });
        AddDataInfos(versionList);

        UpdateDataInfos(items);
    }

    public void DeleteGroupInfo(GroupInfo info)
    {
        var version = new VersionHistory(nameof(GroupInfo), OperationType.Delete, info.GroupGuid, info.VersionGuid, null);
        AddDataInfo(version);

        DeleteDataInfo(info);
    }

    public void UpdateDatabase()
    {
        OnUpdateGroupInfo();
        OnUpdateNugetInfo();
    }

    private void OnUpdateNugetInfo()
    {
        var items = SelectAll<NugetInfo>();
        items.ForEach(s =>
        {
            s.NugetGuid = Guid.NewGuid().ToString();
            s.VersionGuid = Guid.NewGuid().ToString();
        });
        UpdateDataInfos(items);
    }

    private void OnUpdateGroupInfo()
    {
        var items = SelectAll<GroupInfo>();
        items.ForEach(s => s.VersionGuid = Guid.NewGuid().ToString());
        UpdateDataInfos(items);
    }

    [Logging]
    public static void SynchronizeData(DataHelper local, AppSettings settings)
    {
        using (var remote = new DataHelper())
        {
            remote.Initialize(settings.DatabaseType, settings.DatabaseConnectionString, true);

            var now = DateTime.Now;
            SynchronizeData(local, remote, settings.LastSyncTime);
            settings.LastSyncTime = now;
            settings.Save();
        }
    }

    public static void SynchronizeData(DataHelper local, DataHelper remote, DateTime time)
    {
        SynchronizeVersionHistory(local, remote, time);
        SynchronizeGroupInfo(local, remote, time);
        SynchronizeNugetInfo(local, remote, time);
    }

    private static void SynchronizeNugetInfo(DataHelper local, DataHelper remote, DateTime time)
    {
        var remoteItems = remote.Select<NugetInfo>(s => s.UpdateTime >= time);
        var localItems = local.Select<NugetInfo>(s => s.UpdateTime >= time);

        if (remoteItems.IsNullOrEmpty() && localItems.IsNullOrEmpty())
            return;

        foreach (var remoteInfo in remoteItems)
        {
            var localInfo = local.First<NugetInfo>(s => s.NugetGuid == remoteInfo.NugetGuid);
            if (localInfo == null)
            {
                var del = local.First<VersionHistory>(s => s.DataGuid == remoteInfo.NugetGuid && s.Operation == OperationType.Delete);
                if (del != null && del.OldVersionGuid == remoteInfo.VersionGuid)
                {
                    remote.DeleteDataInfo(remoteInfo);
                }
                else
                {
                    local.AddDataInfo(remoteInfo);
                }
            }
            else
            {
                CompareDataVersion(local, remote, localInfo, remoteInfo);
            }
        }

        foreach (var localInfo in localItems)
        {
            var remoteInfo = remote.First<NugetInfo>(s => s.NugetGuid == localInfo.NugetGuid);
            if (remoteInfo == null)
            {
                var del = remote.First<VersionHistory>(s => s.DataGuid == localInfo.NugetGuid && s.Operation == OperationType.Delete);
                if (del != null && del.OldVersionGuid == localInfo.VersionGuid)
                {
                    local.DeleteDataInfo(localInfo);
                }
                else
                {
                    remote.AddDataInfo(localInfo);
                }
            }
            else
            {
                CompareDataVersion(local, remote, localInfo, remoteInfo);
            }
        }
    }

    private static void CompareDataVersion(DataHelper local, DataHelper remote, NugetInfo localInfo, NugetInfo remoteInfo)
    {
        if (localInfo.VersionGuid != remoteInfo.VersionGuid)
        {
            var result = CompareDataVersion(local, localInfo.NugetGuid, localInfo.VersionGuid, remoteInfo.VersionGuid);
            if (result > 0)
            {
                CopyNugetInfo(local, localInfo, remoteInfo);
            }
            else if (result < 0)
            {
                CopyNugetInfo(remote, remoteInfo, localInfo);
            }
            else
            {
                var localText = localInfo.ToString();
                var remoteText = remoteInfo.ToString();
                if (localInfo.Compare(remoteInfo))
                {
                    CopyNugetInfo(local, localInfo, remoteInfo);
                }
                else
                {
                    App.Current.Dispatcher.Invoke(() =>
                    {
                        var win = new WinDiffViewer(localText, remoteText) { Owner = App.Current.MainWindow };
                        if (win.ShowDialog() == true)
                        {
                            switch (win.Operations)
                            {
                                case CompareOperations.Abort:
                                    throw new Exception("同步已中断");

                                case CompareOperations.Remote:
                                    CopyNugetInfo(local, localInfo, remoteInfo);
                                    break;

                                case CompareOperations.Local:
                                    CopyNugetInfo(remote, remoteInfo, localInfo);
                                    break;

                                case CompareOperations.Skip:
                                    break;

                                default:
                                    break;
                            }
                        }
                        else
                        {
                            throw new Exception("同步已中断");
                        }
                    });
                }
            }
        }
    }

    private static void CopyNugetInfo(DataHelper local, NugetInfo localInfo, NugetInfo remoteInfo)
    {
        localInfo.Name = remoteInfo.Name;
        localInfo.PackageName = remoteInfo.PackageName;

        localInfo.Framework = remoteInfo.Framework;
        localInfo.LowVersion = remoteInfo.LowVersion;
        localInfo.LowFramework = remoteInfo.LowFramework;
        localInfo.WebUrl = remoteInfo.WebUrl;
        localInfo.Remark = remoteInfo.Remark;
        localInfo.UsageTimes = remoteInfo.UsageTimes;
        localInfo.Level = remoteInfo.Level;
        localInfo.GroupGuid = remoteInfo.GroupGuid;

        localInfo.CreateTime = remoteInfo.CreateTime;
        localInfo.UpdateTime = remoteInfo.UpdateTime;

        localInfo.SortIndex = remoteInfo.SortIndex;
        localInfo.VersionGuid = remoteInfo.VersionGuid;

        local.UpdateDataInfo(localInfo);
    }

    private static void SynchronizeGroupInfo(DataHelper local, DataHelper remote, DateTime time)
    {
        var remoteItems = remote.Select<GroupInfo>(s => s.CreateTime >= time);
        var localItems = local.Select<GroupInfo>(s => s.CreateTime >= time);

        if (remoteItems.IsNullOrEmpty() && localItems.IsNullOrEmpty())
            return;

        foreach (var remoteInfo in remoteItems)
        {
            var localInfo = local.First<GroupInfo>(s => s.GroupGuid == remoteInfo.GroupGuid);
            if (localInfo == null)
            {
                var del = local.First<VersionHistory>(s => s.DataGuid == remoteInfo.GroupGuid && s.Operation == OperationType.Delete);
                if (del != null && del.OldVersionGuid == remoteInfo.VersionGuid)
                {
                    remote.DeleteDataInfo(remoteInfo);
                }
                else
                {
                    local.AddDataInfo(remoteInfo);
                }
            }
            else
            {
                CompareClassVersion(local, remote, localInfo, remoteInfo);
            }
        }

        foreach (var localInfo in localItems)
        {
            var remoteInfo = remote.First<GroupInfo>(s => s.GroupGuid == localInfo.GroupGuid);
            if (remoteInfo == null)
            {
                var del = remote.First<VersionHistory>(s => s.DataGuid == localInfo.GroupGuid && s.Operation == OperationType.Delete);
                if (del != null && del.OldVersionGuid == localInfo.VersionGuid)
                {
                    local.DeleteDataInfo(localInfo);
                }
                else
                {
                    remote.AddDataInfo(localInfo);
                }
            }
            else
            {
                CompareClassVersion(local, remote, localInfo, remoteInfo);
            }
        }
    }

    private static void CompareClassVersion(DataHelper local, DataHelper remote, GroupInfo localInfo, GroupInfo remoteInfo)
    {
        if (localInfo.VersionGuid != remoteInfo.VersionGuid)
        {
            var result = CompareDataVersion(local, localInfo.GroupGuid, localInfo.VersionGuid, remoteInfo.VersionGuid);
            if (result > 0)
            {
                CopyGroupInfo(local, localInfo, remoteInfo);
            }
            else if (result < 0)
            {
                CopyGroupInfo(remote, remoteInfo, localInfo);
            }
            else
            {
                var localText = localInfo.ToString();
                var remoteText = remoteInfo.ToString();
                if (localInfo.Compare(remoteInfo))
                {
                    CopyGroupInfo(local, localInfo, remoteInfo);
                }
                else
                {
                    App.Current.Dispatcher.Invoke(() =>
                    {
                        var win = new WinDiffViewer(localText, remoteText) { Owner = App.Current.MainWindow };
                        if (win.ShowDialog() == true)
                        {
                            switch (win.Operations)
                            {
                                case CompareOperations.Abort:
                                    throw new Exception("同步已中断");

                                case CompareOperations.Remote:
                                    CopyGroupInfo(local, localInfo, remoteInfo);
                                    break;

                                case CompareOperations.Local:
                                    CopyGroupInfo(remote, remoteInfo, localInfo);
                                    break;

                                case CompareOperations.Skip:
                                    break;

                                default:
                                    break;
                            }
                        }
                        else
                        {
                            throw new Exception("同步已中断");
                        }
                    });
                }
            }
        }
    }

    private static void CopyGroupInfo(DataHelper local, GroupInfo localInfo, GroupInfo remoteInfo)
    {
        localInfo.GroupName = remoteInfo.GroupName;
        localInfo.CreateTime = remoteInfo.CreateTime;
        localInfo.UpdateTime = remoteInfo.UpdateTime;
        localInfo.GroupGuid = remoteInfo.GroupGuid;
        localInfo.Count = remoteInfo.Count;
        localInfo.SortIndex = remoteInfo.SortIndex;
        localInfo.VersionGuid = remoteInfo.VersionGuid;

        local.UpdateDataInfo(localInfo);
    }

    private static void SynchronizeVersionHistory(DataHelper local, DataHelper remote, DateTime time)
    {
        var remoteItems = remote.Select<VersionHistory>(s => s.CreateTime >= time);
        var localItems = local.Select<VersionHistory>(s => s.CreateTime >= time);

        if (remoteItems.IsNullOrEmpty() && localItems.IsNullOrEmpty())
            return;

        var remoteGuids = remoteItems.Select(s => s.HistoryGuid).ToArray();
        var localGuids = localItems.Select(s => s.HistoryGuid).ToArray();

        var remoteAdds = remoteGuids.Except(localGuids).ToArray();
        var localAdds = localGuids.Except(remoteGuids).ToArray();

        if (remoteAdds.HadItems())
        {
            local.AddDataInfos(remoteItems.Where(s => remoteAdds.Contains(s.HistoryGuid)));
        }
        if (localAdds.HadItems())
        {
            remote.AddDataInfos(localItems.Where(s => localAdds.Contains(s.HistoryGuid)));
        }
    }

    /// <summary>
    /// 比较版本
    /// </summary>
    /// <param name="local"></param>
    /// <param name="dataGuid"></param>
    /// <param name="versionGuid1"></param>
    /// <param name="versionGuid2"></param>
    /// <returns>
    /// >0      versionGuid2是versionGuid1的新版本
    /// <0      versionGuid1是versionGuid2的新版本
    /// ==0     这个版本没有直接的继承关系
    /// </returns>
    private static int CompareDataVersion(DataHelper local, string dataGuid, string versionGuid1, string versionGuid2)
    {
        if (versionGuid1.IsNullOrEmpty() || versionGuid2.IsNullOrEmpty())
            return 0;

        var items = local.Select<VersionHistory>(s => s.DataGuid == dataGuid);
        if (items.IsNullOrEmpty())
            return 0;

        if (IsChild(items, versionGuid1, versionGuid2) == true)
            return 1;

        if (IsParent(items, versionGuid1, versionGuid2) == true)
            return -1;

        if (!items.Any(s => s.OldVersionGuid == versionGuid1 || s.NewVersionGuid == versionGuid1) || !items.Any(s => s.OldVersionGuid == versionGuid2 || s.NewVersionGuid == versionGuid2))
            return 0;

        return 0;
    }

    private static bool IsParent(List<VersionHistory> items, string versionGuid1, string versionGuid2)
    {
        var nextVersion = items.FirstOrDefault(s => s.OldVersionGuid == versionGuid2);

        while (nextVersion != null && nextVersion.NewVersionGuid != null)
        {
            if (nextVersion.NewVersionGuid == versionGuid1)
                return true;

            nextVersion = items.FirstOrDefault(s => s.OldVersionGuid == nextVersion.NewVersionGuid);
        }

        return false;
    }

    private static bool IsChild(List<VersionHistory> items, string versionGuid1, string versionGuid2)
    {
        var prevVersion = items.FirstOrDefault(s => s.NewVersionGuid == versionGuid2);

        while (prevVersion != null && prevVersion.OldVersionGuid != null)
        {
            if (prevVersion.OldVersionGuid == versionGuid1)
                return true;

            prevVersion = items.FirstOrDefault(s => s.NewVersionGuid == prevVersion.OldVersionGuid);
        }

        return false;
    }
}

标签:同步,remote,探索,remoteInfo,local,关于,items,var,localInfo
From: https://www.cnblogs.com/wzwyc/p/17871448.html

相关文章

  • 拓数派受邀参加由Google举办的“深度探索 LLM / Generative AI的生态与应用”主题活动
    大语言模型(LLM)可谓是当下国内科创界最热门的话题。近日,拓数派创始人兼CEO冯雷(RayVon)受邀参加由Google举办的“深度探索LLM/GenerativeAI的生态与应用”主题活动,与现场嘉宾共话科技行业发展新趋势。图为:活动现场照片在圆桌讨论环节中,冯雷与主持人及几位创业公司高管,进行了一场......
  • 关于 FontAwesome icon 的 before 伪元素
    看下图这个放大镜的例子:.fa-search:before是一个CSS选择器,它被用于指定某个具有类名为"fa-search"的元素的伪元素":before"。这个样式规则的作用是在该元素的内容之前插入一个字符,具体的字符是"\f002"。在这里,"\f002"是一个Unicode字符码,它通常用于表示字体图标。FontA......
  • 关于 Web 开发中的 CSS before 伪元素
    我用Chrome打开一个网页后,F12打开Chrome开发者工具,在Elements面板观察到一些DOM元素有::before,这是什么含义?在Web前端开发中,::before是CSS伪元素之一,它用于在指定元素的内容前插入生成的内容。这个伪元素允许开发者通过CSS样式向元素的前部添加额外的内容,而无需修......
  • INFINI Labs 产品更新 | 修复 Easysearch 跨集群复制索引同步问题,Gateway 内存异常增
    INFINILabs产品又更新啦~,本次更新主要对Easysearch、Gateway、Console、Agent等产品功能进行优化和相关Bug修复,解决了内存异常增长等问题,以下是详细说明。INFINIEasysearchv1.6.2INFINIEasysearch是一个分布式的近实时搜索与分析引擎,核心引擎基于开源的ApacheLucene......
  • 关于Vue3中调试APP触发异常:exception:white screen cause create instanceContext fai
    bug:reportJSException>>>>exceptionfunction:createInstanceContext,exception:whitescreencausecreateinstanceContextfailed,checkjsstack->atuseStore(app-service.js:2309:15)问题在于:使用了pinia,并且在所有js文件或ts文件中调用超前,导致的加载错误 解决方......
  • TWS耳机电量在手机上同步显示方法
    出处:https://www.wpgdadatong.com.cn/blog/detail/40711 ADK6.x的Earbud工程,默认是有一个电量通知的,但这个电量通知用的AT指令是AT+BIEV,这个指令在苹果和少数安卓机上有用,所以这不满足大部分用户的需求。因此我们需要用AT+IPHONEACCEV指令去把这个电量通知出去。但是......
  • 案例解析关于ArkUI框架中ForEach的潜在陷阱与性能优化
    本文分享自华为云社区《深入解析ForEach的潜在陷阱与性能优化:错误用法与性能下降的案例分析》,作者:柠檬味拥抱。在ArkUI框架中,ForEach接口是基于数组类型数据进行循环渲染的强大工具。它需要与容器组件搭配使用,并能够根据数据源动态生成相应的子组件。以下是对ForEach接口的详细......
  • 【xargs】关于 xargs 的使用
    xargs参数使用(1)使用xargs执行指令:有一个info.log文件catinfo.logabc使用一下xargs,这样看起来意义不大catinfo.log|xargsechoabc可以换一个场景,在某个文件夹下,找到指定文件名的文件,然后删除它find./test/|grep-v不能删|xargsrmfind./test......
  • 音视频FAQ(三):音画不同步
    摘要本文介绍了音画不同步问题的五个因素:编码和封装阶段、网络传输阶段、播放器中的处理阶段、源内容产生的问题以及转码和编辑。针对这些因素,提出了相应的解决方案,如使用标准化工具、选择强大的传输协议、自适应缓冲等。此外,介绍了第三方音视频服务商如即构的解决方案,包括优化的......
  • [Maven]关于Maven的生命周期与命令
    关于Maven的生命周期与命令工作的时候对Maven的install和package的使用产生了一些疑问,干脆将Maven的整个生命周期都复习总结一遍。先看下在IDEA中Maven的生命周期节点:cleanclean是清理命令,相当于执行了mvnclean命令。清理当前工程编译后生成的文件,也就是删除整个target目......