Servlet 技術全總結 (已完成,不按期增長內容)

Servlet是獨立於平臺和協議的服務器端的java應用程序,處理請求的信息並將其發送到客戶端。html

Servlet的客戶端能夠提出請求並動態得到響應。java

Servlet動態生成web頁面,擔當瀏覽器或其餘客戶端發出的請求與HTTP服務器上的數據庫或應用程序之間的中間層。web

對於全部客戶端請求,都只須要建立一次Servlet實例,所以,節省了大量內存。數據庫

 

Part 1     Servlet運行原理數組

web服務器收到一個http請求後,判斷請求內容,如果靜態頁面數據,自行處理,若爲動態數據,交給Servlet容器,Servlet容器找到相應Servlet實例處理;處理結果交給web服務器,再轉交給客戶端。瀏覽器

針對同一個Servlet,Servlet容器會在第一次收到HTTP請求時創建一個Servlet實例,而後啓動一個線程,第二次收到http請求後,Servlet容器無需建立相同Servlet ,僅開啓第二個線程來處理請求。緩存

----->多線程的方式有效提升執行效率,下降服務器負擔。安全

 

Part 2 Servlet 優點服務器

     Servlet具備優良的跨平臺性;cookie

     可移植性良好:java語言編寫,Servlet API標準完善,企業編寫的Servlet程序可輕鬆移植到其餘服務器中;

     執行效率高:Servlet請求到來時激活Servlet,處理完成後等待新請求;新請求產生新線程,而不是進程;

     使用方便:可輕鬆處理HTML表單數據,並讀取和設置HTTP頭,處理cookie,跟蹤會話;

 

Part 3 基礎知識

      HttpServlet做爲一個抽象類來建立用戶本身的Http Servlet. Http Servlet類擴展了GenericServlet類。HttpServlet類的子類必須至少重寫doGet()和doPost()方法其中之一。HttpServlet類提供doGet()方法處理GET請求,doPost()處理POST請求:

      doGet() :經過GenericServlet 類的service()方法來調用此方法;

      doPost():  經過GenericServlet 類的service()方法來調用此方法;

Part 4 Servlet生命週期     

      Servlet生命週期由Servlet容器控制,該容器建立Servlet的實例。Servlet的生命週期是指Servlet實例在建立後,響應客戶端請求直至銷燬的全過程;

      其建立取決於Servlet的首次調用。

       Servlet生命週期定義了它如何被加載,初始化,以及它如何接受請求,響應請求,提供服務;

       代碼中,Servlet生命週期由接口javax.servlet.Servlet定義,全部的Servlet必須直接或間接的實現該接口,這樣才能在Servlet容器中運行。

       Servlet接口定義了生命週期三種方法:

       1    init():建立實例後進行初始化。實現ServletConfig接口的對象做爲參數進行傳遞。在初始化過程當中,Servlet容器使用ServletConfig接口信息(如Servlet的初始化參數的名稱,初始化參數的值,以及Servlet實例名稱等)傳遞給Servlet。

public void init(ServletConfig config)throws ServletException

       2    service():響應客戶端發出的請求。service()方法接受ServletRequest接口和Servletresponse接口的對象來處理請求和發送響應;

public void service(ServleRequest request,ServletResponse response) throws ServletException,IOException

       3    destroy():若是再也不有須要請求的對象,則釋放Servlet對象;

public void destroy()

Servlet生命週期各階段:

1.實例化:Servlet容器建立Servlet類的實例對象;

2.初始化:容器調用Servlet的init()方法,一般會申請資源以便後續使用;

3.服務:由容器使用以響應客戶對Servlet的請求;

4.破壞:在釋放Servlet實例前調用,一般會釋放資源;

5.不可用:釋放內存中的容器;

[要實例化一個Servlet,容器必須先找到Servlet類,加載servlet類並建立Servlet對象,而後經過調用Servlet的init()方法來初始化Servlet。ServletConfig接口對象做爲參數傳給init()方法,該接口對象爲Servlet提供對ServletContext接口的訪問。Servlet容器使用ServletContext接口與Servlet容器進行通訊;

若是初始化Servlet失敗,則拋出UnavailableException或ServletException異常,並再次嘗試對Servlet進行實例化和初始化。而後將ServletRequest和ServletResponse接口做爲參數傳遞給service方法,該方法將處理請求並返回響應。

若是響應請求時發生異常,則容器經過調用destroy()方法卸載實例]

