JavaWeb學習之Servlet(1)

配置完Tomcat后就正式步入了后端JavaWeb的學習,學習servlet是JavaWeb的第一步,那下面就開始了。

先來了解HTTP事務

HTTP事務 = 請求 + 響應

通過瀏覽器開發者工具可以看見HTTP事務

一個完整的HTTP請求分為三部分:請求行、請求頭、請求實體

1.請求行

格式為:
????請求方式 請求內容 協議名和版本

訪問科大官網的請求行

請求方式最常用的有:
????GET
????POST
GET的特點是對用戶可見,它在URL地址后以?開始附帶數據信息,多個鍵值對間用&分隔;但是URL上限為2048個字節,所以對數據長度有限制
POST的特點是單獨通過請求實體來向服務器發送數據,數據容量無限制
請求內容為網站的URL地址
協議和版本現在有HTTP1.0/1.1/2
其中HTTP1.1支持持久連接,在一個TCP連接上可以傳送多個HTTP請求和響應,而HTTP1.0不能。

2.請求頭

請求頭由很多key:value組成,根據需求每次請求是不同的

這里列出一些常用的鍵值對:

3.請求實體

請求實體與請求頭之間有一個空行分隔,并不是每次請求都帶有請求實體
這里我用servlet寫了一個簡單的登陸界面,在這個請求頭中,可以看見請求實體

HTTP響應同樣分為三部分

1.響應行

格式為:
????協議版本 狀態碼 原因敘述
????如HTTP/1.1 ?200 &nbspOK
狀態碼及原因敘述可以在下面這個網址查詢:
http://tool.oschina.net/commons?type=5

2.響應頭

常用的響應頭信息

3.響應實體

通常是html代碼等

什么是Servlet?

Servlet是一個java類及接口,當Web應用運行在服務器上時負責接收客戶端(Client)向服務器發起的HTTP請求(Request),然后再根據需要向客戶端返回HTTP響應(Response)。
使用 Servlet,你可以實現通過 web 頁面表單來收集用戶的輸入,顯示從數據庫或其他來源的記錄,動態地創建 web頁面等。

Tomcat下Servlet處理請求響應的流程
Servlet作為中間層

Servlet的生命周期

如圖所示Servlet的生命周期可以被分為init()→service()→destory(),實際重寫HttpServlet的方法時,我們通常要重寫
init()、doGet()、doPost()方法。

init()

init 方法被設計成只調用一次。它在第一次創建 servlet 時被調用,在后續每次用戶請求時不再調用。

service()

每次服務器接收到一個 servlet 請求時,服務器會產生一個新的線程并調用服務。service() 方法檢查 HTTP 請
求類型(GET、POST、PUT、DELETE 等),并在適當的時候調用 doGet、doPost、doPut、doDelete 等
方法。service() 方法由容器調用,所以
對 service() 方法你什么都不需要做,只是根據你接收到的來自客戶端的請求類型來重寫 doGet()或 doPost()。

doGet()

GET 請求來自于一個 URL 的正常請求,或者來自于一個沒有 method 指定的 html 表單,它由 doGet()處理。

doPost()

同理,處理method=post的html表單時調用。

destroy()

當你關閉servlet響應頁面時執行

簡單的用戶登錄實例,使用Servlet獲取表單數據

Webapp結構

Login.html代碼

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登陸界面Demo</title>
</head>
<link rel="stylesheet" type="text/css" href="Login.css"/>
<body><!-- 這里action中路徑是在域名后直接添加的,等于127.0.0.1:8080/MyServlet/ServletStudy -->
<form action="/MyServlet/ServletStudy" method="post" id="form">
    <div class="input"><p>用戶名:</p><input type="text" name="userName"/></div>
    <div class="input"><p>密碼:</p><input type="password" name="userPassword"/></div>
    <div id="inputButtons"><input type="submit" value="登陸" class="button"/><input type="reset" value="清空" class="button"/></div>
</form>
</body>
</html>

Servlet.java代碼

public class ServletStudy extends HttpServlet {
    private static final long serialVersionUID = 1169754202346967182L;
    @Override
    public void init() throws ServletException {
        System.out.println("===init() is called===");
        super.init();
    }
    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("===init(config) is called===");
        super.init(config);
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("===doGet() is called===");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("===doPost() is called===");
        //獲取請求信息
        String userName = req.getParameter("userName");
        String userPassword = req.getParameter("userPassword");
        if(userName.equals("lihaodong")&&userPassword.equals("lhd123")) {
            //轉發,可以將request信息傳給新頁面
            RequestDispatcher rd = req.getRequestDispatcher("/userInterface.jsp");
            rd.forward(req, resp);
            //重定向,不能將requset信息發送給新頁面
//          resp.sendRedirect(req.getContextPath()+"/success.jsp");
        }
        else {
        resp.sendRedirect(req.getContextPath()+"/false.jsp");
        }
    }
    @Override
    public void destroy() {
        System.out.println("===destroy() is called===");
        super.destroy();
    }
    public ServletStudy() {
        super();
    }
}

