| 巍 的个人资料fantasyswall照片日志列表 | 帮助 |
|
fantasyswall一颗沙子的天地 2月24日 spring 源码Spring源代码解析(一):IOC容器:http://www.javaeye.com/topic/86339 Spring源代码解析(二):IoC容器在Web容器中的启动:http://www.javaeye.com/topic/86594 Spring源代码解析(三):Spring JDBC:http://www.javaeye.com/topic/87034 Spring源代码解析(四):Spring MVC:http://www.javaeye.com/topic/87692 Spring源代码解析(五):Spring AOP获取Proxy:http://www.javaeye.com/topic/88187 Spring源代码解析(六):Spring声明式事务处理:http://www.javaeye.com/topic/88189 Spring源代码解析(七):Spring AOP中对拦截器调用的实现:http://www.javaeye.com/topic/107785 Spring源代码解析(八):Spring驱动Hibernate的实现:http://www.javaeye.com/topic/110801 Spring源代码解析(九):Spring Acegi框架鉴权的实现:http://www.javaeye.com/topic/112979 Spring源代码解析(十):Spring Acegi框架授权的实现:http://www.javaeye.com/topic/113436 10月28日 webwork 值栈
9月25日 Apache Jakarta Commons 工具集简介[转]Apache Jakarta Commons 工具集简介[转] Apache Commons包含了很多开源的工具,用于解决平时编程经常会遇到的问题,减少重复劳动。我选了一些比较常用的项目做简单介绍。文中用了很多网上现成的东西,我只是做了一个汇总整理。 一、Commons BeanUtils http://jakarta.apache.org/commons/beanutils/index.html 说明:针对Bean的一个工具集。由于Bean往往是有一堆get和set组成,所以BeanUtils也是在此基础上进行一些包装。 使用示例:功能有很多,网站上有详细介绍。一个比较常用的功能是Bean Copy,也就是copy bean的属性。如果做分层架构开发的话就会用到,比如从PO(Persistent Object)拷贝数据到VO(Value Object)。 传统方法如下: //得到TeacherForm TeacherForm teacherForm=(TeacherForm)form; //构造Teacher对象 Teacher teacher=new Teacher(); //赋值 teacher.setName(teacherForm.getName()); teacher.setAge(teacherForm.getAge()); teacher.setGender(teacherForm.getGender()); teacher.setMajor(teacherForm.getMajor()); teacher.setDepartment(teacherForm.getDepartment()); //持久化Teacher对象到数据库 HibernateDAO= ; HibernateDAO.save(teacher); 使用BeanUtils后,代码就大大改观了,如下所示: //得到TeacherForm TeacherForm teacherForm=(TeacherForm)form; //构造Teacher对象 Teacher teacher=new Teacher(); //赋值 BeanUtils.copyProperties(teacher,teacherForm); //持久化Teacher对象到数据库 HibernateDAO= ; HibernateDAO.save(teacher); 二、Commons CLI http://jakarta.apache.org/commons/cli/index.html 说明:这是一个处理命令的工具。比如main方法输入的string[]需要解析。你可以预先定义好参数的规则,然后就可以调用CLI来解析。 使用示例: // create Options object Options options = new Options(); // add t option, option is the command parameter, false indicates that // this parameter is not required. options.addOption(“t”, false, “display current time”); options.addOption("c", true, "country code"); CommandLineParser parser = new PosixParser(); CommandLine cmd = parser.parse( options, args); if(cmd.hasOption("t")) { // print the date and time }else { // print the date } // get c option value String countryCode = cmd.getOptionValue("c"); if(countryCode == null) { // print default date }else { // print date for country specified by countryCode } 三、Commons Codec http://jakarta.apache.org/commons/codec/index.html 说明:这个工具是用来编码和解码的,包括Base64,URL,Soundx等等。用这个工具的人应该很清楚这些,我就不多介绍了。 四、Commons Collections http://jakarta.apache.org/commons/collections/ 说明:你可以把这个工具看成是java.util的扩展。 使用示例:举一个简单的例子 OrderedMap map = new LinkedMap(); map.put("FIVE", "5"); map.put("SIX", "6"); map.put("SEVEN", "7"); map.firstKey(); // returns "FIVE" map.nextKey("FIVE"); // returns "SIX" map.nextKey("SIX"); // returns "SEVEN" 五、Commons Configuration http://jakarta.apache.org/commons/configuration/ 说明:这个工具是用来帮助处理配置文件的,支持很多种存储方式 1. Properties files 2. XML documents 3. Property list files (.plist) 4. JNDI 5. JDBC Datasource 6. System properties 7. Applet parameters 8. Servlet parameters 使用示例:举一个Properties的简单例子 # usergui.properties, definining the GUI, colors.background = #FFFFFF colors.foreground = #000080 window.width = 500 window.height = 300 PropertiesConfiguration config = new PropertiesConfiguration("usergui.properties"); config.setProperty("colors.background", "#000000); config.save(); config.save("usergui.backup.properties);//save a copy Integer integer = config.getInteger("window.width"); 六、Commons DBCP http://jakarta.apache.org/commons/dbcp/ 例子: import java.sql.*; import com.gwnet.games.antiLord.util.*; import org.apache.commons.dbcp.ConnectionFactory; import org.apache.commons.dbcp.BasicDataSource; import org.apache.commons.dbcp.DataSourceConnectionFactory; private static BasicDataSource bds=new BasicDataSource(); private static ConnectionFactory fac=null; //初始化连接池 bds.setDriverClassName(“org.postgresql.Driver”); //数据库驱动程序 bds.setUrl(“jdbc:postgresql://localhost:5432/myDB”); //数据库url bds.setUsername(“postgres”); //dba帐号 bds.setPassword(“XXXXXXXX”); //密码 bds.setInitialSize(100); //初始化连接数量 bds.setMaxIdle(10); //最大idle数 bds.setMaxWait(1000*60); //超时回收时间 fac=new DataSourceConnectionFactory(bds); //得到连接工厂 Connection conn=fac.createConnection(); //从池中获得连接 conn.close(); //释放连接,回到池中 //销毁连接池 bds.close(); bds=null; fac=null; 七、Commons DbUtils http://jakarta.apache.org/commons/dbutils/ 说明:我以前在写数据库程序的时候,往往把数据库操作单独做一个包。DbUtils就是这样一个工具,以后开发不用再重复这样的工作了。值得一体的是,这个工具并不是现在流行的OR-Mapping工具(比如Hibernate),只是简化数据库操作,比如 QueryRunner run = new QueryRunner(dataSource); // Execute the query and get the results back from the handler Object[] result = (Object[]) run.query("SELECT * FROM Person WHERE name=?", "John Doe"); 八、Commons FileUpload http://jakarta.apache.org/commons/fileupload/ 说明:jsp的上传文件功能怎么做呢? 使用示例: // Create a factory for disk-based file items FileItemFactory factory = new DiskFileItemFactory(); // Create a new file upload handler ServletFileUpload upload = new ServletFileUpload(factory); // Parse the request List /* FileItem */ items = upload.parseRequest(request); // Process the uploaded items Iterator iter = items.iterator(); while (iter.hasNext()) { FileItem item = (FileItem) iter.next(); if (item.isFormField()) { processFormField(item); } else { processUploadedFile(item); } } 九、Commons HttpClient http://jakarta.apache.org/commons/httpclient/ 说明:这个工具可以方便通过编程的方式去访问网站。 使用示例:最简单的Get操作 GetMethod get = new GetMethod("http://jakarta.apache.org"); // execute method and handle any error responses. ... InputStream in = get.getResponseBodyAsStream(); // Process the data from the input stream. get.releaseConnection(); 十、Commons IO http://jakarta.apache.org/commons/io/ 说明:可以看成是java.io的扩展,我觉得用起来非常方便。 使用示例: 1.读取Stream 标准代码: InputStream in = new URL( "http://jakarta.apache.org" ).openStream(); try { InputStreamReader inR = new InputStreamReader( in ); BufferedReader buf = new BufferedReader( inR ); String line; while ( ( line = buf.readLine() ) != null ) { System.out.println( line ); } } finally { in.close(); } 使用IOUtils InputStream in = new URL( "http://jakarta.apache.org" ).openStream(); try { System.out.println( IOUtils.toString( in ) ); } finally { IOUtils.closeQuietly(in); } 2.读取文件 File file = new File("/commons/io/project.properties"); List lines = FileUtils.readLines(file, "UTF-8"); 3.察看剩余空间 long freeSpace = FileSystemUtils.freeSpace("C:/"); 十一、Commons JXPath http://jakarta.apache.org/commons/jxpath/ 说明:Xpath你知道吧,那么JXpath就是基于Java对象的Xpath,也就是用Xpath对Java对象进行查询。这个东西还是很有想像力的。 使用示例: Address address = (Address)JXPathContext.newContext(vendor). getValue("locations[address/zipCode='90210']/address"); 上述代码等同于 Address address = null; Collection locations = vendor.getLocations(); Iterator it = locations.iterator(); while (it.hasNext()){ Location location = (Location)it.next(); String zipCode = location.getAddress().getZipCode(); if (zipCode.equals("90210")){ address = location.getAddress(); break; } } 十二、Commons Lang http://jakarta.apache.org/commons/lang/ 说明:这个工具包可以看成是对java.lang的扩展。提供了诸如StringUtils, StringEscapeUtils, RandomStringUtils, Tokenizer, WordUtils等工具类。 十三、Commons Logging http://jakarta.apache.org/commons/logging/ 说明:你知道Log4j吗? 十四、Commons Math http://jakarta.apache.org/commons/math/ 说明:看名字你就应该知道这个包是用来干嘛的了吧。这个包提供的功能有些和Commons Lang重复了,但是这个包更专注于做数学工具,功能更强大。 十五、Commons Net http://jakarta.apache.org/commons/net/ 说明:这个包还是很实用的,封装了很多网络协议。 1. FTP 2. NNTP 3. SMTP 4. POP3 5. Telnet 6. TFTP 7. Finger 8. Whois 9. rexec/rcmd/rlogin 10. Time (rdate) and Daytime 11. Echo 12. Discard 13. NTP/SNTP 使用示例: TelnetClient telnet = new TelnetClient(); telnet.connect( "192.168.1.99", 23 ); InputStream in = telnet.getInputStream(); PrintStream out = new PrintStream( telnet.getOutputStream() ); ... telnet.close(); 十六、Commons Validator http://jakarta.apache.org/commons/validator/ 说明:用来帮助进行验证的工具。比如验证Email字符串,日期字符串等是否合法。 使用示例: // Get the Date validator DateValidator validator = DateValidator.getInstance(); // Validate/Convert the date Date fooDate = validator.validate(fooString, "dd/MM/yyyy"); if (fooDate == null) { // error...not a valid date return; } 十七、Commons Virtual File System http://jakarta.apache.org/commons/vfs/ 说明:提供对各种资源的访问接口。支持的资源类型包括 1. CIFS 2. FTP 3. Local Files 4. HTTP and HTTPS 5. SFTP 6. Temporary Files 7. WebDAV 8. Zip, Jar and Tar (uncompressed, tgz or tbz2) 9. gzip and bzip2 10. res 11. ram 这个包的功能很强大,极大的简化了程序对资源的访问。 使用示例: 从jar中读取文件 // Locate the Jar file FileSystemManager fsManager = VFS.getManager(); FileObject jarFile = fsManager.resolveFile( "jar:lib/aJarFile.jar" ); // List the children of the Jar file FileObject[] children = jarFile.getChildren(); System.out.println( "Children of " + jarFile.getName().getURI() ); for ( int i = 0; i < children.length; i++ ){ System.out.println( children[ i ].getName().getBaseName() ); } 从smb读取文件 StaticUserAuthenticator auth = new StaticUserAuthenticator("username", "password", null); FileSystemOptions opts = new FileSystemOptions(); DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(opts, auth); FileObject fo = VFS.getManager().resolveFile("smb://host/anyshare/dir", opts); 十八、Commons-Email commons-email是apache提供的一个开源的API,是对javamail的封装,因此在使用时要将javamail.jar加到 class path中,主要包括SimpleEmail,MultiPartEmail,HtmlEmail,EmailAttachment四个类。 SimpleEmail:发送简单的email,不能添加附件 MultiPartEmail:文本邮件,可以添加多个附件 HtmlEmail:HTML格式邮件,同时具有MultiPartEmail类所有“功能” EmailAttchment:附件类,可以添加本地资源,也可以指定网络上资源,在发送时自动将网络上资源下载发送。 发送基本文本格式邮件: ============== SimpleEmail email = new SimpleEmail(); //smtp host email.setHostName("mail.test.com"); //登陆邮件服务器的用户名和密码 email.setAuthentication("test","testpassword"); //接收人 email.addTo("jdoe@somewhere.org", "John Doe"); //发送人 email.setFrom("me@apache.org", "Me"); //标题 email.setSubject("Test message"); //邮件内容 email.setMsg("This is a simple test of commons-email"); //发送 email.send(); 发送文本格式,带附件邮件: ================== //附件,可以定义多个附件对象 EmailAttachment attachment = new EmailAttachment(); attachment.setPath("e:\\1.pdf"); attachment.setDisposition(EmailAttachment.ATTACHMENT); attachment.setDescription("Picture of John"); // MultiPartEmail email = new MultiPartEmail(); //smtp host email.setHostName("mail.test.com"); //登陆邮件服务器的用户名和密码 email.setAuthentication("test","testpassword"); //接收人 email.addTo("jdoe@somewhere.org", "John Doe"); //发送人 email.setFrom("me@apache.org", "Me"); //标题 email.setSubject("Test message"); //邮件内容 email.setMsg("This is a simple test of commons-email"); //添加附件 email.attach(attachment); //发送 email.send(); 发送HTML格式带附件邮件: ================= //附件,可以定义多个附件对象 EmailAttachment attachment = new EmailAttachment(); attachment.setPath("e:\\1.pdf"); attachment.setDisposition(EmailAttachment.ATTACHMENT); attachment.setDescription("Picture of John"); // HtmlEmail email = new HtmlEmail (); //smtp host email.setHostName("mail.test.com"); //登陆邮件服务器的用户名和密码 email.setAuthentication("test","testpassword"); //接收人 email.addTo("jdoe@somewhere.org", "John Doe"); //发送人 email.setFrom("me@apache.org", "Me"); //标题 email.setSubject("Test message"); //邮件内容 email.setHtmlMsg("This is a simple test of commons-email"); //添加附件 email.attach(attachment); //发送 十九、 Commons Pool 使用Jakarta Commons Pool可以根据需要快速的实现自己的对象池,只需要实现PoolableObjectFactory或者 KeyedPoolableObjectFactory接口。KeyedPoolableObjectFactory和 PoolableObjectFactory的不同之处在于KeyedPoolableObjectFactory的每个方法都比 PoolableObjectFactory多了一个Object key的参数,使用这个参数可以使得对象池中的每个对象都有所不同。 PoolableObjectFactory定义了五个方法(摘至Jakarta Commons Pool API文档): 1. makeObject is called whenever a new instance is needed. 2. activateObject is invoked on every instance before it is returned from the pool. 3. passivateObject is invoked on every instance when it is returned to the pool. 4. destroyObject is invoked on every instance when it is being "dropped" from the pool (whether due to the response from validateObject, or for reasons specific to the pool implementation.) 5. validateObject is invoked in an implementation-specific fashion to determine if an instance is still valid to be returned by the pool. It will only be invoked on an "activated" instance. 二十、Commons Digester 它能方便地将XML文档所定义的元素转化为JAVA对象,其实它的用法有点象栈(当然内在的原理就是那个古老的东西,只是提供了更高一层的封装)。 //生成一个digester。主要需要引进commons-logging.jar、commons-collections.jar、commons- beanutils.jar Digester digester = new Digester(); //设置对XML文档资料是否进行DTD验证 digester.setValidating( false ); //当遇见 catalog 元素的时候,产生一个Catalog对象 digester.addObjectCreate( "catalog", Catalog.class ); //当遇见 catalog 元素下面的book的时候,产生一个Book对象 digester.addObjectCreate( "catalog/book", Book.class ); // 当遇见 catalog 元素下面的book的author时候,调用author属性的Set方法 digester.addBeanPropertySetter( "catalog/book/author", "author" ); digester.addBeanPropertySetter( "catalog/book/title", "title" ); //当再一次遇见 catalog 元素下面的book的时候,调用catalog类的addBook()方法 digester.addSetNext( "catalog/book", "addBook" ); digester.addObjectCreate( "catalog/magazine", Magazine.class ); digester.addBeanPropertySetter( "catalog/magazine/name", "name" ); digester.addObjectCreate( "catalog/magazine/article", Article.class ); //addSetProperties()是将对应元素的属性赋值。 digester.addSetProperties( "catalog/magazine/article", "page", "page" ); digester.addBeanPropertySetter( "catalog/magazine/article/headline" ); digester.addSetNext( "catalog/magazine/article", "addArticle" ); digester.addSetNext( "catalog/magazine", "addMagazine" ); //"F:\\Digester\\catalog.xml"为XML文档 File input = new File( "F:\\Digester\\catalog.xml" ); Catalog c = (Catalog)digester.parse( input ); System.out.println( c.toString() ); 6月13日 send request only once if(str.indexOf("Referer: ")!=-1){
String[] strs = str.split("\r\n"); for(String temp:strs){ if(temp.indexOf("Referer: ")!=-1){ if(!referer.equals(temp)){ referer = temp; System.out.println("++++++++++++++++++++++++++++++++++"); } } } } 5月30日 HtmlBrowserpackage com.test.hello; import java.io.IOException; public class HtmlBrowser extends JFrame { public HtmlBrowser() { // 定义构造方法 private void jbInit() throws Exception { // 界面初始化 void textFieldURL_actionPerformed(ActionEvent e) { // 输入地址后响应回车 void jEditorPane_hyperlinkUpdate(HyperlinkEvent e) { // 响应页面打开超链接消息 protected void processWindowEvent(WindowEvent e) { // 处理窗体事件 public static void main(String[] args) { // Main函数 5月23日 java client for httppackage com.test.hello;
import java.net.*;
import java.io.*; import java.util.Properties; import java.util.Enumeration; /** Http客户端程序已集成在Java语言中,可以通过URLConnection类调用。遗憾的 是,由于SUN没有公布Http客户程序的源码,它实现的细节仍是一个谜。本文根据HTTP 协议规范,用Java.net.Socket类实现一个HTTP协议客户端程序. <pre> 1.Socket类: 了解TCP/IP协议集通信的读者知道,协议间的通信是通过Socket完成的。在 Java.net包中,Socket类就是对Socket的具体实现。它通过连接到主机后,返回一个 I/O流,实现协议间的信息交换。 2 . HTTP协议 HTTP协议同其它TCP/IP协议集中的协议一样,是遵循客户/服务器模型工作的。客 户端发往服务端的信息格式如下: ------------------------------ 请求方法 URL HTTP协议的版本号 提交的元信息 **空行** 实体 ------------------------------ 请求方法是对这次连接工作的说明,目前HTTP协议已经发展到1.1版,它包括GET、 HEAD、POST、DELETE、OPTIONS、TRACE、PUT七种。元信息是关于当前请求的信息。通 过分析元信息,可以检查实体数据是否完整,接收过程是否出错,类型是否匹配等。元 信息的引入使HTTP协议通信更加稳妥可靠。实体是请求的具体内容。 将上述报文发往Web服务器,如果成功,应答格式如下: -------------------------------- HTTP协议的版本号 应答状态码 应答状态码说明 接收的元信息 **空行** 实体 -------------------------------- 以上报文发向客户端,并且接收成功,彼此间关闭连接,完成一次握手。 下面用最常用的GET方法,来说明具体的报文应用 ---------------------------------- GET http://www.youhost.com HTTP/1.0 accept: www/source; text/html; image/gif; image/jpeg; */* User_Agent: myAgent **空行** ----------------------------------- 这个报文是向www.youhost.com主机请求一个缺省HTML文档。客户端HTTP协议版本 号是1.0版,元信息包括可接收的文件格式,用户代理,每一段之间用回车换行符分 隔,最后以一个空行结束。发向服务器后,如果执行过程正常,服务器返回以下代码: ------------------------------------ HTTP/1.1 200 OK Date: Tue, 14 Sep 1999 02:19:57 GMT Server: Apache/1.2.6 Connection: close Content-Type: text/html **空行** <html><head>...</head><body>...</body></html> ------------------------------------ HTTP/1.1表示这个HTTP服务器是1.1版,200是服务器对客户请求的应答状态码,OK 是对应答状态码的解释,之后是这个文档的元信息和文档正文。(相关应答状态码和元 信息的解释请参阅Inetrnet标准草案:RFC2616)。 注: 程序中只实现GET、HEAD、POST三种方法。其他几种因不常使用,暂且忽略。 </pre> */ import java.net.*; import java.io.*;
import java.util.Properties;
import java.util.Enumeration;
/** Http客户端程序已集成在Java语言中,可以通过URLConnection类调用。遗憾的
是,由于SUN没有公布Http客户程序的源码,它实现的细节仍是一个谜。本文根据HTTP
协议规范,用Java.net.Socket类实现一个HTTP协议客户端程序.
<pre> 1.Socket类: 了解TCP/IP协议集通信的读者知道,协议间的通信是通过Socket完成的。在
Java.net包中,Socket类就是对Socket的具体实现。它通过连接到主机后,返回一个
I/O流,实现协议间的信息交换。
2 . HTTP协议 HTTP协议同其它TCP/IP协议集中的协议一样,是遵循客户/服务器模型工作的。客
户端发往服务端的信息格式如下:
------------------------------
请求方法 URL HTTP协议的版本号
提交的元信息
**空行**
实体
------------------------------
请求方法是对这次连接工作的说明,目前HTTP协议已经发展到1.1版,它包括GET、
HEAD、POST、DELETE、OPTIONS、TRACE、PUT七种。元信息是关于当前请求的信息。通
过分析元信息,可以检查实体数据是否完整,接收过程是否出错,类型是否匹配等。元
信息的引入使HTTP协议通信更加稳妥可靠。实体是请求的具体内容。
将上述报文发往Web服务器,如果成功,应答格式如下:
--------------------------------
HTTP协议的版本号 应答状态码 应答状态码说明
接收的元信息
**空行**
实体
--------------------------------
以上报文发向客户端,并且接收成功,彼此间关闭连接,完成一次握手。
下面用最常用的GET方法,来说明具体的报文应用
----------------------------------
GET http://www.youhost.com HTTP/1.0
accept: www/source; text/html; image/gif; image/jpeg; */*
User_Agent: myAgent
**空行**
-----------------------------------
这个报文是向www.youhost.com主机请求一个缺省HTML文档。客户端HTTP协议版本
号是1.0版,元信息包括可接收的文件格式,用户代理,每一段之间用回车换行符分
隔,最后以一个空行结束。发向服务器后,如果执行过程正常,服务器返回以下代码:
------------------------------------
HTTP/1.1 200 OK
Date: Tue, 14 Sep 1999 02:19:57 GMT
Server: Apache/1.2.6
Connection: close
Content-Type: text/html
**空行**
<html><head>...</head><body>...</body></html>
------------------------------------
HTTP/1.1表示这个HTTP服务器是1.1版,200是服务器对客户请求的应答状态码,OK
是对应答状态码的解释,之后是这个文档的元信息和文档正文。(相关应答状态码和元
信息的解释请参阅Inetrnet标准草案:RFC2616)。
注: 程序中只实现GET、HEAD、POST三种方法。其他几种因不常使用,暂且忽略。 </pre> */ public class Http{
protected Socket client;
protected BufferedOutputStream sender;
protected BufferedInputStream receiver;
protected ByteArrayInputStream byteStream;
protected URL target;
private int responseCode = -1;
private String responseMessage = "";
private String serverVersion = "";
private Properties header = new Properties();
public Http(){} public Http(String url){ GET(url);
}
public static void main(String[] args){
Http http = new Http("http://localhost:8080/test/index.html"); System.out.println(http.getResponseMessage()); } /* GET方法根据URL,会请求文件、数据库查询结果、程序运行结果等多种内容 */
public void GET(String url){
try{
checkHTTP(url);
openServer(target.getHost(),target.getPort());
String cmd = "GET " + getURLFormat(target) + " HTTP/1.0\r\n" +
getBaseHeads() + "\r\n";
sendMessage(cmd);
receiveMessage();
}
catch(ProtocolException p){
p.printStackTrace();
return;
}
catch(UnknownHostException e){
e.printStackTrace();
return;
}
catch(IOException i){
i.printStackTrace();
return;
}
}
/* * HEAD方法只请求URL的元信息,不包括URL本身。若怀疑本机和服务器上的
* 文件相同,用这个方法检查最快捷有效。
*/
public void HEAD(String url){
try{
checkHTTP(url);
openServer(target.getHost(),target.getPort());
String cmd = "HEAD " + getURLFormat(target) + " HTTP/1.0\r\n" +
getBaseHeads() + "\r\n";
sendMessage(cmd);
receiveMessage();
}
catch(ProtocolException p){
p.printStackTrace();
return;
}
catch(UnknownHostException e){
e.printStackTrace();
return;
}
catch(IOException i){
i.printStackTrace();
return;
}
}
/* * POST方法是向服务器传送数据,以便服务器做出相应的处理。例如网页上常用的
* 提交表格。
*/
public void POST(String url,String content){
try{
checkHTTP(url);
openServer(target.getHost(),target.getPort());
String cmd = "POST " + getURLFormat(target) + " HTTP/1.0\r\n" +
getBaseHeads();
cmd += "Content-type: application/x-www-form-urlencoded\r\n";
cmd += "Content-length: " + content.length() + "\r\n\r\n";
cmd += content + "\r\n";
sendMessage(cmd);
receiveMessage();
}
catch(ProtocolException p){
p.printStackTrace();
return ;
}
catch(UnknownHostException e){
e.printStackTrace();
return ;
}
catch(IOException i){
i.printStackTrace();
return ;
}
} protected void checkHTTP(String url) throws ProtocolException{ try{
URL target = new URL(url);
if(target == null ||
!target.getProtocol().toUpperCase().equals("HTTP")){
throw new ProtocolException("这不是HTTP协议");
}
this.target = target;
}
catch(MalformedURLException m){
throw new ProtocolException("协议格式错误");
}
}
/* * 与Web服务器连接。若找不到Web服务器,InetAddress会引发UnknownHostException
* 异常。若Socket连接失败,会引发IOException异常。
*/
protected void openServer(String host,int port) throws UnknownHostException,
IOException{
header.clear();
responseMessage = "";
responseCode = -1;
if(client != null){ closeServer();
}
if(byteStream != null){
byteStream.close();
byteStream = null;
}
InetAddress address = InetAddress.getByName(host); client = new Socket(address,port == -1 ? 80 : port);
client.setSoTimeout(5000);
sender = new BufferedOutputStream(client.getOutputStream());
receiver = new BufferedInputStream(client.getInputStream());
}
/* 关闭与Web服务器的连接 */ protected void closeServer() throws IOException{
if(client == null){
return;
}
try{
client.close();
sender.close();
receiver.close();
}
catch(IOException i){
throw i;
}
client = null; sender = null;
receiver = null;
}
protected String getURLFormat(URL target){ String spec = "http://" + target.getHost();
if(target.getPort() != -1){
spec += ":" + target.getPort();
}
return spec += target.getFile(); }
/* 向Web服务器传送数据 */ protected void sendMessage(String data) throws IOException{
sender.write(data.getBytes(),0,data.length());
sender.flush();
}
/* 接收来自Web服务器的数据 */ protected void receiveMessage() throws IOException{
byte data[] = new byte[1024]; int count = 0; int word = -1; // 解析第一行 while( (word = receiver.read()) != -1){ if(word == '\r' || word == '\n'){ word = receiver.read(); if(word == '\n') { word = receiver.read(); } break; } if(count == data.length) { data = addCapacity(data); } data[count++] = (byte) word; } String message = new String(data,0,count); int mark = message.indexOf(32); serverVersion= message.substring(0,mark); while(mark < message.length() && message.charAt(mark + 1) == 32) { mark++; } responseCode = Integer.parseInt(message.substring(mark + 1,mark += 4)); responseMessage = message.substring(mark,message.length()).trim(); // 应答状态码和处理添加
switch(responseCode){
case 400:
throw new IOException("错误请求");
case 404:
throw new FileNotFoundException(getURLFormat(target));
case 503:
throw new IOException("服务器不可用");
}
if(word == -1){ throw new ProtocolException("信息接收异常终止"); } int symbol = -1; count = 0; // 解析元信息
while(word != '\r' && word != '\n' && word > -1){ if(word == '\t') { word = 32; } if(count == data.length) { data = addCapacity(data); } data[count++] = (byte) word; parseLine:{ while( (symbol = receiver.read()) > -1){ switch(symbol){
case '\t': symbol = 32; break; case '\r': case '\n': word = receiver.read(); if(symbol == '\r' && word == '\n'){ word = receiver.read(); if(word == '\r') { word = receiver.read(); } } if(word == '\r' || word == '\n' || word > 32){ break parseLine; } symbol = 32; break; } if(count == data.length) {
data = addCapacity(data); } data[count++] = (byte) symbol; } word = -1; }
message = new String(data,0,count); mark = message.indexOf(':'); String key = null; if(mark > 0) { key = message.substring(0,mark); } mark++; while(mark < message.length() && message.charAt(mark) <= 32) { mark++; } String value = message.substring(mark,message.length());
header.put(key,value); count = 0; } // 获得正文数据 while( (word = receiver.read()) != -1){
if(count == data.length) {
data = addCapacity(data);
} data[count++] = (byte) word; } if(count > 0) { byteStream = new ByteArrayInputStream(data,0,count); } data = null; closeServer(); }
public String getResponseMessage(){ return responseMessage;
}
public int getResponseCode(){ return responseCode;
}
public String getServerVersion(){ return serverVersion;
}
public InputStream getInputStream(){ return byteStream;
}
public synchronized String getHeaderKey(int i){ if(i >= header.size()){
return null;
}
Enumeration enumss = header.propertyNames();
String key = null;
for(int j = 0; j <= i; j++){
key = (String) enumss.nextElement();
}
return key;
}
public synchronized String getHeaderValue(int i){ if(i >= header.size()){
return null;
}
return header.getProperty(getHeaderKey(i));
}
public synchronized String getHeaderValue(String key){ return header.getProperty(key);
}
protected String getBaseHeads(){ String inf = "User-Agent: ZealHttp/1.0\r\nAccept: www/source; text/html; image/gif; */*\r\n";
return inf;
}
private byte[] addCapacity(byte rece[]){ byte temp[] = new byte[rece.length + 1024];
System.arraycopy(rece,0,temp,0,rece.length);
return temp;
}
}
|
|
||||||
|
|