Home Blog Page 81

Cloud Camera (VSaaS) vs Đầu Ghi Truyền Thống

vngcloud
Cloud Camera (VSaaS) vs Đầu Ghi Truyền Thống

VSaaS – Video Surveillance as a service, nghĩa là “giám sát video như một dịch vụ” – được biết đến là giải pháp giám sát camera an ninh trên nền tảng đám mây (Cloud). Dịch vụ VSaaS bao gồm các công nghệ và giải pháp cho phép bạn lưu trữ, quản lý, ghi và phát hình ảnh camera từ nền tảng Cloud. Điều này có nghĩa là bạn không cần phải mua thiết bị và phần mềm đặc biệt để lưu trữ và quản lý dữ liệu hình ảnh camera – tất cả bạn cần là camera và kết nối Internet. Nhiệm vụ còn lại nằm ở nhà cung cấp dịch vụ VSaaS.

Hệ thống giám sát camera an ninh trên Cloud – VSaaS – với những ưu điểm rất khác biệt so với các giải pháp truyền thống dựa trên đầu ghi camera Analog (DVR) hoặc đầu ghi camera IP (NVR) được kết nối với Internet để truy cập từ xa hoặc lưu trữ từ xa.

Để đưa ra các quyết định công nghệ đúng đắn mang tính ảnh hưởng đến hoạt động kinh doanh, bạn cần hiểu rõ sự khác biệt giữa VSaaS và những giải pháp camera an ninh truyền thống. Bài viết này sẽ giúp bạn xác định hệ thống nào phù hợp nhất với nhu cầu của công ty hoặc khách hàng của bạn.

Sự hình thành nền tảng đám mây (Cloud) và tính kinh tế của quy mô

Tại Việt Nam, có khoảng 5 trong số 10 doanh nghiệp hiện đang sử dụng công nghệ điện toán đám mây (bao gồm cả giám sát camera an ninh). Theo báo cáo của RightScale, ít nhất 88% doanh nghiệp sử dụng công nghệ đám mây công cộng (Public cloud) và 63% sử dụng đám mây riêng (Private Cloud). Hầu hết những người được hỏi đều sử dụng công nghệ lưu trữ đám mây.

Mô hình Cloud cung cấp cho các doanh nghiệp quy mô kinh tế đáng kể:

Giảm chi phí vốn ban đầu

Một trong những lợi thế đã được chứng minh của việc tiết kiệm nhờ công nghệ Cloud là giảm chi phí vốn ban đầu, mang lại cho các công ty cơ hội đầu tư vào các lĩnh vực kinh doanh khác.

Tận dụng toàn bộ tài nguyên của thiết bị

Các doanh nghiệp sử dụng cơ sở hạ tầng máy chủ chung, do đó tận dụng hệ thống thiết bị tốt hơn và chi phí hỗ trợ khối lượng công việc được giảm bớt.

Giảm chi phí năng lượng

Việc tận dụng phần cứng tốt hơn đồng nghĩa với việc không có hệ thống máy chủ bị bỏ trống. Khi bạn điều hành trung tâm dữ liệu của riêng mình, bạn sẽ hiếm khi sử dụng hết các máy chủ của mình. Máy chủ không hoạt động sẽ lãng phí nguồn năng lượng.

Giảm chi phí nhân sự IT

Các chi phí liên quan đến nhân sự IT có kinh nghiệm, bao gồm cả tiền lương, thường vượt quá chi phí của phần cứng và phần mềm. Nhân sự IT của các nhà cung cấp dịch vụ cloud thường sẽ duy trì một cơ sở hạ tầng chung, vì vậy bạn có thể giảm chi phí IT của riêng mình hoặc điều chuyển nhân sự đến các bộ phận mang lại lợi ích kinh doanh hơn.

Độ tin cậy và khả năng dự phòng

Để có được một hệ thống đáng tin cậy với khả năng dự phòng cao, bạn cần phải mua thêm thiết bị để bảo vệ chúng khỏi những hỏng hóc. Phần cứng còn trống là nguyên nhân tốn kém gây ra gia tăng thời gian hệ thống hoạt động liên tục. 

Các yếu tố cơ bản của hệ thống

Công nghệ Cloud vẫn còn khá mới mẻ đối với hệ thống giám sát camera an ninh dẫn đến một số nhầm lẫn nhất định.

Viện Tiêu chuẩn và Công nghệ Quốc gia (NIST) thuộc Bộ Thương mại Hoa Kỳ đã phát triển một định nghĩa về điện toán đám mây (Cloud) sẽ giúp làm rõ một số điểm khác biệt. NIST định nghĩa một hệ thống đám mây có năm “đặc điểm chính”:

1. Tự phục vụ theo yêu cầu

Người dùng có thể tự động cài đặt và cấu hình các chức năng cần thiết mà không cần tương tác trực tiếp với nhân viên của nhà cung cấp dịch vụ.

2. Truy cập mạng rộng rãi

Các chức năng (khả năng) theo yêu cầu của người dùng có sẵn qua mạng thông qua các cơ chế tiêu chuẩn cho các nền tảng khác nhau, khách hàng khó hay dễ tính (điện thoại di động, máy tính bảng, máy tính xách tay, máy trạm, v.v.).

3. Tổng hợp tài nguyên

Các tài nguyên máy tính của nhà cung cấp dịch vụ được kết hợp để phục vụ nhiều khách hàng, với các tài nguyên vật lý và ảo khác nhau được phân phối và tái phân phối lại theo nhu cầu của khách hàng. Ví dụ: các tài nguyên đó có thể là hệ thống lưu trữ, xử lý, bộ nhớ, băng thông mạng.

4. Tính linh hoạt tức thì

Các tài nguyên có thể được phân bổ linh hoạt và tự động giải phóng để mở rộng quy mô nhanh chóng theo nhu cầu.

5. Dịch vụ đo lường

Hệ thống Cloud kiểm soát tự động và tối ưu hóa việc sử dụng tài nguyên bằng các công cụ đo lường phù hợp với loại hình dịch vụ.

Thuộc tính và Mô hình

Để cung cấp năm đặc điểm cơ bản của “đám mây đích thực”, các tài nguyên điện toán chạy trên cơ sở hạ tầng đám mây dùng chung – nó có thể là đám mây công cộng (Public Cloud) hoặc riêng tư (Private Cloud). Hãy xem điều này hoạt động như thế nào đối với VSaaS trái ngược với DVR hoặc NVR truyền thống.

Trong hệ thống truyền thống, quá trình xử lý, ghi và quản lý video diễn ra trên máy tính của người dùng. Video có thể có sẵn trên Internet để xem hoặc lưu trữ.

Trong giải pháp Cloud này, việc xử lý và quản lý video được thực hiện bởi đám mây. Hệ thống cần có một thiết bị truyền dẫn Cloud để giao tiếp với hệ thống camera và hệ thống Cloud. Thiết bị truyền dẫn Cloud giúp kết nối tập trung toàn bộ camera, mã hóa và truyền dẫn dữ liệu từ camera lên Cloud, và hơn hết la lưu trữ tạm dữ liệu camera khi mất kết nối internet và tải lên lại Cloud tức thì khi có kết nối trở lại. 

Mười một điểm so sánh: VSaaS và giám sát camera truyền thống

Các so sánh tính năng sau đây sẽ giúp bạn xác định hệ thống nào phù hợp nhất với nhu cầu của bạn.

Hiệu quả và tổng chi phí sở hữu

  1. Cài đặt hệ thống

Triển khai một hệ thống truyền thống là một quá trình lâu dài và phức tạp. Bạn phải cài đặt phần mềm cần thiết, cấu hình bộ định tuyến, cấu hình máy chủ lưu trữ. Trong khi đó, hệ thống VSaaS có triển khai theo yêu cầu, các camera được cấu hình tự động.

  1. Hỗ trợ hệ thống

Trước khi công nghệ Cloud ra đời, hầu hết các phiên bản cập nhật firmware và cài đặt thông số đều cung cấp dưới dạng hỗ trợ thủ công. Đối với VSaaS, cả phần cứng và phần mềm đều yêu cầu một lượng lớn điện toán trên Cloud, và việc hỗ trợ sử dụng đều do nhà cung cấp dịch vụ (bên thứ ba) thực hiện.

  1. Cơ cấu chi phí

Trước đây, chi phí đầu tư ban đầu vào phần cứng và phần mềm rất cao trong khi chi phí hỗ trợ là hoàn toàn không dự phí trước được, và hình thành nguyên tắc “ai làm nấy chịu”.

Mô hình VSaaS có chi phí đầu tư ban đầu cực kỳ thấp với khả năng ước tính chi phí hoạt động theo tháng. KHách hàng chỉ trả cho những dịch vụ họ đã sử dụng. Chi phí dịch vụ dựa trên số lượng camera kết nối dịch vụ, thời gian lưu trữ và chất lượng video.

  1. Tổng chi phí sở hữu

Đối với DVR hay NVR, chi phí sở hữu ban đầu cao bắt nguồn từ chi phí phần cứng, phần mềm và cài đặt. Những chi phí này bao gồm chi phí dịch vụ, network và hệ thống cài đặt, sao lưu, chỉnh sửa điều hành hệ thống an ninh, truy cập network từ xa, thời gian nhân sự IT, thiết bị còn trống, phục hồi dữ liệu, đào tạo nhân viên, cài đặt cập nhật phần mềm, và nhiều chi phí khác.

Đối với VSaaS, chi phí ban đầu chỉ bao gồm camera và chi phí lưu trữ hàng tháng. Điều này giúp giảm bớt chi phí khi bảo trì hạ tầng và co giãn nhu cầu sử dụng khi hệ thống mở rộng hoặc thu nhỏ (chúng ta sẽ đề cập phần này tiếp theo).

Tính linh hoạt, khả năng mở rộng và phát triển công nghệ

  1. Tính linh hoạt trong lưu trữ

Các hệ thống truyền thống lưu trữ dữ liệu cục bộ và bị giới hạn bởi dung lượng của thiết bị.

Hệ thống Cloud cho phép kết hợp linh hoạt giữa lưu trữ cục bộ và lưu trữ trên Cloud. Bạn có thể truy cập cùng một dữ liệu bất kể hình ảnh camera được xem hoặc lưu trữ ở đâu.

Bạn có thể ngay lập tức tăng thời gian lưu trữ của camera mà không cần phải thay đổi thiết bị hiện có. Vì hệ thống này đã sử dụng cơ sở hạ tầng Cloud mang lại tính kinh tế vượt bậc về quy mô và tính linh hoạt.

  1. Thêm và định cấu hình camera

Các hệ thống thông thường hỗ trợ nhiều loại camera analog và IP. Sau khi hoàn tất việc triển khai hệ thống ban đầu, người dùng phải kết nối và cấu hình camera mới theo cách thủ công.

Hệ thống VSaaS cũng hỗ trợ nhiều camera analog và IP. Sau khi kết nối camera, camera sẽ tự động được định cấu hình.

  1. Quản lý băng thông

Để lưu trữ video cục bộ, không cần kênh Internet. Đối với lưu trữ Cloud mà không có Internet là không đủ. Tuy nhiên, một số hệ thống Cloud đã tăng cường kiểm soát băng thông.

Ở vCloudcam , bạn có thể tác động đến lưu lượng truy cập Internet thông qua việc thiết lập camera trong tài khoản của mình. Bạn có thể thay đổi độ phân giải video, tốc độ bit và tốc độ khung hình của luồng chính. Tốc độ bit thể hiện mức độ nén luồng và do đó, xác định kích thước của kênh mà luồng dữ liệu được nén.

  1. Có kế hoạch “bản lỗi thời” và API

Các hệ thống truyền thống có thời gian “lỗi thời” ngắn hơn. Tốt nhất, bạn có thể tải xuống các bản cập nhật firmware theo cách thủ công. API đóng, chức năng bị hạn chế.

Nhà cung cấp VSaaS gửi các bản cập nhật tự động qua Internet. Nhờ sự hỗ trợ liên tục, hệ thống không ngừng phát triển, nhận được các chức năng và khả năng mới. Các API phân tích, tích hợp và ứng dụng đều mở và có sẵn công khai.

Bảo mật, Truy cập từ xa và Sao lưu

  1. Bảo mật

Người dùng luôn mong muốn truy cập vào dữ liệu camera từ xa dẫn đến một sự thật là hệ thống DVR và NVR truyền thống, như một quy tắc, được kết nối vào mạng internet bởi bên tích hợp hoặc cài đặt hệ thống. Điều này dẫn đến kết quả hệ thống cần thiết phải cài đặt và cấu hình tường lửa (firewall). Chính vì thế người dùng cuối phải độc lập đối phó với các vectơ tấn công khác nhau, chẳng hạn như các lỗ hổng hệ điều hành, mở port và phần mềm của chính camera.

Hệ thống quản trị video trên Cloud không vấp phải những lỗ hổng như hệ thống truyền thống. Không mở port, tường lửa cục bộ và phần mềm cục bộ.

Mật khẩu

Thoạt đầu, mật khẩu camera có thể được xem là đề tài dễ chú ý về việc đo lường độ an toàn. Tuy nhiên, mọi người vẫn tiếp tục sử dụng các mật khẩu đơn giản, rất thuận tiện cho việc hack. Đó là chưa kể đến việc lạc quan về mật khẩu và những tin tức về việc 2,7 tỉ tài khoản đã bị hack mật khẩu vào năm 2019.

Hầu hết camera bán trên thị trường hiện nay có Giao diện đồ họa người dùng (GUI) và thường thiết kế sẵn phần Đăng nhập và Mật khẩu. Một số nhà cài đặt không thay đổi mật khẩu gì cả và vẫn giữ cùng một mật khẩu cho tất cả camera.

Lý tưởng nhất là bạn nên gán một mật khẩu duy nhất, dài và không dễ nhận diện cho mỗi camera. Một quy trình tỉ mỉ như vậy cần có thời gian để thiết lập, quản lý phức tạp hơn và rất khó theo dõi. Vì vậy, rất nhiều người cài đặt sử dụng cùng một mật khẩu cho tất cả các camera trong tài khoản.

Đối với tất cả các camera sử dụng dịch vụ vCloucam, mật khẩu được tạo một cách ngẫu nhiên, đáng tin cậy trong quá trình kết nối camera. 

  1. Truy cập từ xa

Trong các hệ thống truyền thống, quyền truy cập từ xa vào dữ liệu camera, như một quy luật, ban đầu không được tích hợp sẵn, nhưng xuất hiện do yêu cầu của khách hàng. Chất lượng truy cập dữ liệu camera có thể không cao, với tính năng phát trực tuyến không liên tục và chất lượng hình ảnh thấp. Ngoài ra, việc sử dụng các cơ chế mã hóa dữ liệu tại nguồn hiếm khi được sử dụng.

Hệ thống Cloud camera ban đầu được thiết kế để thuận tiện cho việc truy cập dữ liệu camera từ xa. Giải pháp cho phép truy cập dữ liệu hình ảnh camera với độ trễ thấp, hỗ trợ tất cả các loại trình duyệt và ứng dụng di động. Ngoài ra, một số hệ thống, như vCloudcam, mã hóa toàn bộ luồng dữ liệu lấy từ camera và mã hóa đường truyền dữ liệu lên Cloud.

  1. Đặt chỗ

Các hệ thống truyền thống có mức độ tin cậy không ổn định. Ngoài ra, họ còn yêu cầu nhân viên CNTT nội bộ phải duy trì mức độ này liên tục. Các máy chủ trùng lặp thường “ngủ đông” càng làm tăng thêm chi phí.

Trung tâm dữ liệu Cloud có khả năng dự phòng gấp đôi và gấp ba. Cơ sở hạ tầng dùng chung cung cấp toàn bộ tải cho máy chủ và tính kinh tế theo quy mô. Hệ thống Cloud vượt bậc hơn cũng cung cấp khả năng lưu trữ video cục bộ như một bản sao lưu để tránh các trường hợp sự cố kết nối Internet.

Tóm lại

Theo xu hướng đã hình thành trong các ngành công nghiệp khác, giám sát camera an ninh đã được chuyển đổi số lên hạ tầng Cloud.

Các động lực chính cho sự phát triển của VSaaS bao gồm việc triển khai nhanh chóng các công nghệ mới, bảo mật, lưu trữ linh hoạt, truy cập từ xa không bị gián đoạn.

Cơ sở lý luận tài chính cho VSaaS là giảm chi phí vốn và giảm tổng chi phí sở hữu do tính kinh tế theo quy mô. Ngoài ra, mô hình “bạn chỉ trả tiền cho những dịch vụ mà bạn sử dụng” vừa vặn hơn với nhu cầu của khách hàng cuối, nhà tích hợp và nhà phân phối về dịch vụ hỗ trợ, tăng trưởng và phát triển kinh doanh liên tục.

5 lời khuyên khi phỏng vấn cho các bạn mới tốt nghiệp

lời khuyên phỏng vấn
5 lời khuyên khi phỏng vấn cho các bạn mới tốt nghiệp

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

Sau bao năm đèn sách, mài đũng quần trên ghế ở giảng đường, cuối cùng bạn cũng đã cầm được tấm bằng tốt nghiệp (bảng điểm, chứng nhận tạm thời…) để bắt đầu một cuộc sống mới. Phỏng vấn xin việc luôn là một thử thách nhiều áp lực khiến hầu hết sinh viên mới ra trường phải hồi hộp, lo lắng đôi khi đến mất ăn mất ngủ bởi sự non nớt về kinh nghiệm hoặc thiếu tự tin về một mặt nào đó. Tuy nhiên, bạn sẽ tự tin hơn nhiều với 5 lời khuyên sau.

job-interview

1.  Làm đẹp lý lịch trực tuyến

Bạn nên dành mỗi ngày 1 giờ để đăng tải, chỉnh sửa và cập nhật hồ sơ của mình trên các trang như Viet Nam Works, Kiếm Việc, LinkedIn. Hãy tạo ra một danh sách các ví dụ về những công việc bạn từng làm từ thời kỳ thực tập, các khóa học kỹ năng hay những dự án riêng. Một bản lý lịch trực tuyến sẽ giúp nhà tuyển dụng hiểu rõ hơn về những giá trị bạn có thể đem lại cho họ.

Bạn có thể tạo CV online và lưu lại thông tin trên các nền tảng tuyển dụng thể tăng khả năng tiếp cận với nhà tuyển dụng.

2. Một bản lý lịch truyền thống vẫn luôn quan trọng

Bản lý lịch cá nhân không thôi là chưa đủ, tuy nhiên nó vẫn rất quan trọng. Sơ yếu lý lịch và lý lịch trực tuyến, cả hai thứ trên đều là những thành phần quan trọng của một đợt tìm việc mới.

  Sơ yếu lý lịch cho IT là gì? Cách viết sơ yếu lý lịch IT siêu chuẩn

3. Đừng ngần ngại bộc lộ cá tính