Part 5    Servlet API

 在javax.servlet和javax.servlet.http包中的各種和接口以下:

(1)ServletInputStream類

    從java.io.InputStream類擴展而來的抽象類,該類建立的對象用於讀取客戶端請求中的二進制數據,而該類的readLine()方法用於每次讀取一行數據;

        該方法將從給定偏移處開始的每字節讀取到數組中,直到該方法遇到換行符或者讀取完必定量的字節數量,該方法返回一個整數來指定實際讀取的字節數,到達流尾時返回-1

public int readLine(byte b[],int offset,int length)throws java.io.IOException
//b爲用於存儲讀取的數據的字節數組;offset指定方法開始讀取字符的起始位置;length讀取的最大字節數

 (2)ServletOutputStream類

     該類建立的對象用於將二進制數據從服務器發送到客戶端。具體實現的方法以下:

       +   print():將字符串寫入客戶端。若是發生任何輸入或輸出異常,則方法print()會引起IOException異常,print()方法接受參數,如char,float,double,int,long,String。

public void print(String str)throws java.io.IOException
//str爲發送到客戶端的字符串

       +     println():將字符串寫入客戶端,緊跟後面輸出回車。若是發生任何I/O異常,則會引起IOException

 (3)ServletRequest接口

     使用ServletRequest接口建立對象,用於使客戶端請求信息對Servlet可用。建立的對象做爲參數傳遞至Servlet的service()。

     該類實現方法以下:

       +     getInputStream():返回客戶端請求中的二進制數據,並將其保存在getInputStream對象中

public ServletInputStream getInputStream()throws IOException

       +     getParameter():用於獲取請求消息一塊兒發送的附加信息-----請求參數

public String getParameter(String str)

       +     getContentLength():返回客戶端發送的請求的實際長度,若是長度未知,則返回-1

public int getContentLength()

       +     getServerName():返回請求發至的服務器名稱

public String getServerName()

   (4)ServletResponse接口

       使用該接口建立的對象用於向客戶端提供響應。建立的對象做爲參數傳遞至Servlet的service()方法中。該接口實現的方法以下:

       +     getOutpouStream():返回一個ServletOutputStream對象,它被用來發送對客戶端的響應

public ServletOutputStream getOutputStream()throws IOException

       +     getWriter():返回將字符文本發送到客戶端的PrintWriter對象

public PrintWriter getWriter()throws IOException

       +      setContentLength():容許用戶設置將做爲響應放的數據的長度

public void setContentLength(int length)

       +      getBufferSize():檢索實際的以響應客戶端的緩存區大小。若沒有使用緩衝區則返回0

public int getBufferSize()

       +      setBufferSize():設置將發送到客戶端的數據的緩衝區的大小

public void setBufferSize(int size)

    (5)HttpServletRequest接口

         容器在調用Servlet的doGet()或doPost()方法時,會建立一個HttpServletRequest接口的實例和一個HttpServletResponse接口的實例,做爲參數傳遞給doGet和doPost()方法。該接口表明客戶請求,它提供了多種獲取請求數據的方法,具體繼承層次如圖:

    (6)HttpServletResponse接口

         該接口表明返回給客戶端的響應;具體繼承層次如圖:

     (7)ServletConfig接口

           在初始化過程當中,Servlet容器使用ServletConfig接口的對象做爲參數來傳遞Servlet的配置信息。方法以下:

              +    getServletName():用於獲取Servlet實例名稱

public String getServletName()

              +     getInitParameter():檢索初始化參數的值,若是參數不存在,則getInitParameter()方法返回null

public String getInitParameter(String name)
//name爲初始化參數的名稱字符串

              +     getServletContext():返回Servlet用來與其容器交互的ServletContext對象

public ServletContext getServletContext()

       (8)ServletContext接口

             該接口定義了一組方法,Servlet使用這些方法與容器進行交互並獲取信息(如讀寫文件等)

               +     getContext():返回容許Servlet訪問服務器上下文的ServletContext類對象

public ServletContext getServletContext(String uripath)
//uripath是Web容器上的另一個Web程序的上下文路徑名稱字符串

              +     getMimeType():返回文件的MIME類型。MIME定義了一種協議,容許用戶經過Internet交換非ASCII消息。不一樣的MIME類型分爲"text/html"和"image/gif"

public String getMimeType(String file)
//file是文件名稱

              +     getResource():返回與路徑名相對應的資源的URL

