Home Blog Page 85

Hướng dẫn cài đặt SSH KEY cho server Linux

cài đặt ssh key
Hướng dẫn cài đặt SSH KEY cho server Linux

Bài viết được sự cho phép của tác giả Lê Chí Dũng

Lý do bạn nên sử dụng SSH Key thay password Root:

  1. Bảo mật hơn việc sử dụng password gấp n+1 lần. Hacker sẽ không thể tấn công bằng Brute Force Attack để đánh cắp password root được.
  2. Tiện lợi trong việc chứng thực vào một hoặc nhiều server nếu không đặt password cho SSH Key thì càng tiện =]].
  3. Dễ dàng cấp phát quyền cho ai đó làm việc trên một server hoặc nhiều server.
  10 điều bạn có thể làm với Linux mà bạn không thể làm với Windows
  14 khóa học Tech miễn phí chất lượng từ MIT, Harvard, Linux...

Xem thêm các việc làm Linux lương cao trên TopDev

1. SSH Key hoạt động như thế nào?

SSH Key hiểu đơn giản là một phương thức chứng thực người dùng truy cập vào server bằng cách đối chiếu giữa một key cá nhân (Private Key) trên thiết bị truy cập lưu trữ và key công khai(Public Key) trên server lưu trữ. Nội dung mã hóa trong 2 key này hoàn toàn khác nhau nhưng Server sẽ tự mã hóa Public Key theo một chuẩn RSA và đối chiếu với Private Key nếu 2 key này giống nhau là hợp lệ.

Thành phần chính của một SSH Key

Khi tạo ra một SSH Key, bạn cần biết sẽ có 3 thành phần quan trọng như sau:

  • Public Key (dạng file và string) – Copy ký tự key này sẽ bỏ vào file /root/.ssh/authorized_keys trên server của bạn.
  • Private Key (dạng file và string) – Lưu file này trên thiết bị đăng nhập, thiết lập cho PuTTY, WinSCP, MobaXterm,..
  • Keypharse (dạng string, cần ghi nhớ) – Mật khẩu để mở private key, khi đăng nhập vào server nó sẽ hỏi cái này. Nếu để trống nó sẽ không hỏi!

2. Tạo SSH Key

Trên Windows

Nếu bạn sử dụng Windows thì sẽ dùng phần mềm PuTTY-Gen để tạo SSH, bạn có thể tải PuTTY-Gen tại đây.

Tải xong bạn mở ra, bạn chọn các tùy chọn như trong ảnh dưới rồi ấn Generate.

Trong lúc tạo, bạn phải rê chuột và click vòng vòng màn hình cho đến khi nó tạo xong.

Sau khi tạo xong, bạn sẽ thấy nó hiện ra thế này.

Kế tiếp đặt mật khẩu cho keypharse.

Cuối cùng Save Private Key và backup nó ở một nơi thật an toàn.

Còn cái public key là cái dãy loằng ngoằng ở trên, nó bắt đầu bằng từ khóa ssh-rsa AAA… Đoạn code này bạn sẽ copy bỏ vào server. Khi nào cần bạn có thể Load private key trong  PuTTYGen là nó hiện ra public key.

Lưu ý tạo OpenSSH pribvate_key cho linux thì export như sau:

2017-03-21 12_44_06-PuTTY Key Generator

Trên Linux (Mac/Ubuntu/LinuxMint,..)

Nếu bạn đang sử dụng Linux thì không cần phần mềm mà sẽ sử dụng Terminal gõ:

ssh-keygen -t rsa

Nó sẽ hỏi bạn muốn lưu private key này vào đâu, mặc định nó sẽ lưu vào /home/user/.ssh. Bạn có thể để trống và Enter.

Tiếp tục nó sẽ hỏi bạn có muốn thiết lập keypharse bạn thấy cần thì nhập vào rồi Enter.

Sau khi tạo xong, mặc định nó sẽ hiện ra thế này:

Trong đó bạn có thể thấy nó có ghi đường dẫn lưu file private key (id_rsa) và file public key (id_rsa.pub). Để xem được public key, bạn cứ mở file id_rsa.pub.

cat ~/.ssh/id_rsa.pub

Cái public key này bạn sẽ mang lên Server.

3. Cấu hình Public key trên Server

Đăng nhập vào Server với tài khoản mà bạn muốn áp dụng SSH Key.

Sau đó gõ các lệnh để tạo thư mục .ssh/ và file authorized_keys trong thư mục đó:

# Tạo foler .ssh
mkdir ~/.ssh
chmod 700 ~/.ssh
# Tạo file authorized_keys lưu Public Key
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

Sau đó mở file authorized_keys trong thư mục .ssh ở thư mục gốc của user và copy toàn bộ ký tự của public key. Có bao nhiêu public key thì lưu bấy nhiêu dòng thôi.

Lưu ý:

SSH Key sẽ không thể hoạt động nếu bạn đang bật SELinux. Hãy tắt SELinux đi bằng cách mở file /etc/selinux/config, tìm SELINUX=enforcing và thay bằng SELINUX=disabled. Sau đó gõ lệnh reboot để khởi động lại server.
Để kiểm tra xem nó đã hoạt động chưa, hãy đăng nhập lại vào SSH với tài khoản vừa thêm SSH Key. Nếu bạn đăng nhập bằng Linux thì nó sẽ tự hỏi keypharse của bạn, còn nếu bạn đăng nhập ở Windows dùng PuTTY thì phải trỏ file private key vào để nó chứng thực.

Nếu dùng MobaXterm thì gắn trong phần Advanced SSH Settings nhé, phần Use private key.

Bây giờ bạn đăng nhập và nó sẽ hỏi keypharse nếu bạn có đặt keypharse, còn không đặt là nó vô thẳng server.

Tắt chức năng sử dụng mật khẩu

Sau khi kiểm tra, nếu bạn thấy đã có thể đăng nhập vào server bằng SSH Key thì có thể tắt chức năng sử dụng mật khẩu đi vì nếu không tắt, các hacker vẫn brute force attack được.

Để tắt chức năng sử dụng mật khẩu trên server, bạn mở file /etc/ssh/sshd_config, và cấu hình như sau:

PasswordAuthentication no
UsePAM no
Bài viết gốc được đăng tải tại lcdung.top
Có thể bạn quan tâm:
Xem thêm Việc làm IT hấp dẫn trên TopDev

Cách tạo sẵn mẫu comment trong INTELLIJ với Live Template

comment
Cách tạo sẵn mẫu comment trong INTELLIJ với Live Template

Bài viết được sự cho phép của blogchiasekienthuc.com

Chào các bạn, đối với anh em lập trình viên thì trong quá trình code có một việt rất quan trọng đó là viết comment.

Vậy comment trong INTELLIJ nghĩa là gì?

Vâng, comment là những chú thích, là những ghi chú với mục đích là để cho người viết code và cả người đọc code có thể hiểu được đoạn chương trình đó chạy như thế nào và mục đích là gì.

  Bí mật giúp thiết kế UX cực hiệu quả cho sản phẩm e-commerce
  Cách sử dụng lệnh Xcopy trong CMD (Command Prompt)

Nhưng trong thực tế có những comment lặp đi lặp lại với một dạng nhất định, nếu cứ mỗi lần tạo hàm mới lại hì hục viết comment thì sẽ rất mất thời gian.

Vì vậy trong bài viết này mình sẽ hướng dẫn anh em cách tạo một comment với định dạng sẵn, anh em chỉ cần gõ từ gợi ý là đoạn comment sẽ tự xổ ra.

Lưu ý: Hướng dẫn này mình dựa trên ngôn ngữ lập trình Java và công cụ IntelliJ Idea nhé.

#1. Ví dụ một đoạn comemnt với các thông tin

  • @author: Người tạo hàm đó
  • @since: Thời gian khởi tạo hàm
  • @description: Mô tả chức năng của hàm
  • @update: Các cập nhật của hàm này sẽ được ghi lại tại đây.

cach-tao-comment-trong-intellij (1)

#2. Hướng dẫn tạo một template comment trong INTELLIJ

Đầu tiên các bạn vào mục File => chọn Setting… hoặc phím tắt là Ctrl + Alt + S như hình bên dưới.

cach-tao-comment-trong-intellij (2)

Tiếp theo trong phần tìm kiếm các bạn nhập Live Templates => rồi chọn các lựa chọn như hình bên dưới.

cach-tao-comment-trong-intellij (3)

Để tạo một Template:

  • (1) Đặt tên (tên này sẽ là tên gợi ý, khi bạn gõ tên này và Enter thì sẽ tạo một template được định nghĩa bên dưới)
  • (2) Mẫu một comment, các bạn có thể tham khảo:

/*
* @author: LongNV
* @since: $nowDate$ $dateTime$
* @description:  $desc$
* @update:
*
* */

Sau khi có tên và nội dung template rồi thì các bạn bấm vào chữ Define như hình ảnh bên dưới.

cach-tao-comment-trong-intellij (4)

Tại đây, nếu bạn định tạo comment cho ngôn ngữ lập trình nào thì chọn ngôn ngữ tương ứng. Nguyên nhân bởi vì mỗi ngôn ngữ có thể có các kiểu comment khác nhau.

Tiếp theo, các bạn bấm Edit variables để chỉnh sửa các biến mà chúng ta sử dụng trong template. Ở đây mình có ba biến đó là:

  • $nowDate$: Ngày hiện tại
  • $dateTime$: Thời gian cụ thể
  • $desc$: Miêu tả

cach-tao-comment-trong-intellij (5)

Sau khi chọn chức năng Edit thì đây chính là màn hình chúng ta sẽ sửa các biến, chính xác hơn chọn giá trị tương ứng cho các biến.

  • nowDate: Mình sẽ chọn tương ứng với date()

cach-tao-comment-trong-intellij (6)

Tương tự thì dateTime mình sẽ chọn tương ứng với time() như hình bên dưới.

cach-tao-comment-trong-intellij (7)

Okay, vậy là công đoạn tạo template đã xong rồi. Bây giờ các bạn có thể gõ chữ “com…” ở bất cứ đâu trong chương trình để tạo một comment với mẫu đã tạo.

cach-tao-comment-trong-intellij (8)

Đây chính là kết quả, các bạn có thể thấy có rất nhiều trường hợp chúng ta phải tạo các comment như thế này. Việc chỉ cần nhập từ gợi ý để tạo một comment dài như thế này là thực sự rất tiện lợi.

cach-tao-comment-trong-intellij (9)

Không những bạn có thể tạo một comment như vậy, mà bạn còn có thể tạo ra rất nhiều các comment khác nhau.

Ví dụ trong phần @update, mình cũng sẽ tạo một template với nội dung như ảnh bên dưới để phục vụ việc khi mình có cập nhật gì đó cho hàm mình đang viết.

cach-tao-comment-trong-intellij (10)

Các bạn cũng có thể gõ gợi ý up… để tạo ra một comment tương ứng template mà các bạn đã định nghĩa thêm.

cach-tao-comment-trong-intellij (11)

Và đây chính là một comment đầy đủ, nhìn có vẻ rất là dài nhưng thông qua việc sử dụng Live Template mình đã viết đoạn comment chỉ với một hai phím gõ.

cach-tao-comment-trong-intellij (12)

#3. Kết luận

Vâng, như vậy là việc tạo comment ghi chú nhanh trong INTELLIJ với tính năng LIVE TEMPLATE cũng không có gì khó khăn cả, có đúng không ạ 🙂

Trên thực tế thì những dự án có nhiều người cùng làm và làm trong thời gian dài sẽ không thể tránh khỏi việc mỗi người code một kiểu.

Nếu không có các dòng comment để chú thích code thì thực sự rất khó cho người sau, chưa kể còn không biết được ai viết hàm đó, chức năng… đó để nhỡ có bị lỗi còn “lôi” ra hỏi.

Nhưng đôi khi việc viết comment lại khá tốn thời gian, vậy nên việc sử dụng Live Templates sẽ là một trong những cách rất hay để tạo nhanh comment mà không tốn quá nhiều thời gian cho nó.

CTV: Nguyễn Đức Cảnh – Bài viết gốc tại blogchiasekienthuc.com

Có thể bạn quan tâm:

Xem thêm Việc làm IT hấp dẫn trên TopDev

Bazel 4.1.0: Bài 3 – Build ứng dụng mẫu

Build ứng dụng
Build ứng dụng mẫu

Bài viết được sự cho phép của tác giả Lê Xuân Quỳnh

Dùng terminal gõ lệnh sau để lấy source code mẫu:

git clone -b source-only https://github.com/bazelbuild/examples

cd vào thư mục examples/tutorial và tạo ra file WORKSPACE bằng cách gõ:

touch WORKSPACE

Mở nó lên và gõ tiếp:

load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")

git_repository(
    name = "build_bazel_rules_apple",
    remote = "https://github.com/bazelbuild/rules_apple.git",
    tag = "0.31.3",
)

git_repository(
    name = "build_bazel_rules_swift",
    remote = "https://github.com/bazelbuild/rules_swift.git",
    tag = "0.23.0",
)

git_repository(
    name = "build_bazel_apple_support",
    remote = "https://github.com/bazelbuild/apple_support.git",
    tag = "0.11.0",
)

git_repository(
    name = "bazel_skylib",
    remote = "https://github.com/bazelbuild/bazel-skylib.git",
    tag = "1.0.3",
)

File trên để lấy rule remote theo name và tag của chúng để build project chúng ta.

  6 project vui dành cho dev build khi chán
  Anh hào UX hội tụ tại Building your UX Design from scratch

Mẹo: trên trang chủ của bazel nội dung khác hẳn với file trên. Lý do tại sao các tag lại khác, đó là tại thời điểm viết bài này thì các tag của các repository ở trên đã cập nhật bản mới nhất. Cụ thể nếu bạn muốn lấy phiên bản repository mới nhất, ví dụ của link https://github.com/bazelbuild/rules_apple.git thì bạn gõ vào trình duyệt link đó, và vào mục tag của nó để xem tag hiện tại là bao nhiêu, ví dụ tôi tìm được tag:

https://github.com/bazelbuild/rules_apple/releases/tag/0.31.3

Tương tự cho các repository khác.

Bạn tiếp tục cd vào thư mục ios-app và tạo file BUILD:

touch BUILD

Và thêm nội dung vào file BUILD:

load("@build_bazel_rules_apple//apple:ios.bzl", "ios_application")
objc_library(
    name = "UrlGetClasses",
    srcs = [
         "UrlGet/AppDelegate.m",
         "UrlGet/UrlGetViewController.m",
         "UrlGet/main.m",
    ],
    hdrs = glob(["UrlGet/*.h"]),
    data = ["UrlGet/UrlGetViewController.xib"],
)

ios_application(
    name = "ios-app",
    bundle_id = "Google.UrlGet",
    families = [
        "iphone",
        "ipad",
    ],
    minimum_os_version = "9.0",
    infoplists = [":UrlGet/UrlGet-Info.plist"],
    visibility = ["//visibility:public"],
    deps = [":UrlGetClasses"],
)

Phân tích nội dung:

