化零为整WCF(14) - 事务(Transaction)

[索引页]
[源码下载] 


化零为整WCF(14) - 事务(Transaction)


作者:webabcd


介绍
WCF(Windows Communication Foundation) - 事务(Transaction):
    ·对契约方法使用TransactionFlowAttribute声明(设置TransactionFlowOption参数),以指定服务操作的事务流策略
    ·对服务方法是用OperationBehaviorAttribute声明(设置TransactionScopeRequired参数),以指定方法是否在事务范围(TransactionScope)内执行
    ·配置host和client的binding节点的transactionFlow属性,以指定绑定是否支持流事务


示例
1、服务
Hello.cs
InBlock.gifusing System; 
InBlock.gifusing System.Collections.Generic; 
InBlock.gifusing System.Linq; 
InBlock.gifusing System.Text; 
InBlock.gif 
InBlock.gifusing System.ServiceModel; 
InBlock.gif 
InBlock.gifnamespace WCF.ServiceLib.Transaction 
InBlock.gif
InBlock.gif        /// <summary> 
InBlock.gif        /// IHello接口 
InBlock.gif        /// </summary> 
InBlock.gif        [ServiceContract] 
InBlock.gif        public interface IHello 
InBlock.gif        { 
InBlock.gif                /// <summary> 
InBlock.gif                /// 打招呼方法 
InBlock.gif                /// </summary> 
InBlock.gif                /// <param name="name">人名</param> 
InBlock.gif                /// <remarks> 
InBlock.gif                /// TransactionFlow - 指定服务操作是否愿意接受来自客户端的传入事务 
InBlock.gif                /// NotAllowed - 禁止事务。默认值 
InBlock.gif                /// Allowed - 允许事务 
InBlock.gif                /// Mandatory - 强制事务 
InBlock.gif                /// </remarks> 

InBlock.gif                /// <returns></returns> 
InBlock.gif                [OperationContract] 
InBlock.gif                [TransactionFlow(TransactionFlowOption.Mandatory)] 
InBlock.gif                void WriteHello(string name); 
InBlock.gif        } 
InBlock.gif 
InBlock.gif        /// <summary> 
InBlock.gif        /// Hello类 
InBlock.gif        /// </summary> 
InBlock.gif        public class Hello : IHello 
InBlock.gif        { 
InBlock.gif                /// <summary> 
InBlock.gif                /// 打招呼方法 
InBlock.gif                /// </summary> 
InBlock.gif                /// <param name="name">人名</param> 
InBlock.gif                /// <remarks> 
InBlock.gif                /// OperationBehavior - 指定服务方法的本地执行行为 
InBlock.gif                /// 1、TransactionScopeRequired - 如果方法需要事务范围才能执行,则为 true;否则为 false。默认值为false 
InBlock.gif                /// 将 TransactionScopeRequired 设置为 true,可以要求操作在事务范围内执行。如果流事务可用,则操作会在该事务内执行。如果流事务不可用,则会创建一个新事务并使用它来执行操作 
InBlock.gif                /// 2、TransactionAutoComplete - 默认值为 true 
InBlock.gif                /// true - 当方法完成执行时,将把该事务标志为完成(自动提交事务) 
InBlock.gif                /// false - 需要调用OperationContext.Current.SetTransactionComplete()方法来手工配置该事务的正确完成;否则,该事务将被标志为失败(手动提交事务) 
InBlock.gif                /// </remarks> 

InBlock.gif                /// <returns></returns> 
InBlock.gif                [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)] 
InBlock.gif                public void WriteHello(string name) 
InBlock.gif                { 
InBlock.gif                        DBDataContext ctx = new DBDataContext(); 
InBlock.gif 
InBlock.gif                        ctx.Items.InsertOnSubmit( 
InBlock.gif                                new Item 
InBlock.gif                                { 
InBlock.gif                                        Title = string.Format("Hello: {0}, TransactionId: {1}", name, System.Transactions.Transaction.Current.TransactionInformation.LocalIdentifier), 
InBlock.gif                                        CreatedTime = DateTime.Now 
InBlock.gif                                }); 
InBlock.gif 
InBlock.gif                        ctx.SubmitChanges(); 
InBlock.gif                } 
InBlock.gif        } 
InBlock.gif}
Hi.cs
InBlock.gifusing System; 
InBlock.gifusing System.Collections.Generic; 
InBlock.gifusing System.Linq; 
InBlock.gifusing System.Text; 
InBlock.gif 
InBlock.gifusing System.ServiceModel; 
InBlock.gif 
InBlock.gifnamespace WCF.ServiceLib.Transaction 
InBlock.gif
InBlock.gif        /// <summary> 
InBlock.gif        /// IHi接口 
InBlock.gif        /// </summary> 
InBlock.gif        [ServiceContract] 
InBlock.gif        public interface IHi 
InBlock.gif        { 
InBlock.gif                /// <summary> 
InBlock.gif                /// 打招呼方法 
InBlock.gif                /// </summary> 
InBlock.gif                /// <param name="name">人名</param> 
InBlock.gif                /// <returns></returns> 
InBlock.gif                [OperationContract] 
InBlock.gif                [TransactionFlow(TransactionFlowOption.Mandatory)] 
InBlock.gif                void WriteHi(string name); 
InBlock.gif        } 
InBlock.gif 
InBlock.gif        /// <summary> 
InBlock.gif        /// Hi类 
InBlock.gif        /// </summary> 
InBlock.gif        public class Hi : IHi 
InBlock.gif        { 
InBlock.gif                /// <summary> 
InBlock.gif                /// 打招呼方法 
InBlock.gif                /// </summary> 
InBlock.gif                /// <param name="name">人名</param> 
InBlock.gif                /// <returns></returns> 
InBlock.gif                [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)] 
InBlock.gif                public void WriteHi(string name) 
InBlock.gif                { 
InBlock.gif                        if (DateTime.Now.Second % 2 == 0) 
InBlock.gif                                throw new System.Exception("为测试事务而抛出的异常"); 
InBlock.gif 
InBlock.gif                        DBDataContext ctx = new DBDataContext(); 
InBlock.gif 
InBlock.gif                        ctx.Items.InsertOnSubmit( 
InBlock.gif                                new Item 
InBlock.gif                                { 
InBlock.gif                                        Title = string.Format("Hi: {0}, TransactionId: {1}", name, System.Transactions.Transaction.Current.TransactionInformation.LocalIdentifier), 
InBlock.gif                                        CreatedTime = DateTime.Now 
InBlock.gif                                }); 
InBlock.gif 
InBlock.gif                        ctx.SubmitChanges(); 
InBlock.gif                } 
InBlock.gif        } 
InBlock.gif}
Result.cs
InBlock.gifusing System; 
InBlock.gifusing System.Collections.Generic; 
InBlock.gifusing System.Linq; 
InBlock.gifusing System.Text; 
InBlock.gif 
InBlock.gifusing System.ServiceModel; 
InBlock.gif 
InBlock.gifnamespace WCF.ServiceLib.Transaction 
InBlock.gif
InBlock.gif        /// <summary> 
InBlock.gif        /// 结果接口 
InBlock.gif        /// </summary> 
InBlock.gif        [ServiceContract] 
InBlock.gif        public interface IResult 
InBlock.gif        { 
InBlock.gif                [OperationContract] 
InBlock.gif                List<Item> GetResult(); 
InBlock.gif        } 
InBlock.gif 
InBlock.gif        /// <summary> 
InBlock.gif        /// 结果类 
InBlock.gif        /// </summary> 
InBlock.gif        public class Result : IResult 
InBlock.gif        { 
InBlock.gif                /// <summary> 
InBlock.gif                /// 返回数据库结果 
InBlock.gif                /// </summary> 
InBlock.gif                /// <returns></returns> 
InBlock.gif                public List<Item> GetResult() 
InBlock.gif                { 
InBlock.gif                        DBDataContext ctx = new DBDataContext(); 
InBlock.gif 
InBlock.gif                        var result = from l in ctx.Items 
InBlock.gif                                                 orderby l.CreatedTime descending 
InBlock.gif                                                 select l; 
InBlock.gif 
InBlock.gif                        return result.ToList(); 
InBlock.gif                } 
InBlock.gif        } 
InBlock.gif}