Điều quan trọng nhất một ứng viên cần nhớ trong quá trình phỏng vấn đó là hãy là chính mình. Cá tính của bạn có thể giúp bạn nổi bật trong đám đông ứng viên. Khi có quá nhiều người cạnh tranh cho cùng một vị trí với trình độ tương đương, nhà tuyển dụng thường chọn những người họ thấy thú vị khi làm việc cùng hàng ngày.

4. Hãy đặt một vài câu hỏi độc đáo, thông minh

Trong một cuộc phỏng vấn “loại câu hỏi một ứng viên tiềm năng đưa ra có thể khiến họ trở nên nổi bật”. Những câu hỏi lặp đi lặp lại như: “Bước tiếp theo trong quá trình tuyển dụng là gì?” hoặc “Chuyện gì đã xảy ra với người tiền nhiệm của tôi?” cũng chấp nhận được và có thể nhận được những câu trả lời thiết thực. Nhưng bạn cũng nên thử tạo ra điểm nhấn cho riêng mình bằng những câu hỏi độc đáo, cho thấy bạn đã nghiên cứu kỹ về vị trí này và thực sự hào hứng với công việc. “Những câu hỏi mạnh mẽ cho thấy bạn đã chuẩn bị trước hay chưa, có hiểu về ngành nghề hoặc công việc hay không, có muốn tìm hiểu sâu hơn về các trách nhiệm của mình hay không”, Arlene Vernon, chủ tịch của công ty tư vấn nhân sự và đào tạo HRx, Inc. khẳng định.

5. Hãy tập trả lời các câu hỏi phỏng vấn và ghi âm lại

“Bất kỳ sự tương tác nào bạn có như là bước khởi đầu sự nghiệp với chủ sử dụng lao động mới đều là một cơ hội để gây ấn tượng và phô diễn các kỹ năng, giá trị bạn có”, Hamill nói tiếp. “Cần chắc chắn rằng trông bạn thật tự tin”. Hãy ghi âm lại những câu trả lời của mình và cố gắng loại bỏ các từ “ừ”, “à” trong đó.

“Hãy luyện tập trả lời một cách to, dõng dạc chứ không phải giữ nó trong đầu để câu trả lời của bạn có thể được truyền đi một cách tự tin”, Vernon khuyên. Và nên nhớ đừng có nhìn điện thoại hay nhìn quanh quá nhiều khi phỏng vấn. Hãy nhìn thẳng, cử chỉ tự tin và trả lời rõ ràng chính là những yếu tố then chốt để đảm bảo một buổi phỏng vấn thành công.

Nguồn: US News

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

Loại bỏ Windows Terminal khỏi Menu chuột phải Windows 10

windows terminal
Loại bỏ Windows Terminal khỏi Menu chuột phải Windows 10

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

Có lẽ, lập trình đang là một trong những ngành nghề hot nhất hiện nay, một công việc nhàn hạ cùng với một mức lương đáng mơ ước ! Vâng, đấy là nhiều bạn đang nghĩ thế 😀 Còn thực tế thì xem tại đây 🙂

Mà đã là dân lập trình (dev) thì chắn chắn không còn xa lạ gì với các công cụ dòng lệnh như Terminal trên Linux, macOS, thậm chí là bạn còn biết cách sử dụng nó một cách thuần thục nữa.

Trên hệ điều hành Windows 10 mà chúng ta đang sử dụng cũng có một công cụ tương tự như vậy, không chỉ một mà có tới hai luôn các bạn ạ.

  10 điều bạn có thể làm với Linux mà bạn không thể làm với Windows
  40 phím tắt dành cho người dùng Windows

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

Khỏi cần kể tên thì chắc các bạn cũng biết hai công cụ mà mình đang muốn đề cập đến nó là gì rồi đúng không 🙂 Vâng, chính là Windows PowerShell và Command Prompt !

Tuy vậy, trên thực tế thì chức năng và ứng dụng của hai công cụ này không thể bằng được so với Terminal, đây cũng chính là lí do mà dân lập trình ưa dùng Linux và macOS hơn là Windows 10.

loai-bo-windows-terminal-khoi-menu-chuot-phai-windows-10 (1)

Mới đây, Microsoft đã giới thiệu và phát hành một ứng dụng mang tên Windows Terminal với mục đích thay thế Command Prompt và PowerShell.

Và nếu bạn không phải dân lập trình, không thường xuyên sử dụng công cụ này thì mình sẽ hướng dẫn cho các bạn cách loại bỏ Windows Terminal khỏi menu chuột phải của Windows 10 nhé !

#1. Windows Terminal xuất hiện ở đâu?

Windows Terminal là một ứng dụng mã nguồn mở được Microsoft phát triển và phát hành miễn phí trên Windows 10.

Đây là một công cụ dòng lệnh có giao diện rất hiện đại, mạnh mẽ, mượt mà và giúp tăng hiệu suất làm việc của người dùng.

Ban đầu, nghe tin Microsoft ra mắt ứng dụng Terminal mới mình đã cảm thấy rất phấn khích và hóng ngày được dùng thử.

Nhưng hy vọng càng nhiều thì thất vọng càng nhiều các bạn ạ, ứng dụng Windows Terminal thực chất vẫn chỉ là Windows PowerShell và Command Prompt trong lớp vỏ trông có phần hiện đại hơn, kèm vài tính năng không mấy hữu ích lắm. Kiểu bình mới rượu cũ ấy 🙁

Và từ đó đến giờ mình cũng chẳng động đến cái ứng dụng Terminal đó lần nào nữa. Ai chưa biết và cũng chưa dùng thử ứng dụng này bao giờ thì có thể xem lại bài viết giới thiệu và hướng dẫn cài đặt Windows Terminal trước đó của mình nha.

Khi đã được cài đặt vào Windows 10, Windows Terminal sẽ mặc định có trong menu chuột phải của File Explorer tùy chọn Open in Windows Terminal.

Nó cho phép bạn mở nhanh một thư mục trong Windows Terminal để làm việc, thay vì phải gõ lệnh cd + đường dẫn thư mục như thông thường, đây là một tính năng khá hữu ích, giúp tiện kiệm thời gian gõ lệnh, đặc biệt là với các thư mục có đường dẫn dài và phức tạp.

Tuy nhiên, nếu bạn không có nhu cầu sử dụng đến tính năng Open in Windows Terminal nhưng vẫn cần dùng Terminal, hoặc cảm thấy khó chịu khi thường bấm nhầm vào tùy chọn này thì hoàn toàn có thể gỡ bỏ nó khỏi menu chuột phải của Windows 10.

loai-bo-windows-terminal-khoi-menu-chuot-phai-windows-10 (3)

#2. Loại bỏ Windows Terminal khỏi Menu chuột phải trên Windows 10

Để loại bỏ tùy chọn Open in Windows Terminal ra khỏi menu chuột phải của Windows 10, chúng ta không có cách nào khác ngoài việc chỉnh sửa trong Registry của hệ thống.

Chính vì thế mà bạn nên sao lưu lại toàn bộ Registry trước khi làm theo bài hướng dẫn này để nếu có lỡ chỉnh sửa sai gây lỗi Windows 10 thì vẫn có thể khôi phục lại được.

Thực hiện:

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

loai-bo-windows-terminal-khoi-menu-chuot-phai-windows-10 (4)

+ Bước 2: Tiếp theo, bạn truy cập vào thư mục Blocked trong Registry theo đường dẫn:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Blocked

NOTE: Bạn có thể truy cập nhanh vào thư mục này bằng cách dán trực tiếp đường dẫn trên vào thanh địa chỉ của Registry Editor rồi bấm Enter là xong.

Ngoài ra, bạn có thể tham khảo cách mở nhanh một đường dẫn bật kỳ trong Registry chỉ với một cú click chuột để rút ngắn, tiết kiệm thời gian truy cập thủ công như mình làm đây ha.

Mặc định thư mục Blocked này sẽ chưa có khóa nào cả, khóa Default (String) không tính vì nó là khóa mặc định và bắt buộc phải có của mọi thư mục trong Registry Editor.

+ Bước 3: Giờ để loại bỏOpen in Windows Terminal trong menu chuột phải, bạn hãy click chuột phải vào khoản trống bất kỳ trong khung bên phải => chọn New => chọn String Value để tạo một khóa mới dạng chuỗi như khóa Default ở trên.

Sau đó, bạn đặt tên cho khóa vừa tạo là {9F156763-7844-4DC4-B2B1-901F640F5155} và phần Value data hãy để trống.

=> Vậy là xong rồi đó, bạn không cần phải chỉnh sửa phức tạp cả và đã có thể đóng Registry Editor đi được rồi.

loai-bo-windows-terminal-khoi-menu-chuot-phai-windows-10 (5)

__________________

Bonus: Nếu bạn sợ thao tác sai thì có thể sử dụng file REG mà mình đã tạo sẵn bên dưới đây !

Vẫn như mọi lần, mình đã chuẩn bị sẵn file REG để cho các bạn tiện sử dụng, chỉ việc giải nén ra và dùng file REG tương ứng thôi.

Chọn một trong các đường link bên dưới để tải về, file ZIP đã bao gồm cả file REG để loại bỏ và khôi phục dòng Open in Windows Terminal.

Thông thường sau khi chỉnh sửa trong Registry của Windows 10, chúng ta sẽ cần khởi động lại máy tính để các thay đổi đó có hiệu lực.

Nhưng đối với trường hợp này, bạn chỉ việc khởi động lại Windows Explorer là được. Mình cũng đã có hẳn một bài viết chia sẻ những cách khởi động lại Windows Explorer trên Windows 10 rồi, bạn có thể tìm và xem lại nha.

Còn cách mình thấy nhanh nhất và thườn xuyên sử dụng nhất đó là mở Task Manager lên (Ctrl + Shift + ESC) => bấn chuột phải vào tiến trình Windows Explorer => rồi chọn Restart thôi.

loai-bo-windows-terminal-khoi-menu-chuot-phai-windows-10 (6)

Và đây kết quả sau khi khởi động lại Windows Explorer, menu chuột phải đã trở về như bình thường.

Đây là cách để áp dụng cho những bạn vẫn có nhu cầu dùng ứng dụng Terminal, còn như mình, không dùng thì gỡ cài đặt Terminal là cách đơn giản và nhanh nhất để loại bỏ tùy chọn Open in Windows Terminal nha các bạn.

loai-bo-windows-terminal-khoi-menu-chuot-phai-windows-10 (7)

#3. Lời kết

Như vậy là mình đã vừa hướng dẫn xong cho các bạn cách để loại bỏ tùy chọn Open in Windows Terminal trong menu chuột phải của Windows 10 rồi.

Tùy chọn này nghe có vẻ hữu ích nhưng trong thực tế thì không được như Microsoft kỳ vọng, thậm chí còn gây phiền phức vì bấm nhầm trong quá trình sử dụng nữa. Và nó còn làm cho menu chuột phải thêm cồng kềnh..

Nhưng mình vẫn hi vọng Microsoft tiếp tục cải tiến nó trong những phiên bản sắp tới !

Nếu thấy thủ thuật mình vừa giới thiệu hay và hữu ích thì đừng quên chia sẻ để nhiều người cùng biết nữa nha. Chúc các bạn thành công !

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ề HTTP Cookies

http cookies
Tìm hiểu về HTTP Cookies

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

Lời nói đầu

Đầu tiên, bài viết này mình viết với mục đích chia sẻ kiến thức của mình về http cookies (hoặc http cookie). Nếu bạn nào chưa biết về HTTP, FTP, SMTP thì có thể đọc bài này trước. Cách chia sẻ của mình là cố gắng diễn tả vấn đề sao cho thật hài hước và dễ hiểu. Bằng cách này, việc đọc bài sẽ giúp các bạn nhớ lâu và việc học trở nên không nhàm chán, chứ không phải là không tôn trọng người đọc.

Vì vậy, việc này có thể sẽ không phù hợp với một số bạn, nên nếu có vấn đề gì về kiến thức hoặc cách diễn đạt của mình, các bạn có thể góp ý cho mình bằng cách comment phía dưới.

  Cách làm HTTPS hoạt động trên local trong 5 phút
  Cấu hình HTTPS Server cho NGINX (SSL Certificate trong NGINX)

1. HTTP Cookies là gì?

Http Cookie, thường được gọi là cookie (bánh). Từ thuở ban đầu dự định sử dụng vào việc lưu trữ thông tin session ở phía client. Theo bản chất, cookie sẽ được gắn với một tên miền (domain) cụ thể.

Câu chuyện ra đời của cookie khá là hấp diêm, ý lộn hấp dẫn.

1.1 Câu chuyện

Ngày xửa ngày xưa, có một cô nàng tên là Netscape, rất xinh đẹp và còn zin 😂😂. Cô ấy yêu say đắm một anh chàng tên Server. Vào một ngày kia, khi tình yêu đã chớm nở, cô gửi cho anh chàng một cái request (với header là hãy làm gì em đi!).

Không bỏ qua cơ hội ngon ăn, anh chàng server gửi ngay một response, anh check hàng (mất zin, ẹc) và đồng ý cho Netscape vào phòng.

Sẽ chẳng có gì để nói nếu 2 tiếng sau đó, cô nàng Netscape đi ra ngoài đổ rác và quay lại gõ cửa yêu cầu được quay trở lại phòng, trớ trêu thay, anh chàng server đã mất đi trí nhớ của mình và lại đòi check hàng Netscape. Vì quá bực tức với độ điếm thúi của server, cô nàng Nestcape đã lấy một ít bánh (cookie) còn sót trong thùng rác, ghi vào đó cặp name value rằng checkroi: 2tiengtruoc. Ngay khi nhận được bánh, server lập tức hiểu rằng đã check hàng, và nó cho Netscape vào. Từ đó cookie ra đời.

Vừa rồi là câu chuyện về sự ra đời của cookie do mình tự bịa, còn ngắn gọn thì cookie được phát minh bởi Netscape, với mục đích ban đầu là để cung cấp bộ nhớ cho máy chủ và trình duyệt web. 🤣🤣

2. Mày vừa mới troll tao đấy!, thế có những loại cookies nào, dùng nó làm gì?.

Tất nhiên, với câu chuyện ra đời hết sức xàm xí, ý lộn có lí của cookie thì về cơ bản cookie có thể được phân làm hai loại chính:

  • Session cookies (phiên cookie): giữ lại ở trình duyệt và sẽ bị xóa bỏ khi đóng trình duyệt. Khi cửa sổ trình duyệt mới được mở lại, người dùng sẽ phải cung cấp lại các chứng thực của mình.
  • Persistent cookise (coookie liên tục): giữ ở trình duyệt cho tới khi hết hạn hoặc được xóa một cách thủ công. Các trang web sẽ ghi nhớ các chứng thực ngay cả khi người dùng đóng trình duyệt.

http-cookies-la-gi


Ứng dụng quan trọng nhất của cookies là giữ cho người dùng đăng nhập khi họ duyệt từ trang này qua trang khác. Một số trang web thương mại điện tử thì sử dụng cả session cookies và persistent cookies để tạo sự liền mạch cho giỏ hàng khi mua sắm.

3. Hai loại, fine!. Thế nó hoạt động như thế nào?.

Nghiêm túc lại nè.

Khi người dùng truy cập vào trang web lần đầu tiên, trang web sẽ tạo ra bản ghi của nó và lưu vào cookies trên trình duyệt của người dùng. Lúc này cookies chỉ là một dòng văn bản ngắn. Không chứa bất cứ thông tin nào về người dùng hoặc máy của người dùng. Thay vào đó, nó chứa URL của trang web đã đặt cookies.

Khi người dùng quay lại và lướt web, mỗi trang mới mà người dùng truy cập, trình duyệt sẽ tìm kiếm cookies. Nếu URL của cookies khớp với URL của trang web, trang web sẽ truy xuất thông tin máy chủ.  Phương thức lấy sẽ là sử dụng thông tin lấy được từ cookies.

Bằng cách này, trang web có thể nâng cao trải nghiệm người dùng, hạn chế phải lặp đi lặp lại nhiều hoạt động của người dùng. Một số trang web cũng có thể sử dụng cookies để nâng cao trải nghiệm người dùng. Người dùng mới có thể thấy phiên bản mới của trang web, trong khi người dùng cũ lại thấy phiên bản trước đó.

Các bạn có thể theo dõi hình dưới:

4. Biết là dùng vậy rồi!. Thế bánh có nhiều thứ không?.

Bánh ngon thì nhiều thứ 😂. Một vài thứ làm nên bánh đây:

  • Name: Một tên duy nhất dùng để định danh (bánh đậu xanh, bánh pía, vân vân). Tên cookies không phân biệt chữ hoa và chữ thường, vậy nên việc sử dụng banhPIA và BanhPia là giống nhau. Tuy nhiên, trong thực tế ta nên phân biệt hoa thường. Một số phần mềm trên server có thể sẽ phân biệt hoa thường. Ngoài ra tên cookies phải được mã hóa URL (URL encoded).
  • Value: giá trị được lưu trữ trong cookies, giá trị này cũng nên được mã hóa URL.
  • Domain: là domain mà cookies chúng ta hợp lệ (bánh not for everyone). Mọi thứ được gửi hoặc được sử dụng từ domain này sẽ kèm theo cookies.
  • Path: đường dẫn được chỉ định trong domain (địa chỉ ship bánh), nơi mà cookies sẽ được gửi đến server.
  • Expiration: Đây là dấu thời gian, nó cho biết lúc nào cookies sẽ bị xóa (bánh có hạn sử dụng, không thể ăn mãi được). Mặc định thì tất cả cookies sẽ bị xóa khi ta tắt trình duyệt.
  • Secure Flag: cờ an toàn, với mục đích chỉ gửi cookies nếu kết nối SSL được sử dụng. Ví dụ: khi gửi request tới https://www.vietcombank.com.vn thì nên gửi kèm thông tin cookies, còn tới http://www.vietcombank.com.vn thì không.

Hình dưới là một số cookies được lưu trữ khi truy cập stackoverflow.com.


tim-hieu-ve-http-cookie

5. Thử một cái xem nào, nhắc tới bánh đói bụng quá!.

Ví dụ đầu tiên thường gặp khi sử dụng cookies là xác thực (authentication). Khi chúng ta đăng nhập ở một website.

Luồng thực hiện:

http-cookies-la-gi

Bước 1: Gửi request method POST yêu cầu đăng nhập tới website (ví dụ github), thông tin là username và password, việc đầu tiên server thực hiện là xác thực tài khoản này.

http-cookies-la-gi

Bước 2: Sau khi xác thực thành công, server sẽ cấp token, lưu trữ vào cookies, ở đây là giá trị usersession

Bước 2

Bước 3: Khi quay lại trang web, server sẽ thực hiện method GET. Method này thực hiện lấy nhiều thông tin, một trong số đó là usersession