objc_library(
    name = "UrlGetClasses",
    srcs = [
         "UrlGet/AppDelegate.m",
         "UrlGet/UrlGetViewController.m",
         "UrlGet/main.m",
    ],
    hdrs = glob(["UrlGet/*.h"]),
    data = ["UrlGet/UrlGetViewController.xib"],
)

Đoạn này bạn tạo ra 1 library objective-c có tên là UrlGetClasses, gồm các file code .m nằm ở thư mục UrlGet. Các file header nằm ở hdrs, các file data chỉ có 1 file .xib ở trên.

Để tạo ra file .ipa ta có rule:

ios_application(
    name = "ios-app",
    bundle_id = "Google.UrlGet",
    families = [
        "iphone",
        "ipad",
    ],
    minimum_os_version = "9.0",
    infoplists = [":UrlGet/UrlGet-Info.plist"],
    visibility = ["//visibility:public"],
    deps = [":UrlGetClasses"],
)

Tên file build ra là ios-app, tên bundle_id của app là Google.UrlGet, hỗ trợ cho families là iphone và ipad. Phiên bản tối thiểu là minimum_os_version 9.0. File plit là UrlGet-Info.plist, trạng thái là visibility public. Phụ thuộc vào thư viện đầu ra thư viện là UrlGetClasses.

Build ứng dụng

Bạn cd ra thư mục tutorial và gõ:

bazel build //ios-app:ios-app

Đợi 1 lúc thấy thông báo như ảnh sau là thành công:

Bạn sẽ thấy bazel tạo ra file output ở đường dẫn:

bazel-out/applebin_ios-ios_x86_64-fastbuild-ST-e637a0adc749/bin/ios-app/ios-app.ipa

Vậy là bước đầu bạn đã hiểu cơ bản về cách build 1 ứng dụng iOS đơn giản nhất bằng bazel.

Bài viết gốc được đăng tải tại codetoanbug.com

Có thể bạn quan tâm:

Xem thêm Việc làm IT hấp dẫn trên TopDev

Lập trình web cơ bản với Javascript jQuery

javascript jquey
Lập trình web cơ bản với Javascript jQuery

Bài viết được sự cho phép của smartjob.vn

Lập trình web cơ bản với Javascript jQuery

Giáo trình Javascript jQuery bản tổng hợp từ cơ bản đến nâng cao bằng tiếng Việt

Giáo trình cung cấp những kiến thức cơ bản nhất cho những ai chưa biết về Javascript và hướng dẫn sử dụng thư viện jQuery của Javascript. Các kiến thức thực tế cần thiết cho việc xây dựng một trang web sẽ được liệt kê và phân tích đầy đủ, rõ ràng.

  10 câu hỏi javascript để nâng cao trình độ
  10 tip tối ưu code trên JavaScript mà web developer nào cũng nên biết

Xem thêm nhiều việc làm JavaScript hấp dẫn trên TopDev

Review về Ebook

Javascript là một ngôn ngữ lập trình kịch bản hướng đối tượng, được phát triển bởi Nestcape và có sự hậu thuẫn mạnh mẽ từ Apple, Microsoft, Oracle, Sybase,… Với sự gia đời của Javascript, các trang web tĩnh HTML trở nên thân thiện và hữu dụng hơn lúc nào hết. Ebook về Javascript bao gồm các chương cơ bản sau:

  • Chương 1: Lời nói đầu
  • Chương 2: Nhập môn Javascript (nhúng Javascript vào file HTML, giới thiệu các thẻ, cách hiển thị một dòng text,…)
  • Chương 3: Các biến trong Javascript, các câu lệnh, mảng,…
  • Phần câu hỏi và bài tập

Với sự phát triển rất mau lẹ của Internet, người dùng ngày càng quan tâm tới hình thức của một trang web. Trước đây, website của bạn chỉ cần banner, nội dung và chút footer là đã hoàn chính. Nhưng giờ đây, tất cả các yếu tố đó cần được đầu tư kỹ lưỡng hơn, lạ mắt hơn để thu hút người dùng. Bởi vậy, các designer bắt đầu hướng sự chú ý đến các thư viện Javascript mở như jQuery nhằm tạo ra những hiệu ứng tương tác trực tiếp tới người đọc.

Các bạn có thể tải Ebook về Javascript tại đây.

Đó là những tài liệu cung cấp kiến thức lập trình web cơ bản nhất cho người mới bắt đầu. Ngoài ra, bạn có thể tham khao thêm những bài viết về lập trình được đội ngũ kỹ thuật viết tại Cẩm nang lập trình.

Bài viết gốc được đăng tải tại smartjob.vn

Có thể bạn quan tâm:

Xem thêm Việc làm IT hấp dẫn trên TopDev

Hướng dẫn sử dụng composer cơ bản

composer
Hướng dẫn sử dụng composer cơ bản

Bài viết được sự cho phép của tác giả Kien Dang Chung

Composer quản lý sự phụ thuộc của một dự án với các thư viện lập trình bên ngoài thông qua một số các tập tin và liên quan đến một số thuật ngữ, chúng ta sẽ bắt đầu tìm hiểu cách sử dụng composer nhé.

Composer.json file chứa các thiết lập dự án

Để bắt đầu một dự án bạn cần có một file composer.json, file này chứa mô tả các thư viện ngoài mà dự án cần cài đặt (phụ thuộc) bằng từ khóa require.

{
    "require": {
        "monolog/monolog": "1.0.*"
    }
}

Phần thiết lập trên nói lên rằng dự án cần gói có tên là monolog/monolog với yêu cầu phiên bản là 1.0.*. Composer sẽ sử dụng thông tin này và tìm kiếm các gói được đăng ký bằng từ khóa repositories hoặc trong Packagist là một kho tài nguyên các gói thư viện trên mạng. Chúng ta tiếp tục làm quen một số thuật ngữ:

Package name

Package name chứa tên nhà cung cấp và tên dự án, ví dụ trên tên nhà cung cấp và tên dự án trùng nhau là monolog. Có thể hai nhà cung cấp khác nhau đặt trùng tên dự án, ví dụ igorw/json là dự án json của nhà cung cấp igorw khác với gói thư viện seldaek/json là dự án json của nhà cung cấp seldaek.

Hạn chế phiên bản gói thư viện

Chúng ta có thể hạn chế phiên bản gói cần cài đặt để đảm bảo dự án hoạt động tốt với tính năng của gói ở một số phiên bản. Trong ví dụ trên, chúng ta yêu cầu gói monolog/monolog với hạn chế phiên bản là 1.0.* tức là các phiên bản >1.0 và <1.1 thỏa mãn yêu cầu.

  Hướng dẫn sử dụng composer cơ bản

Sử dụng composer cài đặt các gói cần thiết

Thực hiện cài đặt các gói đã được khai báo trong composer.json bằng lệnh

php composer.phar install

Nếu bạn đã thêm đường dẫn đến composer.bat vào biến môi trường PATH thì chỉ cần gõ ngắn gọn hơn:

composer install

Khi chạy lệnh cài đặt này sẽ có hai tình huống xảy ra:

  • Nếu trước đó bạn chưa chạy lệnh này bao giờ sẽ không có file composer.lock. Composer sẽ đơn giản là đọc thông tin các gói cần thiết trong composer.json và tải phiên bản mới nhất trong hạn chế phiên bản về thư mục vendor trong dự án. Trong ví dụ trên khi thực hiện lệnh composer install xong chúng ta sẽ thấy có thư mục monolog/monolog trong thư mục vendor của dự án. Khi composer cài đặt xong, tất cả các gói cùng với phiên bản chính xác sẽ được lưu vào composer.lock, bởi vậy tất cả mọi người tham gia dự án sẽ bị lock ở cùng một phiên bản các gói thư viện lập trình.
  • Nếu file composer.lock tồn tại, có nghĩa là bạn đã chạy lệnh install trước đó hoặc có thể một ai đó đã chạy lệnh install và commit file composer.json. Chạy lệnh install khi có tập tin composer.lock giúp Composer sử dụng phiên bản chính xác được liệt kê trong composer.lock và đảm bảo phiên bản các gói thư viện sẽ phù hợp với mọi người đang tham gia trong dự án. Kết quả bạn sẽ có các phiên bản được yêu cầu trong composer.json nhưng không phải tất cả chúng ở phiên bản mới nhất do một số liệt kê trong composer.lock đã phát hành phiên bản mới hơn. Thiết kế này đảm bảo dự án của bạn không bị phá vỡ do những thay đổi bất ngờ trong các gói thư viện.

Commit composer.lock với trình quản lý phiên bản

Như đã viết ở trên, composer.lock sẽ ngăn chặn việc tự động lấy xuống các phiên bản mới nhất, để cập nhật chúng sử dụng lệnh update. Khi chạy lệnh này nó sẽ lấy tất cả các phiên bản mới nhất phù hợp với hạn chế phiên bản trong composer.json và sau đó nó update các thông tin phiên bản chính xác vào composer.lock.

php composer.phar update

hay ngắn gọn

composer update

Chú ý: Composer sẽ hiển thị một cảnh báo khi sử dụng lệnh install mà file composer.json và composer.lock chưa được đồng bộ. Nếu bạn chỉ muốn cập nhật một gói thư viện cụ thể, có thể sử dụng lệnh:

php composer.phar update monolog/monolog [...]

Packagist

Packagist là một nơi chứa các gói thư viện chính của Composer, bạn có thể truy cập Packagist tại https://packagist.org. Bạn có thể tải về các gói thư viện tại đây, vì vậy bạn có thể sử dụng lệnh require để yêu cầu bất kỳ gói thư viện nào có trên Packagist.

php composer.phar require vendor/package:2.*

Gói vendor/package phiên bản hạn chế 2.* sẽ được kiểm tra trong file composer.json, nếu chưa có sẽ được thêm vào phần require. Sau khi thêm hoặc thay đổi composer.json, các gói yêu cầu sẽ được cài đặt hoặc cập nhật.

Composer gọi các gói thư viện trong lập trình như thế nào?

Composer tạo ra file vendor/autoload.php, file này dùng để include vào bắt đầu sử dụng các class mà gói thư viện cung cấp.

require __DIR__ . '/vendor/autoload.php';

$log = new Monolog\Logger('name');
$log->pushHandler(new Monolog\Handler\StreamHandler('app.log', Monolog\Logger::WARNING));
$log->addWarning('Foo');

Bạn có thể thêm các đoạn code riêng vào autoloader này bằng cách thêm vào trường autoload trong composer.json:

{
    "autoload": {
        "psr-4": {"Acme\\": "src/"}
    }
}

Composer sẽ đăng ký PSR-4 cho namespace Acme. src là một thư mục nằm trong thư mục gốc của dự án, ngang mức với thư mục vendor, một file src/Foo.php chứa class Acme/Foo. Sau khi thêm autoload, bạn phải chạy lệnh dump-autoload để hệ thống build lại file vendor/autoload.php. Sau đó, bạn cũng include file vendor/autoload.php và gọi được các class mà bạn tự viết.

$loader = require __DIR__ . '/vendor/autoload.php';
$loader->addPsr4('Acme\\Test\\', __DIR__);

Thuật ngữ PSR-4 là viết tắt của PHP Standards Recommendation 4 là chuẩn quy ước viết code do nhóm FIG(Framework Interop Group) đề xuất và hiện tại có 5 chuẩn là PSR-0 đến PSR-4. Chúng tôi sẽ trở lại bài viết chi tiết các chuẩn này trong bài Các tiêu chuẩn viết code trong PHP.

Bài viết gốc được đăng tải tại allaravel.com

Có thể bạn quan tâm:

Xem thêm Việc làm IT hấp dẫn trên TopDev

Bazel 4.1.0: Bài 2 – khái niệm và thuật ngữ

khái niệm bazel
Bazel 4.1.0: Bài 2 – khái niệm và thuật ngữ

Bài viết được sự cho phép của tác giả Lê Xuân Quỳnh

Workspace, packages và targets

Workspace

Workspace là file để giúp bazel hiểu các thành phần source code để build ứng dụng của bạn. Nó là text file và có tên là WORKSPACE, nó có thể rỗng hoặc chứa các phụ thuộc bên ngoài để build ứng dụng.

  Bazel 4.1.0: Bài 1 – Cài đặt bazel 4.1.0
  "Làm PM, theo anh không cần biết về code, nhưng phải hiểu về SQL, database, những khái niệm cơ bản của code"

WORKSPACE.bazel hay WORKSPACE trong bazel đều là 1.

ví dụ về WORKSPACE của telegram. File này nằm ở thư mục root của source code.

Repositories

Cách tổ chức source code gọi là repositories. Thư mục có chứa file WORKSPACE gọi là thư mục chính, đặt tên là @. Các repositories bên ngoài định nghĩa trong WORKSPACE theo workspace rules. Các quy tắc xem ở đây.

Các repositories bên ngoài cũng có WORKSPACE. Tuy nhiên Bazel sẽ bỏ qua chúng.

Packages

Đơn vị tổ chức source code bằng repository gọi là package. Một package là cách tổ chức các files liên quan tới nhau và phụ thuộc giữa chúng.

Một package được định nghĩa trong 1 thư mục và chứa file BUILD hay BUILD.bazel, nằm bên trong thư mục root chứa file WORKSPACE. Chúng ta hiểu nôm na là các submodule cũng được.

Các package của Telegram-iOS

Ví dụ về cách tổ chức 1 package của Telegram-iOS:

Targets

Một package thì gọi là 1 nơi chứa source code. Còn các thành phần của 1 package thì gọi là target. Các target được quy định qua file và quy tắc của nó. Group target được định nghĩa ở đây.

Các package group được định nghĩa bởi package_group.

Labels

Tên của 1 target gọi là label. Tên điển hình có dạng như sau:

@myrepo//my/app/main:app_binary

Label @myrepo  thường được viết như sau:

//my/app/main:app_binary

Package names, //package-name:...

Tên của package được định nghĩa ở BUILD file của nó.

Rules

Rules là quy tắc giữa input và output, và các bước để build ra outputs. Mọi rule đều có 1 tên định nghĩa qua attribute name. Ví dụ:

swift_library(
    name = "AccountContext",
    module_name = "AccountContext",
    srcs = glob([
        "Sources/**/*.swift",
    ]),

BUILD files

Là tập hợp các quy tắc mà chúng ta đã mô tả qua packages, targets và labels ở trên. Mỗi package chứa 1 BUILD file là 1 chương trình nhỏ.

Loading an extension

Bazel sử dụng các file kết thúc bằng .bzl để load các extension:

load("//foo/bar:file.bzl", "some_library")

Nó sẽ load thư viện some_library bên ngoài và đưa vào chương trình.

Kiểu của build rule

Tùy ngôn ngữ mà sẽ có từng type khác nhau, ví dụ cc_binary, cc_library và cc_test là rule của C++.

Dependencies

Một target A phụ thuộc 1 target B thì cần 1 quy tắc để mô tả nó, gọi là dependency graph. Nếu B sử dụng code trong C nữa thì khi đó A sẽ có ràng buộc trong BUILD file như sau:

rule(
    name = "a",
    srcs = "a.in",
    deps = "//b:b",
)

B có build file như sau:

rule(
    name = "b",
    srcs = "b.in",
    deps = "//c:c",
)
a_b_c.svgbiểu đồ phụ thuộc nhau
Danh mục
Có thể bạn quan tâm:

Selenium IDE – Record and Playback

selenium IDE
Selenium IDE – Record and Playback

Bài viết được sự cho phép của vntesters.com

Để đáp lại lòng mong mỏi & yêu cầu của rất rất nhiều bạn đọc gần xa sau bài “Giới thiệu công cụ kiểm thử tự động Selenium“, chào mừng các bạn trở lại với Selenium phần 2 của mình – Selenium IDE – Record and Playback. Hi vọng không có quá nhiều bạn bị găm miểng sau câu đầu “cưa bom” của mình.

Như hầu hết tất cả các test tool, Selenium cũng hỗ trợ chức năng Record/Playback để chúng ta có thể tạo ra những test script đơn giản, không cần quá nhiều xử lý code hay exception. Selenium IDE đơn giản sẽ copy và làm chính xác hầu hết hành động của chúng ta trên một ứng dụng web.

  Download, Export file tự động với Selenium Webdriver
  Giới thiệu công cụ kiểm thử tự động Selenium

Trước hết, Selenium IDE là một add-on của FireFox. Chúng ta chỉ có thể cài đặt và Record trên FireFox mà thôi. Ở version 1.X, Selenium IDE chỉ cho phép chúng ta Playback trên FireFox, nhưng ở version 2.X, chúng ta có thể Playback trên hầu hết browser hiện hành như IE hay Chrome.

Bước đầu tiên là cài đặt add-on Selenium IDE trên FireFox. Thật đơn giản, chúng ta chỉ cần vào phần add-on của FireFox, search Selenium và cài đặt như một add-on bình thường. Bạn cũng có thể vào trang chủ của Selenium và download nó.

download selenium IDE

Sau khi chọn download, FireFox sẽ hỏi lại để chắc chắn là chúng ta muốn cài đặt add-on này lên browser. Các bạn chọn “Allow” và “Install Now”

Selenium IDE AllowSelenium IDE Install

Sau khi cài đặt Selenium IDE (các bạn có thể xem đoạn clip này để rõ hơn), chúng ta sẽ thể thấy menu item của Selenium trong menu Tools.

Installed Selenium IDE

Hotkey của Selenium IDE là Ctrl+Alt+S. Màn hình chính của Selenium IDE như sau:

Selenium IDE Editor

  • Base URL là nơi lưu trữ homepage của ứng dụng web
  • Test Case list liệt kê tất cả test case có trong test suite
  • Fast…Slow xác định tốc độ execute một test case
  • Play entity test suite thực thi tất cả test case chúng ta đang mở
  • Play current test case thực thi test case đang được mở
  • Pause/Resume: Tạm ngưng/Tiếp tục thực thi test case đang chạy
  • Step: thực thi từng bước một trong test case. Chỉ có tác dụng khi test case đang tạm ngưng
  • Apply Rollup Rules: Chức năng đặc biệt cho phép chúng ta nhóm nhiều action nhỏ thành một action lớn
  • Record Sao chép lại hành động của chúng ta và ghi ra danh sách action.
  • Table/Source danh sách các action trong test case
  • Command danh sách các action mà Selenium IDE đang hỗ trợ
  • Target định nghĩa control mà chúng ta đang tương tác. Các bạn có thể xem chi tiết ở bài Selenium – Xác Định Đối Tượng UI
  • Value dữ liệu test
  • Log thông tin về action đang được thực thi
  • Reference hướng dẫn sử dụng action đang được chọn
  • UI-Element and Rollup được sử dụng ở mức advance, khi mà chúng ta tự thiết kế các nhận diện control hay gom nhóm action.

Next, chúng ta thử Record bằng cách tương tác trên Firefox

Như các bạn thấy, chúng ta làm đến đâu là Selenium IDE sẽ copy và tạo ra một dòng action tương ứng…

Selenium IDE Record

và, Playback…..

Congratulation, các bạn đã tạo ra một test case bằng Selenium IDE (Youtube)

Cuối cùng, chúng ta lưu test case lại để có thể tái sử dụng vào lần sau (Regression Test). Ở đây, Selenium IDE có hai chức năng, Save và Export. Chức năng Save sẽ lưu test case của chúng ta ở dạng html, giống như những gì chúng ta thấy trong tab Source. Chức năng Export dùng để phát sinh ra code ở nhiều ngôn ngữ khác nhau như Python, Java, C#, Ruby. Các bạn chú ý là Export sẽ ra hai dạng code khác nhau, RC và WebDriver. Đây là hai dạng của Selenium Scripting mà mình đã đề cập ở phần một. Khi Save test case ở dạng html, chúng ta có thể mở lại test case trong Selenium IDE và Playback. Khi Export test case ra code, chúng ta không thể import lại Selenium IDE để Playback, mà chúng ta chỉ có thể sử dụng nó trong một framework khác như VS, Eclipse hay RobotFramework.

Selenium IDE Save

Hẹn các bạn ở phần 3 “Selenium IDE – Record and Playback trên các trình duyệt (không phải Firefox)


Các clips minh họa:

Bài viết gốc được đăng tải tại vntesters.com

Có thể bạn quan tâm:

Xem thêm Việc làm IT hấp dẫn trên TopDev

Hướng dẫn tắt cách tắt Superfetch (SysMain) trên Windows 10

tắt superfetch
Hướng dẫn tắt cách tắt Superfetch (SysMain) trên Windows 10

Bài viết được sự cho phép của blogchiasekienthuc.com

Tuy đã được ra mắt từ rất lâu và thua kém rất nhiều mặt khi so sánh ổ cứng HDD với ổ SSD, nhưng không thể phủ nhận một điều là hiện nay ổ cứng HDD vẫn đang được sử dụng rất rộng rãi trong việc lưu trữ dữ liệu.

Bởi khi chọn ổ cứng để lưu trữ dữ liệu thì tốc độ đọc ghi không còn là yếu tố quan trọng với người dùng cá nhân nữa, mà thay vào đó dung lượng lớn mới là yếu tố được đặt lên hàng đầu.

Lớn nhất hiện tại là ổ cứng có dung lượng 20TB của Seagate và đang có xu hướng tăng dần, cùng với mức giá mềm hơn rất rất nhiều khi so với ổ cứng SSD cùng dung lượng.

  Tìm hiểu về tiến trình Superfetch (Sysmain) trên Windows
  Fix Lỗi "RDP Authentication Error Has Occurred – The Function Requested Is Not Supported"

Ngoài ra, ổ HDD cũng đang là thiết bị lưu trữ dữ liệu chính của máy tính, đặc biệt là trên các mẫu PC/ Laptop giá rẻ cho học sinh, sinh viên hoặc các máy tính đời cũ.

Mà khi sử dụng hệ điều hành Windows 10 với ổ cứng HDD thì đồng nghĩa với việc bạn sẽ phải đối mặt với lỗi Full Disk 100%, máy thường xuyên xảy ra hiện tượng giật lag khi làm việc với các tác vụ nặng.

cach-tat-superfetch-sysmain-tren-windows-10 (1)

May mắn là chúng ta vẫn có thể áp dụng một vài thủ thuật để tinh chỉnh/ thiết lập để có thể giảm bớt được tình trạng này.

Và ở trong vài viết này mình sẽ hướng dẫn cho các bạn cách tắt service Superfetch (Sysmain) trên Windows để khắc phục lỗi Full Disk trên Windows 10 nhé !

I. Cách tắt Superfetch (Sysmain) trên Windows 10

Trên blog đã có vài bài hướng dẫn cách tối ưu và tăng tốc Windows 10, trong đó cũng nói về cách tắt dịch vụ Superfetch (ở phần #6), cùng hướng dẫn tắt sử dụng Services Manager mặc định của Windows 10.

Thế nên bạn hãy đọc lại các bài viết đó nếu muốn nhé, còn trong khuôn khổ của bài viết này mình sẽ không nói lại nữa.

Mà ở đây mình sẽ chia sẻ cho các bạn vài cách nâng cao để có thể tắt dịch vụ Sysmain trên Windows trong trường hợp không thể dùng được Services Manager.

Nhưng trước tiên, nếu bạn chưa biết gì về Superfetch (sysmain) thì có thể tham khảo bài viết này nhé: Tìm hiểu về tiến trình Superfetch (Sysmain) trên Windows

I. Cách tắt Sysmain bằng các tinh chỉnh trong Registry của Windows

Registry là nơi lưu trữ các thông tin cũng như hầu hết các thiết lập của hệ điều hành Windows, với nó bạn có thể can thiệp rất sâu vào hệ thống bằng các tinh chỉnh đơn giản.

Trái lại, chỉnh sửa Registry đi kèm với rủi ro lỗi Windows rất cao nên bạn cần backup lại toàn bộ Registry trước khi thực hiện theo bất cứ hướng dẫn nào, để có thể khôi phục khi cần – tránh mất dữ liệu không đáng có.

Thực hiện:

+ Bước 1: Đầu tiên, bạn mở hộp thoại RUN ra (Windows + R) => rồi nhập vào lệnh regedit => và bấm phím Enter để truy cập công cụ Registry Editor trên Windows 10.

Ngoài ra, bạn có thể nhấn Windows + S để mở Windows Search => sau đó nhập trực tiếp câu lệnh này vào ô tìm kiếm hoặc từ khóa Registry Editor thì cũng mở được công cụ này, mình thì quen dùng Windows RUN hơn vì nó đơn giản và tiện.

cach-tat-superfetch-sysmain-tren-windows-10 (2)

+ Bước 2: Sau đó, bạn truy cập vào thư mục Sysmain trong Registry của Windows 10 theo đường dẫn:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\SysMain

Bạn có thể dán trực tiếp đường dẫn này vào thanh địa chỉ của Registry Editor => rồi bấm Enter để truy cập nhanh hơn.

Nếu không thấy thanh địa chỉ như trong hình bên dưới, bạn hãy click vào chữ View trên thanh điều hướng ngang và chọn dòng Address Bar để hiển thị thanh địa chỉ nha.

cach-tat-superfetch-sysmain-tren-windows-10 (3)

+ Bước 3: Rồi ở trong thư Sysmain này, bạn sẽ thấy có rất nhiều các khóa quy định cách thức hoạt động của Superfetch trên Windows 10.

Theo như thông tin ở đây, Superfetch không có file thực thi *.exe cụ thể mà chỉ có file sysmain.dll nằm trong thư mục System32 và hoạt động được nhờ có các Service Host.

Quay trở lại vấn đề chính, hãy tìm trong danh sách này một khóa có tên Start, đây chính là khóa quy định trạng thái bật tắt của Superfetch trên Windows 10. Bạn hãy click chuột phải lên khóa này => rồi chọn Modify… để chính sửa giá trị của nó.

Mặc định khóa Start đã có sẵn trong Registry của Windows 10, nhưng trong trường hợp không thấy thì bạn hoàn toàn có thể tạo lại bằng cách:

Click chuột phải vào khoảng trống bất kỳ trong cửa sổ bên phải => chọn New => DWORD (32-bit) Value rồi đặt tên cho nó là Start và bắt đầu chỉnh sửa.

cach-tat-superfetch-sysmain-tren-windows-10 (4)

+ Bước 4: Cửa sổ Edit DWORD (32-bit) Value xuất hiện, chỉ chỉnh sửa giá trị trong ô Value data, những cái còn lại hãy giữ nguyên. Với Value data, chúng ta có 4 giá trị tương ứng với 4 trạng thái của dịch vụ Superfetch này bao gồm:

  • – Automatic (Delayed Start) – Tự động chạy nhưng chỉ khi Windows đã khởi động xong
  • – Automatic – Tự động chạy và khởi động đồng thời với Windows – Cái này là mình đang để như bạn thấy trong hình ở bên trên.
  •  Manual – Chỉ chạy khi bạn hoặc phần mềm nào đó khởi động nó lên.
  • 4 – Disabled – Tắt Superfetch

=> Vì trong bài viết này chúng ta đang muốn tắt Superfetch để sửa lỗi Full Disk, tăng tốc Windows 10 nên bạn hãy nhập vào ô Value data số 4 => rồi bấm OK để lưu lại.

cach-tat-superfetch-sysmain-tren-windows-10 (5)

+ Bước 5: Quá trình chỉnh sửa Registry đã hoàn tất, giờ bạn đã có thể đóng Registry Editor và khởi động lại máy khi có thể để các thay đổi vừa thực hiện có hiệu lực.

#2. Tắt Superfetch bằng lệnh trong CMD

Nếu như bạn không thích chỉnh sửa trong Registry vì sợ sai hoặc không rành về máy tính thì cũng có thể sử dụng vài dòng lệnh dưới đây trong cửa sổ Command Prompt.

Thực hiện:

Hãy mở Windows Run ra (Windows + R) => rồi nhập cmd và sử dụng tổ hợp phím Ctrl + Shift + Enter để mở CMD với quyền Admin, khuyến khích các bạn sử dụng cách này vì nó tiện 😀

cach-tat-superfetch-sysmain-tren-windows-10 (6)

Trước tiên, chúng ta cần dừng dịch vụ Superfetch lại để nó ngừng ngốn RAM và ổ cứng, và cũng vì không thể End Task trực tiếp bằng Task Manager được nên chúng ta mới phải sử dụng đến Command Prompt.

Nhập vào cửa sổ Command Prompt dòng lệnh sc stop "SysMain" => rồi bấm Enter để tạm dừng dịch vụ Superfetch, nếu thấy kết quả trả về như hình bên dưới là OK rồi đấy.

Còn nếu bạn thấy thông báo OpenService FAILED : Access is denied thì nhớ chạy lại Command Prompt với quyền Admin đi nha.

cach-tat-superfetch-sysmain-tren-windows-10 (7)

Cuối cùng, sử dụng lệnh sc config "SysMain" start=disabled để tắt hẳn dịch vụ Superfetch trên Windows 10.

Ngoài ra, bạn còn có thể thay disabled trong start bằng các tùy chọn khác như là boot, system, auto, demand, delayed-auto nữa.

Chạy xong sẽ xuất hiện dòng chữ [SC] ChangeServiceConfig SUCCESS như bên dưới là bạn đã tắt thành công dịch vụ Superfetch trên Windows 10 chỉ bằng 1 dòng lệnh rồi đó. Giờ bạn cũng cần khởi động lại máy tính để các thay đổi này có hiệu lực.

cach-tat-superfetch-sysmain-tren-windows-10 (8)

II. Lời kết

Như vậy là mình đã hướng dẫn xong cho các bạn tắt dịch vụ SysMain trên Windows để khắc phục lỗi Full Disk trên ổ cứng HDD rồi ha.

Nói chung, các bạn cũng nên đọc tham khảo thêm thôi chứ thực sự 2 cách mình vừa nêu trên không nhanh và tiện bằng cách dùng Service Manager như thông thường được.

CTV: Nguyễn Thanh Tùng – Bài viết gốc tại blogchiasekienthuc.com

Có thể bạn quan tâm:

Xem thêm Việc làm IT hấp dẫn trên TopDev

Tìm hiểu về lệnh DIR [Directory] trong CMD [Command Prompt]

directory

Bài viết được sự cho phép của blogchiasekienthuc.com

Lệnh DIR là viết tắt của từ Directory. Đây là lệnh cho phép chúng ta xem và theo dõi các tệp, cũng như thư mục ở trong Folder mà bạn trỏ tới.

Vâng, và ở trong bài viết này chúng ta sẽ cùng tìm hiểu kỹ hơn về lệnh DIR trên hệ điều hành Windows nhé. Về toàn bộ các lệnh của DIR cũng như cách sử dụng lệnh DIR này.

  Cách sử dụng lệnh Xcopy trong CMD (Command Prompt)
  Cài đặt MySQL Community Server trên macOS

#1. Hướng dẫn cơ bản về lệnh Directory

Ví dụ khi mình chạy một lệnh DIR thì chúng ta có các mục như sau:

  • Màu đỏ: Hiển thị Ngày, tháng, năm của File hoặc Folder (tính cả việc tạo, copy hoặc move file hoặc folder vào thư mục này nha các bạn).
  • Màu cam: Thời gian File hoặc Folder xuất hiện trong thư mục.
  • Màu xanh lam: Đánh dấu cho ta biết đó là thư mục (Folder).
  • Màu tím: Dung lượng của tệp.
  • Màu xanh lá: Tên File hoặc Folder.
  • Màu vàng: Tên và mã số ổ cứng.

tim-hieu-ve-lenh-dir-directory-trong-cmd (1)

  • Màu trắng: Số lượng tệp và thư mục con trong Folder. Đồng thời liệt kê thêm dung lượng đang dùng và còn trống của ổ cứng chứa folder này.

tim-hieu-ve-lenh-dir-directory-trong-cmd (2)

Ví dụ cụ thể nhé: Bây giờ mình muốn xem tệp và thư mục trong Folder Server ở ổ D thì mình sẽ có 2 cách như sau:

Cách 1: Ví dụ ở đây mình muốn truy cập vào thư mục Server trong ổ D thì mình sẽ dùng lệnh như sau (sau mỗi lệnh bạn nhấn Enter nhé):

D:
cd Server
dir

tim-hieu-ve-lenh-dir-directory-trong-cmd (3)

Cách 2: Nhập lệnh dir đường-dẫn-của-thư-mục. Cụ thể ở đây là lệnh dir D:\Server

tim-hieu-ve-lenh-dir-directory-trong-cmd (4)

Vậy sẽ có bạn hỏi là: Hai cách trên sử dụng trong trường hợp nào? Thì đối với mình, cách đầu tiên sẽ sử dụng khi bạn làm nhiều việc với thư mục đó.

Ví dụ, sau khi dùng lệnh dir xong, bạn có thể sử dụng thêm các lệnh khác cho các tệp hoặc thư mục con trong đó.

Cách thứ hai tiện lợi hơn khi chỉ cần copy đường dẫn tới lệnh, tuy nhiên sẽ rất bất tiện nếu bạn muốn sử dụng thêm các lệnh khác cho tệp hoặc thư mục đó. Các bạn sử dụng linh động hai cách trên nha.

#2. Các lệnh nâng cao trong Directory

Ta có thể phân loại tệp hoặc thư mục theo thuộc tính. Có các thuộc tính sau:

  • Directories (d): Chỉ các thư mục con.
  • Read-only tệps (r): Chỉ các tệp hoặc thư mục chỉ đọc.
  • Hidden tệps (h): Chỉ các tệp hoặc thư mục bị ẩn.
  • System tệps (s): Chỉ các tệp hoặc thư mục hệ thống.
  • Not Directories (-d): Không liệt kê các thư mục con.
  • Not Read-only tệps (-r): Không liệt kê các tệp hoặc thư mục chỉ đọc.
  • Not Hidden tệps (-h): Không liệt kê các tệp hoặc thư mục bị ẩn.
  • Not System tệps (-s): Không liệt kê các tệp hoặc thư mục hệ thống.

2.1. Cách quản lý file trong Folder như sau, đây là công thức chung:

dir /a:“thuộc tính trong dấu ngoặc đơn” “Đường dẫn tệp (nếu chưa trỏ đến thư mục)”

_______________________

Ví dụ: Mình muốn lọc Folder Server của mình chỉ hiển thị các thư mục thì sẽ sử dụng lệnh sau đây:

dir /a:d “D:\Server” (Do mình đã trỏ Command Prompt tới thư mục Server nên không cần thêm đường dẫn D:\Server nữa).

=> Như các bạn đã thấy, CMD chỉ hiển thị các thư mục và bỏ qua tất cả các tệp trong thư mục rồi đó.

tim-hieu-ve-lenh-dir-directory-trong-cmd (5)

Lưu ý: Có thể kết hợp các thuộc tính với nhau. Ví dụ mình muốn lọc chỉ hiển thị các thư mục ẩn thì dùng lệnh sau:

dir /a:dh (d: hiển thị thư mục, h: hiển thị tệp và thư mục ẩn).

tim-hieu-ve-lenh-dir-directory-trong-cmd (6)

Như các bạn đã thấy, trong thư mục Server mình chỉ có thư mục con dungeon5 có thuộc tính ẩn nên dir chỉ hiển thị mỗi folder trên.

Không chỉ như vậy, lệnh dir còn cho phép ta thấy được chủ sở hữu của tệp hoặc thư mục bằng cách sử dụng lệnh:

dir /q

tim-hieu-ve-lenh-dir-directory-trong-cmd (7)

Như các bạn đã thấy ở hình bên trên, dir đã thêm một dòng cho mỗi tệp và thư mục là “DESKTOP-U7RQ5F1\~~~~~”.

Phần DESKTOP-U7RQ5F1 là tên máy tính, còn “~~~~~” là tên tài khoản tạo ra File và Folder này. (Tên hơi dị thông cảm cho mình nha :D).

2.2. Ta có thể sắp xếp các File hoặc thư mục theo các thứ tự sau bằng lệnh:

dir /o:”Tên-sắp-xếp”

Trong đó, tên sắp xếp bao gồm các loại như:

  • By Name (n): Theo tên (Bắt đầu tính từ chữ cái đầu là a-z).

tim-hieu-ve-lenh-dir-directory-trong-cmd (8)

  • By Size: (s): Theo kích cỡ file (Bắt đầu tính từ tệp có dung lượng nhỏ nhất).

tim-hieu-ve-lenh-dir-directory-trong-cmd (9)

  • By Extension (e): Theo phần mở rộng của tệp (Bắt đầu tính từ chữ cái đầu là a-z).

tim-hieu-ve-lenh-dir-directory-trong-cmd (10)

  • By Date/time (d): Theo thời gian (Bắt đầu tính từ tệp hoặc thư mục xuất hiện cũ nhất -> mới nhất).

tim-hieu-ve-lenh-dir-directory-trong-cmd (11)

  • Group Directories First (g): Liệt kê tất cả các thư mục trước, tệp sau.

tim-hieu-ve-lenh-dir-directory-trong-cmd (12)

Lưu ý: Bạn có thể thêm dấu (-) trước tên sắp xếp để đảo ngược lại sự sắp xếp của File hoặc Folder. Ví dụ mình muốn sắp xếp file lên trước, folder sau thì dùng lệnh sau:

dir /o:-g

tim-hieu-ve-lenh-dir-directory-trong-cmd (13)

Dir còn có thêm các lệnh như sau:

  • dir /d hoặc dir /w: Xem danh sách liệt kê theo chiều ngang.

tim-hieu-ve-lenh-dir-directory-trong-cmd (14)

  • dir /c: Cho phép ta hiển thị dấu phẩy sau mỗi hàng cho kích cỡ file (hàng nghìn, hàng trăm,…) và được bật mặc định.

tim-hieu-ve-lenh-dir-directory-trong-cmd (15)

  • dir /-c: Tắt hiển thị dấu phẩy cho kích cỡ file.

tim-hieu-ve-lenh-dir-directory-trong-cmd (16)

  • dir /b: Chỉ hiển thị tên file hoặc folder.

tim-hieu-ve-lenh-dir-directory-trong-cmd (17)

  • dir /p: Chỉ sử dụng cho file batch. Sau khi sử dụng xong lệnh sẽ cần bấm phím bất kì để tắt pop-up lệnh.

tim-hieu-ve-lenh-dir-directory-trong-cmd (18)

Okay, như vậy là mình đã hướng dẫn xong cho các bạn hầu như tất cả các lệnh DIR trên hệ điều hành Windows rồi nhé.

CTV: Hoàng Tuấn – Bài viết gốc tại blogchiasekienthuc.com

Có thể bạn quan tâm:

Xem thêm Việc làm IT hấp dẫn trên TopDev

Bazel 4.1.0: Bài 1 – Cài đặt bazel 4.1.0

bazel
Cài đặt bazel 4.1.0

Bài viết được sự cho phép của tác giả Lê Xuân Quỳnh

Bazel là gì?

Nói ngắn gọn:

  • Tool do Google viết, dùng để build các project iOS, android, C++… Trong bài viết này chúng tôi tập trung vào iOS.
  • Sử dụng với các project nhiều người làm, tránh conflict khi nhiều người cùng sửa file project xcode
  • Khi dùng bazel, mọi cài đặt trên Xcode đều vô nghĩa.
  • Mọi thứ cài đặt bằng bazel đều effect tới Xcode, y hệt như bạn cấu hình trên Xcode
  • Cấu hình bằng script, nên đòi hỏi dev phải kiên trì đọc tài liệu của nó.
  • Chọn version 4.1.0 vì nó hỗ trợ M1, và là phiên bản mới nhất tính đến thời điểm viết bài này(8/2021)
  Bộ cài đặt Laravel Installer đã hỗ trợ tích hợp Jetstream
  Cách cài đặt Android Studio phiên bản năm 2020

Hướng dẫn cài đặt

đầu tiên tải file sh của 4.1.0, bấm vào đây:

https://github.com/bazelbuild/bazel/releases/download/4.1.0/bazel-4.1.0-installer-darwin-x86_64.sh

Cho phép quyền thực thi. Bạn dùng terminal cd vào nơi chứa file vừa tải và gõ:

chmod +x bazel-4.1.0-installer-darwin-x86_64.sh

Sau đó gõ tiếp lệnh sau để cài đặt:

./bazel-4.1.0-installer-darwin-x86_64.sh

Cấu hình môi trường bằng lệnh:

export PATH="$PATH:$HOME/bin"

Kiểm tra version để confim là cài đặt thành công bằng lệnh:

bazel --version

Nếu nó ra chữ bazel 4.1.0 thì nghĩa là bạn đã cài đặt thành công.

Bạn có thể cài đặt phiên bản khác bằng cách kiểm tra các release của team bazel ở đây:

https://github.com/bazelbuild/bazel/releases

Lúc đó, phiên bản sẽ tương ứng với file name là bazel-<version>-installer-darwin-x86_64.sh, trong đó version là số hiệu phiên bản hiện có.

Cài đặt bằng Homebrew

Nếu thích Homebrew thì bạn cài như sau:

brew install bazel

Sau đó kiểm tra thành công chưa bằng cách gõ:

bazel --version

Tiếp theo nếu bạn muốn cập nhật lên phiên bản mới nhất của bazel thì gõ lệnh:

brew upgrade bazel

Nếu bạn đọc được tiếng Anh thì đây là phiên bản đầy đủ:

https://docs.bazel.build/versions/4.1.0/install-os-x.html

Bài viết gốc được đăng tải tại codetoanbug.com

Có thể bạn quan tâm:

Xem thêm Việc làm IT hấp dẫn trên TopDev

Hibernate Native SQL Queries

native sql queries
Hibernate Native SQL Queries

Bài viết được sự cho phép của tác giả Giang Phan

Trong Hibernate, HQL hoặc Criteria Query cho phép chúng ta thực hiện hầu hết mọi truy vấn SQL mong muốn. Tuy nhiên, đôi khi về câu lệnh SQL được tạo ra bởi Hibernate chậm hoặc cần viết câu lệnh phức tạp và thích tạo câu lệnh SQL (SQL gốc) của riêng mình hơn. Với Hibernate cho chúng ta sử dụng Native SQL để thao tác với cơ sở dữ liệu, bao gồm các stored procedures, và tất cả các thao tác create, update, delete và select.

Tương tự như HQL hay Creteria, để tạo đối tượng Native Query chúng ta sẽ sử dụng phương thức createNativeQuery() từ đối tượng Session:

org.hibernate.query.NativeQuery createNativeQuery(java.lang.String s); <R> org.hibernate.query.NativeQuery<R> createNativeQuery(java.lang.String s, java.lang.Class<R> aClass);

Scalar queries

Các truy vấn SQL cơ bản nhất là để có được một danh sách các giá trị scalars (column) từ một hoặc nhiều bảng.

Ví dụ lấy tất cả các column của bảng user.

NativeQuery query = session.createNativeQuery("SELECT * FROM user" ); List<Object[]> users = query.getResultList();

Ví dụ lấy fullname và email của 10 user từ vị trí thứ 5

NativeQuery query = session.createNativeQuery("SELECT username, password FROM user ORDER BY username" ); List<Object[]> users = query.setFirstResult(5).setMaxResults(10).getResultList(); users.forEach( user -> { System.out.println("username: " + user[0] + " | password: " + user[1]); });

Ví dụ lấy username và password của một user có id là 1

NativeQuery query = session.createNativeQuery("SELECT username, password FROM user where id = :id" ); Object[] user = (Object[]) query.setParameter("id", 1).uniqueResult(); System.out.println("username: " + user[0] + " | password: " + user[1]);
  "Làm PM, theo anh không cần biết về code, nhưng phải hiểu về SQL, database, những khái niệm cơ bản của code"
  Các thao tác cơ bản với Database SQL Server (tạo mới database, table,...)

Entity queries

Các truy vấn ở trên là về trả về các giá trị vô hướng từ ResultSet.

Ví dụ sử dụng JPA native query để có được các đối tượng Entity từ một truy vấn Native SQL

NativeQuery query = session.createNativeQuery("SELECT * FROM user", User.class ); List<User> users = query.getResultList();

Sau đây là cú pháp để có được các đối tượng Entity từ một truy vấn Native SQL thông qua addEntity().

NativeQuery query = session.createNativeQuery("SELECT * FROM user" ); List<User> users = query.addEntity(User.class).list();

Tìm việc làm lập trình SQL lương cao

DTOs (Data Transfer Objects)

Đôi khi chúng ta cần truy vấn một vài column và trả về trực tiếp cho đối tượng DTO, không cần phải thông qua Entity.

Ví dụ:

UserDTO.java

@Data public class UserDTO {     private String fullname;     private String username; }

Sử dụng ResultTransformer để trả về đượng tượng non-entity.

NativeQuery query = session.createNativeQuery("SELECT fullname, username FROM user" ); List<UserDTO> users = query.setResultTransformer( Transformers.aliasToBean( UserDTO.class ) ).list();

Nếu không muốn trả về DTO, có thể trả về một Map<String, Object> như sau:

NativeQuery query = session.createNativeQuery("SELECT fullname, username FROM user" ); List<Map<String,Object>> mapUsers = query.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE).list(); mapUsers.forEach( user -> { System.out.println(user.get("fullname")); });

Handling associations and collections

Ví dụ lấy thông tin user và user profile.

List<Object[]> tuples = session.createNativeQuery(         "SELECT * " +                 "FROM user u " +                 "INNER JOIN user_profile p ON u.id = p.user_id" )         .addEntity("user", User.class )         .addJoin( "p", "user.userProfile")         .list(); for(Object[] tuple : tuples) {     User user = (User) tuple[0];     UserProfile userProfile = (UserProfile) tuple[1];     System.out.println("fullname " + user.getFullname() + " | address " + userProfile.getAddress()); }

Mặc định khi sử dụng addJoin(), kết quả trả về sẽ bao gồm tất cả các entity được join trong 1 array. Để trả về một đối tượng entity hierarchy, chúng ta cần sử dụng ROOT_ENTITY hoặc DISTINCT_ROOT_ENTITY ResultTransformer.

Chi tiết về các truy vấn khác, các bạn tham khảo thêm link bên dưới.

Tài liệu tham khảo:

Bài viết gốc được đăng tải tại gpcoder.com

Có thể bạn quan tâm:

Xem thêm Việc làm IT hấp dẫn trên TopDev

Strategy pattern: vịt bảo, liên quan gì tới tao?

strategy pattern
Strategy pattern : vịt bảo, liên quan gì tới tao?

Bài viết được sự cho phép của tác giả Kiên Nguyễn

Một ngày đẹp trời, sếp giao cho Tồ ngồi code vài ba con vịt – chẳng liên quan gì tới Strategy Pattern. Vịt thì cũng không nhiều loại lắm (vịt nhựa, vịt trời và vịt nhà). Làm dev cái qq gì lại đi code vài ba con vịt. Rõ điên, tồ cay lắm.

Nhưng thôi, “ăn cơm chúa múa tối ngày”, không code có khi nó lại đuổi cmn mình mất. Tồ lọ mọ ngồi thiết kế class, kế thừa (inheritance) này nọ. Dự án kết thúc, Tồ lại về nhà, ăn ngon, ngủ yên.

3 tháng sau, dự án mantain, dự án thêm 30 loại vịt. Tồ mở code lên maintain, code thế này sao mở rộng được. Hướng thiết kế vừa khó sửa chữa, vừa mất thời gian. Tồ tìm hiểu ngay về STRATEGY PATTERN, cố gắng thiết kế lại. Thành công, tồ hiểu thêm về strategy, tiện viết luôn bài này chia sẻ cùng mọi người.

  Architectural Styles vs. Architectural Patterns vs. Design Patterns
  Building Microservices Application - Phần 2: Xử lý "Chain of Failures" dùng Circuit Breaker Pattern với Netflix Hystrix

1. Revisiting inheritance – một xíu về kế thừa.

Kế thừa (inheritance) là một bốn khái niệm quan trọng và cốt lõi của OOP (lập trình hướng đối tượng). Thông qua kế thừa, ta có thể tái sử dụng hoặc mở rộng hành vi (behavior), thuộc tính (properties) của lớp khác.

Khi kế thừa được sử dụng đúng đắn, code sẽ viết ít đi, các lớp (class) trở nên linh động (flexible). Việc một đối tượng có thể được kế thừa hay không chủ yếu tới từ IS-A (là cái gì).

Ví dụ: Mèo là động vật -> nó nên thuộc về lớp Animal. Mà giờ có khi lại thuộc cmn lớp Boss (vì nó như bố của đứa nuôi nó) =)).

