asp.net應用程序_如何在ASP.NET中為聊天應用程序構建鍵入指示器

asp.net應用程序

by Neo Ighodaro

由新Ighodaro

如何在ASP.NET中為聊天應用程序構建鍵入指示器 (How to build a typing indicator for your chat app in ASP.NET)

A basic understanding of ASP.NET and jQuery is needed to follow this tutorial.
要學習本教程,需要對ASP.NET和jQuery有基本的了解。

When you’re using a chat app, knowing when the person you are chatting with is typing a message can improve your user experience. It gives you some feedback that you’re not alone in the conversation, and that a message is coming your way.

當您使用聊天應用程序時,知道與您聊天的人何時鍵入消息可以改善您的用戶體驗。 它為您提供了一些反饋,表明您并不孤單,并且有消息在向您發送。

In this tutorial, we will go through some simple steps to create this feature using C#, .NET, and Pusher.

在本教程中,我們將通過一些簡單的步驟使用C#、. NET和Pusher創建此功能。

At the end of this tutorial we will have something like this:

在本教程的最后,我們將提供以下內容:

This tutorial assumes prior knowledge of:

本教程假定您具有以下先驗知識:

  • C#

    C#
  • .NET MVC

    .NET MVC
  • JavaScript (jQuery)

    JavaScript(jQuery)

When you’re ready, let’s begin.

準備就緒后,就開始吧。

設置我們的項目 (Setting up our project)

We’ll be using Visual Studio, which is an IDE popularly used for building .NET projects. Visual Studio 2017 is free and available for most Operating Systems. You can view installation details here.

我們將使用Visual Studio ,這是一個廣泛用于構建.NET項目的IDE。 Visual Studio 2017是免費的,適用于大多數操作系統。 您可以在此處查看安裝詳細信息。

After installing Visual Studio, launch it and create a new project by clicking New Project from the dashboard. Following the New Project wizard we:

安裝Visual Studio之后,啟動它并通過從儀表板上單擊“ 新建項目”來創建一個新項目。 遵循“ 新建項目”向導,我們:

  • Set C# as our language

    將C#設置為我們的語言
  • Select .NET MVC Project as the template

    選擇.NET MVC Project作為模板
  • Fill in the Project name (for example “HeyChat” — but any name would do)

    填寫項目名稱(例如“ HeyChat”,但可以使用任何名稱)
  • Fill in the Solution name (that is, the application name — “HeyChat” or any name would do).

    填寫解決方案名稱(即應用程序名稱-“ HeyChat”或任何名稱)。

編寫服務器端(C)代碼 (Writing the server-side (C) code)

To display a typing indicator, our chat app needs to be able to recognize who is typing at any given time. For this, we will add some limited form of identification. We’re not doing any authentication at all, because this tutorial does not require it.

要顯示打字指示符,我們的聊天應用程序需要能夠在任何給定時間識別誰在打字。 為此,我們將添加一些有限形式的身份證明。 我們根本不進行任何身份驗證,因為本教程不需要它。

? For the purpose of this tutorial, we will assume that this chat is open to all users. All that will be required is that our users specify their names on first entry.

就本教程而言,我們假定此聊天對所有用戶開放。 所需要做的就是讓我們的用戶在第一次輸入時指定他們的姓名。

路線定義 (Route definition)

We can define some of the routes that we need to make this feature, which are:

我們可以定義實現此功能所需的一些路線,這些路線是:

  • A home route which renders the first page that takes the user’s name.

    一個家庭路線,該路線顯示使用用戶名的第一頁。
  • A login route which accepts a POST request of the user’s name.

    接受用戶名的POST請求的登錄路由。

  • A chat route which renders the chat view.

    提供聊天視圖的聊天路徑。

? We may need some other routes as we go along, but this is enough for starters.

我們可能會需要一些其他路線,但這對初學者來說足夠了。

To add these routes, we open the RouteConfig.cs file in the App_Start directory of our application. And in it, we add the routes we have defined.

要添加這些路由,我們在應用程序的App_Start目錄中打開RouteConfig.cs文件。 然后在其中添加我們定義的路由。

