Javaweb-Http、Maven及Servlet詳解

来源:https://www.cnblogs.com/twq46/archive/2022/07/25/16508029.html
-Advertisement-
Play Games

一、Http 1.什麼事Http Http(超文本傳輸協議)是一個簡單的請求-響應協議,它通常運行在TCP之上 文本:html,字元串,~.. 超文本:圖片,音樂,視屏,定位,地圖... 埠為80 Https:安全的,埠號443 2.兩個時代 http1.0 HTTP/1.0:客戶端可以與web ...


一、Http

1.什麼事Http

Http(超文本傳輸協議)是一個簡單的請求-響應協議,它通常運行在TCP之上
  • 文本:html,字元串,~..

  • 超文本:圖片,音樂,視屏,定位,地圖...

  • 埠為80
    Https:安全的,埠號443

2.兩個時代

  • http1.0

    • HTTP/1.0:客戶端可以與web伺服器連接後,只能獲得一個web資源,斷開連接
  • http2.0

    • HTTP/1.1:客戶端可以與web伺服器連接後,可以獲得多個web資源

3.Http請求

  • 客戶端--發請求(requset)--伺服器
    百度:
Request URL: https://www.baidu.com/    請求地址
Request Method: GET      get方法/post方法
Status Code: 200 OK      狀態碼:200
Remote(遠程地址) Address: 39.156.66.14:443
Accept: text/html
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: max-age=0
Connection: keep-alive

(1)請求行

  • 請求行中的請求方式:get

  • 請求方式:Get,Post

    • Get:請求能夠攜帶的參數比較少,大小有限制,會在瀏覽器的URL地址欄顯示數據內容,不安全,但高效
    • Postget:請求能夠攜帶的參數沒有限制,大小沒有限制,不會在瀏覽器的URL地址欄顯示數據內容,安全,但不高效

(2)消息頭

Accept: 告訴瀏覽器,他所支持的數據類型
Accept-Language: zh-CN,zh;q=0.9,告訴瀏覽器,它的語言環境
Cache-Control: max-age=0: 緩存控制
Connection: keep-alive:告訴瀏覽器,請求完成是斷開還是保持連接
HOST:主機

4.Http響應

  • 伺服器--響應--客戶端

百度:

Cache-Control: private   
Connection: keep-alive
Content-Encoding: gzip
Content-Type: text/html;charset=utf-8

(1)響應體

Accept: 告訴瀏覽器,他所支持的數據類型
Accept-Language: zh-CN,zh;q=0.9,告訴瀏覽器,它的語言環境
Cache-Control: max-age=0: 緩存控制
Connection: keep-alive:告訴瀏覽器,請求完成是斷開還是保持連接
HOST:主機
Refresh:告訴客戶端,多久刷新一次;
Location:讓網頁重新定位

(2)響應狀態碼

200:請求響應成功

3xx:請求重定向

  • 重定向:你重新到我給你新位置去;

4xx:找不到資源

  • 資源不存在

5xx:伺服器代碼錯誤 500 ,502:網關錯誤
常見面試題:
當你的瀏覽器中地址欄輸入地址並回車的一瞬間到頁面能夠展示回來,經歷了什麼?

二、Maven

為什麼要學習這個技術?
  • 在Javaweb開發中,需要使用大量的jar包,我們手動去導入

  • 如何能夠讓一個東西自動幫我導入和配置這個jar包,由此,Maven誕生了

1.Maven項目架構管理工具

我們目前用來就是方便導入jar包的 Maven的核心思想:約定大於配置
  • 有約束,不要去違反
    Maven會規定好你該如何去編寫我們的Java代碼,必須要按照這個規範來;

2.下載安裝Maven

下載鏈接

https://maven.apache.org/download.cgi

3.配置Maven環境變數

Mac終端輸入
vim ~/.bash_profile

然後將以下配置加入裡面

MAVEN_HOME=/Users/twq/Downloads/apache-maven-3.8.6
PATH=$MAVEN_HOME/bin:$PATH
M2_HOME=/Users/twq/Downloads/apache-maven-3.8.6/bin
export MAVEN_HOME
export PATH
export M2_HOME

最後輸入 mvn -v
出現如下圖表名配置成功


