CƠ BẢN VỀ HTML VÀ CSS
HTML
HTML (HyperText Markup Language) là ngôn ngữ đánh dấu sử dụng các thẻ và phần tử để điều khiển hiển thị tài liệu trực tuyến Nó cho phép truy xuất, đọc tài liệu và tạo các biểu mẫu trực tuyến nhằm thu thập thông tin người dùng và thực hiện giao dịch Bài viết này sẽ trình bày ngắn gọn các thành phần cơ bản của một trang HTML.
Mỗi phần tử trong HTML được cấu thành từ một cặp thẻ, bao gồm thẻ mở (open tag) và thẻ đóng (end tag), cùng với các thuộc tính (attribute) và giá trị của chúng (value) Cấu trúc của một thẻ được minh họa trong Hình 1.1.
Hình 1.1 - Cấu trúc của tag hay phần tử
Attribute cung cấp thông tin mô tả cho phần tử, như thể hiện trong Hình 1.2 Tất cả các attribute cần phải được đặt trong start tag và được viết theo định dạng: name=“value”.
Hình 1.2 - Các attribute của phần tử
Class Classname Xác định classname cho phần tử
Id Id Xác định id duy nhất cho phần tử
Style Style_definition Xác định inline style cho phần tử Title Tooltip_text Xác định thông tin thêm cho phần tử
1.1.3 Một số tag cơ bản
Heading Được dùng để định nghĩa các mức đề mục cho tài liệu Có sáu mức đề mục
text H1 cỡ chữ lớn nhất
text H6 cỡ chữ nhỏ nhất
Hình 1.3 trình bày một trang HTML có sử dụng 6 heading và hiển thị của trang này trên trình duyệt
Hình 1.3 - Ví dụ về các heading
Thẻ
được dùng để định nghĩa một đoạn văn như Hình 1.4
Hình 1.4 - Ví dụ về thẻ
Thẻ trong HTML được sử dụng để hiển thị nội dung chính xác như cách người dùng nhập, bao gồm việc giữ nguyên font chữ, khoảng trắng và ký tự xuống dòng Hình 1.5 minh họa rõ ràng tác dụng của thẻ này.
Hình 1.5 - Tác dụng của thẻ
Chúng ta dùng danh sách thứ tự để liệt kê các nội dung, như được minh họa trong Hình 1.6
Hình 1.6 - Minh họa cách dùng order list
Chúng ta dùng thẻ và thuộc tính color để xác định font và màu chữ như được minh họa trong Hình 1.7
Hình 1.7 - Minh họa cách dùng font chữ và màu chữ
Hyperlink Được dùng để link trang này với trang khác Cú pháp của thẻ này như sau:
Hình 1.8 - Minh họa cách dùng thẻ
Dùng để hiển thị hình ảnh trên trang web Cú pháp của thẻ này như sau:
SRC là attribute bắt buộc, được dùng để xác định URL của hình
Width, height là chiều rộng và chiều cao của hình, được đo bằng pixels hoặc phần trăm của một trang hoặc một frame
Images sẽ được điều chỉnh (scale) để khớp với không gian được cho phép
Hình 1.9 - Minh hoạ thẻ
Hình 1.10 minh hoạ cách dùng thể
Hình 1.10 - Minh họa cách dùng thẻ
Hình 1.11 minh họa cách dùng các thuộc tính border, cellspacing, và cellpadding trong thẻ
Hình 1.11 - Minh họa cách dùng các thuộc tính border, cellspacing, và cellpadding
Chúng ta có thể dùng các thuộc tính của thẻ và để làm việc với dòng và cột của các bảng như được minh họa trong Hình 1.12
Hình 1.12 - Minh họa cách dùng thuộc tính TR và TD
Chúng ta có thể dùng HTML form để thu thập thông tin từ người dùng và gửi về server Hình 1.13 mô tả cách dùng thẻ
Hình 1.13 - Minh họa cách dùng thẻ và
CSS
Trong bài viết này, tác giả sẽ trình bày những kiến thức cơ bản về CSS (Cascading Style Sheet) và CSS3, nhằm hỗ trợ sinh viên áp dụng CSS vào các tài liệu HTML một cách hiệu quả.
1.2.1 HTML động (Dynamic HTML - DHTML)
DHTML là thuật ngữ chỉ trang HTML kết hợp với CSS và các ngôn ngữ script như JavaScript, giúp trang web phản hồi với các tương tác của người dùng, làm cho nó trở nên sinh động hơn Để thực hiện DHTML, việc sử dụng tập tin CSS là rất quan trọng Tập tin CSS, với đuôi mở rộng css, chứa các lệnh và quy tắc quy định cách hiển thị các phần tử HTML.
Hình 1.14 - Vai trò của CSS trong trang web
Hình 1.14 mô tả vai trò của CSS trong các website
1.2.2 Gắn CSS vào một trang HTML
Có 3 cách để gắn CSS vào một trang HTML
Inline Style Sheet: CSS không được khai báo trong header của trang HTML mà được nhúng trược tiếp vào trong tag
Ví dụ:
Some Text
Internal Style Sheet: CSS được khai báo trong phần header của trang HTML Loại này thích hợp cho trường hợp dùng CSS cho một trang Ví dụ:
h1 {color: red)
CSS có thể được lưu trữ trong một tệp riêng biệt và được kết nối với trang HTML thông qua thẻ Phương pháp này thường được áp dụng để định dạng cho nhiều trang HTML cùng một lúc.
\n"; out.println(docType +
"Hello\n" +
} Đoạn code trên được chỉnh sửa từ ví dụ trong bảng trên sao cho servlet này có thể xuất ra định dạng HTML thay vì plain text
Hình 5.2 - Kết quả của http://localhost/servlet/HelloServlet
Bước 3: Kiểm tra lỗi cú pháp HTML bằng một HTML validator bất kỳ.
SERVLETS PACKAGING
Trong môi trường phát triển phần mềm, nhiều lập trình viên thường cùng phát triển nhiều servlet cho một server, dẫn đến việc đặt tất cả servlet vào một thư mục gây ra rủi ro như kích thước thư mục lớn và khó quản lý tên class trùng lặp Để khắc phục, các ứng dụng web đã phân chia vùng lưu trữ thành nhiều thư mục khác nhau, mỗi thư mục chứa các servlet, lớp tiện ích, trang JSP và tệp HTML Tuy nhiên, với kích thước ứng dụng web lớn, việc sử dụng package (gói) là cần thiết để tránh trùng tên Để đặt servlet trong package, cần thực hiện một số bước nhất định.
Để tổ chức các tập tin một cách hợp lý, hãy đặt chúng vào một thư mục con tương ứng với tên package Chẳng hạn, trong giáo trình này, chúng ta sẽ sử dụng package có tên là coreservlets, do đó, các tập tin class cần được lưu trữ trong thư mục con có tên coreservlets.
Để chèn một câu lệnh package vào tập tin class, bạn cần đảm bảo rằng class của bạn được đặt trong thư mục tương ứng với tên package Cụ thể, nếu class của bạn thuộc package có tên là somePackage, hãy đặt class đó trong thư mục somePackage và thêm dòng lệnh sau ở đầu file: package somePackage;
Bảng 5.4 - coreservlets/HelloServlet2.java package coreservlets; import java.io.*; import javax.servlet.*; import javax.servlet.http.*;
/** Simple servlet for testing the use of packages */ public class HelloServlet2 extends HttpServlet { public void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html");
"\n"; out.println(docType +
"Hello (2)\n" +
In the example provided, the HelloServlet class belongs to the coreservlets package, which will be stored in different directories depending on the server used: for Tomcat, it is located at install_dir/webapps/ROOT/WEB-INF/classes/coreservlets; for JRun, it can be found at install_dir/servers/default/default-ear/default-war/WEB-INF/classes/coreservlets; and for Resin, it is situated at install_dir/doc/WEB-INF/classes/coreservlets.
Hình 5.3 - Kết quả của http://localhost/servlet/coreservlets.HelloServlet2
CÁC UTILITIES HỖ TRỢ VIỆC TẠO FILE HTML
Như chúng ta đã biết, cấu trúc một file HTML có dạng như sau:
Bảng 5.5 - Cấu trúc file HTML
Thẻ DOCTYPE có vai trò quan trọng trong việc thông báo cho các công cụ kiểm tra HTML (validators) về phiên bản HTML đang được sử dụng Các validators này giúp phát hiện lỗi cú pháp trong file HTML, đảm bảo rằng mã có thể hoạt động tốt trên một trình duyệt nhưng vẫn có thể gặp vấn đề trên trình duyệt khác.
Hai công cụ xác thực HTML phổ biến hiện nay là WorldWideWebConsortium (http://validator.w3.org) và Web Design Group (http://www.html.help.com/tools/validator) Người dùng có thể gửi liên kết URL của trang HTML cần kiểm tra, và các công cụ này sẽ lấy trang HTML từ địa chỉ đã chỉ định, thực hiện kiểm tra lỗi cú pháp và thông báo lỗi nếu có.
Khi sử dụng lệnh println để xuất ra file HTML, chúng ta thường gặp vấn đề về độ dài của mã nguồn do cấu trúc HTML thường lặp lại Để khắc phục điều này, có thể tạo một utility class nhằm đơn giản hóa các cấu trúc lặp Dưới đây là ví dụ về servlet sử dụng utility.
Bảng 5.6 - coreservlets/ServletUtilities.java package coreservlets; import javax.servlet.*; import javax.servlet.http.*;
/** Some simple time savers Note that most are static methods */ public class ServletUtilities { public static final String DOCTYPE =
""; public static String headWithTitle(String title) { return(DOCTYPE + "\n" +
Bảng 5.7 - coreservlets/HelloServlet3.java package coreservlets; import java.io.*; import javax.servlet.*; import javax.servlet.http.*;
/** Simple servlet for testing the use of packages
* and utilities from the same package
*/ public class HelloServlet3 extends HttpServlet { public void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html");
String title = "Hello (3)"; out.println(ServletUtilities.headWithTitle(title) +
Sau khi biên dịch HelloServlet3.java, file ServletUtilities.java cũng sẽ được biên dịch tự động Hai class này cần được đặt vào thư mục …/WEB-INF/classes Nếu xuất hiện lỗi “Unresolved symbol”, hãy kiểm tra lại biến CLASSPATH.
Hình 5.4 - Kết quả của http://localhost/servlet/coreservlets.HelloServlet3
CHU KỲ SỐNG CỦA SERVLET
Phương thức INIT() được sử dụng để khởi tạo servlet, sau đó mỗi yêu cầu từ người dùng sẽ được xử lý trong một thread thông qua phương thức service() Khi nhiều người dùng gửi yêu cầu đồng thời, nhiều thread sẽ gọi phương thức service() mặc dù servlet chỉ có thể hoạt động ở chế độ SingleThreadModel, cho phép chỉ một thread chạy tại một thời điểm Phương thức service() sẽ tiếp tục gọi các hàm như doGet(), doPost() hoặc các hàm doXXX khác, tùy thuộc vào loại yêu cầu HTTP Cuối cùng, khi máy chủ quyết định giải phóng servlet, phương thức destroy() sẽ được gọi.
Whenever the server receives a request from a servlet, it initiates a new thread and invokes the service() method This method checks the type of HTTP request (GET, POST, PUT, DELETE, etc.) and subsequently calls the corresponding methods such as doGet, doPost, doPut, or doDelete.
Khi xây dựng một servlet cần xử lý cả hai loại request là POST và GET, nhiều lập trình viên thường ghi đè phương thức service thay vì triển khai riêng hai hàm doGet và doPost Tuy nhiên, phương pháp này không phải là giải pháp tối ưu Thay vào đó, nên để doPost gọi doGet hoặc ngược lại để đảm bảo tính hiệu quả và dễ bảo trì cho mã nguồn.
Bảng 5.8 - Ví dụ cài đặt phương thức doPost gọi doGet public void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
} public void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException { doGet(request, response);
Phương pháp này mang lại nhiều lợi ích so với việc ghi đè trực tiếp phương thức service Đầu tiên, nó cho phép bổ sung hỗ trợ cho các phương thức HTTP request như doPut và doTrace trong một subclass Thứ hai, việc thêm hỗ trợ xem ngày chỉnh sửa thông qua phương thức getLastModified là khả thi, vì phương thức này được gọi bởi phương thức service mặc định, trong khi ghi đè sẽ làm mất tính năng này Cuối cùng, phương thức service mặc định cũng tự động hỗ trợ các request HEAD, OPTION và TRACE.
5.6.2 Các phương thức doGet, doPost, doXXX
Khi phát triển ứng dụng, chúng ta thường chỉ chú trọng đến hai loại yêu cầu là GET và POST, và thường sẽ ghi đè các phương thức doGet và doPost Tuy nhiên, nếu cần thiết, chúng ta cũng có thể ghi đè các phương thức doDelete cho yêu cầu DELETE và doPut cho yêu cầu PUT.
PUT, doOptions cho request OPTIONS, doTrace cho request TRACE Cũng cần lưu ý rằng phương thức service tự động hỗ trợ cho request OPTIONS và TRACE
Thông thường, không cần cài đặt phương thức doHead để xử lý request HEAD, vì hệ thống sẽ tự động gọi doGet và sử dụng các cài đặt trạng thái của dòng và tiêu đề để trả lời request HEAD Tuy nhiên, việc cài đặt doHead là cần thiết trong một số trường hợp đặc biệt, chẳng hạn như khi client chỉ cần các HTTP headers mà không cần toàn bộ tài liệu, giúp tiết kiệm thời gian khi không cần xuất ra toàn bộ nội dung cùng lúc.
Servlet thường chỉ xử lý dữ liệu cho mỗi yêu cầu thông qua hai phương thức doGet và doPost Tuy nhiên, khi cần thực hiện các tác vụ cài đặt phức tạp khi servlet được tải lần đầu, chúng ta sử dụng phương thức init Phương thức này được gọi chỉ một lần khi servlet được khởi tạo, không được gọi lại cho mỗi yêu cầu.
Bảng 5.9 - Định nghĩa phương thức init() public void init() throws ServletException {
Phương thức init vận hành hai loại khởi tạo: khởi tạo thông thường và khởi tạo có tham số
Phương thức init trong servlet được sử dụng để tạo hoặc tải dữ liệu cần thiết cho toàn bộ chu kỳ sống của servlet, đồng thời thực hiện một số tính toán chỉ cần thực hiện một lần.
Trong ví dụ bên dưới, phương thức init thực hiện hai việc:
Tạo một mảng 10 phần tử số nguyên để tối ưu hóa hiệu suất tính toán Thay vì tính toán lại cho mỗi yêu cầu, hàm doGet sẽ sử dụng giá trị kết quả đã được tính toán bởi phương thức init, giúp tiết kiệm thời gian và tài nguyên.
Kết quả xuất ra của servlet chỉ thay đổi khi server được khởi động lại, vì vậy phương thức init lưu lại thời điểm chỉnh sửa trang web Thời gian này được hàm getLastModified sử dụng để trả về thời gian chỉnh sửa tính từ năm 1970 (đơn vị milisecond), và giá trị này sẽ tự động chuyển đổi sang định dạng ngày GMT.
Bảng 5.10 - coreservlets/LotteryNumbers.java package coreservlets; import java.io.*; import javax.servlet.*; import javax.servlet.http.*;
/** Ví dụ sử dụng servlet initialization và phương thức */ public class LotteryNumbers extends HttpServlet { private long modTime; private int[] numbers = new int[10];
/** Phương thức init() được gọi chỉ khi servlet được
* loaded, trước khi request đầu tiên được xử lý
*/ public void init() throws ServletException {
// Làm tròn modTime = System.currentTimeMillis()/1000*1000; for(int i=0; i