routes.MapRoute(        name: "Home",        url: "",        defaults: new { controller = "Home", action = "Index" }    );
routes.MapRoute(        name: "Login",        url: "login",        defaults: new { controller = "Login", action = "Index" }    );
routes.MapRoute(        name: "ChatRoom",        url: "chat",        defaults: new {controller = "Chat", action="Index"}    );

Using the Home route as a sample, the route definition states that / requests will be handled by the HomeController which is found in the Controllers/HomeController.cs file and the Index method of that controller. Next, we will create the controllers we’ll need.

使用Home路由作為示例,路由定義指出/請求將由HomeController處理,該請求可在Controllers/HomeController.cs文件和該Controllers/HomeController.csIndex方法中找到。 接下來,我們將創建所需的控制器。

創建控制器和動作方法 (Creating controllers and action methods)

To create a new controller, right-click the Controller directory and select Add → Controller. In the resulting form, we type in the name of our controller and select the empty template.

要創建新的控制器,請右鍵單擊Controller目錄,然后選擇Add → Controller 。 在生成的表單中,我們輸入控制器的名稱,然后選擇空模板。

? When our application is created, it includes a HomeController with an Index action method by default, so we’ll perform the above steps to create our LoginController and ChatController.

創建我們的應用程序時,默認情況下它包括帶有Index操作方法的HomeController,因此我們將執行上述步驟來創建LoginController和ChatController。

In our LoginController class, we create the Index action method specifying [HttpPost] at the top of the action method to indicate that it handles POST requests.

在我們的LoginController類中,我們創建Index操作方法,在該操作方法的頂部指定[HttpPost] ,以指示它處理POST請求。

public class LoginController : Controller    {        [HttpPost]        public ActionResult Index()        {
}    }

The Index action of the LoginController will receive the request payload, read the username from the payload, and assign it to the current user session. Then it will redirect our user to the chat page. When we add this to our action method, we’ll have:

LoginController的Index操作將接收請求有效負載,從有效負載中讀取用戶名,并將其分配給當前用戶會話。 然后它將把我們的用戶重定向到聊天頁面。 將其添加到操作方法時,將具有:

public class LoginController : Controller    {        [HttpPost]        public ActionResult Index()        {            string user = Request.Form["username"];            if (user.Trim() == "") {                return Redirect("/");            }            Session["user"] = user;            return Redirect("/chat");        }    }

? In a real-world chat app, we would add the user to a database and mark the user as logged in so that other users could see the available chat options. But that is beyond the scope of this tutorial, so adding to a session will suffice.

在實際的聊天應用程序中,我們會將用戶添加到數據庫中,并將該用戶標記為已登錄,以便其他用戶可以看到可用的聊天選項。 但這超出了本教程的范圍,因此添加一個會話就足夠了。

In our ChatController class, we will add the Index action method. The Index action of the ChatController will render our chat view and pass along the current user to the view.

在我們的ChatController類中,我們將添加Index操作方法。 ChatController的Index操作將呈現我們的聊天視圖,并將當前用戶傳遞到該視圖。

public class ChatController : Controller    {        public ActionResult Index()        {            if (Session["user"] == null) {                return Redirect("/");            }
ViewBag.currentUser = Session["user"];
return View ();        }    }

? By default, action methods handle GET requests, so we will not need to add [HttpGet] to the top of our method. We’ve also added a simple check to prevent access to the chat page if there is no logged in user.

默認情況下,操作方法處理G ET請求,因此我們無需在方法頂部添加[ HttpGet] 我們還添加了一個簡單的檢查,以防止在沒有登錄用戶的情況下訪問聊天頁面。

Let’s not forget about our Home route. In the HomeController, we’ll add the code to render the front page.

讓我們不要忘記我們的回家路線。 在HomeController中,我們將添加代碼以呈現首頁。

public class HomeController : Controller    {        public ActionResult Index()        {            if ( Session["user"] != null ) {                return Redirect("/chat");            }
return View();        }    }

? We’ve also added a small check to prevent multiple logins in the same user session.

我們還添加了一個小檢查,以防止在同一用戶會話中多次登錄。

At this point, we’ve created the Controllers and methods to serve our views (which we haven’t created yet), so trying to run this will give you some errors! Let’s fix that.