public java.net.URL getResource(String path) throws MalFormedURLexception
//path是資源對應的路徑名稱字符串

         (9)獲取請求中的數據

                在Servlet類的請求處理方法中(如doGet(),doPost()方法),要想得到客戶端請求中提交的數據,須要使用HttpServletRequest提供的如下方法:

public String getParameter(String name)
//獲取指定名稱的參數值

public String[] getParameterValues(String name)
//獲取指定名稱參數的全部值數組。它適用於一個參數名對應多個值的狀況,如頁面表單中的複選框,多選列表提交的值

public java.util.Enumeration getParameterNames()
//返回一個包含請求消息中的全部參數名的Enumeration對象。經過遍歷這個Enumeration對象,就能夠獲取請求消息中全部的參數名

public java.util.Map getParameterMap()
//返回一個保留了請求消息中全部參數名和值的Map對象。Map對象的key是字符串類型的參數名,value是這個參數所對應的Object類型的值數組。

        [提示:在此說明如何處理客戶端提交給服務器的數據的亂碼問題

                  若客戶端以POST方式提交請求,請求消息主體中的參數數據是按HTML頁面中指定的編碼方式進行編碼的,在Servlet類的請求處理方法中須要先調用         HttpServletRequest接口的setCharacterEncoding(String enc)方法對請求消息主體中的數據按參數指定的編碼方式進行編碼,而後才能使用上述介紹的方法正 確得到參數值

                  若客戶端使用GET方法請求,上述方法無效,此時,最好的解決方案是在URL中不使用中文等非ASCII字符]

        (9)重定向和請求分配

              1.重定向:HttpServletRequest接口提供的sendRedirect()方法用於生成302響應碼和Location響應頭從而通知客戶端去從新訪問Location響應頭中指定的URL

public void sendRedirect(String location)throws IOException
//其中location參數指定了重定向的URL,它可使用絕對或相對URL,Servlet會進行轉化           

             2.請求分派:RequestDispatcher接口,(分派器),定義了下面兩個方法

public void forward(ServletRequest request,ServletResponse response)throws ServletException,IOException;
//forward()用於將請求轉發到RequestDispatcher實例封裝的資源

public void include(ServletRequest request,ServletResponse response)throws ServletException,IOException;
//include()用於將RequestDispatcher實例封裝的資源做爲當前響應內容的一部分包含進來

 

RequestDispatcher dispatcher=request.getRequestDispatcher("servlet1");
//參數爲當前servlet名稱

dispatcher.forward(request,response);

     [重定向與請求分派的區別:

             請求分派只能將請求轉發到同Web應用中的其餘組件;而重定向也能夠發送到其餘Web;

             請求分派過程結束後,瀏覽器內網址不改變;重定向完成後瀏覽器內原網址變爲重定向目標網址;

             ]

    (11)利用請求域屬性傳遞對象數據

          HttpServletRequest接口中提供了幾個方法來操做請求實例中的存儲對象

public void setAttribute(String name,Object obj)
//將對象存儲進HttpServletRequest實例中

public Object getAttribute(String name)
//檢索存儲在HttpServletRequest實例中的對象

public Enumeration getAttributeNames()
//返回HttpServletRequest實例中全部屬性名的Enumeration對象

public void removeAtribute(String name)
//從指定HttpServletRequest實例中刪除指定名稱的屬性

        這種存儲在HttpServletRequest中的對象稱之爲請求域屬性,屬於同一請求過程的多個處理模塊之間能夠經過請求域屬性來傳遞對象數據;

//Servlet1.java
package test

import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.*;

public class Servlet1 extends HttpServlet{
         public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
              this.doPost(request,response);
        }

         public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
              String str="Job done";
              request.setAttribute("string",str);
              RequestDispatcher dispatcher=request.getRequestDispatcher("Servlet2");
              dispatcher.forward(request,response);
        }

}
//Servlet2.java
package test

import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.*;

