- 浏览: 439102 次
- 性别:
- 来自: 吉林→上海
文章分类
- 全部博客 (174)
- Java基础-接口与内部类 (5)
- Java基础-流与文件 (10)
- Java基础-JDBC (12)
- Java基础-XML解析 (7)
- Java基础-多线程 (11)
- Java基础-网络 (6)
- Java基础-注解 (5)
- Hibernate 研究记录 (7)
- JavaScript 研究记录 (6)
- ECMAScript 研究记录 (7)
- CSS 研究记录 (9)
- Maven 研究记录 (8)
- SQL 随笔 (5)
- 权限控制和单点登陆 (8)
- Hadoop 研究记录 (6)
- 随想杂谈 (33)
- JAVA EE (4)
- 测试 (3)
- Redis (10)
- Memcached (2)
- MongoDB (6)
- ElasticSearch (3)
最新评论
-
sgq0085:
无尘灬 写道楼主,在吗?可以加你qq咨询一下问题吗?公司禁用Q ...
Shiro通过Redis管理会话实现集群 -
无尘灬:
楼主,在吗?可以加你qq咨询一下问题吗?
Shiro通过Redis管理会话实现集群 -
zhouminsen:
感谢楼主的无私奉献
Shiro通过Redis管理会话实现集群 -
tonny1228:
经测试还是运行在local
远程调用执行Hadoop Map/Reduce -
asdhobby:
楼主,个人感觉每次调用SessionDAO的doUpdate方 ...
Shiro通过Redis管理会话实现集群
为了在Java程序中访问Web服务器,会希望在更高的级别上进行处理,而不只是创建套接字连接和发送HTTP请求。
1.URL和URI
(1)URL和URLConnection类封装了大量复杂的实现细节,这些细节设计如何从远程站点获取信息。
例:通过传递字符串来构建一个URL对象
URL url = new URL(urlString);
如果只是想获得该资源的内容,可以使用URL类中的openStream方法。该方法返回一个InputStream对象,然后就可以按照一般的用法来使用这个对象了,比如用它构建一个Scanner对象。
例:通过URL构建Scanner对象
InputStream inStream = url.openStream(); Scanner in = new Scanner(inStream);
(2)java.net包对 统一资源定位符(uniform resource locator, URL) 和 统一资源标识符(uniform resource identifier, URI) 做了非常有用的区分。
URI是个纯粹的句法结构,用于指定标识Web资源的字符串的各个不同部分。URL是URI的一个特例,它包含了用于定位Web资源的足够信息。
其他URI,比如 mailto:cay@horstmann.com 则不属于定位符,因为根据该标识符我们无法定位任何数据。像这样的URI称之为URN(uniform resource name, 统一资源名称)
(3)在java类库中,URI类不包含任何用于访问资源的方法,它的惟一作用就是解析。想法的是,URL类可以打开一个到达资源的流。因此,URL类只能用于那些Java类库知道该如何处理的模式。
URL可以处理的模式包含 http: 、https 、ftp: 、本地文件系统(file:)和JAR文件(jar:)。
(4)URI的解析并不是可有可无的,要考虑到它也许会变的非常复杂。
例: http://maps.yahoo.com/py/maps.py?csz=Cupertino+CA
ftp://username:password@ftp.yourserver.com/pub/file.txt
URI规范给出了标记这些标识符的规则,一个URI具有以下语法
[scheme:]schemeSpecificPart[#fragment]
上式中,[...]表示可选部分,它与:和#可以被包含在标识符内。
(5)包含 scheme: 部分的URI被称为绝对URI。否则称为相对URI。
(6)如果绝对URI的schemeSpecificPart不是以/开头的,我们就称它是不透明的。
例: mailto:cay@horstmann.com
(7)所有绝对的透明的URI和所有相对的URI都是有 分层的(hierarchical)
例: http://java.sun.com/index.html
../../java/net/Socket.html#Socket()
(8)一个分层的URI的schemeSpecificPart具有以下结构:
[//authority][path][?query]
(9)对于那些基于服务器的URI,authority部分采用以下形式
[user-info@]host[:port]
port必须是一个整数
RFC 2396(标准化URI的文献)还支持一种基于注册表的机制,此时authority采用了一种不同的格式。不过,这种情况并不常见。
(10)URI类的作用之一是解析标识符并将它分解成各种不同的组成部分。可以用一下方法读取它们:
getScheme
getSchemeSpecificPart
getAuthority
getUserInfo
getHost
getPort
getQuery
getFragment
(11)URI类的另一个作用是处理绝对标识符和相对标识符。
例: 如果存在一个如下的绝对URI:
http://docs.mycompany.com/api/java/net/ServerSocket.html
和一下如下的的相对URI
../../java/net/Socket.html#Socket()
那么可以将它们合并为一个绝对URI
http://docs.mycompany.com/api/java/net/Socket.html#Socket()
这个过程被称为相对URL的 转换(resolving)。
(12)与此相反的过程称为相对化(relativization)。
例: 有一个基本URI:
http://docs.mycompany.com/api
和另一个URI:
http://docs.mycompany.com/api/java/lang/String.html
那么相对化之后的URI就是:
java/lang/String.html
(13)URI类同时支持一下两个操作:
relative = base.relativize(combined); combined = base.resolve(relative);
2.使用URLConnection获取信息
如果想从某个Web资源获取更多信息,那么应该使用URLConnection类,它能得到比基本的URL类更多的控制功能。
当操作一个URLConnection对象时,必须像下面这样非常小心的安排操作步骤:
(1)调用URL类中的openConnection方法获得URLConnection对象:
URLConnection connection = url.openConnection();
(2)使用一下方法来设置任意的请求属性
setDoInput
setDoOutput
setIfModifiedSince
setUseCaches
setAllowUserInteraction
setRequestProperty
setConnectTimeout
setReadTimeout
(3)调用connect方法连接远程资源:
connection.connect();
除了与服务器建立套接字连接外,该方法还可以用于向服务器查询头信息(header information)。
(4)与服务器建立连接后,可以查询头信息。getHeaderFieldKey和getHeaderField两个方法列举了消息头的所有字段。
getHeaderFields方法返回一个包含了消息头中所有字段的标准Map对象。为了方便使用,一下方法可以查询各标准字段:
getContentType
getContentLength
getContentEncoding
getDate
getExpiration
getLastModified
(5)最后访问资源数据。使用getInputStream方法获取一个输入流用以读取信息(这个输入流与URL类中的openStream方法所返回的流相同)。
另一个方法getContent在实际操作中并不是很有用。有标准内容类型(比如text/plain和image/gif)所返回的对象需要使用com.sun层次结构中的类来进行处理。也可以注册自己的内容处理器。
(6)注意,URLConnection类中的getInputStream和getOutputStream方法与Socket类中的这些方法不同。
URLConnection类具有很多表面之外的功能,尤其在处理请求和相应消息头时。正因为如此,严格遵循建立连接的每个步骤都显得非常重要。
(7)URLConnection类中的一些方法。有几个方法可以在与服务器建立连接之前设置连接属性。
其中最重要的是setDoInput和setDoOutput。
在默认情况下建立连接只有从服务器读取信息的输入流(即setDoInput默认值为true),并没有任何执行写操作的输出流(setDoOutput默认值为false)。如果想获得输出流(例如,向Web服务器提交数据),需要调用:
connection.setDoOutput(true);
(8)设置某些请求头(request header)。请求头是与请求命令一起发送到服务器的。
例:
GET www.server.com/index.html HTTP/1.0
Referer: http://www.sonewhere.com/links.html
Proxy-Connection: Keep-Alive
User-Agent: Mozilla/5.0(X11; U; Linux i686; en-US; rv:1.8.1.4)
Host:www.server.com
Accept: text/html, image/gif, image/jpeg, image/png, */*
Accept-Language: en
Accept_Charset: iso-8859-1,*,utf-8
Cookie: orangemilano=192218887821987
setIfModifiedSince(long ifmodifiedsince)方法用于告诉连接只对自某个特定日期依赖被修改过的数据该兴趣
setUseCaches(boolean usecaches)和setAllowUserInteraction(boolean allowuserinteraction)这两个方法只用于Applet
setUseCaches方法用于命令浏览器首先检查它的缓存,UseCaches 标志为 true,则允许连接使用任何可用的缓存。如果为 false,则忽略缓存,默认为 true。例如浏览器中的“重新加载”
setAllowUserInteraction方法则用于在访问有密码保护的资源时弹出对话框,以便查询用户名和口令。
(9)一个总揽全局的方法:setRequestProperty,它可以用来设置对特定协议起作用的任何"名-值(name/value)对"。
关于HTTP请求头的格式参加RFC 2616,其中的某些参数没有很好地记录在文档中,它们通常在程序员直接口头传授。
例:访问一个由口令保护的Web也,那么必须按如下步骤操作:
1)将用户名、磨耗和口令以字符串形式连接在一起。
String input = username + ":" + password;
2)计算上一步骤所得字符串的base64编码。(base64编码用于将子就留编码成可打印的ASCII字符流)
可以通过sun.misc.BASE64Encoder进行编码
String encoding = new sun.misc.BASE64Encoder().encode(input.getBytes());
注意sun.misc.BASE64Encoder属于未公开(undocumented)的类
3)调用setRequestProperty方法,设置name参数的值为"Authorization"、value参数的值为"Basic"+encoding;
connection.setRequestProperty("Authorization", "Basic" + encoding);
4)上述是访问有口令保护的web页,如果想通过FTP访问一个由口令保护的文件时,要采用一种完全不同的方法。可以直接构建一个如下格式的URL:
ftp://username:password@ftp.yourserver.com/pub/file.txt
(10)一旦调用了connect方法,就可以查询响应头信息。
列举所有响应头的字段,该操作采用了另一种迭代方式。
String key = connection.getHeaderFieldKey(n);
可以获得响应头的第n个键,其中n从1开始。如果n为0或大于消息头的字段总数,该方法将返回null值。没有哪种方法可以返回字段的数量,必须反复调用getHeaderFieldKey方法直到返回null为止。
得到第n个值
String value = connection.getHeaderField(n);
getHeaderFields方法可以返回一个封装了响应头字段的Map对象。
Map<String, List<String>> headerFields = connection.getHeaderFields(); for(Map<String, List<String>> entry : headerFields){ String key = entry.getKey(); List<String> value = entry.getValue(); }
(11)一组来自典型HTTP请求的相应字段头
Date: Wed, 27 Aug 2008 00:15:48 GMT
Server: Apache/2.2.2(Unix)
Last-Modified: Sun, 22 Jun 2008 20:53:38 GMT
Accept-Ranges: bytes
Content-Length: 4813
Connection: close
Content-Type: text/html
long getDate() : 返回 date 头字段的值,即创建日期。
long getExpiration() : 返回 expires 头字段的值,即过期日。
long getLastModified() : 返回 last-modified 头字段的值,即最后一次被修改日期。
int getContentLength() : 返回 content-length 头字段的值,即如果知道内容的长度,则返回该长度,否则返回-1。
String getContentType() : 返回 content-type 头字段的值,即获取内容的类型,比如text/plain或image/gif。
String getContentEncoding() : 返回 content-encoding 头字段的值,即获取内容的编码,比如gzip,这个值不太常用,因为默认的identity编码并不是Content-Encoding头来设定的。
Java提供了6个方法用以访问大多数常用的消息头类型的值,并在需要的时候将它们转换成数字类型。其中返回类型为long的方法返回的是从格林威治时间1970年1月1日开始计算的秒数。
用于访问响应头值的简便方法
键名 方法名 返回类型
Date getDate long
Expires getExpiration long
Last-Modified getLastModified long
Content-Length getContentLength int
Content-Type getContentType String
Content-Encoding getContentEncoding String
(12)一个常会遇到的问题是Java平台是否支持对安全Web页面的访问(https: URL) : 从Java SE 1.4开始,对安全套接字层ssl的支持已经成为标准程序库的一部分
3.提交表单数据
当表单数据被发送给Web服务器时,通常会有两个命令会被用到: GET 和 POST
(1)在使用GET命令时,只需将参数附在URL结尾处即可。
例: http://host/script?parameters
其中,每个参数都有"名字=值"的形式,而这些参数之间用&字符分隔开。
参数的值遵循的规则
1)保留字符A-Z、a-z、0-9以及 . - * _
2)用 + 字符替换所有的空格
3)将其他所有字符编码为UTF-8,并将每个字节都编码为 % 后面紧跟着一个两位的十六进制数字。
例如,发送街道名S. Main,可以使用S%2e+Main,因为十六进制2e是"."的ASCII码值。
这种编码方式使得在任何中间程序中都不会混入空格,并且也不需要对其他特殊字符进行转换。
GET命令很简单,但是有一个重要的局限性,大多数浏览器都对GET请求中可以包含的字符数做了限制。
(2)使用POST命令时,并不需要在URL中添加任何参数,但是从URLConnection中获取输入流,并将名-值对写入该流中。当然,仍然需要对这些值进行URL编码,并用&字符将它们隔开。
POST提交数据流程
1)创建一个URLConnection对象
URL url = new URL("http://host/script"); URLConnection connection = url.openConnection();
2)调用setDoOutput方法建立一个用于输出的连接。
connection.setDoOutput(true);
3)调用getOutputStream方法获得一个流,可以通过这个流向服务器发送数据。
如果要向服务器发送文本信息,那么可以将流包装在PrintWriter对象中。
PrintWriter out = new PrintWriter(connection.getOutputStream());
4)现在可以向服务器发送数据了
out.print(name1 + "=" + URLEncoder.encode(value1, "UTF-8") + "&"); out.print(name2 + "=" + URLEncoder.encode(value2, "UTF-8"));
5)关闭输出流
out.close();
6)调用getInputStream方法读取服务器的响应。
例:通过POST向服务器发送信息,并接收返回数据。其中urlString为地址,nameValuePairs为表单数据
public static String doPost(String urlString, Map<String, String> nameValuePairs) throws IOException{ URL url = new URL(urlString); URLConnection connection = url.openConnection(); //打开输出流 connection.setDoOutput(true); PrintWriter out = new PrintWriter(connection.getOutputStream()); boolean first = true; for(Map.Entry<String, String> pair : nameValuePairs.entrySet()){ if(first){ first = false; }else{ out.print("&"); } String name = pair.getKey(); String value = pair.getValue(); out.print(name); out.print("="); out.print(URLEncoder.encode(value, "UTF-8")); } out.close(); Scanner in; StringBuilder response = new StringBuilder(); try{ in = new Scanner(connection.getInputStream()); }catch(IOException e){ if(!(connection instanceof HttpURLConnection)){ throw e; } //捕获错误页面 InputStream err = ((HttpURLConnection) connection).getErrorStream(); if(err == null){ throw e; } in = new Scanner(err); } while(in.hasNextLine()){ response.append(in.nextLine()); response.append("\n"); } in.close(); return response.toString(); }
在读取响应时,如果服务器端运行错误,那么调用connection.getInputStream()时就会抛出FileNotFoundException异常,但是此时服务器会返回一个错误页面(常见的404)。
为了捕获错误页面,可以将URLConnection对象转换为HttpURLConnection类,并调用它的getErrorStream方法。
InputStream err = ((HttpURLConnection) connection).getErrorStream();
(3)URLConnection向服务器发送的内容。
URLConnection对象先向服务器发送一个请求头,当提交表单数据时,该请求头必须包含
Content-type: application/x-www-form-urlencoded
而POST的请求头还必须包括长度,例
Content-Length: 24
所以URLConnection对象会把发送到输出流的所有数据都缓存起来,这是因为在发送之前首先确定内容的总长度。
DEMO
import java.awt.EventQueue; import javax.swing.JFrame; public class PostTest { public static void main(String[] args) { EventQueue.invokeLater(new Runnable(){ public void run(){ JFrame frame = new PostTestFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } }); } }
import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; import java.util.Scanner; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SwingConstants; import javax.swing.SwingWorker; public class PostTestFrame extends JFrame { private JPanel northPanel; public PostTestFrame(){ setTitle("PostTest"); northPanel = new JPanel(); add(northPanel, BorderLayout.NORTH); northPanel.setLayout(new GridLayout(0, 2)); northPanel.add(new JLabel("Host: ", SwingConstants.TRAILING)); final JTextField hostField = new JTextField(); northPanel.add(hostField); northPanel.add(new JLabel("Action: ", SwingConstants.TRAILING)); final JTextField actionField = new JTextField(); northPanel.add(actionField); for(int i=1;i<=8;i++){ northPanel.add(new JTextField()); } final JTextArea result = new JTextArea(20, 40); add(new JScrollPane(result)); JPanel southPanel = new JPanel(); add(southPanel, BorderLayout.SOUTH); JButton addButton = new JButton("More"); southPanel.add(addButton); addButton.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent event){ northPanel.add(new JTextField()); northPanel.add(new JTextField()); pack(); } }); JButton getButton = new JButton("Get"); southPanel.add(getButton); getButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { result.setText(""); final Map<String, String> post = new HashMap<String, String>(); for(int i=4;i<northPanel.getComponentCount();i+=2){ String name = ((JTextField)northPanel.getComponent(i)).getText(); if(name.length()>0){ String value = ((JTextField)northPanel.getComponent(i + 1)).getText(); post.put(name, value); } } new SwingWorker<Void, Void>(){ protected Void doInBackground() throws Exception{ try{ String urlString = hostField.getText() + "/" + actionField.getText(); result.setText(doPost(urlString, post)); }catch(IOException e){ result.setText("" + e); } return null; } }.execute(); } }); } public static String doPost(String urlString, Map<String, String> nameValuePairs) throws IOException{ URL url = new URL(urlString); URLConnection connection = url.openConnection(); connection.setDoOutput(true); PrintWriter out = new PrintWriter(connection.getOutputStream()); boolean first = true; for(Map.Entry<String, String> pair : nameValuePairs.entrySet()){ if(first){ first = false; }else{ out.print("&"); } String name = pair.getKey(); String value = pair.getValue(); out.print(name); out.print("="); out.print(URLEncoder.encode(value, "UTF-8")); } out.close(); Scanner in; StringBuilder response = new StringBuilder(); try{ in = new Scanner(connection.getInputStream()); }catch(IOException e){ if(!(connection instanceof HttpURLConnection)){ throw e; } InputStream err = ((HttpURLConnection) connection).getErrorStream(); if(err == null){ throw e; } in = new Scanner(err); } while(in.hasNextLine()){ response.append(in.nextLine()); response.append("\n"); } in.close(); return response.toString(); } }
发表评论
-
(六) 涉及API
2012-02-26 23:20 1411类 java.net.Socket 构造 Socket() ... -
(四) 发送E-mail
2012-02-21 21:21 2157为了发送E-mail,必须建立一个到端口25(即SMTP端口) ... -
(三) 可中断套接字
2012-02-20 22:48 1773当连接到一个套接字时,当前线程将会被阻塞知道建立连接或产生超时 ... -
(二) 实现服务器
2012-02-15 23:31 1328一个简单的服务器,可以向客户端发送信息。一旦启动了服务器程序 ... -
(一) 连接到服务器
2012-02-15 20:18 1115络术语中,端口并不是 ...
相关推荐
### JAVA中三种URL连接方法详解 #### 引言 在JAVA编程中,处理网络资源的能力是必不可少的。通过JAVA的`java.net`包,开发者能够轻松地与远程服务器交互,获取或发送数据。本文将深入探讨JAVA中三种常见的URL连接...
2. **建立连接**: 客户端通过WebSocket URL发起连接请求,服务器端的`afterConnectionEstablished()`方法会被调用。 3. **处理消息**: 当客户端发送消息时,服务器端的`handleTextMessage()`会被调用。在这里,你...
该方法的核心是利用Java内置的`HttpURLConnection`类来尝试建立与指定URL的连接,并根据响应状态码判断连接是否成功。下面将对代码中的关键部分进行深入解析。 #### 代码分析 1. **方法定义**: ```java private...
连接数据库时,首先需要在Java代码中加载相应的驱动,如 `Class.forName("driver_class_name")`,然后使用 `DriverManager.getConnection(url, username, password)` 建立连接。对于ODBC连接,需要先创建数据源,...
WebSocket接口定义在`window.WebSocket`对象中,使用时首先需要创建一个WebSocket对象,然后通过`connect()`方法建立连接,成功连接后,可以通过`send()`方法发送数据,同时可以监听`message`事件来接收服务器返回的...
当SQLSERVER数据库驱动程序遇到无法通过安全套接字层(SSL)加密与SQL Server建立安全连接的问题时,通常涉及到证书配置、驱动版本兼容性、Java安全策略或者缺少必要的库文件等问题。以下是一些解决此类问题的知识点...
4. **连接字符串参数**:在建立数据库连接时,需要在URL中指定`encrypt=true`和`trustServerCertificate=true`参数以启用SSL并跳过服务器证书验证。如果你的服务器证书由权威CA签发,可以不设置`...
在这个示例中,我们首先创建一个`URL`对象,然后调用`openConnection()`方法建立到服务器的连接。接着,我们设置请求方法为GET,并获取服务器的响应码,以检查请求是否成功。最后,我们从连接的输入流中读取响应内容...
4. 用户界面设计:`Connect To.Frm`文件很可能包含了用户输入URL、登录信息等的界面元素,以及用于触发连接的按钮。在按钮的点击事件中,会编写代码来执行上述的网络连接操作。 5. 错误处理:为了确保程序的健壮性...
1. **建立连接**:通过`connect()`方法建立到服务器的连接。这是异步的,不会立即返回结果,但会开始传输数据。 ```java urlConnection = url.openConnection(); urlConnection.connect(); ``` 2. **设置请求属性*...
+ URL:数据库连接 URL 点击“Ping”按钮,出现“Ping Succeeded”,表示数据源配置成功。 ### 3. 建立 JDBC 资源 建立“JDBC Resources”,jndi 名称为:ticket。如下所示: * JNDI Name:ticket *Datasource...
再分享一个Java建立HTTP连接的例子,读取网络上的内容,例子简单,打基础可参考。整体来说,核心的代码如下: ContentConnection connection = (ContentConnection) Connector.open(url); //获取连接 TextBox tb...
Java建立HTTP连接浏览网址打开网站,这个功能的最终效果类似于一个网页浏览器,通过建立HTTP连接,输入URL网址后,可打开网址,浏览网页内容,并且可查看该网页的源代码,本例可学习如何在Java代码中建立HTTP连接。...
2. 创建连接:使用`DriverManager.getConnection()`方法,传入数据库连接URL、用户名和密码来建立连接。 ```java String url = "jdbc:mysql://localhost:3306/mydatabase"; String username = "myuser"; String ...
1. 数据库连接池原理:数据库连接池维护了一组已建立的数据库连接,当应用需要连接时,从池中获取一个已经存在的连接,而不是每次请求时都创建新的连接。使用完毕后,应用会将连接归还给连接池,而不是直接关闭,...
- 使用`DriverManager`类的`getConnection`方法来建立与数据库的连接。需要提供数据库的URL、用户名以及密码作为参数。 #### 二、DB2数据库 IBM DB2是一种高性能的关系型数据库管理系统,支持多种操作系统平台,...
2. **建立HTTP请求**:利用`HttpURLConnection`发送GET请求到指定的APK下载URL。设置连接超时和读取超时以提高用户体验。 ```java URL url = new URL(apkDownloadUrl); HttpURLConnection connection = ...
易语言提供了`Internet建立连接`命令,用于创建一个与指定服务器的TCP连接。该命令需要输入服务器的IP地址或域名以及端口号。如: ```易语言 .连接句柄 = Internet建立连接(“www.example.com”, 80) ``` 这里...
3. 调用`URLConnection`的`connect()`方法建立实际的网络连接。 4. 可以通过`InputStream`或`OutputStream`读写数据,具体取决于连接类型。 在描述中提到,JavaBean与XML文件配合。这可能指的是使用XML文件存储...