通過HttpServletRequest對象我們可以調用以下方法:
request.getParameter(key) 獲取表單參數的值。
request.getParameterValues(key)如果獲取的參數出現不止一次,那么調用該方法并返回多個值,例如復選框。
request.getParameterNames()得到一個當前請求的所有參數的完整列表。
其余方法,通過查相關文檔可以了解具體用法,這里不再解釋。

web.xml代碼

寫好了servlet,我們需要在部署描述符中配置servlet

  <servlet>
    <servlet-name>MyServlet</servlet-name>
    <servlet-class>com.lhd.servlet.ServletStudy</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>/ServletStudy</url-pattern>
  </servlet-mapping>

其中servlet-name的值可以任意定,servlet-class需要輸入servlet.java的完全限定名,在servlet-mapping中url-pattern聲明了servlet的虛擬目錄映射通過servlet-name與物理地址聯系上。這樣我們就可以使用127.0.0.1:8080/項目名稱/servlet虛擬目錄來訪問servlet。

登陸成功.jsp代碼

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>用戶界面</title>
</head>
<body>
    <div id="mainContainer">
        <div id="info">
            <img src="" alt="" />
            <p>歡迎回來,親愛的<%=request.getParameter("userName") %>用戶</p>
            <a href="Login.html" id="logout">注銷</a>
        </div>
        <div id="search">
            <form action="/MyServlet/userSearch" method="get" id="search">
                <input type="text" name="searchUser" id="searchUser"/>
                <input type="submit" value="搜索用戶" id="searchButton"/>
            </form>
        </div>
    </div>
</body>
</html>

失敗的jsp頁面

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>你失敗了大哥</title>
</head>
<style>
    #info{
        width:300px;
        height:200px;
        position:absolute;
        top:calc(50% - 100px);
        left:calc(50% - 150px);
        display:flex;
        flex-direction:column;
        align-items:center;
        justify-content:space-around;
    }
    #info>p:nth-child(1){
        font-size:30px;
        color:red;
    }
    #info>p:nth-child(2){
        font-size:18px;
    }
    #info>a{
        text-decoration:none;
    }
</style>
<body>
<div id="info">
    <p>登陸失敗</p>
    <p>來自<%=request.getRemoteHost() %>的請求</p>
    <a href="Login.html">返回登陸頁面</a>
</div>
</body>
</html>

這樣我們就搭建好了一個基本的客戶端-服務器請求相應框架
輸入用戶名lihaodong,密碼lhd123進行登錄

成功頁面
失敗頁面

實例,使用過濾器Filter過濾不雅詞匯

在上文登陸成功頁面中

<div id="search">
    <form action="/MyServlet/userSearch" method="get" id="search">
        <input type="text" name="searchUser" id="searchUser"/>
        <input type="submit" value="搜索用戶" id="searchButton"/>
    </form>
</div>

表示我們的搜索框會向/userSearch所映射的servlet發送搜索請求,我們為/userSearch寫一個過濾器,過濾掉dashabi這個用戶名,dashabi在Filter配置文件中提前聲明好,也可以用其他方式。

Filter.java代碼

public class FilterOne implements Filter {
    public String initParam = null;
    public FilterOne() {
    }
    public void init(FilterConfig fConfig) throws ServletException {
        System.out.println("===FilterOne init(fConfig) is called===");
        initParam = fConfig.getInitParameter("userName");
    }
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        System.out.println("===FilterOne doFilter() is called===");
        if(req.getParameter("searchUser").equals(initParam)) {
            req.setAttribute("alter", "您要搜索的詞匯包含非法字符");
        }
        chain.doFilter(req, resp);
    }
    public void destroy() {
        System.out.println("===FilterOne destroy() is called===");
    }
}

Filter過濾器也是一個Java 類,可用于下述目的:
?在請求訪問后端資源之前,攔截這些來自客戶端的請求。
?在響應發送回客戶端之前,處理這些來自服務器端的響應。
也就是說Filter會在servlet實例化之前init,在servlet返回響應之后init。
在這里我們使用Filter來過濾掉用戶搜索的不雅詞匯(霧)

web.xml代碼

  <filter>
    <filter-name>FilterOne</filter-name>
    <filter-class>com.lhd.filter.FilterOne</filter-class>
    <init-param>
      <param-name>userName</param-name>
      <param-value>dashabi</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>FilterOne</filter-name>
    <url-pattern>/userSearch</url-pattern>
  </filter-mapping>

filter的配置與servlet類似,filer中可以設置初始化參數init-param,filter-mapping中url-pattern設置過濾的url路徑,通常是servlet的虛擬目錄

UserSearchServlet.java代碼

public class UserSearchServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    public UserSearchServlet() {
        super();
    }
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter pw = resp.getWriter();
        if(req.getAttribute("alter")!=null) {
            pw.println(req.getAttribute("alter").toString());
        }
        else {
            pw.println("您要尋找的"+req.getParameter("searchUser")+"用戶搜索結果如下"+"<br/><br/>");
        }
        pw.close();
    }
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

對應的配置文件略過

當我們輸入dashabi時

Filter過濾

當輸入haha時,不會被Filter過濾

小結:
課外學習真的不容易,我要寫作業了。。。

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

推薦閱讀更多精彩內容