2、宿主
Hello.svc
<%@ ServiceHost Language="C#" Debug="true" Service="WCF.ServiceLib.Transaction.Hello" %>
Hi.svc
<%@ ServiceHost Language="C#" Debug="true" Service="WCF.ServiceLib.Transaction.Hi" %>
Result.svc
<%@ ServiceHost Language="C#" Debug="true" Service="WCF.ServiceLib.Transaction.Result" %>
Web.config
<?xml version="1.0"?> 
<configuration> 
        <system.serviceModel> 
                <behaviors> 
                        <serviceBehaviors> 
                                <behavior name="TransactionBehavior"> 
                                        <!--httpGetEnabled - 指示是否发布服务元数据以便使用 HTTP/GET 请求进行检索,如果发布 WSDL,则为 true,否则为 false,默认值为 false--> 
                                        <serviceMetadata httpGetEnabled="true" /> 
                                        <serviceDebug includeExceptionDetailInFaults="true"/> 
                                </behavior> 
                        </serviceBehaviors> 
                </behaviors> 
                <services> 
                        <!--name - 提供服务的类名--> 
                        <!--behaviorConfiguration - 指定相关的行为配置--> 
                        <service name="WCF.ServiceLib.Transaction.Hello" behaviorConfiguration="TransactionBehavior"> 
                                <!--address - 服务地址--> 
                                <!--binding - 通信方式--> 
                                <!--contract - 服务契约--> 
                                <!--bindingConfiguration - 指定相关的绑定配置--> 
                                <endpoint address="" binding="wsHttpBinding" contract="WCF.ServiceLib.Transaction.IHello" bindingConfiguration="TransactionConfiguration" /> 
                        </service> 
                        <service name="WCF.ServiceLib.Transaction.Hi" behaviorConfiguration="TransactionBehavior"> 
                                <endpoint address="" binding="wsHttpBinding" contract="WCF.ServiceLib.Transaction.IHi" bindingConfiguration="TransactionConfiguration" /> 
                        </service> 
                        <service name="WCF.ServiceLib.Transaction.Result" behaviorConfiguration="TransactionBehavior"> 
                                <endpoint address="" binding="basicHttpBinding" contract="WCF.ServiceLib.Transaction.IResult" /> 
                        </service> 
                </services> 
                <bindings> 
                        <wsHttpBinding> 
                                <!--transactionFlow - 指定该绑定是否应支持流事务--> 
                                <binding name="TransactionConfiguration" transactionFlow="true" /> 
                        </wsHttpBinding> 
                </bindings> 
        </system.serviceModel> 