至此,我們已經創建了Controllers和方法來服務于我們的視圖(尚未創建),因此嘗試運行它會給您一些錯誤! 讓我們修復它。

實施應用程序的視圖 (Implementing the application’s views)

Based on the routes we’ve defined so far, we will need two views:

根據到目前為止我們定義的路線,我們將需要兩個視圖:

  • The front page view with the login form — served by the Indexaction method of the HomeController class

    具有登錄表單的首頁視圖—由HomeController類的Index action方法提供服務

  • The chat view where the typing indicator feature will be seen — served by ChatController class’ Index action method

    可以看到鍵入指示符功能的聊天視圖-由ChatController類的Index操作方法提供

主頁/登錄頁面 (Front page/login page)

For our front page, we’ll create a page with a form that asks for the user’s username and shows them a button to submit for login. Referring to our controller code:

對于我們的首頁,我們將創建一個帶有表單的頁面,該表單要求用戶的用戶名,并向他們顯示一個提交登錄的按鈕。 參考我們的控制器代碼:

public class HomeController : Controller    {        public ActionResult Index()        {            if ( Session["user"] != null ) {                return Redirect("/chat");            }            return View();        }    }

? The View function creates a view response which we return. When View() is invoked, C# looks for the default view of the calling controller class. This default view is the index.cshtml file found in the Views directory, in a directory with the same name as the Controller. That is, the default view of the HomeController class will be the Views/Home/index.cshtml file.

V iew函數創建一個視圖響應,我們將其返回。 調用V iew()時 ,C#查找調用控制器類的默認視圖。 該默認視圖是在Views目錄中的i ndex.cshtml文件,該目錄與Controller的名稱相同。 也就是說,HomeController類的默認視圖將是iews/Home/index.cshtml文件。

To create our HomeController default view, we:

要創建我們的HomeController默認視圖,我們:

  • Right-click on the Views directory and select Add New Folder,

    右鍵點擊Views目錄,然后選擇Add New Folder

  • Fill in Home as the folder name,

    填寫首頁作為文件夾名稱,

  • Right click the newly created Home folder and select Add New View,

    右鍵點擊新創建的文件夾,然后選擇Add New View

  • Fill in the view name (in our case index), select Razor as the view engine, and click OK.

    填寫視圖名稱(在本例中為索引 ),選擇Razor作為視圖引擎,然后單擊“確定”。

Now that we’ve created our front page view file, we’ll add the markup for the login form.

現在,我們已經創建了首頁視圖文件,我們將為登錄表單添加標記。

<div class="container">      <div class="row">        <div class="col-md-5 col-md-offset-4">          <div class="panel panel-default">            <div class="panel-body">              <form action="/login" method="post" style="margin:0">                <div class="form-group">                  <input type="text" name="username" id="username"                       placeholder="Enter Username" class="form-control"                       required minlength="3" maxlength="15" />                </div>                <button type="submit" class="btn btn-primary btn-block">                  Enter Chat                </button>              </form>            </div>          </div>        </div>      </div>    </div>

聊天頁面 (The chat page)

We’ll create the view for the chat page following the same steps as above, but using Chat as our folder name rather than Home.

我們將按照與上述相同的步驟為聊天頁面創建視圖,但是使用“ Chat作為我們的文件夾名稱而不是“ Home

In the chat view, we add markup up to give us a sidebar of available users and an area for chatting.

在聊天視圖中,我們添加了標記,以便為我們提供可用用戶的側邊欄和一個聊天區域。

