Java 高层网络编程

国产NAS哪家强?极空间&绿联&威联通&群晖对比 随着个人数据量暴增,传统网盘空间不足和下载速度慢问题愈发凸显。新势力NAS,作为数据管理领域的璀璨新星,正以其独特的互联网设计理念,引领家庭及小型办公用户向数据存储的新纪元。它不仅仅是一款产品,更是为初学者用户量身定制的贴心伙伴。其系统界面之简洁、操作流程之直观,让人一目了然,真正实现了“即插即用”的极致便捷。同时,新势力NAS在保持专业水准的同时,更提供了多样化的扩展性配置,轻松应对各种数据存储与管理需求,让家庭及小型办公场景下的数据管理变得前所未有的简单与高效。 阅读详情
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script> java.net 包中的类和接口提供了可用于低层和高层网络编程的 API。低层 API 可以让你直接访问网络协议,但是为此你不得不使用低层的 TCP 套接字和 UDP 数据包。高层的 API (如 URL, URLConnection 和 httpURLConnection 等类) 可以使你更快的开发网络应用,却不需要写很多代码。另一篇文章,《Network Programming with J2SE 1.4》会告诉你如何使用低层的套接字进行网络编程。这篇文章的重点则放在如何使用 java.net 包中的高层 API 开发基于 HTTP 的应用程序。 这篇文章将有如下内容: · 概览 HTTP · 概览 java.net 包的高层 API · 示例说明如何使用高层 API · 制作一个可以下载股票行情的应用程序 · 演示如何提交数据到网页服务器 · 概览 HTTP 的验证并展示如何保护你的网络资源 · 提供代码实例演示如何执行 HTTP 的验证 概览 HTTP 超文本传输协议 (Hypertext Transfer Protocol, HTTP) 是一个“请求-回应”的应用协议。这个协议支持一套固定的方法如 GET、POST、PUT、DELETE 等。一般用 GET 方法向服务器请求资源。这里有两个 GET 请求的例子: GET / HTTP/1.1 GET /names.html HTTP/1.1 另外,你可以使用 GET 和 POST 方法向服务器发送数据,它们向服务器发送数据的方式是不同的: · GET 方法:输入的数据将作为 URL 的一部分发送 · POST 方法:输入数据作为一个独立的实体发送 考虑一下下面的 HTML 表单:



<form action="http://www.javacourses.com/servlets/getMarks method="GET">

Student#:

<input type=text name=number size=30>

<input type=submit name=GetMarks value=GetMarks>

</form>



这个表单会提交到 http://www.javacourses.com/servlet/getMarks 由 Servlet 处理。该表单使用了 GET 方法来传输信息。如果用户输入一个学号——比如 556677——并点击 GetMarks 按钮,表单数据就会作为 URL 的一部分传送到 Servlet 中。经过编码之后的 URL 就是:http://www.javacourses.com/servlets/getMarks?number=556677。 在使用 POST 方法的情况下,传输数据时不会将数据作为 URL 的一部分;它们会作为一个独立的实体来传输。因此,POST 方法更安全,你也可以用这个方法传输更多的数据。而且用 POST 传输的数据不一定要是文本,用 GET 方法传输的却一定要是文本。 消息息格式 请求消息指定了方法名称 (GET 或者 POST)、URL、协议版本号、头部消息和可选消息。头部消息也许会包含请求信息和客户端信息,如接受的内容类型、浏览器名称以及验证数据。返回消息指定了协议版本、响应代码和原因。不管执行是否成功,响应代码和原因都会报告。一些响应代码如下:



200 OK: Request succeeded. The requested resource can be found later in this message. 

301 Moved Permanently: Requested resource has moved. New location is specified later in this message. 

400 Bad Request: Request message is not understood by the server. 

404 Not Found: Requested document is not found on this server. 

关于 HTTP 和所有返回代码的信息可以在 HTTP 1.1 规范 RFC2616 中找到。 下面是一个请求消息由浏览器到服务器的例子。这里请求的 URL 是 http://java.sun.com:





GET / HTTP/1.1

Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, 

application/vnd.ms-powerpoint, application/vnd.ms-excel, 