</configuration>
3、客户端
Sample.aspx
<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Sample.aspx.cs" 
        Inherits="Transaction_Sample" Title="事务(Transaction)" %> 

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server"> 
</asp:Content> 
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server"> 
        <p> 
                <asp:Label ID="lblErr" runat="server" ForeColor="Red" /> 
        </p> 
        <p> 
                <asp:Button ID="btnSubmit" runat="server" Text="事务测试" OnClick="btnSubmit_Click" /> 
                <br /> 
                <br /> 
                <asp:GridView ID="GridView1" runat="server"> 
                </asp:GridView> 
        </p> 
        <p> 
                2PC(Two Phase Commitment Protocol)两阶段提交协议(WCF的事务的实现基于此协议) 
                <br /> 
                实现分布式事务的关键就是两阶段提交协议。在此协议中,一个或多个资源管理器的活动均由一个称为事务协调器的单独软件组件来控制。此协议中的五个步骤如下: 
                <br /> 
                1、应用程序调用事务协调器中的提交方法。 
                <br /> 
                2、事务协调器将联络事务中涉及的每个资源管理器,并通知它们准备提交事务(这是第一阶段的开始)。 
                <br /> 
                3、为 了以肯定的方式响应准备阶段,资源管理器必须将自己置于以下状态:确保能在被要求提交事务时提交事务,或在被要求回滚事务时回滚事务。大多数资源管理器会将包含其计划更改的日记文件(或等效文件)写入持久存储区中。如果资源管理器无法准备事务,它会以一个否定响应来回应事务协调器。 
                <br /> 
                4、事务协调器收集来自资源管理器的所有响应。 
                <br /> 
                5、在 第二阶段,事务协调器将事务的结果通知给每个资源管理器。如果任一资源管理器做出否定响应,则事务协调器会将一个回滚命令发送给事务中涉及的所有资源管理 器。如果资源管理器都做出肯定响应,则事务协调器会指示所有的资源管理器提交事务。一旦通知资源管理器提交,此后的事务就不能失败了。通过以肯定的方式响应第一阶段,每个资源管理器均已确保,如果以后通知它提交事务,则事务不会失败。 
        </p> 
