1. 程式人生 > >Web開發&建立專案連線資料庫

Web開發&建立專案連線資料庫

web學習過程中,操作資料庫是經常性的,一般只開發小型的專案,用mysql就可以完成功能,如果開發大型專案,一般藉助oracle。這裡示例myeclipse來連線mysql。首先確保電腦安裝了mysql資料庫。我用的是mysql5.6版本。
mysql連線web專案使用的jar包
1,新建名為mobile的web專案,下載mysql連線java的jar包,將jar包直接放在web專案lib目錄下,或者builder path引入。
這裡寫圖片描述
若沒有特別需求,儘量使用穩定的jdk和tomcat版本,避免不必要的麻煩。
2,為使用方便,新建單獨的類檔案連線資料庫,操作資料庫使只要使用相應方法就可以了。
這裡寫圖片描述


在src目錄下新建一個util包,該包裡面放置web開發需要使用的工具類,這裡我新建了三個類,Jdbc類操作資料庫,Log類用於控制檯輸出日誌或者將日誌輸出到檔案,User類是資料庫表中屬性對應的類。簡單而言,Jdbc類相當於DAO,User相當於VO。
連線資料庫程式碼:

Class.forName("com.mysql.jdbc.Driver");//利用反射例項化驅動類。
Connection conn = DriverManager.getConnection(
                    "jdbc:mysql://localhost:3306/mobile", "root"
,"0000");//與本地資料庫建立連線,第一個引數是url,表示連線到mysql的名為mobile的database,第二個引數為使用者名稱,預設的情況下為“root”,第三個引數為進入資料庫的密碼。 Statement stat=conn.createStatement();//新建操作資料庫語句的物件,該物件用來完成資料庫的增刪改查工作。

為了操作資料的安全性,一般都會將一系列的資料操作整體以事務形式提交,這樣即便執行過程中有異常,也可以保證資料的同步性。

conn.setAutoCommit(false);//設定事務不自動提交
//******操作資料庫
conn.commit();//提交事務
conn.close
();//關閉conn stat.close();// 關閉stat

3,專案jsp與servlet
在src目錄下新建的類檔案,在專案釋出到伺服器上時,會在專案web-inf目錄下的class資料夾下,生成相應的包和.class檔案,但路徑仍然可以用/mobile/包名/類名 訪問到。
web-inf目錄下的class檔案具有私有性,客戶端通常不可直接訪問,一般收費專案等檔案可以放在該目錄,在myeclipse中,class資料夾預設隱藏。

這裡寫圖片描述
這是新建的src目錄下servlet包下的java檔案,tomcat會自動生成.class檔案並置於class資料夾下。

這裡寫圖片描述
這裡寫圖片描述
jsp檔案在經過tomcat處理,也會生成servlet類,生成對應的java檔案以及.class檔案;jsp檔案本身位於專案的目錄之下,生成的檔案位於tomcat目錄的work目錄下。可以從圖片地址中位址列找到對應的檔案位置。

對於一個簡單的jsp檔案,可以看一下生成的java類具體程式碼,以error500.jsp為例
這是error500.jsp程式碼,是一個標準的jsp檔案。

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <title>伺服器錯誤</title> 
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->
  </head>
  <body>
    <center><h1>500</h1></center><br>
    <center><h1><b>服務端解析異常</b></h1></center>
  </body>
</html>

檢視error500.jsp生成的java檔案——error500_jsp.java

package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.util.*;

