JavaWeb
什么是JavaWeb?
- JavaWeb就是指所有通過Java語言撰寫可以通過瀏覽器訪問的程式的總稱;
- 一個JavaWeb程式由多個靜態web資源和動態資源組成,web程式開發完成后,若要被外界訪問,就要把web應用所在的目錄交給web服務器管理(虛擬目錄的映射);
- JavaWeb是基于請求和回應來開發的;

靜態Web
- 指任何時候訪問的內容都一致的Web界面,沒有互動;
- 靜態資源:html、CSS、js、txt、mp4...
動態Web
- 只訪問內容隨時間改變的Web界面,有互動,一般是與資料庫互動;
- 動態資源:jsp頁面、Servlet程式...
什么是請求和回應?
請求
- 請求是指客戶端向服務器發送資料,Request;
回應
- 回應是指服務器給客戶端回傳資料,Response;
請求和回應是成對出現的,有請求就有回應;

常用的Web服務器
Web服務器主要用來接收客戶端發送的請求和回應客戶端的請求;
-
Web服務器主要用來接收客戶端發送的請求和回應客戶端請求,
-
Tomcat(Apache)( 我們主要擼這只貓 ):當前應用最廣的JavaWeb服務器;
-
JBoss(Redhat紅帽):支持JavaEE,應用比較廣EJB容器 –> SSH輕量級的框架代替
-
GlassFish(Orcale):Oracle開發JavaWeb服務器,應用不是很廣;
-
Resin(Caucho):支持JavaEE,應用越來越廣;
-
Weblogic(Orcale):要錢的!支持JavaEE,適合大型專案;
-
Websphere(IBM):要錢的!支持JavaEE,適合大型專案
Tomcat服務器
安裝教程:
目錄介紹

- backup:存放組態檔,是在第一次運行了Tomcat服務器之后產生的,和conf目錄下的內容基本一致;
- bin:存放Tomcat服務器的可執行程式,核心包;
- conf:存放Tomcat服務器的組態檔;
- lib:存放Tomcat服務器的jar包;
- logs:存放Tomcat服務器運行時輸出的日記資訊;
- temp:存放Tomcat服務器運行時產生的臨時資料;
- webapps:存放部署的Web工程,里面的一個檔案夾就是一個Web工程;
- work:是Tomcat作業時的目錄,用來存放Tomcat運行時jsp翻譯為Servlet的原始碼,和Session鈍化的目錄;
啟動Tomcat服務器
- 找到Tomcat安裝目錄下的bin目錄下的startup.bat檔案,雙擊即可啟動Tomcat服務器;
- cmd命令列下,進入bin目錄下,輸入catalina run回車,即可啟動;
啟動Tomcat一閃而過問題解決:檢查JDK的環境配置
測驗Tomcat服務器是否開啟成功
- 在瀏覽器中輸入以下地址進行測驗:
- http://localhost:8080
- http://127.0.0.1:8080
- http://真實IP:8080
關閉Tomcat服務器
- 右上角X號;
- 快捷鍵Ctrl+C;
- Tomcat的bin目錄下的shutdown.bat,雙擊;
修改Tomcat的埠號
- 找到Tomcat目錄下的conf目錄下的server.xml組態檔;
- 找到Connector標簽,port就是埠號設定,修改它;

- Tomcat默認的埠號是8080;
- HTTP協議默認的埠號是:80;
將web工程部署到Tomcat服務器上
-
將Web工程拷貝到Tomcat安裝路徑的webapps目錄中
- 訪問Tomcat中的web工程:瀏覽器中輸入http://ip:port/工程名/目錄名/檔案名
-
找到Tomcat安裝目錄中的conf目錄下的Catalina目錄下的localhost下,創建組態檔XXX.xml
-
<!-- 檔案內容: Context 表示一個工程背景關系 path 表示工程的訪問路徑:/abc docBase 表示你的工程目錄在哪里--> <Context path="/abc" docBase="E:\book" /> -
訪問Tomcat中的web工程:瀏覽器中輸入http://ip:port/abc/ 就代表進入到了E:\book目錄下,先要繼續訪問book檔案中的資訊,就繼續/輸入
-
手托html頁面到瀏覽器與在瀏覽器輸入框http://ip:port:工程名/訪問的區別

地址欄的默認訪問
- 瀏覽器地址欄如果輸入http://ip:port/ 沒有工程名,默認訪問的就是Tomcat中的webapps目錄下的ROOT工程
- 瀏覽器地址欄中輸入http://ip:port/工程名/ 沒有資源名,默認訪問的就是該工程下的index.html檔案
部署在IDEA或者eclipse上
https://blog.csdn.net/weixin_44775516/article/details/109522779
Web工程的目錄介紹

