Xây dựng custom tag hiển thị dữ liệu table của 1 databse
Ở bài này tôi sẽ đề cập với các bạn cách tạo 1 custom tag dùng để hiển thị dữ liệu của 1 bảng bất kỳ trong csdl của 1 database. Trong bài viết này, tôi chỉ có thể thao tác được với 1 trong loại datasource: mssql, mysql và jdbc.
Mong muốn rằng sau khi công việc hoàn tất, với tag sau ta có thể nối đến databse mssql và lấy dữ liệu của bảng AdventureWorksDW với username là sa.
| <dt:datatable dbmsType=”mssql” dbName=”AdventureWorksDW” dbTableName=”DimEmployee” dbUserName=”sa” dbUserPassword=”"> Employees </dt:datatable> |
Kết quả của tag trên sẽ là 1 html table hiển thị như hình sau

Đầu tiên ta tạo 1 project dạng “Dynamic Web Project” trong eclipse.
Copy 2 thư viện msjdbc.jar và mysql.jar vào thư mục lib của project với mục đích nhằm có thể truy xuất được đến 2 hệ quản trị csdl này. Bạn có thể download chúng từ microsoft sqlserver jdbc và từ http://dev.mysql.com/downloads/
Cấu trúc tổng quát của project trong eclipse khi làm xong ví dụ này như sau