Tìm hiểu về HTTP Cookies

Bước 4: Dựa vào thông tin usersession này, server sẽ xác thực và di chuyển thẳng tới trang dashboard

6. Bánh có độc không? (thử rồi mới nói, ẹc).

Khi chúng ta thiết lập một cookies mới, nó sẽ được gửi kèm theo các request tới domain mà nó được khởi tạo. Việc hạn chế này đảm bảo thông tin lưu trữ trong cookie được an toàn. Chỉ có người được cấp phép mới được tiếp cận và không thể truy cập bởi domain khác (ship bánh nhầm cmn địa chỉ).

Vì cookie được lưu trữ trên phía client. Nên dù bánh có ngon, ta cũng không thể ăn quá nhiều. Số lượng cookie trên mỗi domain là có giới hạn!.

Hạn chế này đảm bảo rằng cookies sẽ không bị sử dụng sai mục đích và chiếm quá nhiều dung lượng đĩa (disk space).

Mặc dù bị giới hạn, nhưng số lượng cookie tối đa trên mỗi domain cũng thay đổi qua các phiên bản của trình duyệt.

  • Internet Explorer 6 trở về trước thì tối đa là 20 cookie
  • Internet Explorer 7 trở về sau thì tối đa là 50 cookie (sau khi có bản vá từ Microsoft)
  • Firefox là 50 cookie
  • Chorme và safari thì không giới hạn

7. Tổng kết.

Cookies là một phần của Web Storage interface, cũng là một phần thiết yếu của internet. Thiếu đi nó các trang web sẽ ít tương tác với người dùng, trải nghiệm người dùng trên trang web cũng bị giảm đi đáng kể. Vậy mới nói, nếu không có một tình yêu mãnh liệt giữa Server và Nestcape. Làm sao chúng ta có cookies ngày hôm nay?.

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

Phân biệt same-site và same-origin

same-site-vs-same-origin
Phân biệt same-site và same-origin

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

1. Origin

Phân biệt same-site và same-origin

origin = scheme + host name + port

Ví dụ nếu có URL là: https:///www.example.com:443/foo thì origin của nó là https://www.example.com:443

  .NET core vs ASP.NET core: Phân biệt .NET Framework, .NET Core và Mono
  10 lý do kiểm thử phần mềm trở thành một nghề thời thượng

Vậy same-origin tức là những url có cùng scheme, host name, port, ngược lại thì gọi là cross-origin

Origin A Origin B
https://www.example.com:443 https://example.com:443 cross-origin: khác subdomain
https://www.evil.com:443 cross-origin: khác domain
https://login.example.com:443 cross-origin: khác subdomain
http://www.example.com:443 cross-origin: khác scheme
https://www.example.com:80 cross-origin: khác port
https://www.example.com same-origin: ngầm hiểu cùng port 443 (port mặc định của web)

2. Site

Top-level domains (TLDs) như .com.org được liệt kê trong trang này

site =TLD + phần ngay phía trước domain

Với ví dụ trên, thì site = example.com

Tuy nhiên với những tên miền kiểu .com.vngithub.io, cách xác định site này không còn đúng, nên người ta tạo thêm danh sách effective TLDs (eTLDs)xem chi tiết publicsuffix.org/list

Ví dụ, URL https://my-project.github.io thì site = my-project.github.io

Vậy same-site là những url có cùng site, ngược lại được gọi là cross-site

URL A URL B
https://www.example.com:443 https://www.evil.com:443 cross-site: khác domain
https://login.example.com:443 same-site: khác subdomain không sao
http://www.example.com:443 same-site: khác scheme không sao
https://www.example.com:80 same-site: khác port không sao
https://www.example.com same-site

Gần đây khái niệm same-site được mở rộng và bao gồm luôn scheme

Nếu tính luôn scheme, thì http://example.com và https://example.com là cross-site vì khác scheme

“same-site” và “cross-site” #

Các trang web có cùng eTLD + 1 được coi là “cùng một trang web”. Các trang web có eTLD + 1 khác là “trang web chéo”.

Xuất xứ A Xuất xứ B Giải thích về việc Xuất xứ A và B là “cùng một trang web” hay “trang web chéo”
https://www.example.com:443 https: // www.evil.com : 443 cross-site: các miền khác nhau
https: // đăng nhập .example.com: 443 cùng một trang web: các tên miền phụ khác nhau không quan trọng
http : //www.example.com: 443 cùng một trang web: các chương trình khác nhau không quan trọng
https://www.example.com: 80 cùng một trang web: các cổng khác nhau không quan trọng
https://www.example.com:443 cùng trang web: đối sánh chính xác
https://www.example.com cùng trang web: các cổng không quan trọng

“schemeful same-site”

cùng một địa điểm

Định nghĩa “cùng một trang web” đang được phát triển để coi lược đồ URL là một phần của trang web nhằm ngăn chặn HTTP được sử dụng như một kênh yếu . Khi các trình duyệt chuyển sang phần diễn giải này, bạn có thể thấy các tham chiếu đến “trang web ít sơ đồ hơn” khi tham chiếu đến định nghĩa cũ hơn và ” trang web có sơ đồ tương tự ” tham chiếu đến định nghĩa chặt chẽ hơn. Trong trường hợp đó, http://www.example.comvà https://www.example.comđược coi là trang web chéo vì các lược đồ không khớp.

Xuất xứ A Xuất xứ B Giải thích về việc Xuất xứ A và B có phải là “cùng một trang web được sơ đồ hóa” hay không
https://www.example.com:443 https: // www.evil.com : 443 cross-site: các miền khác nhau
https: // đăng nhập .example.com: 443 cùng một trang web có kế hoạch: các tên miền phụ khác nhau không quan trọng
http : //www.example.com: 443 cross-site: các chương trình khác nhau
https://www.example.com: 80 cùng một trang web có sơ đồ: các cổng khác nhau không quan trọng
https://www.example.com:443 cùng một trang web có kế hoạch: kết hợp chính xác
https://www.example.com cùng một trang web có kế hoạch: các cổng không quan trọng

Cách kiểm tra xem một yêu cầu là “cùng trang web”, “cùng nguồn gốc” hay “trang web chéo” #

Chrome gửi yêu cầu cùng với Sec-Fetch-Sitetiêu đề HTTP. Không có trình duyệt nào khác hỗ trợ Sec-Fetch-Sitekể từ tháng 4 năm 2020. Đây là một phần của đề xuất Tiêu đề yêu cầu siêu dữ liệu tìm nạp lớn hơn . Tiêu đề sẽ có một trong các giá trị sau:

  • cross-site
  • same-site
  • same-origin
  • none

Bằng cách kiểm tra giá trị của Sec-Fetch-Site, bạn có thể xác định xem yêu cầu là “cùng một trang web”, “cùng một nguồn gốc” hay “trang web chéo” (“sơ đồ cùng một trang web” không được nắm bắt Sec-Fetch-Site).

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

Nhân Viên QC Là Gì? Mức Lương Của Nhân Viên QC Bao Nhiêu?

mức lương của nhân viên qc
Nhân Viên QC & Mức Lương Của Nhân Viên QC Ở Thời Điểm Hiện Tại

Nhân viên QC – Quality Control (Kiểm soát chất lượng) là một trong những vị trí không thể thiếu với bất cứ công ty, tổ chức hay xí nghiệp nào. Với nhiệm vụ kiểm soát chất lượng và giám sát quy trình hoạt động, công việc của nhân viên QC phải làm hàng ngày đều rất nhiều và đòi hỏi tính cẩn thận cao. Vậy mức lương của nhân viên QC hiện đang nằm trong mức nào? Công việc phức tạp có đi kèm một mức lương hấp dẫn? Cùng TopDev tìm hiểu thêm với bài viết dưới đây nhé!

lương nhân viên
Lương của người làm QC trên thị trường đang như thế nào?

Các công việc nhân viên QC thường đảm nhận

Nhân viên QC – kiểm soát chất lượng sẽ chịu trách nhiệm chính trong việc kiểm tra và giám sát toàn bộ quy trình sản xuất sản phẩm. Để sản phẩm đến được tay khách hàng đảm bảo chất lượng, không xảy ra lỗi trong quá trình sử dụng, nhân viên QC phải làm việc liên tục để phát hiện kịp thời và phối hợp với nhân QA (Quality Assurance) để tìm ra phương án chỉnh sửa hợp lí nhất.

Nhân viên QC hiện đang có 3 dạng gồm: nhân viên kiểm soát chất lượng đầu vào, kiểm soát chất lượng quy trình sản xuất và kiểm soát chất lượng đầu ra. Tương ứng với mỗi giai đoạn, nhân viên QC ở mỗi vị trí sẽ có trách nhiệm chuyên môn riêng để giảm thiểu xuất hiện lỗi một cách tối đa. Thậm chí, đối với những nhân viên kiểm soát chất lượng chuyên nghiệp và đã có nhiều kinh nghiệm trong nghề, họ thậm chí có thể tìm được cách để gia tăng chất lượng sản phẩm so với ban đầu.

>>> Xem thêm Nhân Viên QC Và Những Kỹ Năng Không Thể Thiếu Trong Công Việc

Mức lương của nhân viên QC

Mức lương của nhân viên QC hiện tại đang được chi trả dựa vào kinh nghiệm và năng lực làm việc. Theo đó, có thể kể qua mức lương của nhân viên QC fresher (chưa có/chưa nhiều kinh nghiệm) và mức lương nhân viên QC đã có nhiều kinh nghiệm làm việc trong ngành.

Mức lương của nhân viên QC chưa có nhiều kinh nghiệm

Vì có vai trò quan trọng nên các vị trí liên quan đến nhân viên kiểm soát chất lượng hiện nay đều có nhu cầu tuyển dụng rất cao. Do đó, với các sinh viên mới ra trường muốn tìm kiếm các công viên liên quan đến QC thì đây được xem là “mảnh đất cực kỳ màu mỡ”.

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

Mức lương trung bình của nhân viên QC mới ra trường, chưa có nhiều kinh nghiệm hoàn toàn có thể nằm trong khoảng từ 8 – 10 triệu đồng/tháng. Thậm chí, nếu bạn đã có một ít kinh nghiệm trong quá trình là sinh viên và có năng lực đảm nhận nhiều việc hơn, mức lương còn có thể cao hơn trong khoảng 12 triệu đồng/tháng.

lương của qc
Lương của nhân viên QC hiện được trả chủ yếu dựa trên kinh nghiệm làm việc

Mức lương của nhân viên QC đã có kinh nghiệm làm việc

Những nhân viên QC giỏi về chuyên môn cũng như có nhiều năm kinh nghiệm làm việc trong nghề được săn đón rất nhiệt tình. Do đó, mức lương cho vị trí này cũng hậu hĩnh hơn hẳn so với những công việc khác. Theo đó, ở thời điểm hiện tại, mức lương của một nhân viên QC đã có trên 3 – 4 năm kinh nghiệm ở mức trên 13 triệu đồng/tháng. Với những vị trí ở cấp quản lý như trưởng phòng, mức lương hoàn toàn có thể nằm trong khoảng trên 20 triệu đồng/tháng.

Tính lương gross sang net của nhân viên QC chuẩn, trải nghiệm ngay!

Không có một công việc nào là dễ dàng, và để có một mức thu nhập hấp dẫn thì việc đánh đổi sức lao động cũng sẽ nhiều hơn. Trau dồi và rèn luyện thật nhiều để có thể vững vàng với chuyên môn công việc của mình. Đón đọc thêm nhiều bài viết hấp dẫn trong lĩnh vực nhân sự và công nghệ cũng TopDev nhé!

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

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

Hiện thực một Maven Archetype

maven archetype
Hiện thực một Maven Archetype

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

Maven Archetype là một tính năng của Maven, các bạn hiểu nôm na là nó cho phép chúng ta tạo nhanh một Maven project với cấu trúc đã được định nghĩa sẵn. Chúng ta chỉ cần thay đổi những giá trị như Group Id, Artifact Id hay Version theo giá trị mà chúng ta muốn mà thôi. Mình thì mình hay sử dụng các Maven Archetype định nghĩa cấu trúc của các project Spring hay Jakarta EE. Trong bài viết này, mình sẽ hướng dẫn các bạn cách hiện thực một Maven archetype để nếu các bạn có ý định hiện thực một Maven Archetype cho riêng mình thì có thể dựa vào hướng dẫn của mình mà làm nhé!

  Build executable jar sử dụng Maven Shade Plugin
  Cài Plugin cho Jenkins, Cài Maven Plugin cho Jenkins

Điều đầu tiên, mình cần nói với các bạn là Maven Archetype cũng là một Maven project nhưng packaging của nó không phải là jar, war hay là pom mà có giá trị là “maven-archetype”. Các bạn có thể sử dụng command line hoặc một Java IDE nào đó có hỗ trợ Maven project để generate Maven Archetype project đều được.

Tạo mới Maven Archetype project

Trong bài viết này, mình sẽ sử dụng Eclipse IDE để làm việc với Maven Archetype project.

Mình sẽ tạo mới một Maven project sử dụng một Maven Archetype của Maven để generate Maven Archetype project 🙂

Maven Archetype này có tên là maven-archetype-archetype:

Khai báo thông tin project:

Kết quả:

Các tập tin, thư mục nằm trong thư mục src/main/resources/archetype-resources sẽ nằm trong project mà chúng ta generate từ Maven Archetype project. Ví dụ, nếu bây giờ, các bạn chạy “mvn clean install” cho project này (các bạn nên sử dụng command line để chạy, chạy trong Eclipse có thể sẽ có issue liên quan đến “${maven.home} is not specified as a directory”) của Maven plugin, sau đó vào thư mục target/test-classes/projects/id-basic/project, các bạn sẽ thấy một project mới được generate từ Maven Archetype project của chúng ta:

Import Maven project này sử dụng một IDE khác như IntelliJ, các bạn sẽ thấy kết quả như sau:

Bây giờ, chúng ta sẽ thử hiện thực Maven Archetype project theo ý của mình nhé!

Hiện thực Maven Archetype project

Để lấy ví dụ cho bài viết này, mình sẽ hiện thực một Spring MVC project dựa trên project template của Spring Tool Suite 3, trong bài viết về Tạo ứng dụng web sử dụng Spring bằng Spring Legacy Project trong Spring Tool Suite 3. Nói cho các bạn hiểu thì Spring MVC project template của Spring Tool Suite 3 đang sử dụng những version cũ của Spring và các library khác, mỗi khi tạo mới project Spring MVC sử dụng nó, mình phải chỉnh sửa lại cho phù hợp với thời điểm hiện tại.

OK, bắt đầu nhé các bạn. Các bạn có thể đọc lại bài viết Tạo ứng dụng web sử dụng Spring bằng Spring Legacy Project trong Spring Tool Suite 3 để hiểu rõ những tập tin thư mục mà mình cần tạo trong Maven Archetype project ví dụ trong bài viết này. Project ví dụ của bài viết trên, mình cũng đã push lên GitHub tại https://github.com/huongdanjavacom/huongdanjava.com/tree/master/spring-mvc-example.

Đầu tiên, chúng ta cập nhập tập tin pom.xml ở thư mục src/main/resources/archetype-resources của Maven Archetype project.

Mình sẽ replace bằng nội dung của tập tin pom.xml trong project spring-mvc-example ở trên, xong chỉnh sửa lại version của các library, framework sử dụng latest version.

Nội dung của tập tin pom.xml của Maven Archetype project lúc này như sau:

Maven Archetype là một tính năng của Maven, các bạn hiểu nôm na là nó cho phép chúng ta tạo nhanh một Maven project với cấu trúc đã được định nghĩa sẵn. Chúng ta chỉ cần thay đổi những giá trị như Group Id, Artifact Id hay Version theo giá trị mà chúng ta muốn mà thôi. Mình thì mình hay sử dụng các Maven Archetype định nghĩa cấu trúc của các project Spring hay Jakarta EE. Trong bài viết này, mình sẽ hướng dẫn các bạn cách hiện thực một Maven archetype để nếu các bạn có ý định hiện thực một Maven Archetype cho riêng mình thì có thể dựa vào hướng dẫn của mình mà làm nhé!

Điều đầu tiên, mình cần nói với các bạn là Maven Archetype cũng là một Maven project nhưng packaging của nó không phải là jar, war hay là pom mà có giá trị là “maven-archetype”. Các bạn có thể sử dụng command line hoặc một Java IDE nào đó có hỗ trợ Maven project để generate Maven Archetype project đều được.

Tạo mới Maven Archetype project

Trong bài viết này, mình sẽ sử dụng Eclipse IDE để làm việc với Maven Archetype project.

Mình sẽ tạo mới một Maven project sử dụng một Maven Archetype của Maven để generate Maven Archetype project 🙂

Maven Archetype này có tên là maven-archetype-archetype:

Khai báo thông tin project:

Kết quả:

Các tập tin, thư mục nằm trong thư mục src/main/resources/archetype-resources sẽ nằm trong project mà chúng ta generate từ Maven Archetype project. Ví dụ, nếu bây giờ, các bạn chạy “mvn clean install” cho project này (các bạn nên sử dụng command line để chạy, chạy trong Eclipse có thể sẽ có issue liên quan đến “${maven.home} is not specified as a directory”) của Maven plugin, sau đó vào thư mục target/test-classes/projects/id-basic/project, các bạn sẽ thấy một project mới được generate từ Maven Archetype project của chúng ta:

Import Maven project này sử dụng một IDE khác như IntelliJ, các bạn sẽ thấy kết quả như sau:

Bây giờ, chúng ta sẽ thử hiện thực Maven Archetype project theo ý của mình nhé!

Hiện thực Maven Archetype project

Để lấy ví dụ cho bài viết này, mình sẽ hiện thực một Spring MVC project dựa trên project template của Spring Tool Suite 3, trong bài viết về Tạo ứng dụng web sử dụng Spring bằng Spring Legacy Project trong Spring Tool Suite 3. Nói cho các bạn hiểu thì Spring MVC project template của Spring Tool Suite 3 đang sử dụng những version cũ của Spring và các library khác, mỗi khi tạo mới project Spring MVC sử dụng nó, mình phải chỉnh sửa lại cho phù hợp với thời điểm hiện tại.

OK, bắt đầu nhé các bạn. Các bạn có thể đọc lại bài viết Tạo ứng dụng web sử dụng Spring bằng Spring Legacy Project trong Spring Tool Suite 3 để hiểu rõ những tập tin thư mục mà mình cần tạo trong Maven Archetype project ví dụ trong bài viết này. Project ví dụ của bài viết trên, mình cũng đã push lên GitHub tại https://github.com/huongdanjavacom/huongdanjava.com/tree/master/spring-mvc-example.

Đầu tiên, chúng ta cập nhập tập tin pom.xml ở thư mục src/main/resources/archetype-resources của Maven Archetype project.