Mặc dù kế thừa là khái niệm quan trọng, lạm dụng kế thừa lại không hề tốt. Nếu thiết kế các lớp kế thừa không tốt, code sẽ trở nên cực kì rối rắm. Các lớp kế thừa được thiết kế nhiều, nhưng các lớp con lại không thể sử dụng linh hoạt, đó là chưa nói tới các đoạn code phải lặp đi lặp lại nhiều lần.

2. Limit of inheritance – hạn chế của việc kế thừa.

Lấy ví dụ như sau: có 3 loại vịt (vịt trời, vịt nhà, vịt nhựa). Cả ba đều kế thừa lớp Vịt. Thiết kế lớp để kế thừa của ta ban đầu được thiết kế như sau:

strategy-pattern

Cả vịt nhưa, vịt trời và vịt nhà đều override lại method display() từ class cha. Tuy nhiên, chỉ có vịt trời và vịt nhà là thật sự biết kêu (quack). Chà, thiết kế còn tốt chán. Trông ra thì cũng chả có vấn đề gì to tát ở đây cả.

Tuy nhiên, một ngày đẹp trời, class cha Duck thêm vào method fly(), tất nhiên, trong họ nhà vịt thiếu gì con biết bay.

strategy-pattern

Đệch, vịt nhựa thì chắc chắn là không bay được, vì vậy phải override lại method này. Hơn nữa, còn phải chắc chắn rằng trong method override này không làm gì cả (do nothing). Sự thật là thế, con vịt nhựa mà bay được thì code sai tè le mất rồi. =))).