<!DOCTYPE html>    <html>    <head>      <title>pChat — Private Chatroom</title>      <link rel="stylesheet" href="@Url.Content("~/Content/app.css")">    </head>    <body>            @{                var currentUser = ViewBag.currentUser;            }        <!-- Navigation Bar -->        <nav class="navbar navbar-inverse">          <div class="container-fluid">            <div class="navbar-header">              <a class="navbar-brand" href="#">pChat</a>            </div>            <ul class="nav navbar-nav navbar-right">              <li><a href="#">Log Out</a></li>            </ul>          </div>        </nav>        <!-- / Navigation Bar -->        <div class="container">          <div class="row">            <div class="col-xs-12 col-md-3">              <aside class="main">                <div class="row">                  <div class="col-xs-12">                    <div class="panel panel-default users__bar">                      <div class="panel-heading users__heading">                        Online Users (1)                      </div>                      <div class="panel-body users__body">                        <ul class="list-group">                        @if( @currentUser == "Daenerys" ) {                            <li class="user__item">                                <div class="avatar"></div> <a href="#">Jon</a>                            </li>                        } else if( @currentUser == "Jon") {                            <li class="user__item">                                <div class="avatar"></div> <a href="#">Daenerys</a>                            </li>                        }                        </ul>                      </div>                    </div>                  </div>                </div>              </aside>            </div>            <div class="col-xs-12 col-md-9 chat__body">              <div class="row">                <div class="col-xs-12">                  <ul class="list-group chat__main">                    <div class="row __chat__par__">                      <div class="__chat__ from__chat">                        <p>Did you see Avery's sword???</p>                      </div>                    </div>                    <div class="row __chat__par__">                      <div class="__chat__ receive__chat">                        <p>Err Looked normal to me...</p>                      </div>                    </div>                    <div class="row __chat__par__">                      <div class="__chat__ receive__chat">                        <p>maybe I'm a hater</p>                      </div>                    </div>                    <div class="row __chat__par__">                      <div class="__chat__ from__chat">                        <p>Lmaooo</p>                      </div>                    </div>                  </ul>                </div>                <div class="chat__type__body">                  <div class="chat__type">                    <textarea id="msg_box" placeholder="Type your message"></textarea>                  </div>                </div>                <div class="chat__typing">                  <span id="typerDisplay"></span>                </div>              </div>            </div>          </div>        </div>        <script src="@Url.Content("~/Content/app.js")"></script>        </body>    </html>

We’re using the razor template engine, which gives us the ability to read data passed from the C# code and assign them to variables that can be used in our frontend. Using @{ var currentUser = ViewBag.currentUser } we have passed in the name of the current user, which will come in handy shortly.

我們使用的是razor模板引擎 ,它使我們能夠讀取從C#代碼傳遞的數據,并將其分配給可在前端使用的變量。 使用@{ var currentUser = ViewBag.currentUser }我們傳入了當前用戶的名稱,這很快就會派上用場。

? To keep things quick and simple, we have assumed that there are only two possible users: Daenerys or Jon. So using the razor @if{ } condition, we are showing who is available to chat with.

為了使事情變得簡單快捷,我們假設只有兩個可能的用戶:D aenerys或J on。 因此,使用剃刀@ if{ }條件,我們正在顯示可以與誰聊天。

Now that we have our views in place, we can move on to our typing indicator feature!

現在我們已經有了自己的視圖,我們可以繼續使用打字指示器功能!

實施打字指示器 (Implementing the typing indicator)

聆聽打字事件 (Listening for the typing event)

In most chat applications, the feature becomes visible when someone is typing. To implement it, we’ll start off by listening for the typing event in the chat text area using jQuery. We’ll also pass the currentUser variable we defined earlier with razor to our script.

在大多數聊天應用程序中,當有人鍵入內容時,該功能將變為可見。 為了實現它,我們將從使用jQuery聊天文本區域中的鍵入事件開始。 我們還將把之前用剃刀定義的currentUser變量傳遞給腳本。

