1. 程式人生 > >Java程式設計師面試題及解答(三)

Java程式設計師面試題及解答(三)

二、Web篇

這部分主要是與Java Web和Web Service相關的面試題。

96、闡述Servlet和CGI的區別? 
答:Servlet與CGI的區別在於Servlet處於伺服器程序中,它通過多執行緒方式執行其service()方法,一個例項可以服務於多個請求,並且其例項一般不會銷燬,而CGI對每個請求都產生新的程序,服務完成後就銷燬,所以效率上低於Servlet。

補充:Sun Microsystems公司在1996年釋出Servlet技術就是為了和CGI進行競爭,Servlet是一個特殊的Java程式,一個基於Java的Web應用通常包含一個或多個Servlet類。Servlet不能夠自行建立並執行,它是在Servlet容器中執行的,容器將使用者的請求傳遞給Servlet程式,並將Servlet的響應回傳給使用者。通常一個Servlet會關聯一個或多個JSP頁面。以前CGI經常因為效能開銷上的問題被詬病,然而Fast CGI早就已經解決了CGI效率上的問題,所以面試的時候大可不必信口開河的詬病CGI,事實上有很多你熟悉的網站都使用了CGI技術。

97、Servlet介面中有哪些方法? 
答:Servlet介面定義了5個方法,其中前三個方法與Servlet生命週期相關: 
- void init(ServletConfig config) throws ServletException 
- void service(ServletRequest req, ServletResponse resp) throws ServletException, Java.io.IOException 
- void destory() 
- java.lang.String getServletInfo() 
- ServletConfig getServletConfig()

Web容器載入Servlet並將其例項化後,Servlet生命週期開始,容器執行其init()方法進行Servlet的初始化;請求到達時呼叫Servlet的service()方法,service()方法會根據需要呼叫與請求對應的doGet或doPost等方法;當伺服器關閉或專案被解除安裝時伺服器會將Servlet例項銷燬,此時會呼叫Servlet的destroy()方法。

98、轉發(forward)和重定向(redirect)的區別? 
答:forward是容器中控制權的轉向,是伺服器請求資源,伺服器直接訪問目標地址的URL,把那個URL 的響應內容讀取過來,然後把這些內容再發給瀏覽器,瀏覽器根本不知道伺服器傳送的內容是從哪兒來的,所以它的位址列中還是原來的地址。redirect就是伺服器端根據邏輯,傳送一個狀態碼,告訴瀏覽器重新去請求那個地址,因此從瀏覽器的位址列中可以看到跳轉後的連結地址,很明顯redirect無法訪問到伺服器保護起來資源,但是可以從一個網站redirect到其他網站。forward更加高效,所以在滿足需要時儘量使用forward(通過呼叫RequestDispatcher物件的forward()方法,該物件可以通過ServletRequest物件的getRequestDispatcher()方法獲得),並且這樣也有助於隱藏實際的連結;在有些情況下,比如需要訪問一個其它伺服器上的資源,則必須使用重定向(通過HttpServletResponse物件呼叫其sendRedirect()方法實現)。

99、JSP有哪些內建物件?作用分別是什麼? 
答:JSP有9個內建物件: 
- request:封裝客戶端的請求,其中包含來自GET或POST請求的引數; 
- response:封裝伺服器對客戶端的響應; 
- pageContext:通過該物件可以獲取其他物件; 
- session:封裝使用者會話的物件; 
- application:封裝伺服器執行環境的物件; 
- out:輸出伺服器響應的輸出流物件; 
- config:Web應用的配置物件; 
- page:JSP頁面本身(相當於Java程式中的this); 
- exception:封裝頁面丟擲異常的物件。