Trước hết ta tạo lớp DataTableTag.java trong package vovanhai.wordpress.com. Nội dung của nó như sau:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.Statement; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.BodyContent; import javax.servlet.jsp.tagext.BodyTagSupport; public class DataTableTag extends BodyTagSupport{ private static final long serialVersionUID = 7908537941853208739L; private String dbmsType; private String dbName; private String dbTableName; private String dbUserName = “”; private String dbUserPassword = “”; @Override public int doAfterBody() throws JspException { try { BodyContent bodycontent = getBodyContent(); String body = bodycontent.getString(); JspWriter out = bodycontent.getEnclosingWriter(); if(body != null) out.println(“<h1 align=’center’>”+body+“</h1>”); else out.println(“<h1 align=’center’>Data in: “+dbTableName+“</h1>”); //=========================================================== String driver=“”,dbURL=“”; if(dbmsType.equalsIgnoreCase(“mssql”)){ driver=“com.microsoft.sqlserver.jdbc.SQLServerDriver”; dbURL=“jdbc:sqlserver://localhost:1433;databaseName=”+dbName; } else if(dbmsType.equalsIgnoreCase(“mysql”)){ driver=“com.mysql.jdbc.Driver”; dbURL=“jdbc:mysql://localhost:3306/”+dbName; } else if(dbmsType.equalsIgnoreCase(“jdbc”)){ driver=“sun.jdbc.odbc.JdbcOdbcDriver”; dbURL=“jdbc:odbc:”+dbName; } //============================= DoTag(driver, dbURL);// //============================== } catch(Exception ioe) { throw new JspException(“Error:”+ioe.getMessage()); } return SKIP_BODY; } private void DoTag(String driver,String dbURL)throws Exception{ Class.forName(driver); Connection con = DriverManager.getConnection(dbURL, dbUserName, dbUserPassword); Statement stmt = con.createStatement(); String query=“SELECT * FROM “+dbTableName; ResultSet rs=stmt.executeQuery(query); BodyContent bodycontent = getBodyContent(); JspWriter out = bodycontent.getEnclosingWriter(); out.println(“<table border=’1′ width=’100%’>”); //header String header=createTableHeader(rs); out.println(header); //body int cols=rs.getMetaData().getColumnCount(); while(rs.next()){ String st=“<tr>”; for (int i = 1; i <= cols; i++) { st+=“<td>”+rs.getString(i)+“</td>”; } st+=“</tr>”; out.println(st); } //end out.println(“</table>”); con.close(); } private String createTableHeader(ResultSet rs) throws Exception{ ResultSetMetaData rsM=rs.getMetaData(); String st=“<tr>”; for (int i = 1; i <= rsM.getColumnCount(); i++) { st+=“<td>”+rsM.getColumnLabel(i)+“</td>”; } st+=“</tr>”; return st; } //=============các thuá»™c tÃnh================================= public String getDbmsType() { return dbmsType; } public void setDbmsType(String dbmsType) { this.dbmsType = dbmsType; } public String getDbName() { return dbName; } public void setDbName(String dbName) { this.dbName = dbName; } public String getDbTableName() { return dbTableName; } public void setDbTableName(String dbTableName) { this.dbTableName = dbTableName; } public String getDbUserName() { return dbUserName; } public void setDbUserName(String dbUserName) { this.dbUserName = dbUserName; } public String getDbUserPassword() { return dbUserPassword; } public void setDbUserPassword(String dbUserPassWord) { this.dbUserPassword = dbUserPassWord; } } |
Như vậy chúng ta có các thuộc tính:
private String dbmsType; //để chỉ đến hệ quản trị csdl được chọn lựa
private String dbName;//database name mà chúng ta sẽ làm việc
private String dbTableName; //Bảng cần truy xuất thông tin
private String dbUserName;//User đăng nhập CSDL
private String dbUserPassword;//mật khẩu đăng nhập
Ở đây ứng với từng dbms type mà chúng ta sẽ xây dựng chuỗi kết nối riêng.
Các công việc còn lại là đọc metadata để hiển thị tiêu đề và đọc dữ liệu để hiển thị nội dung.
Sau đó tạo tập tin định nghĩa thẻ, tập tin datatable.tld. Nội dung như sau:
| <?xml version=”1.0″ encoding=”UTF-8″?> <!DOCTYPE taglib PUBLIC “-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2/EN” “http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd” > <taglib> |
Công việc cuối cùng là tạo trang jsp để thử. Ở đây tôi tạo tập tin DisplayTable.jsp để thử, nội dung như sau:
| <%@ page language=”java” contentType=”text/html; charset=UTF-8″ pageEncoding=”UTF-8″%> <%@ taglib prefix=”dt” uri=”/WEB-INF/tlds/datatable.tld”%> <!DOCTYPE html PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN” “http://www.w3.org/TR/html4/loose.dtd”> </body> |
Kết quả sau khi triển khai trên Tomcat 6.18, vào url http://localhost:8086/MyCustomTag/DisplayTable.jsp, thu được như hình :

Bạn có thể phát triển thêm nhiều thứ để đáp ứng yêu cầu của mình
Chúc thành công!
Bigman said
thay co the cho 2 dia chi chinh xac de down 2 lib do dc k..
TuanNA said
Đối với mysql-connector-j bạn có thể download tại đây. Còn đối với sql server thì link trên là down được rồi, bạn có thể down bản 2.0 hoặc 1.2 là tùy bạn, sau khi down xong chạy file .exe của nó để unzip vào 1 thư mục bất kì, file bạn cần phải copy vào dự án là: sqljdbc.jar
khoa said
thua Thay
Em gap van de nhu sau: khi mo 1 project, bai nay down tu tren mang ve de chay thu, thi no xuat hien 1 bang thong bao co chu nhu sau: you need Revolve missing server problem, voi thong bao nay minh chinh sua lam sao thua Thay??
Mong thay chi giup em.
Cam on Thay
Em ko bit post o dau nen post o day mong Thay thong cam
vovanhai said
Nếu là netbean thì nhấn chuột phải lên project, chọn properties sau đó tìm đến mục run, chọn server là xong. Nếu là eclipse thì nhấn chuột phải lên project, chọn properties sau đó tìm đến mục Java Build Path, chọn thẻ libraries xem mục nào có chữ missing thì remove nó ra sau đó nhấn nút Add Library, chọn server runtime, chọn server chỉ định cho project. Nhấn OK.
Phạm Quang said
thầy ơi..cho em hỏi.nếu mình khai báo thông số connection database trong file JSP khi mình viewsource nó có hiện ra không thầy..nếu nó hiện thị thì có sao không thầy em cám ơn..
thanh_Vh said
chào thầy ! Khi em hiển thị dữ liệu trên jsp có thể hiển thị item theo hàng ngang( theo cột)
giống như Tác động Hướng hiển thị dòng của DataList trong ASP.net được không ? và làm thế nào .Cám ơn thầy..
sgboy17 said
Chào anh Hải, trường hợp của em là thêm đường link delete vào mỗi dòng. Link này dẫn đến servlet delete với parameter là id
str+="Delete";. Trang web khi chạy chỉ thực thi những đoạn code trên dòng code này. Trường hợp này phải xử lý như thế nào? Cám ơn.sgboy17 said
Chào anh Hải, trường hợp của em là thêm đường link delete vào mỗi dòng. Link này dẫn đến servlet delete với parameter là id
str+=rs.getString(1);. Trang web khi chạy chỉ thực thi những đoạn code trên dòng code này. Trường hợp này phải xử lý như thế nào? Cám ơn.phuonghoang2409 said
Chào anh, cho em hỏi là, làm sao tùy biến giá trị truyền vào trong custom tag đó
VD: <dt:database value="”>
Dùng JSPExpression như trên thì lại bị lỗi 500, cho em hỏi là còn cách nào khác để truyền giá trị vào hay ko ??
Võ Văn Hải said
lỗi 500 là lỗi phía server. có thể do việc kết nối cơ sở dữ liệu của bạn có vấn đề. Trong thẻ thì làm sao bạn có cách nào ngoài cách này.
tran ly said
Em chào Thầy!
Có cách nào dùng Crystal Report với JBoss 6 được không?
Rất mong được thầy giúp đỡ!
Võ Văn Hải said
“Có cách nào dùng Crystal Report với JBoss 6 được không?”
Câu trả lời là có nhưng hơi phức tạp. Hôm ào đó rỗi tôi sẽ viết 1 bài hương dẫn.
Tuy nhiên, sao bạn không dùng 1 công cụ report nào đó trên java nhỉ? Vừa miễn phí lại vừa hay lại vừa tương thích?
BIRT, Jasper,….