- src:存放java代碼;
- web:存放web工程的資源檔案,html、css...
- WEB-INF:是一個受服務器保護的目錄,瀏覽器無法直接訪問到此目錄中
- lib:存放第三方jar包,jar包需要配置
- web.xml:是整個動態web工程的配置部署檔案,可以配置Servlet程式、Filter過濾器、Listener監聽器、Session超時...組件
Web 中的相對路徑和絕對路徑
-
相對路徑是:
- . 表示當前目錄
- .. 表示上一級目錄
- 資源名 表示當前目錄/資源名
-
絕對路徑:
- http://ip:port/工程路徑/資源路徑
web 中/ 斜杠的不同意義
- 在web中,/斜杠是一種絕對路徑
- /斜杠在瀏覽器中被決議,地址是:http://ip:port/
- <a href="https://www.cnblogs.com/">斜杠</a>
- / 斜杠如果被服務器決議,得到的地址是:http://ip:port/工程路徑
- <url-pattern>/servlet1</url-pattern>
- servletContext.getRealPath(“/”);
- request.getRequestDispatcher(“/”);
- 特殊情況: response.sendRediect(“/”); 把斜杠發送給瀏覽器決議,得到http://ip:port/
Servlet
什么是Servlet?
- Servlet(Server Applet),全稱Java Servlet;
- Servlet是JavaEE規范之一,就是介面,是用java撰寫的服務端程式;
- Servlet是JavaWeb三大組件之一,都有:Servlet程式、Filter過濾器、Listener監聽器;
- Servlet是運行在服務器上的一個Java小程式,它可以接受客戶端發送過來的請求,并回應資料給客戶端;
第一個Servlet程式
- 撰寫一個類要實作Servlet介面
- 實作介面中的service()方法,用于處理請求與回應資料
- 在web.xml中配置Servlet程式的訪問地址
這種方式一般不使用,我們繼承他的實作類HttpServlet
JAVA代碼:
public class Servlet1 implements Servlet {
@Override//初始化
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
/**
* service方法是用來專門處理請求和回應的
* @param servletRequest
* @param servletResponse
* @throws ServletException
* @throws IOException
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
}
@Override
public String getServletInfo() {
return null;
}
@Override//銷毀
public void destroy() {
}
}
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">
<!--welcome-file-list標簽是當Tomcat服務啟動時,默認跳到哪個資源,
其實這個不用設定,默認也會跳轉到index.html或者index.jsp資源的
-->
<welcome-file-list>
<!--welcome-file標簽就是要跳轉的資源-->
<welcome-file>HolleWord.html</welcome-file>
</welcome-file-list>
<!--service標簽是給Tomcat配置Servlet程式的 -->
<servlet>
<!--servlet-name標簽是給Servlet程式起一個別名-->
<servlet-name>Servlet1</servlet-name>
<!--servlet-class標簽是Servlet程式的全類名-->
<servlet-class>com.mlyr.Servlet1</servlet-class>
</servlet>
<!--servlet-mapping標簽給Servlet程式配置訪問地址-->
<servlet-mapping>
<!--servlet-name標簽的作用是告訴服務器,當前配置的地址給誰用-->
<servlet-name>Servlet1</servlet-name>
<!--
url-pattern標簽配置訪問地址
/ 在服務器決議時,會被決議為http://ip:port/工程名
/servlet1表示地址為:http://ip:port/工程名/servlet1
-->
<url-pattern>/servlet1</url-pattern>
</servlet-mapping>
</web-app>
URL地址到Servlet程式的訪問

Servlet的生命周期
- 第一步:執行Servlet構造器方法;
- 第二步:執行init()初始化方法;
- 第三步:執行service()方法;
- 第四步:執行destroy()銷毀方法;
第一部與第二步,只在第一次訪問,創建Servlet程式的時候會執行;
第三步,每次訪問Servlet程式的時候都會執行;
第四步,只當web工程停止的時候,會執行;
GET、POET請求的分發處理
- getMethod():可以獲取請求過來的方式,是GET請求還是POST請求
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
//型別轉換,HttpServletRequest有getMethod()方法,
HttpServletRequest request = (HttpServletRequest) servletRequest;
//可以獲取請求的方式
String method = request.getMethod();
//將不同的請求,分為兩個方法,分別處理
if (method.equals("GET")){
doGet();
}else if (method.equals("POST")){
doPost();
}
}
private void doPost() {
System.out.println("POST請求");
}
private void doGet() {
System.out.println("GET請求");
}
主要類與方法
HttpServlet類
- 一般實作Servlet程式,都是使用繼承HttpServlet類的方式來開發;
- 它在Servlet介面的基礎上,分開了請求方式,還有一系列方法;
- 撰寫一個類繼承HttpServlet類
- 重寫它的doGet()、doPost()方法;
- 到web.xml檔案中配置Servlet程式的訪問地址
HttpServlet類的方法:
- doPost():處理post請求;
- doGet():處理get請求;
java代碼
public class Servlet2 extends HttpServlet {
/**
* 只有在post請求時呼叫
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("HelloServlet2 doPost 方法");
}
/**
* 只有在get請求時呼叫
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("HelloServlet2 doGet 方法");
}
}
web.xml檔案配置
<servlet>
<servlet-name>Servlet2</servlet-name>
<servlet-class>com.mlyr.Servlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Servlet2</servlet-name>
<url-pattern>/servlet2</url-pattern>
</servlet-mapping>
html檔案
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="servlet2" method="post">
<input type="submit">
</form>
</body>
</html>
- 當表單請求是post方法,只會呼叫Servlet2類中的doPost()方法!

IDEA中能夠一鍵生成Servlet程式:右擊包->點擊NEW->Create New Servlet(在下面找)->Name框(自定義類名)
根據IDEA版本不同,會注解宣告訪問地址或者web.xml檔案中宣告
@WebServlet(name="Servlet3",urlPatterns = "/servlet3")這就是注解宣告訪問地址,idea自動生成的有問題,要自行修改
Servlet類的繼承體系

ServletConfig類
- ServletConfig類是Servlet程式的配置資訊類;
- Servlet程式和ServletConfig物件都是由Tomcat負責創建的,Servlet程式是第一次訪問的時候創建,ServletConfig是每個Servlet程式創建時,就創建一個對應的ServletConfig物件;
ServletConfig類的作用
- 可以獲取Servlet程式的別名,就是servlet-name標簽中的值;
- 獲取初始化引數init-param標簽中的值;
- init-param標簽只能在servlet標簽中定義,它只屬于它所在的Servlet程式;
- 只能被ServletConfig物件獲取;
- 獲取ServletContext物件;
ServletConfig類中的方法:
- getServletName():獲取web.xml組態檔中servlet-name標簽的值;
- getInitParameter(引數):獲取init-param標簽中的值;
- 引數:param-name標簽
- 獲取到param-value標簽的值,這兩個標簽好比鍵值對
- getServletContext():回傳ServletContext物件;
web.xml檔案配置
<servlet>
<servlet-name>Servlet2</servlet-name>
<servlet-class>com.mlyr.Servlet2</servlet-class>
<!--init-param標簽是初始化引數,這個只屬于Servlet2程式中的,別的程式訪問不到-->
<init-param>
<!--引數的名字-->
<param-name>username</param-name>
<!--引數的值-->
<param-value>root</param-value>
</init-param>
<init-param>
<!--引數的名字-->
<param-name>password</param-name>
<!--引數的值-->
<param-value>123456</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Servlet2</servlet-name>
<url-pattern>/servlet2</url-pattern>
</servlet-mapping>
Java代碼
public class Servlet2 implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
//獲取Servlet程式的別名,就是servlet-name標簽的值
System.out.println(servletConfig.getServletName());
//獲取初始化引數,init-param標簽中的
System.out.println("username:"+servletConfig.getInitParameter("username"));
System.out.println("password:"+servletConfig.getInitParameter("password"));
//獲取ServletContext物件
System.out.println(servletConfig.getServletContext());
}
}
上方的是實作了Servlet介面,init()方法自然會重寫Servlet介面中的方法;
下方:如果繼承了HttpServlet類,它的父抽象類GenericServlet中有兩個init()方法,一個是從介面Servlet中實作的有參方法,還有一個無參init()方法是獨有的,如果自定義的類要重寫HttpServlet類中的init()有參方法,一定要呼叫super.init(config);不然會在使用ServletConfig物件的時候會報500錯誤(內部服務器錯誤),空指標例外;

ServletContext類
- ServletContext是一個介面,表示Servlet背景關系物件;
- 一個web工程只有一個ServletContext物件;
- ServletContext物件是一個域物件;
- 域物件,是可以像Map一樣存取資料的物件;
| 存資料 | 取資料 | 洗掉資料 | |
|---|---|---|---|
| Map | put() | get() | remove() |
| 域物件 | setAttribute() | getAttribute() | removeAttribute() |
- ServletContext在web工程啟動的時候創建,在web工程停止的時候銷毀;
ServletContext類的作用
- 獲取web.xml中配置的背景關系引數context-param標簽;
- context-param標簽是不能在servlet標簽中的,只能在最外面,屬于整個web工程,不單單只屬于哪一個Servlet程式;
- 只能被ServletContext物件獲取;
- 獲取當前工程路徑
- 獲取工程部署后在服務器硬碟上的絕對路徑;
- 像Map一樣存取資料;
ServletContext類中的方法
- getInitParameter(引數):獲取context-param標簽中的資料;
- getContextPath():獲取當前工程的路徑;
- getRealPath(引數):獲取工程部署后在服務器硬碟上的絕對路徑;
- 引數/: 斜杠在服務器上會被決議為http://ip:port/工程名/ 就是映射到IDEA代碼的web目錄
- sc.getRealPath("/img"):表示獲取該工程下的img目錄在工程部署后在服務器硬碟上的絕對路徑;
- setAttribute(別名,物件):將一個物件存盤到ServletContext物件中,起個別名;
- getAttribute(別名):通過別名獲取存入其中的物件;
- removeAttribute(別名):洗掉該別名中的物件;
web.xml檔案配置
<!--context-param是背景關系引數,屬于整個web工程,都能訪問到-->
<context-param>
<!--param-name與param-value是存盤資料的標簽-->
<param-name>name</param-name>
<param-value>ROOT</param-value>
</context-param>
<context-param>
<param-name>PSW</param-name>
<param-value>123</param-value>
</context-param>
Java代碼
public class Servlet4 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 獲取ServletContext 物件
ServletContext sc = getServletContext();
//獲取web.xml中配置的背景關系引數,context-param標簽中的資料
System.out.println("name:"+sc.getInitParameter("name"));//name:ROOT
System.out.println("PSW:"+sc.getInitParameter("PSW"));//PSW:123
//獲取當前的工程路徑
System.out.println("當前工程路徑"+sc.getContextPath());//當前工程路徑/JavaWeb_4
//獲取工程部署后在服務器硬碟上的絕對路徑
// / 斜杠在服務器上會被決議為http://ip:port/工程名/ 就是映射到IDEA代碼的web目錄
System.out.println("工程部署的路徑是:"+sc.getRealPath("/"));//工程部署的路徑是:E:\IDEA\JavaWeb_4\out\artifacts\JavaWeb_4_war_exploded\
System.out.println("工程下img目錄的絕對路徑是:"+sc.getRealPath("/img"));//工程下img目錄的絕對路徑是:E:\IDEA\JavaWeb_4\out\artifacts\JavaWeb_4_war_exploded\img
System.out.println("工程下img目錄下的1.jpg檔案的絕對路徑是:"+sc.getRealPath("/img/1.jpg"));//工程下img目錄下的1.jpg檔案的絕對路徑是:E:\IDEA\JavaWeb_4\out\artifacts\JavaWeb_4_war_exploded\img\1.jpg
// 獲取ServletContext 物件
ServletContext context = getServletContext();
System.out.println(context);
System.out.println("保存之前:獲取key的值是:"+ context.getAttribute("key"));//保存之前:獲取key的值是:null
//在key中存盤一個物件
context.setAttribute("key", "value");
System.out.println("存盤之后:獲取域資料key的值是:"+ context.getAttribute("key"));//存盤之后:獲取域資料key的值是:value
//洗掉key里面存盤的物件
context.removeAttribute("key");
//上面的洗掉了key里面的物件,下面將獲取不到
System.out.println("存盤之后:獲取域資料key的值是:"+ context.getAttribute("key"));//存盤之后:獲取域資料key的值是:null
}
}

這個上面的工程路徑是IDEA整合Tomcat之后,Tomcat被拷貝的一些副本內容,就是將IDEA實際存在的專案,映射進Tomcat服務器中;
setAttribute存盤的物件,要先存進去,然后整個web工程中所有Servlet程式才能夠訪問到,沒有存盤到ServletContext物件中,是獲取不到的;
HttpServletRequest類
- 每次只要有請求進入Tomcat服務器,Tomcat服務器就會把請求過來的HTTP協議資訊決議好封裝到Request物件中,然后傳遞到service方法(doGet、doPost方法)中供我們使用;
- 通過HTTPServletRequest物件,可以獲取所有請求的資訊;
HTTPServletRequest類的方法
- getRequestURI() 獲取請求的資源路徑
- getRequestURL() 獲取請求的統一資源定位符(絕對路徑)
- getRemoteHost() 獲取客戶端的ip 地址
- getHeader(引數) 獲取請求頭
- 引數:要獲取的請求頭名稱
- getMethod() 獲取請求的方式GET 或POST
- getParameter(引數) 獲取請求的引數
- 引數:要請求哪一個引數的值
- getParameterValues(引數) 獲取請求的多個引數
- 引數:要請求哪一個引數的值
- setAttribute(別名,物件) 將物件作為request對象的一個屬性存放到request物件中;
- 別名:String型別,就相當于request物件中的一個屬性,自己起名;
- 物件:Object型別
- getAttribute(別名) 獲取request物件中該別名的值(這個值可以是任何型別)
- getRequestDispatcher(引數) 獲取請求轉發物件
- 引數:就是要轉發給誰
- getRequestDispatcher(引數).forward(request,response) 轉發
java代碼
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//獲取請求的資源路徑
System.out.println("URI:"+request.getRequestURI());//URI:/JavaWeb_4/servlet5
//獲取請求的統一資源定位符(絕對路徑)
System.out.println("URL:"+request.getRequestURL());//URL:http://localhost:8080/JavaWeb_4/servlet5
//獲取客戶端的ip 地址
//IP:0:0:0:0:0:0:0:1 客戶端localhost:8080訪問,這個是ipv6的表現形式,對應ipv4來說相當于127.0.0.1
//IP:192.168.137.1 使用真實IP地址訪問
//IP:127.0.0.1 客戶端127.0.0.1:8080訪問
System.out.println("IP:"+request.getRemoteHost());
//獲取請求頭
System.out.println("User-Agent請求頭"+request.getHeader("User-Agent"));//User-Agent請求頭Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36
System.out.println("Accept-Language請求頭"+request.getHeader("Accept-Language"));//Accept-Language請求頭zh-CN,zh;q=0.9
//獲取請求的方式GET 或POST
System.out.println(request.getMethod());//GET
////////////////////////////////////////////////////////////////
//獲取請求引數,就是獲取表單提交過來的引數值
System.out.println("用戶名:"+request.getParameter("username"));//用戶名:MLYR
System.out.println("密碼:"+request.getParameter("password"));//密碼:123
//獲取請求的多個引數
String[] hobby = request.getParameterValues("hobby");
System.out.println("興趣愛好:"+ Arrays.toString(hobby));//興趣愛好:[java, js]
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//設定請求的字符集編碼為UTF-8,如果不設定,輸入中文會亂碼
req.setCharacterEncoding("UTF-8");
//獲取當前請求的字符編碼,需要提前設定,不然是null
System.out.println(req.getCharacterEncoding());//UTF-8
//獲取請求引數,就是獲取表單提交過來的引數值
System.out.println("用戶名:"+req.getParameter("username"));//用戶名:中
System.out.println("密碼:"+req.getParameter("password"));//密碼:1212
//獲取多個請求的引數
String[] hobby = req.getParameterValues("hobby");
System.out.println("興趣愛好:"+ Arrays.toString(hobby));//興趣愛好:[cpp, java]
}
表單代碼
<form action="servlet5" method="get">
用戶名:<input type="text" name="username"><br/>
密碼:<input type="password" name="password"><br/>
興趣愛好:<input type="checkbox" name="hobby" value="https://www.cnblogs.com/MLYR/archive/2023/02/27/cpp">C++
<input type="checkbox" name="hobby" value="https://www.cnblogs.com/MLYR/archive/2023/02/27/java">Java
<input type="checkbox" name="hobby" value="https://www.cnblogs.com/MLYR/archive/2023/02/27/js">JavaScript<br/>
<input type="submit">
</form>
doGet()請求一般不會亂碼,如果有,按照下面的方法解決:
String username = request.getParameter("username");
//先以iso-8859-1進行編碼,再以utf-8進行解碼
username = new String(username.getBytes("iso-8859-1"),"UTF-8");
//獲取請求引數,就是獲取表單提交過來的引數值
System.out.println("用戶名:"+username);
HttpServletResponse類
- HttpServletResponse類和HttpServletRequest類一樣,每一次請求進來,Tomcat服務器都會創建一個Response物件和Request物件;
- HttpServletResponse表示所有的回應資訊,HttpServletRequest表示請求過來的資訊;
- 要回傳給客戶端資訊,都是通過Response物件進行設定;
兩個輸出流
- getOutputStream() 位元組流,常用于下載,傳遞二進制;
- getWriter() 字符流,常用于回傳字串
- 兩個流不能同時使用;
HttpServletResponse類的方法
- setContentType() 同時設定服務器和客戶端的編碼格式
- setCharacterEncoding() 設定服務器的編碼格式
- setStatus(引數) 設定回應狀態嗎,表示重定向
- setHeader() 通過回應頭設定瀏覽器的編碼格式
- getWriter() 獲取字符輸出流物件PrintWriter
- writer(引數) 寫資料,引數可以是Object、int、String、陣列、double...
- getOutputStream() 獲取位元組輸出流物件ServletOutputStream
- print(引數) 寫資料,,引數可以是int、String、陣列、double...不能寫物件
- sendRedirect(引數) 重定向
- 引數:要重定向的路徑
java代碼
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//它會同時設定服務器和客戶端都使用UTF-8 字符集,還設定了回應頭
//此方法一定要在獲取流物件之前呼叫才有效
response.setContentType("text/html; charset=UTF-8");
//設定服務器字符集為UTF-8
response.setCharacterEncoding("UTF-8");
//通過回應頭,設定瀏覽器也使用UTF-8 字符集
response.setHeader("Content-Type", "text/html; charset=UTF-8");
//CharConversionException: 不是ISO 8859-1字符:[啦]
System.out.println("doGet方法");
//獲取字符輸出流物件
//PrintWriter writer = response.getWriter();
//寫資料
//writer.println("啦啦啦lll");
//獲取位元組輸出流物件
ServletOutputStream os = response.getOutputStream();
//寫資料
os.print(121212121);
}
java.lang.IllegalStateException: 當前回應已經呼叫了方法getOutputStream()
兩個流一起使用報錯
請求轉發與重定向
請求轉發
- 服務器收到請求后,從一次資源跳轉到另一個資源的操作,叫做請求轉發;

表單
<form action="servlet6" method="post">
資訊:<input type="text" name="xinxi"><br/>
<input type="submit">
</form>
Servlet6
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//設定請求的字符集編碼
req.setCharacterEncoding("UTF-8");
//獲取請求引數
String xinxi = req.getParameter("xinxi");
System.out.println(xinxi);//陌路邑人
//設定資料域,就是將一個物件放進資料域中,起個別名key
req.setAttribute("key","來自Servlet6");
//獲取要轉發給的地址物件(一般與下面執行轉發是一步撰寫) /servlet7就是http://localhost:8080/JavaWeb_4/servlet7
RequestDispatcher rd = req.getRequestDispatcher("/servlet7");
//執行轉發操作
rd.forward(req,resp);
}
Servlet7
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//doPost方法中,必須是POST請求,才能被獲取
//獲取請求引數
String xinxi = request.getParameter("xinxi");//陌路邑人
System.out.println(xinxi);
//獲取Servlet6轉發過來的物件
Object key = request.getAttribute("key");
System.out.println("Servlet7獲取到Servlet6轉發過來的物件:"+key);//Servlet7獲取到Servlet6轉發過來的物件:來自Servlet6
}
表單中的提交是post請求方式,所以在兩個Servlet程式中,想要獲取表單提交的資料,必須也是doPost方法進行獲取;
a標簽的轉發
web工程下d.html
<head>
<meta charset="UTF-8">
<title>首頁</title>
</head>
<body>
<!--下方的可以與HTML下的e.html互相跳轉-->
<a href="https://www.cnblogs.com/MLYR/archive/2023/02/27/HTML/e.html">b.html</a>
<!--該標簽跳轉到servlet7程式配置的路徑上-->
<a href="https://www.cnblogs.com/MLYR/archive/2023/02/27/servlet7">請求轉發</a>
</body>
HTML下e.html
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--base 標簽設定頁面相對路徑作業時參照的地址href 屬性就是引數的地址值-->
<base href="http://localhost:8080/JavaWeb_4/HTML/e.html">
</head>
<body>
<a href="https://www.cnblogs.com/MLYR/archive/2023/02/d.html">回到首頁</a>
</body>
Servlet7
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("經過了Servlet7程式");
//如果有請求到這,進行轉發到HTML下的e.html
request.getRequestDispatcher("/HTML/e.html").forward(request,response);
}
這種情況沒有base標簽給e.html進行參照路徑的話,他就會報錯,找不到檔案;
下面解釋:
- 當首先訪問web工程下的d.html檔案時,它的絕對路徑是http://localhost:8080/JavaWeb_4/d.html;
- 當點擊請求轉發連接時,他就會跳到Servlet7程式所配置的路徑上:http://localhost:8080/JavaWeb_4/servlet7;
- 然后當點擊回到首頁連接時,它相當于將a標簽中的../d.html路徑與他現在所在的路徑進行拼接跳轉,就會跳轉到http://localhost:8080/JavaWeb_4/d.html(http://localhost:8080/JavaWeb_4/servlet7../d.html,../相當于與前面的目錄相抵消)路徑,當然找不到檔案;
- 當base標簽給e.html檔案給定一個絕對路徑http://localhost:8080/JavaWeb_4/HTML/e.html,就是該檔案的絕對路徑,不管怎么與a標簽上的../d.html進行拼接,他就可以找到正確的路徑

重定向
- 請求重定向,是指客戶端給服務器發送請求后,回傳服務器給客戶端一個新地址,讓客戶端重新去訪問新地址;

java代碼
//Servlet9
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("來晚了");
/*request.setAttribute("kk","KKKKKK");
//第一種重定向方式
//設定回應狀態嗎,表市重定向
response.setStatus(302);
//設定回應頭,說明新地址
response.setHeader("Location","servlet8");*/
//第二種重定向,引數不能加/斜杠,這里的/會被服務器決議為http://localhost:8080/
response.sendRedirect("servlet8");
}
//Servlet8
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet8doGet方法");
//重定向不共享Request物件中的資料域
System.out.println(req.getAttribute("kk"));
}
轉發與重定向的區別
- 路徑區別
- 相對路徑沒有區別;
- 絕對路徑:
- 轉發:中的/表示:http://ip:port/工程路徑;
- 重定向:中的/表示:http://ip:port/;
- 地址欄的變化
- 轉發:地址欄不會顯示出轉發后的地址;
- 重定向:則是完全跳轉到新地址,地址欄也就是新地址;
- Request物件中的資料
- 轉發:不會丟失資料;
- 重定向:會丟失資料;
- 請求次數
- 轉發:客戶端只向服務器發送一次請求;
- 重定向:客戶端發送了兩次請求給服務器;
- 跳轉位置
- 轉發:在服務器中跳轉;
- 重定向:回傳給客戶端新地址,客戶端跳轉;
- 訪問域
- 轉發:只能在web工程中訪問跳轉;
- 重定向:可以跨域訪問跳轉;就是隨便跳;
- 能否訪問web工程的WEB-INF目錄
- 轉發:可以訪問;
- 重定向:不可以訪問;
監聽器
什么是監聽器?
- Listener監聽器是JavaWeb的三大組件之一;
- 作用:監聽某種事物的變化,然后通過回呼函式,反饋給客戶;
ServletContextListener監聽器
- ServletContextListener 它可以監聽ServletContext 物件的創建和銷毀
- ServletContext 物件在web 工程啟動的時候創建,在web 工程停止的時候銷毀,
- 監聽到創建和銷毀之后都會分別呼叫ServletContextListener 監聽器的方法反饋
public interface ServletContextListener extends EventListener {
//在ServletContext 物件創建之后馬上呼叫,做初始化
public void contextInitialized(ServletContextEvent sce);
//在ServletContext 物件銷毀之后呼叫
public void contextDestroyed(ServletContextEvent sce);
}
如何實作ServletContextListener監聽器監聽ServletContext物件
public class Listener1 implements ServletContextListener{
//ServletContext物件在創建的時候執行
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext物件創建了");
}
//ServletContext物件在銷毀的時候被執行
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext物件銷毀了");
}
}
<!--配置監聽器-->
<listener>
<listener-class>com.mlyr.listener.Listener1</listener-class>
</listener>
ServletContextListener監聽器的主要作用
- 初始化作業:初始化物件,初始化資料,比如加載資料庫驅動,對連接池的初始化,
- 加載一些初始化的組態檔;
Cookie
什么是Cookie?
- Cookie 是一小段文本資訊,伴隨著用戶請求和頁面在 Web 服務器和瀏覽器之間傳遞,Cookie 包含每次用戶訪問站點時 Web 應用程式都可以讀取的資訊;