補充:如果用Servlet來生成網頁中的動態內容無疑是非常繁瑣的工作,另一方面,所有的文字和HTML標籤都是硬編碼,即使做出微小的修改,都需要進行重新編譯。JSP解決了Servlet的這些問題,它是Servlet很好的補充,可以專門用作為使用者呈現檢視(View),而Servlet作為控制器(Controller)專門負責處理使用者請求並轉發或重定向到某個頁面。基於Java的Web開發很多都同時使用了Servlet和JSP。JSP頁面其實是一個Servlet,能夠執行Servlet的伺服器(Servlet容器)通常也是JSP容器,可以提供JSP頁面的執行環境,Tomcat就是一個Servlet/JSP容器。第一次請求一個JSP頁面時,Servlet/JSP容器首先將JSP頁面轉換成一個JSP頁面的實現類,這是一個實現了JspPage介面或其子介面HttpJspPage的Java類。JspPage介面是Servlet的子介面,因此每個JSP頁面都是一個Servlet。轉換成功後,容器會編譯Servlet類,之後容器載入和例項化Java位元組碼,並執行它通常對Servlet所做的生命週期操作。對同一個JSP頁面的後續請求,容器會檢視這個JSP頁面是否被修改過,如果修改過就會重新轉換並重新編譯並執行。如果沒有則執行記憶體中已經存在的Servlet例項。我們可以看一段JSP程式碼對應的Java程式就知道一切了,而且9個內建物件的神祕面紗也會被揭開。

JSP頁面:

<%@ page pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>

<!DOCTYPE html>
<html>
  <head>
    <basehref="<%=basePath%>">
    <title>首頁</title>
    <styletype="text/css">
        * { font-family:"Arial"; }</style>
  </head>

  <body>
    <h1>Hello, World!</h1>
    <hr/>
    <h2>Current time is: <%= new java.util.Date().toString() %></h2>
  </body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

對應的Java程式碼:

/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/7.0.52
 * Generated at: 2014-10-13 13:28:38 UTC
 * Note: The last modified time of this file was set to
 *       the last modified time of the source file after
 *       generation to assist with modification tracking.
 */
package org.apache.jsp;

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

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

    private static final javax.servlet.jsp.JspFactory _jspxFactory = javax.servlet.jsp.JspFactory
            .getDefaultFactory();

    private static java.util.Map<java.lang.String, java.lang.Long> _jspx_dependants;

    private javax.el.ExpressionFactory _el_expressionfactory;
    private org.apache.tomcat.InstanceManager _jsp_instancemanager;

    public java.util.Map<java.lang.String, java.lang.Long> getDependants() {
        return _jspx_dependants;
    }

    public void _jspInit() {
        _el_expressionfactory = _jspxFactory.getJspApplicationContext(
                getServletConfig().getServletContext()).getExpressionFactory();
        _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory
                .getInstanceManager(getServletConfig());
    }

    public void _jspDestroy() {
    }

    public void _jspService(
            final javax.servlet.http.HttpServletRequest request,
            final javax.servlet.http.HttpServletResponse response)
            throws java.io.IOException, javax.servlet.ServletException {
        // 內建物件就是在這裡定義的
        final javax.servlet.jsp.PageContext pageContext;
        javax.servlet.http.HttpSession session = null;
        final javax.servlet.ServletContext application;
        final javax.servlet.ServletConfig config;
        javax.servlet.jsp.JspWriter out = null;
        final java.lang.Object page = this;
        javax.servlet.jsp.JspWriter _jspx_out = null;
        javax.servlet.jsp.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 + "/";
// 以下程式碼通過輸出流將HTML標籤輸出到瀏覽器中
            out.write("\r\n");
            out.write("\r\n");
            out.write("<!DOCTYPE html>\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("    <title>首頁</title>\r\n");
            out.write("    <style type=\"text/css\">\r\n");
            out.write("    \t* { font-family: \"Arial\"; }\r\n");
            out.write("    </style>\r\n");
            out.write("  </head>\r\n");
            out.write("  \r\n");
            out.write("  <body>\r\n");
            out.write("    <h1>Hello, World!</h1>\r\n");
            out.write("    <hr/>\r\n");
            out.write("    <h2>Current time is: ");
            out.print(new java.util.Date().toString());
            out.write("</h2>\r\n");
            out.write("  </body>\r\n");
            out.write("</html>\r\n");
        } catch (java.lang.Throwable t) {
            if (!(t instanceof javax.servlet.jsp.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
                    throw new ServletException(t);
            }
        } finally {
            _jspxFactory.releasePageContext(_jspx_page_context);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112