Windows:
在環境變數中添加M2_home和MAVEN_HOME兩個路徑


並繼續添加PATH的路徑

4.配置阿裡雲鏡像

  • 鏡像:mirrors

    • 作用:加速我們的下載
  • 國內建議使用阿裡雲的鏡像

<mirror> 
        <id>nexus-aliyun</id> 
        <mirrorOf>*,!jeecg,!jeecg-snapshots</mirrorOf> 
        <name>Nexus aliyun</name> 
        <url>http://maven.aliyun.com/nexus/content/groups/public/</url> </mirror> 

將此配置放入setting.xml的mirrors中即可

5.設置本地倉庫

創建一個本地倉庫
<localRepository>/Users/twq/Downloads/apache-maven-3.8.6/maven-repo</localRepository

6.在IDEA中操作Maven


進來後可能還會顯示pom.xml(Unknown)
我的第一次進來是這樣,不知道為啥我的pom.xml里是空白的
最後自己手動添加瞭如下

<?xml version="1.0" encoding="UTF-8" ?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example </groupId>
    <!--項目名-->
    <artifactId>tang</artifactId>
    <version>1.0-SNAPSHOT</version>

</project>

進入後如果沒有自動下載maven依賴,則可以自己在IDEA的終端輸入以下命令下載

mvn dependency:resolve-plugins

最後出現如下圖所示則表明下載成功


成功後,自己建的maven倉庫里就有了很多文件

(1)新建src相關目錄

而且還沒有src目錄在,找了很多解決方法,最後發現如下解決辦法 ①點擊項目右鍵新建目錄


這裡會自動顯示你想要的src以及test文件


創建完成如下圖所示

(2)新建webapp目錄

(3)將IDEA中的文件標記為指定樣式的文件

方法一:


方法二:

(4)配置Tomcat

①解決警告問題
為什麼會有這個警告:我們訪問一個網站需要指定一個文件夾名字

啟動Tomcat會直接顯示webapp裡面的index.jsp文件里的內容

(5)pom.xml文件

<?xml version="1.0" encoding="UTF-8" ?>

<!--maven的版本和頭文件-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example </groupId>
    <artifactId>tang</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!-- Package:項目打包的方式
        jar:Java應用
        war:javaweb應用
    -->
<!--    <packaging>war</packaging>-->

<!--    &lt;!&ndash;  配置  &ndash;&gt;-->
<!--    <properties>-->
<!--        &lt;!&ndash;項目預設構建編碼&ndash;&gt;-->
<!--        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>-->
<!--        &lt;!&ndash;編譯版本&ndash;&gt;-->
<!--        <maven.compiler.source>1.8</maven.compiler.source>-->
<!--        <maven.compiler.target>1.8</maven.compiler.target>-->
<!--    </properties>-->
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.22</version>
        </dependency>

    </dependencies>
<!--    在build中配置resource,防止我們資源導出失敗的問題-->
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <excludes>
                    <exclude>**/*.properties</exclude>
                    <exclude>**/*.xml</exclude>
                </excludes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>
</project>

(6)maven的jar包結構圖

三、Servlet

1.Servlet簡介

  • Servlet就是sun公司開發動態web的一門技術

  • Sun在這些API中提供一個介面叫做:Servelt,如果你想開發一個Servlet程式,只需要完成兩個小步驟:

    • 編寫一個類,實現servlet介面
    • 把開發好的Java類部署到web伺服器中

把實現了Servlet介面的Java程式叫做Servlet

2.關於Maven父子工程的理解

父項目中會有
<!--指明該父類下的子模塊-->
    <modules>
        <module>Servlet-01</module>
    </modules>

子項目中會有

<!--    子類必須指明父類-->
    <parent>
        <artifactId>javaweb-02-Servlet</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

父項目中的Java,子項目可以直接使用

註意:

父項目的打包方式必須為pom且必須要定義打包方式,子項目的打包方式必須為jar,否則會報錯:Invalid packaging for parent POM org.example:javaweb-02-Servlet:1.0-SNAPSHOT (/Users/twq/Downloads/javaweb-02-Servlet/pom.xml), must be "pom" but is "jar"

3.編寫HelloServlet

(1).Maven倉庫的使用

官網地址 https://mvnrepository.com/

