Servlet

Servlet 簡介
Java Servlet是和平臺無關(guān)的服務(wù)器端組件,它運(yùn)行在Servlet容器中。Servlet容器負(fù)責(zé)Servlet和客戶的通信以及調(diào)用Servlet的方法,Servlet和客戶的通信采用“請求/響應(yīng)”的模式。

Servlet可完成如下功能:
創(chuàng)建并返回基于客戶請求的動態(tài)HTML頁面。
與其它服務(wù)器資源(如數(shù)據(jù)庫或基于Java的應(yīng)用程序)進(jìn)行通信。


Servlet本質(zhì)上就是一個(gè)運(yùn)行在Servlet容器中的Java類,現(xiàn)在充當(dāng)Servlet容器的就是安裝的Tomcat

第一個(gè)Servlet——HelloWorld
1.創(chuàng)建一個(gè)Java類實(shí)現(xiàn)Servlet接口,并實(shí)現(xiàn)其中所有的方法;

package servlet;

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;
/**
 * Created by ttc on 2018/3/6.
 */
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("HelloServlet");
    }
}

@WebServlet("/hello")
表示的是為helloServlet映射一個(gè)訪問路徑/hello,我們在瀏覽器上輸入http://localhost:8080/hello,代碼執(zhí)行程序流會進(jìn)入到HelloServlet 的doGet方法。

3.運(yùn)行Tomcat,在瀏覽器中輸入http://localhost:8080/hello,可以發(fā)現(xiàn)控制臺輸出了一些內(nèi)容,首先是構(gòu)造器,然后是init,再然后是service,然后每次刷新,每次都只出現(xiàn)了service,然后關(guān)閉服務(wù),發(fā)現(xiàn)出現(xiàn)destory。

Servlet的生命周期

package servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by ttc on 2018/3/6.
 */
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("service");
        HttpServletRequest request = (HttpServletRequest)req;
        System.out.println(request.getMethod());
        super.service(req, res);
    }

    @Override
    public void destroy() {
        System.out.println("destroy");
        super.destroy();
    }

    @Override
    public void init() throws ServletException {
        System.out.println("init");
        super.init();
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("doPost");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("doGet");
    }
}

①服務(wù)器加載Servlet,服務(wù)器啟動之后,但不是創(chuàng)建Servlet

②創(chuàng)建Servlet實(shí)例
--只有第一次請求Servlet時(shí),創(chuàng)建Servlet實(shí)例,調(diào)用構(gòu)造器也就是和類名一樣的構(gòu)造方法,沒寫的話自動生成

③初始化init()
--只被調(diào)用一次,在創(chuàng)建好實(shí)例后立即被調(diào)用,用于初始化當(dāng)前Servlet

④service()處理用戶請求
--可以被多次調(diào)用,每次請求都會調(diào)用service方法,實(shí)際用于響應(yīng)請求的,根據(jù)用戶請求的類型(get或者post),調(diào)用doGet或者doPost方法。

⑤destory()銷毀
--只被調(diào)用一次,在當(dāng)前Servlet所在的WEB應(yīng)用被卸載前調(diào)用,用于釋放當(dāng)前Servlet所占用的資源


load-on-startup

可以指定Servlet被創(chuàng)建的時(shí)機(jī)

package servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by ttc on 2018/3/6.
 */
@WebServlet(value = "/hello",loadOnStartup = 1)
public class HelloServlet extends HttpServlet {
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("service");
        HttpServletRequest request = (HttpServletRequest)req;
        System.out.println(request.getMethod());
        super.service(req, res);
    }

    @Override
    public void destroy() {
        System.out.println("destroy");
        super.destroy();
    }

    @Override
    public void init() throws ServletException {
        System.out.println("init");
        super.init();
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("doPost");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("doGet");
    }
}

在加載完Servlet后直接就創(chuàng)建了Servlet實(shí)例,并進(jìn)行了初始化,在此期間我們并沒有提出請求。
如果配置了多個(gè)Servlet, load-on-startup的值越小越先啟動(包括0,負(fù)數(shù)不會被啟動,還是需要發(fā)出請求才創(chuàng)建實(shí)例并初始化);


Servlet映射細(xì)節(jié)

在Servlet映射到的URL中也可以使用 * 通配符,但是只能有兩種固定的格式:
一種格式是“* .擴(kuò)展名”

@WebServlet(value = "*.do")
public class HelloServlet extends HttpServlet
 {
}

另一種格式是以正斜杠(/)開頭并以“/ * ”結(jié)尾。

@WebServlet(value = "/*")
public class HelloServlet extends HttpServlet
 {
}

注意:既帶 / 又帶 * 的,又帶擴(kuò)展名的,是不合法的(例如:/.do)。*
urlPatterns = "/" 比urlPatterns = ".do"的優(yōu)先級高

HTTP簡介

WEB瀏覽器與WEB服務(wù)器之間的一問一答的交互過程必須遵循一定的規(guī)則,這個(gè)規(guī)則就是HTTP協(xié)議。
HTTP是 hypertext transfer protocol(超文本傳輸協(xié)議)的簡寫,它是 TCP/IP 協(xié)議集中的一個(gè)應(yīng)用層協(xié)議,用于定義WEB瀏覽器與WEB服務(wù)器之間交換數(shù)據(jù)的過程以及數(shù)據(jù)本身的格式。

HTTP 的會話方式

四個(gè)步驟:

瀏覽器與WEB服務(wù)器的連接過程是短暫的,每次連接只處理一個(gè)請求和響應(yīng)。對每一個(gè)頁面的訪問,瀏覽器與WEB服務(wù)器都要建立一次單獨(dú)的連接。
瀏覽器到WEB服務(wù)器之間的所有通訊都是完全獨(dú)立分開的請求和響應(yīng)對。

