konhon

          忘掉過去,展望未來。找回自我,超越自我。
          逃避不一定躲的過, 面對不一定最難過, 孤單不一定不快樂, 得到不一定能長久, 失去不一定不再擁有, 可能因為某個理由而傷心難過, 但我卻能找個理由讓自己快樂.

          Google

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            203 Posts :: 0 Stories :: 61 Comments :: 0 Trackbacks

          常用鏈接

          留言簿(7)

          隨筆分類

          隨筆檔案

          相冊

          Business

          Download

          English

          Erp/Mrp

          HR

          J2me

          Java

          Linux/Unix

          Mobile Telephone

          Oracle

          Other

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          本文示范了如何用一個Java Servlet、一個JSP頁面和一個靜態Java類構造出一個SQL網關應用。利用這個應用,你可以直接在瀏覽器內執行SQL命令,瀏覽器將把SQL命令提交給遠程服務器上的數據庫系統,然后返回結果。

            如果你正在使用ISP(Internet Service Provider)提供的數據庫,可能已經熟悉SQL網關應用的概念了。有的ISP會提供一個操作數據庫的HTML頁面,就象本文提供的網關應用一樣。如果ISP沒有提供這樣的界面,你可以把本文的程序上載到服務器,以后要訪問ISP服務器上的數據庫就很方便了。

            SQL網關應用不僅可以用于開發過程,而且還可以直接提供給比較熟悉系統的最終用戶使用。當然,允許最終用戶直接在數據庫上運行SQL命令會帶來一些安全隱患,應當慎重考慮。

            本文要求讀者具備一定的Java、Servlet、JSP和數據庫的基礎知識,如果要運行本文的程序,還要有一個Servlet/JSP服務器和數據庫服務器。在下面的說明中,我們要使用的是Tomcat 4.0和MySQL,但它應該也能在其他JSP/Servlet容器中運行;如果你要改用MySQL之外的其他數據庫,只要提供一個適當的驅動程序,然后修改數據庫連接字符串就可以了。

            一、用戶界面

            圖1就是本文SQL網關的用戶界面。在這個界面中,SQL網關已經執行了一條SQL命令并返回了結果。



          圖1:SQL網關的用戶界面


            從圖1可以看出,頁面底部的一條信息顯示出最近執行的SQL命令影響的行數。如果SQL命令是一個SELECT語句,當SELECT語句執行成功,頁面底部將用HTML表格顯示出查詢結果,如圖二所示。



          圖2:HTML表格顯示出查詢結果集


            當然,如果SQL命令執行失敗,SQL網關將返回異常信息。

            二、設計JSP頁面

            在JSP頁面中,我們首先放入一個Scriptlet,它的功能是從session對象提取兩個屬性:

          <!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
          <% 
             String sqlStatement=(String)session.getAttribute("sqlStatement");
             if (sqlStatement == null)    sqlStatement = "";
             String message =  (String) session.getAttribute("message");
             if (message == null)  message = "";
          %>


            第一個屬性sqlStatement 表示SQL命令字符串,第二個屬性message 是包含結果信息的字符串。如果這兩個屬性的值是null,則表示它們尚未被設置,我們把sqlStatement和message變量設置成空字符串。

            JSP頁面還有一個HTML表單,HTML表單包含一個文本區域(TEXTAREA)和一個“執行”按鈕。

          <form action="../servlet/test.SQLGatewayServlet" method="post">
          <b>SQL命令:</b><br>
          <textarea name="sqlStatement" cols=60 rows=8>
          <%=sqlStatement%></textarea><br>
          <br>
          <input type="submit" value="執行">
          </form>


            表單中的文本區域用來輸入SQL命令。我們將sqlStatement變量的值作為文本區域的默認內容,文本區域的大小是寬60字符、高8行。當JSP頁面第一次運行時,這個文本區域的內容為空。如果用戶點擊文本區域下面的“執行”按鈕,JSP頁面把表單內容提交給SQLGatewayServlet(稍后再詳細介紹)。

            JSP頁面底部的表格顯示出message字符串的內容。如前所述,message的內容是運行SQL命令的結果。

          <b>SQL命令執行結果:</b><br>
          <table cellpadding="5" border="1">
          <%=message%>
          </table>


            三、編寫Servlet

            SQLGatewayServlet首先導入java.sql包以便使用JDBC類。另外,它還要聲明一個Connection對象,以便Servlet之內的所有方法都可以使用數據庫連接。

          package test;
          
          import java.io.*;
          import javax.servlet.*;
          import javax.servlet.http.*;
          import java.sql.*;
          
          public class SQLGatewayServlet extends HttpServlet{
          
              private Connection connection;


            當Servlet引擎開始運行這個Servlet,Servlet的init方法就打開一個數據庫連接:

          public void init() throws ServletException{
              try{
                  Class.forName("org.gjt.mm.mysql.Driver");
                  String dbURL = "jdbc:mysql://localhost/murach";
                  String username = "root";
                  String password = "";
                  connection = DriverManager.getConnection
          	(dbURL, username, password);
              }
              catch(ClassNotFoundException e){
                  System.out.println("找不到數據庫驅動程序.");
              }
              catch(SQLException e){
                  System.out.println("不能打開數據庫連接: "
                                     + e.getMessage());
              }
          }


            在這個例子中,Servlet利用一個MysQL數據庫的驅動程序打開murach數據庫的連接,數據庫和Servlet運行在同一個服務器上。此外,Servlet使用MySQL的默認用戶名字root,密碼為空。不過,你可以修改這里的代碼,只要有適當的驅動程序,就可以讓Servlet連接到任何服務器上的任何數據庫(有關MySQL數據庫的更多信息,請參見www.mysql.com)。

            Servlet引擎關閉Servlet之前,調用destroy方法關閉數據庫連接,釋放連接資源:

          public void destroy() {
              try{
                  connection.close();
              }
              catch(SQLException e){
                  System.out.println("不能關閉數據庫連接: " + e.getMessage());
              }
          }


            前面介紹的JSP頁面要調用Servlet的doPost方法,doPost方法調用doGet方法:

          public void doPost(HttpServletRequest request,
                             HttpServletResponse response)
                             throws IOException, ServletException{
               doGet(request, response);
           }


            在doGet方法之中,第一個語句首先獲取用戶在JSP頁面中輸入的SQL命令,第二個語句聲明message變量:

          public void doGet(HttpServletRequest request,
                             HttpServletResponse response)
                             throws IOException, ServletException{
          
               String sqlStatement = request.getParameter("sqlStatement");
               String message = "";


            然后,在try塊之內,第一個語句利用Connection對象創建Statement對象,接下來的兩個語句利用String對象的trim方法和substring方法返回用戶輸入的SQL命令的前六個字符。

          try{
               Statement statement = connection.createStatement();
               sqlStatement = sqlStatement.trim();
               String sqlType = sqlStatement.substring(0, 6);


            如果SQL命令的前六個字符是“select”,則利用Statement的executeQuery方法執行SQL語句,獲得一個ResultSet對象,把這個對象傳遞給SQLUtil類(稍后詳細說明)的getHtmlRows方法,getHtmlRows方法將把記錄集中的記錄格式化成HTML表格并返回。

          if  (sqlType.equalsIgnoreCase("select")){
               ResultSet resultSet = statement.executeQuery(sqlStatement);
               // 構造一個String,其中包含HTML表格形式的結果集數據
               message = SQLUtil.getHtmlRows(resultSet);
           }


            如果SQL語句的前六個字符不是“select”,則我們調用Statement對象的executeUpdate方法,executeUpdate方法返回當前操作影響的行數——如果這個數字是0,則該SQL命令是一個DDL命令,例如DROP TABLE或CREATE TABLE等;否則,則表明SQL命令可能是DML命令,如INSERT、UPDATE或DELETE命令。無論是哪一種SQL命令,我們都把message變量設置成相應的消息。

          else
               {
                   int i = statement.executeUpdate(sqlStatement);
                   if (i == 0) // 這是一個DDL命令
                     message =
                       "<tr><td>" +
                         "命令執行成功." +
                       "</td></tr>";
                   else // 這是一個INSERT、UPDATE或DELETE命令
                       message =
                         "<tr><td>" +
                           "SQL命令執行成功。<br>" +
                           "已更改" + i + " 行。" +
                          "</td></tr>";
               }
               statement.close();
           }


            如果try塊里面的任何一個語句拋出一個SQLException,catch塊就設置message變量,使其包含有關該SQLException的信息。例如,如果在表單中輸入的SQL命令語法錯誤,下面設置的message變量值將幫助你排解錯誤。

          catch(SQLException e){
              message = "<tr><td>執行SQL命令時遇到錯誤:<br>"
                      + e.getMessage() + "</tr></td>";
          }


            在catch塊之后,接下來的三個語句獲得session對象,把sqlStatement和message變量設置為session的屬性:

          HttpSession session = request.getSession();
           session.setAttribute("message", message);
           session.setAttribute("sqlStatement", sqlStatement);


            接下來,最后兩個語句創建一個RequestDispatcher,并轉發request和response對象給前文介紹的JSP頁面:

          RequestDispatcher dispatcher =
               getServletContext().getRequestDispatcher(
                   "/sql/sql_gateway.jsp");
           dispatcher.forward(request, response);


            四、編寫工具類

            下面來看看工具類SQLUtil的代碼:

          package test;
          import java.sql.*;
          public class SQLUtil{


            SQLUtil類包含一個getHtmlRows靜態方法,前面的Servlet正是通過調用該方法將結果集格式化成HTML表格。getHtmlRows的輸入參數是一個ResultSet對象,其返回值是一個String對象,這個String對象的內容是記錄集的所有列表題和行的HTML代碼。為了構造出這樣一個String對象,getHtmlRows聲明了一個名為htmlRows的StringBuffer對象,然后在方法執行過程中向這個StringBuffer對象追加數據。在getHtmlRows方法的末尾,我們用toString方法將StringBuffer的內容轉換成String,最后將這個String返回給Servlet:

          public static synchronized String getHtmlRows(ResultSet results)
          throws SQLException{
              StringBuffer htmlRows = new StringBuffer();
              ResultSetMetaData metaData = results.getMetaData();
              int columnCount = metaData.getColumnCount();
              // 將記錄集中列的名稱作為HTML表格列的標題
              htmlRows.append("<tr>");
              for (int i = 1; i <= columnCount; i++)
                  htmlRows.append("<td><b>" + metaData.getColumnName(i) + "</td>");
              htmlRows.append("</tr>");
              // 對于結果集中的每一行...
              while (results.next()){
                  htmlRows.append("<tr>");
                  // 將該行中的每一個列轉換成一個表格單元
                  for (int i = 1; i <= columnCount; i++)
                      htmlRows.append("<td>" + results.getString(i) + "</td>");
              }
              htmlRows.append("</tr>");
              return htmlRows.toString();
          }


            為了獲得記錄集對象的列標題,getHtmlRows方法利用ResultSet的getMetaData方法來創建一個ResultSetMetaData對象,ResultSetMetaData對象包含了有關記錄集的描述信息,例如列的數量、列的名稱可以分別調用ResultSetMetaData的getColumnCount和getColumnName方法獲得。

            為了提取記錄集的數據,getHtmlRows方法利用一個嵌套的循環,即while循環里面嵌套的for循環,來提取每一個行里面每一個列的值。在循環之內,我們用記錄集的getString方法來獲取各個字段的值,不管字段值原來的類型是什么,getString方法都會將它轉換成String。

            請注意這個方法的聲明中帶有synchronized關鍵詞,這是為了避免兩個或兩個以上的Servlet線程同時執行該方法。
          posted on 2006-03-13 02:30 konhon 優華 閱讀(641) 評論(0)  編輯  收藏 所屬分類: JSP/Servlet
          主站蜘蛛池模板: 萍乡市| 察雅县| 绍兴县| 册亨县| 诸城市| 五家渠市| 通山县| 延津县| 囊谦县| 宝清县| 兴仁县| 噶尔县| 乃东县| 轮台县| 乐亭县| 龙口市| 扬中市| 宁波市| 准格尔旗| 莱芜市| 双城市| 南涧| 古蔺县| 罗田县| 高淳县| 昭苏县| 西林县| 衡山县| 集贤县| 洮南市| 凤翔县| 长乐市| 平罗县| 新余市| 普安县| 陕西省| 陵川县| 惠安县| 临朐县| 安仁县| 英山县|