var currentUser = @currentUser;
$('#msg_box').on('keydown', function () {      //stub    });

We added a listener to the keydown event in our typing area to help us monitor when someone is typing.

我們在鍵入區域的keydown事件中添加了一個偵聽器,以幫助我們監視某人何時鍵入。

Now that we’ve created our listeners, we’ll make them send a message that someone is typing to the other members of the chat. To do this, we’ll create an endpoint in our C# code to receive this request and broadcast it via Pusher.

現在,我們已經創建了偵聽器,我們將使他們向聊天的其他成員發送一條消息,指出有人正在鍵入消息。 為此,我們將在C#代碼中創建一個端點,以接收此請求并通過Pusher廣播該請求。

We’ll implement all the client code (assuming that our C# endpoint exists, then we’ll actually create the endpoint later).

我們將實現所有客戶端代碼(假設我們的C#端點存在,然后稍后再實際創建該端點)。

? To prevent excessive requests to our C# code, that is sending a request as every key on the keypad is pressed or released, we’ll throttle the sending of the requests using a debounce function. This debounce function just ignores a function for a while if it keeps occurring.

為防止對C#代碼的過多請求(即在按下或釋放鍵盤上的每個鍵時發送請求),我們將使用反跳功能來限制請求的發送。 如果該反跳功能持續發生,則會暫時忽略該功能。

// Debounce function    // Credit: https://davidwalsh.name/javascript-debounce-function
// Returns a function, that, as long as it continues to be invoked, will not    // be triggered. The function will be called after it stops being called for    // N milliseconds. If `immediate` is passed, trigger the function on the    // leading edge, instead of the trailing.    function debounce(func, wait, immediate) {        var timeout;        return function() {            var context = this, args = arguments;            var later = function() {                timeout = null;                if (!immediate) func.apply(context, args);            };            var callNow = immediate && !timeout;            clearTimeout(timeout);            timeout = setTimeout(later, wait);            if (callNow) func.apply(context, args);        };    };

Now that we have a debounce function, we’ll create the callback function for our keydown event:

現在我們有了一個去抖動功能,我們將為keydown事件創建回調函數:

var isTypingCallback = debounce( function() {        $.post('/chat/typing', {            typer: currentUser,        });    }, 600, true);

and pass the callback to our event listeners.

并將回調傳遞給我們的事件監聽器。

$('#msg_box').on('keydown',isTypingCallback);

創建由鍵入事件觸發的端點 (Creating the endpoint triggered by the typing event)

Earlier, we had our event listeners send a POST request to the /chat/typing Route on the client side. Now we’ll create this Route, which will transmit the typing event to other client users using Pusher.

之前,我們讓事件監聽器將POST請求發送到客戶端的/chat/typing Route。 現在,我們將創建此Route,它將使用Pusher將鍵入事件傳輸給其他客戶端用戶。

First, we’ll create the route for the endpoint in our RouteConfig.cs file.

首先,我們將在RouteConfig.cs文件中為端點創建路由。

...    routes.MapRoute(        name: "UserTyping",        url: "chat/typing",        defaults: new { controller = "Chat", action = "Typing" }    );

? We’ve created this endpoint to be handled by the Typing action method of the ChatController.

我們創建了此端點,以使用C hatController的T yping action方法進行處理

Next, we’ll create our Typing action method in the ChatController:

接下來,我們將在ChatController創建Typing action方法:

[HttpPost]    public ActionResult Typing()    {        //stub    }

使用Pusher實時更新我們的應用程序 (Using Pusher to make our application update in realtime)

Our /`chat/typing` endpoint will receive a post payload of the user who is doing the typing. We’re going to use Pusher to transmit this to everyone else.

我們的/`聊天/打字”端點將收到正在進行打字的用戶的帖子負載。 我們將使用Pusher將其傳輸給其他人。

On our Pusher dashboard, we’ll create a new app filling out the information requested — app name, frontend tech, and so on. You can register for free if you don’t have an account. Next, we’ll install the Pusher Server package in our C# code using NuGet, a packer manager for .NET.

在Pusher 儀表板上 ,我們將創建一個新應用,填寫所需的信息-應用名稱,前端技術等。 如果您沒有帳戶,可以免費注冊 。 接下來,我們將使用.NET的打包程序管理器NuGet將Pusher Server軟件包安裝在C#代碼中。

? To install the package, we right-click the Packages directory, select the add Package option, and select the Pusher Server package.

要安裝該軟件包,我們右鍵單擊P ackages目錄,選擇dd軟件包選項,然后選擇P 服務器服務器軟件包。

Then we’ll add the Pusher broadcasting to our Typing action event. To use Pusher, we’ll have to import the Pusher Server namespace into our code.

然后,我們將Pusher廣播添加到我們的Typing action事件中。 要使用Pusher,我們必須將Pusher Server名稱空間導入我們的代碼中。

...    using PusherServer;
namespace HeyChat.Controllers    {        public class ChatController : Controller        {          ...
[HttpPost]          public ActionResult Typing()          {              string typer        = Request.Form["typer"];              string socket_id    = Request.Form["socket_id"];
var options = new PusherOptions();              options.Cluster = "PUSHER_APP_CLUSTER";
var pusher = new Pusher(              "PUSHER_APP_ID",              "PUSHER_APP_KEY",              "PUSHER_APP_SECRET", options);
pusher.TriggerAsync(              "chat",              "typing",              new { typer = typer },              new TriggerOptions() { SocketId = socket_id });
return new HttpStatusCodeResult(200);          }         ...

We initialized Pusher using our PUSHER_APP_ID, PUSHER_APP_KEY, PUSHER_APP_SECRET, and PUSHER_APP_CLUSTER (be sure to replace these with the actual values from your dashboard). Then we broadcast an object containing the typer — which is the person typing — on the typing event via the chat channel.

我們使用PUSHER_APP_IDPUSHER_APP_KEYPUSHER_APP_SECRETPUSHER_APP_CLUSTER初始化了Pusher(請確保將其替換為儀表板上的實際值)。 然后,我們廣播一個包含 導電型測量儀 -這是人打字-typing通過事件chat通道。

? We’ve added new TriggerOptions() { SocketId = socket_id } to our Pusher triggerAsync function. This is to prevent the sender of the broadcast from receiving the broadcast as well. To do this, we’ve assumed we’re receiving socket_id in our payload along with typer, so on our client side, we’ll add it to the payload sent.

我們在Pusher t riggerAsync函數中添加了ew TriggerOptions() { SocketId = socket_id } 這是為了防止廣播的發送者也接收廣播。 為此,我們假設我們在負載中收到了s ocket_idyper,因此在客戶端,我們將其添加到發送的負載中。

Now, whenever there’s a typing event, our C# code broadcasts it on Pusher. All that is left is to listen to that broadcast and display the ‘xxxx is typing…’ feature.

現在,每當發生打字事件時,我們的C#代碼都會在Pusher中廣播該事件。 剩下的就是收聽廣播并顯示“ xxxx正在輸入...”功能。

First, we’ll initialize Pusher in the script section of our chat page using our PUSHER_APP_KEY and PUSHER_APP_CLUSTER (once again, replace these with the values from your dashboard).

首先,我們將在聊天頁面的腳本部分中使用PUSHER_APP_KEYPUSHER_APP_CLUSTER初始化Pusher(再次將它們替換為儀表板中的值)。

var pusher = new Pusher('PUSHER_APP_KEY', {        cluster:'PUSHER_APP_CLUSTER'    });

To implement the broadcaster exemption we mentioned earlier, we’ll get the socket id from our client pusher instance and amend our payload for the typing request to the server to include it.

為了實現我們前面提到的廣播商豁免,我們將從客戶端pusher實例中獲取套接字ID,并修改向服務器的鍵入請求的有效負載以將其包括在內。

var socketId = null;    pusher.connection.bind('connected', function() {      socketId = pusher.connection.socket_id;    });
var isTypingCallback = debounce( function() {        $.post('/chat/typing', {            typer: currentUser,            socket_id: socketId // pass socket_id parameter to be used by server        });    }, 600, true);

Now that Pusher is initialized on our client side, we’ll subscribe to the chat channel and implement our feature using the typer passed.

現在,在客戶端初始化了Pusher,我們將訂閱聊天頻道并使用傳遞的typer來實現我們的功能。

var channel = pusher.subscribe('chat');
channel.bind('typing', function(data) {        $('#typerDisplay').text( data.typer + ' is typing...');
$('.chat__typing').fadeIn(100, function() {            $('.chat__type__body').addClass('typing_display__open');        }).delay(1000).fadeOut(300, function(){            $('.chat__type__body').removeClass('typing_display__open');        });    });

結論 (Conclusion)

In this tutorial, we’ve walked through implementing the popular typing indicator feature using Pusher, .NET, C# code and some jQuery. We’ve also seen how to broadcast messages and avoid the sender responding to a message they sent.

在本教程中,我們逐步使用了Pusher,.NET,C#代碼和一些jQuery實現了流行的打字指示器功能。 我們還看到了如何廣播消息以及如何避免發件人對他們發送的消息作出響應。

This post was first published to Pusher.

該帖子最初發布給Pusher 。

翻譯自: https://www.freecodecamp.org/news/how-to-build-a-typing-indicator-for-your-chat-app-in-asp-net-2b008680a69a/

asp.net應用程序

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/394069.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/394069.shtml
英文地址,請注明出處:http://en.pswp.cn/news/394069.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

activeMQ在文件上傳的應用

本次試驗主要用到了activeMq和上傳插件uploadify的知識&#xff0c;感謝以下兩篇文章的作者。 1.http://itindex.net/detail/47160-java-jquery-%E4%B8%8A%E4%BC%A0 2.http://blog.csdn.net/jiuqiyuliang/article/details/47160259 本文中不再提供activeMq和uploadify的介紹。 …

java nginx 例子_Java及nginx實現文件權限控制代碼實例

我們知道&#xff0c;使用nginx作為文件下載服務器&#xff0c;可以極大地降低對后端Java服務器的負載沖擊&#xff0c;但是nginx本身并不提供授權控制&#xff0c;因此好的方案是由后端服務器實現權限控制&#xff0c;最好的方式是直接復用應用的認證體系&#xff0c;最大化的…

leetcode934. 最短的橋(dfs+bfs)

在給定的二維二進制數組 A 中&#xff0c;存在兩座島。&#xff08;島是由四面相連的 1 形成的一個最大組。&#xff09; 現在&#xff0c;我們可以將 0 變為 1&#xff0c;以使兩座島連接起來&#xff0c;變成一座島。 返回必須翻轉的 0 的最小數目。&#xff08;可以保證答…

謝煙客---------Linux之DNS服務系統的基礎知識

DNS Domain Name Server1)C/S架構&#xff1a;SOCKET通信IP PORT2&#xff09;應用層協議&#xff1a;資源子網BIND Berkerley Information Name DomainDNS由來1&#xff09;統一名字&#xff0c;自己維護 <自己查詢>解析: 基于key查找value: 查詢數據庫(二維關系的表: …

Java實現點擊導出excel頁面遮罩屏蔽,下載完成后解除遮罩

一、問題場景 最近在做數據統計功能&#xff0c;需求是導出大數據量的excel&#xff0c;時間間隔較長&#xff0c;大概需要十秒左右&#xff0c;點擊導出后&#xff0c;頁面沒有做任何處理&#xff0c;用戶也不知道是否正在導出&#xff1b;如果沒有做交互上的限制&#xff0c;…

pbs 支持 java_Linux下Java安裝與配置

安裝以JDK1.6.0_43為例下載jdk-6u43-linux-x64.bin&#xff0c;http://www.oracle.com/technetwork/java/javase/downloads/index.html增加可執行權限 chmod x jdk-6u43-linux-x64.bin&#xff0c;執行 ./jdk-6u43-linux-x64.bin 生成目錄jdk1.6.0_43拷貝到/usr/share下&#x…

使用Chatkit構建Node.js命令行聊天應用程序

by Hugo雨果 使用Chatkit構建Node.js命令行聊天應用程序 (Build a Node.js command-line chat application with Chatkit) Building chat in your app can be pretty complex. Yet, with Chatkit, implementing fully-featured chat is nothing but a few lines of code.在您的…

java 毫秒轉分鐘和秒_Java程序將毫秒轉換為分鐘和秒

Java程序將毫秒轉換為分鐘和秒在上面的程序中&#xff0c;您將學習如何在Java中將毫秒分別轉換為分鐘和秒。示例1&#xff1a;將毫秒分別轉換為分鐘和秒import java.util.concurrent.TimeUnit;public class Milliseconds {public static void main(String[] args) {long millis…

Andrew Ng機器學習之一 導論

監督學習與無監督學習 監督學習&#xff08;Supervised Learning) Ng的原文是&#xff1a; We gave the algorithm a data set that the "right answers" were given. 即給定了一個正確結果的集合供算法學習&#xff0c;強調了需要實現準備好正負樣本喂給機器。 無監…

leetcode994. 腐爛的橘子(bfs)

在給定的網格中&#xff0c;每個單元格可以有以下三個值之一&#xff1a; 值 0 代表空單元格&#xff1b; 值 1 代表新鮮橘子&#xff1b; 值 2 代表腐爛的橘子。 每分鐘&#xff0c;任何與腐爛的橘子&#xff08;在 4 個正方向上&#xff09;相鄰的新鮮橘子都會腐爛。 返回直…

ES6對象的擴展

1.屬性簡寫表示 2.方法簡寫表示 屬性與方法簡寫&#xff1a; 3.屬性名表達式 ES6允許字面量定義對象時&#xff0c;用方法二&#xff08;表達式&#xff09;作為對象的屬性名&#xff0c;即把表達式放在方括號內。 4.Object.is()比較兩個值是否嚴格相等 轉載于:https://www.cnb…

Spring Cloud項目MVN編譯 -- Non-resolvable import POM

最近利用閑余時間&#xff0c;打算搭建一套基于Spring Cloud G版的微服務架構(Spring boot 2.1.0)&#xff0c;一頓操作之后,IDEA也沒有提示什么錯誤,自認為微服務搭建完畢。啟動項目前&#xff0c;習慣性的Maven -clean了一下&#xff0c;我去&#xff0c;IDEA里面的Maven Pro…

datax底層原理_Datax 插件加載原理

Datax 插件加載原理插件類型Datax有好幾種類型的插件&#xff0c;每個插件都有不同的作用。reader&#xff0c; 讀插件。Reader就是屬于這種類型的writer&#xff0c; 寫插件。Writer就是屬于這種類型的transformer&#xff0c; 目前還未知handler&#xff0c; 主要用于任務執行…

mysql windows身份驗證_SQL Server 2005 怎么就不能用Windows身份驗證方式登錄呢?

SQL Server 2005 自從裝到我的電腦上始終無法使用Windows身份驗證的方式登錄,由于使用用戶名和密碼登錄還算順暢,所以一直忽略了這SQL Server 2005 自從裝到我的電腦上始終無法使用Windows身份驗證的方式登錄,由于使用用戶名和密碼登錄還算順暢,所以一直忽略了這個問題,直到又有…

JavaScript正則表達式快速簡單的指南

Interested in learning JavaScript? Get my ebook at jshandbook.com有興趣學習JavaScript嗎&#xff1f; 在jshandbook.com上獲取我的電子書 正則表達式簡介 (Introduction to Regular Expressions) A regular expression (also called regex for short) is a fast way to w…

leetcode104. 二叉樹的最大深度(dfs)

給定一個二叉樹&#xff0c;找出其最大深度。二叉樹的深度為根節點到最遠葉子節點的最長路徑上的節點數。說明: 葉子節點是指沒有子節點的節點。示例&#xff1a; 給定二叉樹 [3,9,20,null,null,15,7]&#xff0c;3/ \9 20/ \15 7 返回它的最大深度 3 。代碼 class Soluti…

[解讀REST] 3.基于網絡應用的架構

鏈接上文[解讀REST] 2.REST用來干什么的&#xff1f;&#xff0c;上文中解釋到什么是架構風格和應該以怎樣的視角來理解REST&#xff08;Web的架構風格&#xff09;。本篇來介紹一組自洽的術語&#xff0c;用它來描述和解釋軟件架構&#xff1b;以及列舉下對于基于網絡的應用來…

js判斷對象還是數組

1.對于Javascript 1.8.5&#xff08;ECMAScript 5&#xff09;&#xff0c;變量名字.isArray( )可以實現這個目的 var a[]; var b{}; Array.isArray(a);//true Array.isArray(b)//false 2.如果你只是用typeof來檢查該變量&#xff0c;不論是array還是object&#xff0c;都將返回…

mysql 除去列名打印_sql – 使用beeline時避免在列名中打印表名

在beeline中使用hive時使用簡單的select查詢我想在列名中返回沒有表名的表作為默認值.例數據CREATE TABLE IF NOT EXISTS employee ( eid int, name String,salary String, destination String)COMMENT Employee detailsROW FORMAT DELIMITEDFIELDS TERMINATED BY \tLINES TERM…

移動應用程序和網頁應用程序_如何開發感覺像本機移動應用程序的漸進式Web應用程序...

移動應用程序和網頁應用程序by Samuele Dassatti通過薩穆爾達薩蒂 如何開發感覺像本機移動應用程序的漸進式Web應用程序 (How you can develop Progressive Web Apps that feel like native mobile apps) I’m currently developing a Progressive Web App that will also ser…