Servlet詳解

如果網(wǎng)頁(yè)顯示的內(nèi)容在服務(wù)器的數(shù)據(jù)庫(kù)中,除了負(fù)責(zé)顯示的HTML標(biāo)記之外,必須還要有完成這些業(yè)務(wù)功能的代碼存在。這種網(wǎng)頁(yè)我們就叫做動(dòng)態(tài)網(wǎng)頁(yè)。為了實(shí)現(xiàn)動(dòng)態(tài)網(wǎng)頁(yè)的目標(biāo),JavaServlet技術(shù)因應(yīng)而生,它能夠以一種可移植的方法來(lái)提供動(dòng)態(tài)的、面向用戶的內(nèi)容。

Servlet的運(yùn)行過(guò)程

⒈ 客戶端發(fā)送請(qǐng)求至服務(wù)器端;
⒉ 服務(wù)器端根據(jù)web.xml文件中的Servlet相關(guān)配置信息,將客戶端請(qǐng)求轉(zhuǎn)發(fā)到相應(yīng)的>Servlet
⒊ Servlet引擎調(diào)用Service()方法,根據(jù)request對(duì)象中封裝的用戶請(qǐng)求與數(shù)據(jù)庫(kù)進(jìn)行交>互,返回?cái)?shù)據(jù)之后,Servlet會(huì)將返回的數(shù)據(jù)封裝到response對(duì)象中;
⒋ Servlet生成響應(yīng)內(nèi)容并將其傳給服務(wù)器。響應(yīng)內(nèi)容動(dòng)態(tài)生成,通常取決于客戶端>的請(qǐng)求 
⒌ 服務(wù)器將響應(yīng)返回給客戶端

配置文件

<servlet>
    <servlet-name>login</servlet-name>
    <servlet-class>com.cn.control.LoginServlet</servlet-class>
  </servlet>
  
  <servlet>
    <servlet-name>upload</servlet-name>
    <servlet-class>com.cn.control.FileServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>login</servlet-name>
    <url-pattern>/login</url-pattern>
  </servlet-mapping>
  
  <servlet-mapping>
    <servlet-name>upload</servlet-name>
    <url-pattern>/upload</url-pattern>
  </servlet-mapping> 

servlet處理過(guò)程

public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    ...
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        this.doPost(request, response);
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        
        System.out.println("login............");
        
        String username = (String) request.getParameter("username");
        String pass = (String)request.getParameter("pass");
        
        System.out.println("login............"+username+"==="+pass);
        
        User user = new User();
        user.setPass(pass);
        user.setUsername(username);
        
//      if(new LoginService().login(user)){
//          response.sendRedirect("success.html");
//          
//      }else{
//          response.sendRedirect("fail.html");
//      }
            
        StringBuffer stringBuffer = new StringBuffer();
        
        if(new LoginService().login(user)){
            
            stringBuffer.append("{'message':[{'code':'200','str':'登錄成功'}]}");
        }else{
            stringBuffer.append("{'message':[{'code':'100','str':'登錄失敗'}]}");
            
        }
        
        response.getOutputStream().write(stringBuffer.toString().getBytes("GBK")); 
            
    }

調(diào)用Service方法

public class LoginService {

    public boolean login(User user){
        boolean flag = false;
        
        Connection conn = DBHelper.getConn();
        
         PreparedStatement prestate;
         
         String sql = "select * from user where username = ? and pass = ?";
         try{
             prestate = (PreparedStatement) conn.prepareStatement(sql);
             
             prestate.setString(1, user.getUsername());
             prestate.setString(2, user.getPass());
             
             ResultSet  result = prestate.executeQuery();
             
             while(result.next()){
                 String username = result.getString(1);
                 
                 System.out.println("username is "+username);
                 
                 flag = true;
             }
             
         }catch(Exception ex){
             ex.printStackTrace();
         }
        
        return flag;
    }
    
}

