#
Executor
提供了管理终止的方法,以及可为跟踪一个或多个异步任务执行状况而生成 Future
的方法。
可以关闭 ExecutorService,这将导致其停止接受新任务。关闭后,执行程序将最后终止,这时没有任务在执行,也没有任务在等待执行,并且无法提交新任务。
通过创建并返回一个可用于取消执行和/或等待完成的 Future
,方法 submit 扩展了基本方法 Executor.execute(java.lang.Runnable)
。方法 invokeAny 和 invokeAll 是批量执行的最常用形式,它们执行任务集合,然后等待至少一个,或全部任务完成(可使用 ExecutorCompletionService
类来编写这些方法的自定义变体)。
Executors
类提供了用于此包中所提供的执行程序服务的工厂方法。
用法示例
下面给出了一个网络服务的简单结构,这里线程池中的线程作为传入的请求。它使用了预先配置的
Executors.newFixedThreadPool(int)
工厂方法:
class NetworkService {
private final ServerSocket serverSocket;
private final ExecutorService pool;
public NetworkService(int port, int poolSize) throws IOException {
serverSocket = new ServerSocket(port);
pool = Executors.newFixedThreadPool(poolSize);
}
public void serve() {
try {
for (;;) {
pool.execute(new Handler(serverSocket.accept()));
}
} catch (IOException ex) {
pool.shutdown();
}
}
}
class Handler implements Runnable {
private final Socket socket;
Handler(Socket socket) { this.socket = socket; }
public void run() {
// read and service request
}
}
压缩不仅仅可以提高用户的下载速度,同时还可以加密代码,下面说下一个常用的js压缩方法:
首先使用dojo的工具shrinksafe(http://shrinksafe.dojotoolkit.org/)压缩一下,dojo的这个
工具会去掉注释,他的压缩不是简单的替换变量,而是利用了mozilla的一个工具,对js解析后才压缩,确保压缩后的代码不会出错。
dojo压缩后,并不会减少太多,下一步可以使用http://javascriptcompressor.com/这个站点进行更高层次的压缩,可惜只能登陆这个站点再压缩,只能将你的js代码复制的他的文本框,然后等他的压缩输出
经过这2步,你的js会变得既安全,文件又小
关于JSP页面中的pageEncoding和contentType两种属性的区别:
pageEncoding是jsp文件本身的编码
contentType的charset是指服务器发送给客户端时的内容编码
JSP要经过两次的“编码”,第一阶段会用pageEncoding,第二阶段会用utf-8至utf-8,第三阶段就是由Tomcat出来的网页,
用的是contentType。Phontol.com
第一阶段是jsp编译成.java,它会根据pageEncoding的设定读取jsp,结果是由指定的编码方案翻译成统一的UTF-8
JAVA源码(即.java),如果pageEncoding设定错了,或没有设定,出来的就是中文乱码。Phontol.com
第二阶段是由JAVAC的JAVA源码至java
byteCode的编译,不论JSP编写时候用的是什么编码方案,经过这个阶段的结果全部是UTF-8的encoding的java源码。Phontol.com
JAVAC用UTF-8的encoding读取java源码,编译成UTF-8
encoding的二进制码(即.class),这是JVM对常数字串在二进制码(java encoding)内表达的规范。Phontol.com
第三阶段是Tomcat(或其的application
container)载入和执行阶段二的来的JAVA二进制码,输出的结果,也就是在客户端见到的,这时隐藏在阶段一和阶段二的参数contentType就发挥了功效
contentType的設定.
pageEncoding 和contentType的预设都是 ISO8859-1. 而随便设定了其中一个,
另一个就跟着一样了(TOMCAT4.1.27是如此). 但这不是绝对的, 这要看各自JSPC的处理方式.
而pageEncoding不等于contentType, 更有利亚洲区的文字 CJKV系JSP网页的开发和展示, (例pageEncoding=GB2312
不等于 contentType=utf-8)。
在Tomcat中如果在jsp中设定了pageEncoding,则contentType也跟着设定成相同的编码了,但是在resion中就不是,resin中还会用默认的,这点通过查看编译后的类servlet java文件就可以看到这一点,而问题恰恰就出在这里,所以,在jsp中,如果是在resin下最好还是明确的单独设定这2个属性。
jsp文件不像.java,.java在被编译器读入的时候默认采用的是操作系统所设定的locale所对应的编码,比如中国大陆就是GBK,台湾就是BIG5或者MS950。Phontol.com而一般我们不管是在记事本还是在ue中写代码,如果没有经过特别转码的话,写出来的都是本地编码格式的内容。Phontol.com所以编译器采用的方法刚好可以让虚拟机得到正确的资料。Phontol.com
但是jsp文件不是这样,它没有这个默认转码过程,但是指定了pageEncoding就可以实现正确转码了。Phontol.com
举个例子:
<%@ page contentType="text/html;charset=utf-8" %>
|
大都会打印出乱码,因为输入的“你好”是gbk的,但是服务器是否正确抓到“你好”不得而知。Phontol.com
但是如果更改为
<%@ page contentType="text/html;charset=utf-8" pageEncoding="GBK"%>
|
这样就服务器一定会是正确抓到“你好”了。Phontol.com
首先,在linux上安装perl-Mail-Sendmail-0.79-1.0.rh9.rf.noarch.rpm
perl 代码如下:
#!/usr/bin/perl
use Mail::Sendmail;
$delay = 1;
$f_list="list.txt";
$line = 0;#skip the column title line
my $subject="xxx";
open(FILE,$f_list) || die "Can not open list file\n";
while(<FILE>){
chomp;
$line=$line+1;
next if($line==1);
($email,$passwd,$username,$yonghuming) = split(/,/);
%mail = (
from => 'xxx@xxx.com',
to => $email,
subject => $subject,
'content-type' => 'text/html; charset="gbk"',
);
$mail{body} = <<END_OF_BODY;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gbk">
<title>个人邮箱登陆</title>
<style type="text/css">
<!--
body {
margin-left: 0px;
margin-top: 0px;
margin-right: 0px;
margin-bottom: 0px;
}
-->
</style>
<link href="images/css.css" rel="stylesheet" type="text/css">
<style type="text/css">
<!--
.style1 {font-size: 13px}
.style3 {color: #0066CC}
.style4 {color: #FF0000}
-->
</style>
</head>
<body>
<table width="60%" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td height="10" valign="bottom"><hr width="100%" size="10" color="#3399FF">test</td>
</tr>
</table>
</body>
</html>
END_OF_BODY
sendmail(%mail) || print "Error: $Mail::Sendmail::error\n";
sleep($delay);
}
close(FILE);
list file 内容格式:
xx@163.com,xdf.com,xxx,xxx
在firefox3下Components.classes 是不允许直接调用的,需要加上如下那句粗体的语句才可以
<script>
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var prefs = Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces.nsIPrefBranch);
prefs.setBoolPref("dom.allow_scripts_to_close_windows", true);
</script>
在chomal.manifest里如下设定,注意黄色部分,很关键
content sample chrome/content/
xpcnativewrappers=no
overlay chrome://browser/content/browser.xul chrome://sample/content/sample.xul
调用方式:
window.content.document.getElementById('sssddd').onclick();
参考如下连接
http://developer.mozilla.org/En/Safely_accessing_content_DOM_from_chrome
xpcnativewrappers
http://developer.mozilla.org/en/Chrome_Registration
<style type="text/css" media="all">
div,img{margin: 0;padding: 0;border: 0;}
#content{width: 303px;height: 404px;background: #F63;color: #000;font: 12px Arial,Helvetica,sans-serif;position: relative;}
#content div{position: absolute;left: 0;bottom: 0;}
</style>
</head>
<body>
<div id="content">
<div>底端对齐 </div>
</div>
select max(a.num) A,max(b.num) B,max(c.num) C,tttt.name from tttt
left join (select * from tttt where abc='C') c on c.abc=tttt.abc and c.name=tttt.name
left join (select * from tttt where abc='B') b on b.abc=tttt.abc and b.name=tttt.name
left join (select * from tttt where abc='A') a on a.abc=tttt.abc and a.name=tttt.name
group by name
很多朋友在深入的接触 JAVA 语言后就会发现这样两个词:反射 (Reflection) 和内省 (Introspector) ,经常搞不清楚这到底是怎么回事,在什么场合下应用以及如何使用?今天把这二者放在一起介绍,因为它们二者是相辅相成的。
反射
相对而言,反射比内省更容易理解一点。用一句比较白的话来概括,反射就是让你可以通过名称来得到对象 ( 类,属性,方法 ) 的技术。例如我们可以通过类名来生成一个类的实例;知道了方法名,就可以调用这个方法;知道了属性名就可以访问这个属性的值。
还是写两个例子让大家更直观的了解反射的使用方法:
引用
//通过类名来构造一个类的实例
Class cls_str = Class.forName( "java.lang.String" );
// 上面这句很眼熟,因为使用过 JDBC 访问数据库的人都用过 J
Object str = cls_str.newInstance();
// 相当于 String str = new String();
//通过方法名来调用一个方法
String methodName = "length" ;
Method m = cls_str.getMethod(methodName, null );
System.out.println( "length is " + m.invoke(str, null ));
// 相当于 System.out.println(str.length());
上面的两个例子是比较常用方法。看到上面的例子就有人要发问了:为什么要这么麻烦呢?本来一条语句就完成的事情干吗要整这么复杂?没错,在上面的例子中确实没有必要这么麻烦。不过你想像这样一个应用程序,它支持动态的功能扩展,也就是说程序不重新启动但是可以自动加载新的功能,这个功能使用一个具体类来表示。首先我们必须为这些功能定义一个接口类,然后我们要求所有扩展的功能类必须实现我指定的接口,这个规定了应用程序和可扩展功能之间的接口规则,但是怎么动态加载呢?我们必须让应用程序知道要扩展的功能类的类名,比如是 test.Func1 ,当我们把这个类名 ( 字符串 ) 告诉应用程序后,它就可以使用我们第一个例子的方法来加载并启用新的功能。这就是类的反射,请问你有别的选择吗?
关于方法的反射建议大家看我的另外一篇文章《 利用 Turbine 的事件映射来扩展 Struts 的功能 》,地址是: http://www.javayou.com/article/CSDN/extend_struts.html 。这篇文章详细介绍了如果通过反射来扩展 Struts 框架的功能。
内省
内省是 Java 语言对 Bean 类属性、事件的一种缺省处理方法。例如类 A 中有属性 name, 那我们可以通过 getName,setName 来得到其值或者设置新的值。通过 getName/setName 来访问 name 属性,这就是默认的规则。 Java 中提供了一套 API 用来访问某个属性的 getter/setter 方法,通过这些 API 可以使你不需要了解这个规则(但你最好还是要搞清楚),这些 API 存放于包 java.beans 中。
一般的做法是通过类 Introspector 来获取某个对象的 BeanInfo 信息,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后我们就可以通过反射机制来调用这些方法。下面我们来看一个例子,这个例子把某个对象的所有属性名称和值都打印出来:
引用
/*
* Created on 2004-6-29
*/
package demo;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
/**
* 内省演示例子
* @author liudong
*/
public class IntrospectorDemo {
String name;
public static void main(String[] args) throws Exception{
IntrospectorDemo demo = new IntrospectorDemo();
demo.setName( "Winter Lau" );
// 如果不想把父类的属性也列出来的话,
// 那 getBeanInfo 的第二个参数填写父类的信息
BeanInfo bi = Introspector.getBeanInfo(demo.getClass(), Object. class );
PropertyDescriptor[] props = bi.getPropertyDescriptors();
for ( int i=0;i<props.length;i++){
System.out.println(props[i].getName()+ "=" +
props[i].getReadMethod().invoke(demo, null ));
}
}
public String getName() {
return name;
}
public void setName(String name) {
this .name = name;
}
}
Web 开发框架 Struts 中的 FormBean 就是通过内省机制来将表单中的数据映射到类的属性上,因此要求 FormBean 的每个属性要有 getter/setter 方法。但也并不总是这样,什么意思呢?就是说对一个 Bean 类来讲,我可以没有属性,但是只要有 getter/setter 方法中的其中一个,那么 Java 的内省机制就会认为存在一个属性,比如类中有方法 setMobile ,那么就认为存在一个 mobile 的属性,这样可以方便我们把 Bean 类通过一个接口来定义而不用去关心具体实现,不用去关心 Bean 中数据的存储。比如我们可以把所有的 getter/setter 方法放到接口里定义,但是真正数据的存取则是在具体类中去实现,这样可提高系统的扩展性。
总结
将 Java 的反射以及内省应用到程序设计中去可以大大的提供程序的智能化和可扩展性。有很多项目都是采取这两种技术来实现其核心功能,例如我们前面提到的 Struts ,还有用于处理 XML 文件的 Digester 项目,其实应该说几乎所有的项目都或多或少的采用这两种技术。在实际应用过程中二者要相互结合方能发挥真正的智能化以及高度可扩展性。
另外,以下是SUN的java doc 对
Introspector的解释:
- public class Introspector
- extends Object
The Introspector class provides a standard way for tools to learn about the properties, events, and methods supported by a target Java Bean.
For each of those three kinds of information, the Introspector will separately analyze the bean's class and superclasses looking for either explicit or implicit information and use that information to build a BeanInfo object that comprehensively describes the target bean.
For each class "Foo", explicit information may be available if there exists a corresponding "FooBeanInfo" class that provides a non-null value when queried for the information. We first look for the BeanInfo class by taking the full package-qualified name of the target bean class and appending "BeanInfo" to form a new class name. If this fails, then we take the final classname component of this name, and look for that class in each of the packages specified in the BeanInfo package search path.
Thus for a class such as "sun.xyz.OurButton" we would first look for a BeanInfo class called "sun.xyz.OurButtonBeanInfo" and if that failed we'd look in each package in the BeanInfo search path for an OurButtonBeanInfo class. With the default search path, this would mean looking for "sun.beans.infos.OurButtonBeanInfo".
If a class provides explicit BeanInfo about itself then we add that to the BeanInfo information we obtained from analyzing any derived classes, but we regard the explicit information as being definitive for the current class and its base classes, and do not proceed any further up the superclass chain.
If we don't find explicit BeanInfo on a class, we use low-level reflection to study the methods of the class and apply standard design patterns to identify property accessors, event sources, or public methods. We then proceed to analyze the class's superclass and add in the information from it (and possibly on up the superclass chain).
Because the Introspector caches BeanInfo classes for better performance, take care if you use it in an application that uses multiple class loaders. In general, when you destroy a ClassLoader
that has been used to introspect classes, you should use the Introspector.flushCaches
or Introspector.flushFromCaches
method to flush all of the introspected classes out of the cache.
For more information about introspection and design patterns, please consult the JavaBeans specification.
FileInputStream 和 FileReader(头ho晕的)
FileReader 会做编码转换,FileInputStream会忠实于原始文件数据。任何形式的Reader都会涉及编码。
BufferedInputStream和BufferedOutputStream
BufferedInputStream:
添加了功能,即缓冲输入和支持 mark 和 reset 方法的能力。创建 BufferedInputStream
时即创建了一个内部缓冲区数组。读取或跳过流中的各字节时,必要时可根据所包含的输入流再次填充该内部缓冲区,一次填充多个字节。mark
操作记录输入流中的某个点,reset 操作导致在从所包含的输入流中获取新的字节前,再次读取自最后一次 mark 操作以来所读取的所有字节。
BufferedOutputStream:该类实现缓冲的输出流。通过设置这种输出流,应用程序就可以将各个字节写入基础输出流中,而不必为每次字节写入调用基础系统。
BufferedReader和FileReader
BufferedReader :由Reader类扩展而来,提供通用的缓冲方式文本读取,而且提供了很实用的readLine,读取分行文本很适合,BufferedReader是针对Reader的,不直接针对文件,也不是只针对文件读取。
FileReader
是由java.io.InputStreamReade扩展来的,是针对文件读取的。实际使用时往往用 BufferedReader
bufferedreader = new BufferedReader(new
FileReader("test.conf"));先建立一个文件reader,再用BufferedReader读。
FileInputStream和Reader
FileInputStream:
扩展自java.io.InputStream,InputStream提供的是字节流的读取,而非文本读取,这是和Reader类的根本区别。用
Reader读取出来的是char数组或者String ,使用InputStream读取出来的是byte数组。
Reader:Reader
类及其子类提供的字符流的读取char(16位),InputStream及其子类提供字节流的读取byte(8位),所以FileReader类是将文
件按字符流的方式读取,FileInputStream则按字节流的方式读取文件,BufferedReader的作用是提供缓冲,
InputStreamReader可以将读如stream转换成字符流方式(即reader)是reader和stream之间的桥梁
BufferedInputStream和BufferedOutputStream的一个例子
import java.io.*;
public class BufferedStreamDemo...{
public static void main(String[] args)...{
try...{
byte[] data=new byte[1];
File srcFile=new File("BufferedStreamDemo.java");
File desFile=new File("BufferedStreamDemo.txt");
BufferedInputStream bufferedInputStream=new BufferedInputStream(new FileInputStream(srcFile));
BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(new FileOutputStream(desFile));
System.out.println("复制文件: "+srcFile.length()+"字节");
while(bufferedInputStream.read(data)!=-1)...{
bufferedOutputStream.write(data);
}
//将缓冲区中的数据全部写出
bufferedOutputStream.flush();
System.out.println("复制完成");
//显示输出BufferedStreamDemo.txt文件的内容
bufferedInputStream =new BufferedInputStream(new FileInputStream(new File("BufferedStreamDemo.txt")));
while(bufferedInputStream.read(data)!=-1)...{
String str=new String(data);
System.out.print(str);
}
bufferedInputStream.close();
bufferedOutputStream.close();
}catch(ArrayIndexOutOfBoundsException e)...{
System.out.println("using: java useFileStream src des");
e.printStackTrace();
}catch(IOException e)...{
e.printStackTrace();
}
}
}