Không thể cứ class nào cùng overide method.

Nếu class cha có tới 15 method thì sao, chả nhẽ method nào cũng phải override lại?. Tới đây, hạn chế của kế thừa đã lộ rõ, các đoạn code kế thừa ở các lớp con lặp đi lặp lại. Đã không dùng lại phải thêm một đống code vào class. Thật sự tệ. Một thay đổi nhỏ ở lớp cha (super class) cũng kéo theo việc phải thay đổi code ở các lớp con kế thừa nó.

Hừm, để nghĩ xem. À, còn interface, sao không tách m* 2 cái fly và quack ra thành interface. Ngon.

3. Trying interface – thử dùng interface

Đm, học hành phỏng vấn đã lâu, nay đã đùng được interface, thật đáng công sức. Tách ra thế này.

strategy-pattern

Đầu tiên, 2 method fly() và quack() sẽ được tạo thành 2 interface riêng (flyable và quackable). Vịt trời và vịt nhà sẽ implement hai inteface này. Vịt nhựa thì do không bay cũng không kêu, nên nó không implements cái nào.

Chà, nghĩ chút, thiết kế này trông có vẻ ổn. Nếu lớp Duck sau này có thêm method fly(), thì chỉ cần tạo thêm interface Flyable nữa.

Lúc sử dụng thì con vịt nào cần cái nào thì nó implement cái đó.

Mà khoan. Trường hợp có 30 hay 40 lớp vịt thì như thế nào?

Đệch, cả 30, 40 cái class cùng implement quack và fly (hầu như mấy loài vịt khác con nào chả kêu, con nào chả bay). Lúc có thì, bất cứ thay đổi gì (cho dù là nhỏ) trong phương thức fly(), các class implement đều sửa. Maintenance code kiểu này thật sự là ác mộng (nightmare).

strategy-pattern-disadvan

Thiết kế kiểu này xem ra không ổn -> mấy thằng dev sau nó vào đọc code mà đi mainte chắc nó chửi chết. Thôi đành xuất chiêu cuối, sử đụng strategy pattern.

4. Apply the principle – chốt hạ dùng Strategy pattern

Không thể để hậu nhân chửi bới được. Thiết kế chuẩn chỉnh lại theo strategy pattern thôi.

Để xem, vẫn có hai cái interface được tách ra (fly behavior, quack behavior).

strategy-pattern

Tuy nhiên, cái hay của strategy pattern là không phải lũ vịt sẽ implement trực tiếp các interface này. Ta sẽ viết các subclass implement. Cụ thể là:

strategy-pattern

Các class implements sẽ được tách ra theo behavior. Hai class implement fly behavior là flyWithWings (bay được) và flyNoWay (không bay được).

// Fly behavior implement.
public class FlyWithWings implements FlyBehavior {
public void fly() {
System.out.println('Hura, tao có thể bay');
}
}
// Fly behavior implement.
public class FlyNoWay implements FlyBehavior {
public void fly() {
System.out.println('ĐM, tao đéo bay được');
}
}

Quack thì có 2 class Quack (kêu được), Mute (không kêu được).

// Quack behavior implement.
public class Quack implements QuackBehavior {
public void quack() {
System.out.println('Tao kêu được');
}
}
public class Mute implements QuackBehavior {
public void mute() {
System.out.println('Tao đéo kêu được');
}
}

Khúc quan trọng đây rồi. Khi đã có các class cụ thể implements từ interface. Công việc còn lại là viết abtract class Duck cho tất cả lũ vịt extends.

// Fly behavior implement.
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
// Con nào cũng hiển thị
abstract void display();
public Duck() {};
// Fly
public void performFly() {
flyBehavior.fly();
}
// Quack
public void performQuack() {
quackBehavior.quack();
}
}

Ngon lành cành đào, lúc khởi tạo class mới, ví dụ như vịt trời, chỉ cần new constructor theo behavior cho nó. Tất nhiên sẽ extends class Duck.

// Vit troi class.
public class VitTroi extends Duck {
// Constructor instance
public VitTroi() {
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}
}

Đối với vịt nhựa, do vịt nhựa không kêu cũng không bay, nên instance của nó sẽ là Mute và FlyNoWay.

// Vit nhua class.
public class VitNhua extends Duck {
// Constructor instance
public VitNhua() {
quackBehavior = new Mute();
flyBehavior = new FlyNoWay();
}
}

Cuối cùng, class Vịt chỉ đơn giản gọi các method được perform là quack và fly.

// Vit troi class.
public class Vit {
public static void main(String[] args) {
// Vit troi
Duck vitTroi = new VitTroi();
vitTroi.performQuack();
vitTroi.performFLy();

// Vit nhua
Duck vitNhua = new VitNhua();
vitNhua.performQuack();
vitNhua.performFly();
}
}

5. Kết luận

Strategy pattern rõ ràng là một thiết kế tốtTại sao lại thế?. Mặc dù vẫn sử dụng các interface. Tuy nhiên, với mô hình strategy, các interface sẽ được xác định rõ chức năng của nó (thông qua các behavior – class implements FlyNoWays, FlyWithWings, …). Trường hợp có sửa đổi hay thêm mới ta không cần sửa tới các interface, mỗi loài vịt đều có các class riêng đặc trưng khả năng của nó.

Trường hợp lũ vịt có thêm các method mới, đơn giản chỉ cần thêm các class behavior. Các class này độc lập, rất thuận tiện cho việc sửa đổi sau này.

Lúc maintain code, có thể dễ dàng bổ sung class implement các behaviors. Việc sửa đổi hay thêm mới class không hề làm ảnh hưởng tới các loài vịt khác.

Rõ ràng, stategy pattern đem tới một thiết kế không tồi tẹo nào. =))

Trên đây là hiểu biết cá nhân và ý kiến riêng của mình về strategy pattern. Rất mong nhận được phản hồi từ các bạn. Ngoài ra, các bạn có thể tham khảo thêm bài viết về JVM architecture.

6. Tham khảo

Bài viết gốc được đăng tải tại kieblog.vn

Có thể bạn quan tâm:

Xem thêm Việc làm IT hấp dẫn trên TopDev

Lỗi Could not create the Java Virtual Machine khi chạy Minecraft

minecraft
Lỗi Could not create the Java Virtual Machine khi chạy Minecraft

Bài viết được sự cho phép của blogchiasekienthuc.com

Có bao giờ bạn gặp một thông báo lỗi như thế này chưa? (lỗi này xảy ra khi mình chạy game Minecraft).

Error: Could not create the Java Virtual Machine.
Error: A fatalexception has occurred. Program will exit.

loi-could-not-create-the-java-virtual-machine (1)

Mình nghĩ là lỗi này chắc nhiều bạn cũng đã từng bị rồi. Chính vì thế mà hôm nay mình sẽ hướng dẫn cho các bạn các cách để sửa lỗi này một cách hiệu quả nhất nhé.

  10 lý do cho thấy tại sao bạn nên theo học ngôn ngữ lập trình Java
  10 tips để trở thành Java Developer xịn hơn

Xem thêm nhiều việc làm Java lương cao trên TopDev

#1. Tạo một System Variable cho Java

Đầu tiên bạn nhấn tổ hợp phím Windows + R để mở hộp thoại Run => sau đó nhập sysdm.cpl => và bấm OK.

loi-could-not-create-the-java-virtual-machine (2)

Tiếp theo, bạn vào tab Advanced => và bấm vào Environment Variables trong phần Startup and Recovery.

loi-could-not-create-the-java-virtual-machine (3)

Sau đó bạn tiếp tục bấm vào New ở phàn System Variables.

loi-could-not-create-the-java-virtual-machine (4)

Sau đó bạn thiết lập như sau:

  • Variable name bạn nhập JAVA_OPTIONS
  • Variable value bạn nhập là –Xmx512M để xác định số lượng RAM tối đa mà Minecraft có thể sử dụng, ở trong ví dụ này mình để là 512MB. Bạn có thể thay đổi thành –Xmx1024M hoặc –Xmx2048M.

=> Cuối cùng bạn bấm OK để thực hiện.

loi-could-not-create-the-java-virtual-machine (5)

#2. Chạy Java với quyền Admin

Để thực hiện điều này thì bạn nhấn tổ hợp phím Windows + S để mở Windows Search => sau đó nhập từ khóa tìm kiếm là Java.

Nếu như có sẵn shorcut Java ở ngoài màn hình Desktop thì nhấn chuột phải vào shortcut đó luôn.

Bấm chuột phải vào kết quả mà nó tìm thấy => sau đó nhấn vào Open file location để truy cập vào thư mục cài đặt Java.

=> Tiếp theo bạn bấm chuột phải vào file java.exe => và chọn Properties.

loi-could-not-create-the-java-virtual-machine (1)

Bạn chuyển sang tab Compatibility => sau đó bạn tick vào phần Run this program as an administrator. Cuối cùng bấm Apply => OK để kết thúc.

loi-could-not-create-the-java-virtual-machine (2)

#3. Cài đặt lại Java

Cài đặt lại Java đôi khi cũng là một cách để sửa lỗi này. Có thể Java của bạn đã bị lỗi khi cài đặt. Bạn cũng nên tải về bản Java Offline để tránh bị lỗi khi cài đặt nha.

#4. Lời kết

Ok, như vậy là mình đã hướng dẫn xong cho các bạn cách để sửa lỗi Could not create the Java Virtual Machine trên hệ điều hành Windows rồi nhé.

Dù là thành công hay thất bại thì các bạn cũng đừng quên để lại comment bên dưới để anh em trao đổi thêm nhé. Thank you !

CTV: Hoàng Tuấn – Bài viết gốc tại blogchiasekienthuc.com

Có thể bạn quan tâm:

Xem thêm Việc làm IT hấp dẫn trên TopDev

Todo List: Xóa dữ liệu từ database

xóa dữ liệu
Xóa dữ liệu từ database

Bài viết được sự cho phép của tác giả Kien Dang Chung