public class Servlet2 extends HttpServlet{
         public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
              this.doPost(request,response);
        }

         public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
              response.setContentType("text/html;charset=utf-8");
              PrintWriter out=response.getWriter();
              out.println("<html>");
              out.println("<head><title>test</title><head>");
              out.println("<body>");

              //獲取名爲"string"的請求域屬性的值
              String str=(String)request.getAttribute("string");
              
              out.println(str);
              out.println("</body>");
              out.println("</html>");
        }

}

 Part 6   Servlet的線程安全問題 

     Servlet默認是多線程模式執行的,當有多個用戶同時併發請求一個Servlet時,容器將啓動多個線程調用相應的請求處理方法,此時,請求處理方法中的局部變量是安全的,但對於成員變量和共享數據是不安全的,所以這多個線程有可能同時都操做這些數據,這是須要同步處理。因此,編寫代碼時須要很是細緻的考慮多線程的安全性問題。多數人編寫Servlet時不注意多線程問題,致使少許用戶訪問時沒有問題,但併發量大則出現莫名其妙的問題。

    解決: 

    1.使用synchronized:使用synchonized關鍵字同步操做成員變量和共享數據的代碼,就能夠防止出現線程安全性問題,但這也意味着線程須要排隊處理。所以,在使用同步語句時要儘量縮小同步代碼範圍,不能直接在請求處理方法(如doGet(),doPost()方法)使用同步,這樣會嚴重影響效率。

    2.儘可能少使用成員變量和共享數據:對於集合,使用Vector代替非線程安全的ArrayList,使用Hashtable代替HashMap;不能在Servlet內建立本身的線程,致使複雜化。

 

Part 7   Servlet  過濾器

過濾器技術(Filter)是Servlet2.3以上版本新增的功能,2.5對其進一步加強。

Filter是一個程序,它先於相關的Servlet或JSP頁面運行在服務器上。過濾器可附加到多個或一個Servlet或JSP上,而且能夠檢查進入這些資源的請求消息。

Filter在Request到達Servlet以前預處理,也能夠在離開Servlet時處理Response;其實本質就是一個Servlet Chaining.

 一個Filter必須實現javax.servlet.Filter接口並定義三個方法:

public void init(FilterConfig config)
//Filter實例化後進行初始化的回調方法

public void doFilter(ServletRequest req,ServletResponse res,FilterChain chain)
//處理過濾業務的方法

public void destroy()
//Filter釋放時回調的方法

每個Filter從doFilter()方法中獲得當前的request和response。在該方法內,可進行任何針對request和response的操做。Filter調用chain.doFilter()方法把控制權交給下一個Filter。

實例:Filter處理中文亂碼問題:

import java.io.IOException;
import javax.servlet.*;

public class CharacterEncodingFilter implements Filter{
  private FilterConfig config;
  public void destroy(){
  }
  public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)throws IOException,ServletException{
     String encoding=config.getInitParameter("encoding");
     if(null!=encoding&&!"".equals(encoding)){
        request.setCharacterEncoding(encoding);
     }
     chain.doFilter(request,response);
     //將修改過的請求和響應傳遞給下一個過濾器或者Servlet
  }

  //Filter初始化時的回調方法
  //FilterConfig接口實例中封裝了這個Filter的初始化參數
  public void init(FilterConfig config){
     this.config=config;
  }
}

在web.xml中註冊

