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.
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.
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.
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 đượ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.
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ụ:
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:
Để đá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.
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ó.
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”
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.
Hotkey của Selenium IDE là Ctrl+Alt+S. Màn hình chính của Selenium IDE như sau:
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ợ
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…
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.
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.
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.
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.
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.
+ 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:
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.
+ 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.
+ 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:
1 – Automatic (Delayed Start) – Tự động chạy nhưng chỉ khi Windows đã khởi động xong
2 – 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.
3 – 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.
+ 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 😀
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.
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.
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.
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.
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.
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.
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
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
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 đó.
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).
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
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).
By Size: (s): Theo kích cỡ file (Bắt đầu tính từ tệp có dung lượng nhỏ nhất).
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).
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).
Group Directories First (g): Liệt kê tất cả các thư mục trước, tệp sau.
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
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.
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.
dir /-c: Tắt hiển thị dấu phẩy cho kích cỡ file.
dir /b: Chỉ hiển thị tên file hoặc folder.
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.
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é.
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:
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]);
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.
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.
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:
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.
Đệ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.
Đầ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).
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).
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à:
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ốt. Tạ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.
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.
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é.
Đầ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.
Tiếp theo, bạn vào tab Advanced => và bấm vào Environment Variables trong phần Startup and Recovery.
Sau đó bạn tiếp tục bấm vào New ở phàn System Variables.
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.
#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.
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.
#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 !
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.
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:
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:
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:
Đã 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, …
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).
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 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.
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
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á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
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>
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:
<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="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.0http://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.
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ụ:
packagecom.gpcoder;importorg.apache.activemq.ActiveMQConnectionFactory;importorg.apache.qpid.jms.JmsConnectionFactory;importjavax.jms.*;importjava.io.BufferedReader;importjava.io.InputStreamReader;classProducer {publicstaticvoidmain(String[] args) throwsException {System.out.println("Create a ConnectionFactory");// ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");ConnectionFactory connectionFactory = newJmsConnectionFactory("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");} elseif(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 = newBufferedReader(newInputStreamReader(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.
packagecom.gpcoder;importorg.apache.activemq.ActiveMQConnectionFactory;importorg.apache.qpid.jms.JmsConnectionFactory;importjavax.jms.Connection;importjavax.jms.Session;importjavax.jms.Destination;importjavax.jms.MessageConsumer;importjavax.jms.TextMessage;importjavax.jms.*;classConsumer {publicstaticvoidmain(String[] args) throwsJMSException {System.out.println("Create a ConnectionFactory");// ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");ConnectionFactory connectionFactory = newJmsConnectionFactory("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");} elseif(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
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:
Nhập một vài giá trị ở cửa sổ Producer, chúng ta có kết quả sau:
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/
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.
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:
* 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.
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).
(Đố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.
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()
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).
Khi ta khởi tạo thêm object human1 bằng hàm constructor:
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ả.
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
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.
Đế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'constuseFetchProducts=({ page, limit, name })=>{const queryClient =useQueryClient();returnuseQuery(['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
Đi cùng với sự phát triển thần tốc của công nghệ và trí tuệ nhân tạo, việc bảo mật thông tin trước các tội phạm công nghệ cao luôn là vấn đề nhức nhối hiện nay. Không khó để bắt gặp các nguồn tin về việc dữ liệu đánh cắp, kể cả là với những công ty có quy mô và thâm niên hoạt động lâu năm. Đó là lý do nhân lực trong ngành an ninh mạng đang ngày càng được săn đón và có nhu cầu tuyển dụng rất cao. Vậy ngành an ninh mạng hiện nay đang phát triển ra sao, cần học gì để làm việc trong ngành này và mức lương hiện của ngành như thế nào? Cùng TopDev tìm hiểu thêm với bài viết dưới đây.
Ngành An ninh mạng và những điều cần biết
1. Ngành an ninh mạng là gì?
Ngành an ninh mạng hay còn gọi là Cybersecurity được biết đến là công việc hoạt động nhằm phát hiện, ngăn chặn và ứng phó với các cuộc tấn công đến cổng thông tin mạng và máy tính nhằm mục đích trộm cắp các thông tin mang tính bảo mật. Để làm được việc này, các chuyên gia trong lĩnh vực an ninh mạng sẽ chịu trách nhiệm chính để tạo ra “hàng rào bảo vệ” để ngăn chặn việc tấn công ở các bên trong và bên ngoài hệ thống.
An ninh mạng được đánh giá là ngành nghề hấp dẫn hiện nay trong lĩnh vực công nghệ thông tin. Theo chia sẻ của anh Trần Minh Quảng với TopDev TV, vì ngành Cybersecurity là ngành mới nên khi làm việc bạn sẽ có cơ hội nghiên cứu chuyên sâu và phát triển kỹ năng chuyên môn cho bản thân rất tốt.
Bên cạnh đó, cơ hội việc làm đầy hấp dẫn cùng là động lực để bạn theo đuổi ngành an ninh mạng. Tại Việt Nam, Cybersecurity được đánh giá là một lĩnh vực đang phát triển mạnh và có đội ngũ nhân lực là những chuyên gia hàng đầu, nhờ đó, bạn có cơ hội tiếp xúc và cọ sát với những người giỏi nhiều hơn.
2. Ngành an ninh mạng cần học gì để làm tốt công việc?
2.1. Ngành an ninh mạng thi đầu vào khối nào?
Ngành an ninh mạng hiện nay được tuyển sinh với các khối thi gồm:
Khối A: Toán – Lí – Hóa
Khối A1: Toán – Lí – Anh
Khối D: Toán – Văn – Anh
Khối D90: Toán – Anh – KHTN
Điểm chuẩn của ngành an toàn thông tin nói riêng và công nghệ thông tin nói chung hiện nay đang nằm ở mức khá cao. Trong vòng 2 năm trở lại đây, ngành an toàn thông tin của các trường top đầu điểm chuẩn đều trên 20 điểm. Do những cơ hội việc làm và mức lương hấp dẫn mà nhu cầu nộp hồ sơ vào các ngành này đều tăng cao qua mỗi năm.
Trọng tâm kiến thức và đào tạo chuyên môn trong các trường tập trung vào vấn đề bảo vệ dữ liệu cũng như cách phản ứng với các trường hợp tấn công mạng. Một số kiến thức nền tảng sinh viên có thể học như:
Quản trị mạng
Quản trị thông tin
Quản trị hệ thống
Mạng lưới thông tin
Phân tích dữ liệu
Mật mã học đại cương
Phòng thủ không gian mạng
Hệ thống công nghệ thông tin
Nguyên tắc thiết kế bảo mật
…
Tuy nhiên, phương hướng đào tạo có thể khác nhau giữa các trường. Một số trường tập trung chủ yếu vào lập trình, trong khi các trường khác có thể chuyên sâu vào nghiên cứu pháp y kỹ thuật số (digital forensics) hoặc chính sách an ninh mạng.
Chương trình giảng dạy là yếu tố rất quan trọng khi lựa chọn một chương trình đào tạo an ninh mạng. Giáo án thường bao gồm cả lý thuyết và thực hành, như lập trình máy tính và các kỹ năng thực tế, điều này rất hữu ích cho sự nghiệp sau này của học viên trong lĩnh vực công nghệ thông tin.
Làm việc từ xa, Internet of Things (IoT), và sự chuyển dịch ngày càng nhiều khía cạnh của cuộc sống vào không gian kỹ thuật số (cũng như siêu dữ liệu) đã làm gia tăng sự phức tạp của các cuộc tấn công mạng. Điều này tạo ra những thách thức lớn đối với sự an toàn thông tin. Các chuyên gia an ninh mạng hiện đang sử dụng trí tuệ nhân tạo (AI) để dự đoán và ngăn chặn các cuộc tấn công như hack và DDOS. Đồng thời, họ cũng áp dụng các phương pháp tiếp cận tâm lý để đối phó với các kỹ thuật xã hội sử dụng công nghệ thấp hơn. Sự kết hợp của các kỹ năng này làm cho các chuyên gia an ninh mạng trở thành những ứng viên hấp dẫn và phù hợp với lực lượng lao động trong tương lai.
Ngành An ninh mạng đang mở ra nhiều cơ hội nghề nghiệp hấp dẫn và phát triển bền vững. Các tổ chức hiện đang tìm kiếm những chuyên gia có kỹ năng và kiến thức sâu rộng về bảo mật mạng, phòng chống tấn công mạng, phân tích rủi ro và quản lý an ninh thông tin.
Theo thống kê từ Cục An toàn thông tin (Bộ Thông tin và Truyền thông), hiện có khoảng 50.000 người làm việc trong lĩnh vực an toàn thông tin, trong khi nhu cầu nhân lực dự kiến sẽ cần đến khoảng 700.000 người. Điều này cho thấy tiềm năng nghề nghiệp rộng lớn và triển vọng phát triển lâu dài cho những ai theo đuổi ngành An ninh mạng.
4. Mức lương của ngành An ninh mạng
Theo số liệu trong Báo cáo thị trường IT Việt Nam 2023 do TopDev thực hiện, ngành an ninh mạng (Cybersecurity Specialist) hiện đang có mức lương khá cao trong thị trường các việc làm liên quan đến công nghệ thông tin. Mức lương có thể lên đến 3.566 USD với các ứng viên cao cấp. Trong khi đó mức lương của các ứng viên ở cấp độ Basic là 2.072 USD.
Một điều tất yếu đi đôi với mức lương nổi bật hơn hẳn so với mặt bằng chung của thị trường đó là yêu cầu về chất lượng nhân sự đối với ngành an ninh và bảo mật thông tin cũng cao hơn hẳn. Các chuyên viên nhân sự đến từ những công ty hàng đầu luôn gặp rất nhiều khó khăn trong việc tuyển được các ứng viên có năng lực cho những vị trí này.
5. Một số trường chuyên đào tạo ngành An ninh mạng
Việt Nam đang ngày càng chú trọng đến việc đào tạo nhân lực cho lĩnh vực an ninh mạng. Dưới đây là một số trường đại học với chương trình đào tạo chất lượng về an ninh mạng:
Học viện Kỹ thuật Mật mã
Đây là một trường chuyên về đào tạo an toàn thông tin và kỹ thuật mật mã, có kinh nghiệm gần 20 năm về đào tạo ngành An toàn thông tin. Khi theo học tại trường, sinh viên sẽ được đào tạo chuyên nghiệp về các kỹ năng trong lĩnh vực an toàn thông tin, bao gồm việc phân tích và giải mã các thông tin mã hóa, phát hiện và ngăn chặn các cuộc tấn công mạng, thiết kế và triển khai các hệ thống an toàn thông tin,…
Điểm chuẩn ngành An toàn thông tin năm 2023 tại cơ sở Hà Nội là 25.60 và cơ sở TP. Hồ Chí Minh là 25.00.
Đại học Bách Khoa Hà Nội
Ngành An toàn không gian số (Chương trình tiên tiến) là ngành học được thiết kế bởi các giáo sư hàng đầu trong nước và quốc tế. Chương trình được dạy 100% bằng tiếng Anh, với hệ thống các bài thí nghiệm và thực hành theo tiêu chuẩn quốc tế. Sinh viên năm cuối sẽ được hướng dẫn bởi các chuyên gia là cựu sinh viên của trường CNTT&TT đang làm việc tại các công ty tập đoàn lớn như IBM, Bkav, Thales,…
Điểm trúng tuyển của ngành vào năm 2023 là 28.05 điểm với 2 tổ hợp môn xét tuyển là A00 và A01.
Trường Đại học Công nghệ Thông tin (Đại học Quốc gia TP.HCM)
Ngành An toàn thông tin tại trường Đại học Công nghệ Thông tin được xây dựng theo định hướng chuyên sâu, theo mô hình đào tạo phương Tây, thực hành nhiều giúp sinh viên có kỹ năng tốt và kiến thức chuyên môn cao sau khi tốt nghiệp. Khi học tại trường, sinh viên sẽ được trang bị đầy đủ kiến thức và kỹ năng tương đương với một số chứng chỉ quốc tế như CCNP Security, RHCSS, CCNA,…
Điểm chuẩn xét tuyển của ngành An toàn thông tin năm 2023 là 26.3 điểm với 4 tổ hợp môn A00, A01, D01, D07. Trường áp dụng 3 hình thức tuyển sinh là Tuyển thẳng và ưu tiên xét tuyển, Xét tuyển dựa điểm thi, Xét tuyển dựa trên các chứng chỉ quốc tế uy tín.
Tổng kết
Ngành An ninh mạng sẽ còn tiếp tục phát triển hơn nữa trong tương lai nhờ vai trò đặc biệt quan trọng và cần thiết để bảo mật dữ liệu, thông tin. Hi vọng bài viết này sẽ giúp bạn giải quyết được phần nào thắc mắc liên quan đến ngành An ninh và bảo mật thông tin mạng. Đón xem nhiều bài viết hấp dẫn khác tại TopDev.
Cách đơn giản nhất để kiểm tra điều này, bạn mở file .htaccess lên. Thêm bất kì đoạn code nào vào đầu file. VD: <test>. Sau đó khởi động lại Apache. Theo dõi trình duyệt nếu nhận được lỗi như sau thì .htaccess của bạn đã hoạt động bình thường:
Nếu bạn không thấy ‘Interal Server Error’, Apache của bạn đã bỏ qua tệp .htaccess và bạn cần khắc phục điều đó. Nói chung, Apache bỏ qua tệp .htaccess vì cấu hình mặc định đang là AllowOverride none . Kiểm tra cấu hình máy chủ ảo của bạn và thêm / sửa đổi thành AllowOverride All.
Tìm và fix file: /etc/apache2/apache2.conf
Ví dụ:
<Directory /var/www/site/example.com/>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
Kiểm tra mod_rewrite có hoạt động không?
Các bạn thực hiện theo hướng dẫn ở link sau đây để bật mod_rewrite nhé.
Hầu hết các ngân hàng truyền thống đều sẽ thu các khoản phí phát sinh như phí chuyển khoản, phí rút tiền mặt bằng thẻ tại ATM hoặc tại quầy, các phí thường niên như là phí quản lý tài khoản, phí quản lý thẻ, phí báo biến động số dư SMS, phí ngân hàng điện tử, …
Thậm chí, một số ngân hàng còn yêu cầu bạn duy trì số dư tối thiểu trong tài khoản (gọi là tiền duy trì tài khoản) và tất nhiên là bạn không thể rút số tiền này được.
Nếu xét từng loại phí thì có thể bạn sẽ thấy nó không đáng là bao, nhưng nếu tính tất cả trong một năm và cộng dồn lại thì chúng ta cũng tiết kiệm được một số tiền kha khá đấy.
Ưu điểm vượt trội của Tnex (bên trái) so với nhiều ngân hàng truyền thống (bên phải)
#2. Tạo tài khoản và thẻ nhanh chóng, không cần ra phòng giao dịch
Đối với ngân hàng truyền thống, khi đăng kí tài khoản hoặc phát hành thẻ thì bạn cần phải đích thân ra phòng giao dịch để hoàn thành các thủ tục cần thiết.
Còn đối với TNEX thì bạn chỉ cần bỏ ra vài phút đăng kí trên smartphone là đã có ngay tài khoản và thẻ chỉ với vài thao tác đơn giản, an toàn và cực kỳ bảo mật rồi.
TNEX làm được như vậy là nhờ vào việc ứng dụng công nghệ eKYC, một công nghệ bảo mật tuyệt đối. Công nghệ này cho phép nhận dạng và định danh khách hàng hoàn toàn trực tuyến.
KYC (là viết tắt của từ Know Your Customer) – đây là một giải pháp định danh ngân hàng trực tuyến, giúp ngân hàng có thể xác định và xác minh danh tính của khách hàng một cách chính xác. KYC sẽ trở thành tiêu chuẩn trong ngành tài chính, ngân hàng..
Quy trình KYC sẽ là xác minh thẻ ID, nhận dạng và xác minh khuôn mặt, xác minh giấy tờ (như hóa đơn tiền điện, nước nhà bạn, hoặc là thu nhập cá nhân của bạn..) và xác minh sinh trắc học.
Với eKYC thì khác hàng có thể xác thực và định danh 100% online, bạn không cần ra các chi nhánh ngân hàng để làm gì thêm.
Tài khoản ngân hàng là nơi chứa tiền, là nơi chứa “mồ hôi và nước mắt” của bạn nên luôn luôn được TNEX đảm bảo an toàn tuyệt đối bằng các phương thức bảo mật đạt chuẩn Quốc tế. Bạn sẽ nhận được thông báo qua số điện thoại và thư điện tử khi:
Số dư trong tài khoản của bạn có sự biến động (tăng lên hoặc giảm đi).
Có sự thay đổi thông tin tài khoản như mật khẩu hoặc số điện thoại.
Tài khoản của bạn được đăng nhập từ một thiết bị.
Thẻ được phát hành bởi Napas, uy tín và mức độ bảo mật của đơn vị này thì không cần phải bàn đến. Trong trường hợp không may, thẻ bị thất lạc thì bạn cũng có thể chủ động khóa thẻ ngay trên ứng dụng Tnex.
IV. Chỉ một thao tác được 2 sản phẩm
#1. Tài khoản
Ngay khi quá trình phê duyệt hoàn thành bạn sẽ nhận được 2 loại tài khoản, đó là: Tài khoản thanh toán và tài khoản thanh toán Energy:
Tài khoản thanh toán được sử dụng để chuyển và nhận tiền, liên kết với thẻ ghi nợ nội địa để thực hiện các giao dịch bằng thẻ tại ATM.
Tài khoản thanh toánEnergy được sử dụng để thực hiện các giao dịch thanh toán hàng hóa qua QR Code, thanh toán hóa đơn, nạp tiền điện thoại … trên ứng dụng TNEX.
Các bạn nên chú ý:
Tiền trong tài khoản thanh toán là tiền thật 100%, được bảo chứng bởi Ngân hàng TMCP Hàng Hải Việt Nam (MSB).
Tiền trong tài khoản Energy là tiền ảo, được sử dụng riêng trong hệ sinh thái của TNEX – vì vậy bạn không thể chuyển tiền hoặc rút tiền ra được nhé.
Và một điều nữa, bạn có thể chuyển tiền từ tài khoản thanh toán sang tài khoản Energy, nhưng bạn không thể làm điều ngược lại.
#2. Thẻ Tnex vật lý
Thẻ TNEX là thẻ ghi nợ nội địa được phát hành dựa trên tài khoản thanh toán.
Với thẻ ghi nợ nội địa này thì bạn có thể sử dụng để thanh toán trực tuyến, sử dụng thanh toán với phần mềm POS (phần mềm quản lý bán hàng), chuyển tiền, rút tiền mặt tại ATM.
Sự ưu việt của thẻ TNEX
Tích hợp công nghệ Contactless cho phép bạn thực hiện thanh toán cực nhanh và đơn giản nhưng vẫn đảm bảo tính bảo mật.
Không cần mất thời gian đi đến các cây ATM với ứng dụng TNEX là đã có thể tạo và đổi mã PIN một cách dễ dàng.
Sau khi đang kí phát hành thẻ (ngay trong ứng dụng) thẻ sẽ được ship đến “tận giường” của bạn hoàn toàn miễn phí. Mã PIN lần đầu sẽ được ngân hàng gửi tới bạn qua tin nhắn SMS theo số điện thoại bạn đã đăng ký.
V. Các bước đăng kí tài khoản TNEX
#1. Cần chuẩn bị những gì?
Smartphone chạy các phiên bản gần đây của hệ điều hành Android hoặc iOS. Bản iOS/ Android cũ quá sẽ không cài đặt được ứng dụng TNEX vì lý do bảo mật.
Giấy tờ tùy thân của bạn, ví dụ như: Chứng minh nhân dân, hoặc thẻ căn cước công dân….
#2. Các thực hiện đăng ký tài khoản TNEX
+ Bước 1: Trước tiên bạn cần phải cài đặt ứng dụng TNEX – Ngân hàng số thế hệ mới (đừng nhằm lẫm với TNEX Merchant).
TNEX Merchant cũng là của Tnex, nhưng là dành cho những người kinh doanh online, chủ nhà hàng…. chúng ta là người dùng phổ thông thì dùng TNEX ngân hàng số thôi nhé các bạn !
Bạn có thể truy cập thông qua link bên dưới để không bị cài nhầm nhé:
Link dành cho Android (Samsung, OPPO, Xiaomi…..): Tải về !
+ Bước 2: Nhập số điện thoại, mật khẩu truy cập và thư điện tử của bạn vào:
Số điện thoại phải là số chính chủ nhé các bạn.
Mật khẩu truy cập hợp lệ là mật khẩu có độ dài ít nhất 6 ký tự (bao gồm chữ thường, số, chữ hoa, và ký tự đặc biệt).
+ Bước 3: Chụp mặt trước và mặt sau của chứng minh nhân dân hoặc căn cước công dân… Hay là bất cứ giấy tờ gì mà bạn dùng để xác minh.
+ Bước 4: Chụp ảnh khuôn mặt và thực hiện các thao tác theo đúng hướng dẫn trên ứng dụng (xoay trái, mỉm cười, nhắm mắt, xoay trái).
+ Bước 5: Kiểm tra, bổ sung thông tin đăng ký và xác nhận đồng ý với các điều kiện điều khoản dịch vụ của ngân hàng.
+ Bước 6: Nhập mã OTP được gửi tới số điện thoại mà bạn đã khai báo ở Bước 2 để xác thực.
Đến đây thì quá trình đăng kí đã hoàn thành và tất các thông tin đăng ký của bạn đã được hệ thống của TNEX ghi nhận. Thông thường bạn sẽ có tài khoản ngay sau khi đăng ký.
Nếu không may (rất hiếm khi xảy ra), bạn sẽ rơi vào một trong hai trường hợp bên dưới thì thời gian kiểm duyệt thông tin tài khoản của bạn kéo tối đa là 2 ngày làm việc kể từ thời điểm bạn đăng ký.
Ảnh chứng minh nhân dân hoặc căn cước công dân của bạn chụp bị mờ.
Bạn đã thay đổi thông tin sau khi TNEX trích xuất thông tin từ Chứng minh nhân dân hoặc Căn cước công dân.
VI. Hạn mức giao dịch của tài khoản thanh toán
Hạn mức theo tháng: Tổng giá trị giao dịch qua tài khoản thanh toán mở trực tuyến bằng ứng dụng TNEX là 100 triệu đồng/ tháng/ khách hàng
Hạn mức theo ngày và theo từng giao dịch: Bạn có thể tham khảo hình bên dưới nhé.
VII. Một số câu hỏi thường gặp
#1. Có thay đổi được số điện thoại đăng ký Tnex không?
CÓ ! Bạn có thể vào phần Profile => chọn tính năng chỉnh sửa số điện thoại đăng nhập => và thực hiện theo các bước như ứng dụng hướng dẫn.
#2. Có thay đổi được CMTND/ CCCD không?
CÓ ! Bạn cũng vào Profile => chọn tính năng chỉnh sửa thông tin KYC => và thực hiện theo các bước như ứng dụng hướng dẫn.
#3. Sau khi đăng ký Tnex xong, có phải liên kết với tài khoản ngân hàng không?
Bản thân TNEX đã là một ứng dụng ngân hàng rồi, vậy nên nó đã cung cấp cho bạn tài khoản thanh toán của ngân hàng và đầy đủ các dịch vụ ngân hàng đi kèm với tài khoản thanh toán.
Vậy nên bạn không cần phải liên kết với bất kỳ tài khoản ngân hàng nào khác để sử dụng TNEX. Rất hữu ích cho những bạn nào chưa có tài khoản ngân hàng.
#4. Làm thế nào để có được thẻ Tnex vật lý?
Bạn có thể truy cập vào ứng dụng TNEX và yêu cầu phát hành thẻ vật lý. Mã PIN lần đầu sẽ được Tnex gửi tới bạn số điện thoại mà bạn đã dùng để đăng ký.
#5. Câu hỏi khác….
Còn vô số các câu hỏi và câu trả lời khác, nếu bạn muốn tìm hiểu chi tiết hơn thì truy cập vào đây để đọc thêm nhé: https://www.tnex.com.vn/hoi-dap/
VIII. Lời kết
Vâng, như vậy là mình đã vừa giới thiệu và hướng dẫn đến các bạn cách sử dụng ứng dụng Tnex – một ứng dụng ngân hàng số miễn phí 100% các loại phí (với cam kết trọn đời của Tnex).
Vì TNEX là một ứng dụng thuần việc nên cách sử dụng rất đơn giản, mình không hướng dẫn chắc các bạn cũng biết (thật sự rất đơn giản, không tin bạn cứ đăng kí và trải nghiệm thử :D).
Các thao tác sử dụng tương tự như các ứng dụng ngân hàng điện tử VietinBank iPay, VCB Digibank, … hoặc các ví điện tử như Viettelpay, MoMo, ZaloPay, AriPay, …
Xin chào tạm biệt và hẹn gặp lại các bạn trong những bài viết tiếp theo..