Video trong bài viết

Khi làm việc với database người ta thường nhắc đến CRUD là một cụm từ viết tắt của 4 chức năng cần và đủ để tương tác với các bản ghi là Create, Read, Update và Delete. Cho đến bài học hôm nay, bạn đã được tìm hiểu về 3 chức năng đầu và giờ là lúc chúng ta cùng tìm hiểu phần còn lại, chức năng xóa dữ liệu.

  "Làm PM, theo anh không cần biết về code, nhưng phải hiểu về SQL, database, những khái niệm cơ bản của code"
  Các thao tác cơ bản với Database SQL Server (tạo mới database, table,...)

Xem thêm nhiều việc làm Database hấp dẫn trên TopDev

Tại sao phải xóa dữ liệu

Những dữ liệu không cần thiết chúng ta cần phải xóa khỏi database hoặc ít ra thì cũng không hiển thị trên ứng dụng, làm như vậy khi hiển thị các danh sách bản ghi với người dùng sẽ ngắn hơn và người dùng có thể bao quát hoặc tìm kiếm dễ dàng hơn. Có hai loại xóa dữ liệu:

  • Xóa dữ liệu ra khỏi database, dữ liệu sẽ không có khả năng xem lại khi cần thiết. Cách xóa này chỉ áp dụng với dữ liệu thông thường không quá quan trọng.
  • Xóa dữ liệu tạm thời bằng cách đánh dấu bằng các cờ xóa dữ liệu, cách này thường áp dụng cho các dữ liệu quan trọng, ví dụ dữ liệu tài chính, bạn có thể xóa một hợp đồng nhưng vẫn xem được chi tiết hợp đồng này nếu cần.

Trong ứng dụng Todo List, chúng ta sẽ sử dụng cách thứ nhất, xóa hẳn các bản ghi công việc cần làm khỏi database. Cách hai sẽ được giới thiệu đến các bạn trong một khóa học khác về Laravel.

Xóa dữ liệu trong ứng dụng Todo List

Quay trở lại với Quy trình 3 bước, hẳn bạn còn nhớ ở các bài trước chứ? Đường dẫn xóa một bản ghi Todo (giả sử id=3) sẽ có dạng /todos/3/delete. Chúng ta cùng thực hiện nhé.

Bước 1: Đăng ký đường dẫn

Trong các bài viết, các bước này cố tình được lặp đi lặp lại để các kiến thức này có thể được nhớ lâu hơn. Mở file routes/web.php và đăng ký đường dẫn xóa bản ghi:

Route::get('todos/{todo}/delete', 'TodosController@destroy');

Bước 2: Xử lý nghiệp vụ trong TodosController

Trong đăng ký ở bước 1, để xử lý cho đường dẫn xóa bản ghi là phương thức destroy() của TodosController. Thực hiện thêm phương thức này vào file app\Http\Controllers\TodosController.php:

public function destroy($todoId)
{
    $todo = Todo::find($todoId);
    $todo->delete();
    return redirect('/todos');
}

Công việc đơn giản là tìm Todo từ ID có được từ đường dẫn, thực hiện xóa bản ghi này bằng phương thức delete().

Bước 3: Hành động hoàn thành

Sau khi đã xóa xong bảng ghi, chúng ta chuyển hướng người dùng về trang danh sách todos.

Như vậy, chức năng xóa dữ liệu đã hoàn thành, tuy nhiên chúng ta chưa có một nút hoặc một đường link nào đó để bấm vào mỗi khi cần xóa, chẳng lẽ gõ thẳng đường dẫn để xóa một Todo nào đó? Chúng ta sẽ thêm một nút Delete vào trang chi tiết của Todo (view show). Mở resources/views/todos/show.blade.php và thêm vào nút Delete:

@extends('layouts.app')

@section('title')
    Single Todo: {{ $todo->name }}
@endsection

@section('content')
    <h1 class="text-center my-5">
        {{ $todo->name }}
    </h1>

    <div class="row justify-content-center">
        <div class="col-md-6">
            <div class="card card-default">
                <div class="card-header">
                    Details
                </div>

                <div class="card-body">
                    {{ $todo->description }}
                </div>
            </div>
            <a href="/todos/{{ $todo->id }}/edit" class="btn btn-info my-2">Edit</a>
            <a href="/todos/{{ $todo->id }}/delete" class="btn btn-danger my-2">Delete</a>
        </div>
    </div>
@endsection

Chức năng xóa dữ liệu

Source code: Bài 14 – Xóa dữ liệu từ database

Bài viết gốc được đăng tải tại allaravel.com

Có thể bạn quan tâm:

Xem thêm Việc làm IT hấp dẫn trên TopDev

Browser renders website như thế nào?

Browser renders website
Browser renders website như thế nào?

Bài viết được sự cho phép của tác giả Kiên Nguyễn

Đã là lập trình viên, hẳn sẽ có đôi lần bạn nghe qua về DOM, nhưng liệu rằng bạn có biết cây DOM đóng vai trò gì khi trình duyệt hiển thị nội dung?. Ngoài DOM tree còn những loại tree nào được build khi trình duyệt render một website?. Ôi, vô vàn câu hỏi vì sao, nhưng túm váy lại, bài viết này sẽ trả lời cho câu hỏi browser renders website như thế nào?.

Nội dung trang web chúng ta hằng ngày vẫn thường xem được vẽ (paint) ra sao?. Tất cả những câu hỏi này sẽ có trong bài viết sau đây

1. DOM – Document object model

Khi trình duyệt đọc được resource, trước khi browser renders website, nó sẽ có được dữ liệu từ HTML. Cụ thể, các tag html, body, div, … Từng đối tượng sẽ được tạo ra như một Javascript objects – gọi là Node.

Ủa, vậy node là gì?. Node có phải là class cuối cùng của instance các HTML tag không?. Câu trả lời là có. Một node object cho tag div sẽ được tạo từ HTMLDivElement (kế thừa từ class Node).

À, tới đây ta có thể hiểu thêm một phần về cách browser renders website . Trình duyệt sẽ new một loạt các instance theo các thẻ được cung cấp ở HTML. HTMLDivElement, HTMLScriptElement, Node, …

Xem thêm các việc làm Web/Mobile lương cao trên TopDev

Sau khi browser đã khởi tạo xong các instance của node, nó sẽ tiến hành build
tree-like structure của những node đã được tạo. Nói tóm lại, toàn bộ nội dung HTML phía server cung cấp sẽ được xây dựng thành DOM Tree

“Using DOM API, developers can add or remove HTML elements, change its appearance or bind event listeners. Using DOM API, HTML elements can be created or cloned in memory and maniuplated without affecting the rendered DOM tree. This gives developers the ability to construct highly dynamic web page with rich user experience.” – How the browser renders a web page?

“Sử dụng DOM API, lập trình viên có thể thêm hoặc xóa các đối tượng HTML, thay đổi cách mà nó xuất hiện, hoặc gán các event listeners. Sử dụng DOM API, HTML elements có thể khởi tạo hoặc sao chép vào trong bộ nhớ, thay đổi nhưng không nhất thiết phải render lại cây DOM. Điều này đem tới cho các lập trình viên khả năng xây dựng các website có trải nghiệm người dùng tốt”.

2. CSSOM- CSS object model

Từ lúc thiết kế website, tất nhiên ai cũng muốn website của mình đẹp nhất có thể. Bằng cách nào? -> dùng css. Vậy mỗi element trên HTML đều sẽ gắn liền với một CSS selector nhất định. Ví dụ như thẻ h1 có font-size, color. Những thứ này sẽ được xây dựng lên thành CSSOM.

Theo thứ tự, sau khi xây dựng cây DOM, browser renders website sẽ đọc toàn bộ nội dung CSS từ tất cả các nơi (external, embedded, inline, user-agent). Từ những nội dung này, browser dựng lên CSSOM (với cấu trúc tương tự như DOM tree).

Lấy ví dụ, với nội dung CSS được mô tả như sau:

html {
padding: 0;
margin: 0;
}body {
font-size: 14px;
}.container {
width: 300px;
height: 200px;
color: black;
}.container > h1 {
color: gray;
}.container > p {
font-size: 12px;
display: none;
}

Sau khi đọc được toàn bộ nội dung, browser sẽ dựng lên cây CSSOM như sau:

CSSOM tree được browser render sau khi đọc được nội dung CSS

3. Render Tree

Khi đã có cả DOM tree và CSSOM tree, đây là một trong những bước mà browser renders website. Bước này browser sẽ combined cả hai tree lại với nhau. Nội dung của 2 cây này sẽ cho ta thứ tự các nội dung trên website.

Một khi đã xây dựng xong reder tree, browser sẽ thực hiện vẽ từ element – đây là thứ mà chúng ta nhìn thấy. Nếu một node có CSSOM là display:none, hiển nhiên object này sẽ có kích thước 0px 0 0px -> không xuất hiện.

Các bước mà browser tạo ra Render-tree (nội dung website mà chúng ta thấy trên trình duyệt)

Lưu ý rằng, trong một số trường hợp, khi xây dựng cây combined giữa DOM và CSSOM, một số tag sẽ bị bỏ qua (vị dụ như tag meta, script, …). Một số node trên cây sẽ được ẩn đi (nếu CSS được viết với display:none).

  Cách để npm packages chạy trong browser
  Câu hỏi phỏng vấn mẹo về React: Component hay element được render trong browser?

4. Rendering sequence

Đọc tới đây, khi đã có cái nhìn khách quan về DOM, CSSOM và Render Tree, ta sẽ tiếp tục tìm hiểu về các bước (step) mà browser renders website.

4.1 Layout

Sau khi đã có nội dung mô tả chính xác các phần tử trên cây, trình duyệt sẽ thực hiện tính toán không gian cần thiết cho từng phần tử, vị trí của chúng ở trên màn hình.

4.2 Paint

Paint là quá trình trình duyệt vẽ từng pixel lên màn hình. Việc vẽ cũng được thực hiện trên nhiều lớp nếu như cần thiết (match color, layer hay phối màu)

4.3 Composite

Ở bước cuối cùng, browser kết hợp các layer lại với nhau, cho ta một cài nhìn hoàn chỉnh về website.

Bài viết gốc được đăng tải tại kieblog.vn

Có thể bạn quan tâm:

Xem thêm Việc làm IT hấp dẫn trên TopDev

Bộ guide để viết code sạch dành riêng cho Vue

viết code sạch
Bộ guide để viết code sạch dành riêng cho Vue

Bài viết được sự cho phép của tác giả Lưu Bình An

Trước tiên cần thống nhất quan điểm thế này, ko phải guide nào cũng phù hợp cho mọi team, mọi dự án, nến không nhất thiết phải áp dụng một cách cứng nhắc trong mọi trường hợp

  3 phút làm quen với Vue.js
  API Authentication trong Laravel-Vue SPA sử dụng Jwt-auth

Xem thêm các chương trình tuyển dụng VueJS hấp dẫn trên TopDev

Cấp độ: Siêu cần thiết, giúp tránh được nhiều lỗi

Tên component nên là 2 chữ

Trừ App component và các component có sẵn trong Vue như <transition/><component />

Để tránh trùng các thẻ html, có thể sau này, HTML sẽ bổ sung thêm nhiều thẻ mới, thẻ HTML sẽ là 1 chữ

❌ Không ngon
Vue.component('todo', {
	//...
})

export default {
	name: 'Todo'
}

✅ Chuẩn cơm mẹ nấu
Vue.component('todo-item', {
	// ...
})

export default {
	name: 'TodoItem',
}

data phải là một function

data phải là function trả về object. Nếu là một object, tất cả các instance component sẽ cùng trỏ tới một dữ liệu data.

❌ Không ngon
export default{
	data: {
		foo: 'bar'
	}
}  

✅ Chuẩn cơm mẹ nấu
export default {
	data() {
		foo: 'bar'
	}
}

Riêng với thằng root component, nó chỉ có một, nên có thể là object

Khai báo prop càng chi tiết càng tốt

Ít nhất là có type, nếu được càng chi tiết chừng nào tốt chừng đó

❌ Không ngon
props: {
	status: String
}

✅ Chuẩn cơm mẹ nấu
props: {
	status: {
		type: String,
		required: true,
		validator: function (value) {
			return [
				'syncing',
				'synced',
				'version-conflict',
				'error'
			].indexOf(value) !== -1
		}
	}
}

Luôn cung cấp key cho v-for

Có luôn cái video này rồi, bạn xem ở đây

❌ Không ngon
<ul>
	<li v-for="todo in todos">
		{{ todo.text }}
	</li>
</ul> 

✅ Chuẩn cơm mẹ nấu
<ul>
	<li
		v-for="todo in todos"
		:key="todo.id"
	>
		{{ todo.text }}
	</li>
</ul>

Không bao giờ dùng v-for chung với v-if

Vì v-for được ưu tiên cao hơn v-if, nghĩa là nếu viết

❌ Không ngon

<ul>
	<li
		v-for="user in users"
		v-if="user.isActive"
		:key="user.id"
	>
		{{ user.name }}
	</li>
</ul>

Nó sẽ chạy như thế này

this.users.map(function (user) {
	if (user.isActive) {
		return user.name
	}
})

Nghĩa là cứ mỗi lần re-render chúng ta đều loop qua tất cả các phần tử trong mảng, trong khi giá trị isActive này không đổi, nó ko tối ưu

Nên filter trước các user có giá trị isActive = true trước

✅ Chuẩn cơm mẹ nấu
computed: {
	activeUsers: function () {
		return this.users.filter(function (user) {
			return user.isActive
		})
	}
}

CSS scoped trên từng component

Những style nào dùng global có thể đưa vào App component, còn trong từng component, luôn dùng kiểu scoped

Tuy nhiên nếu bạn đang làm 1 thư viện component, để dùng tới dùng lui, hay đưa lên npm cho người khác xài, nên dùng cùng css class bình thường, không có scoped, người khác sử dụng có thể dễ override lại nếu cần

❌ Không ngon
<template>
	<button class="btn btn-close">X</button>
</template>

<style>
	.btn-close {
		background-color: red;
	}
</style>

✅ Chuẩn cơm mẹ nấu
<template>
	<button class="button button-close">X</button>
</template>

<!-- Using the `scoped` attribute -->
<style scoped>
.button {
	border: none;
	border-radius: 2px;
} 

.button-close {
	background-color: red;
}
</style>

Dùng BEM khi viết thư viện component

<template>
	<button class="c-Button c-Button--close">X</button>
</template>

<!-- Using the BEM convention -->
<style>
.c-Button {
	border: none;
	border-radius: 2px;
}

.c-Button--close {
	background-color: red;
}
</style>

Private

Sử dụng module scope cho các function muốn private. Nếu không thể, luôn dùng tiền tố $_ trước các property private trong plugin, mixin,… và thêm luôn tên plugin để tránh bị conflict với các plugin khác ( $_yourPluginName_)

❌ Không ngon
var myMixin = {
	// ...
	methods: {
		update: function () {
			// ...
		},
		_update: function () {
			// ...
		},
		$update: function () {
			// ...
		}
		$_update: function () {
			// ...
		}
	}
}

