Servlet 2.3過濾器程式設計(二) (轉)
:namespace prefix = o ns = "urn:schemas--com::office" />
過濾器
我們將看到的最後一個過濾器是處理多路/多型別資料的POST請求,該型別的請求能包含檔案上傳。每個多路/多型別資料POST請求包含所有引數和檔案,使用一種servlet不能識別的特別的格式。歷史上Servlet開發者使用第三方類來處理上傳,例如在我的com.oreilly.servlet包中的MultipartRequest和MultipartParser類。這裡我們將看到一種使用MultipartFilter的新方法來是處理這種請求更容易。該過濾器基於com.oreilly.servlet包下的parsers構建並已經被整合到該包中(參見world.com/javaworld/jw-06-2001/jw-0622-filters_p.html#res#resources">Resources)。
MultipartFilter工作與觀察輸入的請求,當它發現一個檔案上傳請求時(content type:multipart/form-data),過濾器使用一個知道如何分析這種特殊content type格式的特殊請求包來將請求進行包裝。servlet獲取此特殊請求包並透過標準的getParameter()方法來無縫地訪問此multipart引數,因為這個wrapper中已經重新定義了這些方法的功能。此servelt能夠透過將requset轉換成wrapper型別並使用wrapper中附加的getFile()方法來處理檔案上傳。
過濾器程式碼:
package com.oreilly.servlet;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class MultipartFilter implements Filter {
private FilterConfig config = null;
private String dir = null;
public void init(FilterConfig config) throws ServletException {
this.config = config;
// Detene the directory. First look for an uploadDir filter
// init parameter. Then look for the context tempdir.
dir = config.getInitParameter("uploadDir");
if (dir == null) {
File tempdir = (File) config.getServletContext()
.getAttribute("javax.servlet.context.tempdir");
if (tempdir != null) {
dir = tempdir.toString();
}
else {
throw new ServletException(
"MultipartFilter: No upload directory found: set an uploadDir " +
"init parameter or ensure the javax.servlet.context.tempdir " +
"directory is valid");
}
}
}
public void destroy() {
config = null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String type = req.getHeader("Content-Type");
// If this is not a multipart/form-data request continue
if (type == null || !type.startsWith("multipart/form-data")) {
chain.doFilter(request, response);
}
else {
MultipartWrapper multi = new MultipartWrapper(req, dir);
chain.doFilter(multi, response);
}
}
}
init()方法確定檔案上傳的路徑。這是multipart parser放置檔案的地方,因此實際的請求並不需要駐留在中。它先查詢uploadDir過濾器初始化引數,如果沒找到,則使用預設的tempdir目錄——Servlet 2.2中的標準context屬性。
doFilter()方法檢查請求的content type,如果是multipart/form-data請求,則將此請求用MultipartWrapper打包。wrapper程式碼如下:
package com.oreilly.servlet;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class MultipartWrapper extends HttpServletRequestWrapper {
MultipartRequest mreq = null;
public MultipartWrapper(HttpServletRequest req, String dir)
throws IOException {
super(req);
mreq = new MultipartRequest(req, dir);
}
// Methods to replace HSR methods
public Enumeration getParameterNames() {
return mreq.getParameterNames();
}
public String getParameter(String name) {
return mreq.getParameter(name);
}
public String[] getParameterValues(String name) {
return mreq.getParameterValues(name);
}
public Map getParameterMap() {
Map map = new HashMap();
Enumeration enum = getParameterNames();
while (enum.hasMoreElements()) {
String name = (String) enum.nextElement();
map.put(name, mreq.getParameterValues(name));
}
return map;
}
// Methods only in MultipartRequest
public Enumeration getFileNames() {
return mreq.getFileNames();
}
public String getFilesystemName(String name) {
return mreq.getFilesystemName(name);
}
public String getContentType(String name) {
return mreq.getContentType(name);
}
public File getFile(String name) {
return mreq.getFile(name);
}
}
wrapper構造了一個com.oreilly.servlet.MultipartRequest物件以處理上傳分析並過載getParameter()方法族以使用MultipartRequest取代未加工的請求來讀取引數值。wrapper也定義了不同的getFile()方法以使一個servlet接收打包過的請求以能透過其他方法來處理上傳的檔案。
.xml部署描述器用如下程式碼來新增此過濾器:
<!--
-->
uploadTest
UploadTest
uploadTest
/uploadTest
UploadText servlet如下:
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.oreilly.servlet.*;
public class UploadTest extends HttpServlet {
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html");
PrintWriter out = res.getWriter();
out.println("");
out.println("
out.println("
");out.println("
UploadTest
");
// Parameters can now be read the same way for both
// application/x-www-form-urlencoded and multipart/form-data requests!
out.println("
Request Parameters:
");");Enumeration enum = req.getParameterNames();
while (enum.hasMoreElements()) {
String name = (String) enum.nextElement();
String values[] = req.getParameterValues(name);
if (values != null) {
for (int i = 0; i < values.length; i++) {
out.println(name + " (" + i + "): " + values[i]);
}
}
}
out.println("
// Files can be read if the request class is MultipartWrapper
// Init params to MultipartWrapper control the upload handling
if (req instanceof MultipartWrapper) {
try {
// Cast the request to a MultipartWrapper
MultipartWrapper multi = (MultipartWrapper) req;
// Show which files we received
out.println("
Files:
");out.println("
");");Enumeration files = multi.getFileNames();
while (files.hasMoreElements()) {
String name = (String)files.nextElement();
String filename = multi.getFilesystemName(name);
String type = multi.getContentType(name);
File f = multi.getFile(name);
out.println("name: " + name);
out.println("filename: " + filename);
out.println("type: " + type);
if (f != null) {
out.println("length: " + f.length());
}
out.println();
}
out.println("
}
catch (Exception e) {
out.println("
");");e.printStackTrace(out);
out.println("
}
}
out.println("");
}
}
servlet的前一半顯示了過濾器如何將引數資料毫無改變的傳送給接收的servlet。後半部分則顯示了一個servlet是如何將請求向下傳送給MultipartWrapper以獲得附加的檔案訪問方法。
一個此servlet的HTML例子如下:
What is your name?
What is your age?
Which file do you want to upload?
Any other file to upload?
這是可能的輸出:
UploadTest
Request Parameters:
submitter (0): Jason
age (0): 28
Files:
name: file1
filename: 4008b21.tif
type: application/octet-stream
length: 39396
name: file2
filename: null
type: null
你們也許會疑惑我們如何確信由過濾器設定的MultipartWrapper能正確的傳送給接下來的servlet。在2號釋出稿規範和 4.0 beta 5中,那是不確定的。實際上,如果你試圖用/servlet/UploadTest去訪問此servlet,你將注意到過濾並沒有正確工作,因為/servlet的呼叫將MultipartWrapper轉給Tomcat自己的特殊wrapper了。這允許引數能被正確解析,但檔案訪問方法卻不能正確工作。在Servlet API專家組的討論中,我們決定servlet容器不能對過濾器的wrapper做更多的包裝。這個servlet規範將被修改的更清楚。在Tomcat 4.0以後版本中將澄清這些規則。短期的辦法是在請求wrapper中使用getRequest()方法來“沿著”請求去找到這個隱藏的multipart wrapper。
從如下地址該WAR檔案:
過濾器能力
Servlet過濾器提供了一中強大的能力來控制請求的操作和響應的發生,提供新的servlet功能而不需要太多的程式碼。我希望透過這些已經向你展示使用過濾器的可能情況,並教給你一些關於如何更有效的使用新的過濾器機能的技巧。
感謝這些過濾器的作者以及其他對過濾器提供有用建議的的人:Amy Roh,Criag McClanahan,Serge Knystautas,以及OpenSymphony成員。
關於作者
見原文
資源
見原文
達人給指點斧正了,謝謝:)
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-993922/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Servlet過濾器原始碼分析Servlet過濾器原始碼
- Java設計模式-過濾器模式Java設計模式過濾器
- 極簡設計模式-過濾器模式設計模式過濾器
- 品味布隆過濾器的設計之美過濾器
- JavaWeb之Servlet、攔截器、監聽器及程式設計思想JavaWebServlet程式設計
- 好程式設計師大資料培訓分享HBase Filter過濾器概述程式設計師大資料Filter過濾器
- Laravel 模型過濾(Filter)設計Laravel模型Filter
- 【TUNE_ORACLE】Oracle索引設計思想(二)索引過濾列概述Oracle索引
- Java 網路程式設計----初探ServletJava程式設計Servlet
- 過濾器過濾器
- JAVA網路程式設計基本功之Servlet與Servlet容器Java程式設計Servlet
- 4、過濾器的使用及自定義過濾器過濾器
- 點雲濾波器與過濾器過濾器
- CAN過濾器過濾器
- Filter過濾器Filter過濾器
- vue 過濾器Vue過濾器
- NetCore過濾器NetCore過濾器
- 代理過濾器過濾器
- Vue過濾器Vue過濾器
- DataV過濾器過濾器
- hbase過濾器過濾器
- Xor過濾器:比布隆Bloom過濾器更快,更小過濾器OOM
- Spring Security 實戰乾貨:圖解Spring Security中的Servlet過濾器體系Spring圖解Servlet過濾器
- Spring Cloud Gateway ---GatewayFilter過濾器、過濾器工廠(入門)SpringCloudGatewayFilter過濾器
- PHP 過濾器(Filter)PHP過濾器Filter
- vue---過濾器Vue過濾器
- Vue中過濾器Vue過濾器
- vue filters過濾器VueFilter過濾器
- 布隆過濾器過濾器
- SpringSecurity過濾器原理SpringGse過濾器
- 微課|玩轉Python輕鬆過二級(1.1節):Python指令式程式設計與函數語言程式設計模式Python程式設計函數設計模式
- Python+django網頁設計入門(18):自定義模板過濾器PythonDjango網頁過濾器
- 誠翔濾器光刻膠過濾器濾芯:保障光刻過程的高效與安全過濾器
- Spring Cloud Gateway中的過濾器工廠:重試過濾器SpringCloudGateway過濾器
- 小程式的wxs指令碼(類似過濾器)指令碼過濾器
- 監聽器和過濾器過濾器
- 胖哥學SpringMVC:請求方式轉換過濾器配置SpringMVC過濾器
- Shiro原理解析(二)--過濾器的執行機制過濾器
- 抓包整理外篇fiddler———— 會話欄與過濾器[二]會話過濾器