JSP&Servlet學習筆記----第1/2章

HTML(HyperText Markup Language):超文本標記語言html

HTTP(HyperText Transfer Protocol):超文本傳輸協議java

URL(Uniform Resource Locator):統一資源定位符,以文字的方式來講明因特網上的資源如何取得。web

URN(Uniform Resource Name):表明某個資源獨一無二的名稱,如圖書的ISBN。apache

URI(Uniform Resource Identifier):URL和URN是URI的子集。api

一個簡單的html範例程序:瀏覽器

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>HTML範例</title>
</head>
<body>
    <form method="get" action="hello.do" name="sample">
        姓名:
        <input type="text" name="name">
        <br />
        <button>發送</button>
    </form>
</body>
</html>
HTML學習資源: http://www.w3school.com.cn/html/index.asp

HTTP:指架構在TCP/IP之上應用層的一種協議。它的兩個特色:tomcat

一、無狀態(stateless)通訊協議。(無記憶性)服務器

二、基於請求(request)/響應(response)模型。cookie

客戶端對服務器發出一個取得資源的請求,服務器將要求的資源響應給客戶端,每次的聯機只做一次請求/響應,是一種很簡單的通訊協議,沒有請求就沒有響應。架構

在HTTP 協議下,服務器是個健忘的傢伙,服務器響應客戶端以後,就不會記得客戶端的信息,更不會去維護與客戶端有關的狀態,所以HTTP又稱爲無狀態的通訊協議。

瀏覽器在使用http發送請求,最重要的就是GET和POST。

GET:就是向服務器取得指定的資源。

POST請求:就是請求時發佈(POST)信息給服務器。

對於二者如何進行選擇?

一、get方式請求參數長度是有限的,過長的或者如文件上傳應該使用post請求。

二、get請求參數會出如今地址欄。

三、get請求純粹是爲了取得資源,而不改變服務器上的資源的狀態。而post相反。

對於java,JVM(java virtual machine)是java程序惟一認得的操做系統,其可執行文件爲.class文件。

對於JSP/Servlet,Web容器是JSP/Servlet惟一認得的http服務器。

URL編解碼:

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

/**
 * Created by N3verL4nd on 2017/1/2.
 */


public class HelloWorld
{
    public static void main(String[] args) throws UnsupportedEncodingException {
        System.out.println(URLEncoder.encode("http://www.baidu.com", "UTF-8"));
        System.out.println(URLDecoder.decode("%3A", "UTF-8"));
    }
}
URL編碼針對的字符是UTF-8編碼的8個位數值。

對於ascii字符使用1個字節,非ascii如中文使用3個字節。

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

/**
 * Created by N3verL4nd on 2017/1/2.
 */
public class HelloWorld
{
    public static void main(String[] args) throws UnsupportedEncodingException {
        System.out.println(URLEncoder.encode("我", "UTF-8"));
        System.out.println(URLDecoder.decode("%E6%88%91", "UTF-8"));
    }
}
HTTP規範下的URL編碼,並不限使用UTF-8,例如在一個BIG5網頁中,若窗體使用get發送中文,則是使用BIG5編碼的參數。

System.out.println(URLEncoder.encode("", "BIG5"));

第一個Servlet程序(打印http header):

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

/**
 * Created by N3verL4nd on 2017/1/4.
 */
@WebServlet(name = "testServlet",urlPatterns = {"/test.do"})
public class testServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

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

        out.println("<h1>Hello World</h1>");

        out.println("</body>");
        out.println("</html>");
        out.close();
    }
}

/test.do
/Servlet
/Servlet/test.do host:localhost:8080
connection:keep-alive
upgrade-insecure-requests:1
user-agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
accept-encoding:gzip, deflate, sdch, br
accept-language:zh-CN,zh;q=0.8
cookie:JSESSIONID=CDD8329D5BB881383911AC4CFAB4A159; Idea-e643fc73=b918ddfe-f8fa-43a0-b608-e1670a29b80a

@WebServlet(name = "testServlet",urlPatterns = {"/test.do"})
這表示該Servlet名稱爲testServlet,當請求的URL是/test.do,如http://localhost:8080/Servlet/test.do就會由testServlet處理。
HttpServletRequest

表明請求對象,封裝了HTTP請求信息。

HttpServletResponse
表明對客戶端的響應。

Servlet的編譯(需servlet-api.jar。位於D:\Tomcat\apache-tomcat-9.0.0.M15\lib):



一個簡易的Servlet程序對應的文件目錄結構以下:

E:\MyDocument\Desktop\jspRun\web\WEB-INF>tree /f
文件夾 PATH 列表
卷序列號爲 025427CF 32D1:7CF3
E:.
│  web.xml

├─classes
│      testServlet.class

└─lib


E:\MyDocument\Desktop\jspRun\web\WEB-INF>
部署:

將web.war拷貝到webapps目錄下(D:\Tomcat\apache-tomcat-9.0.0.M15\webapps )

運行bin目錄下的startup.bat


servlet、genericservlet、httpservlet之間的關係:


package javax.servlet;
import java.io.IOException;
public interface Servlet {
    public void init(ServletConfig config) throws ServletException;
    public ServletConfig getServletConfig();
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException;
    public String getServletInfo();
    public void destroy();
}
package javax.servlet;
import java.io.IOException;
import java.util.Enumeration;
public abstract class GenericServlet implements Servlet, ServletConfig,
        java.io.Serializable {

    private static final long serialVersionUID = 1L;

    private transient ServletConfig config;
    public GenericServlet() {
        // NOOP
    }
    @Override
    public void destroy() {
        // NOOP by default
    }
    @Override
    public String getInitParameter(String name) {
        return getServletConfig().getInitParameter(name);
    }
    @Override
    public Enumeration<String> getInitParameterNames() {
        return getServletConfig().getInitParameterNames();
    }
    @Override
    public ServletConfig getServletConfig() {
        return config;
    }
    @Override
    public ServletContext getServletContext() {
        return getServletConfig().getServletContext();
    }
    @Override
    public String getServletInfo() {
        return "";
    }
    @Override
    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
    }
    public void init() throws ServletException {
        // NOOP by default
    }

    public void log(String msg) {
        getServletContext().log(getServletName() + ": " + msg);
    }
    public void log(String message, Throwable t) {
        getServletContext().log(getServletName() + ": " + message, t);
    }
    @Override
    public abstract void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException;
    @Override
    public String getServletName() {
        return config.getServletName();
    }
}
package javax.servlet.http;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.ResourceBundle;
import javax.servlet.DispatcherType;
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public abstract class HttpServlet extends GenericServlet {
    private static final long serialVersionUID = 1L;
    private static final String METHOD_DELETE = "DELETE";
    private static final String METHOD_HEAD = "HEAD";
    private static final String METHOD_GET = "GET";
    private static final String METHOD_OPTIONS = "OPTIONS";
    private static final String METHOD_POST = "POST";
    private static final String METHOD_PUT = "PUT";
    private static final String METHOD_TRACE = "TRACE";
    private static final String HEADER_IFMODSINCE = "If-Modified-Since";
    private static final String HEADER_LASTMOD = "Last-Modified";
    private static final String LSTRING_FILE =
        "javax.servlet.http.LocalStrings";
    private static final ResourceBundle lStrings =
        ResourceBundle.getBundle(LSTRING_FILE);
    public HttpServlet() {
        // NOOP
    }
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
    {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_get_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
        } else {
            resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
        }
    }
    protected long getLastModified(HttpServletRequest req) {
        return -1;
    }
    protected void doHead(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

        if (DispatcherType.INCLUDE.equals(req.getDispatcherType())) {
            doGet(req, resp);
        } else {
            NoBodyResponse response = new NoBodyResponse(resp);
            doGet(req, response);
            response.setContentLength();
        }
    }
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_post_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
        } else {
            resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
        }
    }
    ...
}
Servlet接口:定義了Servlet應當有的基本行爲,全部的Servlet程序都必須實現Servlet接口(GenericServlet或者HttpServlet)。

GenericServlet:實現了Servlet接口,沒有規範任何與HTTP相關的方法,而是由繼承它的HttpServlet來定義。

HttpServlet的service方法流程:

protected void service(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {

    String method = req.getMethod();

    if (method.equals(METHOD_GET)) {
        long lastModified = getLastModified(req);
        if (lastModified == -1) {
            // servlet doesn't support if-modified-since, no reason
            // to go through further expensive logic
            doGet(req, resp);
        } else {
            long ifModifiedSince;
            try {
                ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
            } catch (IllegalArgumentException iae) {
                // Invalid date header - proceed as if none was set
                ifModifiedSince = -1;
            }
            if (ifModifiedSince < (lastModified / 1000 * 1000)) {
                // If the servlet mod time is later, call doGet()
                // Round down to the nearest second for a proper compare
                // A ifModifiedSince of -1 will always be less
                maybeSetLastModified(resp, lastModified);
                doGet(req, resp);
            } else {
                resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
            }
        }

    } else if (method.equals(METHOD_HEAD)) {
        long lastModified = getLastModified(req);
        maybeSetLastModified(resp, lastModified);
        doHead(req, resp);

    } else if (method.equals(METHOD_POST)) {
        doPost(req, resp);

    } else if (method.equals(METHOD_PUT)) {
        doPut(req, resp);

    } else if (method.equals(METHOD_DELETE)) {
        doDelete(req, resp);

    } else if (method.equals(METHOD_OPTIONS)) {
        doOptions(req,resp);

    } else if (method.equals(METHOD_TRACE)) {
        doTrace(req,resp);

    } else {
        //
        // Note that this means NO servlet supports whatever
        // method was requested, anywhere on this server.
        //

        String errMsg = lStrings.getString("http.method_not_implemented");
        Object[] errArgs = new Object[1];
        errArgs[0] = method;
        errMsg = MessageFormat.format(errMsg, errArgs);

        resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
當請求到來時,容器會調用Servlet的service()方法。
相關文章
相關標籤/搜索