✅ Chuẩn cơm mẹ nấu
var myMixin = {
	methods: {
		$_myMixin_update: function () { }
	}
}

Cấp độ: Cực kỳ khuyến khích

Một component là một file

👎 Chuẩn cơm mẹ nấu
Vue.component('TodoList', {
	// ...
})

Vue.component('TodoItem', {
	// ...
})

✅ Chuẩn cơm mẹ nấu
components/
|- TodoList.vue
|- TodoItem.vue

File name luôn là một trong 2 dạng PascalCase hoặc kebab-case

❌ Không ngon
components/
|- mycomponent.vue
components/
|- myComponent.vue  

✅ Chuẩn cơm mẹ nấu
components/
|- MyComponent.vue
components/
|- my-component.vue

Base component

Những component được dùng với mục đích đồng nhất styling, layout được gọi là base component, nó có thể chỉ chứa

  • HTML
  • UI component từ các thư viện khác
  • Các base component khác

Và không được chứa state của Vuex store

Tên nên được đặt theo kiểu BaseButtonBaseTable. Lợi ích của việc này

  • Khi mở trong editor, nó được liệt kê gần nhau, dễ tìm, dễ phân loại
  • Tên component sẽ luôn có 2 chữ như đã nói ở trên
  • Các component này được sử dụng rất thường xuyên, nên có thể dùng prefix để đăng ký một lần một cho tất cả component