</asp:Content>
Sample.aspx.cs
InBlock.gifusing System; 
InBlock.gifusing System.Collections; 
InBlock.gifusing System.Configuration; 
InBlock.gifusing System.Data; 
InBlock.gifusing System.Linq; 
InBlock.gifusing System.Web; 
InBlock.gifusing System.Web.Security; 
InBlock.gifusing System.Web.UI; 
InBlock.gifusing System.Web.UI.HtmlControls; 
InBlock.gifusing System.Web.UI.WebControls; 
InBlock.gifusing System.Web.UI.WebControls.WebParts; 
InBlock.gifusing System.Xml.Linq; 
InBlock.gif 
InBlock.gifusing System.Threading; 
InBlock.gif 
InBlock.gifpublic partial class Transaction_Sample : System.Web.UI.Page 
InBlock.gif
InBlock.gif        protected void Page_Load(object sender, EventArgs e) 
InBlock.gif        { 
InBlock.gif 
InBlock.gif        } 
InBlock.gif 
InBlock.gif        protected void btnSubmit_Click(object sender, EventArgs e) 
InBlock.gif        { 
InBlock.gif                var proxyHello = new TransactionSvc.Hello.HelloClient(); 
InBlock.gif                var proxyHi = new TransactionSvc.Hi.HiClient(); 
InBlock.gif                var proxyResult = new TransactionSvc.Result.ResultClient(); 
InBlock.gif 
InBlock.gif                System.Transactions.TransactionOptions to = new System.Transactions.TransactionOptions(); 
InBlock.gif                // 设置事务的超时时间 
InBlock.gif                to.Timeout = new TimeSpan(0, 0, 30); 
InBlock.gif                // 设置事务的隔离级别 
InBlock.gif                to.IsolationLevel = System.Transactions.IsolationLevel.Serializable; 
InBlock.gif 
InBlock.gif                using (var ts = new System.Transactions.TransactionScope()) 
InBlock.gif                { 
InBlock.gif                        try 
InBlock.gif                        { 
InBlock.gif                                proxyHello.WriteHello("webabcd"); 
InBlock.gif                                proxyHello.Close(); 
InBlock.gif 
InBlock.gif                                proxyHi.WriteHi("webabcd"); 
InBlock.gif                                proxyHi.Close(); 
InBlock.gif 
InBlock.gif                                ts.Complete(); 
InBlock.gif 
InBlock.gif                                lblErr.Text = "OK"
InBlock.gif                        } 
InBlock.gif                        catch (Exception ex) 
InBlock.gif                        { 
InBlock.gif                                lblErr.Text = ex.ToString(); 
InBlock.gif                        } 
InBlock.gif                } 
InBlock.gif 
InBlock.gif                GridView1.DataSource = proxyResult.GetResult(); 
InBlock.gif                GridView1.DataBind(); 
InBlock.gif                proxyHello.Close(); 
InBlock.gif        } 
InBlock.gif}
Web.config
<?xml version="1.0"?> 
<configuration> 
        <system.serviceModel> 
                <client> 
                        <!--address - 服务地址--> 
                        <!--binding - 通信方式--> 
                        <!--contract - 服务契约--> 
                        <endpoint address="http://localhost:3502/ServiceHost/Transaction/Hello.svc" binding="wsHttpBinding" contract="TransactionSvc.Hello.IHello" bindingConfiguration="TransactionBindingConfiguration" /> 
                        <endpoint address="http://localhost:3502/ServiceHost/Transaction/Hi.svc" binding="wsHttpBinding" contract="TransactionSvc.Hi.IHi" bindingConfiguration="TransactionBindingConfiguration" /> 
                        <endpoint address="http://localhost:3502/ServiceHost/Transaction/Result.svc" binding="basicHttpBinding" contract="TransactionSvc.Result.IResult" /> 
                </client> 
                <bindings> 
                        <wsHttpBinding> 
                                <!--transactionFlow - 指定该绑定是否应支持流事务--> 
                                <binding name="TransactionBindingConfiguration" transactionFlow="true" /> 
                        </wsHttpBinding> 
                </bindings> 
        </system.serviceModel> 