Mình sẽ replace bằng nội dung của tập tin pom.xml trong project spring-mvc-example ở trên, xong chỉnh sửa lại version của các library, framework sử dụng latest version.

Nội dung của tập tin pom.xml của Maven Archetype project lúc này như sau:

Maven Archetype là một tính năng của Maven, các bạn hiểu nôm na là nó cho phép chúng ta tạo nhanh một Maven project với cấu trúc đã được định nghĩa sẵn. Chúng ta chỉ cần thay đổi những giá trị như Group Id, Artifact Id hay Version theo giá trị mà chúng ta muốn mà thôi. Mình thì mình hay sử dụng các Maven Archetype định nghĩa cấu trúc của các project Spring hay Jakarta EE. Trong bài viết này, mình sẽ hướng dẫn các bạn cách hiện thực một Maven archetype để nếu các bạn có ý định hiện thực một Maven Archetype cho riêng mình thì có thể dựa vào hướng dẫn của mình mà làm nhé!

Điều đầu tiên, mình cần nói với các bạn là Maven Archetype cũng là một Maven project nhưng packaging của nó không phải là jar, war hay là pom mà có giá trị là “maven-archetype”. Các bạn có thể sử dụng command line hoặc một Java IDE nào đó có hỗ trợ Maven project để generate Maven Archetype project đều được.

Tạo mới Maven Archetype project

Trong bài viết này, mình sẽ sử dụng Eclipse IDE để làm việc với Maven Archetype project.

Mình sẽ tạo mới một Maven project sử dụng một Maven Archetype của Maven để generate Maven Archetype project 🙂

Maven Archetype này có tên là maven-archetype-archetype:

Khai báo thông tin project:

Kết quả:

Các tập tin, thư mục nằm trong thư mục src/main/resources/archetype-resources sẽ nằm trong project mà chúng ta generate từ Maven Archetype project. Ví dụ, nếu bây giờ, các bạn chạy “mvn clean install” cho project này (các bạn nên sử dụng command line để chạy, chạy trong Eclipse có thể sẽ có issue liên quan đến “${maven.home} is not specified as a directory”) của Maven plugin, sau đó vào thư mục target/test-classes/projects/id-basic/project, các bạn sẽ thấy một project mới được generate từ Maven Archetype project của chúng ta:

Import Maven project này sử dụng một IDE khác như IntelliJ, các bạn sẽ thấy kết quả như sau:

Bây giờ, chúng ta sẽ thử hiện thực Maven Archetype project theo ý của mình nhé!

Hiện thực Maven Archetype project

Để lấy ví dụ cho bài viết này, mình sẽ hiện thực một Spring MVC project dựa trên project template của Spring Tool Suite 3, trong bài viết về Tạo ứng dụng web sử dụng Spring bằng Spring Legacy Project trong Spring Tool Suite 3. Nói cho các bạn hiểu thì Spring MVC project template của Spring Tool Suite 3 đang sử dụng những version cũ của Spring và các library khác, mỗi khi tạo mới project Spring MVC sử dụng nó, mình phải chỉnh sửa lại cho phù hợp với thời điểm hiện tại.

OK, bắt đầu nhé các bạn. Các bạn có thể đọc lại bài viết Tạo ứng dụng web sử dụng Spring bằng Spring Legacy Project trong Spring Tool Suite 3 để hiểu rõ những tập tin thư mục mà mình cần tạo trong Maven Archetype project ví dụ trong bài viết này. Project ví dụ của bài viết trên, mình cũng đã push lên GitHub tại https://github.com/huongdanjavacom/huongdanjava.com/tree/master/spring-mvc-example.

Đầu tiên, chúng ta cập nhập tập tin pom.xml ở thư mục src/main/resources/archetype-resources của Maven Archetype project.

Mình sẽ replace bằng nội dung của tập tin pom.xml trong project spring-mvc-example ở trên, xong chỉnh sửa lại version của các library, framework sử dụng latest version.

Nội dung của tập tin pom.xml của Maven Archetype project lúc này 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 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.huongdanjava</groupId>
<artifactId>springmvc</artifactId>
<name>spring-mvc-example</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>

<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>

<org.springframework-version>5.3.9</org.springframework-version>
<org.aspectj-version>1.9.7</org.aspectj-version>
<org.slf4j-version>1.7.32</org.slf4j-version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>

<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>

<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>

<!-- @Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>

<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>

<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.10</version>
<configuration>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
<additionalBuildcommands>
<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
</additionalBuildcommands>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<mainClass>org.test.int1.Main</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.43.v20210629</version>
<configuration>
<webApp>
<contextPath>/springmvc</contextPath>
</webApp>
<httpConnector>
<port>8585</port>
</httpConnector>
</configuration>
</plugin>
</plugins>
</build>
</project>

Vấn đề chúng ta cần sửa để cho người dùng khi sử dụng có thể generate groupId, artifactId, version theo nhu cầu của họ là thay đổi cấu hình groupId, artifactId, version trong tập tin pom.xml này.

Chúng ta sẽ định nghĩa 3 properties là ${groupId}, ${artifactId}, ${version} rồi thay thế groupId, artifactId, version trong tập tin pom.xml bằng những properties này, như sau:

<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 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<name>${artifactId}</name>
<packaging>war</packaging>
<version>${version}</version>

...
</project>

Giá trị của các properties này sẽ được người dùng nhập lúc generate project của họ từ Maven Archetype project của chúng ta các bạn nhé.

Tiếp theo, chúng ta sẽ copy class HomeController, package com.huongdanjava.springmvc trong project spring-mvc-example, bỏ vào thư mục src/main/resources/archetype-resources/src/main/java của Maven Archetype project.

Khi generate project sử dụng Maven Archetype, người dùng có thể đặt package name theo tên họ muốn. Câu hỏi đặt ra là làm sao Maven Archetype project của chúng ta có thể generate đúng package mà người dùng muốn. Solution ở đây là chúng ta sẽ khai báo sử dụng properties ${package} để làm điều này.

Ví dụ với class HomeController thì sau khi copy, mình sẽ sửa dòng code khai báo package như sau:

package $package;

import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
* Handles requests for the application home page.
*/
@Controller
public class HomeController {

private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

/**
* Simply selects the home view to render by returning its name.
*/
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);

Date date = new Date();
DateFormat dateFormat =
DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);

String formattedDate = dateFormat.format(date);

model.addAttribute("serverTime", formattedDate);

return "home";
}

}

Nếu Maven Archetype project của các bạn có những sub-package nữa, ví dụ như trong project spring-mvc-example của mình, có thêm một package là com.huongdanjava.mvc.test, thì class nằm trong package com.huongdanjava.mvc.test này, cần khai báo dòng code package như sau:

package ${package}.test;

Trong Maven Archetype project ví dụ của mình, class App không cần thiết nữa nên mình sẽ xoá nó đi.

Đối với tập tin log4j.xml trong thư mục src/main/resources thì mình sẽ tạo mới thư mục resouces trong thư mục src/main/resources/archetype-resources/src/main của Maven Archetype project, để copy tập tin này qua.

Để copy các tập tin thư mục trong thư mục webapp của project spring-mvc-example, mình cũng sẽ tạo mới thư mục webapp trong thư mục src/main/resources/archetype-resources/src/main của Maven Archetype project.

Trong thư mục src/main/resources/archetype-resources/src/main/webapp/spring/appServlet có tập tin servlet-context.xml, có khai báo một cấu hình về component-scan của Spring framework, base-package liên quan đến project mà người dùng sẽ generate nên mình sẽ sửa lại sử dụng propery ${package} như sau:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->

<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />

<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the 
${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />

<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views 
directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>

<context:component-scan base-package="${package}" />

</beans:beans>

Class AppTest trong thư mục src/main/resources/archetype-resources/src/test/java không cần nữa, các bạn có thể remove nó đi nhé.

Sau khi đã có những resource cần thiết cho Maven project sẽ được generate, các bạn cần cập nhập tập tin archetype-metadata.xml nằm trong thư mục src/main/resources/META-INF/maven.

Tập tin này dùng để định nghĩa các tập tin, thư mục sẽ được generate thành project mà người dùng muốn. Mặc định thì nội dung của tập tin này như sau:

<?xml version="1.0" encoding="UTF-8"?>
<archetype-descriptor
xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd"
name="${artifactId}">

<fileSets>
<fileSet filtered="true" packaged="true">
<directory>src/main/java</directory>
</fileSet>
<fileSet filtered="true" packaged="true">
<directory>src/test/java</directory>
</fileSet>
</fileSets>
</archetype-descriptor>

Đã có thư mục src/main/java và src/test/java được định nghĩa sẵn, chúng ta cần cấu hình thêm cho thư mục src/main/webapp nữa:

<?xml version="1.0" encoding="UTF-8"?>
<archetype-descriptor
xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd"
name="${artifactId}">

<fileSets>
<fileSet filtered="true" packaged="true">
<directory>src/main/java</directory>
</fileSet>
<fileSet filtered="true">
<directory>src/main/webapp</directory>
</fileSet>
<fileSet filtered="true" packaged="true">
<directory>src/test/java</directory>
</fileSet>
</fileSets>
</archetype-descriptor>

Các bạn để ý là khi khai báo cho thư mục webapp, mình không khai báo attribute “package=true” trong tag <fileSet>, để Maven Archetype không để thư mục này trong một package.
Đến đây thì chúng ta đã hoàn thành việc hiện thực một Maven Archetype project rồi đó các bạn!

Các bạn có thể chạy lại “mvn clean install” rồi refresh lại project đã import trong IDE như mình ở trên, các bạn sẽ thấy kết quả giống mình như sau:

Chạy “mvn clean jetty:run” cho project này, các bạn sẽ thấy kết quả giống như mình làm trong bài viết Tạo ứng dụng web sử dụng Spring bằng Spring Legacy Project trong Spring Tool Suite 3 đó các bạn.

One more thing, các bạn sẽ tự hỏi là groupId, artifactId và version của generated project trong ví dụ của mình lấy ở đâu? Nó nằm trong tập tin archetype.properties ở thư mục src/test/resources/projects/it-basic đó các bạn! Nội dung của tập tin này như sau:

groupId=archetype.it
artifactId=basic-project
version=0.1-SNAPSHOT
package=it.pkg

Tập tin này được maven-archetype-plugin sử dụng để generate project ví dụ cho chúng ta đó các bạn.

Bài viết gốc được đăng tải tại huongdanjava.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ề HTTP Polling và SSE

http polling vs sse
Tìm hiểu về HTTP Polling và SSE

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

Hôm nay, nhân tiện có task research call API bằng thằng AFNetworking bên Objective C. Lướt qua thấy một số kĩ thuật giao tiếp (Client / Server) mới. Đọc ra mới thấy có Library AFRocketClient sử dụng Server sent events (SSE), rồi thì là HTTP Polling, Long Polling. Đúng là đụng vào cái nào cũng brand new, nên có tìm hiểu đôi chút, viết bài này chia sẻ chút kiến thức nhỏ nhoi.

Do chưa bắt tay code thực tế, nên mình chỉ chú trọng vào bản chất, không có code ví dụ, mong anh em thông cảm.

  Cách làm HTTPS hoạt động trên local trong 5 phút
  Cấu hình HTTPS Server cho NGINX (SSL Certificate trong NGINX)

1. HTTP Regular – Kiểu truyền thống (anh hỏi thì em thưa).

Đối với HTTP kiểu truyền thống, khi anh (client) đưa ra câu hỏi, yêu cầu có thể “ấy” một cái được không?. Nếu em đồng ý, lập tức trả lời CÓ, ngược lại thì nói là KHÔNG. Chả hề chần chừ suy nghĩ.

HTTP Regular

Vấn đề đối với kiểu truyền thống này là hai chữ lập tức. Thời nay đã hiện đại rồi, vừa mới 8h02 client (anh) gửi request cho em (server) thì sau 2 mi li se cần ba má server (em) gửi request với nội dung đồng ý.

Vậy là chỉ tại 2 mi li se cần mà client (anh) lại nhận được câu trả lời là “éo”.

Thiệt tình là cay cú vl, từ đó kỹ thuật HTTP Polling ra đời. Mục đích nhằm gia tăng khả năng kết đôi, giúp tăng tỉ lệ sinh, giảm tỉ lệ tử, … lạc đề 😅

2. HTTP Polling – Kiểu siêng năng (cứ sau 5 phút lại hỏi, bất kể em có đồng ý không, hết 5 phút lại hỏi).

Chính vì kiểu regular hỏi phát bị từ chối luôn, nên Polling ra đời. Siêng năng cần cù gửi request sau một thời gian nhất định, vấn đề bất kể phản hồi (responsecó dữ liệu hay không?. Cụ thể ra là kệ em có trả lời có hay là không?. Nếu ỉm (timeout) thì cứ 5 phút anh vẫn hỏi 1 lần (đẹp trai không bằng chai mặt) 😞 😞 😞

Chính vì nguyên nhân đó, kĩ thuật này sẽ gây lãng phí lớn, tiêu chí realtime cũng không thật sự ổn định. Chính vì cái thái độ chày cối bất cần này, kĩ thuật HTTP Long Polling ra đời.

Hỗ trợ: Kĩ thuật này hoạt động ở tất cả browser có Javascript được bật.

Lưu ý: Kỹ thuật này là loại kĩ thuật gây lãng phí lớn, nếu thời gian giữa mỗi lần gửi request quá ít, gánh nặng về băng thông và xử lí request sẽ dồn nặng lên server. Ngay lúc này, một cuộc tấn công DDos bùng phát, đảm bảo server sẽ quá tải và chết bất đắc kì tử. Vì vậy, nếu không cần thiết, nên thận trọng khi sử dụng HTTP Polling

3. HTTP Long Polling – Kiểu chai mặt (anh hỏi nhưng phải chờ em hỏi ba má mới trả lời anh được).

Mới nhìn sơ thì phương thức này đập vào mặt là một chữ Long, vấn đề là cái gì Long (pen!s thì khỏi nói :v). Đáng buồn thay, kỹ thuật này lại nhấn mạnh vào thời gian chờ đợi dài.

Vậy kĩ thuật này hoạt động như thế nào?

Nhìn chung, client (anh) sẽ gửi request (yêu cầu) liên tục lặp lại giữa các khoảng thời gian dài (long). Hình dung ra theo 4 bước dưới đây:

  • Bước 1: Send request – anh hỏi em cho anh “ấy” cái được không?
  • Bước 2: Server event – em mở một luồng suy nghĩ (idle event – khoảng chờ), chờ sự hiện phản hồi từ một client khác (ba má). Vấn đề là anh (client) không thể chờ em cả đời -> Next step.
  • Bước 3: Nếu hết thời gian chờ, ba má chưa có câu trả lời thì em (server) vẫn phản hồi cho anh kết quả là “đéo”.
  • Bước 4: Send request again – sau khi nhận được câu trả lời (dù là yes hay no) thì anh (client) vẫn tiếp tục gửi lại request)

Bảng so sánh độ trễ và tốc độ load giữa Polling và Long Polling

Khi nào thì nên sử dụng kiểu chai mặt (HTTP Polling)?

So với kiểu truyền thống, kĩ thuật này mang màu sắc chai mặt (gửi request hoài hoài), nhưng cũng không phải là không có ưu điểm. Trường hợp user (ba má client) chỉ có mỗi một mụn con, đã gần đất xa trời, luôn mong ngóng có đứa nào đó chấp nhận cái request của con trai rồi mới nhắm mắt xuôi tay thì kĩ thuật này nên được áp dụng. Ưu điểm của HTTP Long polling là nó đáp ứng Realtime (thời gian thực), với độ trễ (Latency) gần như bằng Zero (0). Khi em trả lời là có, ngay lập tức anh (client) có câu trả lời sau 0 mi li se cần, sau đó ba má anh cũng biết, có thể thanh thản ra đi.



Nghiêm túc lại thì HTTP Polling sẽ cung cấp một API ổn định, mức độ phản hồi khi có thông tin mới rất nhanh, đáp ứng tiêu chí realtime.


Lưu ý: một nhược điểm tương đối cố hữu đối với HTTP Polling là chiếm băng thông (bandwidth), vì vậy cần phải cân nhắc chu kì gửi request không nên diễn ra quá nhanh.

Con nào mà cứ 2 phút lại hỏi “cho anh ấy một cái”, nó lại chả block

4. Server Sent Events – Kiểu dồn dập (anh hỏi một lần, em trả lời liên tục, chắc em cũng thích “ấy” 🤤 ) .

Kỹ thuật này nhìn chung là giống HTTP Polling. Tuy nhiên có đôi chút khác biệt ở chỗ, client (anh) chỉ hỏi có một lần (kết nối chỉ mở một lần duy nhất), sau đó em (server) do quá hăng hái, nhiệt tình, nên cứ 3s em lại trả lời một lần rằng “ba má em chưa chịu”. Việc giao tiếp này gần như là một chiều (one way comminucation). Chiều từ server tới client.

Mới đầu đọc tới đây, mình cũng như anh em, đều phát sinh ý nghĩ rằng sao lại có cái kỹ thuật kết nối dở người kiểu này?.

Mục đích nó sinh ra là gì?

Sau một hồi research hăng hái, cuối cùng mình cũng có câu trả lời. Thực sự thì SSE (Server sent events) lại thật sự hữu ích đối với các yêu cầu dữ liệu phản hồi real time liên tục. Ví dụ như ứng dụng xem vị trí máy bay, ta chỉ gửi request xem lộ trình của máy bay A380 một lần, sau đó, server sẽ liên tục trả về tọa độ (latitude, longitude) của máy bay.

5. Kết luận

Túm cái quần lại, bài viết này cho các bạn một cái nhìn khách quan, vui vẻ về một số kỹ thuật mới (chắc có khi chỉ mới đối với mình 😂😂) sử dụng trong giao tiếp giữa client và server. Tuy nhiên, còn một thiếu sót nhỏ là chưa đề cập tới Websocket. Thời gian tới, mình sẽ viết riêng một bài mới về Websocket và so sánh giữa Websocket và SSE (Server sent events).

Cảm ơn các bạn đã đọc bài của mình, nếu bài viết của sai sót về nội dung, các bạn có thể comment phía dưới.

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

Thiết Kế Đồ Họa Và Những Tư Chất Cần Thiết Của Một Nhà Thiết Kế Đồ Họa

học thiết kế đồ họa cần những gì
Thiết Kế Đồ Họa Và Những Tư Chất Cần Thiết Của Một Nhà Thiết Kế Đồ Họa

Thiết kế đồ họa là một trong những ngành nghề đã nằm trong top các công việc hấp dẫn nhân sự cũng như có thu nhập cao hiện nay. Tuy nhiên, có phải bất cứ ai cũng phù hợp với ngành nghề này hay học thiết kế đồ họa cần những gì khác nữa? Bài viết dưới đây sẽ phần nào giúp bạn giải tỏa những thắc mắc xoay quanh ngành thiết kế đồ họa nhé!

học thiết kế đồ họa cần những gì
Thiết kế đồ họa và các vấn đề liên quan

Tại sao ngành thiết kế đồ họa trở nên quan trọng trong cuộc sống ngày nay?

Không quá khó để bạn bắt gặp rất nhiều hình ảnh khác nhau xuất hiện trong tầm mắt mỗi ngày. Trên đường đi làm, đi học, trên xe bus, trên các tòa nhà, các biển quảng cáo,… luôn có sự xuất hiện dày đặc của các hình ảnh mang tính chất giới thiệu, quảng cáo và truyền tải thông điệp. Một nội dung hay để nhanh chóng tiếp cận khách hàng luôn cần có những hình ảnh đẹp. Một hình ảnh sản phẩm tốt, một hình ảnh nắm bắt đúng tâm lí khách hàng với các thông tin cần, luôn là yếu tố quan trọng để giữ chân người đọc tìm hiểu thêm về nội dung sản phẩm.

Xem thêm TOP 7 Ngành Nghề Thu Hút Nhân Lực Trong Tương Lai

Thêm vào đó, thiết kế đồ họa muốn thành công không chỉ đáp ứng được đúng nội dung truyền tải mà còn phải có tính thẩm mỹ cao. Vậy nên không khó hiểu khi tính thẩm mỹ cũng như màu sắc được yêu cầu rất cao với nhà thiết kế đồ họa – graphic designer. Một bức ảnh đẹp không chỉ truyền tải được ý nghĩa sản phẩm mà còn làm nổi bật được hình ảnh của công ty. Thông qua hình ảnh, người xem có thể dễ dàng nhận ra đây là màu sắc, là cá tính, là tiếng nói, là nội dung của công ty. Đó chính là thành công của đội ngũ thiết kế đồ họa.

Bên cạnh hình ảnh, thiết kế đồ họa còn có thể đảm nhận cả công việc thiết kế hình ảnh cho website, xây dựng landing page bắt mắt và thu hút người xem. Một landing page thu hút và dễ dàng sử dụng chắc chắn sẽ giúp khách hàng ở lại trên website lâu hơn và kích cầu mua sắm, sử dụng dịch vụ nhiều hơn. Làm được điều này chính là thành công của một nhà thiết kế đồ họa.

Học thiết kế đồ họa cần những gì?

Vậy để làm tốt trong ngành thiết kế đồ họa, bạn sẽ cần chuẩn bị những gì?

Một tinh thần và động lực luôn sẵn sàng cho việc học hỏi

Để trở nên thăng hoa trong công việc sau này, con đường học hỏi và theo đuổi sự nghiệp khi vừa mới bắt đầu của các nhà thiết kế đồ họa thực sự không dễ dàng. Bạn sẽ phải đối mặt với việc sáng tạo ý tưởng một cách liên tục mà không tạo sự nhàm chán, bạn phải xử lý và làm việc với nhiều phòng ban khác nhau để hoàn tất thông tin cần thiết cho công việc của mình.

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

Và còn vô vàn vấn đề khác mà bạn sẽ gặp phải trong suốt quá trình làm việc của mình. Ngoài ra, một nhà thiết kế đồ họa cũng cần liên tục tự học, tự trau dồi kiến thức cho mình để sáng tạo ra những hình ảnh không chỉ đẹp mà còn mới mẻ và bắt kịp xu hướng. Do đó, hãy chuẩn bị cho mình một tâm lí và động lực sẵn sàng đối diện với mọi khó khăn và chông gai trong công việc. Không ngại dành thời giờ để học hỏi và trau dồi liên tục chính là chìa khóa cho sự thành công.

thiết kế đồ họa
Động lực mạnh mẽ là một trong những yếu tố quan trọng của các nhà thiết kế đồ họa

Chấp nhận làm việc nhiều hơn so với mức 8 tiếng một ngày

Như đã chia sẻ ở bên trên, công việc mà một nhà thiết kế đồ họa phải làm việc mỗi ngày là rất nhiều, do đó đừng mong chờ tìm được một công việc chỉ làm đúng 8 tiếng mỗi ngày nếu bạn theo đuổi nghiệp đồ họa. Thời gian làm việc của một nhà thiết kế đồ họa thật ra không luôn luôn gắn liền với làm thêm giờ, nếu bạn biết cách sắp xếp công việc cũng như tần suất hình ảnh phải làm mỗi ngày sẽ quyết định đến thời gian mà bạn làm việc.

Đặc biệt, với những lúc cần phải hoàn thành kịp thời hạn, việc chạy quá nhiều ý tưởng có thể khiến bạn trở nên khó khăn trong việc sáng tạo ra những hình ảnh, bố cục mới. Thậm chí, với những dự án lớn, bạn sẽ phải “căng mình” hoàn toàn để đáp ứng kịp công việc và hình ảnh đồ họa phải bàn giao mỗi ngày cho các team khác làm việc. Có một “tinh thần thép” trước áp lực trong công việc là điều cần thiết với các nhà thiết kế đồ họa.

  Bí kíp tìm dự án cho anh em mới vào nghề freelancer thiết kế website wordpress
  30 tiện ích Chrome (extensions) cho Designer và Developer

Lựa chọn chuyên môn phù hợp với năng lực và sở thích bản thân

Không chỉ với thiết kế đồ họa mà với bất kì ngành nghề nào cũng thế, ngành nghề thì rất rộng nhưng chuyên môn sẽ khác nhau, vậy nên xác định rõ ràng lĩnh vực mình muốn làm việc sẽ giúp đỡ rất nhiều trong quá trình làm việc của bạn. Để trở thành thật sự giỏi trong lĩnh vực mà mình theo đuổi, bạn cần tìm ra xem đâu là điều mình mong muốn để dành thời gian nhiều hơn cho việc học hỏi và trau dồi.

Thiết kế đồ họa nói chung là một lĩnh vực rộng lớn và đa dạng các lĩnh vực chuyên môn khác nhau như: thiết kế web, thiết kế đồ họa chuyển động, thiết kế hình ảnh tạp chí, bìa sách, thiết kế hình ảnh quảng cáo,… Mỗi lĩnh vực khác nhau sẽ đòi hỏi những kiến thức, kỹ năng khác nhau, do đó đừng nên vội vàng trong việc lựa chọn mà bạn có thể thử qua tất cả các lĩnh vực này để xem đâu mới là chuyên môn mình thật sự yêu thích và có thể làm tốt. Lắng nghe ý kiến từ người khác cũng là một ý kiến hay ho mà bạn có thể lựa chọn.

Mỗi ngành nghề đều có những đòi hỏi riêng và yêu cầu riêng cho người trong ngành. Hãy làm hết sức của bản thân để thật sự đạt được những điều mà mình mong muốn. Hi vọng bài viết này đã mang đến cho người đọc một cái nhìn tổng quan về ngành thiết kế đồ họa cũng như việc học thiết kế đồ họa cần những gì. Đón đọc nhiều bài viết hấp dẫn khác cùng TopDev bạn nhé!

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

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

Lương lập trình viên có thể đạt 100 triệu/tháng: Tin được không?

lương lập trình viên
Lương lập trình viên có thể đạt 100 triệu/tháng: Tin được không?

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àm trong giới lập trình thì mình tin chắc một điều là đã có không ít lần anh em nghe kể về những người có mức lương khủng.

Ở đây mình đang nói đến những người làm thuần về kỹ thuật, chứ không nói đến các vị trí cấp quản lý cao hơn. Vì nếu đã lên các vị trí cấp quản lý thì kiểu gì lương cũng cao rồi !

Và tất nhiên, còn một điều nữa là mình chỉ chia sẻ về ngành IT thôi, các ngành khác có thể sẽ có mức thu nhập cao hơn hoặc thấp hơn, cái này nếu thích thì các bạn tự tìm hiểu thêm nhé

  4 mẹo deal lương như ý với vị trí Product Manager
  5 điều NÊN và KHÔNG NÊN khi review tăng lương mà lập trình viên nào cũng nên biết!

#1. Đặc thù công việc?

Mình biết là mỗi ngành nghề thì đều có những đặc thù riêng và đặc thù đó quyết định ít nhiều tính chất của công việc.

luong-cua-lap-trinh-vien (2)

Đối với ngành IT, mà cụ thể hơn là các lập trình viên thì đặc thù công việc chính là sự tư duy. Tư duy trong giải quyết vấn đề, tư duy trong xây dựng phát triển sản phẩm…

Chính vì công việc đòi hỏi phải suy nghĩ nhiều, mặc dù không nặng về chân tay nhưng nhiều khi anh em lập trình viên chúng ta sẽ cảm thấy cực kỳ stress và áp lực, mình tin là ai trong ngành này cũng vậy cả thôi !

Không phải ai cũng có thể chịu được áp lực của ngành lập trình này trong nhiều năm liền, chứ chưa muốn nói là làm được việc hay không.

Và chính vì đặc thù đó mà để đào tạo hoặc tuyển được một lập trình viên “cứng”, có thể làm ĐƯỢC VIỆC thì thực sự không phải là dễ.

Khái niệm OT (Overtime) gần như cũng được xuất phát từ các công ty công nghệ, khi mà khối lượng công việc quá nhiều nếu không làm thêm giờ thì không thể xong được.

Với đặc thù công việc áp lực là như vậy, thử hỏi nếu mức lương không tương xứng thì liệu có ai chấp nhận đánh đổi để làm hay không?

Đây là sự thật và là minh chứng rõ nhất cho câu nói làm bao nhiêu hưởng bấy nhiêu. Không có chuyện làm thì lười mà vẫn có ăn đâu nhé các bạn.

Trải nghiệm công cụ tính lương gross to net chuẩn tại TopDev

#2. Những áp lực mà họ phải chịu?

luong-cua-lap-trinh-vien (5)

Nói về áp lực của anh em lập trình viên thì mình đã từng có một bài viết riêng về chủ đề này rồi, các bạn có thể tham khảo lại bài viết này để biết thêm về những áp lực đó: Những áp lực khi HỌC và LÀM IT [Lập Trình Viên]

Vậy áp lực thì liên quan gì đến việc lương cao hay thấp? Cá nhân mình thấy thì hầu như những công việc với mức thu nhập ổn thì đều áp lực cả.

Làm IT cũng tùy dự án, tùy công ty mà áp lực công việc là cao hay thấp. Nhưng có một điều chắc chắn là nếu bạn làm IT mà chịu được áp lực thì khi đó, mức lương của bạn không thể thấp được.

Tại sao mình lại có sự so sánh như vậy, bởi thực tế nhiều người chịu được áp lực nhưng lương đâu có cao đâu?

Nói đến đây thì mình lại phải tiếp tục chia nó ra làm 2 đối tượng, đó là: Người chịu được áp lực và người phải chịu áp lực.

Người chịu được áp lực là người biết biến áp lực công việc thành động lực, biết biến khó khăn thành cơ hội để tự nâng cao giá trị bản thân.

Ngược lại, người phải chịu áp lực là những người làm các công việc bản thân không mấy yêu thích nhưng vẫn phải làm. Họ quen với áp lực và đôi khi “thờ ơ” hoặc “miễn nhiễm” với áp lực. Dù công việc đó có vội đến đâu họ vẫn thảnh thơi làm.

Và tất nhiên, là một lập trình viên, nếu người nào chịu được áp lực tốt thì người đó ắt sẽ có mức lương tương xứng với trí tuệ và công sức mà họ bỏ ra.

#3. Xu hướng

luong-cua-lap-trinh-vien (1)

Nếu các bạn để ý thì trong những năm trở lại đây, do sự phát triển của cuộc cách mạng công nghiệp 4.0 thì các ngành học liên quan đến kỹ thuật, công nghệ cao đang rất được quan tâm.

Song song với đó là số lượng các công việc liên quan đến các lĩnh vực này cũng tăng lên rất nhiều và đòi hỏi một đội ngũ nhân lực đủ tiêu chuẩn để đáp ứng được công việc.

Chúng ta có thể liên hệ một chút sang thị trường hàng hóa. Nếu nói một cách thẳng thắn thì sức lao động cũng là một dạng hàng hóa.

Mà đã là hàng hóa thì chắc chắn phải buôn bán được và nếu loại hàng hóa đó càng quý hiếm, càng khó để có được thì nó càng đắt.

Đến đây chắc các bạn có thể hình dung được là tại sao lương của lập trình viên thường cao hơn một số ngành khác rồi đúng không.

Đặc biệt là các bạn sinh viên có khả năng kỹ thuật tốt thì việc đạt mức lương 20-25 triệu/tháng là hoàn toàn có thể, chứ chưa muốn nói là có nhiều bạn giỏi đặc biệt thì con số này còn cao hơn rất nhiều lần.

Có thể lương của lập trình viên nói riêng và của các bạn làm về công nghệ nói chung cao hơn mặt bằng chung một phần cũng phần do ảnh hưởng của xu hướng thị trường việc làm.

#4. Nhu cầu từ thị trường

luong-cua-lap-trinh-vien (3)

Thị trường mà mình muốn nói đến ở đây là thị trường lao động, đặc biệt là thị trường lao động với hàm lượng chất xám cao.

Mà đại diện tiêu biểu ở đây là những người làm trong giới lập trình, là các lập trình viên, kỹ sư phần mềm, chuyên viên hệ thống…

Chúng ta đều biết rằng, quy luật cung cầu của thị trường đó là: Nếu cung mà nhỏ hơn cầu thì giá trị mặt hàng sẽ bị tăng lên, hay nói cách khác là hàng hóa đó sẽ tăng giá.

Nói vậy để chúng ta hiểu rằng, nhu cầu thị trường về nguồn nhân lực chất lượng cao trong các lĩnh vực công nghệ đang tăng lên rất nhanh.

Trong khi các nguồn cung chất lượng thì lại rất ít và hầu như không đủ tiêu chuẩn. Rất nhiều trường đại học mở ra các ngành, chuyên ngành đào tạo nhân lực trong lĩnh vực công nghệ nhưng nhìn chung chất lượng không thực sự tốt.

Chính vì vậy, các lập trình viên nói riêng hay các kỹ sư làm trong lĩnh vực công nghệ thông tin nói chung mà có kinh nghiệm, kiến thức thì thực sự mức lương của họ là rất đáng mơ ước nếu ở Việt Nam. Và đó cũng là lý do mà nhiều người nói rằng thừa thầy thiếu thợ là như vậy !

#5. Chất lượng nhân sự

Chất lượng nhân sự đã được mình nhắc đến trong ý bên trên khi nói về nhu cầu thị trường. Vậy chất lượng nhân sự ảnh hưởng gì tới thu nhập của một người làm công nghệ, mà đại diện ở đây là các lập trình viên (dev)?

luong-cua-lap-trinh-vien (4)

Thực tế thì Việt Nam xuất phát điểm là một quốc gia hàng đầu về Outsourcing, tức là một quốc gia chuyên đi “gia công phần mềm” cho các khách hàng từ nước ngoài (đặc biệt là thị trường Nhật).

Chúng ta sẽ không đánh giá việc gia công phần mềm là nên hay không nên, tốt hay không tốt khi muốn thúc đẩy sự phát triển về công nghệ của nước nhà.

Nhưng có một sự thật mà chúng ta phải thừa nhận, đó là hiện nay hầu hết các bạn sinh viên được đào tạo dù là cấp đại học hay cao đẳng thì các bạn vẫn mang cái tư duy đi làm thuê nhiều hơn là làm chủ.

Mà khi chấp nhận làm thuê thì chúng ta sẽ tự động hạ thấp chất lượng của mình xuống, không muốn cải thiện và không có ý chí thăng tiến mạnh mẽ.

Và chính cái tư duy đó sinh ra hệ lụy đó là chất lượng nhân sự không cao một cách đồng đều. Nếu các bạn để ý, nhiều bạn sinh viên mới ra trường làm lập trình viên nhưng chỉ được khoảng 4-6 triệu.

Có thể nói chất lượng nhân sự trong lĩnh vực công nghệ là một trong những lĩnh vực có chất lượng không đồng đều nhất tại Việt Nam.

Có những người rất giỏi với mức lương cực “khủng”, nhưng cũng có những người mức lương chỉ đủ chi tiêu sinh hoạt cơ bản là hết.

#6. Kết luận

Kết thúc bài viết này mình muốn khẳng định là nếu bạn là một lập trình viên bình thường, đặc biệt là lại chỉ làm việc ở Việt Nam thì rất khó mà đạt được mức lương 100 triệu/tháng.

Nhưng ngược lại, nếu bạn có khả năng kỹ thuật tốt, là người giỏi chịu được áp lực và ham học hỏi thì mình tin chắc một điều là các bạn cũng có cơ hội với mức lương 100 triệu/tháng. Hẹn gặp lại các bạn trong các bài viết tiếp theo nhé.

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 4 – Sử dụng tulsi generate Xcode project

bazel
Bazel Bazel 4.1.0: Bài 4 – Sử dụng tulsi generate Xcode project 4.1.0: Bài 4 – Sử dụng tulsi generate Xcode project

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

Trong bài trước chúng ta đã build thành công ra file .ipa từ các file source bằng bazel.

Ở bài này chúng ta sẽ generate các file đó thành 1 project xcode để debug được.

  Cách sử dụng lệnh Xcopy trong CMD (Command Prompt)
  Hướng dẫn sử dụng Xcode và Tạo project Xcode

Đầu tiên bạn tải code tulsi về bằng cách gõ lệnh trên terminal:

https://github.com/bazelbuild/tulsi

Vào thư mục tulsi bằng lệnh:

cd tulsi

Cấp quyền chạy cho file build_and_run.sh:

chmod +x build_and_run.sh

Kiểm tra xcode build version bằng cách chọn Xcode -> preference:

Ở máy tôi là 12.5.1. Vào sửa file build_and_run.sh:

Tùy vào máy bạn mà sửa cho phù hợp.

Gõ tiếp lệnh sau để generate tulsi:

./build_and_run.sh

Đợi 1 lúc tulsi mở lên như hình:

Nếu có lỗi không tìm thấy bazel vui lòng cài nó ở bài 1.

Chọn vào Create new project…

Đặt tên project: DemoUrlRequest(hoặc tên tùy ý do bạn)

Chọn tiếp vào dòng Choose the WORKSPACE file for this project và chọn như sau:

Nhấn next. Sau đó chọn vào nút +:

Chọn tiếp file BUILD như hình:

Chọn phiên bản bazel để build. Bấm Command + shift + . để hiển thị file ẩn của hệ thống. Chọn tiếp bazel như hình:

Ở tab Config bấm nút + và lưu như hình:

Sau đó sẽ hiển thị và chọn như sau:

chọn next:

Chọn tiếp như hình và bấm Save:

Lưu với tên XcodeTusiDemo(hoặc tùy ý). Bấm tiếp generate:

Sau đó tulsi mở Xcode như hình và build:

Bấm vào Get URL contents như hình là bạn đã tạo thành công.

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

Http Methods: thất tinh bắc đẩu trận

http methods
Http Methods: thất tinh bắc đẩu trận

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

Trung Hoa quốc, Toàn chân giáo, 12/06/2018. Http Methods – bá chủ võ lâm.

Giáo chủ phái toàn chân Vương Trùng Dương, trong khẩu quyết truyền cho môn đệ có đoạn viết:

Các con, nay ta đã nghĩ ra “Thất tinh bắc đẩu trận là siêu cực trận đồ, để HTTP Methods có thể hùng cứ bốn phương trong làng IT, 7 người các con phải tuyệt đối kiên trì luyện tậpnắm vững bản chất của các vì tinh tú này.

GET, POST, PUT, HEAD, DELETE, PATCH, OPTIONS đều nhất mực nghe lời sư phụ, cố gắng tu luyện, cuối cùng đã thành 7 vì sao sáng, soi chiếu và bảo vệ HTTP Methods.

Bảy methods này phối hợp với nhau lập thành “THẤT TINH BẮC ĐẨU TRẬN” trận. Trận pháp này là xương sống cho RESTFul API. Nhờ trận pháp này mà phái RESFUL API đã bá chủ võ lâm, hùng cường thiên hạ.

  Cách làm HTTPS hoạt động trên local trong 5 phút
  Cấu hình HTTPS Server cho NGINX (SSL Certificate trong NGINX)
http_methodsThất tinh bắc đẩu trận – hội chiếu phò trợ HTTP Methods.

Hãy cùng Kieblog tìm hiểu từng vị tinh tú trong bộ thất tinh này nhé.

1. Tứ hành xung, ý lộn, TỨ ĐẠI CÔNG PHU

Mỗi vị học trò của Vương Trùng Dương đều cố gắng rèn cho mình được thành tựu bốn loại công phu. Tuy nhiên, do tư chất mỗi người khác nhau, nên có người thành tựu, có người thất bại. Bốn loại công phu mà mỗi methods trong HTTPMethods được đem ra đánh giá là:

  • SAFE (Độ an toàn).
  • IDEMPOTENT (Tính bất biến).
  • VISIBILITY (Tính che giấu thông tin).
  • CACHEABLE (có thể cache được).
http methods safe, idempotent, visibility và cacheable.Bảng so sánh 4 tính chất của các methods trong HTTP Methods.

1.1 SAFE

ĐỊNH NGHĨA: Một request trong http methods được xem là safe khi sau rất nhiều lần gọi, nó vẫn không làm thay đổi resource mà nó đang truy cập đến.

1.2 IDEMPOTENT

ĐỊNH NGHĨA: Một request được xem là idempotent nếu sau nhiều lần gọi, nó vẫn trả về kết quả như nhau.

Để dễ hình dung, ta có biến i khai báo bằng 100 và biến i tăng 1.

int i = 100; // idempotent
i++; // not idempotent

Thao tác gán đầu tiên được hiểu là idempotent, vì cho dù ta thực hiện câu lệnh này bao nhiêu lầngiá trị của i cũng vẫn chỉ là 100. Ngược lại, khi giá trị i++, mỗi lần gọi sẽ tăng giá trị i lên 1. Vì vậy, i không là idempotent.

Understand result as the state of the resource on the server (and bear in mind that status codes are not relevant from the idempotency point of view).

Hãy chú rằng kết quả ở đây là trạng thái của nguồn dữ liệu trên server (lưu ý rằng các mã trạng thái (200,400,403,…) ở đây không liên quan tới tính ổn định).

1.3 VISIBILITY

ĐỊNH NGHĨA: Một request trong http methods được xem là visibility khi nó không để lộ ra thông tin trên URL khi request được gửi.

Cần lưu ý rằng visibility ở đây chỉ giới hạn ở URL (phần người dùng có thể nhìn thấy được).

1.4 CACHEABLE

ĐỊNH NGHĨA: Một request được xem là cacheable khi sau lần gửi thứ nhất của request, kết quả phản hồi có thể được lưu vào một trong các loại cache trên websites (localStorage, cookies, …).

http methods cacheSơ đồ mô tả cách thức cache thông tin trên client browser

2. Thất tinh lộ diện – Http methods

2.1 GET

GET requests are the most common and widely used methods in HTTP methods and websites. Simply put, the GET method is used to retreive data from a server at the specified resource.

GET là phương thức phổ biến nhất và được sử dụng rộng rãi nhất trong HTTP methods và websites. Nói một cách đơn giản, GET là phương thức được sử dụng để truy xuất dữ liệu từ server ở một tài nguyên rõ ràng đã được chỉ định.

2.1.1 Safe – YES

Tất nhiên rồi, phương thức GET chỉ lấy, yêu cầu và truy xuất dữ liệu nên nó được xem là method an toàn nhất. Tuy nhiên, an toàn ở đây được hiểu rằng phương thức GET không làm thay đổi resources mà nó gọi tới.

Không nên nhầm lẫn tính an toàn này với việc xác thực API.

Nếu phương thức GET này cung cấp thông tin (user, password của admin) thì nó không được xem là an toàn. Vấn đề này sẽ được nói rõ hơn ở một bài viết khác về API attack.

2.1.2 Idempotent – YES

GET method luôn là idempotent, bởi vì cho dù ta có gọi hàng ngần method này tới Server thì cũng không làm thay đổi resource của nó. Chính vì lẽ này, GET luôn được đánh giá là method an toàn nhất trong 7 loại của htttp methods.

2.1.3 Visibility – NO

Khi nói tới tính che giấu thông tin khi thực hiện method. Phương thức GET không thực sự tốt, các parameter được nhìn thấy rõ trên URL. Điều này cũng đồng nghĩa với việc các param này được lưu lại trong lịch sử. Những ai tò mò muốn thay đổi cũng có thể dễ dàng thực hiện (không cần lập trình viên chuyên nghiệp – chỉ chỉnh sửa trên URL gọi tới server)

Method GET với từ khóa tìm kiếm là trump.
Method GET với request chuyển tới trang số 5 (page 5).

2.1.4 Cacheable – YES

Vì method GET đơn thuần là dể lấy dữ liệu, nên khi đã lấy xong, ta có thể cache những giá trị này lại. Việc lưu trữ có thể là (Local Storage, Cookies, …)

2.2 POST

POST: Submits data to be processed to a specified resource.

POST: Gửi data lên server để xử lí ở một tài nguyên cố định.

2.2.1 Safe – NO

Suy nghĩ một tí, nếu người viết web service cho API không quản lí tốt cách thức xác thực người dùng được thực hiện method POST. Một lập trình viên có thể dễ dàng tạo các parameter fake. Sau đó gửi tới server, các hình thức tấn công đã được biết tới trước đây như là Cross-Site Request Forgery

2.2.2 Idempotent – NO

Methods POST là method được sử dụng rất nhiều trong Http Methods. Tuy nhiên, tính idempotent của methods POST lại rất khó để đảm bảo. Nếu một POST được gọi để khởi tạo folder, ở lần đầu tiên -> folder được tạo. Ở lần gọi thứ 2 -> thất bại -> do folder đã được tạo.

Ngày nay, xu hướng thiết kế API càng ngày càng chú ý tới tính idempotent của các method. POST cũng không là một ngoại lệ.

2.2.3 Visibility – YES

Các tham số được gửi lên sử dụng method post sẽ không để lộ ra trên URL.

2.2.4 Cacheable – NO

Phương thức POST không thể được cache lại. Mọi xử lí của chúng ta mong muốn về method cache đều được xử lí ở server. Chính vì vậy, không thể cache lại bất cứ giá trị gì ở phía client khi ta gọi method POST.

2.3 PUT

Used to create a resource, or overwrite it.

Method PUT được sử dụng để tạo tài nguyên, hoặc ghi đè nó.

2.3.1 Safe – NO

Do method PUT thực hiện cập nhật trạng thái tài nguyên. Nên nó được đánh giá là không an toàn.

2.3.2 Idempotent – YES

PUT APIs are used to update the resource state. If you invoke a PUT API N times, the very first request will update the resource; then rest N-1 requests will just overwrite the same resource state again and again – effectively not changing anything.

PUT sử dụng để cập nhật trạng thái của tài nguyên. Nên nếu ta gọi method PUT n lần, lần đầu tiên sẽ cập nhật trạng thái tài nguyên. Tiếp đến, N – 1 request tiếp theo sẽ thực hiện lặp đi lặp lại – không thay đổi gì.

2.3.3 Visibility – YES | Cacheable – NO

Method PUT giống với method POST ở 2 tính chất này. Nó ẩn đi các parameter gửi đi ở URL – Do không lấy dữ liệu gì ở server nên không thể cache lại các kết quả đã lấy được.

2.4 HEAD

The HTTP HEAD method requests the headers that are returned if the specified resource would be requested with an HTTP GET method.

HEAD method sẽ trả về nội dung headers nếu tài nguyên được chỉ định gọi tới có thể lấy được bằng method GET.

2.4.1 Safe – YES

Chính vì method Head chỉ trả về thông tin của headers, nên nó được xem là an toàn.

2.4.2 Idempotent – YES

Tương tự như GET, method HEAD cũng được đánh giá là idempotent -> do sau n lần gọi giá trị của nó vẫn trả về không đổi.

2.4.3 Visibility – NO

Vì thông tin được lấy cũng nằm trong URL, nên tính che dấu thông tin của HEAD method là giống GET -> không được đảm bảo.

2.4.4 Cacheable – YES

Do thông tin được lấy về là headers, nên có thể cache lại các giá trị này cho các request tiếp theo. GET và HEAD methods đều có thể cache được.

2.5 DELETE

The DELETE method requests that the origin server delete the resource identified by the Request-URI.

Method DELETE sẽ xóa một tài nguyên nhất định ở server bằng Request-URI.

2.5.1 Safe – NO

Nếu như ở method GET, khi thực hiện thành công, ta nhìn thấy dữ liệu trả về thì method DELETE là không an toàn vì.

The client cannot be guaranteed that the operation has been carried out, even if the status code returned from the origin server indicates that the action has been completed successfully

Client không đảm bảo được rằng các thao tác mong muốn khi gửi method GET đã được thực hiện ở Server.

2.5.2 Idempotent – NO

Bản thân mình nghĩ rằng DELETE methods là không idempotent. Tuy nhiên, vấn đề này hiện vẫn đang có nhiều bàn cãi.

Lấy ví dụ, nếu lần đầu tiên chúng ta xóa đi 1 ảnh ở server, lần request tiếp theo sẽ cho ra kết quả 404 Not Found. Vì kết quả khác nhau ở các lần gọi request -> không là idempotent.

Tuy nhiên, nếu nói về trạng thái ở server:

The state on the server is the same after each DELETE call, but the response is different.

Trạng thái ở server sau mỗi lần gọi DELETE là giống nhau, chỉ khác giá trị trả về.

2.5.3 Visibility – YES | Cacheable – NO

Về visibility và cacheable, method DELETE giống với method POST.

2.6 PATCH

The PATCH method is used to apply partial modifications to a resource.

PATCH method được sử dụng để ghi đè các thông tin thay đổi.

2.7 OPTIONS

The HTTP OPTIONS method is used to describe the communication options for the target resource. The client can specify a URL for the OPTIONS method, or an asterisk (*) to refer to the entire server.

HTTP OPTIONS method sử dụng để mô tả tùy các options giao tiếp cho tài nguyên đích. client có thể tùy chỉnh URL cho OPTIONS methods, hoặc sử dụng dấu *, với ý nghĩa cho cả server.

http_methods_safeBảng so sánh mức độ an toàn của các http methods. 2 methods được đánh giá là an toàn cho server là GET và HEAD.

3. Tham khảo

Ngoài ra, để tìm hiểu thêm về bảo mật Http methods, các bạn có thể đọc thêm bài viết này ở kieblog nhé.

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

Hibernate Lifecycle

hibernate lifecycle
Hibernate Lifecycle

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

Trong Hibernate, chúng ta sẽ tạo một đối tượng từ một Entity (thực thể) và lưu nó vào cơ sở dữ liệu hoặc chúng ta lấy dữ liệu từ cơ sở dữ liệu. Ở đây, mỗi Entity được liên kết với lifecycle (vòng đời), chịu sự quản lý của Session. Đối tượng Entity đi qua các giai đoạn khác nhau của lifecycle. Trong bài viết này, chúng ta sẽ cùng tìm hiểu về các giai đoạn này.

  Hibernate Batch processing
  Hibernate là gì? Sao phải dùng nó thay JDBC?

Giới thiệu Hibernate Lifecycle

Khi nói về trạng thái (state) của object trong Hibernate, chúng ta nói một đối tượng có quan hệ với Session, nghĩa là Session có tham chiếu đến đối tượng đó, hay một cách khác là chịu sự quản lý của Session. Session được coi là một loại của Persistence Context.

Quản lý các Entity

Ngoài việc map đối tượng Java đến bản ghi trong CSDL (tức là ORM), thì có một vấn đề mà Hibernate phải care đến đó là quản lý các Entity. Cái ý niệm về “persistence context” chính là giải pháp để giúp Hibernate làm được việc này. Persistence context có thể coi là một “môi trường” chứa toàn bộ các đối tượng mà ta tạo ra và lưu vào csdl trong mỗi session.

Một Session, hay là 1 phiên, là một giao dịch, có phạm vi tùy vào từng ứng dụng. Khi ta làm việc với DB thông qua một Persistence Context, mọi thực-thể sẽ gắn vào context này, mỗi bản ghi trong DB mà ta tương tác sẽ tương ứng với 1 thực thể trong context này.

Trong Hibernate, PersistenceContext được tạo ra nhờ org.hibernate.Session . Với JPA, PersistenceContext được thể hiện thông qua class javax.persistence.EntityManagerJPA là bộ đặc tả cho việc lưu dữ liệu vào DB dành cho ngôn ngữ Java, Hibernate sau này đã tuân theo bộ đặc tả đó. Khi đó nếu dùng combo JPA-Hibernate, thì Persistence Context được tạo ra bởi EntityManager interface, thực tế sẽ là một lớp bọc lấy cái Session object ở phía dưới. Nếu ta xài thẳng Session (ko xài EntityManager) thì sẽ có nhiều phương thức cho ta xài hơn, tiện dụng hơn.

Trạng thái của các Entity

Một đối tượng trong Hibernate có 1 trong 4 trạng thái:

  • Transient (Tạm thời): Đối tượng không có quan hệ với Session hiện tại của Hibernate. Đối tượng ở trạng thái này chưa từng gắn vào context, nó không có bản ghi tương ứng trong CSDL

  • Persistent (Bền vững): Đối tượng đang liên hệ với một context, tức là với một đối tượng Session và trạng thái của nó được đồng bộ với cơ sở dữ liệu khi mà ta commit cái Session.

  • Detached (Đã bị tách riêng ra): Đối tượng đã từng có trạng thái persistent nhưng hiện tại đã không còn giữ quan hệ với Session. Nếu nó không được attached trở lại, nó sẽ bị bộ gom rác của Java quét đi theo cơ chế thông thường. Một đối tượng đang trong session muốn đạt đươc trạng thái này thì có những cách là gọi hàm evict(), close Session hoặc làm combo thao tác: serialize/deserialize.

  • Removed (Đã bị xóa): tương tự như detached nhưng bản ghi tương ứng với đối tượng này trước đó đã bị xóa khỏi database.

Sơ đồ bên dưới minh hoạ các trạng thái này:

  • (1) Transient: Trường hợp bạn tạo mới một đối tượng java từ một Entity, đối tượng đó có tình trạng là Transient. Hibernate không biết về sự tồn tại của nó. Nó nằm ngoài sự quản lý của Hibernate.
  • (2) Persistent: Trường hợp bạn lấy ra đối tượng Entity bằng method get, load hoặc find, bạn có được một đối tượng nó tương ứng với 1 record dưới database. Đối tượng này có trạng thái Persistent. Nó được quản lý bởi Hibernate. Khi đối tượng ở trạng thái persistent, tất cả các thay đổi mà bạn thực hiện đối với đối tượng này sẽ được áp dụng cho các bản ghi và các trường cơ sở dữ liệu tương ứng khi flush session.
  • (3) Transient -> Persistent: Session gọi một trong các method save, saveOrUpdate, persist, merge sẽ đẩy đối tượng Transient vào sự quản lý của Hibernate và đối tượng này chuyển sang trạng thái Persistent. Tùy tình huống nó sẽ insert hoặc update dữ liệu vào DB.
  • (4) Persistent -> Detached: Session gọi evict(..) hoặc clear() để đuổi các đối tượng có trạng thái persistent (bền vững) ra khỏi sự quản lý của Hibernate, giờ các đối tượng này sẽ có trạng thái mới là Detached (Bị tách ra).  Nếu nó không được đính (Attached) trở lại, nó sẽ bị bộ gom rác của Java quét đi theo cơ chế thông thường.
  • (5) Detached -> Persistent: Sử dụng update(..), saveOrUpdate(..), merge(..) sẽ đính trở lại các đối tượng Detached vào lại. Tùy tình huống nó sẽ tạo ra dưới DB câu lệnh update hoặc insert. Các đối tượng sẽ trở về trạng thái Persistent (bền vững).
  • (6) Persistent -> Removed: Session gọi method remove(..), delete(..) để xóa một bản ghi, đối tượng persistent giờ chuyển sang trạng thái Removed (Đã bị xóa).

Thao tác Select, Insert, Update, Delete (CRUD) với Hibernate

Trước khi đi vào chi tiết từng phương thức, các bạn nên nhớ rằng tất cả các phương thức như persist, save, update, merge, saveOrUpdate, remove, … không ngay lập tức thực thi các câu lệnh SQL UPDAT, INSERT hoặc DELETE tương ứng. Việc thực thi câu lệnh SQL thực tế vào cơ sở dữ liệu xảy ra khi commit transaction hoặc flush session.

Các phương thức được đề cập về cơ bản quản lý trạng thái của các thể hiện của thực thể bằng cách chuyển chúng giữa các trạng thái khác nhau theo vòng đời của đối tượng trong Hibernate.

Persistent

Phương thức load()

Dùng để load một đối tượng từ database lên, nó sẽ có trạng thái persistent, throw ObjectNotFoundException nếu id không tồn tại.

  • Chỉ sử dụng method load() khi chắc chắn rằng đối tượng tồn tại trong database.
  • Method load() sẽ ném ra 1 exception nếu đối tượng không tìm thấy trong database.
  • Method load() chỉ trả về 1 đối tượng giả (proxy object) nó chỉ lấy dữ liệu từ database ra khi cần tới.

* Proxy Object là 1 đối tượng giả, nó chỉ có id, các thuộc tính khác không được khởi tạo, ví dụ khi bản để FETCH_TYPE = LAZY khi mapping thì nó cũng chỉ trả về 1 proxy object.

Phương thức get()

Giống load(), tuy nhiên trả về null nếu không tồn tại.

  • Nếu không chắc chắn rằng đối tượng có tồn tại trong database không thì hãy dùng get().
  • Method get() sẽ trả về null nếu không tìm thấy đối tượng trong database.
  • Method get() sẽ truy xuất vào database ngay lập tức để lấy đối tượng thực đang tồn tại.

Phương thức find()

Cách thức hoạt động tương tự như get(). Sự khác biệt giữa find() và get() là:

  • find() là một đặc tả của JPA, get() là đặc tả riêng của Hibernate.
  • Một điểm khác biệt nữa về mặt ngữ nghĩa sử dụng: find() có thể có kết quả hoặc không, get() sẽ luôn trả về một vài thứ gì đó thậm chí là null.

Ví dụ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
try (Session session = HibernateUtils.getSessionFactory().openSession();) {
    // Begin a unit of work
    session.beginTransaction();
    System.out.println("- Loading user 1");
    User user1 = session.load(User.class, 1L);
    System.out.println("- After called ");
    System.out.println("- Fullname of user 1 " + user1.getFullname());
    System.out.println("---");
    System.out.println("- Getting user 2");
    User user2 = session.get(User.class, 2L);
    System.out.println("- After called ");
    System.out.println("- Fullname of user 2 " + user2.getFullname());
    System.out.println("---");
    System.out.println("- Finding user 3");
    User user3 = session.find(User.class, 3L);
    System.out.println("- After called ");
    System.out.println("- Fullname of user 3 " + user3.getFullname());
    // Commit the current resource transaction, writing any unflushed changes to the database.
    session.getTransaction().commit();
}

Log:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
- Loading user 1
- After called
Hibernate: select user0_.id as id1_3_0_, user0_.created_at as created_2_3_0_, user0_.fullname as fullname3_3_0_, user0_.modified_at as modified4_3_0_, user0_.password as password5_3_0_, user0_.username as username6_3_0_ from user user0_ where user0_.id=?
- Fullname of user 1 Changed 2nd
---
- Getting user 2
Hibernate: select user0_.id as id1_3_0_, user0_.created_at as created_2_3_0_, user0_.fullname as fullname3_3_0_, user0_.modified_at as modified4_3_0_, user0_.password as password5_3_0_, user0_.username as username6_3_0_ from user user0_ where user0_.id=?
- After called
- Fullname of user 2 Hibernate Example
---
- Finding user 3
Hibernate: select user0_.id as id1_3_0_, user0_.created_at as created_2_3_0_, user0_.fullname as fullname3_3_0_, user0_.modified_at as modified4_3_0_, user0_.password as password5_3_0_, user0_.username as username6_3_0_ from user user0_ where user0_.id=?
- After called
- Fullname of user 3 Hibernate Example

Như bạn thấy, thời điểm thực thi SQL của get() và load() là khác nhau. Load() chỉ gọi SQL khi cần sử dụng, SQL được thực thi ngay khi hàm get() và find() được call.

Xem ví dụ về cách xử lý khi không tìm thấy data trong cơ sở dữ liệu:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
try (Session session = HibernateUtils.getSessionFactory().openSession();) {
    // Begin a unit of work
    session.beginTransaction();
    try {
        System.out.println("- Loading user 1");
        User user1 = session.load(User.class, 1L);
        System.out.println("- After called ");
        System.out.println("- Fullname of user 1 " + user1.getFullname());
    } catch(ObjectNotFoundException e) {
        System.out.println("Could not found user with id = 1");
    }
    System.out.println("---");
    System.out.println("- Getting user 2");
    User user2 = session.get(User.class, 2L);
    System.out.println("- After called ");
    System.out.println("- User 2 is null = " + (user2 == null));
    System.out.println("---");
    System.out.println("- Finding user 3");
    User user3 = session.find(User.class, 3L);
    System.out.println("- After called ");
    System.out.println("- User 3 is null = " + (user3 == null));
    // Commit the current resource transaction, writing any unflushed changes to the database.
    session.getTransaction().commit();
}

Log:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
- Loading user 1
- After called
Hibernate: select user0_.id as id1_3_0_, user0_.created_at as created_2_3_0_, user0_.fullname as fullname3_3_0_, user0_.modified_at as modified4_3_0_, user0_.password as password5_3_0_, user0_.username as username6_3_0_ from user user0_ where user0_.id=?
Could not found user with id = 1
---
- Loading user 2
Hibernate: select user0_.id as id1_3_0_, user0_.created_at as created_2_3_0_, user0_.fullname as fullname3_3_0_, user0_.modified_at as modified4_3_0_, user0_.password as password5_3_0_, user0_.username as username6_3_0_ from user user0_ where user0_.id=?
- After called
- User 2 is null = true
---
- Finding user 3
Hibernate: select user0_.id as id1_3_0_, user0_.created_at as created_2_3_0_, user0_.fullname as fullname3_3_0_, user0_.modified_at as modified4_3_0_, user0_.password as password5_3_0_, user0_.username as username6_3_0_ from user user0_ where user0_.id=?
- After called
- User 3 is null = true

Như bạn thấy, load() sẽ throw 1 exception khi không tìm thấy dữ liệu, get() và find() sẽ return về một giá trị null khi không tìm thấy dữ liệu.

Nên sử dụng phương thức nào?

Phương thức get()/ find() thực thi SQL để lấy data ngay khi được gọi, trong khi phương thức load() trả về một proxy object, câu lệnh SQL thực sự chỉ được thực thi cần thiết. Vì vậy load() tốt hơn về performance bởi vì nó hỗ trợ lazy loading.

Phương thức load() sẽ throw exception khi không tìm thấy dữ liệu, vì vậy chúng ta chỉ sử dụng khi đã biết dữ liệu chắc chắn tồn tại.

Phương thức get()/ find() được sử dụng khi ta muốn make sure dữ liệu tồn tại trong database.

Transient –> Persistent

Phương thức persist()

Phương thức persist được thiết kế để thêm một thể hiện mới của thực thể vào persistent context, tức là chuyển một thể hiện từ trạng thái Transient sang trạng thái Persistent. Sau khi gọi persit(), đối tượng bây giờ trong persistence context, nhưng chưa được lưu vào cơ sở dữ liệu. Việc tạo ra các câu lệnh SQL INSERT sẽ chỉ xảy ra khi commit transaction, flush hoặc close session.

Ta thường sử dụng persit() khi ta muốn thêm một bản ghi vào cơ sở dữ liệu. Persit() hoạt động trên đối tượng được truyền “tại chỗ”, thay đổi trạng thái của chính nó và tham chiếu đến đối tượng tồn tại thực tế.

1
2
3
Category cat = new Category();
cat.setName("Java");
session.persist(cat); // void

Phương thức save()

Phương thức save() là original Hibernate API, nó không thuộc đặc tả JPA. Mục đích của nó về cơ bản giống như persist(), nhưng implementation details của nó thì khác. Phương thức này sẽ tạo ra một định danh, đảm bảo rằng nó sẽ return the Serializable của định danh này.

1
2
3
4
5
6
7
8
Category cat = new Category();
cat.setName("Java");
Long id = (Long) session.save(cat);
System.out.println("Cat id = " + id); // 5
Long id2 = (Long) session.save(cat);
System.out.println("Cat id = " + id2); // 5

Hiệu quả của việc lưu một persisted instance là giống như với persist. Sự khác biệt xuất hiện khi ta cố gắng lưu một detached instance:

1
2
3
4
5
6
7
8
9
10
Category cat = new Category();
cat.setName("Java");
Long id = (Long) session.save(cat);
System.out.println("Cat id = " + id); // 6
session.evict(cat);
Long id2 = (Long) session.save(cat);
System.out.println("Cat id = " + id2); // 7

Như bạn thấy, sau khi gọi evict():

  • Id được save lần đầu khác với id được save lần sau.
  • Khi save trên một detached instance sẽ tạo ra một persistent instance mới và gán nó cho một định danh mới. Kết quả là bị duplicate bản ghi trong database khi commit hoặc flush.

Phương thức merge()

Mục đích chính của phương thức merge() là update một persistent entity instance với các giá trị mới từ một detached entity instance.

Phương thức này hoạt động như sau:

  • Tìm một entity instance bằng id lấy từ đối tượng được truyền (hoặc một existing entity instance từ persistence context được lấy ra, hoặc một new instance được load ra từ database).
  • Sao chép các trường từ đối tượng được truyền vào instance vừa tìm được.
  • returns instance mới đã được update, đối tượng trả về có trạng thái persistence, còn đối tượng ban đầu vẫn sẽ không bị quản lý bởi session.

Trong ví dụ sau, ta evict (detach) thực thể đã lưu khỏi context, thay đổi name field, và sau đó merge với detached entity.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
try (Session session = HibernateUtils.getSessionFactory().openSession();) {
    // Begin a unit of work
    session.beginTransaction();
    Category cat = new Category();
    cat.setName("Java");
    Long id = (Long) session.save(cat);
    System.out.println("saved object is managed by hibernate session = " + session.contains(cat));
    session.evict(cat);
    System.out.println("evicted object is managed by hibernate session = " + session.contains(cat));
    cat.setName("Hibernate");
    Category cat2 = (Category) session.merge(cat);
    System.out.println("merged object is managed by hibernate session = " + session.contains(cat2));
    System.out.println("Saved object is equals with merged object = " + (cat == cat2));
    // Commit the current resource transaction, writing any unflushed changes to the database.
    session.getTransaction().commit();
}

Log:

1
2
3
4
5
6
7
Hibernate: insert into Category (name) values (?)
saved object is managed by hibernate session = true
Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_ from Category category0_ where category0_.id=?
evicted object is managed by hibernate session = false
merged object is managed by hibernate session = true
Saved object is equals with merged object = false
Hibernate: update Category set name=? where id=?

Lưu ý rằng phương thức merge trả về một đối tượng – nó là đối tượng được merge, được load vào persistent context và được update, không phải đối tượng category mà ta đã truyền làm đối số. Đó là hai đối tượng khác nhau, và đối tượng category thường cần phải được loại bỏ sau đó.

Như với phương thức persist(), phương thức merge() được chỉ định bởi JSR-220 để có một số ngữ nghĩa nhất định mà bạn có thể dựa vào:

  • Nếu thực thể là detached, nó được sao chép trên một existing persistent entity.
  • Nếu thực thể là transient, nó được sao chép trên một newly created persistent entity.
  • Hoạt động cascades cho tất cả các mối quan hệ : cascade = MERGE hoặc cascade = ALL.

Phương thức update()

Tương tự như với persist() và save(), phương thức update() là một “original” Hibernate API method đã tồn tại trước khi phương thức merge được thêm vào. Ngữ nghĩa của nó khác nhau ở một số điểm chính:

  • Nó hoạt động khi đối tượng được truyền là một persistence entity hoặc detached entity.
  • Phương thức này chuyển đổi đối tượng được truyền từ trạng thái detached thành trạng thái persistent.
  • Phương thức này ném một ngoại lệ nếu ta truyền vào nó một transient entity.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
try (Session session = HibernateUtils.getSessionFactory().openSession();) {
    // Begin a unit of work
    session.beginTransaction();
    Category cat = new Category();
    cat.setName("Java");
    session.save(cat);
    System.out.println("saved object is managed by hibernate session = " + session.contains(cat));
    session.evict(cat);
    System.out.println("evicted object is managed by hibernate session = " + session.contains(cat));
    cat.setName("Hibernate");
    session.update(cat);
    System.out.println("updated object is managed by hibernate session = " + session.contains(cat));
    // Commit the current resource transaction, writing any unflushed changes to the database.
    session.getTransaction().commit();
}

Log:

1
2
3
4
5
Hibernate: insert into Category (name) values (?)
saved object is managed by hibernate session = true
evicted object is managed by hibernate session = false
updated object is managed by hibernate session = true
Hibernate: update Category set name=? where id=?

Cố gắng thực hiện update trên một transient instance sẽ dẫn đến một ngoại lệ TransientObjectException. Điều sau đây sẽ không hoạt động:

1
2
3
Category cat = new Category();
cat.setName("Java");
session.update(cat); // TransientObjectException

Phương thức SaveOrUpdate()

Phương thức này chỉ xuất hiện trong Hibernate API. Tương tự như update(), nó cũng có thể được sử dụng cho các trường hợp attached lại. Sự khác biệt chính của phương thức update() và saveOrUpdate() là nó không ném ngoại lệ khi được áp dụng cho một transient instance.

Phương thức này hoạt động như sau: nếu là đối tượng mới thì save xuống database, nếu không thì update xuống database. Nó sẽ thực hiện SELECT để kiểm tra trước khi save hoặc update.

  • Nếu  đối tượng đã tồn tại trong session thì nó không làm gì cả.
  • Nếu tồn tại 1 đối tượng khác trong cùng session mà có cùng id thì sẽ xảy ra exception.
  • Nếu đối tượng tượng không có id (chưa tồn tại) thì sẽ thực hiện save().
  • Nếu đối tượng có id nhưng id đó chưa có trong database thì thực hiện save().
  • Các trường hợp còn lại thực hiện update().
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
try (Session session = HibernateUtils.getSessionFactory().openSession();) {
    // Begin a unit of work
    session.beginTransaction();
    Category cat = new Category();
    cat.setName("Java");
    session.saveOrUpdate(cat);
    System.out.println("saved object is managed by hibernate session = " + session.contains(cat));
    session.evict(cat);
    System.out.println("evicted object is managed by hibernate session = " + session.contains(cat));
    cat.setName("Hibernate");
    session.saveOrUpdate(cat);
    System.out.println("updated object is managed by hibernate session = " + session.contains(cat));
    // Commit the current resource transaction, writing any unflushed changes to the database.
    session.getTransaction().commit();
}

Log:

1
2
3
4
5
Hibernate: insert into Category (name) values (?)
saved object is managed by hibernate session = true
evicted object is managed by hibernate session = false
updated object is managed by hibernate session = true
Hibernate: update Category set name=? where id=?

Như bạn thấy phương thức này là một công cụ phổ biến để làm cho một đối tượng persistent bất kể trạng thái của nó là transient hay detached.

Bây giờ hãy xem trường hợp một đối tượng bị giữ bởi 2 session, khi đó phương thức saveOrUpdate() sẽ throw ra một ngoại lệ.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
try (Session session = HibernateUtils.getSessionFactory().openSession();) {
    // Begin a unit of work
    session.beginTransaction();
    Category cat = new Category();
    cat.setId(20L);
    cat.setName("Java");
    session.saveOrUpdate(cat);
    Category cat2 = new Category();
    cat2.setId(20L);
    cat2.setName("Java");
    session.saveOrUpdate(cat2);
    // Commit the current resource transaction, writing any unflushed changes to the database.
    session.getTransaction().commit();
}

Khi chạy chương trình trên, chúng ta sẽ gặp một excepion NonUniqueObjectException. Lý do là có 2 đối tượng cùng được quản lý trong một session.

1
Exception in thread "main" org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [com.gpcoder.entities.Category#20]

Nên sử dụng phương thức nào?

Nếu không có bất kỳ yêu cầu đặc biệt nào, theo quy tắc chung, ta nên tuân thủ các phương thức persist() và merge(), vì chúng được chuẩn hóa và được đảm bảo để tuân theo đặc tả JPA. Nó sẽ dễ dàng hơn trong trường hợp ta quyết định chuyển sang một persistence provider khác, chẳng hạn iBatis, Eclipse Link, OpenJPA, … Tuy nhiên, một số trường hợp đặc biệt các phương thức Hibernate “gốc” như save(), update() và saveOrUpdate() sẽ hữu dụng hơn nhiều.

Persistent –> Detached

Phương thức evict()

Tách một đối tượng ra khỏi session, biến nó từ trạng thái persistent thành detached.

Các bạn có thể xem lại các ví dụ trên để thấy được cách sử dụng evict().

Phương thức clear()

Tách tất cả đối tượng ra khỏi session, biến tất cả chúng từ trạng thái persistent thành detached.

Ví dụ:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
try (Session session = HibernateUtils.getSessionFactory().openSession();) {
    // Begin a unit of work
    session.beginTransaction();
    Category cat = new Category();
    cat.setName("Java");
    session.saveOrUpdate(cat);
    Category cat2 = new Category();
    cat2.setName("Hibernate");
    session.saveOrUpdate(cat2);
    System.out.println("cat1 is managed by hibernate session = " + session.contains(cat));
    System.out.println("cat2 is managed by hibernate session = " + session.contains(cat2));
    session.clear();
    System.out.println("After clear session");
    System.out.println("cat1 is managed by hibernate session = " + session.contains(cat));
    System.out.println("cat2 is managed by hibernate session = " + session.contains(cat2));
    // Commit the current resource transaction, writing any unflushed changes to the database.
    session.getTransaction().commit();
}

Log:

1
2
3
4
5
6
7
Hibernate: insert into Category (name) values (?)
Hibernate: insert into Category (name) values (?)
cat1 is managed by hibernate session = true
cat2 is managed by hibernate session = true
After clear session
cat1 is managed by hibernate session = false
cat2 is managed by hibernate session = false

Detached –> Persistent

Phương thức refresh()

Refresh một đối tượng đang ở trạng thái persistent.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
try (Session session = HibernateUtils.getSessionFactory().openSession();) {
    // Begin a unit of work
    session.beginTransaction();
    Category cat = new Category();
    cat.setName("Java");
    session.saveOrUpdate(cat);
    System.out.println("saved object is managed by hibernate session = " + session.contains(cat));
    session.evict(cat);
    System.out.println("evicted object is managed by hibernate session = " + session.contains(cat));
    session.refresh(cat);
    System.out.println("refreshed object is managed by hibernate session = " + session.contains(cat));
    // Commit the current resource transaction, writing any unflushed changes to the database.
    session.getTransaction().commit();
}

Log:

1
2
3
4
5
Hibernate: insert into Category (name) values (?)
saved object is managed by hibernate session = true
evicted object is managed by hibernate session = false
Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_ from Category category0_ where category0_.id=?
refreshed object is managed by hibernate session = true

Persistent –> Removed

Phương thức delete()

Phương thức này không nằm trong đặc tả JPA, nó là một original hibernate.

Chúng ta cần load đối tượng lên và xoá nó đi thông qua phương thức delete().

Nếu không muốn load lên thì dùng session.createQuery(“DELETE FROM user WHERE …”).executeUpdate();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
try (Session session = HibernateUtils.getSessionFactory().openSession();) {
    // Begin a unit of work
    session.beginTransaction();
    Category cat = new Category();
    cat.setName("Java");
    session.save(cat);
    System.out.println("saved object is managed by hibernate session = " + session.contains(cat));
    session.delete(cat);
    System.out.println("deleted object is managed by hibernate session = " + session.contains(cat));
    // Commit the current resource transaction, writing any unflushed changes to the database.
    session.getTransaction().commit();
}

Log:

1
2
3
4
Hibernate: insert into Category (name) values (?)
saved object is managed by hibernate session = true
deleted object is managed by hibernate session = false
Hibernate: delete from Category where id=?

Phương thức remove()

Phương thức này nằm trong đặc tả JPA, và hoạt động tương tự như delete().

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

Hỏi khó – Java Clone hoạt động như thế nào?

java clone
Hỏi khó – Java Clone hoạt động như thế nào?

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

Java Clone là một trong 5 cách khởi tạo mới một Object. Tại sao chúng ta lại cần nó?. Hãy cùng tìm hiểu qua bài viết dưới đây:

1. Từ câu chuyện của reference variable.

Không cần quá phức tạp, ngay từ ban đầu, ta sẽ tự đặt câu hỏi rằng:

“Nếu muốn sao chép một Object A, chẳng phải cứ gán A = B là được sao?, cần gì tới Java Clone”

  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 các việc làm Java lương cao trên TopDev

Rất tiếc, câu trả lời là không. Đối với C++, phép gán này sẽ cho ra một Object mới, hoàn toàn độc lập với Object cũ. Nhưng Java thì không làm được, nếu sử dụng phép toán ==, java sẽ tạo ra một biến tham chiếu (reference variable) -> không tạo ra một object mới.

Thực chất, trường hợp sử dụng Operator equal hay toán tử New, Java đều trỏ tới cùng một địa chỉ trên memory. Object được tạo ra có thể bị thay đổi nếu object mà nó reference trước đó thay đổi.

Để dễ hiểu hơn, ta cùng xem xét ví dụ dưới đây:

import java.io.*; 

// Class Test, nơi chưa object ta muốn clone.
class Test 
{ 
int x, y; 
Test() 
{ 
x = 10; 
y = 20; 
} 
} 

// Main Class
class Main 
{ 
public static void main(String[] args) 
{ 
// Tạo object ob1
Test ob1 = new Test(); 

System.out.println(ob1.x + " " + ob1.y); 

// Tạo mới reference variable cho ob2 
// Thực chất Object ob2 trỏ tới cùng một địa chỉ với Object ob1 
Test ob2 = ob1; 

// Bất cứ thay đổi nào ở Object 2 cũng đều reflect tới Object 1
// in ob1 
ob2.x = 100; 

System.out.println(ob1.x+" "+ob1.y); 
System.out.println(ob2.x+" "+ob2.y); 
} 
}

Output:

10 20
100 20
100 20

2. Java clone ra đời.

3. Sử dụng như thế nào?.

Để có thể sử dụng method clone, có hai thứ cần làm:

  • Class chúng ta muốn Clone nhất thiết phải implement Cloneable interface. Nếu không, JVM sẽ throw exception CloneNotSupportedException khi ta gọi method clone() trong Object.
  • Trường hợp muốn gọi clone() ở class cha, sử dụng super.clone().

4. Shallow copy và deep copy.

4.1 Shallow copy

Shallow copy is method of copying an object and is followed by default in cloning. In this method the fields of an old object X are copied to the new object Y. While copying the object type field the reference is copied to Y i.e object Y will point to same location as pointed out by X. If the field value is a primitive type it copies the value of the primitive type.

Shallow copy là một method copy object, đây là phương thức được sử dụng mặc định trong cloning. Ở method này, các field của object X được copy tới object Y. Trong quá trình sao chép, cả Object X và Y đều cùng trỏ tới một địa chỉ. Trường hợp field value được copy là kiểu nguyên thủy -> giá trị của Object sẽ được copy.

Chính vì cả 2 Object X và Y đều trỏ về cùng 1 địa chỉ -> trường hợp có thay đổi giá trị ở Object cha, giá trị sẽ thay đổi luôn ở Object con. Tuy cũng sử dụng Java Clone, nhưng Shallow có chi phí khởi tạo (memory) thấp hơn.

Shallow copies are cheap and simple to make.

Shallow copies được tạo ra tương đối đơn giản, chi phí để tạo ra một Object được copy theo kiểu này cũng không quá cao.

4.2 Deep copy

Phương thức chính được sử dụng trong Java Clone là clone(). Phương thức này sử dụng Deep copy, ta sẽ sử dụng method clone(). Khi sử dụng clone(), một Object được tạo ra. Nhưng khi có sự thay đổi về giá trị ở Object cha -> sự thay đổi sẽ không reflect (phản án) tới Object con.

If we want to create a deep copy of object X and place it in a new object Y then new copy of any referenced objects fields are created and these references are placed in object Y. This means any changes made in referenced object fields in object X or Y will be reflected only in that object and not in the other.

Nếu bạn muốn tạo một deep copy của object X và biến nó trở thành một Object mới Y. Tất cả những thay đổi ở Object X sẽ chỉ được phản ánh cho chính nó. Các giá trị còn lại ở Object Y đã clone sẽ không thay đổi.

5. 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

Cài đặt GlassFish server trong Eclipse

glassfish server
Cài đặt GlassFish server trong Eclipse

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

GlassFish là một trong những Java server runtime giúp chúng ta có thể chạy ứng dụng Java web application. Trong bài viết này, mình hướng dẫn các bạn cách cài đặt nó trong Eclipse để có thể dễ dàng phát triển các ứng dụng Java EE, Jakarta EE sử dụng Eclipse các bạn nhé!

  Cài đặt TestNG trong Eclipse
  Hướng dẫn cách kết nối đến Database MySQL trong Eclipse

Cài đặt GlassFish plugin

Điều đầu tiên các bạn cần phải làm là cài đặt GlassFish plugin cho Eclipse.

Các bạn hãy vào Help ->  Install New Software…, sau đó nhấn nút Add, điền thông tin GlassFish plugin repository là http://download.eclipse.org/glassfish-tools/1.0.1/repository/, như sau:

Sau khi nhấn nút Add, các bạn sẽ thấy kết quả như sau:

Nhấn Next các bạn nhé!

Next tiếp các bạn nhé!

Các bạn hãy chọn “I accept the terms of the license agreements” để đồng ý điều khoản sử dụng rồi nhấn nút Finish.

Quá trình cài đặt sẽ bắt đầu.

Sau khi cài đặt xong, Eclipse sẽ cần restart lại.

Hãy restart lại Eclipse các bạn nhé!

Tạo mới GrassFish server trong Eclipse

Sau khi đã cài GrassFish plugin, chúng ta có thể tạo mới một server runtime sử dụng GrassFish.

Các bạn hãy vào Preferences trong Eclipse, đi đến Server -> Runtime Environments như sau:

Nhấn Add rồi chọn GrassFish để cấu hình GrassFish server như sau:

Các bạn hãy nhấn nút Next sau đó thì cấu hình GrassFish server như sau:

Nhấn Finish để hoàn thành việc cấu hình này các bạn nhé.

Định nghĩa một GrassFish server để chạy ứng dụng

Nếu các bạn có một ứng dụng Java EE hay Jakarta EE, các bạn có thể ứng dụng này sử dụng GrassFish như sau:

Right click vào project ứng dụng, chọn Run As -> Run on Server, chọn Manually define a new server rồi chọn GrassFish như sau:

Nhấn Next

Các bạn cứ để giá trị mặc định rồi nhấn nút Finish nhé!

Các bạn sẽ thấy GrassFish server started như sau;

Ứng dụng Visitor Pattern để làm configure UI driven

visitor pattern
Ứng dụng Visitor Pattern để làm configure UI driven

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

Vấn đề chúng ta cần giải quyết: chúng ta cần render form với các loại field phổ biến như datenumberdropdowntext, với điều kiện là những field này user có thể config được, giống như google form

Visitor pattern là 1 phương pháp thiết kế trong OOP, cách làm là chúng ta sẽ có một object với cấu trúc định sẵn, sử dụng object này để thực hiện những xử lý chúng mong muốn

object với cấu trúc định sẵn thường được gọi là schema, trong bài toán của chúng ta thì schema cần những property sau

  • fieldType: ví dụ dropdown, textbox, date, number
  • label: ví dụ first name, birthday
  • name: field name dùng để submit form
  • required: thuộc tính có bắt buộc không
  3 bước tối ưu hiệu năng React App bằng các API mới của React
  Architectural Styles vs. Architectural Patterns vs. Design Patterns

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

const schema = [
  {
    label: "First Name",
    name: "firstName",
    required: true,
    fieldType: "Text",
  },
  {
    label: "Birthdate",
    name: "birthdate",
    required: true,
    fieldType: "Date",
  },
  {
    label: "Number of Pets",
    name: "numPets",
    required: false,
    fieldType: "Number",
  },
]

Để render form dựa trên schema này, giải pháp xuất hiện ngay trong đầu sẽ là

function Form({ schema }) {
  return schema.map((field) => {
    switch (field.fieldType) {
      case "Text":
        return <input type="text" /> 
      case "Date":
        return <input type="date" />
      case "Number":
        return <input type="number" />
      default:
        return null
    }
  })
}

Tuy nhiên, đây chưa phải là visitor pattern, để có thể customize sâu và rộng schema, mà không cần cập nhập lại Form

const defaultComponents = {
    Text: () => <input type="text" />,
  	Date: () => <input type="date" />,
  	Number: () => <input type="number" />
}
    
function ViewGenerator({ schema, components }) {
	const mergedComponents = {
		...defaultComponents,		...components	}
	
	return schema.map((field) => {
		return mergedComponents[field.fieldType](field)
	})
}

ViewGenerator cũng chung một công dụng như Form ở trên, ở đây chúng ta chỉ làm thêm việc, 1 là đưa phần khai báo component ra defaultComponent và bổ sung tham số components để khi có nhu cầu mở rộng, override các component default thì truyền thêm. Quá generic!

const data = {
  firstName: "John",
  birthdate: "1992-02-01",
  numPets: 2
}

const profileViewComponents = {
  Text: ({ label, name }) => (
    <div>
      <p>{label}</p>
      <p>{data[name]}</p>
    </div>
  ),
  Date: ({ label, name }) => (
    <div>
      <p>{label}</p>
      <p>{data[name]}</p>
    </div>
  ),
  Number: ({ label, name }) => (
    <div>
      <p>{label}</p>
      <p>{data[name]}</p>
    </div>
  )
}

function ProfileView({ schema }) {
  return (
    <ViewGenerator
      schema={schema}
      components={profileViewComponents}
    />
  )
}

Giờ nếu các field được group vào kiểu cha-con thì sao? Một cách (mình cũng không thích lắm) là thêm children

const schema = [
  {
    label: "Personal Details",
    fieldType: "Section",
    children: [
      {
        label: "First Name",
        fieldType: "Text",
      },
      {
        label: "Birthdate",
        fieldType: "Date",
      },
    ],
  },
  {
    label: "Favorites",  
    fieldType: "Section",
    children: [
      {
        label: "Favorite Movie",
        fieldType: "Text",
      },
    ],
  },
]

Với một cấp duy nhất thì schema này ok, nhưng nếu lồng nhiều hơn một cấp thì đây không phải cách mình sẽ làm, anyway để đơn giản hóa chúng ta chỉ dùng một cấp. Phần ViewGenerator cần được cập nhập để render thêm các children

function ViewGenerator({ schema, components }) {
  const mergedComponents = {
    ...defaultComponents,
    ...components,
  }

  return schema.map((field) => {
    const children = field.children ? (      <ViewGenerator
        schema={field.children}
        components={mergedComponents}
      />
    ) : null

    return mergedComponents[field.fieldType]({ ...field, children });  })
}

Đệ quy như vậy chưa hẳn là giải pháp hoàn hảo, hy vọng các bạn nào có giải pháp nào tốt hơn thì góp ý thêm.

Khi nghĩ về visitor pattern, chúng ta nghĩ đến

  1. Configure Object đứng độc lập
  2. UI đứng độc lập
  3. Hàm trung gian dùng để map configure object và UI tương ứng

https://www.arahansen.com/react-design-patterns-generating-user-configured-ui-using-the-visitor-pattern

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

Nhân Viên QC Và Những Kỹ Năng Không Thể Thiếu Trong Công Việc

3 kỹ năng quan trọng nhất cho nhân viên qc
Nhân Viên QC Và Những Kỹ Năng Không Thể Thiếu Trong Công Việc

Nhân viên QC là một trong những vị trí quan trọng giúp vận hành và duy trì chất lượng sản phẩm trong kinh doanh. Do đó, những yêu cầu về công việc đặt ra với nhân viên QC cũng phần nào khắt khe hơn so với các vị trí khác. Sở hữu những kỹ năng cần thiết cho công việc sẽ giúp cho quá trình làm việc được thuận lợi hơn. Vậy 3 kỹ năng quan trọng nhất cho nhân viên QC là gì? Cùng TopDev tìm hiểu thêm với bài viết dưới đây nhé!

3 kỹ năng quan trọng nhất cho nhân viên qc
Nhân viên QC phải đảm nhận nhiều công việc quan trọng

Nhân viên QC là gì?

Khái niệm nhân viên QC

QC là viết tắt của Quality Control, nhiệm vụ chính của một nhân viên QC liên quan phần nhiều đến việc kiểm tra và giám sát chất lượng sản phẩm. Nhân viên QC sẽ trực tiếp kiểm tra và đánh giá sản phẩm trước khi đưa ra thị trường để có thể mang đến cho khách hàng những sản phẩm tốt nhất. Nhân viên QC giúp doanh nghiệp tìm ra các sản phẩm bị lỗi sớm nhất trước khi được đưa ra thị trường, đảm bảo uy tín và hoạt động trơn tru cho doanh nghiệp.

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

Nhân viên QC quản lý những công việc nào?

Hiện nay nhân viên QC được chia thành 3 dạng gồm:

  • Nhân viên kiểm soát chất lượng đầu vào
  • Nhân viên kiểm soát chất lượng của quy trình sản xuất
  • Nhân viên kiểm soát chất lượng đầu ra

3 vị trí này sẽ theo dõi và làm việc xuyên suốt quá trình sản xuất để đảm bảo chất lượng sản phẩm.

Công việc chính của một nhân viên QC sẽ tập trung vào việc kiểm tra, phân loại và phát hiện sớm nhất các lỗi phát sinh. Sau khi phát hiện và phân tích lỗi sai, nhân viên QC sẽ làm việc với nhân viên QA (Quality Assurance) – bộ phận đảm bảo chất lượng cho sản phẩm để đề xuất hướng xử lý và sửa lỗi, đảm bảo chất lượng cho thành phẩm cuối cùng.

Tìm việc làm QA QC lương cao trên TopDev

công việc của nhân viên qc
Quy trình làm việc của một nhân viên QC

3 kỹ năng quan trọng nhất của nhân viên QC

1. Kỹ năng giám sát chất lượng và tư duy logic

Vì là người trực tiếp quản lý và kiểm tra chất lượng của sản phẩm nên kỹ năng giám sát có thể nói là điều kiện tiên quyết với bất cứ nhân viên QC nào. Nhân viên QC cần có kỹ năng quan sát và giám sát tốt để phát hiện nhanh chóng các vấn đề còn chưa hoàn thiện và sửa chữa sớm nhất. Đôi mắt nhạy bén là một phần không thể thiếu với bất cứ nhân viên QC nào. Phát hiện được những lỗi sai dù rất nhỏ là công việc cần thiết của nhân viên QC.

Khả năng giám sát tốt cùng với tư duy logic sẽ giúp nhân viên QC không chỉ nhanh chóng phát hiện được vấn đề mà còn biết được cách để xử lý những lỗi sai đó theo hướng tối ưu về thời gian và sức lực. Những nhân viên QC chuyên nghiệp là những người phát huy rất tốt các khả năng này. Vì thời gian xử lý lỗi sai quá lâu chắc chắn sẽ kéo theo ảnh hưởng đến một dây chuyền hoạt động phía sau.

Xem thêm TOP 4 Công Việc Có Thu Nhập Hấp Dẫn Trong Tương Lai

2. Kỹ năng quản lý và điều hành

Về mặt chuyên môn, kỹ năng quản lý và điều hành chắc chắn không chỉ quan trọng với nhân viên QC mà còn với tất cả các ngành nghề khác. Với nhân viên QC – Quality Control, kỹ năng quản lý sẽ giúp bạn làm chủ được thời gian và công việc của mình, cũng như làm tốt hơn trong việc quản lý các nhân viên cấp dưới của mình nếu có.

Kỹ năng quản lý và điều hành công việc sẽ giúp bạn hoàn thành công việc tốt hơn nhờ phối hợp tốt giữa các quy trình, không bị lộn xộn hay ôm đồm quá nhiều công việc cùng lúc. Bên cạnh đó, khi nắm được thế mạnh cũng như điểm yếu của các nhân viên cấp dưới, bạn sẽ biết được nên giao cho họ công việc để họ làm tốt nhất. Giúp công việc được hoàn thành đúng thời hạn, thậm chí sớm hơn thời hạn mà vẫn đảm bảo được hiệu quả về mặt chất lượng cũng như số lượng.

3. Kỹ năng sử dụng công nghệ

Đối với vị trí của một nhân viên QC, một trong 3 kỹ năng quan trọng nhất cho nhân viên QC đó là khả năng sử dụng công nghệ và các thiết bị có liên quan đến công việc một cách thuần thục. Một số kỹ năng cần có với nhân viên kiểm soát chất lượng là biết cách sử dụng các thiết bị kỹ thuật số, các dụng cụ đo đạc và kiểm tra chất lượng sản phẩm chuyên dụng cũng như có khả năng tin học văn phòng tốt.

  Cơ Hội Việc Làm Cho Sinh Viên CNTT Mới Ra Trường
  Sinh viên CNTT làm thế nào để học tốt ở trường đại học?

Bên cạnh những kỹ năng mềm như khả năng giao tiếp, diễn đạt tốt cũng năng lực hợp tác và phối hợp làm việc với nhiều phòng ban khác nhau, kỹ năng sử dụng các thiết bị công nghệ hoàn toàn có thể trau dồi qua thời gian. Chính vì thế, để công việc kiểm soát chất lượng có thể diễn ra suôn sẻ, việc đầu tư thời gian cho những kỹ năng này là hoàn toàn cần thiết cho một công việc trôi chảy và thuận lợi.

Chiếm vai trò quan trọng trong các khâu làm việc và quyết định đến thành phẩm cuối cùng, mức lương cho nhân viên QC hiện nay cũng được xếp vào nhóm khá cao, mức trung bình hoàn toàn có thể nằm khoảng 10 triệu đồng/tháng. Do đó, để sở hữu công việc mình đam mê với mức lương hấp dẫn, biết thêm 3 kỹ năng quan trọng nhất cho nhân viên QC có thể giúp bạn hoàn thiện năng lực làm việc của mình hơn. Cùng TopDev đón đọc thêm nhiều bài viết bổ ích và hấp dẫn khác nhé!

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 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