public final class error500_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

  private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory();

  private static java.util.List _jspx_dependants;

  private javax.el.ExpressionFactory _el_expressionfactory;
  private org.apache.AnnotationProcessor _jsp_annotationprocessor;

  public Object getDependants() {
    return _jspx_dependants;
  }

  public void _jspInit() {
    _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
    _jsp_annotationprocessor = (org.apache.AnnotationProcessor) getServletConfig().getServletContext().getAttribute(org.apache.AnnotationProcessor.class.getName());
  }

  public void _jspDestroy() {
  }

  public void _jspService(HttpServletRequest request, HttpServletResponse response)
        throws java.io.IOException, ServletException {

    PageContext pageContext = null;
    HttpSession session = null;
    ServletContext application = null;
    ServletConfig config = null;
    JspWriter out = null;
    Object page = this;
    JspWriter _jspx_out = null;
    PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html;charset=UTF-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
                null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write('\r');
      out.write('\n');

String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

      out.write("\r\n");
      out.write("\r\n");
      out.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
      out.write("<html>\r\n");
      out.write("  <head>\r\n");
      out.write("    <base href=\"");
      out.print(basePath);
      out.write("\">\r\n");
      out.write("    \r\n");
      out.write("    <title>伺服器錯誤</title>\r\n");
      out.write("    \r\n");
      out.write("\t<meta http-equiv=\"pragma\" content=\"no-cache\">\r\n");
      out.write("\t<meta http-equiv=\"cache-control\" content=\"no-cache\">\r\n");
      out.write("\t<meta http-equiv=\"expires\" content=\"0\">    \r\n");
      out.write("\t<meta http-equiv=\"keywords\" content=\"keyword1,keyword2,keyword3\">\r\n");
      out.write("\t<meta http-equiv=\"description\" content=\"This is my page\">\r\n");
      out.write("\t<!--\r\n");
      out.write("\t<link rel=\"stylesheet\" type=\"text/css\" href=\"styles.css\">\r\n");
      out.write("\t-->\r\n");
      out.write("\r\n");
      out.write("  </head>\r\n");
      out.write("  \r\n");
      out.write("  <body>\r\n");
      out.write("    <center><h1>500</h1></center><br>\r\n");
      out.write("    <center><h1><b>服務端解析異常</b></h1></center>\r\n");
      out.write("  </body>\r\n");
      out.write("</html>\r\n");
    } catch (Throwable t) {
      if (!(t instanceof SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try { out.clearBuffer(); } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
        else log(t.getMessage(), t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}

程式碼明顯要長的多,可以來分析一下,jsp生成的java原始碼到底什麼意思:
開始第一行,表示將該java類打包到org.apache.jsp包下,我們可以只當作是一個路徑對映。
然後可以看到該類繼承自org.apache.jasper.runtime.HttpJspBase,這是一個apache自定義的類,而一般的servlet繼承自HttpServlet類,該類全路徑為javax.servlet.http.HttpServlet。很明顯自定義的servlet可以不借助tomcat就能完成一般的功能。
隔過中間部分看_jspService(HttpServletRequest request, HttpServletResponse response)方法,該方法內部定義了八個變數,其中兩個重複,在加上requset以及response兩個引數,以及沒有使用的exception,正好是jsp內建的九個物件,這九個物件可以直接使用,不需要例項化(tomcat會自動新增這些程式碼)。
jsp內建的九大物件及其對應的類分別為:

javax.servlet.Jsp.JspWriter out;
/*out物件是我們最多的一個,雖然jsp中看不到,但客戶端呈現的html的內容,都是該物件‘寫’到瀏覽器的。該物件主要是把資訊填充到輸出流,在瀏覽器訪問的時候把內容傳給瀏覽器,而瀏覽器自身負責將獲取的資訊顯示出來。 */
javax.servlet.http.HttpServletRequest request;
/*request物件是瀏覽器訪問某個url時,以引數的形式傳入的物件,通過該物件可以讀取到客戶端瀏覽器所在主機的網址,進行訪問的埠,瀏覽器的型別,版本,協議等等,也可以通過request.getRequestDispatcher("/mobile/index.jsp").forward(request, response)方式進行頁面跳轉,此種方式跳轉後的兩個頁面,有相同的request,若request物件本身攜帶大量的資料,可以使用此種方法。此種方法相當於使用標籤<jsp:forward page=""></jsp:forward>,這種方式跳轉時,只能訪問自身專案下的檔案,不能跨域或者其他應用程式,jsp:forward後跟的url,根目錄相當於/mobile,即如果需要轉到/mobile/jsp/index.jsp,則應寫為page="/jsp/index.jsp",而不是page="/mobile/jsp/index.jsp";。另外web開發中如果不明白的話,地址儘量用絕對定址方式,以/開頭,避免出錯*/
javax.servlet.http.HttpServletResponse response;
/*response物件與request物件有些相反,request是客戶端發起的請求,response是伺服器對客戶端的相應;response.sendRedirect(String url),利用response可以操作瀏覽器進行重定向,即要求客戶端對一個新的url發起請求,此url是可以跨域的,可以利用response來設定out物件向瀏覽器輸出資訊時的編碼,可以通過response.setHeader("Refresh","1")設定客戶端每秒進行重新整理,可以設定網頁的一系列基本屬性。*/
javax.servlet.http.HttpSession session;
/*session物件使用的很多,一般購物車等功能都需要session來實現。session就沒有攜帶的資訊,sesson的使用與application等大致相同,都是藉助setAttribute與getAttribute方法*/
javax.servlet.ServletContext application;
/*application相當於服務端的sessoin,只有當伺服器關閉時,application物件才會被銷燬,可以儲存全域性的變數,例如統計一個網站的訪問量等等*/
java.lang.Throwable exception;
/*exception物件不經常看到,主要是用來使用者輸入的或者不可預見的錯誤,只有當頁面的isErrorPage屬性為true時,該物件才可以被使用,否則報錯。另外說明,我們常見的Exception物件是直接繼承Throwalbe的*/
javax.servlet.Jsp.PageContext pageContext;
/*pageContext物件可以直接訪問其餘的幾個物件,一般而言,java程式中都會有一個context物件,此物件可以管理所有的資源,例如安卓開發中的application中的context物件,另外借助pageContext物件便可以完成page,request,session,application的資料儲存讀取的功能*/
javax.servlet.ServletConfig config;
/*config物件是在jsp程式初始化時傳遞訊息使用的,主要是jsp引擎用來向jsp程式傳遞引數以及伺服器的有關資訊,不經常見到*/
java.lang.Object page;
/*該物件是隻jsp頁面本身,即this,利用page物件可以匯入包,可以設定編碼,設定路徑,設定語言等等,就是jsp頁面開始的<%@ page *** %>部分,一般每一個jsp頁面都會用到*/

session和cookie的區別及實現原理
往下便可以看出,系統是將jsp中<%%>之外的所有程式碼都以out.write()的方式“寫”到了java類中,這也是為什麼jsp中java程式可以跨越多個段落的原因。很清楚的發現,客戶端瀏覽器頁面原始碼便是out.write的部分。

現自己編寫一個servlet,名字為ReturnUsers,在servlet包下;來處理某些功能

package servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.ws.RespectBindingFeature;

public class ReturnUsers extends HttpServlet {
//servlet都需要在web.xml中註冊,否則會有405異常,405異常是指伺服器不允許靜態檔案接受post訪問請求。
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        String line;
        line="<?xml version='1.0' encoding='UTF-8'?>";
        line+="<user>";
        line+="<account>"+"1111"+"</account>";
        line+="<password>"+"2222"+"</password>";
        line+="</user>";
        PrintWriter out=resp.getWriter();
        out.print(line);
        //自己拼接xml檔案,將字串傳輸到客戶端。
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        super.doPost(req, resp);
        doGet(req, resp);
    }

}

一般而言,只要重寫doGet以及doPost方法就可以了,訪問該servlet時,會將response與request當作引數傳入,在servlet中可以採取如下方式獲取之前jsp中的內建物件:

PrintWriter out=response.getWriter();//獲取out物件,這裡的out物件與jsp中out物件雖然功能一樣,但卻是不同的兩個類。
HttpSession session=request.getSession();//獲取session物件
ServletContext application=this.getServletContext()//獲取application物件,this是指該servlet自身,this即是page物件。
PageContext pageContext=JspFactory.getDefaultFactory().getPageContext(this,request,response,null,false,JspWriter,DEFAULT_BUFFER,true);//獲取pageContext物件,可以看到pageContext包含了很多內容
ServletConfig config=this.getServletConfig();

這個servlet中,自動拼接了一個xml格式字串,利用out輸出到瀏覽器,瀏覽器獲得的原始碼為

這裡寫圖片描述
可以看到與line字串相同。
在servlet編寫之後編譯器會自動的在web.xml中進行註冊,該servlet註冊程式碼為:

  <servlet>
    <servlet-name>ReturnUsers</servlet-name>
    <servlet-class>servlet.ReturnUsers</servlet-class>
    <!--該servlet類的全名-->
  </servlet>
  <servlet-mapping>
    <servlet-name>ReturnUsers</servlet-name>
    <!--這裡servlet-name和上一個配置的servlet-name必須相同-->
    <url-pattern>/servlet/ReturnUsers</url-pattern>
    <!--該servlet類所處的路徑,這路徑是相當與web-inf/classes資料夾而言的-->
  </servlet-mapping>

如果需要訪問該servlet類,可以使用地址/mobile/servlet/ReturnUsers,很顯然如果此時mobile專案如果根目錄下同樣有一個servlet資料夾,裡面放置了一個ReturnUsers檔案,那麼兩個檔案會發生衝突,此時系統會預設讀取名為ReturnUsers的servlet類,如果該類不存在,才會去讀取專案mobile根目錄的資料夾servlet下的檔案ReturnUsers。
servlet後也可以手工的新增引數資訊,在servlet內部可以通過request.getParameter()方法獲取,如訪問url:/mobile/servlet/ReturnUsers?name=”1111”

另外,web.xml檔案可以配置出錯頁面,加入碰到已經定義的異常程式碼,會跳轉到對應的頁面:

  <error-page>
    <error-code>500</error-code>
    <location>/error500.jsp</location>
  </error-page>
  <error-page>
    <error-code>404</error-code>
    <location>/error404.jsp</location>
  </error-page>
  <!-- 當發生404和500錯誤時,跳轉到對應的頁面 -->

4,mysql檔案儲存編碼,設定儲存中文。
mysql預設是不可以儲存中文的,開啟mysql控制檯,輸入show variables like ‘character_set_%’;
可以看到如下頁面:
這裡寫圖片描述
其中有一行:character_set_database 的值為latinl,說明資料庫編碼方式不是utf-8,可以進行修改,輸入:set character_set_database=utf8;
然後在輸入show variables like ‘character_set_%’可以看到
這裡寫圖片描述
之後就可以儲存中文了。
然而大多時候這種修改方式只對當前會話有用,因此想要解決該問題,需要修改底層的配置檔案。詳細步驟參考文件:
mysql編碼支援中文
因資料庫版本不同,且網上大多數只是重複的抄襲甚至有些根本無用,我把使用的方法記錄下來:
第一:web連線mysql後,當執行新建資料庫或表格時設定編碼:

create database mobile default charset=utf8;
create table user default charset=utf8;

第二,在jdbc連線資料庫時在url中新增編碼方式:

DriverManager.getConnection("jdbc:mysql://localhost:3306/mobile?unicode=true&characterEncoding=utf8","XXXX","XXXX");

是utf8而不是utf-8,中間是&號。

如果有時想把傳遞的漢字放在url裡跳轉到另外jsp頁面或交給servlet處理,則需要在jsp或者servlet中新增如下程式碼:

String information=new String(request.getParameter("information").getBytes("iso8859-1"),"utf-8");

因為url預設是iso編碼,因此需要先以iso編碼方式轉換成字元流,再以utf-8編碼轉換為字串。information是url中攜帶資訊的變數名字。