......
    <filter>
         <filter-name>characterEncodingFilter</filter-name>
         <filter-class>(路徑).characterEncodingFilter</filter-class>
         <init-param>
                <param-name>encoding</param-name>
                <param-value>UTF-8</param-value>
          </init-param>
    </filter>
    <filter-mapping>
          <filter-name>characterEncodingFilter</filter-name>
          <url-pattern>/*</url-pattern>
    </filter-mapping>
.........

此處/*是過濾全部頁面請求,若是須要,能夠指定頁面 或文件夾下的全部頁面。

 

過濾鏈:爲web添加按順序執行的多個Filter,進入時執行順序A-B,離開時執行順序B-A

排列方法是在web.xml中,按順序註冊便可;

以下示例:(在上一示例基礎上添加一個能夠自動壓縮響應輸出流的Filter,提升傳輸效率)

......
    <filter>
         <filter-name>characterEncodingFilter</filter-name>
         <filter-class>(路徑).characterEncodingFilter</filter-class>
         <init-param>
                <param-name>encoding</param-name>
                <param-value>UTF-8</param-value>
          </init-param>
    </filter>
    <filter-mapping>
          <filter-name>characterEncodingFilter</filter-name>
          <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
         <filter-name>Compression Filter</filter-name>
         <filter-class>compressionFilters.CompressionFilter</filter-class>
         <!--設置緩衝區大小-->
         <init-param>
                <param-name>compressionThreshold</param-name>
                <param-value>512</param-value>
          </init-param>

          <!--調試級別-->
          <init-param>
                <param-name>debug</param-name>
                <param-value>0</param-value>
          </init-param>
    </filter>
    <filter-mapping>
          <filter-name>Compression Filter</filter-name>
          <url-pattern>/*</url-pattern>
    </filter-mapping>
.........    

便可實現Filter Chain。

Part 8  Servlet 監聽器      

監聽器可以使應用對某些事件作出反應:

Servlet2.3以上版本提供了一下幾個接口:

      +   ServletContextListener:應用上下文生命週期監聽器,用於監聽Web應用的啓動和銷燬事件;

      +   ServletContextAttributeListener:應用上下文屬性事件監聽器,用於監聽Web應用上下文中的屬性改變事件;

      +   ServletRequestListener:請求生命週期監聽器,監聽請求的建立和銷燬;

      +   ServletRequestAttributeListener:請求屬性事件監聽器,用於監聽請求中的屬性改變事件;

      +   HttpSessionListener:會話生命週期監聽器,用於監聽會話的建立和銷燬;

      +   HttpSessionActivationListener:會話激活和鈍化事件監聽器;

      +   HttpSessionAtributeListener:會話屬性事件監聽器;

      +   HttpSessionBindingListener:會話值綁定事件監聽器;

每一個監聽器接口都定義了一些回調方法,當對應事件發生後,Web容器會自動調用對應監聽器實現類中的相關方法。

實例:用監聽器統計web在線人數: 

//OnlineListener.java

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

public class OnlinListener implements ServletContextListener,HttpSessionAttributeListener,HttpSessionListener{
   private ServletContext application=null;
 
   public void attributeAdded(HttpSessionBindingEvent arg0){
   List<String>  online= (List<String>)this.application.getAttribute("online");
   
      if("uesrname".equals(arg0.getName())){
          online.add((String)arg0.getValue());
      }
    this.application.setAttribute("online",online);
    }
    
    //實現空方法
    public void attributeRemoved(HttpSessionBindingEvent arg0){}
    public void attributeReplaced(HttpSessionBindingEvent arg0){}
    public void sessionCreated(SessionEvent arg0){}

   //銷燬時的回調方法
    public void sessionDestroyed(HttpSessionEvent arg0){
       List<String> online=(List<String>)this.application.getAttribute("online");
       String username=(String)arg0.getSession().getAttribute("username");
       online.remove(username)
       this.application.setAttribute("online",online);
    }

    public void contextDestroyed(ServletContextEvent arg0){}

    public void contextInitialized(ServletContextEvent arg0){
        this.application=arg0.getServletContext();
        this.application.setAttribute("online",new LinkedList<String>());
    }
}        

在web.xml中註冊:

...
<listener>
    <listener-class>....</listener-class>
</listener>
...

 最後,建立幾個Servlet測試監聽器實現效果:

import java.io.*;
import java.util.List;
import javax.servlet.ServletExcetion;
import javax.servlet.http.*;

public class LoginServlet extends HttpServlet{
  public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
     this.doPost(request,response);
  }
   public void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
      request.setCharacterEncoding("UTF-8");
      String username=request.getParameter("username");

      //向session中添加屬性
      //觸發HttpSessionAttributeListener中的AttributeAdded方法
      if(usesrname!=null&& !username.equals("")){
          request.getSession().setAttribute("username",username);
      }
      List<String> online=(List<String>)getServletContext().getAttribute("online");

      response.setContentType("text/html;charset=utf-8");
      PrintWriter out=response.getWriter();
      out.println("<HTML>");
      out.println("<HEAD><TITLE>用戶列表</TITLE></HEAD>");
      out.println("<BODY>");
      out.println("當前用戶是:"+username);
      out.println("<hr/><h3>在線用戶列表</h3>");

      int size=online==null?0:online.size();
       for(int i=0;i<size;i++){
           if(i>0){
               out.println("<br/>");
           }
           out.println(i+1+"."+online.get(i));
       }
      
      //注意,此處對連接URL進行重寫
      out.println("<hr/><a href=\""+response.encodingUrL("logout")+"\">註銷</a>"); 
      out.println("</BODY>");
      out.println("</HTML>");
      out.flush();
      out.close();
   }
}
import java.io.*;
import java.util.List;
import javax.servlet.ServletExcetion;
import javax.servlet.http.*;

public class LogoutServlet extends HttpServlet{
  public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
     this.doPost(request,response);
  }
   public void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
      request.setCharacterEncoding("utf-8");
      //銷燬會話,觸發SessionListener中的SessionDestroyed方法
      request.getSession().invalidate();

     
      List<String> online=(List<String>)getServletContext().getAttribute("online");

      response.setContentType("text/html;charset=utf-8");
      PrintWriter out=response.getWriter();
      out.println("<HTML>");
      out.println("<HEAD><TITLE>用戶列表</TITLE></HEAD>");
      out.println("<BODY>");
      out.println("當前用戶是:"+username);
      out.println("<hr/><h3>在線用戶列表</h3>");

      int size=online==null?0:online.size();
       for(int i=0;i<size;i++){
           if(i>0){
               out.println("<br/>");
           }
           out.println(i+1+"."+online.get(i));
       }
      
      //注意,此處對連接URL進行重寫
      out.println("<hr/><a href=\"index.html\">主頁</a>"); 
      out.println("</BODY>");
      out.println("</HTML>");
      out.flush();
      out.close();
   }
}

最後建立index.html裏面添加表單

....
<form action="login" method="post">
      用戶名:<input type="text" username"/>
      <input type="submit" value="登陸"/><br/><br/>
</form>
....

 

Part 9  我的寫法

在這裏介紹下本人以爲比較好的寫法,感受很相似Spring MVC,寫起來很簡單,並且運行效率高。

下圖是項目目錄,分爲DAO,Entity,util,和最後一個:Servlet

Entity:java Beans (setter;getter); DAO 操做數據庫(本人使用JDBC);util(主要就是dbUtil,負責建立鏈接和關閉);最後一個:Servlet,其實只有一個,我將它命名爲ActionServlet,負責接收處理Request,其實做用至關於DispatcherServlet (Spring)

 

//核心代碼

public class ActionServlet extends HttpServlet {

    public void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        String uri = request.getRequestURI();
        String action = uri.substring(
                uri.lastIndexOf("/"),uri.lastIndexOf("."));
        if(action.equals("/regist")){
            //先進行驗證碼的檢驗
            //用戶名是否存在
            String username = request.getParameter("username");
            UserDAO dao = new UserDAO();
            try {
                User user = dao.findByUsername(username);
                if(user != null){
                    request.setAttribute(
                            "regist_error", "用戶名已經存在");
                    request.getRequestDispatcher("regist.jsp")
                    .forward(request, response);
                }else{
                    user = new User();
                    //populate方法:會依據Map中的key
                    //去給user對象對應的屬性賦值。
                    BeanUtils.populate(user, 
                            request.getParameterMap());
                    int id = dao.save(user);
                    //爲用戶新建一個用來保存文件的文件加
                    String path = 
                        getServletContext().getRealPath("upload");
                    File file = new File(path + "\\" + "pic_" + id);
                    if(!file.exists())
                        file.mkdirs();
                    response.sendRedirect("login.html");
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new ServletException(e);
            }
        }else if(action.equals("/login")){
            String username = request.getParameter("username");
            String pwd = request.getParameter("pwd");
            UserDAO dao = new UserDAO();
            try {
                User user = dao.findByUsername(username);
                if(user !=null && user.getPwd().equals(pwd)){
                    //登陸成功
                    HttpSession session = 
                        request.getSession();
                    session.setAttribute("user", user);
                    response.sendRedirect("projectlist.do");
                }else{
                    request.setAttribute("login_error",
                            "用戶名或密碼出錯");
                    request.getRequestDispatcher("project_list.jsp")
                    .forward(request, response);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else if(action.equals("/list")){
            UserDAO dao = new UserDAO();
            try {
                List<User> users = dao.findAll();
                request.setAttribute("users", users);
                request.getRequestDispatcher("user_list.jsp")
                .forward(request, response);
            } catch (Exception e) {
                e.printStackTrace();
                throw new ServletException(e);
            }
        }else if(action.equals("/userDetail")){
            int id = Integer.parseInt(request.getParameter("id"));
            UserDAO dao = new UserDAO();
            PicDAO dao2 = new PicDAO();
            try {
                User user = dao.findByUserId(id);
                List<Pic> pics = dao2.findPics(id);
                request.setAttribute("user", user);
                request.setAttribute("pics", pics);
                request.getRequestDispatcher("userDetail.jsp")
                .forward(request, response);
            } catch (Exception e) {
                e.printStackTrace();
                throw new ServletException(e);
            }
            

在web.xml中註冊時,只須要註冊這個Servlet,便可獲取全部請求,分析其名稱,使用相應的DAO方法操做數據庫,搞定!

(正在更新)

相關文章
相關標籤/搜索