--------------------------------------------------------------------------------------------------
在Java Web开发中Q经怼用到跌{面的方法,一般有下面两种Ҏ?br />Java代码
HttpServletResponse response = new HttpServletResponse();
response.sendRedirect(location);
RequestDispatcher rd = new RequestDispatcher();
rd.forward(request, response);
跌{方式
http://localhost:8080/Test应用
q用forwardҎ只能重定向到同一个Web应用E序中的一个资源。而sendRedirectҎ可以让你重定向到MURL?br />表单form的action= “/uu “;sendRedirect( “/uu “);表示相对于服务器根\径。如http://localhost:8080/Test应用Q则提交至http://localhost:8080/uuQ?
Forward代码中的 “/uu “则代表相对与WEB应用的\径。如http://localhost:8080/Test应用Q则提交至http://localhost:8080/Test/uuQ?
Q运用RequestDispatcher接口的ForwardQ方?br />forward()无法重定向至有frame的jsp文g,可以重定向至有frame的html文g,
同时forward()无法在后面带参数传?比如servlet?name=frank,q样不行,可以E序内通过response.setAttribute( “name “,name)来传至下一个页?
重定向后览器地址栏URL不变.
只有在客L没有输出时才可以调用forwardҎ。如果当前页面的~冲区(bufferQ不是空的,那么你在调用forwardҎ前必d清空~冲区?br />“/ “代表相对与web应用路径
RequestDispatcher rd = request.getRequestDispatcher( “/ooo “);
rd.forward(request, response);提交至http://localhost:8080/Test/ooo
RequestDispatcher rd = getServletContext().getRequestDispatcher( “/ooo “);
rd.forward(request, response);提交至http://localhost:8080/Test/ooo
RequestDispatcher rd =getServletContext().getNamedDispatcher( “TestServlet “);QTestServletZ?<servlet-name> Q?br />rd.forward(request, response);提交臛_为TestServlet的servlet
如果?<jsp:forward> 之前有很多输?前面的输出已使缓冲区?自动输出到客户?那么该语句将不v作用,q一点应该特别注意?br />另外要注意:它不能改变浏览器地址Q刷新的话会D重复提交
从http://localhost:8080/Test/gw/page.jsp中{?br /><jsp:forward page= “OtherPage.jsp “/> 在JSP面被解析后转换成pageContext.forward( “OtherPage.jsp [...]
--------------------------------------------------------------------------------------------------
清空当前~存Q?/p>
在之前撰写JSP的例子中Q实用了outq个对象Q这个对象您不用事先宣告Q就可以在JSP|页中用,q是JSP所提供的隐含对?/p>
(Implicit Object)Q在转译为Servlet之后Qout会{换ؓ对应于javax.servlet.jsp.JspWriter型态的对象?/p>
JspWriter直接l承自java.io.WriterQ您可以使用println()、print()Ҏ指定的数据以字W的方式传送至客户端,println()?/p>
在送出数据之后q行换行Q而print()则否Q注意换行指的是在HTML原始码中讑֮换行字符Q而不是输?lt;br>标签使得在网中可以
换行?/p>
out(JspWriter)h~冲区功能,HTTP的特性是Z要取得一份资源,p行一份协议沟通,如果资源数目很多(例如一份HTML文g
q包括了许多的小囄)Q而每份资源的定w实际上很,那么Z要取得完整的资源Q将会花费很多通讯在协议往来上Q假讑֦?/p>
out(JspWriter)不具有缓冲功能,则每一ơout.println()Q就会直接将数据送出臛_LQ那么单要完成一个完整网늚传送,?/p>
会花费不的|络资源Q每一个JSP|页预设上都会具有缓Ԍ您可以用page指o元素的autoFlush属性来讑֮是否使用~冲区功?/p>
?/p>
在Tomcat5上,预设为每一个JSP|页备有8192字节的缓冲区(您可以用page指o元素的buffer属性来自缓冲区的大?Q在~冲
没有满之前,数据不会真正被送出臛_LQ在q之前,您还有机会重N出的数据,如果~冲区满了,数据会被清出ƈ送至客户
端,可以使用下面q个E序来示范:
buffer.jsp
<%@page contentType="text/html;charset=Big5"%>
<%
out.println("预设~冲区大:" + out.getBufferSize() + "<br>");
out.flush();
//下面的文字不会出现在客户?br />out.println("您看的到q段文字?");
out.clearBuffer();
out.println("q段您可以看?");
%>
您可以用flush()直接清出~冲区的内容Q而clearBuffer()会将~冲区的内容清除Q所以第二段文字不会出现在客L的网上Q?/p>
而最后一D会整个JSP|页执行完整后自动送出臛_LQ执行结果如下:
预设~冲区大:8192
q段您可以看?
您可以用page指o元素的autoFlush来设定JSP面是否使用~冲动清出功能,out(JspWriter)以一U方式与
HttpServletResponse的PrintWriter建立关系Q两者之间的行ؓ关系取决于是否用缓冲区自动清出Q如果用缓冲区自动清出Q则
在缓冲区满之前,或是使用flush()之前不会建立PrintWriter对象来对客户端进行输出,如果不用缓冲区自动清出Q则写入out
(JspWriter)对象的数据会直接写入PrintWriter对象Q然后在指定flush()之后输出臛_L?/p>
如果您将autoFlush讑֮为falseQ则您必L的使用flush()来输出数据,否则~冲区满了的话,׃发生IOException例外Q?/p>
~冲区有其好处,但由于缓冲区在满之前Q数据ƈ不会真正送出客户端,所以会有响应gq的问题Q如果您要实时性将l果响应臛_
LQ则可以关闭~冲区?/p>
下面q个E序试~冲区关闭之后,如果~冲区满了,会有什么结果:
buffer.jsp
<%@page contentType="text/html;charset=Big5" %>
<%
for(int i=0; i<2000; i++){
out.println("test");
//out.flush();
}
%>
如果没有Udout.flush()的批注符P则会响应一下的错误讯息Q?br />HTTP Status 500 -
type Exception report
message
description The server encountered an internal error() that prevented it from fulfilling this request.
exception
java.io.IOException: Error: JSP Buffer overflow
......
A.1?/span>Redirect?/span>Forward的区?/span>
web开发开发中q行面跌{的方法有两个Q?/span>forward?/span>redirect?/span>
Forward
Forward单来说就是在服务器端完成叉跌{Q服务端?/span>A?/span>forward?/span>B,对于客户端来说一直都在访?/span>A,不知道有?/span>B存在(客户端地址栏看不到B地址Q它一直显C?/span>A늚地址Q?/span>
Forward是服务器h资源Q服务器直接讉K目标地址?/span>URLQ把那个URL的响应内容读取过来,然后把这些内容再发给览器。浏览器Ҏ不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址?/span>
Forward是在web应用E序之内q行的,可以讉Kweb应用E序所讑֮的内部目录,像是WEB-INF目录Q只能在Web应用E序中进行,不能指定臛_它的Web应用E序的地址?/span>
Forward跌{的页面中,request作用域的变量都能生效Q因为无?/span>forward多少ơ,都是同一?/span>request?/span>
Redirect
Redirect容易理解的多了Q从A?/span>forward?/span>B,服务端告诉客LQ你要从A跛_BQ由客户端发出指挥,所以客L地址栏看CA变?/span>B了?/span>
Redirect是服务端Ҏ逻辑Q发送一个状态码Q告诉浏览器重新去请求那个地址。所以地址栏显C的是新?/span>URL?/span>
Redirect的请求由览器发出,所以不能访?/span>Web应用E序中的隐藏目录Q像?/span>WEB-INFQ重新是由浏览器重新要求一个网,可以指定臛_他的Web应用E序地址?/span>
Reirect是由客户端指挥的Q所?/span>redirect以后已l是W二?/span>request了?/span>
A.2?/span>forwardҎ?/span>include的区?/span>
Forward
forwardҎ调用后在响应中的没有提交的内容被自动消除。将h转发l其他的Servlet后,p调用?/span>Servlet负责对请求做出响应,而原?/span>Servlet的执行则l止
Include
includeҎ使原先的Servlet和{发到?/span>Servlet都可以输出响应信息,卛_先的Servletq可以l输出响应信息?/span>
A.3、三者区?/span>
三个都可以对用户?/span>requestq行转发Q但是还是有许多的不同,差别最主要集中在如下几个方面:
1?/span>forward?/span>include׃nRequest范围内的对象Q?/span>redirect则不行,卻I如果一?/span>javabean被声明ؓrequest范围的话Q则?/span>forward到的资源也可以访问这?/span>javabeanQ?/span>redriect则不行?/span>
2?/span>forward?/span>include基本上都是{发到context内部的资源,?/span>redirect可以重定向到外部的资?/span>,如:req.sendRedriect(http://www.mocuai.com);
3?/span>RequestDispatcher.forward()仅是容器中控制权的{向,在客L览器地址栏中不会昄{向后的地址Q他是不会改?/span>Request的|如果你需要在下一个页面中能从中获取新的信息的话,你可?/span>Request.setAttribute()来放|一些标志,q样从下一个页面中获取Q?/span>HttpServletResponse.sendRedirect()Ҏ则是完全的蟩转,览器将会得到蟩转的地址Qƈ重新发送请求链接。这P从浏览器的地址栏中可以看到跌{后的链接地址。所以,前者更加高效,在前者可以满需要时Q尽量?/span>RequestDispatcher.forward()ҎQƈ且,q样也有助于隐藏实际的链接?/span>
B?/span>Redirect?/span>Forward?/span>Include的应?/span>
B.1、在JAVA中应?/span>
B.1.1?/span>Forward?/span>Include
forward?/span>include?/span>javax.servlet.RequestDispatcher来封装的Q其中声明如下:
void forward(ServletRequest req,ServletResponse res)
void include(ServeltRequest req,ServletResponse res)
可以通过两种方式得到RequestDispatcher:
ServletContext.getRequestDispatcher(String path);
其中q里?/span>path必须开始ؓ"/"Q即q里?/span>path必须相对?/span>context?/span>root.
ServeltRequest.getRequestDispatcher(String path)
q里?/span>path可以为相对\?/span>,如果path开始ؓ"/",则也认ؓ是从context?/span>root开始的?/span>
B.1.2?/span>Redirect
Redirect?/span>HttpServletResponse.sendRedirect(String location)来支?/span>
B.2、在Spring中应?/span>
B.2.1?/span>Forward?/span>Include
?/span>Spring mvc框架中一个控制器通常q回一个视囑Q然后视图解析器把它解析到某U视图技术上实现。对于?/span>JSP/Servlet视图技术时Q其实就是?/span>RequestDispatcher.forward()?/span>RequestDispatcher.include()Ҏ。比如当客户在浏览器中输入一?/span>URLQ如Q?/span>http://xxx/1.htmlQ,视图解析器把它解析到一?/span>jsp资源上,昄l客L?/span>jsp资源的数据,而客h览器中的地址没有变化?/span>
比如有些时候我们处理表单提交时Q若使用Spring内部forward机制Q一个控制器接收请求ƈq行处理Q处理完成后它可能返回一个视囑Q这时这个视囑ְ会有一个问题就是返回的视图会得C?/span>POST的数据,q容易造成h。还有一个问题是若用户刷新页面会D数据重复提交。若使用Redirect机制Q返回的视图?/span>GET{到的,是不同的hQ故可以避免多次提交的问题?/span>
forward: 前缀
使用UrlBasedViewResolver?/span>redirect:前缀?/span>
B.2.2?/span>Redirect
Ҏ一Q?/span>RedirectView
Spring?/span>Redirect实现Ҏ之一是让控制器(ControllerQ创建和q回一?/span>RedirectViewQ这U情况下Q?/span>DispatcherServlet不会使用通常的视图解析机Ӟ而是让控制器指定?/span>RedirectView视图来处理表单提交后的工作?/span>
RedirectView会调?/span>HttpServletResponse.sendRedirect()Q其中的model值将被{化ؓString传递给redirect的视图?/span>
Ҏ二:redirect:前缀
W二U方法是使用UrlBasedViewResolver?/span>redirect:前缀?/span>
<form name ="Form1" enctype="multipart/form-data" method="post" action="jspsmart.jsp">
<p>上传文g1Q?span style="color: #0000ff"><input type ="file" name ="File1" size="20" maxlength="20"/></p>
<input type ="submit" value="上传"/>
<input type ="reset" value="清除"/>
</form>
jspsmart.jsp中代码:
<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body>
<h2>文g上传规范-jspSmart</h2>
<jsp:useBean id="mySmartUpload" scope="page" class="com.jspsmart.upload.SmartUpload"/>
<%
//计算文g上传个数
int count=0;
//SmartUpload的初始化Q用这个jspsmart一定要在一开始就q样声明
mySmartUpload.initialize(pageContext);
//声明限制上传的文件的大小5MB
mySmartUpload.setMaxFileSize(5*1024*1024);
//依据form的内容上?br /> mySmartUpload.upload();
//上传的文g一个一个取出来处理
for (int i=0;i<mySmartUpload.getFiles().getCount();i++)
{
//取出一个文?br /> com.jspsmart.upload.File myFile = mySmartUpload.getFiles().getFile(i);
//如果文g存在Q则做存档操?br /> if (!myFile.isMissing()){
//文件存攑֜l对路径的位|?br /> myFile.saveAs("C:\\upload\\"+myFile.getFileName(),mySmartUpload.SAVE_PHYSICAL);
//昄此上传文件的详细信息
out.println("FieldName="+myFile.getFieldName()+"<BR>");
out.println("Size="+myFile.getSize()+"<BR>");
out.println("FileName="+myFile.getFileName()+"<BR>");
out.println("FileExt="+myFile.getFileExt()+"<BR>");
out.println("FilePathName="+myFile.getFilePathName()+"<BR>");
out.println("ContentType="+myFile.getContentType()+"<BR>");
out.println("ContentDisp="+myFile.getContentDisp()+"<BR>");
out.println("TypeMIME="+myFile.getTypeMIME()+"<BR>");
out.println("SubTypeMIME="+myFile.getSubTypeMIME()+"<BR>");
count++;
}
}
//昄应该上的文件数?br /> out.println("<BR>"+mySmartUpload.getFiles().getCount()+"file could be uploaded.<BR>");
//昄成功上传的文件数?br /> out.println(count+"file(s) upload.");
%>
</body>
</html>
downlload.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body>
<h2>文g下蝲</h2>
<jsp:useBean id="mySmartUpload" scope="page" class="com.jspsmart.upload.SmartUpload"/>
<%
//SmartUpload的初始化
mySmartUpload.initialize(pageContext);
//必须如此声明Q否则将会把文g昄与浏览器?br /> mySmartUpload.setContentDisposition("inline;");
//sample.zip下蝲 下蝲默认名称为download.zip
mySmartUpload.downloadFile("C:\\upload\\aa.txt","application/x-zip-compressed","downloaded.zip");
%>
</body>
</html>
<FORM METHOD="POST" ENCTYPE="multipart/form-data" ACTION="/jspSmartUpload/upload.jsp"> <INPUT TYPE="FILE" NAME="MYFILE"> <INPUT TYPE="SUBMIT"> </FORM>上传+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
<% // 新徏一个SmartUpload对象 SmartUpload su = new SmartUpload(); // 上传初始? su.initialize(pageContext); // 讑֮上传限制 // 1.限制每个上传文g的最大长度? // su.setMaxFileSize(10000); // 2.限制M传数据的长度? // su.setTotalMaxFileSize(20000); // 3.讑֮允许上传的文Ӟ通过扩展名限Ӟ,仅允许doc,txt文g? // su.setAllowedFilesList("doc,txt"); // 4.讑֮止上传的文Ӟ通过扩展名限Ӟ,止上传带有exe,bat, jsp,htm,html扩展名的文g和没有扩展名的文件? // su.setDeniedFilesList("exe,bat,jsp,htm,html,,"); // 上传文g su.upload(); // 上传文件全部保存到指定目录 int count = su.save("/upload"); out.下蝲+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
<%@ page contentType="text/html;charset=gb2312" import="com.jspsmart.upload.*" %><% // 新徏一个SmartUpload对象 SmartUpload su = new SmartUpload(); // 初始? su.initialize(pageContext); // 讑֮contentDisposition为null以禁止浏览器自动打开文gQ? //保证点击链接后是下蝲文g。若不设定,则下载的文g扩展名ؓ //docӞ览器将自动用word打开它。扩展名为pdfӞ //览器将用acrobat打开? su.setContentDisposition(null); // 下蝲文g su.downloadFile("/upload/如何赚取我的W一桉.doc"); %>下蝲 中文处理+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public void downloadFile(String s, String s1, String s2, int i) throws ServletException, IOException, SmartUploadException { if(s == null) throw new IllegalArgumentException("File '" + s + "' not found (1040)."); if(s.equals("")) throw new IllegalArgumentException("File '" + s + "' not found (1040)."); if(!isVirtual(s) && m_denyPhysicalPath) throw new SecurityException("Physical path is denied (1035)."); if(isVirtual(s)) s = m_application.getRealPath(s); java.io.File file = new java.io.File(s); FileInputStream fileinputstream = new FileInputStream(file); long l = file.length(); boolean flag = false; int k = 0; byte abyte0[] = new byte[i]; if(s1 == null) m_response.setContentType("application/x-msdownload"); else if(s1.length() == 0) m_response.setContentType("application/x-msdownload"); else m_response.setContentType(s1); m_response.setContentLength((int)l); m_contentDisposition = m_contentDisposition != null ? m_contentDisposition : "attachment;"; if(s2 == null) m_response.setHeader("Content-Disposition", m_contentDisposition + " filename=" + toUtf8String(getFileName(s))); else if(s2.length() == 0) m_response.setHeader("Content-Disposition", m_contentDisposition); else m_response.setHeader("Content-Disposition", m_contentDisposition + " filename=" + toUtf8String(s2)); while((long)k < l) { int j = fileinputstream.read(abyte0, 0, i); k += j; m_response.getOutputStream().write(abyte0, 0, j); } fileinputstream.close(); } /** * 文件名中的汉字转ؓUTF8~码的串,以便下蝲时能正确昄另存的文件名. * U|软g制作中心雨亦?003.08.01 * @param s 原文件名 * @return 重新~码后的文g? */ public static String toUtf8String(String s) { StringBuffer sb = new StringBuffer(); for (int i=0;i<s.length();i++) { char c = s.charAt(i); if (c >= 0 && c <= 255) { sb.append(c); } else { byte[] b; try { b = Character.toString(c).getBytes("utf-8"); } catch (Exception ex) { System.out.println(ex); b = new byte[0]; } for (int j = 0; j < b.length; j++) { int k = b[j]; if (k < 0) k += 256; sb.append("%" + Integer.toHexString(k). toUpperCase()); } } } return sb.toString(); }+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++