為什么需要Cookie?
- 因為HTTP協議是無狀態的,對于一個瀏覽器發出的多次請求,WEB服務器無法區分是否來源于同一個瀏覽器;
- 所以,需要額外的資料用于維護會話;Cookie正是這樣一段隨HTTP請求一起被傳遞的額外資料;
Cookie的注意點
能不能一次發送多個Cookie?
- 可以,可以創建多個Cookie物件,使用response呼叫多次addCookie方法發送即可;
Cookie能不能存中文?
- 在Tomcat8之前不能存中文,要進行URL編碼(%E3)或者BASE64編碼將中文資料轉碼
- 在Tomcat8之后支持中文資料,但是特殊字符還是不支持;
Cookie大小限制
- 瀏覽器對于單個cookie 的大小有限制(4kb) 以及 對同一個域名下的總cookie數量也有限制(20個)
Cookie的創建、獲取、修改

html頁面
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Cookie</title>
<base href="http://localhost:8080/JavaWeb_4/">
<style type="text/css">
ul li {
list-style: none;
}
</style>
</head>
<body>
<iframe name="target" height="500" style="float: left;"></iframe>
<div style="float: left;">
<ul>
<li><a href="https://www.cnblogs.com/MLYR/archive/2023/02/27/cookie1?action=createCookie" target="target">Cookie的創建</a></li>
<li><a href="https://www.cnblogs.com/MLYR/archive/2023/02/27/cookie1?action=getCookie" target="target">Cookie的獲取</a></li>
<li><a href="https://www.cnblogs.com/MLYR/archive/2023/02/27/cookie1?action=updateCookie" target="target">Cookie值的修改</a></li>
<li>Cookie的存活周期</li>
<li>
<ul>
<li><a href="https://www.cnblogs.com/MLYR/archive/2023/02/27/cookie1?action=defaultLife" target="target">Cookie的默認存活時間(會話)</a></li>
<li><a href="https://www.cnblogs.com/MLYR/archive/2023/02/27/cookie1?action=deleteNow" target="target">Cookie立即洗掉</a></li>
<li><a href="https://www.cnblogs.com/MLYR/archive/2023/02/27/cookie1?action=life3600" target="target">Cookie存活3600秒(1小時)</a></li>
</ul>
</li>
<li><a href="https://www.cnblogs.com/MLYR/archive/2023/02/27/cookie1?action=testPath" target="target">Cookie的路徑設定</a></li>
<li><a href="" target="target">Cookie的用戶免登錄練習</a></li>
</ul>
</div>
</body>
</html>
java代碼
package com.mlyr.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;
public class Cookie1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
String action = request.getParameter("action");
switch (action){
case "createCookie":
createCookie(request,response);
break;
case "getCookie":
getCookie(request,response);
break;
case "updateCookie":
updateCookie(request,response);
break;
}
}
// Cookie的創建
protected void createCookie(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//創建Cookie物件
Cookie cookie1 = new Cookie("key1", "value1");
Cookie cookie2 = new Cookie("key2", "value2");
//保存到客戶端
response.addCookie(cookie1);
response.addCookie(cookie2);
//回傳資訊給客戶端頁面
response.getWriter().write("Cookie創建成功{Cookie1:"+cookie1+"-->Cookie2:"+cookie2+"}");
}
// Cookie的獲取
protected void getCookie(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//通過請求獲取客戶端中的Cookie陣列
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
//getName():獲取到Cookie的key值
//getValue():獲取到Cookie的value值
response.getWriter().write("key=="+cookie.getName()+"-->valuehttps://www.cnblogs.com/MLYR/archive/2023/02/27/=="+cookie.getValue()+"\n");
}
Cookie key1 = CookieUtils.findCookie("key1", cookies);
String value = https://www.cnblogs.com/MLYR/archive/2023/02/27/key1.getValue();
response.getWriter().write("key1=="+value);
}
// Cookie的修改
protected void updateCookie(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
//第一種方式:直接創建一個新的Cookie物件,key值與要修改的一樣,直接覆寫掉原來的
Cookie cookie = new Cookie("key1", "我改了");
response.addCookie(cookie);
//第二種方式:先找到要修改的Cookie物件,呼叫setValue()方法修改值
Cookie key2 = CookieUtils.findCookie("key2", request.getCookies());
if (key2!=null){
//修改
key2.setValue("人傻了");
//通知客戶端
response.addCookie(key2);
}else {
System.out.println("沒找到");
}
}
}
查找Cookie
import javax.servlet.http.Cookie;
// Cookie工具類
public class CookieUtils {
public static Cookie findCookie(String name,Cookie[] cookies ){
//判斷當名字、Cookie陣列任意一個為null時,就沒有必要查詢了
if (name == null || cookies == null || cookies.length ==0){
return null;
}
//回圈遍歷Cookie陣列
for (Cookie cookie : cookies) {
//當name與cookie中的key值相同就回傳它
if (name.equals(cookie.getName())) {
return cookie;
}
}
return null;
}
}
Cookie的生命周期
- setMaxAge(int seconds):這個方法就是設定Cookie的保存時間的方法;
- 正數:要保存的時間秒數,將Cookie資料寫到硬碟中;
- 負數:默認值,當瀏覽器關閉,Cookie資料被銷毀;
- 零:洗掉Cookie資訊;
//Cookie的立即洗掉
private void deleteNow(HttpServletRequest request, HttpServletResponse response) throws IOException {
Cookie key3 = CookieUtils.findCookie("key3", request.getCookies());
if (key3!=null){
key3.setMaxAge(0);
response.addCookie(key3);
response.getWriter().write("Key3已經洗掉!!!");
}
}
//保存3600秒
private void life3600(HttpServletRequest request, HttpServletResponse response) throws IOException {
Cookie key4 = new Cookie("key4", "3600");
//設定保存key4的時間
key4.setMaxAge(60*60);
response.addCookie(key4);
response.getWriter().write("Key4已經設定保存時間1小時");
}
Cookie的共享設定
- 默認的Cookie只能在一個應用中共享,即一個Cookie只能由創建它的應用獲得,
- setPath():設定cookie的共享范圍;
- cookie.setPath("/"):可在同一應用服務器內共享方法
- cookie.setPath(request.getContextPath()+"/HTML");只在該工程的HTML下共享,別的目錄下獲取不到
private void testPath(HttpServletRequest request, HttpServletResponse response) throws IOException {
Cookie cookie = new Cookie("key5", "有效路徑");
cookie.setPath(request.getContextPath()+"/HTML");
response.addCookie(cookie);
response.getWriter().write("創建了一個帶有路徑的cookie");
}
免輸入用戶名登錄
java代碼
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//獲取到請求進來的用戶名與密碼
String username = request.getParameter("username");
String password = request.getParameter("password");
//先給定一個死的值
if ("111111".equals(username) && "111111".equals(password)){
//將請求進來的用戶名放入Cookie物件中
Cookie cookie = new Cookie("username",username);
//設定它的保存時間
cookie.setMaxAge(60*60*60);
//回傳給客戶端
response.addCookie(cookie);
System.out.println("登陸成功");
}else{
System.out.println("登錄失敗");
}
}
jsp頁面
- jap頁面中的用戶名輸入框中的value值就在cookie域中拿就行,第一次沒有默認就為空,第二次訪問時,Cookie域中就會保存有用戶名,當訪問時就有了用戶名
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="http://localhost:8080/JavaWeb_4/cookie2" method="get">
用戶名:<input type="text" name="username" value="https://www.cnblogs.com/MLYR/archive/2023/02/27/${cookie.username.value}"> <br>
密碼:<input type="password" name="password"> <br>
<input type="submit" value="https://www.cnblogs.com/MLYR/archive/2023/02/27/登錄">
</form>
</body>
</html>
Session
什么是Session?
- Session 就是會話,它是用來維護一個客戶端和服務器之間關聯的一種技術;
- Session是另一種記錄客戶狀態的機制,不同的是Cookie保存在客戶端瀏覽器中,而Session保存在服務器上,
- 客戶端瀏覽器訪問服務器的時候,服務器把客戶端資訊以某種形式記錄在服務器上,這就是Session,客戶端瀏覽器再次訪問時只需要從該Session中查找該客戶的狀態就可以了
創建Session物件、Session域中的存取
HTML頁面
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Session</title>
<base href="http://localhost:8080/JavaWeb_4/">
<style type="text/css">
ul li {
list-style: none;
}
</style>
</head>
<body>
<iframe name="target" height="500" style="float: left;"></iframe>
<div style="float: left;">
<ul>
<li><a href="https://www.cnblogs.com/MLYR/archive/2023/02/27/session1?action=createOrGetSession" target="target">Session的創建和獲取(id號、是否為新創建)</a></li>
<li><a href="https://www.cnblogs.com/MLYR/archive/2023/02/27/session1?action=setAttribute" target="target">Session域資料的存盤</a></li>
<li><a href="https://www.cnblogs.com/MLYR/archive/2023/02/27/session1?action=getAttribute" target="target">Session域資料的獲取</a></li>
<li>Session的存活</li>
<li>
<ul>
<li><a href="https://www.cnblogs.com/MLYR/archive/2023/02/27/session1?action=defaultLife" target="target">Session的默認超時及配置</a></li>
<li><a href="https://www.cnblogs.com/MLYR/archive/2023/02/27/session1?action=life3" target="target">Session3秒超時銷毀</a></li>
<li><a href="https://www.cnblogs.com/MLYR/archive/2023/02/27/session1?action=deleteNow" target="target">Session馬上銷毀</a></li>
</ul>
</li>
<li><a href="" target="target">瀏覽器和Session系結的原理</a></li>
</ul>
</div>
</body>
</html>
java代碼
package com.mlyr;
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 javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/session1")
public class Session1 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
String action = request.getParameter("action");
switch (action){
case "createOrGetSession":
createOrGetSession(request,response);
break;
case "setAttribute":
setAttribute(request,response);
break;
case "getAttribute":
getAttribute(request,response);
break;
}
}
//Session的創建和獲取(id號、是否為新創建)
protected void createOrGetSession(HttpServletRequest request, HttpServletResponse response) throws IOException {
//創建Session物件
HttpSession session = request.getSession();
//獲取Session物件的ID值
String id = session.getId();
//判斷Session是否剛剛創建的
boolean aNew = session.isNew();
//將結果回應給頁面
response.getWriter().write("Session物件:"+session+"\n");
response.getWriter().write("Session物件的ID值:"+id+"\n");
response.getWriter().write("判斷Session是否剛剛創建的:"+aNew+"\n");
}
//Session域資料的存盤
protected void setAttribute(HttpServletRequest request, HttpServletResponse response) throws IOException {
//向Session域中存放資料
request.getSession().setAttribute("key1","value1");
response.getWriter().write("Session域資料的存盤完成");
}
//Session域資料的獲取
protected void getAttribute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
//獲取Session域中的資料
Object key1 = request.getSession().getAttribute("key1");
response.getWriter().write("獲取Session域中的資料:"+key1);
}
}
Session生命周期
- public void setMaxInactiveInterval(int interval) 設定Session 的超時時間(以秒為單位),超過指定的時長,Session就會被銷毀,
- 值為正數的時候,設定Session 的超時時長,
- 負數表示永不超時(極少使用)
- public int getMaxInactiveInterval()獲取Session 的超時時間
- public void invalidate() 讓當前Session會話馬上超時無效
Session的默認Session超時時長
- IDEA中Using CATALINA_BASE整合后的路徑下,web.xml組態檔中默認配置了Session的超時時長為30分鐘
<session-config>
<session-timeout>30</session-timeout>
</session-config>
- 如果想修改整個Web工程的所有Session超時時長,可以在Web工程下的web.xml組態檔中添加配置,就是上面的
- 如果只想修改個別Session的超時時長,使用setMaxInactiveInterval()方法單獨設定
//Session的默認超時及配置
protected void defaultLife(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
int maxInactiveInterval = request.getSession().getMaxInactiveInterval();
response.getWriter().write("Session的默認超時時長:"+maxInactiveInterval);
}
//Session3秒超時銷毀
protected void life3(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
request.getSession().setMaxInactiveInterval(3);
response.getWriter().write("已經設定Session的超時時長為3秒");
}
//Session馬上銷毀
protected void deleteNow(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
request.getSession().invalidate();
response.getWriter().write("設定Session立即銷毀");
}

