• 稳扎稳打Silverlight(44) 4.0浏览器外运行(Out Of Browser)之OOB的增强及其新增的NotificationWindow


    [索引页]
    [源码下载]


    稳扎稳打Silverlight(44) - 4.0浏览器外运行(Out Of Browser)之OOB的增强及其新增的NotificationWindow



    作者:webabcd


    介绍
    Silverlight 4.0 OOB 模式的新特性:

    • 新增了 Closing 事件
    • 实现程序在 OOB 模式下的自动更新
    • NotificationWindow - 在 OOB 模式下显示通知窗口,也就是 toast
    • 实现自定义的 NotificationWindow



    在线DEMO
    http://www.cnblogs.com/webabcd/archive/2010/08/09/1795417.html


    示例
    1、OOB(Out Of Browser)模式的复习,以及其新增的 Closing 事件
    Demo.xaml

    代码
    <navigation:Page x:Class="Silverlight40.OutOfBrowser.Demo" 
               xmlns
    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
               xmlns:x
    ="http://schemas.microsoft.com/winfx/2006/xaml" 
               xmlns:d
    ="http://schemas.microsoft.com/expression/blend/2008"
               xmlns:mc
    ="http://schemas.openxmlformats.org/markup-compatibility/2006"
               xmlns:navigation
    ="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
               Title
    ="Other Page">
        
    <Grid x:Name="LayoutRoot">

            
    <StackPanel HorizontalAlignment="Left">

                
    <Button Name="btnOutOfBrowser" Margin="50" Click="btnOutOfBrowser_Click" />

                
    <Button Name="btnClose" Margin="50" Content="关闭" Click="btnClose_Click" />

                
    <TextBlock Text="OOB 模式下网络状况的检测,以及程序的升级详见本目录下的 AutoUpdateDemo.xaml" Margin="5" />

                
    <TextBlock Text="OOB 模式的 toast(以及与 Popup 的对比)详见本目录下的 NotificationWindowDemo.xaml" Margin="5" />

                
    <TextBlock Text="OOB 模式下自定义 NotificationWindow 的内容及样式详见本目录下的 CustomNotificationWindowDemo.xaml" Margin="5" />

            
    </StackPanel>
            
        
    </Grid>
    </navigation:Page>


    Demo.xaml.cs

    代码
    /*
     * Silverlight 3.0 时代具有如下特性
     * Application.InstallStateChanged - 浏览器外运行的相关状态发生改变时所触发的事件
     * Application.InstallState - 浏览器外运行的相关状态 [System.Windows.InstallState 枚举]
     *     NotInstalled - 在浏览器中运行
     *     Installing - 安装到桌面中
     *     Installed - 在浏览器外运行
     *     InstallFailed - 安装到桌面的过程中发生错误
     * Application.IsRunningOutOfBrowser - 当前程序是否是从浏览器外启动的
     * Application.Install() - 安装 Silverlight 程序到浏览器外(卸载只能通过右键菜单的方式卸载)
     * Application.CheckAndDownloadUpdateAsync, Application.CheckAndDownloadUpdateCompleted - 一对异步方法/事件,用于更新浏览器外运行的 Silverlight 程序(从服务器上下载新的版本)
     * 
     * 启用 OOB:在 Silverlight 项目上单击右键 -> 属性 -> Silverlight -> 选中 Enable running application out of the browser
     * 配置 OOB:在 Silverlight 项目上单击右键 -> 属性 -> Silverlight -> Out-of-Browser Settings 可以对“浏览器外运行”的相关参数做设置(也可以手动修改 Properties/OutOfBrowserSettings.xml)
     
    */


    /*
     * 调试 OOB 模式下的 Silverlight 程序:启用 OOB 模式,将 Silverlight 项目设置为启动项目,然后运行即可
     
    */


    /*
     * 本例用于演示 Closing 事件
     * Application.Current.MainWindow - OOB 模式下的应用程序窗口。属性值为 System.Windows.Window 类型
     * Window.Activate() - 激活窗口,使之具有焦点,并置于最前面
     * Window.IsActive - 是否为激活窗口(仅 get)
     * Window.Close() - 关闭窗口
     * Window.Closing - 窗口关闭前触发的事件。事件参数为 System.ComponentModel.ClosingEventArgs 类型
     *     ClosingEventArgs.IsCancelable - 是否可以取消窗口的关闭事件
     *     ClosingEventArgs.Cancel - 是否取消窗口的关闭事件
     
    */

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.Windows.Navigation;

    namespace Silverlight40.OutOfBrowser
    {
        
    public partial class Demo : Page
        {
            
    public Demo()
            {
                InitializeComponent();
            }

            
    protected override void OnNavigatedTo(NavigationEventArgs e)
            {
                
    if (App.Current.IsRunningOutOfBrowser)
                    btnOutOfBrowser.Content 
    = "卸载";
                
    else
                    btnOutOfBrowser.Content 
    = "安装";

                Init();
            }

            
    private void btnOutOfBrowser_Click(object sender, RoutedEventArgs e)
            {
                
    if (!App.Current.IsRunningOutOfBrowser && App.Current.InstallState == InstallState.NotInstalled)
                    App.Current.Install();
                
    else
                    MessageBox.Show(
    "已经安装,使用右键卸载");
            }

            
    void Init()
            {
                
    if (Application.Current.IsRunningOutOfBrowser)
                    Application.Current.MainWindow.Closing 
    += new EventHandler<System.ComponentModel.ClosingEventArgs>(MainWindow_Closing);
            }

            
    void MainWindow_Closing(object sender, System.ComponentModel.ClosingEventArgs e)
            {
                
    if (MessageBox.Show("确认关闭吗?""确认", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
                {

                }
                
    else
                {
                    
    if (e.IsCancelable)
                        e.Cancel 
    = true;
                }
            }

            
    private void btnClose_Click(object sender, RoutedEventArgs e)
            {
                
    if (Application.Current.IsRunningOutOfBrowser)
                    Application.Current.MainWindow.Close();
            }
        }
    }



    2、演示如何实现程序在 OOB 模式下的自动更新
    AutoUpdateDemo.xaml

    代码
    <navigation:Page x:Class="Silverlight40.OutOfBrowser.AutoUpdateDemo" 
               xmlns
    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
               xmlns:x
    ="http://schemas.microsoft.com/winfx/2006/xaml" 
               xmlns:d
    ="http://schemas.microsoft.com/expression/blend/2008"
               xmlns:mc
    ="http://schemas.openxmlformats.org/markup-compatibility/2006"
               xmlns:navigation
    ="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
               Title
    ="AutoUpdateDemo Page">
        
    <Grid x:Name="LayoutRoot">
            
    <StackPanel>
                
                
    <Button Name="btnOutOfBrowser" Margin="50" Click="btnOutOfBrowser_Click" />
                
                
    <TextBlock Name="lblMsg" />
                
            
    </StackPanel>
        
    </Grid>
    </navigation:Page>


    AutoUpdateDemo.xaml.cs

    代码
    /*
     * 本例演示 Silverlight 应用程序在 OOB 模式下的自动更新
     * 注1:Silverlight 应用程序根据 Assembly Version 来判断是否需要更新
     * 注2:程序下载成功后,需要重启 Silverlight 应用程序,这样运行的才是更新后的程序
     * 
     * NetworkInterface.GetIsNetworkAvailable() - 网络是否有效
     * NetworkChange.NetworkAddressChanged - 网络状态发生变化时所触发的事件
     * Application.CheckAndDownloadUpdateAsync, Application.CheckAndDownloadUpdateCompleted - 一对异步方法/事件,用于更新浏览器外运行的 Silverlight 程序(从服务器上下载新的版本)
     * CheckAndDownloadUpdateCompletedEventArgs.UpdateAvailable - 是否已经成功更新了版本
     * CheckAndDownloadUpdateCompletedEventArgs.Error - 下载更新时发生了异常
     
    */

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.Windows.Navigation;

    using System.Net.NetworkInformation;

    namespace Silverlight40.OutOfBrowser
    {
        
    public partial class AutoUpdateDemo : Page
        {
            
    public AutoUpdateDemo()
            {
                InitializeComponent();
            }

            
    protected override void OnNavigatedTo(NavigationEventArgs e)
            {
                
    if (App.Current.IsRunningOutOfBrowser)
                    btnOutOfBrowser.Content 
    = "卸载";
                
    else
                    btnOutOfBrowser.Content 
    = "安装";
                
                Init();
            }

            
    private void btnOutOfBrowser_Click(object sender, RoutedEventArgs e)
            {
                
    if (!App.Current.IsRunningOutOfBrowser && App.Current.InstallState == InstallState.NotInstalled)
                    App.Current.Install();
                
    else
                    MessageBox.Show(
    "已经安装,使用右键卸载");
            }

            
    private void Init()
            {
                lblMsg.Text 
    = string.Format("网络状态:{0}", NetworkInterface.GetIsNetworkAvailable().ToString());

                
    // 网络状态发生改变时所触发的事件,可以拔网线看效果
                NetworkChange.NetworkAddressChanged += new NetworkAddressChangedEventHandler(NetworkChange_NetworkAddressChanged);

                
    if (App.Current.IsRunningOutOfBrowser && NetworkInterface.GetIsNetworkAvailable())
                {
                    App.Current.CheckAndDownloadUpdateCompleted 
    += new CheckAndDownloadUpdateCompletedEventHandler(Current_CheckAndDownloadUpdateCompleted);
                    App.Current.CheckAndDownloadUpdateAsync();

                    lblMsg.Text 
    += "\n检查更新。。。";
                }
            }

            
    void NetworkChange_NetworkAddressChanged(object sender, EventArgs e)
            {
                lblMsg.Text 
    += "\n";
                lblMsg.Text 
    += string.Format("网络状态:{0}", NetworkInterface.GetIsNetworkAvailable().ToString());
            }

            
    void Current_CheckAndDownloadUpdateCompleted(object sender, CheckAndDownloadUpdateCompletedEventArgs e)
            {
                
    if (e.UpdateAvailable)
                {
                    lblMsg.Text 
    += "\n更新完毕,请重启程序";
                }
                
    else
                {
                    
    if (e.Error == null)
                        lblMsg.Text 
    += "\n程序无更新(如果有新更新要修改 Assembly Version)";
                    
    else
                        lblMsg.Text 
    += "\n" + e.Error.ToString();
                }
            }
        }
    }



    3、演示 NotificationWindow(toast) 的效果,以及其和 Popup 的对比
    NotificationWindowDemo.xaml

    代码
    <navigation:Page x:Class="Silverlight40.OutOfBrowser.NotificationWindowDemo" 
               xmlns
    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
               xmlns:x
    ="http://schemas.microsoft.com/winfx/2006/xaml" 
               xmlns:d
    ="http://schemas.microsoft.com/expression/blend/2008"
               xmlns:mc
    ="http://schemas.openxmlformats.org/markup-compatibility/2006"
               xmlns:navigation
    ="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
               Title
    ="NotificationWindowDemo Page">
        
    <Grid x:Name="LayoutRoot">
            
    <StackPanel HorizontalAlignment="Left">
                
    <Button Name="btnOutOfBrowser" Margin="50" Click="btnOutOfBrowser_Click" />

                
    <!-- Popup 的 Demo -->
                
    <Button Name="btnShowPopup" Margin="5" Content="弹出 Popup" Click="btnShowPopup_Click" />

                
    <!-- NotificationWindow 的 Demo -->
                
    <Button Name="btnShowNotificationWindow" Margin="5" Content="弹出 NotificationWindow" Click="btnShowNotificationWindow_Click" />

            
    </StackPanel>
        
    </Grid>
    </navigation:Page>


    NotificationWindowDemo.xaml.cs

    代码
    /*
     * NotificationWindow - 在 OOB 模式下显示通知窗口,也就是 toast
     
    */

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.Windows.Navigation;

    using System.Windows.Controls.Primitives;

    namespace Silverlight40.OutOfBrowser
    {
        
    public partial class NotificationWindowDemo : Page
        {
            
    public NotificationWindowDemo()
            {
                InitializeComponent();
            }

            
    protected override void OnNavigatedTo(NavigationEventArgs e)
            {
                
    if (App.Current.IsRunningOutOfBrowser)
                    btnOutOfBrowser.Content 
    = "卸载";
                
    else
                    btnOutOfBrowser.Content 
    = "安装";
            }

            
    private void btnOutOfBrowser_Click(object sender, RoutedEventArgs e)
            {
                
    if (!App.Current.IsRunningOutOfBrowser && App.Current.InstallState == InstallState.NotInstalled)
                    App.Current.Install();
                
    else
                    MessageBox.Show(
    "已经安装,使用右键卸载");
            }

           
            
    private void btnShowPopup_Click(object sender, RoutedEventArgs e)
            {
                
    /*
                 * Popup - 用于在 Silverlight 程序区域之内,Silverlight 内容之上显示内容,其通吃浏览器内外。来自 Silverlight 2.0
                 *     Popup.Child - Popup 上显示的内容 
                 *     Popup.IsOpen - 是否显示 Popup
                 
    */

                Popup popup 
    = new Popup();

                Border border 
    = new Border();
                border.BorderBrush 
    = new SolidColorBrush(Colors.Black);
                border.BorderThickness 
    = new Thickness(5.0);

                StackPanel container 
    = new StackPanel();
                container.Width 
    = 320;
                container.Height 
    = 240;
                container.Background 
    = new SolidColorBrush(Colors.Yellow);

                TextBlock lblMsg 
    = new TextBlock();
                lblMsg.Text 
    = "Popup 信息";

                Button btnClose 
    = new Button();
                btnClose.Content 
    = "关闭";
                btnClose.Click 
    += (x, y) => { popup.IsOpen = false; };

                container.Children.Add(lblMsg);
                container.Children.Add(btnClose);
                border.Child 
    = container;

                popup.Child 
    = border;

                popup.VerticalOffset 
    = 100;
                popup.HorizontalOffset 
    = 100;

                popup.IsOpen 
    = true;
            }
           
            
    private void btnShowNotificationWindow_Click(object sender, RoutedEventArgs e)
            {
                
    /*
                 * NotificationWindow.Content - toast 所显示的内容
                 * NotificationWindow.Show(int durationInMilliseconds) - 显示 toast,并在指定时间后隐藏 toast
                 * 
                 * 注:每个 Silverlight 应用程序在同一时间只能显示一个 toast 。如果在一个 toast 正在显示的同时调用 NotificationWindow.Show() 则会引发异常
                 
    */

                
    if (App.Current.IsRunningOutOfBrowser)
                {
                    NotificationWindow notify 
    = new NotificationWindow();
                    notify.Width 
    = 320;
                    notify.Height 
    = 80;

                    TextBlock lblMsg 
    = new TextBlock();
                    lblMsg.Text 
    = "NotificationWindow 信息";
                    lblMsg.FontSize 
    = 18;

                    notify.Content 
    = lblMsg;

                    notify.Show(
    3000);
                }
                
    else
                {
                    MessageBox.Show(
    "请在浏览器外运行");
                }
            }
        }
    }



    4、演示如何实现自定义的 NotificationWindow
    generic.xaml

    代码
    <ResourceDictionary
        
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x
    ="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys
    ="clr-namespace:System;assembly=mscorlib"
        xmlns:vsm
    ="clr-namespace:System.Windows;assembly=System.Windows"
        xmlns:local
    ="clr-namespace:Silverlight40.OutOfBrowser">

        
    <ResourceDictionary.MergedDictionaries>
            
    <!--
                自定义控件时,将 Style 放到 generic.xaml 之外的注意事项:generic.xaml 和 Style 的 xaml 文件均要设置为资源类型
            
    -->
            
    <ResourceDictionary Source="/Silverlight40;component/themes/CustomNotificationWindow.xaml"/>
        
    </ResourceDictionary.MergedDictionaries>

    </ResourceDictionary>


    CustomNotificationWindow.xaml

    代码
    <ResourceDictionary
        
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x
    ="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys
    ="clr-namespace:System;assembly=mscorlib"
        xmlns:vsm
    ="clr-namespace:System.Windows;assembly=System.Windows"
        xmlns:local
    ="clr-namespace:Silverlight40.OutOfBrowser">

        
    <Style TargetType="local:CustomNotificationWindow">
            
    <Setter Property="IsTabStop" Value="False"/>
            
    <Setter Property="Background" Value="Black"/>
            
    <Setter Property="Template">
                
    <Setter.Value>
                    
    <ControlTemplate TargetType="local:CustomNotificationWindow">
                        
    <StackPanel>
                            
    <!-- 关闭按钮 -->
                            
    <Button Name="btnClose" Content="关闭" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="5" />
                            
    <!-- toast 的标题 -->
                            
    <TextBlock Text="{TemplateBinding Title}" Foreground="Red" FontWeight="Bold" FontSize="12" />
                            
    <!-- toast 的正文 -->
                            
    <TextBlock Text="{TemplateBinding Text}" FontSize="12" TextWrapping="Wrap" />
                        
    </StackPanel>
                    
    </ControlTemplate>
                
    </Setter.Value>
            
    </Setter>
        
    </Style>
        
    </ResourceDictionary>


    CustomNotificationWindow.cs

    代码
    /*
     * 本例演示如何实现自定的 NotificationWindow
     
    */

    using System;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;

    namespace Silverlight40.OutOfBrowser
    {
        
    public class CustomNotificationWindow : ContentControl
        {
            
    public CustomNotificationWindow()
            {
                
    // 设置控件的默认样式
                this.DefaultStyleKey = typeof(CustomNotificationWindow);
            }


            
    // toast 的标题
            public string Title
            {
                
    get { return (string)GetValue(CustomNotificationWindow.TitleProperty); }
                
    set { SetValue(CustomNotificationWindow.TitleProperty, value); }
            }
            
    public static readonly DependencyProperty TitleProperty = DependencyProperty.Register
            (
                
    "Title",
                
    typeof(string),
                
    typeof(CustomNotificationWindow),
                
    new PropertyMetadata(OnTitlePropertyChanged)
            );
            
    private static void OnTitlePropertyChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
            {
            }


            
    // toast 的正文
            public string Text
            {
                
    get { return (string)GetValue(CustomNotificationWindow.TextProperty); }
                
    set { SetValue(CustomNotificationWindow.TextProperty, value); }
            }
            
    public static readonly DependencyProperty TextProperty = DependencyProperty.Register
            (
                
    "Text",
                
    typeof(string),
                
    typeof(CustomNotificationWindow),
                
    new PropertyMetadata(OnTextPropertyChanged)
            );
            
    private static void OnTextPropertyChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
            {
            }


            
    //  UI 元素在应用程序中显示之前所调用的方法
            public override void OnApplyTemplate()
            {
                
    base.OnApplyTemplate();

                
    // Control.GetTemplateChild() - 在实例化的 ControlTemplate 可视化树中检索已命名的元素
                Button btnClose = GetTemplateChild("btnClose"as Button;
                
    if (btnClose != null)
                {
                    btnClose.Click 
    += (s, e) =>
                    {
                        EventHandler
    <EventArgs> handler = this.Closed;
                        
    if (handler != null)
                            handler(
    this, EventArgs.Empty);
                    };
                }
            }

            
    public event EventHandler<EventArgs> Closed;
        }
    }


    CustomNotificationWindowDemo.xaml

    代码
    <navigation:Page x:Class="Silverlight40.OutOfBrowser.CustomNotificationWindowDemo" 
               xmlns
    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
               xmlns:x
    ="http://schemas.microsoft.com/winfx/2006/xaml" 
               xmlns:d
    ="http://schemas.microsoft.com/expression/blend/2008"
               xmlns:mc
    ="http://schemas.openxmlformats.org/markup-compatibility/2006"
               xmlns:navigation
    ="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
               Title
    ="CustomNotificationWindowDemo Page">
        
    <Grid x:Name="LayoutRoot">
            
    <StackPanel HorizontalAlignment="Left">
                
    <Button Name="btnOutOfBrowser" Margin="50" Click="btnOutOfBrowser_Click" />

                
    <!-- 自定义 NotificationWindow 的 Demo -->
                
    <Button Name="btnShowCustomNotificationWindow" Margin="5" Content="弹出 CustomNotificationWindow" Click="btnShowCustomNotificationWindow_Click" />

            
    </StackPanel>
        
    </Grid>
    </navigation:Page>


    CustomNotificationWindowDemo.xaml.cs

    代码
    /*
     * 本例演示如何使用自定的 NotificationWindow
     
    */

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.Windows.Navigation;

    namespace Silverlight40.OutOfBrowser
    {
        
    public partial class CustomNotificationWindowDemo : Page
        {
            
    public CustomNotificationWindowDemo()
            {
                InitializeComponent();
            }

            
    protected override void OnNavigatedTo(NavigationEventArgs e)
            {
                
    if (App.Current.IsRunningOutOfBrowser)
                    btnOutOfBrowser.Content 
    = "卸载";
                
    else
                    btnOutOfBrowser.Content 
    = "安装";
            }

            
    private void btnOutOfBrowser_Click(object sender, RoutedEventArgs e)
            {
                
    if (!App.Current.IsRunningOutOfBrowser && App.Current.InstallState == InstallState.NotInstalled)
                    App.Current.Install();
                
    else
                    MessageBox.Show(
    "已经安装,使用右键卸载");
            }


            
    private void btnShowCustomNotificationWindow_Click(object sender, RoutedEventArgs e)
            {
                
    // 实例化一个 NotificationWindow,并指定其宽和高
                NotificationWindow notify = new NotificationWindow();
                notify.Width 
    = 320;
                notify.Height 
    = 80;

                
    // 将 NotificationWindow 的显示内容设置为自定义的内容
                CustomNotificationWindow custom = new CustomNotificationWindow();
                custom.Title 
    = "我是标题";
                custom.Text 
    = "我是内容";
                custom.Width 
    = notify.Width;
                custom.Height 
    = notify.Height;
                custom.Closed 
    += (x, y) => { notify.Close(); };

                notify.Content 
    = custom;

                notify.Show(
    3000);
            }
        }
    }



    OK
    [源码下载]

  • 相关阅读:
    【分享】项目开发容易出现的问题?身为前端/后端你见到过吗?
    标准化API设计的重要性
    【分享】对外API接口安全设计
    【实例】调用数据库自动生成接口代码
    【翻译】API-First是什么概念?有什么商业价值?
    保障接口安全的5种常见方式
    【翻译】使用OpenAPI规范进行安全的API设计
    为什么需要API文档
    利用java的反射,实现工厂创建对象
    Cesium入门8
  • 原文地址:https://www.cnblogs.com/webabcd/p/1800388.html
Copyright © 2020-2023  润新知