??xml version="1.0" encoding="utf-8" standalone="yes"?> 1.字符"a"-"z"Q?A"-"Z"Q?0"-"9"Q?."Q?-"Q?*"Q和"_" 都不会被~码; URLEncodercd含将字符串{换ؓapplication/x-www-form-urlencoded MIME 格式的静态方法?/p>
web设计者面临的众多N之一便是怎样处理不同操作pȝ间的差异性。这些差异性能引vURL斚w的问题:例如Q一些操作系l允许文件名中含有空格符Q有些又不允许。大多数操作pȝ不会认ؓ文g名中含有W号“#”会有什么特D含义;但是在一个URL中,W号“#”表示该文件名已经l束Q后面会紧跟一个fragmentQ部分)标识W。其他的Ҏ字符Q非字母数字字符集,它们在URL或另一个操作系l上都有其特D的含义Q表q着怼的问题。ؓ了解册些问题,我们在URL中用的字符必L一个ASCII字符集的固定字集中的元素Q具体如下: cURLq不自动执行~码或解码工作。你能生成一个URL对象Q它可以包括非法的ASCII和非ASCII字符??xx。当用方法getPath() 和toExternalForm( ) 作ؓ输出ҎӞq种字符和{Uȝ不会自动~码或解码。你应对被用来生成一个URL对象的字W串对象负责Q确保所有字W都会被恰当地编码?br />
下面是它的输出。需要注意的是这些代码应该以其他~码形式被保存而不是以ASCII码的形式Q还有就是你选择的编码Ş式应该作Z个参Cl编译器Q让~译器能据此Ҏ代码中的非ASCII字符作出正确的解释?br />
q篇文章来自一个研Iƈ提供信息架构的网站:Information Architects JapanQ原文:Web design is 95% typography. 又及Q文章多ơ出现typographyq个单词。正规的中文译应该?#8220;排印”Q但考虑webq个非印刷媒体,使用排印q不见得好。于是我Ҏ语境Q有时用“排版”Q有时用“排印”Q请读者明鉴。以下是译正文?/p>
web中的信息?5%是成文的语言。ؓ何web设计师应该好好学习一下设计成文信息的主要准则Q换句话_排版Q这是最佳的理由?/p>
回到1969q_Emil Ruder, 一个瑞士著名的排印大师Q其W下关于当时的印h_直就是我们今天网站的写照Q?/p>
今天印刷术的泛滥成灾让我们的个h价D轻视Q因为郁L我们现在q不能掌控印刷中的一切。分剌Ӏ组l和实现印刷术的一切是排印师应有的dQ只有这P读者才有更好的Z扑և吸引她/他的东西?/p>
E微联想一下(L在线排版取代印刷Q,q就像是信息设计师的职务描述?strong>分割、组l和实现印刷术的一切是“信息设计?#8221;应有的Q务,只有q样Q读者才有更好的Z扑և吸引她/他的东西?/strong>宏观排版Q所有的文本l构Q跟微观排版Q样式和I间的细节方面)包括我们今天UCؓ“信息设计”的很多方面。也是_信息设计师今天正在做排印?0q前的工作: 排版面一个很直白的职责,q就是传达信息。没有理p免除排版的这一职责。一个ƈ不能阅读的印刷品只能变成一个无用的产品?/p>
优化排版是优化阅读Q亲和力Q可用性(Q)Q综合文本^衡等。组l文本块q结合图片,N不是囑Ş设计师、可用性专家、信息架构师应该做的吗?但ؓ什么这是一个被忽视的主题呢Q?/p>
主要原因——抱怨连天的——不看好在线排版准则的观ҎQ能用的字太了。第二个观点是屏q分辨率太低Q让像素或者反锯字体之一很难阅读?/p>
认ؓ我们没有_的字体可用的观点是不切题的:在意大利文艺复兴时期Q排印师只有一个字体可用,但这个时期还是生一些顶U漂亮的排版品: 该排印师应该没有太在意他手中手能掌握的字体种c,实际上也不应该太在意字体的选择。他应该更关心时代能赋予自己手中掌握的,q尽力发挥?/p>
W二个观点也q不见得好到哪儿厅R在印刷初期Q印出来的字母质量比我们今天在显C器上看到的更差。更重要的是Q如果处理得专业Q屏q字体更易于阅读。信息设计不是关于用好的字P而是关于使用好的排版。两者的区别很大。谁都可以用字P有h可以选择好的字样Q但只有数够精通排版?/p>
对,不同q_和不同浏览器如何处理字体是恼人的Q也对,分L率问题很难让注意力集中坚持到五分钟的。但是,好啦Q确保文本在所有主要^台和览器中赏心悦目是web设计师的职责。正的行间距,单词和字母间距,留白Q一定量颜色的用有助于可读性。但q不d。一个优U的web设计师知道如何跟文本而不仅仅是内Ҏ交道Q?a >“把文本当作用L?#8221;。瞧?a >Kohi Vinh的网?/a>Q你大概会明白他的意思: E微著名把文本当作用L面的unornamental|站例子有: google, ebay, craigslist, youtube, flickr, Digg, reddit, delicious. 一个难以争辩的必然事实是,把文本当作用L面是成功的唯一参数。成功的|站设法同时创徏单的界面和强烈的特征。但q是另外一个主题了?/p>
String enUft = URLEncoder.encode("q东省福利彩开奖信息网", "UTF-8");
System.out.println(enUft);
java.net.URLDecoder urlDecoder = new java.net.URLDecoder();
String s = urlDecoder.decode(enUft,"UTF-8");
System.out.println(s);
} catch (Exception e) {
e.printStackTrace();
}
try {
String enUft = URLEncoder.encode("q东省福利彩开奖信息网", "GB2312");
System.out.println(enUft);
java.net.URLDecoder urlDecoder = new java.net.URLDecoder();
String s = urlDecoder.decode(enUft,"GB2312");
System.out.println(s);
} catch (Exception e) {
e.printStackTrace();
}
try {
String enUft = URLEncoder.encode("q东省福利彩开奖信息网", "UTF-8");
System.out.println(enUft);
java.net.URLDecoder urlDecoder = new java.net.URLDecoder();
String s = urlDecoder.decode(enUft,"GB2312");
System.out.println(s);
} catch (Exception e) {
e.printStackTrace();
}
l果:
%E5%B9%BF%E4%B8%9C%E7%9C%81%E7%A6%8F%E5%88%A9%E5%BD%A9%E7%A5%A8%E5%BC%80%E5%A5%96%E4%BF%A1%E6%81%AF%E7%BD%91
q东省福利彩开奖信息网
%B9%E3%B6%AB%CA%A1%B8%A3%C0%FB%B2%CA%C6%B1%BF%AA%BD%B1%D0%C5%CF%A2%CD%F8
q东省福利彩开奖信息网
%E5%B9%BF%E4%B8%9C%E7%9C%81%E7%A6%8F%E5%88%A9%E5%BD%A9%E7%A5%A8%E5%BC%80%E5%A5%96%E4%BF%A1%E6%81%AF%E7%BD%91
骞夸?????l???╁僵lㄥ???淇℃??~?
/*
|页中的表单使用POSTҎ提交Ӟ数据内容的类型是 application/x-www-form-urlencodedQ这U类型会Q?
2.空D{换ؓ加号 (+) ;
3.非文本内容转换?%xy"的Ş?xy?span class="commentform">两位16q制的数?/span>;
4.在每?name=value 对之间放|?& W号?br />
*/
1.大写字母A-Z
2.写字母a-z
3.数字 0-9
4.标点W?- _ . ! ~ * ' (?,)
诸如字符: / & ? @ # ; $ + = ?%也可以被使用Q但是它们各有其Ҏ的用途,如果一个文件名包括了这些字W( / & ? @ # ; $ + = %Q,q些字符和所有其他字W就应该被编码?br />
~码q程非常单,M字符只要不是ASCII码数字,字母Q或者前面提到的标点W,它们都将被{换成字节形式Q每个字节都写成q种形式Q一?#8220;%”后面跟着两位16q制的数倹{空格是一个特D情况,因ؓ它们太^怺。它除了被编码成“%20”以外Q还能编码ؓ一?#8220;+”。加P+Q本w被~码?2B。当/ # = & ?作ؓ名字的一部分来用时Q而不是作为URL部分之间的分隔符来用时Q它们都应该被编码?br />
WARNINGq种{略在存在大量字W集的异构环境中效果不甚理想。例如:在U.S. Windows pȝ? é 被编码ؓ %E9. ?U.S. Mac中被~码?8E。这U不定性的存在是现存的URI的一个明昄不。所以在来URI的规范当中应该通过国际资源标识W?IRIs)q行改善?br />
q运的是Qjava提供了一个类URLEncoder把string~码成这UŞ式。Java1.2增加了一个类URLDecoder它能以这UŞ式解码string。这两个c都不用初始化:
public class URLDecoder extends Object
public class URLEncoder extends Object
一、URLEncoder
在java1.3和早期版本中Q类java.net.URLEncoder包括一个简单的静态方法encode( )Q?它对string以如下规则进行编码:
public static String encode(String s)
q个ҎL用它所在^台的默认~码形式Q所以在不同pȝ上,它就会生不同的l果。结果java1.4中,q个Ҏ被另一U方法取代了。该Ҏ要求你自己指定编码Ş式:
public static String encode(String s, String encoding) throws UnsupportedEncodingException
两种关于~码的方法,都把M非字母数字字W{换成%xxQ除了空|下划U?_)Q连字符Q?Q?句号Q。),和星P*Q)。两者也都编码所以的非ASCII字符。空D转换成一个加受这些方法有一点过分篏赘了Q它们也?#8220;~”Q?#8220;‘”Q?#8220;Q)”转换?xxQ即使它们完全用不着q样做。尽这P但是q种转换q没被URL规范所止。所以web览器会自然地处理这些被q分~码后的URL?br />
两中关于~码的方法都q回一个新的被~码后的stringQjava1.3的方法encode( ) 使用了^台的默认~码形式Q得?xx。这些编码Ş式典型的有:?U.S. Unix pȝ上的ISO-8859-1, 在U.S. Windows pȝ上的Cp1252,在U.S. Macs上的MacRomanQ和其他本地字符集等。因为编码解码过E都是与本地操作q_相关的,所以这些方法是令h不爽的,不能跨^台的?br />
q就明确地回{了Z么在java1.4中这U方法被抛弃了,转而投向了要求以自己指定编码Ş式的q种Ҏ。尽如此,如果你执意要使用所在^台的默认~码形式Q你的程序将会像在java1.3中的E序一P是本地^台相关的。在另一U编码的Ҏ中,你应该L用UTF-8Q而不是其他什么。UTF-8比v你选的其他的编码Ş式来_它能与新的web览器和更多的其他Y件相兼容?br />
例子7-8是用URLEncoder.encode( ) 来打印输出各U被~码后的string。它需要在java1.4或更新的版本中编译和q行?br />
Example 7-8. x-www-form-urlencoded strings
% javac -encoding UTF8 EncoderTest %
java EncoderTest
This+string+has+spaces
This*string*has*asterisks
This%25string%25has%25percent%25signs
This%2Bstring%2Bhas%2Bpluses
This%2Fstring%2Fhas%2Fslashes
This%22string%22has%22quote%22marks
This%3Astring%3Ahas%3Acolons
This%7Estring%7Ehas%7Etildes
This%28string%29has%28parentheses%29
This.string.has.periods
This%3Dstring%3Dhas%3Dequals%3Dsigns
This%26string%26has%26ampersands
This%C3%A9string%C3%A9has%C3%A9non-ASCII+characters
特别需要注意的是这个方法编码了W号Q?#8220;\” ,&,=,和:。它不会试着去规定在一个URL中这些字W怎样被用。由此,所以你不得不分块编码你的URL,而不是把整个URL一ơ传l这个方法。这是很重要的,因ؓ对类URLEncoder最通常的用法就是查询stringQؓ了和服务器端使用GETҎ的程序进行交互。例如,假设你想~码q个查询stingQ它用来搜烦AltaVista|站Q?br />
pg=q&kl=XX&stype=stext&q=+"Java+I/O"&search.x=38&search.y=3
q段代码对其q行~码Q?br />
String query = URLEncoder.encode( "pg=q&kl=XX&stype=stext&q=+\"Java+I/O\"&search.x=38&search.y=3");System.out.println(query);
不幸的是Q得到的输出?
pg%3Dq%26kl%3DXX%26stype%3Dstext%26q%3D%2B%22Java%2BI%2FO%22%26search.x%3D38%26search.y%3D3
出现q个问题是ҎURLEncoder.encode( ) 在进行盲目地~码。它不能区分在URL或者查询string中被用到的特D字W(象前面string中的“Q?#8221;Q和“&”Q和实需要被~码的字W。由此,所以URL需要像下面q样一ơ只~码一块:
String query = URLEncoder.encode("pg");
query += "=";
query += URLEncoder.encode("q");
query += "&";
query += URLEncoder.encode("kl");
query += "=";
query += URLEncoder.encode("XX");
query += "&";
query += URLEncoder.encode("stype");
query += "=";
query += URLEncoder.encode("stext");
query += "&";
query += URLEncoder.encode("q");
query += "=";
query += URLEncoder.encode("\"Java I/O\"");
query += "&";
query += URLEncoder.encode("search.x");
query += "=";
query += URLEncoder.encode("38");
query += "&";
query += URLEncoder.encode("search.y");
query += "=";
query += URLEncoder.encode("3");
System.out.println(query);
q才是你真正惛_到的输出Q?br />
pg=q&kl=XX&stype=stext&q=%2B%22Java+I%2FO%22&search.x=38&search.y=3
例子7-9是一个QueryStringcR在一个java对象中,它用了cURLEncoder来编码连l的属性名和属性值对Q这个java对象被用来发送数据到服务器端的程序?br />
当你在创Z个QueryString对象Ӟ你可以把查询string中的W一个属性对传递给cQueryString的构造函敎ͼ得到初始string。如果要l箋加入后面的属性对Q就应调用方法addQ)Q它也能接受两个string作ؓ参数Q能对它们进行编码。方法getQuery( )q回一个属性对被逐个~码后得到的整个string?br />
Example 7-9. -The QueryString class
package com.macfaq.net;
import java.net.URLEncoder;
import java.io.UnsupportedEncodingException;
public class QueryString {
private StringBuffer query = new StringBuffer();
public QueryString(String name, String value) {
encode(name, value);
}
public synchronized void add(String name, String value) {
query.append('&');
encode(name, value);
}
private synchronized void encode(String name, String value) {
try {
query.append(URLEncoder.encode(name, "UTF-8"));
query.append('=');
query.append(URLEncoder.encode(value, "UTF-8"));
} catch (UnsupportedEncodingException ex) {
throw new RuntimeException("Broken VM does not support UTF-8");
}
}
public String getQuery() {
return query.toString();
}
public String toString() {
return getQuery();
}
}
利用q个c,现在我们p对前面那个例子中的stringq行~码?
QueryString qs = new QueryString("pg", "q");
qs.add("kl", "XX");
qs.add("stype", "stext");
qs.add("q", "+\"Java I/O\"");
qs.add("search.x", "38");
qs.add("search.y", "3");
String url = "http://www.altavista.com/cgi-bin/query?" + qs;
System.out.println(url);
二、URLDecoder
与URLEncoder cȝ对应的URLDecoder cL两种静态方法。它们解码以x-www-form-url-encodedq种形式~码的string。也是_它们把所有的加号Q?Q{换成I格W,把所有的%xx分别转换成与之相对应的字W:
public static String decode(String s) throws Exception
public static String decode(String s, String encoding) // Java 1.4 throws UnsupportedEncodingException
W一U解码方法在java1.3和java1.2中用。第二种解码Ҏ在java1.4和更新的版本中用。如果你拿不定主意用哪种~码方式Q那选择UTF-8吧。它比其他Q何的~码形式更有可能得到正确的结果?br />
如果string包含了一?#8220;%”Q但紧跟其后的不是两?6q制的数或者被解码成非法序列,该方法就会抛出IllegalArgumentException 异常。当下次再出现这U情冉|Q它可能׃会被抛出了。这是与q行环境相关的,当检查到有非法序列时Q抛不抛出IllegalArgumentException 异常Q这时到底会发生什么是不确定的。在Sun's JDK 1.4中,不会抛出什么异常,它会把一些莫名其妙的字节加进不能被顺利编码的string中。这的确令h头疼Q可能就是一个安全漏z?br />
׃q个Ҏ没有触及到非转义字符Q所以你可以把整个URL作ؓ参数传给该方法,不用像之前那样分块进行。例如:
String input = "http://www.altavista.com/cgi-bin/" + "query?pg=q&kl=XX&stype=stext&q=%2B%22Java+I%2FO%22&search.x=38&search.y=3";
try {
String output = URLDecoder.decode(input, "UTF-8");
System.out.println(output);
}import java.net.URLEncoder;
import java.net.URLDecoder;
import java.io.UnsupportedEncodingException;
public class EncoderTest {
public static void main(String[] args) {
try {
System.out.println(URLEncoder.encode("This string has spaces","UTF-8"));
System.out.println(URLEncoder.encode("This*string*has*asterisks","UTF-8"));
System.out.println(URLEncoder.encode("This%string%has%percent%signs", "UTF-8"));
System.out.println(URLEncoder.encode("This+string+has+pluses","UTF-8"));
System.out.println(URLEncoder.encode("This/string/has/slashes","UTF-8"));
System.out.println(URLEncoder.encode("This\"string\"has\"quote\"marks", "UTF-8"));
System.out.println(URLEncoder.encode("This:string:has:colons","UTF-8"));
System.out.println(URLEncoder.encode("This~string~has~tildes","UTF-8"));
System.out.println(URLEncoder.encode("This(string)has(parentheses)", "UTF-8"));
System.out.println(URLEncoder.encode("This.string.has.periods","UTF-8"));
System.out.println(URLEncoder.encode("This=string=has=equals=signs", "UTF-8"));
System.out.println(URLEncoder.encode("This&string&has&ersands","UTF-8"));
System.out.println(URLEncoder.encode("Thiséstringéhasé non-ASCII characters","UTF-8"));
// System.out.println(URLEncoder.encode("this中华人民共和?,"UTF-8"));
} catch (UnsupportedEncodingException ex) {throw new RuntimeException("Broken VM does not support UTF-8");
}
}
}
]]>
import javax.servlet.http.*;
public class SessionCounter implements HttpSessionListener {
private static int activeSessions = 0;
public void sessionCreated(HttpSessionEvent se) {
activeSessions++;
}
public void sessionDestroyed(HttpSessionEvent se) {
if(activeSessions > 0)
activeSessions--;
}
public static int getActiveSessions() {
return activeSessions;
}
}
然后配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
****************************************
<!-- Listeners -->
<listener>
<listener-class>
SessionCount.SessionCounter (注意此处)
</listener-class>
</listener>
*****************************************
</web-app>
ZJSP试:
test.jsp
<%@ page language="Java" contentType="text/html;charset=GBK"%>
<%@ page import="java.sql.*"%>
<%@ page import="SessionCount.SessionCounter" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GBK">
<title>无标题文?lt;/title>
<body bgcolor="#FFFFFF">
在线人数:<%=SessionCounter.getActiveSessions()%>
</body>
</html>
看看可以实现?我也是找到的,我用?可以l计出来.
]]>信息设计是排版
信息设计师是21世纪的排版师
Z么这是一个被忽视的主题?
字体太少Q分辨率低?
文艺复兴Q只有一个字?/h4>
选择字样q不是排?/h4>
把文本当作用L?/h4>
从哪开?/h3>
]]>
jsp文g上传大多采用采用开源项目来化处理,q里列出常用的两个jar包的实现Qƈq行比较Q说明他们的优缺点和应该注意的问题?/p>
Commons FileUploadQ可以在http://jakarta.apache.org/commons/fileupload/下蝲Q这个包需要Commons IO的支持,可以?a >http://jakarta.apache.org/commons/io/下蝲
com.oreilly.servletQ可以在http://www.servlets.com/cos/下蝲
Commons FileUpload提供三种文g上传处理方式QDiskFileUpload、ServletFileUpload和PortletFileUpload三种方式Q其中DiskFileUpload已经在javadoc下已l被标记期的ҎQ徏议用ServletFileUpload代替Q而PortletFileUpload需要配合portlet-api来用,所以这里我们只介绍ServletFileUploadQƈ且这个也是最常用的?/p>
com.oreilly.servlet也提供了三种文g上传的处理方式,MultipartWrapper、MultipartRequest和MultipartParser三种方式Q其中MultipartWrapper和MultipartRequest的用法基本相同,q且没有MultipartRequest提供的操作多Q所以这里介lMultipartRequestQMultipartParser和前两者有些不同,可以用来处理某些Ҏ情况Q例如表单中有两个同名的文g上传选择框?/p>
我们暂时UC面三U文件上传方式分别ؓQServletFileUpload方式QMultipartTestServletQ、MultipartRequest方式QMultipartTestServlet2Q、MultipartParser方式QMultipartTestServlet3Q?/p>
代码如下Q?br /> test.html
<%@ page language="java" import="java.util.*" contentType="text/html;charset=gbk" pageEncoding="gbk"%>
<html>
<body>
<form action="MultipartTestServlet" enctype="multipart/form-data" method="post">
<input type="text" name="username" /><br />
<input type="file" name="myfile" /><br/>
<input type="file" name="myfile" /><br/>
<input type="submit" />
</form>
<br/><br/><br/><br/>
<form action="MultipartTestServlet2" enctype="multipart/form-data" method="post">
<input type="text" name="username" /><br />
<input type="file" name="myfile" /><br/>
<input type="file" name="myfile" /><br/>
<input type="submit" />
</form>
<br/><br/><br/><br/>
<form action="MultipartTestServlet3" enctype="multipart/form-data" method="post">
<input type="text" name="username" /><br />
<input type="file" name="myfile" /><br/>
<input type="file" name="myfile" /><br/>
<input type="submit" />
</form>
</body>
</html>
MultipartTestServlet.java
package com.bug.servlet;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
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.FileUpload;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.RequestContext;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.servlet.ServletRequestContext;
public class MultipartTestServlet extends HttpServlet {
public MultipartTestServlet() {
super();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("gbk");
RequestContext requestContext = new ServletRequestContext(request);
if(FileUpload.isMultipartContent(requestContext)){
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setRepository(new File("c:/tmp/"));
ServletFileUpload upload = new ServletFileUpload(factory);
//upload.setHeaderEncoding("gbk");
upload.setSizeMax(2000000);
List items = new ArrayList();
try {
items = upload.parseRequest(request);
} catch (FileUploadException e1) {
System.out.println("文g上传发生错误" + e1.getMessage());
}
Iterator it = items.iterator();
while(it.hasNext()){
FileItem fileItem = (FileItem) it.next();
if(fileItem.isFormField()){
System.out.println(fileItem.getFieldName() + " " + fileItem.getName() + " " + new String(fileItem.getString().getBytes("iso8859-1"), "gbk"));
}else{
System.out.println(fileItem.getFieldName() + " " +
fileItem.getName() + " " +
fileItem.isInMemory() + " " +
fileItem.getContentType() + " " +
fileItem.getSize());
if(fileItem.getName()!=null && fileItem.getSize()!=0){
File fullFile = new File(fileItem.getName());
File newFile = new File("c:/temp/" + fullFile.getName());
try {
fileItem.write(newFile);
} catch (Exception e) {
e.printStackTrace();
}
}else{
System.out.println("文g没有选择 ?文g内容为空");
}
}
}
}
}
}
MultipartTestServlet2.java
package com.bug.servlet;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;
public class MultipartTestServlet2 extends HttpServlet {
public MultipartTestServlet2() {
super();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//request.setCharacterEncoding("gbk"); 不v作用
System.out.println("start ");
MultipartRequest multi = new MultipartRequest(request, "c:/tmp/", 2*1024*1024, "gbk", new DefaultFileRenamePolicy());
System.out.println("start ");
Enumeration filesName = multi.getFileNames();
Enumeration paramsName = multi.getParameterNames();
while(paramsName.hasMoreElements()){
String paramName = (String) paramsName.nextElement();
System.out.println(multi.getParameter(paramName));
}
while(filesName.hasMoreElements()){
String fileName = (String) filesName.nextElement();
System.out.println(multi.getFilesystemName(fileName) + " " +
multi.getOriginalFileName(fileName) + " " +
multi.getContentType(fileName) + " ");
if(multi.getFilesystemName(fileName)!=null && !multi.getFilesystemName(fileName).equals(""))
System.out.println(multi.getFile(fileName).toURI());
}
}
}
MultipartTestServlet3.java
package com.bug.servlet;
import java.io.File;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.oreilly.servlet.multipart.FilePart;
import com.oreilly.servlet.multipart.MultipartParser;
import com.oreilly.servlet.multipart.ParamPart;
import com.oreilly.servlet.multipart.Part;
public class MultipartTestServlet3 extends HttpServlet {
public MultipartTestServlet3() {
super();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
MultipartParser mp = new MultipartParser(request, 2*1024*1024, false, false, "gbk");
Part part;
while ((part = mp.readNextPart()) != null) {
String name = part.getName();
if (part.isParam()) {
ParamPart paramPart = (ParamPart) part;
String value = paramPart.getStringValue();
System.out.println("param: name=" + name + "; value=" + value);
}
else if (part.isFile()) {
// it's a file part
FilePart filePart = (FilePart) part;
String fileName = filePart.getFileName();
if (fileName != null) {
long size = filePart.writeTo(new File("c:/tmp/"));
System.out.println("file: name=" + name + "; fileName=" + fileName +
", filePath=" + filePart.getFilePath() +
", contentType=" + filePart.getContentType() +
", size=" + size);
}
else {
System.out.println("file: name=" + name + "; EMPTY");
}
System.out.flush();
}
}
}
}
web.xml中加?/p>
<servlet>
<servlet-name>MultipartTestServlet</servlet-name>
<servlet-class>com.bug.servlet.MultipartTestServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>MultipartTestServlet2</servlet-name>
<servlet-class>com.bug.servlet.MultipartTestServlet2</servlet-class>
</servlet>
<servlet>
<servlet-name>MultipartTestServlet3</servlet-name>
<servlet-class>com.bug.servlet.MultipartTestServlet3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MultipartTestServlet</servlet-name>
<url-pattern>/MultipartTestServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>MultipartTestServlet2</servlet-name>
<url-pattern>/MultipartTestServlet2</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>MultipartTestServlet3</servlet-name>
<url-pattern>/MultipartTestServlet3</url-pattern>
</servlet-mapping>
我用q第一个例子的:
<!--注意:
1.当利用ServletUpload?lt;input type="radio" checked="checked">的元素会被认为是文g元素<input type="file">
从而会被解析出几个IFile出来
2.当用在struts的action?action的name不要讄,否则解析不出文g控g存在.因ؓactionform之前被解析掉?
-->
问题1、中文问题:
三种凡是都可以通过自己的方法来讄encoding为gbk开处理和解决中文问题,包括初始化的时候传入gbk作ؓ参数Q或是是初始化后通过setEncoding的方式来实现?br />
另外ServletFileUpload方式也可以通过request.setCharacterEncoding("gbk");的方式来实现Q而其它两U方式不支持q种方式?/p>
问题2、文件大限?br />
ServletFileUpload方式可以讄文g大小限制Q也可以不用讄Q例子中的upload.setSizeMax(2000000)可以注释掉。如果设|upload.setSizeMax(-1)Q表明不限制上传的大。文档中没有指明默认的限制的多少Q我在不讄的情况下上传了一?M的东西,可以上传Q估计默认是不限制大的?br />
而MultipartRequest方式和MultipartParser方式是必设|文件的上传文g的大限制的Q如果不讄Q默认是1M的大限制?/p>
问题3、文件上传发生错?br />
如果文g上传q程中发生Q何错误,或者是文g的大超Z范围Q系l都抛出错误?br />
ServletFileUpload方式在upload.parseRequest(request)时抛出错?br />
MultipartRequest方式在new MultipartRequest(。。?时抛出错?br />
MultipartParser方式在new MultipartParser(。。?时抛出错?/p>
问题4、上传同名文件时Q他们保存到临时目录是的冲突问题
ServletFileUpload方式Q不会有冲突Q系l会把上传得文g按照一定的规则重新命名Q保证不会冲H?br />
MultipartParser方式Q会产生冲突Q系l会把文件按照上传时的文件名Q保存到临时目录下,如果两个用会同时上传文g名相同的文gQ那么就可能会生冲H,一Ҏ另一方的临时文gl替换了?br />
MultipartRequest方式Q在初始化时如果提供了一个名U{换策略,׃会有冲突Q如果不提桶Q就会有冲突。在上面的例子中我们提供了一个new DefaultFileRenamePolicy()保证了文件名不会有冲H发生?/p>
问题5Q表单中有两个同名的文g上传选择框,像我们例子中的myfile一P每个表单中有两个name=“myfile”的上传框
ServletFileUpload方式Q可以处理,可以分别得到他们各自的文Ӟ
MultipartRequest方式Q不可以处理Q会发生冲突Q会有一个上传框的文件覆盖了另外一个?br />
MultipartParser方式Q可以处理,可以分别得到他们各自的文Ӟ
备注Q?br />
代码比较乱,主要是ؓ了说明他们间的区别。他们的详细C用说明还是要参考他的javadoc和domo?/p>
参考:
1?a >http://www.servlets.com/cos/#classes
2?a >http://jakarta.apache.org/commons/fileupload/apidocs/index.html
3?a >http://jakarta.apache.org/commons/fileupload/using.html
4?a >http://www.onjava.com/pub/a/onjava/2003/06/25/commons.html?page=3
最q一直在搞FCKeditor在线文本~辑器的裁剪和集成,ȝ了自q一?
心得体会Q跟大家分n一下自ql验Q?
1.jsp/java中引用FCKeditor步骤和具体做法,参见如下的链接:
a.jsp面集成调用说明Q?nbsp; b.后台览和上传功能集成指?/font>Q?
注意点:配置好jsp面集成FCKeditor的javascrīpt调用以后Q页面将?
昄如下的样子:
面上相应的代码如下Q?
<scrīpt type="text/javascrīpt" src="FCKeditor/fckeditor.js"></scrīpt> |
<textarea name="content" cols="80" rows="4"> </textarea> <scrīpt type="text/javascrīpt"> var ōFCKeditor = new FCKeditor('content') ; oFCKeditor.BasePath = "FCKeditor/"; oFCKeditor.Height = 400; oFCKeditor.ToolbarSet = "Default" ; oFCKeditor.ReplaceTextarea(); </scrīpt> |
如果是要想从数据库读来的文本数据或者是后台来自文g的txt/html
文本数据。只要在
<textarea name="content" cols="80" rows="4"> </textarea> |
中加入自q昄内容的formbean对应字段卛_
<textarea name="content" cols="80" rows="4"> <c:out value="${ contentData}" /> |
q样内容׃被显C在FCKeditor~辑框中了,点击提交按钮以后可?
在后台的相应java action中得到content参数中的内容是面?
FCKeditor中的内容数据了。可以在struts/jsf做用的哦?
要提醒一点的是由于你lFCKeditor瘦nQ所以常会报~少对象支持
{错误,只要在FCKeditor/editor/lang中加上相应的js语言文g卛_
如果加蝲面p|Q?font color=#ff0000>FCKeditor未定?/font>Q还有一个可能就是引?
FCKeditor/fckeditor.js文g路径不对Q关于FCKeditor瘦n可以
参考网上文?我还是摘一些要点从|上Q?
1?/strong>FCKeditor目录下及子目录下所有以”_”下划U开 头的文g夹删?/font>
fckeditor.js, fckstyles.xml, fcktemplates.xml
其余全部删除
清空.
default一套皮肤(如果你不需要换皮肤的话Q?/font>
en.js, fcklanguagemanager.js, zh-cn.js, zh.js
文g
6.如果你是使用javascrīpt来调用加载FCKeditorQ那?/font>
׃需要在web.xml中配|fckeditor的tag文g?/font>
7.q有一个问题刚开始用FCKeditor的h怼遇到
怎么控制它的toolbar的大和元素排列Q其实很单?/font>
在fckconfig.js中用使用q样的标{[]来划分每行的
元素的多,q样可以控制toolbar的长短和大小了,
具体CZ参看Qfckconfig.js中的toolbarset
["Default"] |
2.下面再说说fckconfig.js中的一些选项来控制toolbarset中的控g
的功能,实现功能裁剪Q?
1):取消链接中的浏览服务器和上传功能,Ҏ如下Q?
FCKConfig.LinkBrowser = true ; FCKConfig.LinkUpload = true ; 改ؓ FCKConfig.LinkBrowser = false ; FCKConfig.LinkUpload = false ; |
2Q:取消囄链接中的览服务器和上传功能Q方法如下:
FCKConfig.ImageUpload = true ; FCKConfig.ImageBrowser = true ; 改ؓ FCKConfig.ImageUpload = false ; FCKConfig.ImageBrowser = false ; |
3):Dlg Button中取消高U功能,Ҏ如下Q?
FCKConfig.LinkDlgHideAdvanced = false ; FCKConfig.ImageDlgHideAdvanced = false ; 改ؓ FCKConfig.ImageDlgHideAdvanced = true ; FCKConfig.LinkDlgHideTarget = true ; |
下一介lFCKeditor的上传和览服务器功能,以及如何在里面实现动?
连接,转发到servletl过filter以后去调用服务器的action
如何实现对应用户览自己的图片的列表实现Q?
FCKeditor集成java servlet可以实现文g的上传和服务器端列表d?
能FCKeditor自己提供了两个servlet来分别实C传文件功能,和读取服
务器端文件列表功能,q两个servlet分别为:
com.fredck.FCKeditor.connector.ConnectorServletQ读取文件列
表)com.fredck.FCKeditor.uploader.SimpleUploaderServletQ实
?/font>文g上传Q?/font>
1.览服务器端文g列表
web.xml文g中,比如ConnectorServlet?/font>?/font>配置选项Q?
意思在览服务器上的baseDir配置指定里面的所有文件极其目录结构列?
如果你的baseDir没有配置QConnector会自动创徏一个默认的文g?
userFilesQ对应的ConnectorServlet中init()Ҏ中代码如下:
q想说一下的是,FCKeditor的client调用server的servletҎ采用
的是Ajax思想来实现。当你点L览服务器(browser server)的时?
׃触发一个异步的javascrīpt + xmlhttp的调用响应,后台的servlet
会去完成你要h的事Ӟ然后数据以xml方式q回lclient来解析?
很明显,你要实现L据库或者其他的文gpȝh列表Q你只要修改
ConnectorServlet中两个私有方法:getFolders ?getFiles
让它M指定的地方得到文件列表即可,q样你的文g可以攑֜M?
指定目录下。多说一句,很多人都想知道个人blogpȝ中怎么实现上传
文g以后对应用户览自己的列表的Q我的做法很单,建立你用户名
的文件夹Q你上传只能上传C的目录夹Q浏览可以通过E序指定览
对应用户下的文g夹即可,q个时候你要修改Connectorservlet中的
路径卛_Q?
2.连接重定位问题
FCKeditor可以插入连接,实现Ҏ件的预览功能Q只要我们稍微改?
我们可以使FCKeditor~辑器支持对L文gpȝ下的L文g的客L
览和下载保存!FCKeditor本来提供的是相对URL连接,只要我们修改
ConnectorServlet中传递给客户端的地址的时候,把它改写成绝对URL
然后再通过我们自己的filter的servlet实现重定向去一个下?览
文g的struts的actionҎ可以实现在客户端对连接文件的下蝲?
览Q说一下具体做法吧Q?
1):修改ConnectorServlet传递给客户端javascrīpt的\径,代码如下
String currentUrl= "http://" + request.getserver +request.getServerPort + request.getContextPath +resourcePath;
以上代码请在ConnectorServlet的doGet()里面DQ在
调用CreateCommonXmlQ)U有Ҏ的时候参C?/font>
myEl.setAttribute("path",currentPath); 提醒一?font color=#0000ff>resourcePath 的一个初始化参数配置Q等一下利用filter实现对超q接的重定位提?
URL中的q个配置参数来判断,配置如下Q?
<init-param> 2Q:建立你的filter servletQ实现对URL的截P对符合要求的
URLq行重定位到你的对应action中去卛_
3Q:实现你的对应action来实现文件的上传和下载功能即可!
4Q:扩展功能Q实现对URL的加密,对连接的URL中加上一串字W,最?
几位作ؓ法校验Q对不符合要求的URLq接,filter会拒绝重定位到
指定action。此外利用自己写的扩展类q可以实现对连接的文gcd
q行限制Q比如你只能连接JPG|GIF|DOC|TXT|HTML{几U后~名的
文gQ对其他文g即你指定超q接也让你浏览和下蝲Q这些都可以?
web.xml中通过修改对应servlet的配|文件的初始化参数实现?
3.面javascrīpt修改
览服务器的功能对应的html/javascrīpt相关的文件ؓQbrowser.html
和frmresourcelist.html对应你想传递的信息你可以append在文件名?
字符串后面,?font color=#ff0000>GetFileRowHtmlQ) 名的截取Q这样client只会昄文g名,而你可以得到文g的数据库唯一
标识QQ何你惌的信息你都可以通过修改ConnectorServlet中的U有
ҎgetFiles()来实玎ͼ只要修改面frmresurcelist.html中的
GetFileRowHtmlQ)中传入变?font color=#ff0000>fileName卛_。你q可以在点击选中 文g的时候实C个你自己的Ajax调用Q一切取决你的项目需要!
4.我不是一个javascrīpt高手Q其实如果我对javascrīpt了解多一?
也许对客L的代码修改以后做出更眩的功能。可以更好的完成?
FCKeditor裁剪。我q发C个问题,是FCKeditor2.3自己提供?
textarea控g一直不能获得输入焦点,接受文字输入Q如果有高手知道
怎么修改javascrīpt修复q个bugQ请也回复我Q?
5.注意?/font>
无论怎么修改别h的东西,请一定尊重开源精!
很多人配|好了FCKeditor的上传功能以后常会遇到xmlhttp request
404 error,后面是一串\径,其实是你的servlet-mapping中的路径
不对Q你只要把xmlhttp request errot 404 后面跟的路径Qcopy?
你的web.xml中对应红色文字的位置Q如下:
<servlet-mapping> /FCKeditor/editor/filemanager/browser/default/connectors/jsp/connector
</url-pattern>
</servlet-mapping> 别忘?font color=#ff0000>SimpleUploader的servletQmapping q有一个错误就是http 500错误Q这个可能是你的URLh不对Q应该和
FCKeditor没关pȝ!
<init-param>
<param-name>baseDir</param-name>
<param-value>/UserFiles/</param-value>
</init-param>
baseDir=getInitParameter("baseDir");
if(baseDir==null)
baseDir="/UserFiles/";
myEl.setAttribute("url",currentUrl);
<param-name>resourcePath</param-name>
<param-value>/fileSystem/</param-value>
</init-param>
<servlet-name>Connector</servlet-name>
<url-pattern>
二、服务端的输出缓冲区
~省情况?服务端要输出到客L的内?不直接写到客L,而是先写C个输出缓冲区?只有在下面三中情况下Q才会把该缓冲区的内容输出到客户端上Q?br />
三、服务端输出重定?/p>
有以?U方法可以做到输出重定向:
说明Q?br />1. Ҏ(1),(2)可以使用变量表示重定向的地址;Ҏ(3)不能使用变量表示重定向的地址?br />String add="./index.html";
<jsp:forward page= add />
无法重定向到index.html中去
String add=http://localhost:7001/index.html
response.sendRedirect(add);
可以重定向到http://localhost:7001/index.html中去?
2. 采用Ҏ(1),(2)request中的变量(通过request.setAttribute()保存到request中的?不能在新的页面中采用,采用Ҏ(3)? lg,我们应该采用(1),(2)重定向比较好.
四、JSP中正应用类:
应该把类当成JAVA BEAN来用Q不要在<% %> 中直接? 如下的代?1)l过JSP引擎转化后会变ؓ代码(2):
从中可看出如果把一个类在JSP当成JAVA BEAN 使用,JSP会根据它的作用范围把它保存到相应的内部对象中.
如作用范围ؓrequest,则把它保存到request对象?q且只在W一ơ调?对象的gؓnull)它时q行实例? 而如果在<% %>中直接创cȝ一个对?则每ơ调用JSP?都要重新创徏该对?会媄响性能.
代码(1)
<jsp:useBean id="test" scope="request" class="demo.com.testdemo">
</jsp:useBean>
<%
test.print("this is use java bean");
testdemo td= new testdemo();
td.print("this is use new");
%>
代码(2)
demo.com.testdemo test = (demo.com.testdemo)request.getAttribute("test");
if (test == null)
{
try
{
test = (demo.com.testdemo) java.beans.Beans.instantiate(getClass().getClassLoader(),"demo.com.testdemo");
}
catch (Exception _beanException)
{
throw new weblogic.utils.NestedRuntimeException("cannot instantiate 'demo.com.testdemo'",_beanException);
}
request.setAttribute("test", test);
out.print("\r\n");
}
out.print("\r\n\r\n\r\n");
test.print("this is use java bean");
testdemo td= new testdemo();
td.print("this is use new");
五、JSP的调?
JSP的调试比较麻?特别是当bean是在一个session中存在时Q更加困难。得从好几个面开始往里面走才行。通常是用out.println()或System.out.print()来打一大堆的信息来查问题。如果是用jbuilder做开?它能直接调试JSP.不过更重要的是知道错误生的原因及解x法。下面对一些JSP~程常见错误q行分析?
(1).java.lang.NullPointerException异常
一般是对一个ؓNULL值的变量q行操作引v?如下面的操作׃抛出
java.lang.NullPointerException
String a = null;
a.substring(0,1);
为避免这U异常最好在对变量操作之前检查看它是否ؓNULL??
<% String ss=Session.getAttribute("NAME")
if isnull(ss)
{
}
else
{
}
%>
(2).JSP是用JAVA写的Q所以它是大写敏感的,用过其他~程语言的h最Ҏ犯这个错误。另外在览器的地址栏中输入的访问JSP的地址也是区分大小写的.如http://localhost:7001/demo/t.jsp与http://localhost:7001/Demo/t.jsp是不一L
(3).在jsp中判断字W串要用compareToҎQ不要用==Q因为在java中String变量不是一个简单的变量而是一个类实例Q不同的Ҏ会得?不同的结果,如下所C:
(4)防止JSP或SERVLET中的输出被浏览器保存在缓冲区?
览器在默认情况下会把浏览过的网保存在~冲Z,在调试时,一般不希望q样.把下面的脚本加入E序?可防止JSP或SERVLET中的输出被浏览器保存在缓冲区?
<%
response.setHeader("Cache-Control","no-store"); //HTTP 1.1
response.setHeader("Pragma","no-cache"); //HTTP 1.0
response.setDateHeader ("Expires", 0); //prevents caching at the proxy server
%>
在IE中也可通过讄实现Q把/工具/INTERNET选项/常规/讄/的检察所存页面的较新版本,设ؓ每次讉K该页旉?
六、COOKIE
HTTP COOKIE实质是服务端与在客户端之间传送的普通HTTP?可保存也可不保存在客L盘?如果保存,每一个文件大不过4K的文本文?多个COOKIE可保存到同一个文件中. 如果从编E角度来?在JSP中COOKIE是JAVA提供的一个类.常用的方法如下所表示Q因为客L可能不接受COOKIEQ所以徏议不用它Q改用SESSION{其他方式?
如何查一个客L是否支持COOKIE的方?
用下面的Ҏ写一个COOKIE到客L,q确认成?
try
{
Cookie c = new Cookie("mycookie","COOKIE TEST");
response.addCookie(c);
}
catch(Exception e)
{
System.out.println(e);
}
然后在一个新的JSP文g?用下面的Ҏ取客L的COOKIE到cookies? 如果cookies.length ==0,说明该客L的浏览器不支持COOKIE
try
{
Cookie[] cookies = request.getCookies();
if(cookies.length ==0)
{
System.out.println("not support cookie");
}
}
catch(Exception e)
{
System.out.println(e);
}
七、JSP和SERVLET的区?
SUN首先发展出SERVLETQ其功能比较强劲Q体p设计也很先q,只是Q它输出HTML语句q是采用了老的CGI方式Q是一句一句输出,所以,~写和修改HTML非常不方ѝ?后来SUN推出了类gASP的JSPQ把JAVA代码嵌套到HTML语句中,q样Q就大大化和方便了网늚设计和修攏VASPQPHPQJSP都是嵌套型的SCRIPT语言?一个分布式pȝ应分Z层:表示?业务逻辑?数据存取?在J2EE体系l构?SERVLET用来写业务逻辑层是很强大的Q但是对于写表示层就很不方便。JSP则主要是Z方便写表C层而设计的。ENTITY BEAN实现数据存取层,SESSION BEAN实现业务逻辑层。如果是单的应用pȝ,可采用JSP+BEANS的结构进行设?JSP中应该仅仅存放与表示层有关的东西Q也是_只放输出HTML|页的部份。而所有的数据计算Q数据分析,数据库联l处理,l统是属于业务逻辑层,应该攑֜JAVA BEANS中。通过JSP调用JAVA BEANSQ实C层的整合?实际上,微Y的DNA技术,单说Q就是ASP+COM/DCOM技术。与JSP+BEANS完全cMQ所有的表示层由ASP完成Q所有的业务逻辑由COM/DCOM完成?Z么要采用q些lg技术呢Q因为单U的ASP/JSP语言是非怽效率执行的,如果出现大量用户点击Q纯SCRIPT语言很快到达了他的功能上限Q而组件技术就能大q度提高功能上限Q加快执行速度。另外一斚wQ纯SCRIPT语言表C层和业务逻辑层在一P造成修改不方便,q且代码不能重复利用Q采用组件技术就只改lg可以了?对于复杂的应用,应该采用ENTITY BEAN实现数据存取层,SESSION BEAN实现业务逻辑层,用JSP来调用SESSION BEANQ由SESSION BEAN调用ENTITY BEAN。即采用JSP+EJB来构Z个复杂的分布式系l。它比JSP+BEANh更高的吞吐量Q可靠性,安全性。综上所qͼ对简单应用,可采用JSP+BAENQ对复杂的应用系l,应采用JSP+EJBQSERVLET变的无轻重。用JSP完全可替代它?