Session的實作原理
- Session 技術,底層其實是基于Cookie 技術來實作的,

session和cookie的聯系和區別
- session和cookie都可以保存跟特定會話關聯的資訊
- session的資訊是存放在服務器端的,cookie的資訊是存放在瀏覽器端
- session中可以存放Object,cookie只能存放字串資訊
過濾器
是什么過濾器?
- Filter過濾器是JavaWeb的三大組件之一;
- 過濾器實際上就是對web資源進行攔截,做一些處理后再交給下一個過濾器或servlet處理,通常都是用來攔截request進行處理的,也可以對回傳的response進行攔截處理;
- 它的作用:攔截請求,過濾回應;
- 攔截請求的常見應用場景:權限檢查、日記操作、事務管理...

創建一個Filter過濾器
- 權限設定,沒有登錄的不能直接訪問web工程下的HTML目錄下的所有資源
首先一個登陸頁面
- 提交到LoginServlet程式
<form action="http://localhost:8080/JavaWeb_4/loginservlet" method="get">
用戶名:<input type="text" name="username"/><br/>
密 碼:<input type="password" name="password"/><br/>
<input type="submit"/>
</form>
LoginServlet程式
@WebServlet(name = "LoginServlet",urlPatterns = "/loginservlet")
public class LoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//處理回應亂碼
response.setContentType("text/jsp;charset=UTF-8");
//獲取輸入的用戶名以及密碼
String username = request.getParameter("username");
String password = request.getParameter("password");
//先給定一個值
if ("abcdef".equals(username) && "123456".equals(password)){
//如果用戶名密碼正確,將用戶名保存在Session域中
request.getSession().setAttribute("username",username);
response.getWriter().write("登陸成功!!!");
}else {
request.getRequestDispatcher("/index.jsp").forward(request,response);
}
}
}
登陸成功之后將用戶名放入到Session域中
創建Filter過濾器
public class Filter1 implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//通過ServletRequest請轉獲取到HttpServletRequest請求
HttpServletRequest request = (HttpServletRequest) req;
//通過request請求再獲取Session域
HttpSession session = request.getSession();
//查詢Session與中是否有用戶名資訊,有說明已經登錄,可訪問HTML下的
Object username = session.getAttribute("username");
//為null,就說明沒有登錄
if (username == null) {
//沒有登錄就重定向到登錄頁面
req.getRequestDispatcher("/index.jsp").forward(req, resp);
} else {
//登錄的話,就放行,該請求哪里就讓他到哪里
chain.doFilter(req, resp);
}
}
}
當Session域中沒有用戶名的時候(用戶沒有登錄),放強行訪問HTML下的資源時,就會被過濾器重定向到登錄頁面,只有當Session域中存在用戶名時,才會被過濾器放行允許其訪問HTML下的資源
Filter過濾器的web配置
<!--filter 標簽用于配置一個Filter 過濾器-->
<filter>
<!--給filter起一個別名-->
<filter-name>Filter1</filter-name>
<!--配置filter的全類名-->
<filter-class>com.mlyr.filter.Filter1</filter-class>
</filter>
<!--filter過濾器攔截的路徑-->
<filter-mapping>
<!--給那個filter過濾器使用-->
<filter-name>Filter1</filter-name>
<!--url-pattern:配置filter的攔截路徑
/ 表示http://ip:port/工程路徑/ 映射到web目錄
/HTML/*</ 表示攔截http://ip:port/工程路徑/HTML/目錄下的所有檔案及目錄
-->
<url-pattern>/HTML/*</url-pattern>
</filter-mapping>
Filter的生命周期
public class Filter2 implements Filter {
//構造方法
public Filter2() {}
@Override//init()初始化方法
public void init(FilterConfig filterConfig) throws ServletException {}
@Override//doFilter()過濾方法
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {}
@Override//destroy()銷毀方法
public void destroy() {}
}
構造方法與init()初始化方法在web工程啟動的時候執行
doFilter()過濾方法在每次攔截到請求時執行
destroy()銷毀方法在停止web工程的時候執行
FilterConfig類
- 它是Filter過濾器的組態檔類
- 當web工程創建Filter過濾器時,同時會創建一個FilterConfig類
- 它的作用:獲取Filter過濾器的配置內容
- 獲取Filter的名稱,也就是filter-name標簽中的內容
- 獲取Filter中配置的init-param初始化的內容
- 獲取ServletContext物件
public void init(FilterConfig config) throws ServletException {
//獲取Filter過濾器名字
System.out.println(config.getFilterName());//Filter3
//獲取init初始化內容
System.out.println(config.getInitParameter("name"));//張三
//獲取ServletContext物件
ServletContext servletContext = config.getServletContext();
}
<filter>
<filter-name>Filter3</filter-name>
<filter-class>com.mlyr.filter.Filter3</filter-class>
<init-param>
<param-name>name</param-name>
<param-value>張三</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Filter3</filter-name>
<url-pattern>/</url-pattern>
</filter-mapping>
FilterChain過濾鏈
- 如果有多個過濾器,它就形成了一個FilterChain過濾器鏈
- 那個Filter先執行與Filter的配置相關,在web.xml組態檔中,那個配置在最前方,那個就先執行
- 第一個執行到doFilter時,會進行判斷,如果有下一個Filter,就去執行下個Filter;沒有的話,就直接執行資源檔案,然后回傳Filter執行doFilter后面的代碼
- 所有的Filter和目標資源默認在同一個執行緒中;多個Filter執行的時候,他們使用同一個Request物件

Filter的攔截路徑分類
精確匹配
- 只會攔截HTML下的a.html的請求
<url-pattern>/HTML/a.html</url-pattern>
目錄匹配
- 只會攔截HTML下的所有請求
<url-pattern>/HTML/*</url-pattern>
后綴名匹配
- 只會攔截以.html結尾的請求
<url-pattern>*.html</url-pattern>
不經風雨,怎見彩虹?Filter過濾器只關心請求的地址是否匹配,不關心請求的資源是否存在
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/545186.html
標籤:其他