</configuration>
运行结果:
单击"btnSubmit"按钮后,可以发现,两个数据库插入操作,要么都执行,要么都不执行


OK
[源码下载]
 

本文转自webabcd 51CTO博客,原文链接:http://blog.51cto.com/webabcd/344160,如需转载请自行联系原作者

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/257050.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

iOS开发网络篇—NSURLConnection基本使用

iOS开发网络篇—NSURLConnection基本使用 一、NSURLConnection的常用类 &#xff08;1&#xff09;NSURL&#xff1a;请求地址 &#xff08;2&#xff09;NSURLRequest&#xff1a;封装一个请求&#xff0c;保存发给服务器的全部数据&#xff0c;包括一个NSURL对象&#xff0c;…

使用HTML5+CSS3制作圆角内发光按钮----示例

<!doctype html> <html> <head> <meta charset"utf-8" /> <title>制作漂亮的圆角按钮<title> <style type"text/css"> .loginBtnDiv { float:right; padding-right:50px; padding-top:10px; } .loginBtn, .Resg…

ccBPM典型的树形表单和多表头表单的流程示例

ccBPM典型的树形表单和多表头表单的流程 关键字&#xff1a;树形表单。ccBPM支持树形表单&#xff0c;也可以称之为树结构的多表单或者多表头表单。 应用场景&#xff1a;比如项目招标类流程&#xff0c;在填写项目申请的环节&#xff0c;需要填写公司简介、公司业绩、项目实施…

H5+JS实现《Just Do 8》游戏源码分享

【界面效果图】 【代码结构】 【代码结构解释】 1、使用html语言实现数据 2、使用css3语言实现样式 3、使用JS语言实现路基控制 【注意是想】 1、如需查看效果&#xff0c;请使用手机浏览器&#xff0c;或者使用appcan打包查看 2、如果使用浏览器&#xff0c;请选择google的Chr…

python数据结构_大O符号_学习笔记(1)

1.概念 &#xff1a;大O符号是用来表达一个算法的复杂程度的&#xff0c;是一个数量级 2.代码 a 1 b 2 c 3 for i in range(n):for j in range(n):x i*iy j*jz i*jfor k in range(n):m a*k 5v k*kd 100*c e c*d3.分析 在上述代码中&#xff0c;分配操作数分为四…

.NET简谈组件程序设计之(上下文与同步域)

我们继续学习.NET多线程技术&#xff0c;这篇文章的内容可能有点复杂。在打破常理之后&#xff0c;换一种新的思考模型最为头疼。这篇文章里面会涉及到一些不太常见的概念&#xff0c;比如&#xff1a;上下文、同步域等等。我也是最近才接触这些关于组件编程方面的高深技术&…

调用图片按钮的img图片

今天是我学前端的第12天。早上起床后活动筋骨时看了《JS的基本属性操作》&#xff0c;作业是模拟手机发送短信。文字都能传输到<div>上&#xff0c;就是图片不知道怎么传。折腾了好久才弄清楚&#xff0c;多亏了某群的小伙伴们。 这一节课&#xff0c;我学会了如何调用图…

python数据结构_(列表)大O性能_学习笔记(2)

1.列表 1&#xff09;一般列表操作命令的复杂度&#xff08;准确来说是函数的复杂度&#xff09; 2&#xff09;时间计算&#xff08;timeit模块和Timer对象&#xff09; 要捕获我们的每个函数执行所需的时间&#xff0c;我们将使用 Python 的 timeit 模块。timeit 模块旨在 …

找到你的位置(JS在页面中的位置)最常用的方式是在页面中head部分放置script元素,浏览器解析head部分就会执行这个代码,然后才解析页面的其余部分...

