1. http協議
1. 什么是協議:雙方再交互通信時候,遵守的一種規范,規則
http協議:針對網絡上的客戶端和服務器端在執行http請求時遵守的一種規范,其實就是規定了客戶端在訪問服務器端和服務器返回數據時,需要帶上什么東西。
2. http協議版本:
1.0版本:請求數據,服務器返回后,回斷開連接
通用1.1版本:請求數據,服務器返回后,連接會繼續保持,除非服務器和客戶端關閉。有一定的時間限制,如果一直空着連接,會自動關閉。
在地址欄中鍵入網絡地址,或者注冊按鈕,瀏覽器會顯示一些內容,瀏覽器和服務器如何通訊呢。
使用瀏覽器打開http://localhost:8082/examples/servlets/servlet/RequestParamExample
3. http請求數據解析
a. 請求行:
POST:請求的方式
/examples/servlets/servlet/RequestParamExample 請求的URL地址
HTTP/1.1:協議的版本
b. 請求頭:
Host: localhost:8082
Connection: keep-alive
Content-Length: 28
Cache-Control: max-age=0
Origin: http://localhost:8082
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://localhost:8082/examples/servlets/servlet/RequestParamExample
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: pgv_pvi=2747698176; Phpstorm-eb09a0a4=f84c3339-7383-49af-a83f-1fababd2ac0d
Accept:客戶端告訴服務端能支持什么類型的數據
Referer:真正請求的全地址路徑
Accept-language:支持的語言格式
User-Agent:向服務器表名,當前來訪的客戶端信息
Content-Type:提交的數據類型,經過urlencoding編碼的form表單數據
Accept-Encoding:gzip,deflate:壓縮算法
Content-Length:數據長度
Connection:Keep-Alilve 保持連接
Cache-Control:對緩沖的操作
c. 請求體:
firstname=wang&lastname=jing
瀏覽器真正發送給服務器的數據
發送的數據時key=value的格式,如果存在多個數據,那么使用&
http響應數據解析
響應的數據里面包含三部分的內容:響應行,響應頭,響應體
HTTP/1.1 200
Content-Type: text/html;charset=UTF-8
Content-Length: 711
Date: Wed, 17 Oct 2018 07:07:10 GMT
響應行:HTTP/1.1 200 協議版本,狀態碼
200:成功,正常處理,得到數據
403:forbidden:拒絕
404:Not Found
500:服務器異常
響應頭
Content-Type:服務器返回給客戶端的內容類型
Content-Lenght:返回的數據的長度
Date:響應的時間
4. Post和Get請求的數據的區別
http://localhost:8082/examples/servlets/servlet/RequestParamExample?firstname=wang&lastname=jing可以得到Get請求
Get: GET /examples/servlets/servlet/RequestParamExample?firstname=wang&lastname=jing HTTP/1.1 Host: localhost:8082 Connection: keep-alive Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Cookie: pgv_pvi=2747698176; Phpstorm-eb09a0a4=f84c3339-7383-49af-a83f-1fababd2ac0d Post: POST /examples/servlets/servlet/RequestParamExample HTTP/1.1 Host: localhost:8082 Connection: keep-alive Content-Length: 28 Cache-Control: max-age=0 Origin: http://localhost:8082 Upgrade-Insecure-Requests: 1 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Referer: http://localhost:8082/examples/servlets/servlet/RequestParamExample Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Cookie: pgv_pvi=2747698176; Phpstorm-eb09a0a4=f84c3339-7383-49af-a83f-1fababd2ac0d
a. 請求的地址不同
b. 帶的數據不同
Post采用流的方式攜帶數據
5. Web資源
在http協議當中,規定了請求和響應雙方,客戶端和服務器端,與web相關的資源有兩類:
靜態資源:html,js,css
動態資源:servlet/jsp
2. Servlet
servlet:一個java程序,運行在web服務器上面,用於接收和響應,客戶端的http請求
更多的是配合動態資源來做,當然靜態資源也需要使用Servlet,不過是Tomcat里面已經定義好了一個DefaultServlet
1. 定義一個Hello Servlet工程
a. 新建一個工程,配置服務器
b. 測試運行Web工程
新建一個類,實現Servlet接口
配置Servlet:告訴服務器,我們的應用有這些Servlet,配置文件webContent/WEB-INF/web.xml
<!-- 向tomcat報告,這個應用中有此servlet,名稱為HelloServlet,全路徑 /HelloServlet/src/--> <servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>day_01.HelloServlet</servlet-class> </servlet> <!-- 注冊servlet的映射,servletName:找到上面注冊的具體的servlet,url-pattern:地址欄中的路徑 --> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
使用http://localhost:8082/HelloServlet/hello訪問該java類
執行過程:
1. 找到tomcat應用
2. 找到項目
3. 找web.xml,然后在里面找到url-pattern,有沒有哪一個pattern的內容是hello
4. 找到servlet-mapping中的哪個servlet-name
5. 找到上面定義的Servlet元素中的servlet-name中的HelloServlet
6. 找到下面定義的Servlet-class然后開始創建該類的實例
7. 繼而執行該Servlet的service方法
2. Servlet的通用寫法
servlet(接口)------>GenericServlet-------->HttpServlet(用於處理Http的請求)
定義一個類,繼承HttpServlet復寫doGet和doPost
public class HelloServlet02 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("get..."); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("post"); } }
3. Servlet的生命周期
生命周期:從創建到銷毀的時間
生命周期方法:從創建到銷毀,所調用的方法
public class HelloServlet03 implements Servlet { // 創建servlet實例時,調用該方法,初次使用servlet,創建實例,init()方法只能執行一次 @Override public void init(ServletConfig config) throws ServletException { System.out.println("HelloServlet03...init..."); } // 客戶端來一個請求,執行一次該方法 @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { System.out.println("HelloServlet03...service..."); } // 該項目從tomcat里面移除,正常關閉服務器,shutdown.bat @Override public void destroy() { System.out.println("HelloServlet03...destroy..."); } @Override public ServletConfig getServletConfig() { // TODO Auto-generated method stub return null; } @Override public String getServletInfo() { // TODO Auto-generated method stub return null; } }
4. 讓servlet創建實例的時機提前
a. 默認情況下,只有在初次訪問servlet時候,才會執行init方法,有時候,可能需要在這個方法中執行一些初始化工作,甚至時做一些比較耗時的邏輯
b. 這個時候,初次訪問,可能會在Init方法中逗留太久的時間,那么有沒有辦法讓時間提前一些呢。
<servlet> <servlet-name>HelloServlet04</servlet-name> <servlet-class>day_01.HelloServlet04</servlet-class> <load-on-startup>2</load-on-startup> //值越小越提前執行 </servlet>
服務器重啟或者部署項目時就會執行
c. 配置時候,使用load-on-startup來執行,給的數字越小,啟動的時機越早,一般不寫負數,從2開始即可
5. servletConfig
servletConfig使用方法
package day_01; import java.io.IOException; import java.util.Enumeration; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class HelloServletConfig extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // ServletConfig:可以獲得servlet在配置時的一些信息 ServletConfig config = getServletConfig(); // 獲取配置servlet里面servlet-name的文本內容 String servletName = config.getServletName(); System.out.println("servletname:" + servletName); // 獲取配置時具體的參數 String initParameter = config.getInitParameter("address"); System.out.println("initparameter:" + initParameter); System.out.println("-----------"); // 獲取所有的名稱 Enumeration<String> names = config.getInitParameterNames(); while (names.hasMoreElements()){ String name = (String)names.nextElement(); String initpara = config.getInitParameter(name); System.out.println(name + ":" + initpara); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } } <servlet> <servlet-name>HelloServletConfig</servlet-name> <servlet-class>day_01.HelloServletConfig</servlet-class> <!-- 可以添加初始化參數 --> <init-param> <param-name>name</param-name> <param-value>Feng_Ying</param-value> </init-param> <init-param> <param-name>age</param-name> <param-value>20</param-value> </init-param> <init-param> <param-name>address</param-name> <param-value>Beijing_University</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>HelloServletConfig</servlet-name> <url-pattern>/hello5</url-pattern> </servlet-mapping>
1. 未來我們開發了一些應用,使用到了一些技術,或者一些代碼,但是我們不會,但是有人寫出來了,它的代碼放置在servlet類里面
2. 剛好這個servlet里面有一個數字或者變量,但是不是固定的,所以要求使用到servlet時,注冊servlet時候,必須要在web.xml,聲明init-params
servlet的配置方式
1. 全路徑匹配:/a/b
2. 路徑匹配:以/開始,但是以*結束,/a/*,/*是任意匹配,*是一個通配符
3. 以擴展名匹配,沒有/:*.擴展名,*的內容可以是任意的
6. ServletContext
Servlet上下文:每個web工程都只有一個ServletContext對象,不管在那個servlet里面,獲取到的這個類的對象都是同一個
1. 可以獲取全局配置參數
<!-- 可以配置全局的參數 --> <context-param> <param-name>address</param-name> <param-value>深圳東莞</param-value> </context-param> <servlet> <servlet-name>ServletContextDemo</servlet-name> <servlet-class>day_01.ServletContextDemo</servlet-class> </servlet>
所有的servlet對象都可以用全局變量
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 獲取ServletContext對象
ServletContext context = getServletContext(); String address = context.getInitParameter("address"); System.out.println("address:" + address); }
2. 可以獲取web應用中的資源
package day_01; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Properties; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServletContextDemo2 extends HttpServlet{ private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Properties prop = new Properties(); // InputStream is = ServletContextDemo2.class.getClassLoader().getResourceAsStream("config.properties"); ServletContext context = getServletContext(); // 獲取給定文件在服務器上的絕對路徑 String path = context.getRealPath("/CONFIG/config.properties"); System.out.println(path); InputStream is = new FileInputStream(path); prop.load(is); String address = prop.getProperty("address"); System.out.println("address:" + address); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
輸出:
D:\Wang_File\myeclipse_workspace\.metadata\.me_tcat85\webapps\HelloServlet\CONFIG\config.properties
address:shengzhengdongguan
另一種更加簡潔的方法
private void method_other(){ try { Properties prop = new Properties(); // InputStream is = ServletContextDemo2.class.getClassLoader().getResourceAsStream("config.properties"); ServletContext context = getServletContext(); // 獲取給定文件在服務器上的絕對路徑,獲取web工程下的資源,轉換成流對象 InputStream is = context.getResourceAsStream("CONFIG/config.properties"); prop.load(is); String address = prop.getProperty("address"); System.out.println("address:" + address); } catch (Exception e) { e.printStackTrace(); } }
第三種方法:通過classLoader獲取資源文件:默認的getClassLoader()路徑:D:\Wang_File\myeclipse_workspace\.metadata\.me_tcat85\webapps\HelloServlet\WEB-INF\classes
目標目錄:D:\Wang_File\myeclipse_workspace\.metadata\.me_tcat85\webapps\HelloServlet\CONFIG
private void method_another(){ try { Properties prop = new Properties(); InputStream is = this.getClass().getClassLoader().getResourceAsStream("../../CONFIG/config.properties"); // 獲取給定文件在服務器上的絕對路徑 prop.load(is); String address = prop.getProperty("address"); System.out.println("address:" + address); } catch (Exception e) { e.printStackTrace(); } }
3. 存取數據:servlet間共享數據,域對象
a. 定義一個登陸的html頁面,定義一個form表單
b. 定義一個Servlet,名為LoginServlet
c. 針對成功和失敗,跳轉到不同的頁面
package com.wang.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class LoginServlet */ @WebServlet("/LoginServlet") // localhost/HelloServlet/LoginServlet public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 設置請求體里面的編碼,這句話對於post沒有作用,應為get數據在url上面 request.setCharacterEncoding("UTF-8"); String username = request.getParameter("username"); // 本處不需要解碼,應該是版本比較高tomcat-8.5 // 常用的解碼形式:username = new String(username.getBytes("ISO-8859", "UTF-8")) String password = request.getParameter("password"); System.out.println("username:" + username + ",password:" + password); PrintWriter pw = response.getWriter(); if("風影".equals(username) && "wang".equals(password)){ Object obj = getServletContext().getAttribute("count");; int totalCount = 0; if(obj != null){ totalCount = (int)obj; } getServletContext().setAttribute("count", totalCount + 1); System.out.println("登陸成功的次數:" + (totalCount + 1)); // 用戶名密碼校驗成功登陸 設置狀態碼,重新定位 response.setStatus(302); // 定位跳轉的位置是哪一個頁面 response.setHeader("Location", "success.html"); }else{ pw.write("login fail..."); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
package com.wang.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class CountServlet */ @WebServlet("/CountServlet") public class CountServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int count = (int)getServletContext().getAttribute("count"); response.getWriter().write("當前網站成功登陸:" + count + "次"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
<!DOCTYPE html> <!-- -http://localhost:8082/HelloServlet/login.html --> <html> <head> <meta charset="UTF-8"> <title>Login</title> </head> <body> <h2>請輸入以下的內容,完成登陸</h2> <form action = "LoginServlet" method = "post"> 賬號:<input type="text" name="username" /><br> 密碼:<input type="text" name="password" /><br> <input type="submit" value="登陸" /> </form> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>success</title> </head> <body> Login successful... <br/> <a href = "CountServlet">網站登陸成功的次數</a> </body> </html>
ServletContext何時創建,何時銷毀
服務器啟動的時候,會為每個web應用程序,創建一個ServletContext,當服務器關閉或者從服務器移除托管,會銷毀
ServletContext的作用范圍:本項目中都可以使用
7. HttpServletRequest
這個對象封裝了客戶端提交過來的所有信息
1. 可以獲取客戶端請求的頭信息
Enumeration<String> headerNames = request.getHeaderNames(); while(headerNames.hasMoreElements()){ String name = (String)headerNames.nextElement(); String value = request.getHeader(name); System.out.println(name + ":" + value); } host:localhost:8082 connection:keep-alive upgrade-insecure-requests:1 user-agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36 accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 accept-encoding:gzip, deflate, br accept-language:zh-CN,zh;q=0.9 cookie:pgv_pvi=2747698176; Phpstorm-eb09a0a4=f84c3339-7383-49af-a83f-1fababd2ac0d
2. 獲取客戶端提交過來的數據
// 獲取客戶端提交的數據 或者Enumeration<String> parameterNames = // request.getParameterNames(); String name = request.getParameter("name"); System.out.println("name:" + name); // 獲取所有的數據,一個Key可以對應多個數據 Map<String, String[]> map = request.getParameterMap(); Set<String> keySet = map.keySet(); Iterator<String> iterator = keySet.iterator(); while (iterator.hasNext()) { String key = iterator.next(); String[] value = map.get(key); System.out.println("key:" + key + ",value:" + Arrays.deepToString(value)); } name:wangjing key:name,value:[wangjing, hage]
3. 讀取中文數據
Myeclipse get讀取的中文不存在中文亂碼問題,應該是使用的tomcat-8.5版本比較高:
如果存在,get方式獲取數據存在兩種解決方法
1. 代碼轉碼
String username = request.getParameter("username"); // 常用的解碼形式:get請求過來的數據,在url地址欄經過編碼了,所以取到的數據是亂碼,tomacat收到這批數據,getParameter,默認使用IOS-8859-1去解碼 username = new String(username.getBytes("ISO-8859", "UTF-8")) String password = request.getParameter("password"); System.out.println("username:" + username + ",password:" + password);
2. 在tomcat里面conf/server.xml加上URIEncoding="UTF-8"
<connector connectionTimeout="2000" prot = "8082" protocol = "HTTP/1.1" redirectPort="8445" URIEncoding="UTF-8" />
但是post請求會出現亂碼問題,怎么解決呢
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8");// 設置請求體里面的編碼,這句話對於get沒有作用,應為get數據在url上面 String username = request.getParameter("username"); // 本處不需要解碼,應該是版本比較高tomcat-8.5 // 常用的解碼形式:username = new String(username.getBytes("ISO-8859", "UTF-8")) String password = request.getParameter("password"); System.out.println("username:" + username + ",password:" + password); PrintWriter pw = response.getWriter(); if("風影".equals(username) && "wang".equals(password)){ Object obj = getServletContext().getAttribute("count");; int totalCount = 0; if(obj != null){ totalCount = (int)obj; } getServletContext().setAttribute("count", totalCount + 1); System.out.println("登陸成功的次數:" + (totalCount + 1)); // 用戶名密碼校驗成功登陸 設置狀態碼,重新定位 response.setStatus(302); // 定位跳轉的位置是哪一個頁面 response.setHeader("Location", "success.html"); }else{ pw.write("login fail..."); } }
8. HttpServletResponse
負責返回數據給客戶端,輸出數據到頁面上
// 以字符串方式寫數據,文字信息 // response.getWriter().write("hello response"); // 以字節流的方式寫數據,文字信息,文件信息 response.getOutputStream().write("Hello Response".getBytes());
響應的數據中有可能出現亂碼package com.wang.servlet;import java.io.IOException;import java.nio.charset.Chars
import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class ResponseDemo1 */ @WebServlet("/ResponseDemo1") public class ResponseDemo1 extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 字符流輸出 // response.getWriter().write("hello response"); // 2. 字節流輸出 // response.getOutputStream().write("Hello Response".getBytes()); // 設置響應頭 // response.setHeader(name, value); // 設置狀態碼 // response.setStatus(""); // // response.setContentType(type); // CharacterOutput(response); ByteOutput(response); } private void CharacterOutput(HttpServletResponse response) throws IOException { /* * 中文亂碼問題 */ // 字符流方法 // 1. 設置編碼時使用utf-8編碼 response.setCharacterEncoding("UTF-8"); // 2. 指定瀏覽器查看這份數據使用的碼表 response.setHeader("Content-Type", "text/html;charset=UTF-8"); response.getWriter().write("我愛java"); } private void ByteOutput(HttpServletResponse response) throws IOException { /* * 中文亂碼問題 */ // 字節流方法// 1. 指定瀏覽器查看這份數據使用的碼表,以后不管是字節流還是字符流,寫如下一句即可 response.setContentType("text/html;charset=UTF-8");
// response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Type", "text/html;charset=UTF-8"); 同上 // 2. 指定輸出的中文使用的碼表 response.getOutputStream().write("我愛java".getBytes()); // 默認是utf-8 // String csn = Charset.defaultCharset().name(); UTF-8 } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
9. Tomcat下載資源
1. 直接以超鏈接形式,不寫任何代碼,也可以下載文件
<body>
讓tomcat的默認servlet提供下載功能<br />
<a href = "download/aa.jpg">aa.jpg</a><br />
<a href = "download/bb.txt">bb.jpg</a><br />
<a href = "download/cc.rar">cc.jpg</a><br />
</body>
原因時tomcat里面有一個默認的servlet,DefaultServlet,這個DefaultServlet專門用於處理放在tomcat服務器上面的靜態資源
2. 采用自定義tomcat方式
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>index</title> </head> <body> 讓tomcat的默認servlet提供下載功能<br /> <a href = "download/aa.jpg">aa.jpg</a><br /> <a href = "download/bb.txt">bb.txt</a><br /> <a href = "download/cc.rar">cc.rar</a><br /> 手動編碼提供下載功能:<br> <a href = "DownloadServlet?filename=aa.jpg">aa.jpg</a><br /> <a href = "DownloadServlet?filename=bb.txt">bb.txt</a><br /> <a href = "DownloadServlet?filename=cc.rar">cc.rar</a><br /> </body> </html>
package com.wang.servlet; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/DownloadServlet") public class DownloadServlet extends HttpServlet { private static final long serialVersionUID = 1L; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 獲取下載文件的名字 String fileName = request.getParameter("filename"); // 2. 獲取這個文件在tomcat里面的絕對路徑地址 String path = getServletContext().getRealPath("download/" + fileName); // 3. 設置瀏覽器收到這種資源,采用下載的方式打開 response.setHeader("Content-Disposition", "attachment; filename ="+fileName); // 4. 轉換成輸入流 InputStream is = new FileInputStream(path); OutputStream os = response.getOutputStream(); // 5. 流轉換 int len = 0; byte[] buffer = new byte[1024]; while((len = is.read(buffer)) != -1){ os.write(buffer, 0, len); } os.close(); is.close(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
下載過程中出現的中文文件名亂碼問題解決方案:
package com.wang.servlet; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URLEncoder; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/DownloadServlet") public class DownloadServlet extends HttpServlet { private static final long serialVersionUID = 1L; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 獲取下載文件的名字 String fileName = request.getParameter("filename"); // 2. 獲取這個文件在tomcat里面的絕對路徑地址 String path = getServletContext().getRealPath("download/" + fileName); /* * filename = new String(fileName.getBytes("ISO-8859-1"),"UTF-8"); */ // 3. 如果文件的名字帶有中文,那么需要對這個文件進行編碼處理,如果是IE,Chrome使用URLEncoding編碼 // 如果是Firefox,使用Base64編碼 String clientType = request.getHeader("User-Agent"); if(clientType.contains("Firefox")){ fileName = DownloadUtil.base64EncodeFileName(fileName); }else{ fileName = URLEncoder.encode(fileName, "UTF-8"); } // 4. 設置瀏覽器收到這種資源,采用下載的方式打開 response.setHeader("Content-Disposition", "attachment; filename ="+fileName); // 5. 轉換成輸入流 InputStream is = new FileInputStream(path); OutputStream os = response.getOutputStream(); // 6. 流轉換 int len = 0; byte[] buffer = new byte[1024]; while((len = is.read(buffer)) != -1){ os.write(buffer, 0, len); } os.close(); is.close(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } package com.wang.servlet; import java.io.UnsupportedEncodingException; import sun.misc.BASE64Encoder; public class DownloadUtil { public static String base64EncodeFileName(String fileName) { BASE64Encoder base64Encoder = new BASE64Encoder(); try { return "=?UTF-8?B?" + new String(base64Encoder.encode(fileName .getBytes("UTF-8"))) + "?="; } catch (UnsupportedEncodingException e) { e.printStackTrace(); throw new RuntimeException(e); } } }
10. 請求轉發和重定向
重定向:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); String username = request.getParameter("username"); String password = request.getParameter("password"); if("admin".equals(username) && "admin".equals(password)){ /*response.setStatus(302); response.setHeader("Location", "success.html");*/ // 上面時以前的寫法,重定向寫法: response.sendRedirect("servlet/success.html"); }else{ /*response.setStatus(302); response.setHeader("Location", "fail.html");*/ } }
請求轉發
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); String username = request.getParameter("username"); String password = request.getParameter("password"); if("admin".equals(username) && "admin".equals(password)){ /*response.setStatus(302); response.setHeader("Location", "success.html");*/ // 上面時以前的寫法,重定向寫法: //response.sendRedirect("servlet/success.html"); // 請求轉發的寫法 request.getRequestDispatcher("servlet/success.html").forward(request, response); }else{ /*response.setStatus(302); response.setHeader("Location", "fail.html");*/ } }
請求轉發和重定向的不同點:
1. 重定向顯示的是最后的那個資源的路徑地址 http://localhost:8082/HelloServlet/servlet/success.html
請求的次數至少有兩次,服務器在第一次請求后,會返回302以及一個地址,瀏覽器會根據這個地址進行第二次訪問
可以跳轉到任意的路徑,不是自己的工程也可以
效率稍微低一點,需要執行兩次請求
后續的請求,沒法使用上一次request存儲的數據,或者,沒有辦法使用上一次的request對象,因為這是兩次不同的請求
2. 請求轉發顯示的是請求servlet的地址 http://localhost:8082/HelloServlet/Login?username=admin&password=admin
請求次數只有一次,因為服務器內部幫助客戶端執行了后續的工作
只能跳轉自己項目的項目路徑
效率稍微高一點,執行一次請求
可以使用上一次的request對象
11. Cookie
一份小數據,是服務器給客戶端,並且存儲在客戶端上的小數據
應用場景:自動登陸,瀏覽記錄,購物車
cookie出現的原因:
http的請求是無狀態的,客戶端與服務器通訊時候是無狀態的,客戶端在第二次訪問服務器時候,是根本不知道這個客戶端是以前來訪過的。為了更好的收集用戶習慣,更好的用戶體驗和交互。
cookie的簡單使用
1. 在響應的時候,添加cookie
2. 客戶端接收到信息的界面,響應頭多了一個字段set-cookie
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Cookie cookie = new Cookie("wangjing", "2015141452156"); response.setContentType("text/html;charset=UTF-8"); // 給響應添加一個cookie response.addCookie(cookie); response.getWriter().write("請求成功"); }
對於客戶端的一個網址,訪問一次后cookie便會記錄下來
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Cookie cookie = new Cookie("wangjing", "2015141452156"); response.setContentType("text/html;charset=UTF-8"); // 給響應添加一個cookie // response.addCookie(cookie); response.getWriter().write("請求成功"); // 獲取客戶端返回的cookie Cookie[] cookies = request.getCookies(); if(cookies != null){ for(Cookie c : cookies){ String cookieName = c.getName(); String cookieValue = c.getValue(); System.out.println("cookieName:" + cookieName + ",cookieValue:" + cookieValue); } } }
常用的方法:
案例1:顯示最近一次訪問的時間
1. 判斷賬號是否正確,如果正確,則獲取cookie,但是得到的cookie是一個數組,要從數組中找到我們想要的對象
2. 如果找到的對象為空,表明第一次登陸,需要添加cookie
3. 如果找到的對象不為空,表明不是第一次登陸,如果更新cookie
package com.wang.cookie; import java.io.IOException; import java.util.Date; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/LoginServlet_cookie") public class LoginServlet_cookie extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); String password = request.getParameter("password"); response.setContentType("text/html;charset=UTF-8"); if("admin".equals(username) && "admin".equals(password)){ Cookie[] cookies = request.getCookies(); Cookie cookie = CookieUtil.findCookie(cookies, "last"); if(cookie == null){ Cookie c = new Cookie("last", System.currentTimeMillis()+""); c.setMaxAge(60*60*3); response.addCookie(c); response.getWriter().write("歡迎您" + username); }else{ long lastVisitTime = Long.parseLong(cookie.getValue()); response.getWriter().write("歡迎您" + username + ",上次來訪時間:" + new Date(lastVisitTime)); cookie.setValue(System.currentTimeMillis() + ""); response.addCookie(cookie); } }else{ response.getWriter().write("登陸失敗"); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
package com.wang.cookie; import javax.servlet.http.Cookie; public class CookieUtil { public static Cookie findCookie(Cookie[] cookies, String name){ if(cookies != null){ for(Cookie cookie :cookies){ if(name.equals(cookie.getName())){ return cookie; } } } return null; } }
案例2:顯示商品的瀏覽記錄
jsp:java server pager 最終會翻譯成一個類,就是一個servlet
定義全局變量:<%! int a = 0; %>
定義局部變量:<% int b = 99; %>
在jsp頁面上,顯示a和b的值
<% =a %>
<% =b %>

<%@ page language = "java" contentType = "text/html;charset=UTF-8" pageEncoding="UTF-8" %> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>會員登錄</title> <link rel="stylesheet" href="css/bootstrap.min.css" type="text/css" /> <script src="js/jquery-1.11.3.min.js" type="text/javascript"></script> <script src="js/bootstrap.min.js" type="text/javascript"></script> <!-- 引入自定義css文件 style.css --> <link rel="stylesheet" href="css/style.css" type="text/css" /> <style> body { margin-top: 20px; margin: 0 auto; width: 100%; } .carousel-inner .item img { width: 100%; height: 300px; } </style> </head> <body> <!-- 時間:2015-12-30 描述:菜單欄 --> <div class="container-fluid"> <div class="col-md-4"> <img src="img/logo2.png" /> </div> <div class="col-md-5"> <img src="img/header.png" /> </div> <div class="col-md-3" style="padding-top:20px"> <ol class="list-inline"> <li><a href="login.htm">登錄</a></li> <li><a href="register.htm">注冊</a></li> <li><a href="cart.htm">購物車</a></li> </ol> </div> </div> <!-- 時間:2015-12-30 描述:導航條 --> <div class="container-fluid"> <nav class="navbar navbar-inverse"> <div class="container-fluid"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">首頁</a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li class="active"><a href="#">手機數碼<span class="sr-only">(current)</span></a></li> <li><a href="#">電腦辦公</a></li> <li><a href="#">電腦辦公</a></li> <li><a href="#">電腦辦公</a></li> </ul> <form class="navbar-form navbar-right" role="search"> <div class="form-group"> <input type="text" class="form-control" placeholder="Search"> </div> <button type="submit" class="btn btn-default">Submit</button> </form> </div> <!-- /.navbar-collapse --> </div> <!-- /.container-fluid --> </nav> </div> <div class="row" style="width:1210px;margin:0 auto;"> <div class="col-md-12"> <ol class="breadcrumb"> <li><a href="#">首頁</a></li> </ol> </div> <div class="col-md-2"> <a href="ProductInfoServlet?id=1"> <img src="products/1/cs10001.jpg" width="170" height="170" style="display: inline-block;"> </a> <p><a href="product_info.html" style='color:green'>冬瓜</a></p> <p><font color="#FF0000">商城價:¥299.00</font></p> </div> <div class="col-md-2"> <a href="ProductInfoServlet?id=2"> <img src="products/1/cs10002.jpg" width="170" height="170" style="display: inline-block;"> </a> <p><a href="product_info.html" style='color:green'>圓白菜</a></p> <p><font color="#FF0000">商城價:¥299.00</font></p> </div> <div class="col-md-2"> <a href="ProductInfoServlet?id=3"> <img src="products/1/cs10003.jpg" width="170" height="170" style="display: inline-block;"> </a> <p><a href="product_info.html" style='color:green'>甜玉米</a></p> <p><font color="#FF0000">商城價:¥299.00</font></p> </div> <div class="col-md-2"> <a href="ProductInfoServlet?id=4"> <img src="products/1/cs10004.jpg" width="170" height="170" style="display: inline-block;"> </a> <p><a href="product_info.html" style='color:green'>胡蘿卜</a></p> <p><font color="#FF0000">商城價:¥299.00</font></p> </div> <div class="col-md-2"> <a href="ProductInfoServlet?id=5"> <img src="products/1/cs10005.jpg" width="170" height="170" style="display: inline-block;"> </a> <p><a href="product_info.html" style='color:green'>芹菜</a></p> <p><font color="#FF0000">商城價:¥299.00</font></p> </div> <div class="col-md-2"> <a href="ProductInfoServlet?id=6"> <img src="products/1/cs10006.jpg" width="170" height="170" style="display: inline-block;"> </a> <p><a href="product_info.html" style='color:green'>韭菜</a></p> <p><font color="#FF0000">商城價:¥299.00</font></p> </div> <div class="col-md-2"> <a href="product_info.htm"> <img src="products/1/cs10007.jpg" width="170" height="170" style="display: inline-block;"> </a> <p><a href="product_info.html" style='color:green'>香菜</a></p> <p><font color="#FF0000">商城價:¥299.00</font></p> </div> <div class="col-md-2"> <a href="product_info.htm"> <img src="products/1/cs10008.jpg" width="170" height="170" style="display: inline-block;"> </a> <p><a href="product_info.html" style='color:green'>土豆</a></p> <p><font color="#FF0000">商城價:¥299.00</font></p> </div> <div class="col-md-2"> <a href="product_info.htm"> <img src="products/1/cs10007.jpg" width="170" height="170" style="display: inline-block;"> </a> <p><a href="product_info.html" style='color:green'>香菜</a></p> <p><font color="#FF0000">商城價:¥299.00</font></p> </div> <div class="col-md-2"> <a href="product_info.htm"> <img src="products/1/cs10008.jpg" width="170" height="170" style="display: inline-block;"> </a> <p><a href="product_info.html" style='color:green'>土豆</a></p> <p><font color="#FF0000">商城價:¥299.00</font></p> </div> <div class="col-md-2"> <a href="product_info.htm"> <img src="products/1/cs10007.jpg" width="170" height="170" style="display: inline-block;"> </a> <p><a href="product_info.html" style='color:green'>香菜</a></p> <p><font color="#FF0000">商城價:¥299.00</font></p> </div> <div class="col-md-2"> <a href="product_info.htm"> <img src="products/1/cs10008.jpg" width="170" height="170" style="display: inline-block;"> </a> <p><a href="product_info.html" style='color:green'>土豆</a></p> <p><font color="#FF0000">商城價:¥299.00</font></p> </div> </div> <!--分頁 --> <div style="width:380px;margin:0 auto;margin-top:50px;"> <ul class="pagination" style="text-align:center; margin-top:10px;"> <li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">«</span></a></li> <li class="active"><a href="#">1</a></li> <li><a href="#">2</a></li> <li><a href="#">3</a></li> <li><a href="#">4</a></li> <li><a href="#">5</a></li> <li><a href="#">6</a></li> <li><a href="#">7</a></li> <li><a href="#">8</a></li> <li><a href="#">9</a></li> <li> <a href="#" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li> </ul> </div> <!-- 分頁結束======================= --> <!-- 商品瀏覽記錄: --> <div style="width:1210px;margin:0 auto; padding: 0 9px;border: 1px solid #ddd;border-top: 2px solid #999;height: 246px;"> <h4 style="width: 50%;float: left;font: 14px/30px " 微軟雅黑 ";">瀏覽記錄</h4> <div style="width: 50%;float: right;text-align: right;"><a href="">more</a></div> <div style="clear: both;"></div> <div style="overflow: hidden;"> <ul style="list-style: none;"> <% Cookie[] cookies = request.getCookies(); Cookie cookie = com.itcast.servlet.CookieUtil.findCookie(cookies,"history"); if(cookie == null){ %> <h2>您還沒有任何的瀏覽記錄</h2> <% }else{ String[] ids = cookie.getValue().split("#"); for(String id : ids){ %> <li style="width: 150px;height: 216;float: left;margin: 0 8px 0 0;padding: 0 18px 15px;text-align: center;"><img src="products/1/cs1000<%=id %>.jpg" width="130px" height="130px" /></li> <% } } %> </ul> </div> <h2><a href = "ClearHistory">清除瀏覽記錄</a></h2> </div> <div style="margin-top:50px;"> <img src="./image/footer.jpg" width="100%" height="78" alt="我們的優勢" title="我們的優勢" /> </div> <div style="text-align: center;margin-top: 5px;"> <ul class="list-inline"> <li><a>關於我們</a></li> <li><a>聯系我們</a></li> <li><a>招賢納士</a></li> <li><a>法律聲明</a></li> <li><a>友情鏈接</a></li> <li><a target="_blank">支付方式</a></li> <li><a target="_blank">配送方式</a></li> <li><a>服務聲明</a></li> <li><a>廣告聲明</a></li> </ul> </div> <div style="text-align: center;margin-top: 5px;margin-bottom:20px;"> Copyright © 2005-2016 傳智商城 版權所有 </div> </body> </html>
@WebServlet("/ProductInfoServlet") public class ProductInfoServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 獲取到當前用戶准備瀏覽的商品ID String id = request.getParameter("id"); Cookie[] cookies = request.getCookies(); Cookie cookie = CookieUtil.findCookie(cookies, "history"); if (cookie == null) { Cookie c = new Cookie("history", id); // 設置有效期 c.setMaxAge(60 * 60 * 24 * 7); // 設置訪問這個工程的時候,才帶cookie過來 c.setPath("/Product_view"); response.addCookie(c); } else { // 獲取以前的cookie String ids = cookie.getValue(); // 讓現在瀏覽的商品和以前瀏覽的商品形成cookie新的值 cookie.setValue(id + "#" + ids); // 需要重新設置有效期 cookie.setMaxAge(60 * 60 * 24 * 7); // 設置訪問這個工程的時候,才帶cookie過來 cookie.setPath("/Product_view"); response.addCookie(cookie); } response.sendRedirect("product_info.htm"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
清除瀏覽記錄:其實就是清除cookie,刪除cookie沒有什么delete方法,只有設置maxage=0
@WebServlet("/ClearHistory") public class ClearHistory extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 清除cookie Cookie cookie = new Cookie("history", ""); cookie.setMaxAge(0); // 設置立即刪除 cookie.setPath("/Product_view"); response.addCookie(cookie); response.sendRedirect("product_list.jsp"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
cookie總結:
1. 服務器給客戶端發過來的一小份數據,並且存放在客戶端上面
2. 獲取cookie,添加cookie
request.getCookie();
response.addCookie();
3. Cookie分類
會話cookie:默認情況下,關閉瀏覽器,cookie就會消失
持久cookie:在一定的時間,都有效,並且保存在客戶端上面
cookie.setMasAge(100);
4. cookie的安全問題:
由於cookie保存在客戶端上,會有安全隱患
cookie的大小與客戶端有限制,一個web工程限制20個,總共限制300個,為了解決這個問題,出現了session
12 Session
session是基於Cookie的一種會話機制,cookie是數據存放在客戶端,session是數據存放在服務器端。
session何時創建,何時銷毀
創建:如果在servlet里面調用了request.getSession();
銷毀:存放在服務器內存中的一份數據,可以持久化,關閉了瀏覽器,session也不會銷毀
session會話時間過期,默認時間為30分鍾或者關閉服務器,session銷毀
// 得到會話的ID String id = session.getId(); // 存值 session.setAttribute("wang", "2015141452156"); // 取值 session.getAttribute("wang"); // 移除值 session.removeAttribute("wang");
@WebServlet("/LoginSession") public class LoginSession extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); String id = request.getSession().getId(); System.out.println("session id:" + id); response.getWriter().write("收到請求了"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }
案例:簡單的購物車
package com.itcast.session; import java.io.IOException; import java.util.LinkedHashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class CarServlet */ @WebServlet("/CarServlet") public class CarServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); // 1. 獲取要添加到購物車的商品id System.out.println(request.getParameter("id")); int id = Integer.parseInt(request.getParameter("id")); System.out.println(id); String[] names = {"Iphone", "小米", "華為", "錘子", "洛基亞"}; String name = names[id]; // 2. 獲取購物車存放東西的session Map<String, Integer> Map<String, Integer> map = (Map<String, Integer>) request.getSession().getAttribute("cart"); // session里面沒有任何東西 if(map == null){ map = new LinkedHashMap<String, Integer>(); request.getSession().setAttribute("cart", map); } // 3. 判斷購物車中有沒有這個商品 if(map.containsKey(name)){ map.put(name, map.get(name) + 1); }else{ map.put(name, 1); } // 4. 輸出界面,跳轉 response.getWriter().write("<a href = 'product_list.jsp'><h3>繼續購物</h3></a>"); response.getWriter().write("<a href = 'cart.jsp'><h3>去購物車結算</h3></a>"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
package com.itcast.session; import java.io.IOException; 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; /** * Servlet implementation class ClearCart */ @WebServlet("/ClearCart") public class ClearCart extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); // session.invalidate(); // 使此會話無效,直接使里面存放的所有數據消失 session.removeAttribute("cart"); response.sendRedirect("cart.jsp"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'cart.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <!-- 展示購物車的商品 --> <h2>您的購物車商品如下</h2> <% Map<String, Integer> map = (Map<String, Integer>)session.getAttribute("cart"); if(map != null){ for(String key : map.keySet()){ int value = map.get(key); %> <h3>名稱:<%=key %>, 數量:<%=value %></h3> <% } } %> <a href = "ClearCart"><h4>清空購物車</h4></a> </body> </html>

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'product_list.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <a href = "CarServlet?id=0"><h3>Iphone</h3></a> <a href = "CarServlet?id=1"><h3>小米</h3></a> <a href = "CarServlet?id=2"><h3>華為</h3></a> <a href = "CarServlet?id=3"><h3>錘子</h3></a> <a href = "CarServlet?id=4"><h3>洛基亞</h3></a> </body> </html>