一、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>-->
<!-- <!– 配置 –>-->
<!-- <properties>-->
<!-- <!–專案默認構建編碼–>-->
<!-- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>-->
<!-- <!–編譯版本–>-->
<!-- <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依賴,復制上圖方框里的依賴代碼,依賴里的



然后將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
- 客戶端技術(服務器通過回應將資料發給客戶端,客戶端通過請求將資料帶到服務器上)
CookieDemo代碼
package com.tang.cookie;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
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.Date;
//保存用戶上一次訪問的時間
public class CookieDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//服務器告訴你,你來的時間,把這個時間封裝成一個信件,你下次帶來,我就知道你來了
//解決中文亂碼
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html");
PrintWriter out = resp.getWriter();
//Cookie,服務器端從客戶端獲取
Cookie[] cookies = req.getCookies();//這里回傳陣列,說明Cookie可能存在多個
//判斷Cookie是否存在
if(cookies != null){
//如果存在的話,就遍歷取出就行
out.write("你上一次訪問的時間是:");
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
//獲取cookie的名字
if(cookie.getName().equals("lastLoginTime")){
//獲取cookie中的值
long l = Long.parseLong(cookie.getValue());//將一個字串型別的時間戳轉換為長整型資料
Date date = new Date(l);//將時間戳轉化為日期
out.write(date.toLocaleString());//將一個日期轉化為字串,并寫出
//解碼
//out.write(URLDecoder.decode(cookie.getValue(),"utf-8"));
}
}
}else{
out.write("這是您第一次訪問本站");
}
//服務器給客戶端回應一個cookie,System.currentTimeMillis()得到的是從1970年1月1日到今天所獲得的時間戳,單位為毫秒
//編碼:中文傳輸盡量這樣傳,以防亂碼
//Cookie cookie = new Cookie("name", URLEncoder.encode("唐昊","utf-8"));
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+"");
resp.addCookie(cookie);//該方法需要一個Cookie所以就new一個就行
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
web.xml中servlet的注冊代碼就不寫了,上面寫的帶太多變了
運行結果圖


并且當你退出瀏覽器,再次進入后cookie值就會消失,但是如果設定cookie的生存期的話,即使退出瀏覽器,cookie的值任然存在,設定生存期的方法
//cookie有效期為1天,里面存盤的單位是秒,因此要計算一天有多少秒
cookie.setMaxAge(24*60*60);
cookie的細節問題:
-
一個cookie只能保存一個資訊;
-
一個web站點可以給瀏覽器發送多個cookie,最多存放20個cookie;
-
cookie大小有限制為4kb
-
300個cookie瀏覽器上限
洗掉Cookie
-
不設定有效期,關閉瀏覽器,自動失效
-
設定有效期時間為0;
編碼解碼:
//編碼:中文傳輸盡量這樣傳,以防亂碼
Cookie cookie = new Cookie("name", URLEncoder.encode("唐昊","utf-8"));
//解碼
out.write(URLDecoder.decode(cookie.getValue(),"utf-8"));
②session(重點)
-
服務器技術,利用這個技術,可以保存用戶的會話資訊,我們可以吧資訊或者資料放在Session中
-
服務器會給每一個用戶(瀏覽器)創建一個Session物件;
-
一個Session獨占一個瀏覽器,只要瀏覽器沒有關閉,這個session就存在
-
用戶登錄之后,整個網站它都可以訪問 -->保存用戶的資訊:保存購物車的資訊....
Session 和Cookie的區別: -
Cookie是把用戶的資料寫給用戶的瀏覽器,瀏覽器保存(可以保存多個)
-
Session把用戶的資料寫到用戶獨占Session中,服務器端保存(保存重要的資訊,減少服務器資源的浪費)
-
Session物件由服務創建
使用Session
SessionDemo代碼如下
package com.tang.session;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
public class SessionDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解決亂碼問題
resp.setCharacterEncoding("UTF-8");
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html");
//得到session
HttpSession session = req.getSession();
//給Session中存東西
session.setAttribute("name",new Person("唐三",23));
//獲取Session的ID
String sessionId = session.getId();
//判斷session是不是新創建的
if(session.isNew()){
resp.getWriter().write("session創建成功,ID為:"+sessionId);
}else{
resp.getWriter().write("session在服務器中已經存在了,ID為:"+sessionId);
}
//Session創建的時候自動做了如下的事情
// Cookie cookie = new Cookie("JSESSIONID",sessionId);
// resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
獲取Session里面存的資料
SessionDemo02
package com.tang.session;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
public class SessionDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解決亂碼問題
resp.setCharacterEncoding("UTF-8");
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html");
//得到session
HttpSession session = req.getSession();
Person person = (Person) session.getAttribute("name");
System.out.println(person.toString());
resp.getWriter().write(person.toString());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
運行結果圖

手動注銷Session
注:注銷的原理就是將其SessionID給注銷,注銷后再次訪問會分配一個新的SessionID
package com.tang.session;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class SessionDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
session.removeAttribute("name");
//手動注銷Session
session.invalidate();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
會話自動失效:web.xml代碼,注冊的代碼就不展示了
<!-- 設定Session默認失效時間-->
<session-config>
<!-- 1分鐘后,Session失效,以分鐘為單位-->
<session-timeout>1</session-timeout>
</session-config>
③常見場景
網站登錄之后,你下次不用在登錄了,第二次范文就直接訪問進去轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/500374.html
標籤:其他
上一篇:day07-
