. 增強HttpServletResponse對象
1. 實現(xiàn)一個增強的HttpServletResponse類,需要繼承javax.servlet.http.HttpServletRequestWrapper類,通過重寫自己需要增強的方法來實現(xiàn)(這種模式就叫做裝飾者模式),使用該增強類在加上過濾器就可以實現(xiàn)無編碼轉(zhuǎn)換處理代碼。
public class MyRequest extends HttpServletRequestWrapper{ private HttpServletRequest req; public MyRequest(HttpServletRequest request) { super(request); req=request; } @Override public String getParameter(String name) { //解決編碼問題,無論是post還是get請求,都不需要在業(yè)務(wù)代碼中對編碼再處理 String method=req.getMethod(); if("get".equalsIgnoreCase(method)){ try { String str=req.getParameter(name); byte[] b=str.getBytes("iso8859-1"); String newStr=new String(b, "utf-8"); return newStr; } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } }else if("post".equalsIgnoreCase(method)){ try { req.setCharacterEncoding("utf-8"); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //絕對不能刪除此行代碼,因為此行代碼返回的就是編碼之后的數(shù)據(jù) return super.getParameter(name); } }
在過濾器中應(yīng)用
public class FilterTest4 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException {} @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //生成增強的HttpServletRequest對象 HttpServletRequest req=(HttpServletRequest) request; MyRequest myReq=new MyRequest(req); //將增強的HttpServletRequest對象傳入過濾器執(zhí)行鏈中,在后面?zhèn)魅氲膔equest對象都會是增強的HttpServletRequest對象 chain.doFilter(myReq, response); } @Override public void destroy() {} }
2. 文件上傳原理過程
1. JavaWeb中實現(xiàn)文件上傳:
<html> <head> <title>My JSP 'upload.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"> </head> <body> <form action="" method="post" enctype="multipart/form-data"> <input type="text" name="name"> 請選擇文件:<input type="file" name="upload"> <input type="submit" value="上傳"> </form> </body> </html>
import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; public class UploadServlet extends HttpServlet{ @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { /** * 1. 創(chuàng)建磁盤文件項工廠類 DiskFileItemFactory * 2. 創(chuàng)建核心解析Request類 ServletFileUpload * 3. 開始解析Request對象中的數(shù)據(jù),并返回一個List集合 * 4. List中包含表單中提交的內(nèi)容 * 5. 遍歷集合,獲取內(nèi)容 */ DiskFileItemFactory fac=new DiskFileItemFactory(); ServletFileUpload upload=new ServletFileUpload(fac); upload.setHeaderEncoding("utf-8");//防止中文的文件名亂碼 try { List<FileItem> fileItems = upload.parseRequest(req); for(FileItem item:fileItems){ //有可能是普通文本項,比如<input type="text">標簽提交上來的字符串 //也有可能是<input type="submit" value="上傳">上傳的文件 //文件項與普通項有不同的API來處理 //首先判斷是普通文本項還是文件項, if(item.isFormField()){ //true表示普通文本項 //獲取文本項的name屬性值 String name=item.getFieldName(); //獲取對應(yīng)的文本 String value=item.getString("utf-8");//防止中文亂碼 System.out.println(name+":"+value); }else{ //false表示文件項 //先獲取文件名稱 String name=item.getName(); //獲取文件項的輸入流 InputStream in=item.getInputStream(); //獲取服務(wù)器端文件存儲的目標磁盤路徑 String path=getServletContext().getRealPath("/upload"); System.out.println(path); //獲取輸出流,輸出到本地文件中 OutputStream out=new FileOutputStream(path+"/"+name); //寫入數(shù)據(jù) int len=0; byte[] b=new byte[1024]; while((len=in.read(b))!=-1){ out.write(b,0,len); } in.close(); out.close(); } } } catch (FileUploadException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
注意:在文件上傳時,會將form表單的屬性enctype屬性值為"multipart/form-data",當提交到服務(wù)端后,無法使用 req.getParameter(name) 方法來獲取到內(nèi)容,只有通過上面的方法來獲取文本項。
2. 文件上傳相關(guān)核心類:
//改進上面的文件上傳代碼,添加一個臨時文件 public class UploadServlet extends HttpServlet{ @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { DiskFileItemFactory fac=new DiskFileItemFactory(); fac.setSizeThreshold(1024*1024);//設(shè)置緩沖區(qū)為1mb //設(shè)置臨時文件的本地磁盤存儲路徑 File repository=new File(getServletContext().getRealPath("/temp")); fac.setRepository(repository); ServletFileUpload upload=new ServletFileUpload(fac); upload.setHeaderEncoding("utf-8");//防止中文的文件名亂碼 try { List<FileItem> fileItems = upload.parseRequest(req); for(FileItem item:fileItems){ if(item.isFormField()){ String name=item.getFieldName(); String value=item.getString(); String value=item.getString("utf-8");//防止中文亂碼 System.out.println(name+":"+value); }else{ String name=item.getName(); InputStream in=item.getInputStream(); String path=getServletContext().getRealPath("/upload"); System.out.println(path); OutputStream out=new FileOutputStream(path+"/"+name); int len=0; byte[] b=new byte[1024]; while((len=in.read(b))!=-1){ out.write(b,0,len); } in.close(); out.close(); } } } catch (FileUploadException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
3. 實現(xiàn)多文件上傳(需要js技術(shù)):主要是更改jsp頁面,通過js代碼來添加多個文件進行上傳,服務(wù)器代碼無需更改
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" contentType="text/html; charset=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 'upload.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"> </head> <body> <script type="text/javascript"> function run(){ var div=document.getElementById("divId"); div.innerHTML+= "<div><input type='file' name='upload'><input type='button' value='刪除' onclick='del(this)'></div>" } function del(presentNode){ var div=document.getElementById("divId"); div.removeChild(presentNode.parentNode); } </script> <div> 多文件上傳<br/> <form action="/Servlet/upload" method="post" enctype="multipart/form-data"> <input type="button" value="添加" onclick="run()"><br/> <div id="divId"> </div> <input type="submit" value="上傳"> </form> </div> </body> </html>
4. 關(guān)于文件上傳的一些問題:
3. 文件下載
1. 傳統(tǒng)文件下載方式有超鏈接下載或者后臺程序下載兩種方式。通過超鏈接下載時,如果瀏覽器可以解析,那么就會直接打開,如果不能解析,就會彈出下載框;而后臺程序下載就必須通過兩個響應(yīng)頭和一個文件的輸入流。
2. 后臺程序下載:
單的 ASP.NET 頁面看上去就像普通的 HTML 頁面。
Hello RUNOOB.COM
在開始學(xué)習(xí) ASP.NET 之前,我們先來構(gòu)建一個簡單的 HTML 頁面,該頁面將在瀏覽器中顯示 "Hello RUNOOB.COM":
Hello RUNOOB.COM! |
用 HTML 編寫的 Hello RUNOOB.COM
下面的代碼將以 HTML 頁面的形式顯示實例:
<html>
<body bgcolor="yellow">
<center>
<h2>Hello RUNOOB.COM!</h2>
</center>
</body>
</html>
如果您想親自嘗試一下,請保存上面的代碼到一個名為 "firstpage.htm" 的文件中,并創(chuàng)建一個到該文件的鏈接:firstpage.htm。
用 ASP.NET 編寫的 Hello RUNOOB.COM
轉(zhuǎn)換 HTML 頁面為 ASP.NET 頁面最簡單的方法是,直接復(fù)制一個 HTML 文件,并把新文件的擴展名改成 .aspx 。
下面的代碼將以 ASP.NET 頁面的形式顯示實例:
<html>
<body bgcolor="yellow">
<center>
<h2>Hello RUNOOB.COM!</h2>
</center>
</body>
</html>
如果您想親自嘗試一下,請保存上面的代碼到一個名為 "firstpage.aspx" 的文件中,并創(chuàng)建一個到該文件的鏈接:firstpage.aspx。
它是如何工作的?
從根本上講,ASP.NET 頁面與 HTML 是完全相同的。
HTML 頁面的擴展名是 .htm。如果瀏覽器向服務(wù)器請求一個 HTML 頁面,服務(wù)器可以不進行任何修改,就直接發(fā)送頁面給瀏覽器。
ASP.NET 頁面的擴展名是 .aspx。如果瀏覽器向服務(wù)器請求個 ASP.NET 頁面,服務(wù)器在將結(jié)果發(fā)回給瀏覽器之前,需要先處理頁面中的可執(zhí)行代碼。
上面的 ASP.NET 頁面不包含任何可執(zhí)行的代碼,所以沒有執(zhí)行任何東西。在下面的實例中,我們將添加一些可執(zhí)行的代碼到頁面中,以便演示靜態(tài) HTML 頁面和動態(tài) ASP 頁面的不同之處。
經(jīng)典 ASP
Active Server Pages (ASP) 已經(jīng)流行很多年了。通過 ASP,可以在 HTML 頁面中放置可執(zhí)行代碼。
之前的 ASP 版本(在 ASP.NET 之前)通常被稱為經(jīng)典 ASP。
ASP.NET 不完全兼容經(jīng)典 ASP,但是只需要經(jīng)過少量的修改,大部分經(jīng)典 ASP 頁面就可以作為 ASP.NET 頁面良好地運行。
如果您想學(xué)習(xí)更多關(guān)于經(jīng)典 ASP 的知識,請訪問我們的 ASP 教程。
用經(jīng)典 ASP 編寫的動態(tài)頁面
為了演示 ASP 是如何顯示包含動態(tài)內(nèi)容的頁面,我們將向上面的實例中添加一些可執(zhí)行的代碼(紅色字體標識):
<html>
<body bgcolor="yellow">
<center>
<h2>Hello RUNOOB.COM!</h2>
<p><%Response.Write(now())%></p>
</center>
</body>
</html>
<% --%> 標簽內(nèi)的代碼是在服務(wù)器上執(zhí)行的。
Response.Write 是用來向 HTML 輸出流中寫東西的 ASP 代碼。
Now() 是一個返回服務(wù)器當前日期和時間的函數(shù)。
如果您想親自嘗試一下,請保存上面的代碼到一個名為 "dynpage.asp" 的文件中,并創(chuàng)建一個到該文件的鏈接:dynpage.asp。
用 ASP .NET 編寫的動態(tài)頁面
下面的代碼將以 ASP.NET 頁面的形式顯示實例:
<html>
<body bgcolor="yellow">
<center>
<h2>Hello RUNOOB.COM!</h2>
<p><%Response.Write(now())%></p>
</center>
</body>
</html>
如果您想親自嘗試一下,請保存上面的代碼到一個名為 "dynpage.aspx" 的文件中,并創(chuàng)建一個到該文件的鏈接:dynpage.aspx。
ASP.NET 對比經(jīng)典 ASP
上面的實例無法演示 ASP.NET 與經(jīng)典 ASP 之間任何的不同之處。
正如最后的兩個實例中,您看不出 ASP 頁面和 ASP.NET 頁面兩者之間的不同之處。
在下一章中,您將看到服務(wù)器控件是如何讓 ASP.NET 比經(jīng)典 ASP 更強大的。
)CSS 標準盒子模型(Box Model)
在網(wǎng)頁中所有HTML元素可以看作盒子,在CSS中,"box model"術(shù)語是用來設(shè)計和布局時使用的;CSS盒模型本質(zhì)上是一個盒子,封裝周圍的HTML元素包括:外邊距(margin)邊框(border)內(nèi)邊距(padding)實際內(nèi)容(content)四個屬性,所以布局時每個元素所占的總寬高是這4個屬性的總和;比如寬度:總元素的寬度=寬度+左填充+右填充+左邊框+右邊框+左邊距+右邊距
1.1Margin(外邊距)清除邊框外的區(qū)域,外邊距是透明的
1.2Border(邊框)圍繞在內(nèi)邊距和內(nèi)容外的邊框
1.3Padding(內(nèi)邊距)清除內(nèi)容周圍的區(qū)域,內(nèi)邊距是透明的
1.4Content(內(nèi)容)盒子里填充的內(nèi)容比如文本,圖像等
標準盒子模型
寬度為100px的div
根據(jù)盒子模型得出該元素的總寬度為:100+(20+20)+(15+15)+(15+15)(由里至外)因此如果想在此div中放置一個寬度為100px的元素,此元素的總寬度必須小于等于100px
2)DIV+CSS布局
Div+CSS布局就是將網(wǎng)頁內(nèi)容用<div>分割為塊,之后使用css設(shè)置每個塊的大小,位置等
DIV+CSS布局最重要的是靈活運用float(浮動)屬性,其值:1)left 2)right 3)both
clear屬性作用是清除浮動,其值為:1)left 2)right 3)both
d2向右浮動 float:right
因為div是塊級元素,如果都沒有脫離文檔流div就會按照從上到下的順序放置
d2設(shè)置為右浮動其他兩個div位置的變化:
1)d1沒有脫離文檔流會占據(jù)一行,所以d2只能浮動到d1下面的右面如上圖所示
2)d2脫離文檔流,d3自動填充到d2的位置
d1,d2全部設(shè)置為右浮動
1)當d1,d2都設(shè)置為右浮動時:因為css中d1在d2上面先設(shè)置,因此d1在右側(cè),如果d2在d1上面先設(shè)置樣式,則d2在右側(cè),d1在左側(cè),自己測試不再截圖
2)當d1,d2都設(shè)置為右浮動時:d3就會跑到上圖中d2的位置
3)如果3個div都設(shè)置左或右浮動,當3個width加一起<=100%就會在第一行顯示(d1,d2,d3)
<style type="text/css">
#d1 {
margin: 0px;
background-color: red;
padding: 0px;
width: 50%;
height: 100px;
float:right;
}
#d2 {
margin: 0px;
background-color: yellow;
padding: 0px;
width: 50%;
height: 100px;
float:right;
}
#d3 {
margin: 0px;
background-color: green;
padding: 0px;
width: 50%;
height: 100px;
}
</style>
d2清除左浮動,d3設(shè)置為右浮動
當d2清除了左浮動,d3設(shè)置為右浮動,就會如上圖所示;如果d2清除的是右浮動,d2就會在d1上面,d3就會定位在d1下面的右面,自己測試不再截圖
當d2清除了左浮動,如果想要d2緊挨著d1(與d1在一行上),可以通過position脫離文檔流設(shè)置其上下左右屬性使其定位在d1右側(cè),自己測試
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>div+CSS布局</title>
<style type="text/css">
#d1 {
margin: 0px;
background-color: red;
padding: 0px;
width: 30%;
height: 100px;
float:left;
}
#d2 {
margin: 0px;
background-color: yellow;
padding: 0px;
width: 40%;
height: 100px;
clear: left;
}
#d3 {
margin: 0px;
background-color: green;
padding: 0px;
width: 30%;
height: 100px;
float: right;
}
</style>
</head>
<body>
<div id="d1"><span style="font-size: 50px;">d1</span></div>
<div id="d2"><span style="font-size: 50px;">d2</span></div>
<div id="d3"><span style="font-size: 50px;">d3</span></div>
</body>
</html>
DIV+CSS布局綜合運用position+上下左右屬性與float屬性為網(wǎng)頁進行布局
注意:瀏覽器的兼容性問題,特別是使用IE內(nèi)核的瀏覽器對W3C的規(guī)范不怎么遵守
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。