Tomcat中Servlet的使用樣例鏈接
http://localhost:8080/examples/servlets/


上圖若沒有搜索到,則可去Maven倉庫中尋找


一搜發現搜到一堆沒用的,心想既然在Tomcat上能使用肯定是導入了某一個與HttpServlet相關的jar包,於是乎又來到Tomcat的lib目錄(存放各種jar包的地方)下查找


發現lib目錄下與servlet相關的jar包只有一個,於是再次回到maven倉庫中尋找該jar包


我選擇的是導入maven依賴,複製上圖方框里的依賴代碼,依賴里的provided表示作用範圍,把這行去掉


然後將Tomcat中Servlet下的hello樣例代碼粘貼過來,就是如下代碼

response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Hello World!</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>Hello World!</h1>");
        out.println("</body>");
        out.println("</html>");

(2).編寫web.xml

建一個包

①編寫servlet的映射
為什麼需要映射:我們寫的是Java程式,但是要通過瀏覽器訪問,而瀏覽器需要連接web伺服器,所以我們需要在web服務中註冊我們寫的Servlet,還需要給他一個瀏覽器能夠訪問的路徑
<!--註冊servlet-->
    <servlet>
        <!--隨便起個名字-->
        <servlet-name>hello</servlet-name>
        <servlet-class>com.tang.HelloServlet</servlet-class>
    </servlet>

<servlet-mapping>
        <servlet-name>hello</servlet-name>
        <!--請求路徑 -->
        <url-pattern>/Twq</url-pattern>
 </servlet-mapping>
②Servlet映射原理

可以根據輸入的指定路徑如我的指定的Twq路徑http://localhost:8080/Servlet_01_war/Twq,然後根據Twq請求路徑在Servlet-mapping中找到servlet-name也即是hello,然後在根據註冊的servlet-name找到要執行的Java程式,最後運行Java程式

自定義前尾碼映射