application/msword, */*

Accept-Language: en-ca

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; YComp 5.0.0.0)

Host: java.sun.com

Connection: Keep-Alive

Cookie: SUN_ID=24.80.19.177:28346100732290; 

SunONEUserId=24.80.19.177:86521021960770

然后这里是服务器对这个请求的回复消息:





HTTP/1.1 200 OK

Server: Netscape-Enterprise/6.0

Date: Mon, 14 Oct 2002 15:18:04 GMT

Content-type: text/html

Connection: close

概览 java.net 包的高层 API java.net 包中含有高层 API。它们实现了一些最常用的基于 TCP 的协议,如 HTTP 和 FTP 等。其中两个主要的类是 URL 和 URLConnection。另一个有用的类是 HttpURLConnection,它是 URLConnection 的子类,支持 HTTP 的特性。 URL (Uniform Resource Locator,统一资源定位器) 是一个描述 Internet 中文档 (或者其它常见的资源) 位置的地址。URL 的样子就像这样: protocol://machineName:port/resource 注意 URL 类不是基于 HTTP 的,这一点非常重要。它支持 FTP、HTTPS 和 FILE 协议。所以,对于 URL 类来说,下面所有 URL 都是有效的。 http://java.sun.com http://localhost:8080/myApplication http://www.yahoo.com/index.html http://www.yahoo.com ftp://ftp.borland.com ftp://ftp.sun.com https://www.scotiaonline.scotiabank.com https://central.sun.net file:///C:/j2sdk1.4/docs/api/index.html 你在浏览器里输入一个 URL 的时候,浏览器产生一个 HTTP GET (或者 POST) 命令寻找 (或者查询) URL 请求的资源。如果没有指定要查询的的资源,被查询的就会是默认文档 (通常是 index.html)。 读取 URL 的内容 让我们以一个简单的应用程序开始,它将会直接从 URL 读取内容。不妨先尝试一下使用低层的套接字来读取,请看示例代码 1。在这个例子中,用户在命令行输入资源的 URL,然后在 80 端口 (默认的 HTTP 服务器端口号) 打开一个套接字并建立相应的输入输出流。输出流用来向 HTTP 服务器发送 HTTP 命令 (比如 GET),输入流则用来读取 HTTP 服务器的返馈。注意,在这个例子中,服务器回应的头信息也会被读入 (这是 URL 内容之外的东西)。 示例代码 1: ReadURL1.java





import java.net.*;

import java.io.*;





public class ReadURL1 {

public static void main(String argv[]) throws Exception {

final int HTTP_PORT = 80;

if(argv.length != 1) {

System.out.println("Usage: java ReadURL1 <url>");

System.exit(0);

}



Socket socket = new Socket(argv[0], HTTP_PORT);

BufferedWriter out= new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

BufferedReader in= new BufferedReader(new InputStreamReader(socket.getInputStream()));

out.write("GET /index.html HTTP/1.0/n/n");

out.flush();

String line;

StringBuffer sb = new StringBuffer();

while((line = in.readLine()) != null) {

sb.append(line);

}

out.close();

in.close();

System.out.println(sb.toString());

}

}



// end code

你运行这个例子的时候请注意,URL 必须是一个域名如 java.sun.com 或者 IP 地址。不能加上 http:// 作为 URL 的一部分。如果你要解决这个问题,你就得解析输入的内容并找出它使用什么协议,端口号和要请求什么资源。你也可以使用 URL 类,它提供了一些非常有用的方法,如 getProtocal、getPort、getHost 和 getFile 等。 使用 URL 类 要从 URL 读取内容,可以用 URL 类非常容易的实现,就像示例代码 2 所展示的那样。这使得直接从 URL 读取内容变得简单。用这种方法读取的内容不包含服务器回应的头信息,所以不需要你去解析它们了。运行这个例子时要输入有效的 URL ,就像 protocol://domainName:port/resource 这样。URL 类会解析输入的 URL 并处理低层的麻烦的工作。 示例代码 2:ReadURL2.java





import java.net.*;

import java.io.*;



public class ReadURL2 {



public static void main(String argv[]) throws Exception {

if(argv.length != 1) {

System.out.println("Usage: java ReadURL2 <url>");

System.exit(0);

}



URL url = new URL(argv[0]);

BufferedReader in= new BufferedReader(new InputStreamReader(url.openStream()));

String line;

StringBuffer sb = new StringBuffer();



while ((line = in.readLine()) != null) {

sb.append(line);

}

in.close();

System.out.println(sb.toString());



}



}

在你运行 ReadURL2 的时候,你会看到你输入的 URL 所请求的文档内容命令窗口中显示出来。 如果你想做除了读取之外的其它事情,请使用 openConnection 来建立到 URL 的连接。这个方法返回一个 URLConnection 对象,你可以用这个对象来与 URL 通信,如读、写、查询等。一但 openConnetion 方法创建了连接,你就可以使用 getContentType、getContentLength、getContentEncoding 等非常有用的方法了。 使用 URLConnection 类 我们现在要创建一个从 http://quote.yahoo.com 获取股票信息的应用程序来演示如何使用 URLConnection。为了获取特别的股票信息,用户输入股票标号 (比如 SUNW、IBM 或者 MOT),由应用程序从 Yahoo Quote 服务器获取相应的股票信息。应用程序会显示出该股票的名称、价格和日期。 有两种方法 (可以用在这个应用程序中的) 用来从 Yahoo Quote 服务器获取股票信息。第一种方法的格式如下: http://quote.yahoo.com/d/quotes.csv?s=SUNW&f=slc1wop 如果你在浏览器的地址栏输入这个 URL,你将会看到像图 1 所示的那些内容。
图 1:获取股票行情
另一种方法的格式是: http://finance.yahoo.com/q?s=SUNW
图 2: 获取股票行情的另一种方法
你可以看到第一种方法的结果是一行文本,解析时会比第二种容易许多,也快许多,因为第二种方法的结果含有大量的文字,包括许多广告和格式化信息。所以我用第一种方法实现这个关于股票的应用程序,它由两个类组成:Stock.java 和 StockReader.java。 Stock.java 类 这个类将从 Yahoo Quote 服务器获得的字符串解析成字段 (例如股票名称、价格和日期)。示例代码 3 中展示了一个实现的例子。示例代码 4 中的 StockReader 类会用到这个工具类。 示例代码 3:Stock.java





public class Stock {



private static String name, time, price;



// Given a quote from the server,

// retrieve the name, price, and date of the stock

public static void parse(String data) {



int index = data.indexOf('"');

name = data.substring(  index,(index = data.indexOf('"', index)));

index  =3;

time = data.substring(index, (index = data.indexOf('-', index))-1);

index  =5;

price = data.substring(index, (index = data.indexOf('>', index)));

}



// Get the name of the stock from

public static String getName(String record) {

parse(record);

return(name);

}



// Get the price of the stock from

public static String getPrice(String record) {

parse(record);

return(price);

}



// Get the date of the stock

public static String getDate(String record) {

parse(record);;

return time;

}

}

StockReader.java 类 这个类的任务是连接到 Yahoo Quote 服务器,并从服务器上获取股票行情。它使用 Stock 类解析从服务器返回的字符串。示例代码 4 是它的一个实现。 示例代码 4:StockReader.java





import java.io.*;

import java.net.*;



public class StockReader {

public static void main(String argv[]) throws Exception {

String quoteFormat = "&f=slc1wop";

if (argv.length != 1) {

System.err.println("Usage: java StockReader <symbol>");

System.exit(1);

}



URL url = new URL("http://quote.yahoo.com/d/quotes.csv?");

URLConnection connection = url.openConnection();

connection.setDoOutput(true);



PrintWriter out = new PrintWriter(connection.getOutputStream());

out.println("s="   argv[0]   quoteFormat);

out.close();



BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));

String line = in.readLine();



/* DEBUG

while ((line = in.readLine()) != null) {

System.out.println("Got: "  line);

}

*/

