梦想空间's profile梦想空间PhotosBlogListsMore Tools Help

Blog


    July 10

    java类加载的表现形式(收藏)

    使用者角度

    java中的类是动态加载的,我们先看一下我们常用的类加载方式,先有一个感性的认识,才能进一步
    深入讨论,类加载无非就是下面三种方式。
    class A{}
    class B{}
    class C{}
    public class Loader{
        public static void main(String[] args) throws Exception{
           Class aa=A.class;
           Class bb=Class.forName("B");
           Class cc=ClassLoader.getSystemClassLoader().loadClass("C");
        }
    }
    我们先看.class字面量方式,很多人可能不知道这种方式,因为这种用法不是一般java语法。
    通过javap我们可以发现,这种方式的大致等价于定义了一个静态成员变量
        static Class class$0;(后面的编号是增长的)
    你可以试图再定义一个  static Class class$0,应该会收到一个编译错误(重复定义)。
    Class aa=A.class;
    就相当于
        if(class$0==null){
     try{
               Class.forName("A");
     }
     cacth(ClassNotFoundException e){
        throw new NoClassDefFoundError(e);
     }
        }
        Class aa=class$0;
    可以很清楚的看到,这种类的字面量定义其实不是加载类的方式,而是被编译器处理了,实质
    上是使用了Class.forName方法,但是使用这种方式有一个很大的好处就是不用处理异常,因为
    编译器处理的时候如果找不到类会抛出一个NoClassDefFoundError。也许你觉得需要处理
    ClassNotFoundException这种异常,事实上99%的情况下我们可以把这种异常认为是一个错误。
    所以大部分情况我们使用这种方式会更简洁。
    最常用的方式就是Class.forName方式了,这也是一个通用的上层调用。这个方法有两个重载,
    可能很多人都忽略了第二个方法。
    public static Class forName(String name) throws ClassNotFoundException
    public static Class forName(String name, boolean initialize,ClassLoader loader) throws ClassNotFoundException
    第二个方法后面多了两个参数,第二个参数表示是否初始化,第三个参数为指定的类加载器。
    在上面的例子中:
    Class bb=Class.forName("B");等价于
    Class bb=Class.forName("B",true,Loader.class.getClassLoader());
    这里要详细说一下这个类的初始化这个参数,如果这个参数为false的话,
    类中的static成员不会被初始化,static语句块也不会被执行。
    也就是类虽然被加载了,但是没有被初始化,不过在第一次使用时仍然会初始化。
    所以我们有时候会看到Class.forName("XXX").newInstance()这样的语句,为什么这里要创建一个
    不用的实例呢?不过是为了保证类被初始化(兼容以前的系统)。
    其实第二个方法是比较难用的,需要指定类加载器,如果不指定而且又没有安装安全管理器的化,
    是无法加载类的,只要看一下具体的实现就明白了。
    最本质的方式当然是直接使用ClassLoader加载了,所有的类最终都是通过ClassLoader加载的,
    Class cc=ClassLoader.getSystemClassLoader().loadClass("C");
    这里通过使用系统类加载器来加载某个类,很直接的方式,但是很遗憾的是通过这种方式加载类,
    类是没有被初始化的(也就是初始化被延迟到真正使用的时候).不过我们也可以借鉴上面的经验,加载
    后实例化一个对象Class cc=ClassLoader.getSystemClassLoader().loadClass("C").newInstance()。
    这里使用了系统类加载器,也是最常用的类加载器,从classpath中寻找要加载的类。
    java中默认有三种类加载器:引导类加载器,扩展类加载器,系统类加载器。
    java中的类加载有着规范的层次结构,如果我们要了解类加载的过程,需要明确知道哪个类被谁
    加载,某个类加载器加载了哪些类等等,就需要深入理解ClassLoader的本质。
    以上只是类加载的表面的东西,我们还将讨论深层次的东西。

    java中的时间操作(收藏)

    java中的时间操作不外乎这四种情况:

    1、获取当前时间

    2、获取某个时间的某种格式

    3、设置时间

    4、时间的运算

    好,下面就针对这三种情况,一个一个搞定。

     

    一、获取当前时间

     

    有两种方式可以获得,第一种,使用Date类。

    j2SE的包里有两个Date类,一个是java.sql.Date,一个是java.util.Date

    这里,要使用java.util.Date。获取当前时间的代码如下

    Date date = new Date();

    date.getTime();

    还有一种方式,使用System.currentTimeMillis();

     

    这两种方式获得的结果是一样的,都是得到一个当前的时间的long型的时间的毫秒值,这个值实际上是当前时间值与1970年一月一号零时零分零秒相差的毫秒数。

    当前的时间得到了,但实际的应用中最后往往不是要用这个long型的东西,用户希望得到的往往是一个时间的字符串,比如“2006618号”,或“2006-06-18”,老外可能希望得到的是“06-18-2006”,诸如此类等等。这就是下一个要解决的问题

     

    二、获取某个时间的某种格式

     

    获取时间的格式,需要用到一个专门用于时间格式的类java.text.SimpleDateFormat

    首先,定义一个SimpleDateFormat变量

    SimpleDateFormat sdf = new SimpleDateFormat("",Locale.SIMPLIFIED_CHINESE);

    这个构造函数的定义如下:

    SimpleDateFormat(String pattern, Locale locale)

    第一个参数pattern,我们后面再解释,这里我们使用一个"",第二个参数,是用来设置时区的,这里用到了java.util.Locale这个类,这个类了面定义了很多静态变量,直接拿过来用就OK,我们把时区设置为Locale.SIMPLIFIED_CHINESE,只看名字,这个静态变量的意义已经很清楚了。

     

    接下来我们使用这个SimpleDateFormat把当前时间格式化为一个如下格式的时间字符串“XXXXXXXX_XXXXXX秒”,代码:

    sdf.applyPattern("yyyy年MM月dd日_HH时mm分ss秒");

    String timeStr = sdf.format(new Date());

     

    获取时间格式的函数是format,这个函数的参数是java.util.Date对象,这个没有什么花头。

    要说明一下的是这个pattern,所谓的模式。这里,yyyy,MM,dd等,这就是模式。

    我们可以在SimpleDateFormat的构造函数中指定模式,比如

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd",Locale.SIMPLIFIED_CHINESE);

    也可以获取时间格式的时候使用applyPattern函数临时指定,上面的例子就是这样。

    什么字符代表什么,这是j2se约定好的,设置模式的时候,我们可以使用约定好的字符加上任何我们想要的字符串。

    j2se对字符所代表的模式的约定列表如下:

     

     

    Letter Date or Time Component Presentation
    G Era designator Text
    y Year Year
    M Month in year Month
    w Week in year Number
    W Week in month Number
    D Day in year Number
    d Day in month Number
    F Day of week in month Number
    E Day in week Text
    a Am/pm marker Text 
    H Hour in day (0-23) Number
    k Hour in day (1-24) Number
    K Hour in am/pm (0-11)  Number
    h   Hour in am/pm (1-12)  Number
    m   Minute in hour  Number
    s   Second in minute  Number
    S   Millisecond  Number  
    z   Time zone   General time zone 
    Z   Time zone  RFC 822 time zone 

     

    June 16

    JAVA中数据库操作的各种方式与设计模式的应用 (收藏)

         青山不改绿水长流-EKing 1. 在业务层使用JDBC直接操作数据库-最简单,最直接的操作紧耦合方式,黑暗中的痛苦 1)数据库url,username,password写死在代码中 Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); String url="jdbc:oracle:thin:@localhost:1521:orcl"; String user="scott"; String password="tiger"; Connection conn= DriverManager.getConnection(url,user,password); Statement stmt=conn.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); String sql="select * from test"; ResultSet rs=stmt.executeQuery(sql); 2)使用DBHelp类封装JDBC操作;数据库url,username,password可以放在配置文件中(如xml)。这种方法在小程序中应用较多。 2.DAO(Data Accessor Object)模式-松耦合的开始 DAO = data + accessor + domain object 例如User类-domain object (javabean) UserDAO类-accessor ,提供的方法getUser(int id),save(User user)内包含了JDBC操作在业务逻辑中使用这两个类来完成数据操作。 使用Factory模式可以方便不同数据库连接之间的移植。 3.数据库资源管理模式 3.1 数据库连接池技术资源重用,避免频繁创建,释放连接引起大大量性能开销;更快的系统响应速度; 通过实现JDBC的部分资源对象接口( Connection, Statement, ResultSet ),可以使用Decorator设计模式分别产生三种逻辑资源对象: PooledConnection, PooledStatement和 PooledResultSet。 一个最简单地数据库连接池实现: public class ConnectionPool { private static Vector pools; private final int POOL_MAXSIZE = 25; /** * 获取数据库连接 * 如果当前池中有可用连接,则将池中最后一个返回;若没有,则创建一个新的返回 */ public synchronized Connection getConnection() { Connection conn = null; if (pools == null) { pools = new Vector(); } if (pools.isEmpty()) { conn = createConnection(); } else { int last_idx = pools.size() - 1; conn = (Connection) pools.get(last_idx); pools.remove(last_idx); } return conn; } /** * 将使用完毕的数据库连接放回池中 * 若池中连接已经超过阈值,则关闭该连接;否则放回池中下次再使用 */ public synchronized void releaseConnection(Connection conn) { if (pools.size() >= POOL_MAXSIZE) try { conn.close(); } catch (SQLException e) { // TODO自动生成 catch 块 e.printStackTrace(); } else pools.add(conn); } public static Connection createConnection() { Connection conn = null; try { Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); String url = "jdbc:oracle:thin:@localhost:1521:orcl"; String user = "scott"; String password = "tiger"; conn = DriverManager.getConnection(url, user, password); } catch (InstantiationException e) { // TODO自动生成 catch 块 e.printStackTrace(); } catch (IllegalAccessException e) { // TODO自动生成 catch 块 e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO自动生成 catch 块 e.printStackTrace(); } catch (SQLException e) { // TODO自动生成 catch 块 e.printStackTrace(); } return conn; } } 注意:利用getConnection()方法得到的Connection,程序员很习惯地调用conn.close()方法关闭了数据库连接,那么上述的数据库连接机制便形同虚设。 在调用conn.close()方法方法时如何调用releaseConnection()方法?这是关键。这里,我们使用Proxy模式和java反射机制。 public synchronized Connection getConnection() { Connection conn = null; if (pools == null) { pools = new Vector(); } if (pools.isEmpty()) { conn = createConnection(); } else { int last_idx = pools.size() - 1; conn = (Connection) pools.get(last_idx); pools.remove(last_idx); } ConnectionHandler handler=new ConnectionHandler(this); return handler.bind(con); } public class ConnectionHandler implements InvocationHandler { private Connection conn; private ConnectionPool pool; public ConnectionHandler(ConnectionPool pool){ this.pool=pool; } /** * 将动态代理绑定到指定Connection * @param conn * @return */ public Connection bind(Connection conn){ this.conn=conn; Connection proxyConn=(Connection)Proxy.newProxyInstance( conn.getClass().getClassLoader(), conn.getClass().getInterfaces(),this); return proxyConn; } /* (非 Javadoc) * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO自动生成方法存根 Object obj=null; if("close".equals(method.getName())){ this.pool.releaseConnection(this.conn); } else{ obj=method.invoke(this.conn, args); } return obj; } } 在实际项目中,并不需要你来从头开始来设计数据库连接池机制,现在成熟的开源项目,如C3P0,dbcp,Proxool等提供了良好的实现。一般推荐使用Apache dbcp,基本使用实例: DataSource ds = null; try{ Context initCtx = new InitialContext(); Context envCtx = (Context) initCtx.lookup("java:comp/env"); ds = (DataSource)envCtx.lookup("jdbc/myoracle"); if(ds!=null){ out.println("Connection is OK!"); Connection cn=ds.getConnection(); if(cn!=null){ out.println("cn is Ok!"); Statement stmt = cn.createStatement(); ResultSet rst = stmt.executeQuery("select * from BOOK"); out.println("

    rst is Ok!" + rst.next()); while(rst.next()){ out.println("

    BOOK_CODE:" + rst.getString(1)); } cn.close(); }else{ out.println("rst Fail!"); } } else out.println("Fail!"); }catch(Exception ne){ out.println(ne); } 3.2 Statement Pool 普通预编译代码: String strSQL=”select name from items where id=?”; PreparedStatement ps=conn.prepareStatement(strSQL); ps.setString(1, “2”); ResultSet rs=ps.executeQuery(); 但是PreparedStatement 是与特定的Connection关联的,一旦Connection关闭,则相关的PreparedStatement 也会关闭。为了创建PreparedStatement 缓冲池,可以在invoke方法中通过sql语句判断池中还有没有可用实例。 4. 持久层设计 1) Hernate:适合对新产品的开发,进行封闭化的设计 Hibernate 2003年被Jboss接管,通过把java pojo对象映射到数据库的table中,采用了xml/javareflection技术等。3.0提供了对存储过程和手写sql的支持,本身提供了hql语言。开发所需要的文件: hibernate配置文件: hibernate.cfg.xml 或 hibernate.properties hibernate 映射文件: a.hbm.xml pojo类源文件: a.java   导出表与表之间的关系: a. 从java对象到hbm文件:xdoclet b. 从hbm文件到java对象:hibernate extension c. 从数据库到hbm文件:middlegen d. 从hbm文件到数据库:SchemaExport 2) Iatis :适合对遗留系统的改造和对既有数据库的复用,有很强的灵活性 3) Apache OJB:优势在于对标准的全面支持 4)EJB:适合集群服务器,其性能也不象某些人所诟病的那么差劲 5) JDO (java data object) 设置一个Properties对象,从而获取一个JDO的PersistenceManagerFactory(相当于JDBC连接池中的DataSource),进而获得一个PersistenceManager对象(相当于JDBC中的Connection对象),之后,你可以用这个PersistenceManager对象来增加、更新、删除、查询对象。 JDOQL是JDO的查询语言;它有点象SQL,但却是依照Java的语法的。

    JDBC连接各种数据库方式列表 (收藏)

    下面罗列了各种数据库使用JDBC连接的方式,可以作为一个手册使用。 

      1、Oracle8/8i/9i数据库(thin模式) 

    Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); 
    String url="jdbc:oracle:thin:@localhost:1521:orcl"; //orcl为数据库的SID 
    String user="test"; 
    String password="test"; 
    Connection conn= DriverManager.getConnection(url,user,password);  

      2、DB2数据库 

    Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance(); 
    String url="jdbc:db2://localhost:5000/sample"; //sample为你的数据库名 
    String user="admin"; 
    String password=""; 
    Connection conn= DriverManager.getConnection(url,user,password);  

      3、Sql Server7.0/2000数据库 

    Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance(); 
    String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydb"; 
    //mydb为数据库 
    String user="sa"; 
    String password=""; 
    Connection conn= DriverManager.getConnection(url,user,password);  

      4、Sybase数据库 

    Class.forName("com.sybase.jdbc.SybDriver").newInstance(); 
    String url =" jdbc:sybase:Tds:localhost:5007/myDB";//myDB为你的数据库名 
    Properties sysProps = System.getProperties(); 
    SysProps.put("user","userid"); 
    SysProps.put("password","user_password"); 
    Connection conn= DriverManager.getConnection(url, SysProps);  

      5、Informix数据库 

    Class.forName("com.informix.jdbc.IfxDriver").newInstance(); 
    String url = "jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=myserver; 
    user=testuser;password=testpassword"; //myDB为数据库名 
    Connection conn= DriverManager.getConnection(url);  

      6、MySQL数据库 

    Class.forName("org.gjt.mm.mysql.Driver").newInstance(); //或者Class.forName("com.mysql.jdbc.Driver");
    String url ="jdbc:mysql://localhost/myDB?user=soft&password=soft1234&useUnicode=true&characterEncoding=8859_1" 
    //myDB为数据库名 
    Connection conn= DriverManager.getConnection(url);  

      7、PostgreSQL数据库 

    Class.forName("org.postgresql.Driver").newInstance(); 
    String url ="jdbc:postgresql://localhost/myDB" //myDB为数据库名 
    String user="myuser"; 
    String password="mypassword"; 
    Connection conn= DriverManager.getConnection(url,user,password);  

      8、access数据库直连用ODBC的

    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") ;
    String url="jdbc:odbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ="+application.getRealPath("/Data/ReportDemo.mdb");
    Connection conn = DriverManager.getConnection(url,"","");
    Statement stmtNew=conn.createStatement() ;