■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■↓↓↓↓↓↓↓↓↓ Java程序文件上傳和下載↓↓↓↓↓↓↓↓↓↓↓■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
Java程序上傳和下載;
為什么要有?
如果是直接把數(shù)據(jù)輸出到瀏覽器,
那么部分的二進制文件則用戶沒法下載,
也會使得某些特殊的網站則無法運行下去,
因為有一些網絡提供資源下載是商業(yè)行為。
是什么?
是SUN公司制定的位于Java語言一套標準。
作用;
? ? 增加了對業(yè)務的處理的多樣性,和可控性。
特點;
? ? ?頁面必須要按照SUN公司的標準進行配置
◆◆◆◆◆◆注;在下載和上傳中要善于使用URLEncoder.encode("xxx","UTF-8");
這個URLEncoder類的靜態(tài)方法,用于轉換編碼集避免亂碼
-----------------------------------↓↓↓↓↓↓↓↓↓網絡傳輸?shù)奈募愋汀?------------------------------------------
網絡傳輸文件類型;
?在網絡傳輸中的文件類型是分為大類型和小類型的,
? 主要是為了便于標識某一些文件的子類型,
? ?因為在網絡傳輸文件的過程中,
? ?也可以必須這些文件的受到破壞。
?如;圖片文件,有GIF,jpg等后綴文件,
? 而如果這些文件的后綴都是img那么則會出現(xiàn)損壞,
? 而且這些文件的所顯示的功能和效果都是不一樣的,
? 但是這些文件都是屬于image類型的即是圖片類型。
?常用的文件類型;
?1.文本文件text/xxx ?---> text,HTML,JSP,CSS......
?2.圖片文件image/xxx ---> jpg,gif......
? ? ?◆◆◆◆◆注;可以在Tomcat ---> conf ---> web.xml 中查找到所需要的文件類型
---------------------------------------↓↓↓↓↓↓↓↓↓文件上傳條件↓↓↓↓↓↓↓↓↓↓↓---------------------------------------------
文件上傳;
?上傳一般都是使用開源的解析工具進行開發(fā),
? ? ? ? 因為如果是開發(fā)人員進行手動開發(fā)的話會使得效率低下,
? 而且業(yè)務的處理也不夠細致,如果是使用工具開發(fā),
? ? ? ? ? 那么可以使得效率提高而且在處理的方面,
? ? ? 可以使用開發(fā)人員不必考慮太多。
? ? ? ? ?工具;
? commons-fileupload-1.2.2.jar ?---> Apache ?主包
comons-io-2.1.jar?---> Apache ?輔助包
? ? ? ? ? ?條件;
? ? 1.必須要在后臺頁面提供form表單
? ? ? ? ······因為只有form表單都有提供文件上傳的功能和屬性
? ? 2.<input>標簽中的type屬性必須要是file
? ? ······因為form表單中的<input>標簽只有file屬性才可以讓使用將文件進行上傳
◆◆◆注;給這個<input type="file">標簽添加一個multiple屬性,
? ? ? ? ? ? 則可以讓用戶在進行文件上傳的時候可以一次選擇多個文件進行上傳
? ? 3.必須要是post提交
? ? ······因為Get提交的大小只有1KB而且Get提交不是提交內容(正文),只是提交文件名而已
? ? ? ? 4.需要把form表單中的···enctyle···屬性設置為···multipart/form-data···
? ? ······因為這個屬性是設置請求頭的contentType的值,而默認是application/www-form
只有設置稱為multipart/form-data才是請求正文類型才能接收數(shù)據(jù)
-------------------------------------↓↓↓↓↓↓↓↓↓文件上傳開發(fā)步驟↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
文件上傳開發(fā)步驟;
?1.定義頁面必須要按照上面↑↑↑↑↑↑↑的標準
?2.導入jar包
?3.創(chuàng)建硬盤文件項目工廠類,---> DiskFileItemFactory
? 定于文件緩存的位置和大小。
?4.創(chuàng)建Servlet上傳類對象,---> ServletFileUpload
? 傳入一個硬盤文件項目工廠類對象,
? 對上傳的文件進行緩存等操作。
? ?◆◆◆注;可以在Servlet上傳類的方法中設置緩存的大小和位置也可以
?5.通過Servlet上傳類對象的方法解析上傳的所有文件。
?6.使用文件工具類的方法直接將這個文件寫出到硬盤中。
? ?◆◆◆注;一般的文件是不存放在數(shù)據(jù)庫的[資源寶貴]。。。。。。。
--------------------------------------↓↓↓↓↓↓↓↓↓文件上傳開發(fā)過程↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
文件上傳開發(fā)過程;
?1.創(chuàng)建硬盤文件項目工廠類對象,設置緩存大小和緩存的位置
? ---> DiskFileItemFactory factory
= new DiskFileItemFactory(緩存(B)1024*1024,new File(緩存位置));
?2.創(chuàng)建Servlet文件上傳類對象,傳入一個DiskFileItemFactory對象,用于緩存上傳文件
---> ServletFileUpload upload =new ServletFileUpload(factory);
? 或 --->
upload.setItemFactory(factory); 通過這個方法
?3.調用ServletFileUpload類的方法獲取到上傳的所有文件,
? 傳入一個request對象,因為用戶與服務器進行交互都是通過請求類的。
---> List list =upload.parseRequest(request);
?4.遍歷這個List集合,而這些文件都按照Apache提供的,
? ·而ServletFileUpload這個類繼承的了一個抽象的頂層類FileUploadBase,
? ·而FileUploadBase這個抽象類的parseRequest(RequestContext ctx)方法
? ·將這個文件封裝為一個FileItem這個接口(標準)的對象,添加到集合中返回。
? ···從而才可以調用這個接口的方法對文件進行操作
? ···但是FileUploadBase這個抽象類沒有實現(xiàn)FileItem這個接口,只是在方法中調用進行封裝
---> for(FileItem fileItem :list){
? A.調用FileItem這個接口的方法獲取到這個文件名
String name = fileItem.getName();
? B.調用FileItem這接口的方法獲取到這個上傳的文件流
InputStream is =fileItem.getInputStream();
? C.使用io.jar包下的FileUtils這個工具類的方法直接將這個上傳的文件流寫出到硬盤中
? FileUtils.copyInputStreamToFile(is[流],new File(寫出路徑和文件名));
}
◆◆◆注意;在使用copyInputStreamToFile這個方法的時候記得寫出的時候是要加上文件名的
-----------------------------------↓↓↓↓↓↓↓↓↓文件上傳開發(fā)細節(jié)↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
文件上傳開發(fā)細節(jié);
1.創(chuàng)建一個DiskFileItemFactory對象,配置緩存,1M
? ---> DiskFileItemFactory factory
= new DiskFileItemFactory(1024*1024,new File("目錄"));
2.創(chuàng)建一個SerlvetFileUpload類對象,并且傳入一個配置好緩存的DiskFileItemFactory對象
---> ServletFileUpload upload =new ServletFileUpload(factory);
A.設置上傳的文件內容編碼集
upload.setHeaderEncoding("UTF-8");
B.限制上傳的每一個文件的大小,50M
upload.setFileSizeMax([B]50*1024*1024);
C.限制上傳的全部文件總大小,500M
upload.setSizeMax(1024*1024*500);
3.調用方法獲取到所有上傳的文件,傳入一個request對象,因為所有交互都是通過請求對象
---> List list =upload.parseRequest(request);
4.遍歷所有請求的上傳文件
for(FileItem fileItem : list){
//A.判斷是不是普通表單提交
if(fileItem.isFieldForm()){
//獲取到這個普通表單提交的name值
String name = fileItem.getFieldName();
//獲取到這個普通表單提交的value值
String value = fileItem.getString();
//獲取到這個普通表單提交的value值類型名
Object o =fileItem.getType().getSimpleName;
}
//獲取到文件名
String fileName = fileItem.getName();
//獲取到文件提交內容的類型
String type = fileItem.contentType();
//B.判斷文件類型是不是圖片,設置只接收圖片
if(!type.matches("image/[a-zA-Z]")){
System.out.println("只能是圖片");
}
//C.調用UUID生成一個唯一的系列號,避免文件名重復
String uuid = UUID.randomUUID().toString;
//D.獲取到上傳的文件流
InputStream is = fileItem.getInputStream();
//d.調用文件工具類的方法將這個文件寫出
FileUtils.copyInputStreamToFile(is,newFile(URLEncoder.encode("c:/" + uuid + fileName,"UTF-8")));
//E.刪除緩存的文件
fileItem.delete();
}
◆◆◆◆◆◆注意;在生成UUID和獲取到傳入的文件名的時候,
最好將文件名的所帶的···符號···去除,
和文件名長度最好不要···超過20,
避免出現(xiàn)瀏覽器···解析文件問題。
? 而且以上都是Apache提供的工具jar包中的,而不是JDK_API的
------------------------------------------↓↓↓↓↓↓↓↓↓文件下載↓↓↓↓↓↓↓↓↓↓↓-----------------------------------------------
文件下載;
一般頁面提供給用戶下載,一般都是有兩種方式。
一、直接下載 ?---> 如;直接使用<a>標簽嵌套<img>標簽
二、程序下載 ?---> 使用java代碼進行控制
-------------------------------------↓↓↓↓↓↓↓↓↓文件下載開發(fā)過程↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
文件下載開發(fā)過程;
1.獲取到源文件的路徑 --->
this.getServletContext.getRealPath("/x");獲取到一個相對路徑文件的一個絕對路徑
2.獲取到Servlet的輸出流---> response.getOutputStream();
3.獲取到源文件的輸入流---> FileInputStream
4.寫出到瀏覽器
5.關閉流
◆◆◆◆◆◆注;可以在寫出瀏覽器之前給響應頭添加content-disposition屬性,提升用戶的體驗
resposne.setHeader("content-disposition","attachment;filename="
+ URLEncoder.encode(源文件路徑,"UTF-8"));
----------------------------------------↓↓↓↓↓↓↓↓↓文件下載開發(fā)過程↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
文件下載開發(fā)過程;
?1.獲取到文件的路徑,? ?通過這個方法獲取到一個相對路徑文件的絕對路徑
? String path =
this.getServletContext().getRealPath("文件相對路徑");
?2.獲取到Servlet的輸出流,因為提供文件給用戶是響應包的數(shù)據(jù)
ServletOutputStream stream =resposne.getOutputStream();
?3.獲取到當前服務器中的文件輸入流
FileInputStrema is = newFileInputStream(path);
?4.設置這個響應的Content-disposition的屬性,
? 使得瀏覽器解析出這個是一個下載從而提升用戶體驗
responser.setHeader("content-disposition","attachment;filename="+ URLEncodier.encode(path));
?5.將這個文件寫出到用戶的瀏覽器中,從而使得用戶可以下載到自己的硬盤中
.....................................................................
?6.關閉流
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■↓↓↓↓↓↓↓↓↓ JavaMail↓↓↓↓↓↓↓↓↓↓↓■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
JavaMail;
為什么要有?
當一個網站的用戶注冊了,
需要進行郵箱的驗證的時候,
如果是人工一個一個的發(fā)送,
那么效率低下,用戶體驗差......
是什么?
是SUN公司規(guī)定的標準,是用于通過Java程序進行發(fā)送郵件的操作
作用;
通過業(yè)務的邏輯,從而發(fā)送郵件給用戶,提高安全性,實現(xiàn)業(yè)務的多樣性......
特點;
發(fā)送基本都是依賴SMTP協(xié)議(簡單郵件發(fā)送協(xié)議)
接收基本都是依賴pop3協(xié)議(郵件接收協(xié)議版本3)
--------------------------------------↓↓↓↓↓↓↓↓↓郵件發(fā)送的方式↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
常見郵件發(fā)送的方式;
? 1.cmd命令
? 2.java命令
? 3.郵件應用
--------------------------------------↓↓↓↓↓↓↓↓↓郵件運行原理↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
郵件運行原理;
一般都是由兩臺服務器組成的
A、SMTP服務器 ?
---> ? 發(fā)送郵件
B、POP3服務器 ?
---> ? 接收郵件
? ? ?163.用戶A給qq.用戶B發(fā)送了一封郵件,
而這封郵件先發(fā)送到163的SMTP服務器,
163的SMTP服務器則對這封郵件后綴進行解析
解析到了是qq.com的地址,
則會按照smtp.qq.com這個地址將郵件發(fā)送的pop3服務器。
------------------------------------↓↓↓↓↓↓↓↓↓JavaMail開發(fā)步驟↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
JavaMail開發(fā)步驟;
1.創(chuàng)建一個Properties類,定義發(fā)送的屬性
2.通過JavaMail的Session核心類的getDefaultInstance(pro,Atthencator);方法連接數(shù)據(jù)庫
---> Session 是一個抽象類
---> Atthenticator 也是一個抽象類
3.創(chuàng)建MimeMessage類傳入一個連接服務器的Session類對象
4.調用MimeMessage類的方法定義郵件并且發(fā)送
◆◆◆重◆◆◆注意;如果創(chuàng)建的是普通的java項目而不是web項目,
則需要進行導入jar包---> mail.jar
? ? 而在MyEclipse中的web項目自帶mail.jar可能無法使用則刪除在導入
------------------------------------↓↓↓↓↓↓↓↓↓JavaMail開發(fā)過程↓↓↓↓↓↓↓↓↓↓↓-------------------------------------------
JavaMail開發(fā)過程;
?1.創(chuàng)建一個Porperties類對象
properties pro = new Properties();
?2.定義連接數(shù)據(jù)庫的屬性
? A.定義連接的服務器的地址
pro.setProperty("mail.host","smtp.qq.com");
B.定義是否需要進行驗證
pro.setProperty("mail.smtp.auth","true");
?3.通過Session類的靜態(tài)方法創(chuàng)建一個Session對象,從而連接到服務器
Session session =Session.getDefaultInstance(pro,new Authencator(){
protected javax.mail.PasswordAuthenticationgetPasswordAuthentication() {
//調用PsswordAuthentication類在構造方法中傳入密碼和賬號
return new PasswordAuthentication("賬號","密碼");
});
? 說明;
? ? ? Session是JavaMail中的一個核心類,
? ? ? ? ?而這個類是用于連接郵件服務器的,
傳入一個Properties對象,
? ?而這個properties對象是定義好連接服務器的屬性的
? ?Authentication是一個抽象類,
? ? 而這個類是用于封裝賬號密碼的,
? ? ? ?對賬號和密碼進行加密的。
?4.創(chuàng)建一個MimeMessage類傳入一個Session對象,
? 這個類是用于定義郵件格式和數(shù)據(jù)發(fā)送給用戶的。
MimeMessage mes = newMimeMessage(session);
? A.定義發(fā)件人信箱,必須要和賬號一樣,傳入一個Address的子類
mes.setFrom(newInternetAddress("xx.qq.com"));
B.定義收件人信息
mes.setRecipient(RecipientType.XX,new
InternetAddress(收件人郵箱));
說明;
? ? ?RecipientType有三種發(fā)送方式;
? ? ? 1.TO ---> 發(fā)送
? ? ? ? ? ?直接發(fā)送
? ? ? 2.CC ---> 抄送
? ? ? ? ? ?類似A-B-C轉發(fā)
? ? ? 3.BCC ---> 密送
? ? ? ?類似A-D私聊,但是D可以看到B和C的郵件內容
C.添加附件(文件、圖片......) ?---> ◆可選
i.創(chuàng)建一個附件類
MimeBodyPart part = new MimeBodyPart();
1.添加一個文件
part.attachFile(new File("附件路徑"));
2.添加附件內容
part.setContent("xx","text/plain;charset=UTF-8");
ii.創(chuàng)建一個附件類的容器類
MimeMultipart multipart = newMimeMultipart();
1.調用方法添加一個好的附件類對象
multipart.addBodyPar(part);
D.調用MimeMessage的添加郵件內容方法將這個附件類容器對象傳入
1.發(fā)送郵件附件
mes.setContent(mutilpart);
2.設置發(fā)送郵件正文
mes.setContent("xxx","text/plain; charset=utf-8;");
3.設置郵件正文為一張網絡上一張照片,并且設置為超鏈接,廣告形式
mes.setContent("
? ? <img src="網絡圖片地址">
,
"text/html;charset=UTF-8");
E.調用Transport抽象類的方法將郵件信息發(fā)送給服務器
Transport.send(mm);
◆◆◆◆◆注;在發(fā)送內容的時候要指定內容在網絡中傳輸?shù)念愋?/p>
而郵件基本都是使用BASE64進行加密的
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■↓↓↓↓↓↓↓↓↓ 其他↓↓↓↓↓↓↓↓↓↓↓■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
1、泛型
作用;
? ? 1.可以減少代碼轉換,使得方法更加通用
? ? a_ 自定義類<T>轉換 ? ?---> 自定義泛型類
? ? b_ 方法轉換 ? ? ? ? ? ---> 自定義泛型方法
? ? 2.提前預知類運行時異常
? ? a_ 因為在給一個類或方法設置了泛型,
? ? 則使得在轉換成為不是這個泛型,
? ? 所規(guī)定的則會報編譯時錯誤。
? ? 3.可以限定轉換的類型范圍
? a_ <?> 則是通配所有類型,一般都是為了使得工具不出現(xiàn)警告
? b_ <? extends Xx> 只能存放本類和本類下的子類
? c_ <? super Xx> 只能存放本類和本類的父類
2、枚舉
作用;如;實現(xiàn)一個多選一的功能
在定義枚舉類的屬性的時候可以定義這個屬性的值
---> A("xxx"); ? ---> 而這個也會作為一個類似對象的存在
而當這個枚舉類提供了一個有參的構造器
通過這個參數(shù)的對應成員變量的get方法
進行獲取,所以可以理解為一個對象。
3、注解
作用;攜帶數(shù)據(jù)
而···注釋只是一個說明而已
自定義注解;
? ?語法;@interfaceXx{};
? ? 屬性語法;類型 名() ---> 修飾符只能是public default
? ? ? ? ?---> 如果在定義屬性的時候添加了default "xx",
? ? ? ? ?則在使用這個注解的時候不用顯示的賦值
? ? ? ? ?···使用默認值
? ? ?---> 如果屬性名是value則在調用的時候,
? ? ? 則可以省略不寫屬性名
◆◆◆注;類型不可以是集合,
但是可以是數(shù)組。
調用屬性;@Xx (Ff=Aa); ---> 普通屬性
? @Xx (Ee={xx,xx}) ---> 數(shù)組屬性
常用的元注解;
? ?作用;使得這個自定義注解可以更加靈活的應用
? ? ◆◆注;是聲明在這個自定義注解上面的
? ? @Target ({ElementType.Xx})
---> 定義這個注解的位置,如;屬性,方法......
? ? 常用;
? ? ? ? ?Type
? 作用在類
? ? ? ? ?Field
? 作用在成員變量
? ? ?Method ? 作用在方法上
? ? ?Constractor ? 作用在構造器上
? ? ?Parameter ? 作用在參數(shù)
? ? ?Local_Value ? 作用在本地值
? ? ?。。。。。。
◆◆◆注;默認是全部的作用在全部的位置上
? ?@Retention (RetentionPolicy.X)
---> 設置這注解攜帶數(shù)據(jù)的范圍
? ? 三種范圍;
? ? ?Source ---> 源碼,當前這個注解元素范圍
? ? ?Class ?---> 字節(jié)碼上有效 ---> 包含了Source
? ? ?Runtime ---> 運行時有效 ---> 包含了Source、Class
◆◆◆注;默認是Class
4、反射
是所有Java對象構建的原理,
任何的類都是通過類加載器加載進內存的,
由類加載器讀取指定目錄的class文件后,
將class文件中的所有信息封裝為不同的類,
Method類,Constracter類,Field類,Class正在運行時類,
可以通過這些類的方法獲取到對應的相關的信息。
代碼;
? ? Class x = Yy.getClass();
---> 獲取到Yy這個運行時類對象
? ? Method m =
x.getDeclarMethod("方法名"); ---> 獲取到這個運行時類對象的所有方法(可見/不可見)
? ? m.setAccessible(true); ?
? ---> 設置可以訪問所有的方法,無視修飾符
◆◆◆注;如果是final修飾的,則無效
? ? Object o = x.newIstance();
---> 獲取到這個類的實例
m.invoke(o,"xx");---> 調用某一個方法并且進行賦值(有參)
5、類加載器
? ?作用;是用于加載所有的類對象的
? ? ?所有的類都是通過類加載器加載進內存的,
? ? 而加載器也是一個類來的,ClassLoader類
? ?Java類加載器內部結構
? ? ↑↑↑ C++程序讀取
? ? ↑↑↑ BootStrap ? ?
?---> 根類加載器 ---> %jdk%/lib/tr.jar 核心類包
? ? ↑↑↑ ExtClassLoader ---> 擴展加載器---> %jdk%/lib/ext/*.jar
? ? ↑↑↑ AppClassLoader ---> 應用加載器 ---> %app%/bin/* 源碼下bin文件夾
? ? ↑↑↑ ClassLoader ?
?---> 類加載器 ? ? ? ?當前類
? ? ◆◆◆注;這個也是一個內部執(zhí)行的順序---> C - A - E - B - C+
? ?類加載器相關的API_ClassLoad基本方法 ---> X.getClassload()
---> 獲取到一個類的加載器
?getParent() ---> 獲取到父類加載器,
? ? ? ? ? ?可以用while獲取到整個結構
? ? ? ? ? ?如果是null則是根類加載器
Java類加載機制 —— 委托機制
發(fā)出;類T由C類加載器發(fā)出加載請求給A類加載器,
A類加載器則向E類加載器發(fā)出請求,
E類加載器則向B類加載器發(fā)出請求。
處理;
? 找不到;B類加載器獲取到這個請求,
↓↓↓ 則在當前的目錄下查找是否有這個類對應的class文件,
↓↓↓ 沒有則將這個請求發(fā)送給E類加載器,E類加載器重復B類加載器的查找動作
↓↓↓ 沒有拋給A類加載器,A類加載器則會在%app%/bin/*目錄下查找
↓↓↓ 沒有這個類對應的class文件則,
會報NotFoundClassException類找不到異常
? ? 找到;在提交到根類加載器的時候找到了則加載,
? ? 找不到則向下委托,向下委托找到了則加載,
? ? 找不到則重復,直到A類加載器找到為止,
? ? A類加載器找不到則報錯。
? ? ◆◆◆注;必須先提交到B類(根類)加載器才會進行查找文件操作
◆◆◆注;如果一個類1中還有一個類2,
那么類1被那個類加載器加載到這個類2也是被這個類加載器加載到
委托機制的好處;
1.提高效率,節(jié)省資源.....
提高效率是因為是逐層查找,加載的,
那么則不會使得當每一個類加載器,
都有一個同名的文件的時候都要進行加載
2.提高對JDK核心類的安全性......
因為如果創(chuàng)建java.util包創(chuàng)建了Date類,
那么在查找的時候,因為使用哪個呢?
有了委托機制則只會使用核心包的Date的類
◆◆◆◆◆注;無論有多少個對象,
都是只有一個類加載器,
因為只是對源class文件進行加載的。
而在new對象的時候有無數(shù)個對象,
都是通過反射調用這個類的構造器
? ◆◆ 類是對數(shù)據(jù)的一個抽取,而對象是對這個數(shù)據(jù)的實現(xiàn),
而對象的實現(xiàn)始終還是指向這個一個類(.class文件)