in.close();

System.out.println("Name: "  Stock.getName(line));

System.out.println("Price: "  Stock.getPrice(line));

System.out.println("Date: "  Stock.getDate(line));

}

}

将数据提交到网页服务器 在上面的例子中,数据是作为 URL 的一部分被送到服务器的,使用的 GET 方法。现在来看一个使用 POST 方法发送数据的例子。这个例子中,http://www.javacourses.com/cgi-bin 中的 CGI 脚本 (名为 .cgi) 需要 name 和 email 值。如果用户提交 Sally McDonald 作为 name 值,smc@yahoo.com 作为 email 值,CGI 脚本会获取输入并对消息进行解析、解码,再将提交的内容返回给客户端。这个 CGI 脚本做事情并不多,但我们要用它来演示如何向服务器提交数据。 还有一点非常重要——请注意使用 POST 方法时,消息内容的类型是 application/x-www-form-urlencoded,这种类型会: · 指定常规数据编码 · 将空格转换为加号 ( ) · 将非文本内容转换成十六进制数后接百分号 (%) 的形式 · 在每个 name=value 对之间放置 & 符号 根据这个编码规则,消息 (name=Sally McDonald and email=smc@yahoo.com) 在发送给 CGI 脚本之前必须被编码成: name=Sally McDonald&email=smc@yahoo.com CGI 脚本收到这个已编码的消息后会对它进行解码。不过非常幸运,你不必为手工进行编码操作。你可以使用 java.net.URLEncoder 类来对消息进行编码,就像下面的例子中那样。相应地你可以使用 java.net.URLDecoder 来对消息进行解码。 示例代码 5 中是这个例子的实现 (使用 HttpURLConnection 类),它展示了如何使用 POST 方法向服务器发送数据。你会看到: · 为 CGI 脚本打开连接和 I/O 流 · 设置请求方法为 POST · 使用 URLEncoder.encode 方法对消息进行编码 (URLDecoder.decode 方法可以用于解码) · 向 CGI 脚本发送已经编码的消息 · 接收服务器返回的消息并在控制台打印出来 示例代码 5:PostExample.java