①指定首碼,尾碼隨意
 <servlet-mapping>
        <servlet-name>helloServlet</servlet-name>
        <!--請求路徑 -->
        <url-pattern>/Twq/*</url-pattern>
    </servlet-mapping>

測試數據:
http://localhost:8080/Servlet_01_war/Twq/fafsdafgsfvdsfsdgg
測試結果:

②指定尾碼,首碼隨意
 <servlet-mapping>
        <servlet-name>helloServlet</servlet-name>
        <!--請求路徑 -->
        <!--註意點 .*前面不能加項目映射的路徑否則會啟動Tomcat報錯 -->
        <url-pattern>*.Twq</url-pattern>
    </servlet-mapping>

測試數據:
http://localhost:8080/Servlet_01_war/sdfadfvfsgsddfrqw.Twq
測試結果:
發現只要尾碼是.Twq結尾前面是什麼無所謂

web.xml代碼

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
<!--        web.xml中是配置我們web的核心應用-->
    <!--註冊servlet-->
    <servlet>
        <!--隨便起個名字-->
        <servlet-name>helloServlet</servlet-name>
        <servlet-class>com.tang.HelloServlet</servlet-class>
    </servlet>
    <!--一個servlet對應一個mapping:映射-->
    <servlet-mapping>
        <servlet-name>helloServlet</servlet-name>
        <!--請求路徑 -->
        <url-pattern>/Twq</url-pattern>
    </servlet-mapping>
</web-app>

4.運行Tomcat

(1)解決啟動報錯

然後運行Tomcat可能會報 java: 錯誤: 不支持發行版本 5這個錯誤(之前還能用的,不知道怎麼回事突然報了這個錯誤,說實在的這兩天解決這些奇怪的報錯,真是讓人頭疼!!!) 解決方法(沒辦法,還是得笑對人生繼續改錯)

完成上面幾步之後可以解決此問題,Tomcat就可以正常啟動了
運行結果圖

(2)解決中文亂碼

亂碼的原因及解決方法

解決方法:
設置瀏覽器的響應的編碼格式即可

HelloServlet代碼

package com.tang;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException {
        //響應的類型:html
        response.setContentType("text/html");
        //設置瀏覽器響應的編碼格式
        response.setCharacterEncoding("UTF-8");
        //獲取響應的輸出流
        PrintWriter out = response.getWriter();

        out.println("<html>");
        out.println("<head>");
        out.println("<title>Hello World!</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>唐昊!!</h1>");
        out.println("</body>");
        out.println("</html>");

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

}

5.ServletContext對象

web容器在啟動的時候,它會為每個web程式都創建一個對應的ServletContext對象,它代表了當前的web應用;

(1).共用數據

  • 在這個Servlet中保存的數據,可以咋另外一個Servlet中拿到;
    存放數據的類

      public class HelloServlet extends HttpServlet {
      @Override
      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          //響應的類型:html
          ServletContext context = this.getServletContext();
    
          String username="唐三";
          context.setAttribute("username",username); //將一個數據保存在了ServletContext中,名字為:username,值為username
    
      }
    }
    

    讀取的類

      public class GetServlet extends HttpServlet {
      @Override
      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          ServletContext context = this.getServletContext();
          String username = (String) context.getAttribute("username");
          resp.setContentType("text/html");
          resp.setCharacterEncoding("UTF-8");
        //        resp.setHeader("text/html","UTF-8");
          resp.getWriter().println("姓名:"+username);
      }
    
      @Override
      protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
      }
    }
    

    web.xml

      <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee   http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
           version="4.0">
      <servlet>
          <servlet-name>hello</servlet-name>
          <servlet-class>com.tang.HelloServlet</servlet-class>
      </servlet>
      <servlet-mapping>
          <servlet-name>hello</servlet-name>
          <url-pattern>/Twq1</url-pattern>
      </servlet-mapping>
    
      <servlet>
          <servlet-name>get</servlet-name>
          <servlet-class>com.tang.GetServlet</servlet-class>
      </servlet>
      <servlet-mapping>
          <servlet-name>get</servlet-name>
          <url-pattern>/Twq2</url-pattern>
      </servlet-mapping>
    </web-app>
    

    測試訪問結果:

(2)獲取初始化參數

web.xml代碼如下
<context-param>
        <param-name>url</param-name>
        <param-value>jdbc:mysql://localhost:3306</param-value>
    </context-param>
 <servlet>
        <servlet-name>gp</servlet-name>
        <servlet-class>com.tang.ServletDemo03</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>gp</servlet-name>
        <url-pattern>/gp</url-pattern>
    </servlet-mapping>

ServletDemo03中代碼如下

package com.tang;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ServletDemo03 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();

        String url = context.getInitParameter("url");

        resp.setContentType("text/html");
        resp.setCharacterEncoding("UTF-8");

        resp.getWriter().println(url);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    }
}

(3)請求轉發

ServletDemo04代碼

package com.tang;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ServletDemo04 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();

        System.out.println("進入了ServletDemo04");
        RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");//轉發的請求路徑
        requestDispatcher.forward(req,resp);//調用forward實現請求轉發

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    }
}

web.xml 代碼

    <servlet>
        <servlet-name>sd4</servlet-name>
        <servlet-class>com.tang.ServletDemo04</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>sd4</servlet-name>
        <url-pattern>/sd4</url-pattern>
    </servlet-mapping>

運行結果圖


轉發的大致思想:
比如有A,B,C,現在有一個需求是A想要拿到C的資源,但是A又無法直接調用C,且只能連接到B,就只能B找C拿,然後C在返回給B,最後B在將C返回的數據交給A,這個過程中,A和C始終沒有見到C,所以上圖路徑沒有變化(用sd4的路徑去訪問jp路徑裡面的內容),圖形化過程如下:

(4)讀取資源文件

Properties
  • 在Java目錄下新建Properties

  • 在resource目錄下新建Properties

發現:都被打包到了同一個路徑下:classes,我麽俗稱這個路徑為classpath:
當在java目錄下寫資源文件時,並不會被打包,可以通過如下方法解決,將以下代碼放入當前模塊的pom.xml中即可

    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <excludes>
                    <exclude>**/*.properties</exclude>
                    <exclude>**/*.xml</exclude>
                </excludes>
                <filtering>false</filtering>
            </resource>
            <resource>
                  <!-- 這裡就是將在Java目錄下的資源文件也給打包-->
                <directory>src/main/java</directory>
                <includes>
                        
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>

加上之後再重新打包,就會生成資源文件


開始讀取該資源文件的流
aa.properties文件里的內容如下:

username=root
password=123456

web.xml代碼

<servlet>
        <servlet-name>sd5</servlet-name>
        <servlet-class>com.tang.ServletDemo05</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>sd5</servlet-name>
        <url-pattern>/sd5</url-pattern>
    </servlet-mapping>

ServletDemo05代碼如下:

package com.tang;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class ServletDemo05 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        InputStream resource = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/tang/aa.properties");

        Properties properties = new Properties();

        properties.load(resource);

        String username = properties.getProperty("username");
        String password = properties.getProperty("password");

        resp.getWriter().println(username+":"+password);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    }
}

當前項目路徑


運行結果圖

6.HttpServletResponse

響應:web伺服器就收到客戶端的Http請求,針對這個請求,分別創建一個代表請求的HttpServletRequest對象,代表響應的一個HttpServletResponse;
  • 如果要獲取客戶端請求過來的參數:找HttpSerletRequest

  • 如果要給客戶端響應一些信息:找HttpServletResponse

(1)簡單分類

①負責像瀏覽器發送數據的方法
ServletOutputStream getOutputStream() throws IOException;

PrintWriter getWriter() throws IOException;

②負責向瀏覽器發送響應頭的方法

void setDateHeader(String var1, long var2);

    void addDateHeader(String var1, long var2);

    void setHeader(String var1, String var2);

    void addHeader(String var1, String var2);

    void setIntHeader(String var1, int var2);

    void addIntHeader(String var1, int var2);

(2)常見應用

①下載文件(瞭解)
  • 要獲取下載文件的路徑

  • 下載的文件名是啥?

  • 設置想辦法讓瀏覽器能夠支持下載我們需要的東西

  • 獲取下載文件的輸入流

  • 輸出獲取到的輸入流

    • 創建緩衝區
    • 獲取OutputStream對象
    • 將FileOutputStream流寫入到buffer緩衝區中
    • 使用OutputStream將緩衝區中的數據輸出到客戶端
      web.xml代碼如下:
<servlet>
            <servlet-name>fileDown</servlet-name>
            <servlet-class>com.tang.FileServlet</servlet-class>
        </servlet>
    <servlet-mapping>
        <servlet-name>fileDown</servlet-name>
        <url-pattern>/down</url-pattern>
    </servlet-mapping>

該模塊的pom.xml中儘量加上如下代碼:

<build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <excludes>
                    <exclude>**/*.properties</exclude>
                    <exclude>**/*.xml</exclude>
                </excludes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>

FileServlet代碼如下

package com.tang;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;

public class FileServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp){
        FileInputStream in = null;//將文件變成流
        ServletOutputStream outputStream = null;
        try {
            //1.要獲取下載文件的路徑
            String realPath = "/Users/twq/Downloads/javaweb-02-Servlet/out/artifacts/Servlet_03_war_exploded/WEB-INF/classes/唐三.jpg";
            System.out.println("下載的文件的路徑為:"+ realPath);
            //2.下載的文件名是啥?
            String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);// 因為一個/需要轉義,所以寫兩個表示截取到最後一個/,然後加1就表示最後一個/後面的名字,也即是文件名
            //3.設置想辦法讓瀏覽器能夠支持下載我們需要的東西
            //Content-disposition:表示web下載文件的頭消息,也是用其來支持下載我們需要的東西;中文文件名使用URLEncoder.encode編碼,否則可能會亂碼
            resp.setHeader("Content-disposition","attachment;filename="+ URLEncoder.encode(fileName,"UtF-8"));
            //4.獲取下載文件的輸入流
            in = new FileInputStream(realPath);
            //5.輸出獲取到的輸入流
            //6.創建緩衝區
            int len = 0;
            byte[] buffer = new byte[1024];
            //7.獲取OutputStream對象
            outputStream = resp.getOutputStream();
            //8.將FileOutputStream流寫入到buffer緩衝區中,使用OutputStream將緩衝區中的數據輸出到客戶端
            while((len=in.read(buffer)) != -1){
                outputStream.write(buffer,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //關閉流
            if(in != null){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(outputStream != null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

填寫文件的絕對路徑時,可以再out目錄下去複製對應文件的絕對路徑

運行結果圖

②驗證碼功能(瞭解)
驗證實現方法
  • 前端實現

  • 後端實現,需要用到Java的圖片類,生成一個圖片
    web.xml註冊代碼

 <servlet>
        <servlet-name>ImageServlet</servlet-name>
        <servlet-class>com.tang.ImageServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ImageServlet</servlet-name>
        <url-pattern>/img</url-pattern>
    </servlet-mapping>

ImageServlet代碼

package com.tang;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

public class ImageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //讓瀏覽器3秒自動刷新一次
        resp.setHeader("refresh","2");

        //在記憶體中創建一個圖片
        BufferedImage image = new BufferedImage(100, 20, BufferedImage.TYPE_INT_RGB);
        //得到圖片,用一個2D的筆
        Graphics2D g = (Graphics2D)image.getGraphics();
        //設置圖片的背景顏色
        g.setColor(Color.white);
        //fillRect:填充一個矩形,從(0,0)點開始到(80,20)結束填充一個背景為白色矩形
        g.fillRect(0,0,100,20);
        //給圖片寫數據
        g.setColor(Color.red);//設置畫筆顏色
        g.setFont(new Font(null,Font.BOLD,20));//設置字體
        g.drawString(makeNum(),0,20);//在(0,20)這個位置將隨機數給畫上去

        //告訴瀏覽器,這個請求用圖片的方式打開
        resp.setContentType("image/jpg");
        //網站存在緩存,設置不讓瀏覽器緩存
        resp.setDateHeader("Expires",-1);
        resp.setHeader("Cache-Control","no-cache");
        resp.setHeader("Pragma","no-cache");

        //把圖片寫給瀏覽器
        ImageIO.write(image,"jpg",resp.getOutputStream());
    }
    //生成隨機數
    private String makeNum(){
        Random random = new Random();
        //7個9表示一個七位數,一個整數加上一個空串之後變為一個字元串
        String num = random.nextInt(9999999) + "";
        StringBuffer sb = new StringBuffer();
        //保證生成的數為七位的,不足七位補零
        for(int i =0; i < 7-num.length();i++){
            sb.append("0");
        }
        num = sb.toString() + num;
        return num;
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

運行結果圖

③重定向(重點)
一個web資源(B)收到客戶端(A)請求,他(B)會通知客戶端(A)去訪問另一個web資源(C),這個過程叫重定向


常見場景:

  • 用戶登錄
    web.xml代碼
<servlet>
        <servlet-name>Redirect</servlet-name>
        <servlet-class>com.tang.RedirectServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Redirect</servlet-name>
        <url-pattern>/red</url-pattern>
    </servlet-mapping>

RedirectServlet代碼

package com.tang;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /*
          由運行結果下麵結果圖知下麵這行代碼等價於
          resp.setHeader("Location","/Servlet_03_war/img");  
          resp.setStatus(302);
        */
        resp.sendRedirect("/Servlet_03_war/img");//重定向
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