找到你的位置&#xff08;JS在页面中的位置&#xff09; 我们可以将JavaScript代码放在html文件中任何位置&#xff0c;但是我们一般放在网页的head或者body部分。放在<head>部分 最常用的方式是在页面中head部分放置<script>元素&#xff0c;浏览器解析head部分就…

3.cocos2dx它Menu,由menu为了实现场景切换

&#xfeff;&#xfeff;1 头文件 TMenu.h #ifndef __TMENU_H__ #define __TMENU_H__ #include "cocos2d.h" USING_NS_CC; class TMenu :public CCLayer { public: static CCScene * scene(); CREATE_FUNC(TMenu); bool init(); CCMenu * menu; void menuCallback(C…

人工智能数学基础知识

方差的概念与计算公式&#xff0c;例1 两人的5次测验成绩如下&#xff1a;X&#xff1a; 50&#xff0c;100&#xff0c;100&#xff0c;60&#xff0c;50 E(X)72&#xff1b;Y&#xff1a; 73&#xff0c; 70&#xff0c; 75&#xff0c;72&#xff0c;70 E(Y)72。平均成绩相同…

认真分析mmap:是什么 为什么 怎么用

mmap基础概念 mmap是一种内存映射文件的方法&#xff0c;即将一个文件或者其它对象映射到进程的地址空间&#xff0c;实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后&#xff0c;进程就可以采用指针的方式读写操作这一段内存&#xff…

数据库子查询

子查询&#xff0c;又叫做嵌套查询。 将一个查询语句做为一个结果集供其他SQL语句使用&#xff0c;就像使用普通的表一样&#xff0c;被当作结果集的查询语句被称为子查询。 子查询有两种类型&#xff1a; 一种是只返回一个单值的子查询&#xff0c;这时它可以用在一个单值可以…

配置vim在源代码中自动添加作者信息

每个程序员都有自己心爱的代码编辑和查看工具&#xff0c;相信不少Linux下的程序员都喜欢用Vim&#xff0c;尽管Vim没有SourceInsight这种依托于桌面环境的编辑器看起来那样强大&#xff0c;但是Vim的高效、简洁以及强大的可配置性都让它吸引了无数忠实的fans。 很多编辑器都支…

Ubuntu系统盘制作

1、首先打开UltraISO软件&#xff0c;尽量下载最新版的&#xff0c;小编曾用某个旧版的UltraISO&#xff0c;制作的安装盘&#xff0c;不能不能识别磁盘&#xff0c;安装失败! 2、点击工具栏中的第二个打开镜像文件工具&#xff0c;如图红色方框标志按钮&#xff0c;然后在打开…

RH131 网络配置

ip addr show 查看当前网络地址 ip link show 查看网络链接状态 ip -s link show 查看网卡统计信息 ip addr add 192.168.0.154 添加ip地址 ip link dev eth0 down 禁用ip地址 网卡的配置文件/etc/sysconfig/network-scripts/ifcfg-ethx 自动专用地址&#xff1a;169.254.*.* …

学习笔记02:直播串讲02

1.基于模型的学习 根据以往的学习经验&#xff0c;建立起输入输出的模型&#xff0c;然后预测输入&#xff0c;并且将输入带入到模型中&#xff0c;进而预测出输出的结果&#xff0c;这种学习称为基于模型的学习 2.机器学习的过程 1&#xff09;数据收集&#xff1a;通过爬虫、…

Dojo仪表板

Dojo它提供了一个良好的仪表板显示器&#xff0c;的影响&#xff0c;如以下&#xff1a; <!DOCTYPE html> <html> <head><title>Dojo仪表盘</title><meta charset"utf-8"><script src"http://192.168.240.186/arcgis_js…

Exchange2013恢复已删除用户邮箱

上一篇文章我们讲到了如何恢复已禁用的邮箱。但是在微软的Exchange中&#xff0c;禁用邮箱和删除邮箱毕竟是两个截然不同的概念&#xff0c;这篇文章我们就来看看如何恢复已删除的邮箱。 1.依然是新建用户“张三”&#xff0c;然后给其发一封邮件&#xff0c;作为后续邮箱数据恢…