import java.io.*;

import java.net.*;



public class PostExample {

public static void main(String[] argv) throws Exception {

URL url = new URL("http://www.javacourses.com/cgi-bin/names.cgi");

HttpURLConnection connection = (HttpURLConnection) url.openConnection();

connection.setRequestMethod("POST");

connection.setDoOutput(true);

PrintWriter out = new PrintWriter(connection.getOutputStream());

// encode the message

String name = "name=" URLEncoder.encode("Qusay Mahmoud", "UTF-8");

String email = "email=" URLEncoder.encode("qmahmoud@javacourses.com", "UTF-8");

// send the encoded message

out.println(name "&" email);

out.close();

BufferedReader in= new BufferedReader(new InputStreamReader(connection.getInputStream()));

String line;

while ((line = in.readLine()) != null) {

System.out.println(line);

}

in.close();

}

}

代理服务器和防火墙 如果你使用了防火墙,你就得把代理服务器以及端口号的详细信息告诉 Java,这样才能访问到防火墙外的主机。你可以通过定义一些 HTTP 或者 FTP 属性来做到:



http.proxyHost (default: )

http.proxyPort (default: 80 if http.proxyHost specified)

http.nonProxyHosts (default: )

http.proxyHost 和 http.proxyPort 用来指定 HTTP 协议处理器需要使用的代理服务器和端口号。http.nonProxyHosts 用来指定哪些主机是直接连接的 (即不通过代理服务器来连接)。http.nonProxyHosts 属性的值是一个由 | 分隔开的主机列表,它可以使用正则表达式来表示所匹配的主机,如:*.sfbay.sun.com 将匹配 sfbay 域中的任何主机。



ftp.proxyHost (default: )

ftp.proxyPort (default: 80 if ftp.proxyHost specified)

ftp.nonProxyHosts (default: )

ftp.proxyHost 和 ftp.proxyPort 用来指定 FTP 协议处理器需要使用的代理服务器和端口号。ftp.nonProxyHosts 用来指定哪些主机是直接联系的,指定的方法与 http.nonProxyHosts 类似。 你可以在应用程序启动的时候设置这些属性: Prompt> java -Dhttp.proxyHost=HostName -Dhttp.proxyPort=PortNumber yourApp HTTP 验证 HTTP 协议提供验证机制来保护资源。当一个请求要求取得受保护的资源时,网页服务器回应一个 401 Unauthorized error 错误码。这个回应包含一个指定了验证方法和领域的 WWW-Authenticate 头信息。把这个领域想像成一个存储着用户名和密码的数据库,它将被用来标识受保护资源的有效的用户。比如,你试着去访问某个网站上标识为“Personal Files”的资源,服务器响应可能是:WWW-Authenticate: Basic realm="Personal Files" (假设验证方法是 Basic)。 验证方法 现在有几种用于网络应用的验证方法,其中最广泛使用的是基本验证 (Basic Authentication) 和摘要验证 (Digest Authentication)。 当用户想要访问有限的资源时,使用基本验证方法的网页服务器会要求浏览器询显示一个对话框,并要求用户输入用户名和密码。如果用户输入的用户名和密码正确,服务器就允许他访问这些资源;否则,在接连三次尝试失败之后,会显示一个错误消息页面。这个方法的缺点是用户名和密码都是用 Base64 编码 (全是可读文本) 之后传输过去的。也就是说,这个验证方法的安全程度只是和 Telnet 一样,并不是非常安全。 数据验证方法不会在网络中传输密码,而是生成一些数字 (根据密码和其它一些需要的数据产生的) 来代替密码,而这些数字是经过 MD5 (Message Digest Algorithm) 加密的。生成的值在网络有随着服务器需要用来校难密码的其它信息一起传输。这个方法明显更为安全。 基于表单的验证方法和基本验证方法类似,只是服务器使用你自定义的登录页面来代替了标准的登录对话框。 最后,客户证书验证使用 SLL (Secure Socket Layer,安全套接层) 和客户证明。 在 Tomcat 下保护资源 你可以在 tomcat-users.xml 文件中写一个用户及其角色的列表。这个文件在 TOMCAT_HOME (你安装 Tomcat 的目录) 下的 conf 目录中。这个文件默认包含了三个用户 (tomcat、role1、both) 的定义。下面一段 XML 代码是我添加了两个新用户 (qusay 和 reader) 之后的 tomcat-users.xml:



<tomcat-users>

<user name="tomcat" password="tomcat" roles="tomcat" />

<user name="role1" password="tomcat" roles="role1" />

<user name="both" password= "tomcat" roles="tomcat,role1" />

<user name="qusay" password="guesswhat" roles="author" />

<user name="reader" password="youguess" roles="reader" />

</tomcat-users>

新添加的两个用户 (qusay 和 reader) 的 roles 分别设置为 author 和 reader。角色属性非常重要,因为当你创建安全规则的时候,每个受限制的资源都是与可访问它的角色相关联 (稍后你会看到)。 下面做个实验 (假设你已经安装并配置好了 Tomcat)。为你期望的页应用程序建立一个目录。可以按下列步骤做好准备: 1. 在你安装了 Tomcat 的目录下,有一个目录是 webapps。在这个目录下建立一个目录 (如:learn)。 2. 在第一步建立的目录下建立一个子目录,命名为 chapter。 3. 在 chapter 目录中,建立一个 HTML 文件,内容自定,文件名为 index.html。 4. 在第一步建立的目录下建立一个名为 WEB-INF 的子目录。 5. 在 WEB-INF 目录中创建一个名为 web.xml 的文件,该文件内容如下:





6. <?xml version="1.0" encoding="ISO-8859-1"?>

7. 

8. <!DOCTYPE web-app

9. PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"

10. "http://java.sun.com/dtd/web-app_2_3.dtd">

11. 

12. <web-app>

13. 

14. <description>

15. Learning Web Programming

16. </description>

17. 

18. <security-constraint>

19. <web-resource-collection>

20. <web-resource-name>

21. Restricted Area

22. </web-resource-name>