連接服務(wù)器中數(shù)據(jù)庫(kù)的JDBC

public class DBHelper {

    public static Connection getConn() {
        String driver = "com.mysql.jdbc.Driver";
        String url = "jdbc:mysql://localhost:3306/renaitable";
        String username = "root";
        String password = "root";
        Connection conn = null;
        try {
            Class.forName(driver); //classLoader,??????????
            conn = (Connection) DriverManager.getConnection(url, username, password);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }
}

Servlet如何同時(shí)處理多個(gè)請(qǐng)求?

  • Servlet采用多線程來(lái)處理多個(gè)請(qǐng)求的同時(shí)訪問(wèn)。Servlet容器通過(guò)線程池來(lái)管理維護(hù)服務(wù)請(qǐng)求。所謂線程池,相當(dāng)于數(shù)據(jù)庫(kù)連接池,實(shí)際上是等待執(zhí)行代碼的一組線程,叫做工作者線程。Servlet容器通過(guò)一個(gè)調(diào)度線程來(lái)管理工作者線程。
  • 當(dāng)容器收到一個(gè)Servlet的訪問(wèn)請(qǐng)求,調(diào)度者線程就從線程池中選出一個(gè)工作者線程,將用戶請(qǐng)求傳遞給該線程,然后由該線程處理Servlet的service()方法;
  • 當(dāng)這個(gè)線程在執(zhí)行的時(shí)候,容器收到一個(gè)新的請(qǐng)求,調(diào)度者線程再次從線程池中選出一個(gè)新的工作者線程;
    當(dāng)容器同時(shí)收到對(duì)同一個(gè)Servlet的多個(gè)請(qǐng)求時(shí),那么Servlet的service方法將在多線程中并發(fā)執(zhí)行。

如何開發(fā)線程安全的Servlet?

Servlet容器采用多線程來(lái)處理請(qǐng)求,提高性能的同時(shí)也造成了線程安全問(wèn)題。要開發(fā)線程安全的Servlet應(yīng)該從一下幾個(gè)方面進(jìn)行:
1. 變量的線程安全; 多線程并不共享局部變量,所以我們要盡可能的在Servlet中使用局部變量;
2. 代碼塊的線程安全; 使用同步塊Synchronized,防止可能調(diào)用的代碼塊;但是要注意的是,要盡可能得縮小同步代碼的方范圍,不要在service方法和響應(yīng)方法上直接使用同步,這會(huì)嚴(yán)重影響性能。
3. 屬性的線程安全; ServletContext,HttpSession,ServletRequest對(duì)象中屬性;
4. 使用同步集合; 使用Vector代替ArrayList,使用HashTable代替HashMap;
5. 不要在Servlet中創(chuàng)建自己的線程來(lái)完成某個(gè)功能; Servlet本身就是多線程的,如果再創(chuàng)建新的線程,將會(huì)導(dǎo)致線程執(zhí)行復(fù)雜化,出現(xiàn)線程安全問(wèn)題;
6. 在多個(gè)Servlet中,對(duì)外部對(duì)象,比如:文件;進(jìn)行修改操作一定要加鎖,做到互斥訪問(wèn);

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,699評(píng)論 19 139
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂(lè)視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,887評(píng)論 11 349
  • 0 系列目錄# WEB請(qǐng)求處理 WEB請(qǐng)求處理一:瀏覽器請(qǐng)求發(fā)起處理 WEB請(qǐng)求處理二:Nginx請(qǐng)求反向代理 本...
    七寸知架構(gòu)閱讀 14,250評(píng)論 22 189
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚_t_閱讀 34,853評(píng)論 18 399
  • 你說(shuō),因?yàn)槲?,你才看到幸福原本該有的樣子??墒?,你一定不知道,因?yàn)槟悖也耪业轿倚闹凶蠲赖呐?。——題記 親愛的又...
    王請(qǐng)兒閱讀 861評(píng)論 5 6

友情鏈接更多精彩內(nèi)容