var requireComponent = require.context("./src", true, /^Base[A-Z]/)
requireComponent.keys().forEach(function (fileName) {
var baseComponentConfig = requireComponent(fileName)
baseComponentConfig = baseComponentConfig.default || baseComponentConfig
var baseComponentName = baseComponentConfig.name || (
	fileName
	.replace(/^.+\//, '')
	.replace(/\.\w+$/, '')
)
Vue.component(baseComponentName, baseComponentConfig)
})
❌ Không ngon
components/
|- MyButton.vue
|- VueTable.vue
|- Icon.vue 

✅ Chuẩn cơm mẹ nấu
components/
|- BaseButton.vue
|- BaseTable.vue
|- BaseIcon.vue  

components/
|- AppButton.vue
|- AppTable.vue
|- AppIcon.vue

components/
|- VButton.vue
|- VTable.vue
|- VIcon.vue

Component chỉ có một instance duy nhất

Với những component chỉ xuất hiện một lần trên 1 trang, không bao giờ nhận prop. Chúng ta có một cách đặt tên riêng, thêm tiền tố The

❌ Không ngon
components/
|- Heading.vue
|- MySidebar.vue

✅ Chuẩn cơm mẹ nấu
components/
|- TheHeading.vue
|- TheSidebar.vue

Component luôn gắn chặt vào một component cha

Nếu một component con, luôn đi cùng một component cha nhất định, thêm tên component cha làm tiền tố

Một số người sẽ dùng cách đưa các component này vào trong thư mục con

components/
|- TodoList/
|- Item/
|- index.vue
|- Button.vue
|- index.vue

hoặc 

components/
|- TodoList/
|- Item/
|- Button.vue
|- Item.vue
|- TodoList.vue

Cách này ko được khuyến khích, vì nó có quá nhiều trùng tên, việc chuyển qua lại giữa các file này trong editor rất khó chịu, vì ko biết đang mở file nào, nhiều thư mục như vậy, làm việc duyệt qua các component này cũng mệt

❌ Không ngon
components/
|- TodoList.vue
|- TodoItem.vue
|- TodoButton.vue

components/
|- SearchSidebar.vue
|- NavigationForSearchSidebar.vue  

✅ Chuẩn cơm mẹ nấu
components/
|- TodoList.vue
|- TodoListItem.vue
|- TodoListItemButton.vue 

components/
|- SearchSidebar.vue
|- SearchSidebarNavigation.vue

Sử dụng kebab-case trong DOM template

Tên file của component thì nên viết dạng PascalCase, còn trong template nên dùng kebab-case

❌ Không ngon
<!-- In single-file components and string templates -->
<mycomponent/>

<!-- In single-file components and string templates -->
<myComponent/>  

<!-- In DOM templates -->
<MyComponent></MyComponent>

✅ Chuẩn cơm mẹ nấu
components/
<!-- In single-file components and string templates -->
<MyComponent/>

<!-- In DOM templates -->
<my-component></my-component>
 
OR 

<!-- Everywhere -->
<my-component></my-component>
❌ Không ngon
Vue.component('myComponent', {
	// ...
})

import myComponent from './MyComponent.vue'
export default {
	name: 'myComponent',
	// ...
}

export default {
	name: 'my-component',
	// ...
}

✅ Chuẩn cơm mẹ nấu
components/
Vue.component('MyComponent', {
	// ...
}) 

Vue.component('my-component', {
	// ...
})

import MyComponent from './MyComponent.vue'
export default {
	name: 'MyComponent',
	// ...
}

Đặt tên prop

Dùng camelCase lúc khai báo, kebab-case trong template

❌ Không ngon
props: {
	'greeting-text': String
}

<WelcomeMessage greetingText="hi"/>

✅ Chuẩn cơm mẹ nấu
props: {
	greetingText: String
}
	
<WelcomeMessage greeting-text="hi"/>

📜 Style Guide

Bài viết gốc được đăng tải tại vuilaptrinh.com

Có thể bạn quan tâm:

Xem thêm Việc làm IT hấp dẫn trên TopDev

Kết nối JMS Client với ActiveMQ

kết nối jms client
Kết nối JMS Client với ActiveMQ

Bài viết được sự cho phép của tác giả Giang Phan

Trong bài này, chúng ta sẽ cùng tìm hiểu cách tạo JMS Client (Producer và Consumer) để kết nối đến ActiveMQ server, cũng như sự khác biệt trong việc phân phối tin nhắn giữa Queue va Topic.

Tạo ActiveMQ project

Tạo maven project và mở file pom.xml, khai báo dependency như sau:

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">     <modelVersion>4.0.0</modelVersion>     <groupId>com.gpcoder</groupId>     <artifactId>activemq-example</artifactId>     <version>1.0-SNAPSHOT</version>     <properties>         <java.version>1.8</java.version>         <maven.compiler.target>1.8</maven.compiler.target>         <maven.compiler.source>1.8</maven.compiler.source>     </properties>     <dependencies>         <!-- https://mvnrepository.com/artifact/org.apache.activemq/activemq-client -->         <dependency>             <groupId>org.apache.activemq</groupId>             <artifactId>activemq-client</artifactId>             <version>5.15.12</version>         </dependency>         <!-- https://mvnrepository.com/artifact/org.apache.qpid/qpid-jms-client -->         <dependency>             <groupId>org.apache.qpid</groupId>             <artifactId>qpid-jms-client</artifactId>             <version>0.50.0</version>         </dependency>     </dependencies>     <build>         <plugins>             <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-compiler-plugin -->             <plugin>                 <groupId>org.apache.maven.plugins</groupId>                 <artifactId>maven-compiler-plugin</artifactId>                 <version>3.8.1</version>                 <configuration>                     <source>1.8</source>                     <target>1.8</target>                 </configuration>             </plugin>             <!-- include all the dependencies into the jar for easier to execute the application -->             <!-- https://mvnrepository.com/artifact/org.fusesource.mvnplugins/maven-uberize-plugin -->             <plugin>                 <groupId>org.fusesource.mvnplugins</groupId>                 <artifactId>maven-uberize-plugin</artifactId>                 <version>1.45</version>                 <executions>                     <execution>                         <phase>package</phase>                         <goals>                             <goal>uberize</goal>                         </goals>                     </execution>                 </executions>             </plugin>         </plugins>     </build> </project>

Chúng ta chỉ cần sử dụng 1 trong 2 thư viện JMS Client: activemq-client hoặc qpid-jms-client. Trong bài này, tôi muốn giới thiệu với các bạn cả 2, nên cần include cả 2 thư viện này.

  • activemq-client : nếu muốn kết nối thông qua giao thức TCP.
  • qpid-jms-client : nếu muốn kết nối thông qua giao thức AMQP.
  Cài đặt ActiveMQ
  Bộ cài đặt Laravel Installer đã hỗ trợ tích hợp Jetstream

Tạo Producer và Consumer

Kết nối JMS Client với ActiveMQ

Tạo Producer

Các bước thực hiện:

  • Tạo ConnectionFactory : xác định remote URI đến ActiveMQ server. ActiveMQ hỗ trợ nhiều loại giao thức khác nhau, trong ví dụ này, tôi sẽ sử dụng giới các bạn cách tạo ConnectionFactory sử dụng giao thức AMQP và TCP.
    • remoteURI sử dụng AMQP: amqp://localhost:5672
    • remoteURI sử dụng TCP: tcp://localhost:61616
  • Tạo Connection từ ConnectionFactory, cần cung cấp username và password.
  • Tạo Session: mỗi Connection có thể có nhiều Session quản lý những thứ như Transaction và lưu giữ Message riêng biệt.
  • Tạo Destination: là một địa chỉ của một Topic hoặc Queue cụ thể được lưu trữ bởi JMS broker.
  • Tạo Producer: producer dành riêng cho một Destination, nó chỉ có thể gửi tin nhắn đến một Topic hoặc Queue cụ thể.
  • Tạo Message: Mỗi khi muốn gửi tin nhắn đến Topic hoặc Queue, cần phải tạo một đối tượng Message. Có một vài loại khác nhau: text, binary, object, IO stream. Trong ví dụ này, tôi chỉ gửi một tin nhắn dạng text, đây là một trong những dạng đơn giản nhất.
  • Gửi Message: thực hiện gửi message đến JMS Broker.
  • Đóng kết nối: sau khi sử dụng xong cần đóng kết nối. Điều này nói với JMS broker rằng nó có thể giải phóng các tài nguyên được sử dụng cho kết nối đó.

Ví dụ:

package com.gpcoder; import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.qpid.jms.JmsConnectionFactory; import javax.jms.*; import java.io.BufferedReader; import java.io.InputStreamReader; class Producer {     public static void main(String[] args) throws Exception {         System.out.println("Create a ConnectionFactory");         // ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");         ConnectionFactory connectionFactory = new JmsConnectionFactory("amqp://localhost:5672");         System.out.println("Create a Connection");         Connection connection = connectionFactory.createConnection("admin", "admin");         connection.start();         System.out.println("Create a Session");         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);         System.out.println("Create a Topic/ Queue based on the given parameter");         Destination destination = null;         if (args.length > 0 && args[0].equalsIgnoreCase("QUEUE")) {             destination = session.createQueue("gpcoder-jms-queue");         } else if (args.length > 0 && args[0].equalsIgnoreCase("TOPIC")) {             destination = session.createTopic("gpcoder-jms-topic");         } else {             System.out.println("Error: You must specify Queue or Topic");             connection.close();             System.exit(1);         }         System.out.println("Create a Producer to send messages to one Topic or Queue.");         MessageProducer producer = session.createProducer(destination);         System.out.println("Start sending messages ... ");         try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in));) {             String response;             do {                 System.out.print("Enter message: ");                 response = br.readLine().trim();                 TextMessage msg = session.createTextMessage(response);                 producer.send(msg);             } while (!response.equalsIgnoreCase("close"));         }         System.out.println("Shutdown JMS connection and free resources");         connection.close();         System.exit(1);     } }

Tạo Consumer

Các bước thực hiện tương tự như tạo Producer, khác biệt duy nhất là thay vì tạo Producer để gửi tin nhắn, ta tạo Consumer để nhận tin nhắn.

package com.gpcoder; import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.qpid.jms.JmsConnectionFactory; import javax.jms.Connection; import javax.jms.Session; import javax.jms.Destination; import javax.jms.MessageConsumer; import javax.jms.TextMessage; import javax.jms.*; class Consumer {     public static void main(String[] args) throws JMSException {         System.out.println("Create a ConnectionFactory");         // ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");         ConnectionFactory connectionFactory = new JmsConnectionFactory("amqp://localhost:5672");         System.out.println("Create a Connection");         Connection connection = connectionFactory.createConnection("admin", "admin");         connection.start();         System.out.println("Create a Session");         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);         System.out.println("Create a Topic/ Queue based on the given parameter");         Destination destination = null;         if (args.length > 0 && args[0].equalsIgnoreCase("QUEUE")) {             destination = session.createQueue("gpcoder-jms-queue");         } else if (args.length > 0 && args[0].equalsIgnoreCase("TOPIC")) {             destination = session.createTopic("gpcoder-jms-topic");         } else {             System.out.println("Error: You must specify Queue or Topic");             connection.close();             System.exit(1);         }         System.out.println("Create a Consumer to receive messages from one Topic or Queue.");         MessageConsumer consumer = session.createConsumer(destination);         System.out.println("Start receiving messages ... ");         String body;         do {             Message msg = consumer.receive();             body = ((TextMessage) msg).getText();             System.out.println("Received = " + body);         } while (!body.equalsIgnoreCase("close"));         System.out.println("Shutdown JMS connection and free resources");         connection.close();         System.exit(1);     } }

Chạy ứng dụng

Trước hết, chúng ta cần package ứng dụng trên thành gói jar, chạy lệnh: mvn clean install

Sau khi chạy lệnh trên, trong thư mục target của project, chúng ta có gói: activemq-example-1.0-SNAPSHOT.jar

Start ActiveMQ Server: xem lại bài viết trước “Cài đặt ActiveMQ“.

Trường hợp JMS Queue

Kết nối JMS Client với ActiveMQ

Mô hình P2P (Point to Point) đảm bảo chỉ có một người gửi và một người nhận tin nhắn.

Nhiều Consumer và một Producer

Mở 2 console và chạy lệnh sau để start 2 JMS Consumer:

java -cp target/activemq-example-1.0-SNAPSHOT.jar com.gpcoder.Consumer Queue

Mở thêm 1 console khác để start JMS Producer:

java -cp target/activemq-example-1.0-SNAPSHOT.jar com.gpcoder.Producer Queue

Chúng ta có kết quả như sau:

Kết nối JMS Client với ActiveMQ

Nhập một vài giá trị ở cửa sổ Producer, chúng ta có kết quả sau:

Kết nối JMS Client với ActiveMQ

Như bạn thấy, một tin nhắn chỉ được gửi cho một client tại một thời điểm và client thay phiên nhau nhận tin nhắn.

Hãy đóng các console trên bằng cách enter “exit” trên console của Producer hoặc Ctrl + C.

Producer gửi message trước khi Consumer start

Tiếp tục hãy test thử một trường hợp khác: Start Producer và gửi một vài message:

Kết nối JMS Client với ActiveMQ

Sau đó start Consumer và check kết quả.

Kết nối JMS Client với ActiveMQ

Bạn có thể thấy rằng, người nhận không cần active tại thời điểm Producer gửi message. JMS Broker sẽ deliver message ngay khi Consumer active.

Trường hợp JMS Topic

Kết nối JMS Client với ActiveMQ

Mô hình Pub/ Sub (Publisher/ Subscriber) cho phép 1 người gửi và nhiều người nhận.

Mở 2 console và chạy lệnh sau để start 2 JMS Consumer:

java -cp target/activemq-example-1.0-SNAPSHOT.jar com.gpcoder.Consumer Topic

Mở thêm 1 console khác để start JMS Producer:

java -cp target/activemq-example-1.0-SNAPSHOT.jar com.gpcoder.Producer Topic

Chúng ta có kết quả như sau:

Kết nối JMS Client với ActiveMQ

Nhập một vài giá trị ở cửa sổ Producer, chúng ta có kết quả sau:

Kết nối JMS Client với ActiveMQ

Như bạn thấy, mỗi khi Producer gửi một tin nhắn thì tất cả consumer đều nhận được ngay tức thì. Khi bạn nhập “close” thì chương trình cũng kết thúc và đóng connection.

Hãy đóng các console trên bằng cách enter “exit” trên console của Producer hoặc Ctrl + C.

Tiếp tục hãy test thử một trường hợp khác: start Producer và gửi một vài message. Sau đó start Consumer. Bạn sẽ thấy rằng, Consumer không nhận được message của Producer đã gửi từ trước. Mỗi Consumer sẽ chỉ nhận được message từ Topic sau khi đã subscription.

Mở admin page của ActiveMQ để kiểm tra lại Topic và Queue đã tạo: http://localhost:8161/admin/

Trang Queues:

Kết nối JMS Client với ActiveMQ

Trang Topics:

Kết nối JMS Client với ActiveMQ

Bài viết gốc được đăng tải tại gpcoder.com

Có thể bạn quan tâm:

Xem thêm Việc làm IT hấp dẫn trên TopDev

Sự khác nhau giữa file application với bootstrap trong Spring

spring boot
Sự khác nhau giữa file application với bootstrap trong Spring

Bài viết được sự cho phép của tác giả Trần Hữu Cương

Sự khác nhau giữa file application với bootstrap trong Spring

Phân biệt sự khác nhau giữa 2 file cấu hình là application.properties với bootstrap.properties hoặc application.yml với bootstrap.yml.
Khi nào thì sử dụng file cấu hình application, khi nào thì sử dụng file cấu hình bootstrap?

1. File application.properties / application.yml dùng để làm gì?

File application.properties hoặc application.yml được dùng để cấu hình application context (ngữ cảnh ứng dụng)

Khi ứng dụng Spring Boot được khởi động, nó sẽ tạo một application context mà không cần phải chỉ định 1 cách rõ ràng (tự động cấu hình). Đó là nguyên nhân vì sao khi sử dụng spring boot bạn phải cấu hình rất ít.

  Bảo mật ứng dụng Java web bởi Spring Security
  Cách sử dụng properties trong tập tin cấu hình của Spring

Xem thêm nhiều việc làm Spring lương cao trên TopDev

Ngoài việc sử dụng file application.properties hoặc application.yml thì spring cũng cho phép ghi đè lại các cấu hình bằng nhiều cách như sử dụng code, các biến môi trường…

Chúng ta có thể nhóm các thuộc tính cấu hình mà có thể ghi đè trong application context như sau:

  • Core properties (logging properties, thread properties)
  • Integration properties (RabbitMQ properties, ActiveMQ properties)
  • Web properties (HTTP properties, MVC properties)
  • Security properties (LDAP properties, OAuth2 properties)

* Lưu ý: nếu các cấu hình của application context được ghi đè ở nhiều nơi thì cấu hình trong file application.properties hoặc application.yml có ưu tiên thấp hơn

2. File bootstrap.properties / bootstrap.yml dùng để làm gì?

File bootstrap.properties hoặc bootstrap.yml chỉ cần khi sử dụng Spring Cloud.

File bootstrap.properties hoặc bootstrap.yml được dùng để cấu hình bootstrap context. Bootstrap context chính là response của việc load các cấu hình từ một nguồn bên ngoài.

File bootstrap.properties hoặc bootstrap.yml thường gồm 2 thuộc tính:

  • Uri của config server (server chứa các cấu hình): spring.cloud.config.uri
  • Tên của ứng dụng: spring.application.name

Khi ứng dụng Spring Cloud được khởi động, nó sẽ tạo một bootstrap context. Dựa vào các thông tin cấu hình trong file bootstrap.properties hoặc bootstrap.yml, ứng dụng sẽ tạo một http request tới config server với name của ứng dụng để lấy về các thông tin cấu hình tương ứng.

File bootstrap sẽ được ứng dụng nạp vào trước file application.

3. Kết luận

File application.properties hoặc application.yml là nơi chứa cấu hình mặc định của ứng dụng. Còn file bootstrap.properties hoặc bootstrap.yml chỉ dùng cho các ựng dụng spring cloud.

Okay, Done!

References:

https://cloud.spring.io/spring-cloud-commons/multi/multi__spring_cloud_context_application_context_services.html

https://stackoverflow.com/questions/32997352/what-is-the-difference-between-putting-a-property-on-application-yml-or-bootstra

Bài viết gốc được đăng tải tại stackjava.com

Có thể bạn quan tâm:

Xem thêm Việc làm IT hấp dẫn trên TopDev

Biết gì về prototype trong Javascript?

prototype trong javascript
Biết gì về prototype trong Javascript?

Bài viết được sự cho phép của tác giả Kiên Nguyễn

1. OOP trong Javascript

Javascript là một ngôn ngữ dựa trên nguyên mẫu (prototype-based language), nó có nghĩa rằng thuộc tính và phương thức của object có thể được chia sẻ thông qua các đối tượng tổng quát (generalized objects) có khả năng mở rộng.

Trong số các ngôn ngữ hướng đối tượng phổ biến như Java, Python, PHP, Javascript khá là đặc biệt.  JS không hề có class, vậy các tính chất của OOP trên javascript được thể hiện như thế nào?.

Trong bài viết này, ta sẽ tìm hiểu cách thức làm việc của prototype (được hiểu như là kế thừa (inheritance) ở javascript).

  Nếu vỗ ngực xưng tên là một javascript developer sành sỏi, mà không giải thích được prototype inheritance thì thật là kỳ
  Protocol-oriented programming: Trái tim của Swift!

Xem thêm các việc làm JavaScript lương cao trên TopDev

2. Prototype là gì?

(Đối với một số bạn chưa có khái niệm sơ qua về prototype có thể đọc ở bài viết này).

Prototype là cơ chế mà các object trong javascript kế thừa các tính năng từ một object khác.

Prototype

Mỗi một object trong javascript đều có một thuộc tính nội bộ (internal property) gọi là [[Prototype]].

Chúng ta có thể chứng minh điều này bằng cách tạo ra một object mới.

let a = {};

Đây là cách đơn giản nhất để khởi tạo một object, hoặc một cách khác là khởi tạo object với constructor.

let x = new Object().

Dấu ngoặc kép nói lên rằng thuộc tính này không thể truy cập trực tiếp ở code của chúng ta. Để thực hiện việc truy cập, ta sử dụng phương thức getPrototypeOf()

Object.getPrototypeOf(x);

Output ở đây là:

{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, …}

3. Thêm thuộc tính prototype cho các đối tượng

Chúng ta sẽ cùng tìm hiểu sâu hơn với ví dụ sau đây:

function Human(firstName, lastName) {
this.firstName = firstName,
this.lastName = lastName,
this.fullName = function() {
return this.firstName + " " + this.lastName;
}
}

Hãy khởi tạo 2 object person1 và persion2, sử dụng human constructor như sau:

var person1 = new Human("Kien", "Nguyen");
var person2 = new Human("Khai", "Nguyen");

Đầu tiên, khi hàm Human được khởi tạo, javascript sẽ thêm thuộc tính prototype vào hàm. Nói cho dễ hiểu là thằng human sẽ gửi cho constructor 1 cái yêu cầu, nó nói là constructor mày hãy cho tao cái thể hiện đi, constructor hì hục làm việc và trả lại cho nó một cái thể hiện (instance).

javascript-prototype-constructor

Khi ta khởi tạo thêm object human1 bằng hàm constructor:

javascript-prototype-property

Lúc đối tượng này khởi tạo cũng là lúc javascript enginesthêm thuộc tính proto (cũng được gọi là dunder proto) vào đối tượng. Chính dunter proto này sẽ trỏ tới prototype object của hàm constructor.

4. Javascript engines tìm kiếm prototype property như thế nào?

Ta cùng xem xét ví dụ sau đây:

// Tạo một hàm constructor function rỗng 
function Person() {}
// Thêm thuộc tính name, age cho prototype property của hàm Person constructor 
Person.prototype.name = "Kien";
Person.prototype.age = 24;
Person.prototype.sayName = function() {
console.log(this.name);
}
// Khởi tạo object sử dụng hàm khởi tạo của Person 
var person1 = new Person();
// Truy cập tới thuộc tính name sử dụng đối tượng person 
console.log(person1.name) 
// Output Kien

Khi chúng ta cố gắng truy cập thuộc tính của một đối tượng (ở đây là person1.name), việc đầu tiên javascript engines làm là sẽ cố gắng tìm thuộc tính chúng ta cần trên đối tượng, nếu thuộc tính ** tồn tại** trên đối tượng, như thế thì quá đơn giản, chúng ta chỉ việc xuất ra kết quả.

javascript-engines

Nếu không, lúc này nó sẽ kiểm tra thuộc tính ở đối tượng nguyên mẫu (prototype object) hoặc đối tượng mà nó kế thừa. Trường hợp tệ nhất, đến cuối cùng vẫn không tìm được thuộc tính -> kết quả trả về sẽ là undefined.

Đối với ví dụ trên, khi person1.name được gọi, javascript engines sẽ kiểm tra property này có tồn tại trên đối tượng person hay không?. Không may thay, y thuộc tính name không tồn tại trên đối tượng person. Tiếp tục tìm kiếm trên dunder proto hoặc trên prototype của đối tượng person. Rất may thuộc tính name tồn tại trên prototype của đối tượng person. Kết quả là Kien

javascript-prototype-output

Qua hai ví dụ nhỏ này, mong các bạn có một chút hình dùng về cách thức hoạt động của prototype trong javascript.

Sau prototype sẽ là gì?. Sau prototype thì nên tìm hiểu tiếp về closure.

Again, thanks for reading, love u so much!

Bài viết gốc được đăng tải tại kieblog.vn

Có thể bạn quan tâm:

Xem thêm việc làm IT hấp dẫn trên TopDev

Sử dụng React-Query để fetch data

react query
Sử dụng React-Query để fetch data

Bài viết được sự cho phép của tác giả Lưu Bình An

React-query sẽ giúp chúng ta giải quyết các vấn đề sau

  • Một global context để lưu trữ dữ liệu lấy về từ server
  • Thiết đặt Caching đơn giản
  3 bước tối ưu hiệu năng React App bằng các API mới của React
  3 tools giúp bạn tăng hiệu năng của React App một cách bất ngờ

Xem thêm chương trình tuyển dụng React hấp dẫn trên TopDev

Nếu thích bạn cũng có thể tham khảo thêm swr cũng khá cool

Chúng ta sẽ có các Server side APIs sau

// api/product.js

// 1. Fetch tất cả products
const useFetchProducts = () => {}

// 2. Fetch một product cụ thể
const useFetchProduct = (id) => {}

// 3. Thêm một product
const useAddProduct = (product) => {}

// 4. Cập nhập một product
const useEditProduct = (product) => {}

// 5. Xóa một product
const useDeleteProduct = (id) => {}

Thực hiện fetch với useQuery

import { useQuery } from 'react-query'

const useFetchProducts = () => {
	return useQuery(
		// định danh
		'products',		() => {
			fetch('/api/products')
		}
	)
}

Sử dụng trong component

import { useFetchProducts } from "../api/products"

const Products = () => {
	const {
		data: products,
		isLoading
	} = useFetchProducts();

	return (
		<div>
			{
				isLoading && <div>Loading...</div>
			}
			{
				products && (
					products.map((product) => {
						<div key={product.id}>
							{product.name}
						</div>
					})
				)
			}
		</div>
	)
}

Việc fetch dữ liệu sẽ còn thêm các tính năng như search, phân trang, filter. Có react-query mọi thứ sẽ vô cùng đơn giản

import { useState } from "react"
import { useFetchProducts } from "../api/products"

const Products = () => {
	// trang hiện tại
	const [page, setPage] = useState(1)
	// số item trên trang
	const [limit, setLimit] = useState(10)
	// từ khóa
	const [name, setName] = useState('')		
	const {
		data: products,
		isLoading
	} = useFetchProducts({
		page,		limit,		name	});

	return (
		<div>
			{
				isLoading && <div>Loading...</div>
			}
			{
				products && (
					products.map((product) => {
						<div key={product.id}>
							{product.name}
						</div>
					})
				)
			}
		</div>
	)
}

Chúng ta cần cập nhập lại useFetchProducts

import { useQuery } from 'react-query'

const useFetchProducts = ({ page, limit, name }) => {
	return useQuery(
		['products', { page, limit, name }],		() => {
			fetch(`/api/products?page=${page}&limit=${limit}&search=${name}`)		}
	)
}

Thực hiện cache

Ví dụ chúng ta muốn đặt cache 10s, chúng ta sẽ sử dụng thiết đặt staleTime

import { useQuery } from 'react-query'

const useFetchProducts = ({ page, limit, name }) => {
	return useQuery(
		['products', { page, limit, name }],
		() => {
			fetch(`/api/products?page=${page}&limit=${limit}&search=${name}`)
		},
		{
			staleTime: 10000		}
	)
}

Cực kỳ đơn giản đúng không!

Tưởng tượng chúng ta có danh sách product hiển thị trên màn hình, click vào một product chúng ta hiển thị pop-up với các thông tin của product

Để fetch một product, chúng ta cũng đồng thời áp dụng cache

const useFetchProduct = (id) => {
	return useQuery(
		['product', id],
		() => {
			fetch(`/api/products/${id}`)
		},
		{
			staleTime: 10000
		}
	)
}

Đến phần thú vị nè, nếu các thông tin của từng product hoàn toán giống với thông tin trả về từ danh sách product?, chúng ta có thể áp dụng cache cho từng product trong lúc fetch danh sách product

import { useQuery, useQueryClient } from 'react-query'

const useFetchProducts = ({ page, limit, name }) => {
	const queryClient = useQueryClient();
	return useQuery(
		['products', { page, limit, name }],
		() => {
			fetch(`/api/products?page=${page}&limit=${limit}&search=${name}`)
		},
		{			
			staleTime: 10000,
			onSuccess: (products) => {				products.forEach(product => {
					queryClient.setQueryData(						['product', product.id],
						product
					);
				})
			}
		}
	)
}

Bằng cách dùng useQueryClient().setQuery, chúng ta force cache cho từng product.id, để khi useFetchProduct chạy nó sẽ có sẵn giá trị cache này và không cần thực hiện gọi API

Thể hiện chút tình yêu với dự án react-query nhé các bạn, star ngay không nói nhiều

Bài viết gốc được đăng tải tại vuilaptrinh.com

Có thể bạn quan tâm:

Xem thêm Việc làm IT hấp dẫn trên TopDev