23. <url-pattern>/chapter/*</url-pattern>

24. </web-resource-collection>

25. <auth-constraint>

26. <role-name>tomcat</role-name>

27. <role-name>author</role-name>

28. <role-name>reader</role-name>

29. </auth-constraint>

30. </security-constraint>

31. 

32. <login-config>

33. <auth-method>BASIC</auth-method>

34. <realm-name>Authenticate yourself</realm-name>

35. </login-config>

36. 

</web-app>

web.xml 配置描述 web.xml 是描述配置的文件,这里集中说明一下安全相关的配置元素。 <security-constraint>:这个元素限制对一个或者多个资源的访问,可以在配置信息中出现多次。上面的配置信息中,它限制了 chapter 目录 (http://localhost:8080/learn/chapter) 下所有资源的访问。<security-constraint> 包含了下列元素: o <web-resource-collection>:这个元素用于标识你想限制访问的资源。你可以定义 URL 模式 和 HTTP 方法 (用 <http-method> 元素定义 HTTP 方法)。如果没有定义 HTTP 方法,那么限制将应用于所有方法。在上面的应用中,我想限制访问的资源是 http://localhost:8080/learn/chapter/*,也就是 chapter 目录下的所有文档。 o <auth-constraint>:这个元素可以访问上面定义的受限资源的用户角色。在上面的应用中,tomcat、author 和 erader 这三个角色可以访问这些资源。 <login-config>:这个元素用于指定验证方法。它包含下列元素: o <auth-method>:指定验证方法。它的值可能是下列值集中的一个:BASIC (基本验证)、DIGEST (摘要验证)、FORM (基于表单的验证) 或者 CLIENT-CERT (客户证书验证)。 o <realm-name>:如果选用 BASIC 方法进行验证的时候,标准登录对话框中的一个描述名称。 示例 上述配置中使用了 BASIC 验证方法。下面我们做个实验:启动你的 Tomcat 服务器并向它发送到 http://localhost:8080/learn/chapter 的请求。这时候,就会有像图 3 所示那样的对话框提示你输入用户和密码:
图 3:HTTP 基本验证 (Basic Authentication)
输入一个用户及其密码 (你可以看看 tomcat-users.xml 文件),这个用户的角色应该在配置 (web.xml) 中存在。如果你输入的用户名和密码正确,你就能访问到那些资源;否则,你还可以再试两次。 使用摘要验证来实验: · 关闭你的 Tomcat 服务器。 · 修改你的配置文件 (web.xml),把 BASIC 换成 DIGEST。 · 重新启动你的 Tomcat 服务器。 · 打开一个新的浏览器窗口。 · 在地址栏中输入 http://localhost:8080/learn/chapter 并回车。 你会看到类似的对话框。从图 4 你可以看到,这个登录对话框是安全的,因为使用了摘要验证。
图 4:HTTP 摘要验证 (Digest Authentication)
服务器在幕后的回复 当使用基本验证方法保护资源的时候,服务器发回类似于图 5 所示的响应信息:
图 5:服务器回复 (基本验证)
如果是使用的摘要验证方法来保护的资源,服务器发回的响应信息就像图 6 所示的那样:
图 6:服务器回复 (摘要验证)
Java 支持 HTTP 验证 J2SE (1.2 或者更高版本) 通过 Authenticator 类为验证提供了本地支持。你所要做的只是继承这个类并实现它的 getPasswordAuthentication 方法。这个方法取得用户名和密码并用它们生成一个 PasswordAuthentication 对象返回。完成之后,你还得使用 Authenticator.setDefault 方法注册你的 Authenticator 实例。现在,只要你想访问受保护的资源,就会调用 getPasswordAuthentication。Authenticator 类管理着所有低层的详细资料。它不受 HTTP 的限制,可以应用于所有网络连接,这不能不说是一个好消息。 示例代码 6 中是实现 Authenticator 的一个示例。正如你所看到的,在请求验证的时候,getPasswordAuthentication 方法会弹出一个登录对话框。 示例代码 6:AuthImpl.java



import java.net.*;

import java.awt.*;

import javax.swing.*;



public class AuthImpl extends Authenticator {

protected PasswordAuthentication getPasswordAuthentication() {

JTextField username = new JTextField();

JTextField password = new JPasswordField();

JPanel panel = new JPanel(new GridLayout(2,2));

panel.add(new JLabel("User Name"));

panel.add(username);

panel.add(new JLabel("Password") );

panel.add(password);

int option= JOptionPane.showConfirmDialog(null,

new Object[] {"Site: " getRequestingHost(),

"Realm: " getRequestingPrompt(),panel},

"Enter Network Password",

JOptionPane.OK_CANCEL_OPTION,

JOptionPane.PLAIN_MESSAGE);

if ( option == JOptionPane.OK_OPTION ) {

String user = username.getText();

char pass[] = password.getText().toCharArray();

return new PasswordAuthentication(user, pass);

} else {

return null;

}

}

}

示例代码 7 用来做测试的代码。我做的第一件事情就是用 Authenticator.setDefault 让我的 Authenticator 实例开始运行。我不必去解析任何服务器返回的信息以检查是否需要验证,因为 Authenticator 类非常聪明,它知道是否需要验证。 示例代码 7:BasicReader.java



import java.io.*;

import java.net.*;



public class BasicReader {

public static void main(String argv[]) throws Exception {

Authenticator.setDefault(new AuthImpl());

if (argv.length != 1) {

System.err.println("Usage: java BasicReader <site>");

System.exit(1);

}

URL url = new URL(argv[0]);

URLConnection connection = url.openConnection();

BufferedReader in= new BufferedReader(new InputStreamReader(connection.getInputStream()));



String line;

StringBuffer sb = new StringBuffer();

while ((line = in.readLine()) != null) {

sb.append(line);

}

in.close();

System.out.println(sb.toString());

System.exit(0);

}

}

运行下面的命令,用 Tomcat 来进行测试: prompt> java BasicReader http://localhost:8080/learn/chapter 如果你进入的站点需要验证 (它也这样做了),那会像图 7 那样的对话框就会显示出来。
图 7:Java 处理 HTTP 验证
一旦你输入了正确的用户名和密码,服务器就会允许你访问。BasicReader 会读取被请求页面的 HTML 内容并显示在你的控制台窗口。 特别注意:在 Tomcat 4.0 中使用摘要验证时你可能会遇到问题,这是由 J2SE 1.4.0 和 J2SE 1.4.1 的一个 BUG 引起的。不过这个问题已经在 J2SE 1.4.2 中解决了。详情情看这里。 总结 这篇文章是一篇教程,它介绍了 java.net 包的高层 API。这些 API 使你可以快速简捷地建立有用的网络应用程序,如 StockReader。这里也讨论了 HTTP 验证,并用实例演示了如何使用你自己的验证方案。URL 和 URLConnection 还有一些优势没有在文中提到,它们包括:自动重定向、自动管理保持的连接等。不过现在你已经从文中获得基础知识,可以自己解决这些问题了。
编程实践:寒武纪-LLM&VLM模型量化&部署 本文介绍了在MLU370-S4平台上对大模型(LLM/VLM)进行量化的两种方法:SmoothQuant和WeightOnly。以Qwen2-VL-2B模型为例,详细说明了两种量化方式的命令行参数配置,包括必须设置的per_channel选项和量化参数调整建议。量化完成后,提供了模型部署的具体命令示例,包含设备分配、端口设置、并行度等关键参数。文章强调在MLU370芯片上需要手动设置block_size,并指出两种量化方式只能二选一使用。配套资料已上传至百度网盘供参考。 阅读详情

相关推荐

自动驾驶技术路线之争:纯视觉与多模态融合的成本与性能博弈

本文深入剖析了自动驾驶领域两大主流技术路线——纯视觉与多模态融合的本质差异。文章从成本结构、性能博弈与商业逻辑等多维度展开,揭示了纯视觉方案在硬件成本与数据算力投入上的权衡,以及多模态融合方案在安全冗余与感知稳定性方面的优势。这场技术路线之争,实则是车企在性能、成本与商业化落地之间寻求平衡的综合博弈。

weixin_29038303的博客 391

使用 Authenticator.setDefault 时,修改账号密码无效的替换方案。

之前做过一个webservie项目,需要请求 带有用户名密码校验 的https  接口。 刚开始用的就是Authenticator.setDefault 来处理用户名密码校验,但是后台客户提出一个需求,用户名与密码需要可以改变。 天真的写好代码就给客户演示了。。。然后就被这玩意坑了。。。 找了不少资料,最后结果是说 这东西是jdk  2007的bug。。。。无解,只能找其他东西替换他了。

qq_15274099的博客 3364

用Multisim仿真AD630锁定放大器:从2012年电赛A题实战到避坑指南

本文详细介绍了如何使用Multisim仿真AD630锁定放大器,从2012年电赛A题实战出发,提供完整的电路搭建、参数优化及避坑指南。重点解析AD630的开关调制架构和双相位检测的工程实现,帮助读者在强噪声背景下有效提取微弱信号,提升电子设计竞赛和工程实践中的信号处理能力。

weixin_42549451的博客 203

SpringBoot代理配置

我们在公司开发时,经常会遇到代理配置问题。 下面的方法是配置SpringBoot的代理(应用场景,当SpringBoot访问第三方接口时) //配置代理 private static final String PROXY_HOST = "proxy.xxx.com"; private static final int PROXY_PORT = 8080; private static fin...

tq369的专栏 8292

工创赛智能搬运小车实战:视觉定位、底盘控制与RTOS调度

智能搬运系统是嵌入式控制与机器视觉融合的典型工程实践,其核心在于视觉定位精度、运动控制稳定性与实时任务调度能力。在有限算力(如STM32H7)、低功耗约束和结构化场景下,传统CV方法(如FAST+RANSAC)比轻量级深度学习更具鲁棒性与实时性;而底盘控制需穿透PID表层,直击死区补偿、编码器硬件滤波与负载自适应等物理层细节;RTOS则不是炫技工具,而是保障多模块时序确定性的刚需——尤其在视觉-控制-执行强耦合链路中,任务优先级、事件组通信与栈安全直接影响系统存活。本文聚焦全国大学生工程训练竞赛(工创赛)真

weixin_29194693的博客 275

deepseek本地部署及应用部署指南

如果你找到的日志是[send] via NET/IB/0,则表示网络通信是通过IB网络的,但是没有开启GDRDMA技术,则会有大致5%的性能损耗(网传,未实测)。新增的环境变量配置,主要用于启用IB网络通信,而非使用以太网进行通信,详细的每一个参数的具体含义,可以在英伟达NCCL的官方网站上找到说明。下一步,我会对已经完成部署的模型进行压测,来探索系统的性能极限在哪里,以及如何在生产环境中何如进行进一步的性能优化,期待你的关注。

weixin_39797121的博客 2625

Authenticator默认验证器分析

Authenticator默认验证器分析

wwj19941028的博客 1107

PLSQL 14.0.6 下载使用教程

众所周知,PLSQL 只是一个oracle第三方开发测试工具,它依赖oracle 客户端搭配使用,但是oracle 客户端有2G,相当庞大,不建议安装。所以我们如果下载安装好PLSQL,再下载好轻量级的支持远程链接的oracle客户端,这样搭配使用可以的话就最好了,答案是可以的。 第一步: PLSQL 下载与安装 PLSQL 14.0.6 下载地址 : https://www.allroundautomations.com/registered-plsqldev/ 下载下来,除了安装路径更改一下,

qq976511508的博客 2136

java实现http/https请求

最近有个功能是用java爬去大量url信息。网上找了个code了一段代码,拿来直接可以用,但是打包到jdk1.7上报407没有权限,于是手动添加了 String headerkey = "Proxy-Authorization"; String headerValue = "Basic "+Base64.encodeToString("*****:*****".getBytes(), false); //帐号密码用:隔开,base64加密方式 ...

chujian630的博客 1750

智能车八邻域图像算法_二

智能车八邻域图像算法 文章目录智能车八邻域图像算法前言一、一些想法二、生长方向的使用1.点的生长方向的表示2. 用点的生长方向来做初步判断1.引入库2.读入数据总结 前言 上一篇里面讲过用八邻域来获得赛道边界:智能车八邻域图像算法 当已经能稳定获得赛道边界时,就可以进行元素识别,获得偏差了。 这里就介绍一下我的一些思路。 早在前两年,优快云上就有一篇关于八邻域如何处理元素的文章第十五届全国大学生智能汽车竞赛-双车组三轮图像处理总结,写得很好,我当时也参考了这篇文章,但是我觉得不是很详细,所以我这里想写得

技术缝合怪的博客 1万+

STM32G4 电机外设篇(三) TIM1 发波 和 ADC COMP DAC级联

STM32G4电机控制外设应用笔记摘要:本文详细介绍了TIM1高级定时器生成三对互补PWM波的配置方法(预分频器PSC=30000,重装载值ARR=10000),重点说明需断开电机连线避免干扰。通过STM32CubeMX配置TIM1通道4触发ADC采样,设置RCR分频参数,并给出Keil代码修改要点。第二部分探讨了TIM1、ADC、比较器和DAC的级联应用,包括电流采样触发时序(在PWM波峰值前采样)和过流保护机制。配置步骤包含DAC3作为比较器负输入端、设置Break触发封波保护,并附关键代码段实现外设联

qq_43091070的博客 1103

Java 高层网络编程 (GET,POST取得数据)

Java 高层网络编程    java.net 包中的类和接口提供了可用于低层和高层网络编程的 API。低层 API 可以让你直接访问网络协议,但是为此你不得不使用低层的 TCP 套接字和 UDP 数据包。高层的 API (如 URL, URLConnection 和 httpURLConnection 等类) 可以使你更快的开发网络应用,却不需要写很多代码。另一篇文章,《

程序人生 3366

攻克反光难题!YOLOv9工业缺陷检测实战:高反光件、微小划痕精准识别(附抗反光代码+产线数据)

文章摘要:本文针对不锈钢、铝合金等高反光工业件的缺陷检测难题,提出了一套“硬件抗反光+YOLOv9小目标增强”的解决方案。通过分析反光干扰(镜面/漫反射)和微小划痕(0.1mm级)两大核心问题,详细介绍了500万像素工业相机+偏振光源的硬件配置方案,以及基于偏振图像融合和超分辨率放大的预处理方法。最终实现误检率1.2%、微小划痕检出率99.3%的工业级检测效果,并提供了可落地的代码实现和车间实测数据。(148字)

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1043

Java 高层网络编程 (GET,POST取得数据)

Java 高层网络编程     java.net 包中的类和接口提供了可用于低层和高层网络编程的 API。低层 API 可以让你直接访问网络协议,但是为此你不得不使用低层的 TCP 套接字和 UDP 数据包。高层的 API (如 URL, URLConnection 和 httpURLConnection 等类) 可以使你更快的开发网络应用,却不需要写很多代码。

1146

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

3.基于URL的高层次Java网络编程

你只管努力, 256

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Java低层次网络编程和高层次网络编程应用场合

Java的网络编程是基于传输层和应用层之间 在程序设计中,我们一般根据不同的应用场合选用不同层次的网络编程 基于Socket的低层次的网络编程:一个socket由一个IP地址和一个端口号唯一确定,通常实现客户端与服务端的连接,面向内部网络通信 基于URL的高层次的网络编程:通过URL(统一资源定位地址,就是网址)来访问Internet上的各种资源,由于URL使用http协议可跨越网络 防火墙,所以适用于面向Internet的通信 ...

一只可爱的小猴子的博客 538

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

上一篇: 谨防Java网络编程“陷阱”
下一篇: 一些面向对象的设计法则(1)
java169
博客等级 码龄19年 27粉丝 2568原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值