一、JavaWeb概述
1. 什么是Javaweb
JavaWeb是指所有通過Java語言編寫,可以通過瀏覽器訪問的程序的總稱。
JavaWeb是基于請求和響應(yīng)來開發(fā)的。
請求:Request
響應(yīng):Response
客戶端(瀏覽器) 服務(wù)器(Tomcat等)
2. Web資源分類
- 靜態(tài)資源:HTML,CSS,JS,txt,mp4,jpg等等
- 動態(tài)資源:jsp頁面,servlet程序
3. 常用Web服務(wù)器
- Tomcat:提供對jsp和servlet的支持,是一種輕量級的JavaWeb容器
- Jboss
- GlassFish
- Resin
- WebLogic
4. Tomcat的使用
①Tomcat目錄中的webapps文件夾存放部署的Web工程
②啟動Tomcat,找到bin目錄下的startup.bat文件?;蛘吖芾韱T權(quán)限下的cmd,輸入startup。
③測試是否啟動成功,訪問本機(jī)真實(shí)地址或者(localhost:8080)
④停止Tomcat的方式:找到tomcat的bin目錄下的shutdown.bat按鈕
⑤如何修改Tomcat的端口號:
mysql默認(rèn)3306,Tomcat默認(rèn)8080
server.xml配置文件下的Connector標(biāo)簽,修改port屬性,修改完端口號之后要重啟Tomcat⑥HTTP協(xié)議默認(rèn)端口是80
部署Web工程到Tomcat服務(wù)器
Tomcat是一個服務(wù)器,供客戶端訪問Web工程。
- 直接把Web工程拷貝到Tomcat的webapps下如何訪問Web工程。先localhost:8080(這一步就相當(dāng)于切入到webapps文件夾下)然后再加上這里面某個html文件的路徑即可