HTTP請求消息(了解即可)

請求消息的結(jié)構(gòu):
一個(gè)請求行、若干消息頭、以及實(shí)體內(nèi)容,其中的一些消息頭和實(shí)體內(nèi)容都是可選的,消息頭和實(shí)體內(nèi)容之間要用空行隔開。

HTTP響應(yīng)消息(了解即可)

響應(yīng)消息的結(jié)構(gòu):
一個(gè)狀態(tài)行、若干消息頭、以及實(shí)體內(nèi)容 ,其中的一些消息頭和實(shí)體內(nèi)容都是可選的,消息頭和實(shí)體內(nèi)容之間要用空行隔開。
這里舉個(gè)小實(shí)例:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

    <form action="/loginServlet" method="post">
        user:<input type="text" name="user">
        password:<input type="password" name="password">
        <input  type="submit" value="Submit">
    </form>

</body>
</html>

運(yùn)行服務(wù)器,在瀏覽器中打開這個(gè)網(wǎng)頁,開發(fā)者工具,提交表單,提示404(申請資源不存在),在chrome network中查看請求及響應(yīng)消息。

POST和GET請求

post請求方式我們可以看到請求參數(shù)在請求體里面
將請求方式改為get后再運(yùn)行觀察

<form action="/loginServlet" method="get">
        user:<input type="text" name="user">
        password:<input type="password" name="password">
        <input  type="submit" value="Submit">
</form>

可以觀察到地址欄是這樣的:http://localhost:8080/loginServlet?user=123&password=123
get請求把請求參數(shù)附著在url后面,中間以"?”分割。

使用GET方式傳遞參數(shù)

①在瀏覽器地址欄中輸入某個(gè)URL地址或單擊網(wǎng)頁上的一個(gè)超鏈接時(shí),瀏覽器發(fā)出的HTTP請求消息的請求方式為GET。
②如果網(wǎng)頁中的<form>表單元素的method屬性被設(shè)置為了“GET”,瀏覽器提交這個(gè)FORM表單時(shí)生成的HTTP請求消息的請求方式也為GET。
③使用GET請求方式給WEB服務(wù)器傳遞參數(shù)的格式:
http://www.neusoft.net/counter.jsp?name=yzn&password=123
④使用GET方式傳送的數(shù)據(jù)量一般限制在1KB以下。

使用POST方式傳遞參數(shù)

①POST請求方式主要用于向WEB服務(wù)器端程序提交FORM表單中的數(shù)據(jù)。
②POST方式將各個(gè)表單字段元素及其數(shù)據(jù)作為HTTP消息的實(shí)體內(nèi)容發(fā)送給WEB服務(wù)器,傳送的數(shù)據(jù)量要比使用GET方式傳送的數(shù)據(jù)量大得多。
3.如果網(wǎng)頁中的<form>表單元素的method屬性被設(shè)置為了“POST”,瀏覽器提交這個(gè)FORM表單時(shí)生成的HTTP請求消息的請求方式也為POST。


如何在Servlet中獲取信息

這里我們可以新建一個(gè)Servlet。

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet { 

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("get");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("post");
    }

}

其中,方法的參數(shù)HttpServletRequest requestHttpServletResponse response封裝了請求和響應(yīng)信息

一.如何獲取請求信息

HttpServletRequest常用的方法:
String getParameter(String name)
--根據(jù)請求參數(shù)的名字,返回參數(shù)值,特別常用

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String user = request.getParameter("user");
        String password = request.getParameter("password");
        System.out.println(user+"   "+password);
}


String[] getParameterValues(String name)
--根據(jù)請求參數(shù)的名字,返回請求參數(shù)對應(yīng)的字符串?dāng)?shù)組(例如:一組復(fù)選框-->名字是一樣的)

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String intrests[] = request.getParameterValues("hobby");
        for(String str:intrests) {
            System.out.println(str);
        }
}

獲取請求的URI
獲取請求方式

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String method = request.getMethod();
        System.out.println(method);

        String servletPath = request.getServletPath();
        System.out.println(servletPath);
}

解決請求中的中文亂碼問題:

request.setCharacterEncoding("utf-8");

二.如何返回響應(yīng)信息

HttpServletResponse常用的方法:
①getWriter()方法
--返回PrintWriter對象,調(diào)用這個(gè)對象的println()方法可以將信息直接打印在客戶的瀏覽器上

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  

        PrintWriter out = response.getWriter();
        out.println("hello...");

}

解決回應(yīng)中的中文亂碼問題

//1.設(shè)置response的編碼為utf-8
response.setCharacterEncoding("utf-8");
//2.通知瀏覽器,以UTF-8的編碼打開
response.setContentType("text/html;charset=UTF-8");

練習(xí)

定義一個(gè)login.html,里面定義一個(gè)表單,表單中包含2個(gè)請求字段user,password,發(fā)送請求到loginServlet,再創(chuàng)建一個(gè)LoginServlet,在其中獲取請求的user,password,比對其是否是zhangsan,123,若一致,響應(yīng)Hello:xxx;若不一致,響應(yīng)Sorry:xxx;xxx為user

<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <a href="login.html">login</a>
  </body>
</html>
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;

@WebServlet(name = "loginServlet",urlPatterns = "/login")
public class loginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String username = request.getParameter("username");
        String password = request.getParameter("password");
        PrintWriter printWriter =response.getWriter();
        if(username.equals("zhangsan")&&password.equals("123")){
            printWriter.println("hello"+username);
        }
        else {
            printWriter.println("sorry"+username);
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form method="post" action="login">
    <input type="text" name="username">
    <input type="text" name="password">
    <input type="submit">
</form>
</body>
</html>

上面的輸入中文會亂碼,改進(jìn)措施

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容