iLeichun

当前位置:首页Java

用Java统计java代码行数

分类:Java  来源:网络  时间:2010-9-14 23:30:58

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
*
* @author LC
*
*/
public class SumJavaCode {
static long normalLines = 0; // 空行
static long commentLines = 0; // 注释行
static long whiteLines = 0; // 代码行
public static void main(String[] args) {
SumJavaCode sjc = new SumJavaCode();
//目录
File f = new File("D:MyEclipse7_1Worklog_strutssrccomase");
System.out.println(f.getName());
sjc.treeFile(f);
System.out.println("空行:" + normalLines);
System.out.println("注释行:" + commentLines);
System.out.println("代码行:" + whiteLines);
}
/**
* 查找出一个目录下所有的.java文件
*
* @param f 要查找的目录
*/
private void treeFile(File f) {
File[] childs = f.listFiles();
//int count = 0;
//int sum = 0;
for (int i = 0; i < childs.length; i++) {
// System.out.println(preStr + childs[i].getName());
if (!childs[i].isDirectory()) {
if (childs[i].getName().matches(".*//.java$")) {
System.out.println(childs[i].getName());
//count ++;
sumCode(childs[i]);
}
} else {
treeFile(childs[i]);
//sum += count;
}
}
}
/**
* 计算一个.java文件中的代码行,空行,注释行
*
* @param file
* 要计算的.java文件
*/
private void sumCode(File file) {
BufferedReader br = null;
boolean comment = false;
try {
br = new BufferedReader(new FileReader(file));
String line = "";
try {
while ((line = br.readLine()) != null) {
line = line.trim();
if (line.matches("^[//s&&[^//n]]*$")) {
whiteLines++;
} else if (line.startsWith("/*") && !line.endsWith("*/")) {
commentLines++;
comment = true;
} else if (true == comment) {
commentLines++;
if (line.endsWith("*/")) {
comment = false;
}
} else if (line.startsWith("//")) {
commentLines++;
} else {
normalLines++;
}
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
br = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

Java中各类Cache机制实现解决方案

分类:Java  来源:网络  时间:2010-8-28 1:27:24

  在Java中,不同的类都有自己单独的Cache机制,实现的方法也可能有所不同,文章列举了Java中常见的各类Cache机制的实现方法,同时进行了综合的比较。

  OSCache

  OSCache是个一个广泛采用的高性能的Java EE缓存框架,OSCache能用于任何Java应用程序的普通的缓存解决方案。

  OSCache有以下特点:缓存任何对象,你可以不受限制的缓存部分jsp页面或HTTP请求,任何java对象都可以缓存。拥有全面的API--OSCache API给你全面的程序来控制所有的OSCache特性。

  永久缓存--缓存能随意的写入硬盘,因此允许昂贵的创建(expensive-to-create)数据来保持缓存,甚至能让应用重启。支持集群--集群缓存数据能被单个的进行参数配置,不需要修改代码。缓存记录的过期--你可以有最大限度的控制缓存对象的过期,包括可插入式的刷新策略(如果默认性能不需要时)。

  Java Caching System

  JSC(Java Caching System)是一个用分布式的缓存系统,是基于服务器的java应用程序。它是通过提供管理各种动态缓存数据来加速动态web应用。JCS和其他缓存系统一样,也是一个用于高速读取,低速写入的应用程序。动态内容和报表系统能够获得更好的性能。

  如果一个网站,有重复的网站结构,使用间歇性更新方式的数据库(而不是连续不断的更新数据库),被重复搜索出相同结果的,就能够通过执行缓存方式改进其性能和伸缩性。

  EHCache

  EHCache是一个纯Java的在进程中的缓存,它具有以下特性:快速,简单,为Hibernate 2.1充当可插入的缓存,最小的依赖性,全面的文档和测试。

  JCache

  JCache是个开源程序,正在努力成为JSR-107开源规范,JSR-107规范已经很多年没改变了。这个版本仍然是构建在最初的功能定义上。

  ShiftOne

  ShiftOne Java Object Cache是一个执行一系列严格的对象缓存策略的Java lib,就像一个轻量级的配置缓存工作状态的框架。

  SwarmCache

  SwarmCache是一个简单且有效的分布式缓存,它使用IP multicast与同一个局域网的其他主机进行通讯,是特别为集群和数据驱动web应用程序而设计的。SwarmCache能够让典型的读操作大大超过写操作的这类应用提供更好的性能支持。SwarmCache使用JavaGroups来管理从属关系和分布式缓存的通讯。

  TreeCache/JBossCache

  JBossCache是一个复制的事务处理缓存,它允许你缓存企业级应用数据来更好的改善性能。缓存数据被自动复制,让你轻松进行JBoss服务器之间的集群工作。JBossCache能够通过JBoss应用服务或其他J2EE容器来运行一个MBean服务,当然,它也能独立运行。

  JBossCache包括两个模块:TreeCache和TreeCacheAOP。TreeCache --是一个树形结构复制的事务处理缓存。TreeCacheAOP --是一个“面向对象”缓存,它使用AOP来动态管理POJO(Plain Old Java Objects)

  注:AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向方面编程。

  WhirlyCache

  Whirlycache是一个快速的、可配置的、存在于内存中的对象的缓存。它能够通过缓存对象来加快网站或应用程序的速度,否则就必须通过查询数据库或其他代价较高的处理程序来建立。

Java 7:最新特性更新、代码示例及性能测试

分类:Java  来源:网络  时间:2010-8-28 1:26:49

  如果说今年Java开发平台有什么大事儿,那就要数将于年底发布的Java 7了。之前51CTO曾报道过Java 7已经完成的七大新功能,包括新增的垃圾回收器G1、JVM动态语言支持以及模块化等等。进入2010年,Java 7有哪些新的进展?这些新的特性更新对我们有哪些好处?该如何使用?Java 7的性能如何?本文将给你答案。

  这里的内容主要包括其最新更新、一些代码实例、跟以前版本的Java进行性能比较需要参考的一些基准、以及什么时候它才会发布等信息。

  首先,让我们来看最重要的事情。为了确定JDK 7中有哪些语言方面的微小变化,有关人员建立了一个名叫Project Coin的项目。描述了最终的五个变化(比五个多一点)。

  Java 7更新内容如下所示:

  ◆允许在switch中使用字符串

  ◆自动资源管理

  ◆通用实例创建来改进类型推断(diamond)

  ◆简化的Varargs方法调用

  ◆更好的整型文字综合性建议

  ◆Collections集合的语言支持

  ◆JSR292的语言支持

  在the OpenJDK 7特性页面中,你还可以看到其他的功能。

  这些功能分为不同的种类:

  ◆虚拟机(VM)

  ◆压缩的64位对象指针

  ◆G1垃圾回收器GC(G1)

  ◆JSR 292:非Java语言的虚拟机支持(动态调用,InvokeDynamic)

  语言方面(lang)

  ◆SR 294:模块化编程的语言以及虚拟机支持

  ◆JSR 308:Java类型注释

  ◆语言微小增强(我所谈论的Project Coin)

  ◆JSR TBD: Project Lambda

  内核(core)

  ◆模块化(Jigsaw项目)

  ◆对类加载器的结构进行升级

  ◆关闭URLClassLoader的方法

  ◆Unicode 5.1标准

  ◆并行以及集合的升级(jsr166y)

  ◆JSR 203:Java平台(NIO.2)的更多新型I/O API

  ◆SCTP (流控制传输协议,Stream Control Transmission Protocol)

  ◆SDP (套接字直接协议,Sockets Direct Protocol)

  ◆椭圆曲线加密技术(ECC)

  客户端(client)

  ◆Java 2D的XRender管道

  ◆转发端口6u10部署特性

  ◆为6u10图形功能创建新的平台API

  ◆Swing的Nimbus外观和感觉

  ◆Swing的JLayer元件

  网络(web)

  ◆更新XML的栈

  就像你所看到的,这涉及了很多东西。几个月前,我亲自尝试了新的Garbage Collector (GC),其性能表现给我留下了非常深刻的印象。不幸的是,JVM几个小时就会崩溃一次,所以这个产品不能使用JVM。虽然在Java 1.6中也可以使用这个GC,但也会出现同样的问题,经常会出现崩溃。

  我想,这就是Java1.7增加新特性的原因。那么,现在我们最好去看一些代码实例。

  Java 7新特性的代码实例

  下面列出的大多数例子都是来源于Joe Wright博客中(Java7中的新语言特性)的高水平文章。

  集合的语言支持

  在这里我们主要讲的是,当创建一个List、Set或者Map的时候,你怎样尽量少写代码。你不必先实例化Object,然后再给Collection添加元素。你现在只需1行代码就可以完成。

  List list = ["item"]; String item = list[0]; Set set = {"item"}; Map map = {"key" : 1}; int value = map["key"];

  自动资源管理

  由于try / catch语句的原因,冗长的代码令人非常头痛。你或许会喜欢这个全新的特性。

  实际上,下面这些代码:

  BufferedReader br = new BufferedReader(new FileReader(path)); try { return br.readLine(); } finally { br.close(); }

  转变成了如下这种形式:

  try (BufferedReader br = new BufferedReader(new FileReader(path)) { return br.readLine(); }

  通用实例创建来改进类型推断(diamond)

  当你把对象的接口申明指定成范型后,你在对象实例化时不得不再指定一次。现在,你不必如此了,因为你可以这样:

  Map> map = new HashMap<>();

  数值文字的加强

  我不敢肯定这个对大多数人都有用。你可以这样做:

  int billion = 1_000_000_000;

  允许在switch中使用字符串

  这个无需解释,其意思很明确。

  String availability = "available"; switch(availability) { case "available": //code break; case "unavailable": //code break; case "merged": //code default: //code break; }

  二进制文字

  你可以使用前缀0b创建二进制文字

  int binary = 0b1001_1001;

  以上这些就是Java1.7的代码实例。如果有人能给我指出还有哪些没有包含进去,那就更好了。我敢肯定,已经有其他的开发人员对此进行了关注。

  Java 1.7的性能表现

  Java 7的性能有多大的提升?这里我们来针对Java 7做一个测试,内容如下。在一台装有ArchLinux系统的Macbook Pro电脑上(因特尔Duo CPU T7700,主频2.40GHz,有两年的使用时间)运行了这些测试。内存是2Gb的,把Heap Size设置成了728m(-Xms728m -Xmx728m)。

  ◆测试1 为一个List添加100万个字符串值(String字符串是一个UUID,是用UUID.randomUUID()产生的)。

  ◆测试2 带有100万键、值对的HashMap。每个键、值对通过并行线程进行计算。键是一个UUID,值int是用Math.random()产生的。

  ◆测试3 把100万个ArrayList条目打印到一定数量的文件(1000个)中。把条目写进恰巧并行的不同文件中。

  我只比较了Java1.6 (1.6.0_19) 和 Java 1.7 (b87)。后来根据评论的要求,我把Java1.5也添加了进来,但是并没有添加Java1.4,因为它的时间太久远了。

  结果如下所示:

  Java1.7性能测试

  Java 1.5Java 1.6Java 1.7

  Test 110,698 秒9,481秒9,328秒

  Test 269,827秒37,935秒36,636秒

  Test 326,931秒30,868秒27,383秒

  显然,不同版本之间的性能差异并不是特别大。

  Java 7的发布日期

  在2009年11月的时候,Java1.7计划是在2010年9月发布,到那时还将发布3个里程碑版本。其中,里程碑6在build 84版中已经完成,里程碑7的第一个测试版B85也计划在2010年3月4日完成,而本文使用的B87版本已在2010年3月25日发布。这样看起来,Java 1.7很有可能在2010年9月发布。让我们等待吧。

MyEclipse6.0连接SQL2000和2005

分类:Java  来源:网络  时间:2010-8-18 11:28:42

步骤:
1. 下载Microsoft SQL Server 2000 Driver for JDBC这个,并在MyEclipse 6.0中添加了引用
2. 加环境变量
    CLASSPATH值%JAVA_HOME%in;
    JAVA_HOME值C:Program FilesJavajdk1.6.0_02
    修改增加path值%JAVA_HOME%in;
3. 安装SQL 2000的SP3补丁
4. 在命令下测试telnet localhost 1433正常
代码如:
import java.sql.*;
public class HelloWorld {
   
    private static String driverName = "com.microsoft.jdbc.sqlserver.SQLServerDriver";

     private static String dbURL = "jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=pubs";

     private static Connection dbConn = null;
       
         public static void main(String [] args)
            {
             try
              {

               Class.forName(driverName);
               dbConn = DriverManager.getConnection(dbURL,"sa","");
               Statement sql = dbConn.createStatement();
               ResultSet set = sql.executeQuery("select * from jobs");
               while(set.next())
               {
                System.out.println(set.getString("job_id")+" "+
                  set.getString("job_desc"));
               }
               System.out.println("连接成功!");
               dbConn.close();
              } catch (ClassNotFoundException e)
              {
               e.printStackTrace();
              } catch (SQLException e)
              {
               e.printStackTrace();
              }
            }
}

测试成功!
连2005
1. 下载sqljdbc_1.1.1501.101_chs.exe并引入
2. 更改端口为5125(用360查出的)
import java.sql.*;

public class DbConnect {
    private static String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
    private static String dbURL = "jdbc:sqlserver://localhost:5125; DatabaseName=master";
    private static Connection dbConn = null;
    public static void main(String[] args) {
        try
          {
           Class.forName(driverName);
           dbConn = DriverManager.getConnection(dbURL,"sa","000000");
           Statement sql = dbConn.createStatement();
           ResultSet set = sql.executeQuery("SELECT * FROM spt_values");
           while(set.next())
           {
            //System.out.println(set.getString("name")+" "+
              //set.getString("number"));
            System.out.println(set.getString(1));
           }
           System.out.println("连接成功!");
           dbConn.close();
          } catch (ClassNotFoundException e)
          {
           e.printStackTrace();
          } catch (SQLException e)
          {
           e.printStackTrace();
          }
    }

}

Java加密技术

分类:Java  来源:网络  时间:2010-8-18 11:26:53

除了DES,我们还知道有DESede(TripleDES,就是3DES)、AES、Blowfish、RC2、RC4(ARCFOUR)等多种对称加密方式,其实现方式大同小异,这里介绍对称加密的另一个算法——PBE
  PBE
  PBE——Password-based encryption(基于密码加密)。其特点在于口令由用户自己掌管,不借助任何物理媒体;采用随机数(这里我们叫做盐)杂凑多重加密等方法保证数据的安全性。是一种简便的加密方式。
  通过java代码实现如下:
  import java.security.Key;
  import java.util.Random;
  import javax.crypto.Cipher;
  import javax.crypto.SecretKey;
  import javax.crypto.SecretKeyFactory;
  import javax.crypto.spec.PBEKeySpec;
  import javax.crypto.spec.PBEParameterSpec;
  /** *//**
  * PBE安全编码组件
  *
  */
  public abstract class PBECoder extends Coder {
  /** *//**
  * 支持以下任意一种算法
  *
  * <pre>
  * PBEWithMD5AndDES
  * PBEWithMD5AndTripleDES
  * PBEWithSHA1AndDESede
  * PBEWithSHA1AndRC2_40
  * </pre>
  */
  public static final String ALGORITHM = "PBEWITHMD5andDES";
  /** *//**
  * 盐初始化
  *
  * @return
  * @throws Exception
  */
  public static byte[] initSalt() throws Exception {
  byte[] salt = new byte[8];
  Random random = new Random();
  random.nextBytes(salt);
  return salt;
  }
  /** *//**
  * 转换密钥<br>
  *
  * @param password
  * @return
  * @throws Exception
  */
  private static Key toKey(String password) throws Exception {
  PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
  SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
  SecretKey secretKey = keyFactory.generateSecret(keySpec);
  return secretKey;
  }
  /** *//**
  * 加密
  *
  * @param data
  * 数据
  * @param password
  * 密码
  * @param salt
  * 盐
  * @return
  * @throws Exception
  */

        public static byte[] encrypt(byte[] data, String password, byte[] salt)
  throws Exception {
  Key key = toKey(password);
  PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 100);
  Cipher cipher = Cipher.getInstance(ALGORITHM);
  cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
  return cipher.doFinal(data);
  }
  /** *//**
  * 解密
  *
  * @param data
  * 数据
  * @param password
  * 密码
  * @param salt
  * 盐
  * @return
  * @throws Exception
  */
  public static byte[] decrypt(byte[] data, String password, byte[] salt)
  throws Exception {
  Key key = toKey(password);
  PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 100);
  Cipher cipher = Cipher.getInstance(ALGORITHM);
  cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
  return cipher.doFinal(data);
  }
  }
  再给出一个测试类:
  import static org.junit.Assert.*;
  import org.junit.Test;
  /** *//**
  *
  * @version 1.0
  * @since 1.0
  */
  public class PBECoderTest {
  @Test
  public void test() throws Exception {
  String inputStr = "abc";
  System.err.println("原文: " + inputStr);
  byte[] input = inputStr.getBytes();
  String pwd = "efg";
  System.err.println("密码: " + pwd);
  byte[] salt = PBECoder.initSalt();
  byte[] data = PBECoder.encrypt(input, pwd, salt);
  System.err.println("加密后: " + PBECoder.encryptBASE64(data));
  byte[] output = PBECoder.decrypt(data, pwd, salt);
  String outputStr = new String(output);
  System.err.println("解密后: " + outputStr);
  assertEquals(inputStr, outputStr);
  }
  }
  控制台输出:
  原文: abc
  密码: efg
  加密后: iCZ0uRtaAhE=
  解密后: abc

       RSA
  这种算法1978年就出现了,它是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作,也很流行。算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman.这种加密算法的特点主要是密钥的变化,上文我们看到DES只有一个密钥。相当于只有一把钥匙,如果这把钥匙丢了,数据也就不安全了。RSA同时有两把钥匙,公钥与私钥。同时支持数字签名。数字签名的意义在于,对传输过来的数据进行校验。确保数据在传输工程中不被修改。
  流程分析:
  1、甲方构建密钥对儿,将公钥公布给乙方,将私钥保留。
  2、甲方使用私钥加密数据,然后用私钥对加密后的数据签名,发送给乙方签名以及加密后的数据;乙方使用公钥、签名来验证待解密数据是否有效,如果有效使用公钥对数据解密。
  3、乙方使用公钥加密数据,向甲方发送经过加密后的数据;甲方获得加密数据,通过私钥解密。
  通过java代码实现如下:
  import java.security.Key;
  import java.security.KeyFactory;
  import java.security.KeyPair;
  import java.security.KeyPairGenerator;
  import java.security.PrivateKey;
  import java.security.PublicKey;
  import java.security.Signature;
  import java.security.interfaces.RSAPrivateKey;
  import java.security.interfaces.RSAPublicKey;
  import java.security.spec.PKCS8EncodedKeySpec;
  import java.security.spec.X509EncodedKeySpec;
  import java.util.HashMap;
  import java.util.Map;
  import javax.crypto.Cipher;
  /** *//**
  * RSA安全编码组件
  *
  * @version 1.0
  * @since 1.0
  */
  public abstract class RSACoder extends Coder {
  public static final String KEY_ALGORITHM = "RSA";
  public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
  private static final String PUBLIC_KEY = "RSAPublicKey";
  private static final String PRIVATE_KEY = "RSAPrivateKey";
  /** *//**
  * 用私钥对信息生成数字签名
  *
  * @param data
  * 加密数据
  * @param privateKey
  * 私钥
  *
  * @return
  * @throws Exception
  */
  public static String sign(byte[] data, String privateKey) throws Exception {
  // 解密由base64编码的私钥
  byte[] keyBytes = decryptBASE64(privateKey);
  // 构造PKCS8EncodedKeySpec对象
  PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  // KEY_ALGORITHM 指定的加密算法
  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  // 取私钥匙对象
  PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
  // 用私钥对信息生成数字签名
  Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
  signature.initSign(priKey);
  signature.update(data);
  return encryptBASE64(signature.sign());
  }
  /** *//**
  * 校验数字签名
  *
  * @param data
  * 加密数据
  * @param publicKey
  * 公钥
  * @param sign
  * 数字签名
  *
  * @return 校验成功返回true 失败返回false
  * @throws Exception
  *
  */
  public static boolean verify(byte[] data, String publicKey, String sign)
  throws Exception {
  // 解密由base64编码的公钥
  byte[] keyBytes = decryptBASE64(publicKey);
  // 构造X509EncodedKeySpec对象
  X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
  // KEY_ALGORITHM 指定的加密算法
  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  // 取公钥匙对象
  PublicKey pubKey = keyFactory.generatePublic(keySpec);
  Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
  signature.initVerify(pubKey);
  signature.update(data);
  // 验证签名是否正常
  return signature.verify(decryptBASE64(sign));
  }

       /** *//**
  * 解密<br>
  * 用私钥解密
  *
  * @param data
  * @param key
  * @return
  * @throws Exception
  */
  public static byte[] decryptByPrivateKey(byte[] data, String key)
  throws Exception {
  // 对密钥解密
  byte[] keyBytes = decryptBASE64(key);
  // 取得私钥
  PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
  // 对数据解密
  Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  cipher.init(Cipher.DECRYPT_MODE, privateKey);
  return cipher.doFinal(data);
  }
  /** *//**
  * 解密<br>
  * 用私钥解密
  *
  * @param data
  * @param key
  * @return
  * @throws Exception
  */
  public static byte[] decryptByPublicKey(byte[] data, String key)
  throws Exception {
  // 对密钥解密
  byte[] keyBytes = decryptBASE64(key);
  // 取得公钥
  X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  Key publicKey = keyFactory.generatePublic(x509KeySpec);
  // 对数据解密
  Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  cipher.init(Cipher.DECRYPT_MODE, publicKey);
  return cipher.doFinal(data);
  }
  /** *//**
  * 加密<br>
  * 用公钥加密
  *
  * @param data
  * @param key
  * @return
  * @throws Exception
  */
  public static byte[] encryptByPublicKey(byte[] data, String key)
  throws Exception {
  // 对公钥解密
  byte[] keyBytes = decryptBASE64(key);
  // 取得公钥
  X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  Key publicKey = keyFactory.generatePublic(x509KeySpec);
  // 对数据加密
  Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  cipher.init(Cipher.ENCRYPT_MODE, publicKey);
  return cipher.doFinal(data);
  }
  /** *//**
  * 加密<br>
  * 用私钥加密
  *
  * @param data
  * @param key
  * @return
  * @throws Exception
  */
  public static byte[] encryptByPrivateKey(byte[] data, String key)
  throws Exception {
  // 对密钥解密
  byte[] keyBytes = decryptBASE64(key);
  // 取得私钥
  PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
  // 对数据加密
  Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  cipher.init(Cipher.ENCRYPT_MODE, privateKey);
  return cipher.doFinal(data);
  }
  /** *//**
  * 取得私钥
  *
  * @param keyMap
  * @return
  * @throws Exception
  */
  public static String getPrivateKey(Map<String, Object> keyMap)
  throws Exception {
  Key key = (Key) keyMap.get(PRIVATE_KEY);
  return encryptBASE64(key.getEncoded());
  }
  /** *//**
  * 取得公钥
  *
  * @param keyMap
  * @return
  * @throws Exception
  */
  public static String getPublicKey(Map<String, Object> keyMap)
  throws Exception {
  Key key = (Key) keyMap.get(PUBLIC_KEY);
  return encryptBASE64(key.getEncoded());
  }
  /** *//**
  * 初始化密钥
  *
  * @return
  * @throws Exception
  */

        public static Map<String, Object> initKey() throws Exception {
  KeyPairGenerator keyPairGen = KeyPairGenerator
  .getInstance(KEY_ALGORITHM);
  keyPairGen.initialize(1024);
  KeyPair keyPair = keyPairGen.generateKeyPair();
  // 公钥
  RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
  // 私钥
  RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
  Map<String, Object> keyMap = new HashMap<String, Object>(2);
  keyMap.put(PUBLIC_KEY, publicKey);
  keyMap.put(PRIVATE_KEY, privateKey);
  return keyMap;
  }
  }
  再给出一个测试类:
  import static org.junit.Assert.*;
  import org.junit.Before;
  import org.junit.Test;
  import java.util.Map;
  /** *//**
  *
  * @version 1.0
  * @since 1.0
  */
  public class RSACoderTest {
  private String publicKey;
  private String privateKey;
  @Before
  public void setUp() throws Exception {
  Map<String, Object> keyMap = RSACoder.initKey();
  publicKey = RSACoder.getPublicKey(keyMap);
  privateKey = RSACoder.getPrivateKey(keyMap);
  System.err.println("公钥: " + publicKey);
  System.err.println("私钥: " + privateKey);
  }
  @Test
  public void test() throws Exception {
  System.err.println("公钥加密——私钥解密");
  String inputStr = "abc";
  byte[] data = inputStr.getBytes();
  byte[] encodedData = RSACoder.encryptByPublicKey(data, publicKey);
  byte[] decodedData = RSACoder.decryptByPrivateKey(encodedData,
  privateKey);
  String outputStr = new String(decodedData);
  System.err.println("加密前: " + inputStr + " " + "解密后: " + outputStr);
  assertEquals(inputStr, outputStr);
  }
  @Test
  public void testSign() throws Exception {
  System.err.println("私钥加密——公钥解密");
  String inputStr = "sign";
  byte[] data = inputStr.getBytes();
  byte[] encodedData = RSACoder.encryptByPrivateKey(data, privateKey);
  byte[] decodedData = RSACoder
  .decryptByPublicKey(encodedData, publicKey);
  String outputStr = new String(decodedData);
  System.err.println("加密前: " + inputStr + " " + "解密后: " + outputStr);
  assertEquals(inputStr, outputStr);
  System.err.println("私钥签名——公钥验证签名");
  // 产生签名
  String sign = RSACoder.sign(encodedData, privateKey);
  System.err.println("签名: " + sign);
  // 验证签名
  boolean status = RSACoder.verify(encodedData, publicKey, sign);
  System.err.println("状态: " + status);
  assertTrue(status);
  }
  }
  Console代码:
  公钥:
  MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYU/+I0+z1aBl5X6DUUOHQ7FZpmBSDbKTtx89J
  EcB64jFCkunELT8qiKly7fzEqD03g8ALlu5XvX+bBqHFy7YPJJP0ekE2X3wjUnh2NxlqpH3/B/xm
  1ZdSlCwDIkbijhBVDjA/bu5BObhZqQmDwIxlQInL9oVz+o6FbAZCyHBd7wIDAQAB
  私钥:
  MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJhT/4jT7PVoGXlfoNRQ4dDsVmmY
  FINspO3Hz0kRwHriMUKS6cQtPyqIqXLt/MSoPTeDwAuW7le9f5sGocXLtg8kk/R6QTZffCNSeHY3
  GWqkff8H/GbVl1KULAMiRuKOEFUOMD9u7kE5uFmpCYPAjGVAicv2hXP6joVsBkLIcF3vAgMBAAEC
  gYBvZHWoZHmS2EZQqKqeuGr58eobG9hcZzWQoJ4nq/CarBAjw/VovUHE490uK3S9ht4FW7Yzg3LV
  /MB06Huifh6qf/X9NQA7SeZRRC8gnCQk6JuDIEVJOud5jU+9tyumJakDKodQ3Jf2zQtNr+5ZdEPl
  uwWgv9c4kmpjhAdyMuQmYQJBANn6pcgvyYaia52dnu+yBUsGkaFfwXkzFSExIbi0MXTkhEb/ER/D
  rLytukkUu5S5ecz/KBa8U4xIslZDYQbLz5ECQQCy5dutt7RsxN4+dxCWn0/1FrkWl2G329Ucewm3
  QU9CKu4D+7Kqdj+Ha3lXP8F0Etaaapi7+EfkRUpukn2ItZV/AkEAlk+I0iphxT1rCB0Q5CjWDY5S
  Df2B5JmdEG5Y2o0nLXwG2w44OLct/k2uD4cEcuITY5Dvi/4BftMCZwm/dnhEgQJACIktJSnJwxLV
  o9dchENPtlsCM9C/Sd2EWpqISSUlmfugZbJBwR5pQ5XeMUqKeXZYpP+HEBj1nS+tMH9u2/IGEwJA
  fL8mZiZXan/oBKrblAbplNcKWGRVD/3y65042PAEeghahlJMiYquV5DzZajuuT0wbJ5xQuZB01+X
  nfpFpBJ2dw==
  公钥加密——私钥解密
  加密前: abc
  解密后: abc
  公钥:
  MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdOj40yEB48XqWxmPILmJAc7UecIN7F32etSHF
  9rwbuEh3+iTPOGSxhoSQpOED0vOb0ZIMkBXZSgsxLaBSin2RZ09YKWRjtpCA0kDkiD11gj4tzTiM
  l9qq1kwSK7ZkGAgodEn3yIILVmQDuEImHOXFtulvJ71ka07u3LuwUNdB/wIDAQAB
  私钥:
  MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAN06PjTIQHjxepbGY8guYkBztR5w
  g3sXfZ61IcX2vBu4SHf6JM84ZLGGhJCk4QPS85vRkgyQFdlKCzEtoFKKfZFnT1gpZGO2kIDSQOSI
  PXWCPi3NOIyX2qrWTBIrtmQYCCh0SffIggtWZAO4QiYc5cW26W8nvWRrTu7cu7BQ10H/AgMBAAEC
  gYEAz2JWBizjI31bqhP4XiP9PuY5F3vqBW4T+L9cFbQiyumKJc58yzTWUAUGKIIn3enXLG7dNqGr
  mbJro4JeFIJ3CiVDpXR9+FluIgI4SXm7ioGKF2NOMA9LR5Fu82W+pLfpTN2y2SaLYWEDZyp53BxY
  j9gUxaxi1MQs+C1ZgDF2xmECQQDy70bQntbRfysP+ppCtd56YRnES1Tyekw0wryS2tr+ivQJl7JF
  gp5rPAOXpgrq36xHDwUspQ0sJ0vj0O7ywxr1AkEA6SAaLhrJJrYucC0jxwAhUYyaPN+aOsWymaRh
  9jA/Wc0wp29SbGTh5CcMuGpXm1g0M+FKW3dGiHgS3rVUKim4owJAbnxgapUzAgiiHxxMeDaavnHW
  9C2GrtjsO7qtZOTgYI/1uT8itvZW8lJTF+9OW8/qXE76fXl7ai9dFnl5kzMk2QJBALfHz/vCsArt
  mkRiwY6zApE4Z6tPl1V33ymSVovvUzHnOdD1SKQdD5t+UV/crb3QVi8ED0t2B0u0ZSPfDT/D7kMC
  QDpwdj9k2F5aokLHBHUNJPFDAp7a5QMaT64gv/d48ITJ68Co+v5WzLMpzJBYXK6PAtqIhxbuPEc2
  I2k1Afmrwyw=
  私钥加密——公钥解密
  加密前: sign
  解密后: sign
  私钥签名——公钥验证签名
  签名:
  ud1RsIwmSC1pN22I4IXteg1VD2FbiehKUfNxgVSHzvQNIK+d20FCkHCqh9djP3h94iWnIUY0ifU+
  mbJkhAl/i5krExOE0hknOnPMcEP+lZV1RbJI2zG2YooSp2XDleqrQk5e/QF2Mx0Zxt8Xsg7ucVpn
  i3wwbYWs9wSzIf0UjlM=
  状态:
  true
  简要总结一下,使用公钥加密、私钥解密,完成了乙方到甲方的一次数据传递,通过私钥加密、公钥解密,同时通过私钥签  名、公钥验证签名,完成了一次甲方到乙方的数据传递与验证,两次数据传递完成一整套的数据交互!
  类似数字签名,数字信封是这样描述的:
  数字信封
  数字信封用加密技术来保证只有特定的收信人才能阅读信的内容。
  流程:
  信息发送方采用对称密钥来加密信息,然后再用接收方的公钥来加密此对称密钥(这部分称为数字信封),再将它和信息一起发送给接收方;接收方先用相应的私钥打开数字信封,得到对称密钥,然后使用对称密钥再解开信息。

Java5.0的元注解

分类:Java  来源:网络  时间:2010-8-16 19:16:40

许多API都需要为数不少的“模板式”的代码,比如,如果想写一个JAX-RPC(JAX-RPC即Java API for XML-Based RPC-译注)的web service,你需要提供一对接口及其实现程序。如果程序本身能被表明哪些方法可以由远程访问的注释所“修饰”的话,那么这种“模板式”的代码就可以用工具自动生成。

另一些API需要在维护程序的同时维护一些“辅助”文件,比如,维护JavaBean的同时需要维护BeanInfo类,Enterprise JavaBeans (EJB) 则需要部署说明档(deployment descriptor)。如果这些辅助信息能在程序中作为注解来维护,就会方便地多,并且也不容易犯错。

Java平台已经提供了几种不同的注解机制。比如transient修饰符就是一种特别的注解,标明被修饰的字段在序列化的子系统应该被忽略,@deprecated 作为javadoc的特殊标签,标明该方法不应该再用。在5.0版本中,Java平台提供了一种一般性的注解(即元数据metadata)机制,允许你自定义注解类型和使用该类型。该机制包含注解的定义语法、声明语法、读取注解的API、注解的代理类文件以及注解的一个处理工具。

注解并不直接对程序语义产生影响,但是会对工具或库在处理程序的方式上时产生影响,进而影响程序在运行时的语义。注解可以从源文件或类文件中读取,甚至在运行时以反射方式读取。

注解是对javadoc标签的补充。一般而言,如果标注的目的是影响或产生文档,那么就该用javadoc标签,否则就用注解。典型的应用程序的程序员永远不必自己定义一个注解类型,但其实真要做也不难。注解类型的定义跟接口定义相似,只是需要在inteface关键字前面加一个at符(@),声明一个方法即为注解类型定义一个元素。方法声明时不允许有参数或throw语句,返回值类型被限定为原始数据类型、字符串String、Class、枚举enums、注解类型,或前面这些的数组,方法可以有默认值,下面是一个定义注解类型的例子:

/**
 * Describes the Request-For-Enhancement(RFE) that led
 * to the presence of the annotated API element.
 */
public @interface RequestForEnhancement {
    int    id();
    String synopsis();
    String engineer() default "[unassigned]";
    String date();    default "[unimplemented]";
}一旦完成定义,就可以使用它做注解声明。注解是一个特殊的修饰符,可以和其他修饰符一样(如public,static,final)用在各种地方。为方便计,注解一般放在最前面。注解修饰符由@符号、注解类型名和括号括起来的元素名/值对组成。下面这个例子声明一个方法使用了上面所定义的注解。

@RequestForEnhancement(
    id       = 2868724,
    synopsis = "Enable time-travel",
    engineer = "Mr. Peabody",
    date     = "4/1/3007"
)
public static void travelThroughTime(Date destination) { ... }
注解类型如果不含任何元素,被称为“标记”注解类型,如:

/**
 * Indicates that the specification of the annotated API element
 * is preliminary and subject to change.
 */
public @interface Preliminary { }
“标记”注解类型允许忽略括号,如下:

@Preliminary public class TimeTravel { ... }
如果注解只有一个元素,那么该元素应该被命名为value,如下:

/**
 * Associates a copyright notice with the annotated API element.
 */
public @interface Copyright {
    String value();
}
如果注解只有一个元素,并且元素名为value,那么元素名和等号(=)都可以忽略不写,如下:

@Copyright("2002 Yoyodyne Propulsion Systems")
public class OscillationOverthruster { ... }
我们将建一个简单的基于注解的测试框架,将前面所讲的合起来用。首先我们定义一个“标记”注解类型,来说明某个方法是一个测试方法,需要被测试工具执行:

import java.lang.annotation.*;

/**
 * Indicates that the annotated method is a test method.
 * This annotation should be used only on parameterless static methods.
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Test { }
注意这个注解本身也是被注解的。这些注解被称为“元注解” (meta-annotations). 第一个(@Retention(RetentionPolicy.RUNTIME)) 表示注解由虚拟机保留,可以在运行时通过反射读取;第二个(@Target(ElementType.METHOD)) 表示注解只能用在方法上。

下面是一个例子程序,其中的一些方法由上面所定义的注解来修饰:

public class Foo {
    @Test public static void m1() { }
    public static void m2() { }
    @Test public static void m3() {
        throw new RuntimeException("Boom");
    }
    public static void m4() { }
    @Test public static void m5() { }
    public static void m6() { }
    @Test public static void m7() {
        throw new RuntimeException("Crash");
    }
    public static void m8() { }
}
下面是测试工具程序:

import java.lang.reflect.*;

public class RunTests {
   public static void main(String[] args) throws Exception {
      int passed = 0, failed = 0;
      for (Method m : Class.forName(args[0]).getMethods()) {
         if (m.isAnnotationPresent(Test.class)) {
            try {
               m.invoke(null);
               passed++;
            } catch (Throwable ex) {
               System.out.printf("Test %s failed: %s %n", m, ex.getCause());
               failed++;
            }
         }
      }
      System.out.printf("Passed: %d, Failed %d%n", passed, failed);
   }
}
这个工具程序将一个类名作为命令行运行时的参数,然后遍历该类的所有方法,并尝试调用每一个被“Test”注解(就是上面所定义的)所修饰的方法。那行绿色的代码以反射调用方式查找方法是否被“Test”注解所修饰。如果调用测试方法时抛出异常,就认为测试失败,测试失败的信息就会打印出来。最后作为总结,测试失败的方法个数和测试成功的方法个数也会打印出来。下面是对Foo程序(就是上面那个)运行测试工具得到的结果:

$ java RunTests Foo
Test public static void Foo.m3() failed: java.lang.RuntimeException: Boom
Test public static void Foo.m7() failed: java.lang.RuntimeException: Crash
Passed: 2, Failed 2
这个测试工具无疑是个玩具程序,但它表明了注解的强大,并能很容易的扩展为一个有用的工具。