IDEA整合Tomcat服務(wù)器
- 全局添加服務(wù)器
image-20200608100326929.png
- 單個工程添加服務(wù)器
Server&Deployment
- 配置工程輸出路徑
image-20200608100828701.png
- 解決服務(wù)器控制臺輸出亂碼
image-20200608100929905.png
二、Servlet
1. 什么是Servlet
- Servlet是JavaEE規(guī)范之一,規(guī)范就是接口
- Servlet是JavaWeb三大組件之一,三大組件分別是Servlet程序,F(xiàn)ilter過濾器,Listener監(jiān)聽器
- Servlet是運(yùn)行在服務(wù)器上的一個Java小程序,它可以接收客戶端發(fā)送過來的請求,并響應(yīng)客戶的請求。Tomcat等服務(wù)器相當(dāng)于容器,里面裝了許多Servlet。
2. 實(shí)現(xiàn)Servlet程序
編寫一個類去實(shí)現(xiàn)Servlet接口
實(shí)現(xiàn)service方法,處理請求并響應(yīng)請求得到數(shù)據(jù)(抽象類HttpServlet中service方法就包含了doGet,doPost,doDelete等等所有請求類型的方法)
到web.xml文件中去配置Servlet程序的訪問地址
<-- servlet標(biāo)簽:給Tomcat配置Servlet程序--> <servlet> <-- servlet-name標(biāo)簽:給servlet程序起一個別名(別名一般是該servlet實(shí)現(xiàn)類的類名)--> <servlet-name>MyServletImpl</servlet-name> <-- 上面那個servlet的全限定類名--> <servlet-class>com.zt.MyServletImpl</servlet-class> </servlet> <-- servlet-mapping標(biāo)簽:給servlet程序配置一個訪問地址--> <servlet-mapping> <-- 該處servlet-name標(biāo)簽作用是:告訴服務(wù)器,當(dāng)前mapping標(biāo)簽配置的地址給哪個servlet程序用 一般和上面那個一致,就表示該地址就給該servlet程序用--> <servlet-name>MyServletImpl</servlet-name> <-- url-pattern標(biāo)簽:用來配置訪問地址 /:"/"在服務(wù)器解析的時(shí)候,被解析為:http://ip:port/工程路徑/。其中工程路徑就是配置Tomcat時(shí)的Deployment中的context /hello:這表示http://ip:port/工程路徑/hello,即該servlet程序要去訪問這個地址,然后執(zhí)行service方法 --> <url-pattern>/hello</url-pattern> //在開發(fā)的時(shí)候一般遵守習(xí)慣:/xxx,xxx的內(nèi)容與類名有關(guān)聯(lián) </servlet-mapping>
3. Servlet生命周期
- 執(zhí)行Servlet構(gòu)造方法
- 執(zhí)行init()初始化方法
- 執(zhí)行service()方法,每次調(diào)用Servlet都會調(diào)用該方法
- 執(zhí)行destroy()方法
4. 通過繼承HttpServlet實(shí)現(xiàn)Servlet程序
一般實(shí)際開發(fā)項(xiàng)目中,都是使用繼承HttpServlet類(它實(shí)現(xiàn)了Servlet接口,它是個抽象類)去實(shí)現(xiàn)Servlet程序
①編寫一個類繼承HttpServlet
②根據(jù)業(yè)務(wù)需要重寫doGet()doPost()等方法
③到web.xml文件中配置Servlet程序的訪問地址
ServletConfig類
Servlet程序的配置類,它是某個servlet應(yīng)用程序的config,不是全局的config
作用:
(1)可以獲取Servlet程序的別名servlet-name
(2)獲取初始化參數(shù)init-param
(3)獲取ServletContext對象
ServletContext類
這是一個全局的對象,作用域?yàn)檎麄€Web工程,可以用它去做一些全局性的配置,也可以獲得全局的屬性
image-20200608105748297.png
ServletContex是一個接口,它表示Servlet上下文對象
一個Web工程只有一個ServletContext對象實(shí)例,相對于每個servlet程序而言
ServletContext對象是一個域?qū)ο?/p>
ServletContext在web工程部署的時(shí)候創(chuàng)建,在web工程停止的時(shí)候銷毀
存數(shù)據(jù) 取數(shù)據(jù) 刪除數(shù)據(jù) Map put get remove 域?qū)ο?/strong> setAttribute getAttribute removeAttribute
HttpServletRequest類(實(shí)現(xiàn)ServletRequest接口)
作用
每次只要有請求進(jìn)入Tomcat服務(wù)器,Tomcat服務(wù)器就會把請求過來的HTTP協(xié)議信息解析好封裝到HttpServletRequest對象中,然后傳遞到service方法(doGet,doPost)中給我們使用。我們可以通過HttpServletRequest對象,獲取到請求的所有信息HttpServletRequest常用API
String getContextPath():獲取Web工程相對路徑(Tomcat服務(wù)器中除去http://ip:port) System.out.println(req.getContextPath()); /Temp URI getRequestURI():獲取請求的資源路徑,相對路徑,某Web工程下的路徑 System.out.println(req.getRequestURI()); /Temp/hello URL getRequestURL():獲取請求的統(tǒng)一資源定位符(絕對路徑) System.out.println(req.getRequestURL()); http://localhost:8080/Temp/helloString getRemoteHost():獲取客戶端的ip地址 String getParameter():獲取請求的參數(shù) String getParameterValues():獲取請求的參數(shù)(多個值時(shí)) 可以用于獲取用戶輸入的值,如用戶名。 String getHeader():獲取請求頭 String getMethod():獲取請求的方式GET或POST setAttribute(key,value):設(shè)置域數(shù)據(jù) Object getAttribute(key):獲取域數(shù)據(jù) getRequestDispatcher("/+servlet名"):獲取下一個轉(zhuǎn)發(fā)對象。必須以斜杠開頭 RequestDispatcher rd = servletRequest.getRequestDispatcher("Two"); rd.forward(servletRequest,servletResponse); //獲取之后進(jìn)入到下一個servlet總 req.setCharacterEncoding("UTF-8")
HttpServletResponse類
每次請求進(jìn)來,Tomcat服務(wù)器都會創(chuàng)建一個Response對象傳遞給Servlet程序去使用,HttpServletResponse表示所有響應(yīng)的信息。如果需要設(shè)置返回給客戶端的信息,都可以通過HttpServletResponse對象來進(jìn)行設(shè)置
兩個輸出流
字節(jié)流:getOutputStream(),常用于下載(傳遞二進(jìn)制數(shù)據(jù))
字符流:getWriter(),常用于回傳字符串(常用)
resp.setContentType("text/html; charset=UTF-8"); //同時(shí)設(shè)置服務(wù)器和客戶端的字符集為UTF-8 PrintWriter writer = resp.getWriter(); writer.write("Hello World");
請求重定向
請求重定向是指,客戶端給服務(wù)器發(fā)送請求,然后服務(wù)器給客戶端一個新地址,客戶端轉(zhuǎn)發(fā)到新地址。
resp.sendRedirect("http://www.sina.com");注意
- 不能重定向到自己,否則瀏覽器會報(bào)錯
- 瀏覽器地址會發(fā)生變化,請求次數(shù)為兩次,而不是請求轉(zhuǎn)發(fā)的一次
- 兩個servlet程序不共享HttpServletRequest域中的數(shù)據(jù),因?yàn)槊總€HttpServletRequest只屬于一個Servlet
- 不能訪問WEB-INF下的內(nèi)容
- 可以訪問工程外的資源
三、HTTP協(xié)議
1. GET請求
- 請求的方式 GET
- 請求的資源路徑
- 請求的協(xié)議版本號 HTTP/1.1
- 請求頭 key:value 組成
2. POST請求
- 請求方式POST
- 請求資源路徑
- 請求的協(xié)議版本號 HTTP/1.1
- 請求頭 key:value
- 請求體:發(fā)送給服務(wù)器的數(shù)據(jù)
<常見的GET請求和POST請求>
GET請求:
①<form>標(biāo)簽,method=get
②<a>標(biāo)簽
③<link>標(biāo)簽引入css
④<Script>標(biāo)簽引入js文件
⑤<img>標(biāo)簽引入圖片
⑥<iframe>標(biāo)簽引入html頁面
⑦在瀏覽器地址欄中輸入地址后敲回車
POST請求:
<form>標(biāo)簽,method=post
3. 常用請求頭
- Accept:表示客戶端可以接收的數(shù)據(jù)類型
- Accpet_language:表示客戶端可以接收的語言類型
- User-Agent:表示客戶端瀏覽器的信息
- Host:表示請求時(shí)的服務(wù)器ip和端口號
4. 響應(yīng)的HTTP格式
- 響應(yīng)的協(xié)議和版本號
- 響應(yīng)狀態(tài)碼
- 響應(yīng)狀態(tài)描述符
- 響應(yīng)頭:key:value
- 響應(yīng)體 :回傳給客戶端的數(shù)據(jù)
5. 響應(yīng)碼
- 200:表示請求成功
- 302:表示請求重定向()
- 404:表示請求服務(wù)器已經(jīng)收到了,但是數(shù)據(jù)不存在(請求地址錯誤或數(shù)據(jù)不存在)
- 500:表示服務(wù)器已經(jīng)收到請求,但是服務(wù)器內(nèi)部錯誤(代碼錯誤)
6. MIME類型
- 格式:大類型/小類型如:
image/jpg video/mp4
四、監(jiān)聽器
- 作用:監(jiān)聽某種事物的變化,回調(diào)函數(shù),反饋給客戶做一些響應(yīng)的處理
- ServletContextListener監(jiān)聽器
五、文件上傳與下載
1. 上傳
- 導(dǎo)入依賴
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
- form表單設(shè)置
<form action="http://localhost:8080/day01_2_war_exploded/photo" method="post" enctype="multipart/form-data">
用戶名:<input type="text" name="username"><br/>
密碼:<input type="password" name="password"><br/>
頭像:<input type="file" name="image"><br/>
<input type="submit" value="上傳頭像">
</form>
- ServletFileUpload獲得文件對象
// 1、判斷上傳的數(shù)據(jù)是否是多段數(shù)據(jù),只有是多段數(shù)據(jù)才能解析
if(ServletFileUpload.isMultipartContent(req)){
// 2、創(chuàng)建fileItemFactory工廠實(shí)現(xiàn)類
FileItemFactory fileItemFactory = new DiskFileItemFactory();
// 3、創(chuàng)建用于解析上傳數(shù)據(jù)的工具類ServletFileUpload類
ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
// 4、解析數(shù)據(jù),得到每一個FileItem
try {
//解析request,得到文件項(xiàng)
List<FileItem> fileItems = servletFileUpload.parseRequest(req);
for (FileItem f : fileItems){
// 如果每個fileItem是普通表單項(xiàng)
if (f.isFormField()){
// 獲得表單項(xiàng)的name屬性值
System.out.println(f.getFieldName());
// 獲得表單項(xiàng)的value值
System.out.println(f.getString("UTF-8"));
}
// 否則上傳的是文件
else {
// 獲得表單中的各項(xiàng)input里的name屬性名稱以及他們的值
System.out.println(f.getFieldName());
// 獲得文件名,因?yàn)樯蟼鞯氖俏募?,則要獲取名稱不能用getFiledName
System.out.println(f.getName());
// 保存在服務(wù)器,參數(shù)為地址
f.write(new File("E:\\"+f.getName()));
}
}
} catch (FileUploadException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
2. 下載
- form表單
<form action="http://localhost:8080/day01_2_war_exploded/download" method="get">
用戶名:<input type="text" name="username"><br/>
密碼:<input type="password" name="password"><br/>
<input type="submit" value="下載文件">
</form>
- 客戶端
// 1、獲取要下載的文件名
String downloadFileName = "picture.png";
// 2、獲取讀取要下載的文件內(nèi)容的對象(ServletContext)
ServletContext sc = getServletContext();
// 獲取要下載的文件類型
String mimeType = sc.getMimeType("/download/" + downloadFileName);
// 在回傳數(shù)據(jù)之前,告訴客戶端要返回的數(shù)據(jù)類型
resp.setContentType(mimeType);
// 告訴客戶端收到的數(shù)據(jù)是用在直接使用(在瀏覽器打開)還是保存在本地
// Content-Disposition響應(yīng)頭,表示收到的數(shù)據(jù)怎么處理
// attachment:表示附件,表示下載使用 filename=表示指定下載的文件名
// 將文件名進(jìn)行url編碼,防止下載時(shí)客戶端出現(xiàn)中文亂碼
resp.setHeader("Content-Disposition","attachment; filename=" + URLEncoder.encode(downloadFileName,"UTF-8"));
// 獲取下載文件的輸入流
InputStream resource = sc.getResourceAsStream("/download/"+downloadFileName);
// 3、獲取響應(yīng)的輸出流,用于下載
OutputStream os = resp.getOutputStream();
// 4、讀取輸入流中全部的數(shù)據(jù),復(fù)制給輸出流,輸出給客戶端
IOUtils.copy(resource,os);
六、Cookie
1. 什么是Cookie
Cookie是服務(wù)器通知客戶端保存鍵值對的一種技術(shù),客戶端有了cookie后,每次請求都發(fā)送給服務(wù)器,每個cookie的大小不超過4kB。cookie如果要支持中文,必須對值進(jìn)行Base64編碼
2. 設(shè)置Cookie
創(chuàng)建
// 創(chuàng)建cookie對象
Cookie cookie1 = new Cookie("key1", "value1"); //cookie可以一次創(chuàng)建多個
// 通知客戶端保存cookie
resp.addCookie(cookie1);
Cookie cookie2 = new Cookie("key2", "value2"); //cookie可以一次創(chuàng)建多個
// 通知客戶端保存cookie
resp.addCookie(cookie2);
? 流程:
image-20200608121314714.png
獲取
Cookie[] cookies = req.getCookies();
for (Cookie c : cookies)
System.out.println(c.getName() + " " + c.getValue());
修改
//覆蓋cookie的value屬性,類似Map,key不變。
// 創(chuàng)建cookie對象
Cookie cookie1 = new Cookie("key1", "newValue1"); //cookie可以一次創(chuàng)建多個
// 通知客戶端保存cookie
resp.addCookie(cookie1);
存活時(shí)間
// 默認(rèn)為-1,負(fù)數(shù)表示瀏覽器一關(guān)閉(即一個session結(jié)束),cookie就刪除
cookie1.setMaxAge(-1);
// 0表示馬上刪除,都不需要等待瀏覽器關(guān)閉
cookie1.setMaxAge(0);
// 以秒為單位,設(shè)置1小時(shí)后刪除
cookie1.setMaxAge(60*60);
有效路徑
// 只有當(dāng)訪問的url是以下url時(shí),才會創(chuàng)建cookie
cookie1.setPath("url");
3. 練習(xí)
免用戶名登錄
<form action="login" method="get">
用戶名:<input type="text" name="username" value="${cookie.username.value}"/><br/> //將保存的cookie顯示到頁面上
密碼:<input type="password" name="password" value="${cookie.password.value}"/><br/>
<input type="submit" value="登錄">
</form>
resp.setContentType("text/html; Charset=UTF-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
if (username.equals("abcd")&&password.equals("1234")){
Cookie cookie = new Cookie(username,password);
cookie.setMaxAge(60*60);
resp.addCookie(cookie);
resp.getWriter().write("登錄成功");
}else {
resp.getWriter().write("登錄失敗");
}
七、Session
1. 什么是Session
- session是一個接口(HttpSession),它用來維護(hù)一個客戶端和服務(wù)器之間關(guān)聯(lián)的一種技術(shù)
- 每個客戶端都有自己的一個session會話
- session會話中,經(jīng)常用來保存用戶登錄之后的信息。(一個session就是客戶端與服務(wù)器之間的一次會話,關(guān)閉客戶端就結(jié)束一次會話)
- cookie是保存在客戶端,session保存在服務(wù)器端
2. 設(shè)置Session
創(chuàng)建和獲取
// 創(chuàng)建Session會話對象
HttpSession session = req.getSession();
// 判斷當(dāng)前Session是否是新創(chuàng)建的
System.out.println(session.isNew());
// 獲取Session的唯一標(biāo)識id
System.out.println(session.getId());
// 取得key1的值
session.getAttribute("key1");
超時(shí)時(shí)間
超時(shí)時(shí)間指的是客戶端兩次請求之間的最大間隔
// 設(shè)置當(dāng)前session的超時(shí)時(shí)間,以秒為單位,超過超時(shí)時(shí)間就銷毀
// 默認(rèn)的超時(shí)時(shí)間為:1800秒,因?yàn)門omcat服務(wù)器的默認(rèn)設(shè)置為30分鐘
session.setMaxInactiveInterval(60);
3. Session和Cookie的關(guān)系
session技術(shù),底層其實(shí)是基于cookie技術(shù)實(shí)現(xiàn)的
沒有cookie的時(shí)候,getSession()獲得一個session,把session的id給cookie的value。以后有了cookie,再getSession()時(shí)就獲得session的id與cookie的value值相同的session。

八、過濾器
1. 概述
- 用于攔截請求,過濾響應(yīng),攔截請求的常見應(yīng)用場景:權(quán)限檢查、日記操作、事務(wù)操作等
- 要求:在web工程下新建一個admin目錄,目錄下的所有資源必須是用于登錄之后才允許訪問
- 思路:用戶登錄后的信息保存在服務(wù)器的session域中,檢查session域中是否包含有用于登錄的信息即可
Filter的生命周期
- 構(gòu)造器方法
- init初始化方法
- doFilter過濾方法
- destroy銷毀方法
實(shí)現(xiàn)filter接口,運(yùn)行doFilter方法
HttpSession session = ((HttpServletRequest) request).getSession();
Object user = session.getAttribute("user");
if (user==null){
// 如果user=null,則權(quán)限檢查沒有通過,就轉(zhuǎn)到登錄頁面
request.getRequestDispatcher("/login.jsp").forward(request,response);
}else {
// 權(quán)限檢查通過,放行,讓客戶端訪問目標(biāo)資源
chain.doFilter(request,response);
}
Session域保存用戶數(shù)據(jù)
resp.setContentType("text/html; charset=UTF-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
if (username.equals("abcd")&&password.equals("1234")){
req.getSession().setAttribute("user",username);
System.out.println(username);
resp.getWriter().write("登錄成功");
}else {
req.getRequestDispatcher("/login.jsp").forward(req,resp);
}
web.xml配置過濾器
<!--filter標(biāo)簽配置一個filter過濾器-->
<filter>
<!--給filter起一個別名-->
<filter-name>MyFilter</filter-name>
<!--配置filter的全限定類名-->
<filter-class>com.zt.MyFilter</filter-class>
</filter>
<!--filter-mapping配置filter過濾器的攔截路徑-->
<filter-mapping>
<!--filter-name表示當(dāng)前的攔截路徑給哪個filter使用-->
<filter-name>MyFilter</filter-name>
<!--/斜杠表示當(dāng)前的請求地址為:http://ip:port/工程路徑/ 映射到idea的webapp目錄下
/admin/*表示攔截訪問路徑為admin目錄下的全部url-->
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
2. FilterConfig類
- 它是filter過濾器的配置文件類,Tomcat每次創(chuàng)建Filter的時(shí)候也會創(chuàng)建一個FilterConfig類的對象,包含了Filter配置文件的配置信息。作用是獲取filter過濾器的配置內(nèi)容
- 過濾鏈FilterChain
FilterChain.doFilter()方法的作用:
①如果有filter,執(zhí)行下一個Filter過濾器
②執(zhí)行目標(biāo)資源(沒有Filter過濾器)**多級Filter執(zhí)行順序
image-20200608125441552.png
3. Filter的攔截路徑
精確匹配
<url-pattern>/admin/demo1.jsp</url-pattern>目錄匹配
<url-pattern>/admin/*</url-pattern>后綴名匹配
<表示以.html結(jié)尾的都被攔截,這個后綴名不是說必須這種文件,而是所有字符串都可以,只要有這種字符串,都會被攔截 filter過濾器只關(guān)心請求的地址是否匹配,不關(guān)心請求的地址是否存在。> <url-pattern>*.html</url-pattern>