運行結果圖


註意:重定向的路徑要添加如下圖所示的東西

重定向和轉發的區別(面試題)

相同點:
  • 頁面都會實現跳轉

不同點:

  • 請求轉發的時候,轉發的url不會發生變化

  • 重定向的時候,url地址欄會發生變化

7.HttpServletRequest

HttpServletRequest代表客戶端的請求,用戶通過Http協議訪問伺服器,HTTP請求中的所有信息會被封裝到HttServletRequest,通過這個HttpServletRequest的方法獲得客戶端的所有信息

(1)獲取參數,請求轉發


RequestTest代碼如下:

package com.tang;

import javax.naming.Context;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class RequestTest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("有請求進來");
        //處理請求
        String username = req.getParameter("username");//獲取請求參數的值
        String password = req.getParameter("password");

        System.out.println(username + ":" +password);
        //重定向的時候一定添加web應用的路徑,否則404
        //resp.sendRedirect("/Servlet_03_war/Success.jsp");
        /*轉發的時候web應用的路徑就不用寫了,否則也會報404
        因為這裡的 / 代表的就是當前的web應用,在寫就重覆了*/
        req.getRequestDispatcher("/Success.jsp").forward(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

web.xml代碼

<servlet>
        <servlet-name>request</servlet-name>
        <servlet-class>com.tang.RequestTest</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>request</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>

index.jsp代碼

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--這裡提交的路經,需要尋找到項目的路徑--%>
<%--${pageContext.request.contextPath}代表當前的項目--%>
<form action="${pageContext.request.contextPath}/login" method="get">
    用戶名:<input type="text" name="username"><br>
    密碼:<input type="text" name="password"><br>
    <input type="submit">
</form>
</body>
</html>

Success.jsp代碼

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>Success</h1>
</body>
</html>

運行結果

8.Cookie、Session

(1)會話

會話:用戶從打開一個瀏覽器->點擊了很多超鏈接->訪問多個web資源->關閉瀏覽器,這個過程可以稱之為會話。

有狀態的會話:一個同學來過教室下次再來教室,我們會知道這個同學曾經來過,稱之為有狀態會話

一個網站,怎麼證明你來過?

  • 服務端給客戶端一個信件,客戶端下次訪問服務端帶上信件就可以了;cookie

  • 伺服器登記你來過了,下次你來的時候我來匹配你;session

(2)保存會話的兩種技術

①cookie
  • 客戶端技術(伺服器通過響應將數據發給客戶端,客戶端通過請求將數據帶到伺服器上)
②session
  • 伺服器技術,利用這個技術,可以保存用戶的會話信息,我們可以吧信息或者數據放在Session中
③常見場景
網站登錄之後,你下次不用在登錄了,第二次範文就直接訪問進去
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • JavaScript進階內容——jQuery 我們在前面的文章中已經掌握了JavaScript的全部內容,現在讓我們瞭解一下JavaScript庫 這篇文章主要是為了為大家大致講解JavaScript庫以及使用方法,本篇不會完全講解jQuery的全部語法 如果希望完全掌握,可以參考網站jQuery ...
  • 1.創建虛擬環境 conda create --name yourEnv python=3.6 --name:也可以縮寫為 【-n】 yourEnv:是新創建的虛擬環境的名字,創建完,可以裝anaconda的目錄下找到envs/環境名 目錄 python=3.6:是python的版本號。也可以指定為 ...
  • JavaWeb 多個Servlet整合優化 由於一個Servlet只能接收一個地址的http請求,如果系統複雜度提高,就會有很多Servlet類。例如,對銷售系統來說,可能會有OederInsertServlet, OrderUpdateServlet, OrderDeleteSerlvet, Or ...
  • Spring Data JPA是Spring Data的子模塊。使用Spring Data,使得基於“repositories”概念的JPA實現更簡單和容易。Spring Data JPA的目標是大大簡化數據訪問層代碼的編碼。作為使用者,我們只需要編寫自己的repository介面,介面中包含一些個 ...
  • python3.9安裝pyqt,並設置pycharm 前言 這個學期的暑假實訓需要使用pyqt開發gui界面,然後我的python不知道發生了什麼,安裝總是爆出各種奇怪的錯誤,安裝完後,開發和運行的過程中也發生了很多的離奇的問題,我浪費了很多的時間在解決各種報錯上,項目進度被耽誤了許多,幸運的是後來 ...
  • Java面向對象(八) 二十四、abstract 關鍵字 abstract 可以用來修飾的結構:類、方法。 abstract 修飾類:抽象類。 此類不能實例化。 抽象類中一定有構造器,便於子類實例化時調用。(涉及:子類對象實例化的全過程) 開發中,都會提供抽象類的子類,讓子類對象實例化,完成相關的操 ...
  • 上一講【RocketMQ】消息的拉取 消息消費 當RocketMQ進行消息消費的時候,是通過ConsumeMessageConcurrentlyService的submitConsumeRequest方法,將消息提交到線程池中進行消費,具體的處理邏輯如下: 如果本次消息的個數小於等於批量消費的大小c ...
  • 遇到問題和需求 我的電腦環境:先安裝py2再安裝py3,平時我工作中是使用python2,如何保證兩個版本共存且讓代碼來選擇要使用的版本。 遇到問題 在cmd中輸入python,進入的是py2的環境,但是通過pip install模塊是安裝到了python3目錄下 需求 工作中使用pytho2,在學 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...