戈戈个人博客

愿居于一城,与卿所见美好......

推荐文章

H2数据库使用教程-1-介绍篇

    1.H2简介


    H2是纯JAVA编写的轻量级数据库,类似于HSQLDB,但比HSQLDB好用多了。使用非常方便,无需安装,你就可以在程序中启动数据库服务器、连接、创建数据库,客户端连接也不需要任何安装,只要有IE即可。官网http://www.h2database.com/html/main.html。下载后bin目录下会有数据库驱动包,假设名叫h2-1.3.162.jar,如果你不需要看源代码,就这一个文件就够用了,启动数据库及连接数据库所用的资源都在里面了。为了方便,我们将它改名为h2.jar。

    2.H2启动与连接

    H2数据库启动选项可通过java -classpath h2.jar org.h2.tools.Server -?查询,如下:

    1)文件方式启动

    严格来说应该叫文件方式连接,因为文件方式启动不需要先启动数据库服务器,直接在连接URL中填写绝对或相对路径即可,由于创建数据库连接时,H2引擎发现指定的路径下如果不存在数据库,则会自动创建,如:

    Class.forName("org.h2.Driver");
    Connection conn = DriverManager.getConnection("jdbc:h2:file:~/test", "sa", "");

    这段代码可以正常执行,其中file表示以文件方式启动数据库连接,但如果是第一次使用,可能不知道H2把数据库创建在了什么位置,熟悉linux的会知道~符号表示系统当前用户的主文件夹,所以(以win7为例),上面这段代码会在C:\Users\Administrator目录下创建名为test的数据库,用户名为sa,密码为空(用户名密码在首次创建时可以随意设置)。由于H2默认连接方式就是文件方式,所以file关键字可以省略,也就是说,在win7下,以下三种写法是等价的:

    Connection conn = DriverManager.getConnection("jdbc:h2:~/test", "sa", "");
    Connection conn = DriverManager.getConnection("jdbc:h2:file:~/test", "sa", "");
    Connection conn = DriverManager.getConnection("jdbc:h2:file:C:/Users/Administrator/test", "sa", "");


    以上的三种写法使用的是绝对路径,在实际应用中,你可能会希望程序在哪运行,就是哪创建数据库,所以会用到相对路径,如:

    Connection conn = DriverManager.getConnection("jdbc:h2:file:h2db/test", "sa", "");

    当执行以上代码时,H2会在JAVA程序运行的根目录下创建h2db文件夹,然后在h2db下创建test数据库。

    如果数据库已经创建,下次再进行连接时,就必须提供与第一次创建时一致的用户名密码,否则将连接不成功。

    另外需要强调的是,以文件方式连接数据库时,H2引擎会新建两个守护线程,一个用来锁文件,一个用来写文件:


    所以这种方式是独占的,即当以文件方式连接数据库所创建的Connection如果没有关闭,不允许再有其他的进程以文件方式连接此数据库。如果尝试连接,将会报以下错误:

    Exception in thread "main" org.h2.jdbc.JdbcSQLException: Database may be already in use: Locked by another process. Possible solutions: close all other connection(s); use the server mode [90020-72]
     at org.h2.message.Message.getSQLException(Message.java:92)
     at org.h2.message.Message.getSQLException(Message.java:96)
     at org.h2.message.Message.getSQLException(Message.java:74)

    所以文件方式不适合做类似数据库连接池的应用。

    2)使用web控制台

    在讲完一种启动方式时需要先讲一下H2的web控制台,然后再讲更高级的数据库启动方式。因为无论以哪一种数据库方式启动数据库,你都可以使用web控制台来连接,并执行CRUD操作,非常方便,要启动web控制台,可以执行java -classpath h2.jar org.h2.tools.Console -web,登陆界面如下:

    登陆成功后,可以在里面直接执行SQL语句:



    3)tcp方式启动

    tcp方式启动时,H2将在本地启动一个tcp服务器,你可以用客户端连接至此端口访问不同的数据库,这种方式支持多客户端。在启动数据库时,你不需要指定具体数据库(因为在连接时才需要指定),只需指定需要监听的端口即可,如:

    java -classpath h2.jar org.h2.tools.Server -tcp

    这样即可启动数据库服务器了,由于你没有指定端口,所以H2将监听默认端口9092,如果你想指定端口,需要使用tcpPort参数,如:

    java -classpath h2.jar org.h2.tools.Server -tcp -tcpPort 9092

    注意,此种方式启动后,你将可以在本地通过9092访问H2数据库,但不允许其他机器访问,如果你希望从其他机器也能通过此端口访问数据库,就需要用到tcpAllowOthers参数了,如:

    java -classpath h2.jar org.h2.tools.Server -tcp -tcpPort 9092 -tcpAllowOthers

    数据库启动后,通过web console或JDBC连接时,需要把URL也更改为tcp方式,如:

    jdbc:h2:tcp://localhost:9092/~/test

    可以看到,在端口号后面追加绝对或相对路径和前面讲的文件方式启动时规则是一样的。

    4)tcp方式启动(匿名ssl)

    当使用tcp方式启动数据库时,如果需要从外网访问,就必须考虑安全问题,H2官网对SSL方式启动数据库做了非常精要的说明,如下:


    Remote SSL/TLS connections are supported using the Java Secure Socket Extension (SSLServerSocket, SSLSocket). By default, anonymous SSL is enabled. The default cipher suite is SSL_DH_anon_WITH_RC4_128_MD5.

    To use your own keystore, set the system properties javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword before starting the H2 server and client. See also Customizing the Default Key and Trust Stores, Store Types, and Store Passwords for more information.

    To disable anonymous SSL, set the system property h2.enableAnonymousSSL to false.


    要使用ssl方式启动数据库,需要使用h2.enableAnonymousSSL和tcpSSL参数,如:

    java -Dh2.enableAnonymousSSL=true -classpath h2.jar org.h2.tools.Server -tcp -tcpPort 9092 -tcpAllowOthers -tcpSSL

    注意,前面的h2.enableAnonymousSSL需要设置到JAVA系统属性里,所以要在前面追加-D。由于默认使用的就是匿名SSL,所以h2.enableAnonymousSSL参数可以省略,也就是说,下面两个命令是等价的:

    java -Dh2.enableAnonymousSSL=true -classpath h2.jar org.h2.tools.Server -tcp -tcpPort 9092 -tcpAllowOthers -tcpSSL
    java -classpath h2.jar org.h2.tools.Server -tcp -tcpPort 9092 -tcpAllowOthers -tcpSSL

    启动完毕,客户端连接的方式还和原来一样,不过要把url更改为ssl方式,如:

    jdbc:h2:ssl://localhost:9092/~/test


    5)tcp方式启动(ssl双向认证)

    尽管匿名ssl方式启动数据库保证了数据传输的可靠与安全性,但仍然没有解决客户端及服务器身份问题。也就是说,通过上面的方式启动数据库后,任何一个人都可以通过其他机器连接至9092端口,只需要破解数据库密码即可随意操作你的数据库了,这无疑非常危险,所以我们需要更安全的方式。SSL双向认证的原理及细节这里就不再阐述了,我们主要讲解如何使用SSL双向认证的方式启动H2数据库。步骤如下:


      a)制作证书

      特别说明,以下制作证书的步骤我是参考http://www.blogjava.net/stone2083/archive/2007/12/20/169015.html上的。

      我们将使用jdk的keytool制作安全证书,请确保你的JDK已正确安装并且已经设置好环境变量。我的JDK安装在D:\soft\Java\jdk\jdk1.6.0_10目录下,为了简单,我直接在D:\soft\Java\jdk\jdk1.6.0_10\bin目录下运行相关命令,请依次运行:

    (1)keytool -genkey -alias serverkey -keystore kserver.keystore

    (2)keytool -export -alias serverkey -keystore kserver.keystore -file server.crt

    (3)keytool -import -alias serverkey -file server.crt -keystore tclient.keystore


    (4)keytool -genkey -alias clientkey -keystore kclient.keystore

    (5)keytool -export -alias clientkey -keystore kclient.keystore -file client.crt

    (6)keytool -import -alias clientkey -file client.crt -keystore tserver.keystore


    为简单其见,凡是需要输入密码的地方都输入123456,凡是需要输入y和n的地方都输入y,这样命令执行成功后会生成以下文件

    kserver.keystore

    tserver.keystore

    server.crt


    kclient.keystore

    tclient.keystore

    client.crt

    我们只需要其中的四个就行了,服务器需要使用kserver.keystore、tserver.keystore,客户端使用kclient.keystore、tclient.keystore。


      b)启动数据库

    如果成功制作了安全证书,那么启动数据库就很简单了,只需要把上一步制作的kserver.keystore、tserver.keystore放在h2.jar同目录下(当然放在别的目录也可以,只要在参数上指定对的路径即可),启动命令如下:


    java -Dh2.enableAnonymousSSL=false -Djavax.net.ssl.keyStore=kserver.keystore -Djavax.net.ssl.keyStorePassword=123456 -Djavax.net.ssl.trustStore=tserver.keystore -Djavax.net.ssl.trustStorePassword=123456 -classpath h2.jar org.h2.tools.Server -tcp -tcpPort 9092 -tcpAllowOthers -tcpSSL


      c)客户端连接

    客户端连接时需要对应的kclient.keystore、tclient.keystore,放在h2.jar同一目录下即可,连接命令如下:

    java -Djavax.net.ssl.keyStore=kclient.keystore -Djavax.net.ssl.keyStorePassword=123456 -Djavax.net.ssl.trustStore=tclient.keystore -Djavax.net.ssl.trustStorePassword=123456 -classpath h2.jar org.h2.tools.Console -web

    如果你连接时出现Connection is broken [90067-72] 90067/90067 (Help)的错误,可能的原因有:

    (1)未在启动参数中指明安全证书路径或指明的证书路径错误,或者忘了把证书放在指定的路径下

    (2)启动参数中指明的密码错误

    (3)连接的URL有误,比如忘了加ssl或者端口号指定错误等等

    (4)连接的命令中忘了加-web参数,如果没有加-web,在本机测试时客户端也会占用9092端口,但它发现此端口已经被服务器占用了,就会启动失败,结果程序退出,这样的话IE虽然能打开,但是也会连接不上


    3. h2的用户和schema

    它同oracle和db2不同,sa可以认为是个实例用户,但与db2和oracle貌似不大一样,原因在于这个test的schame,用sa登陆test之后,可以建立用户,但并不要在上面直接建立schema,不是不能,可以建立,但建完的schema是属于test数据库下的,并不能真正可用,所以必须自行用建立好的用户登陆,这里直接登陆个没有的schema,h2会自动建立出来,然后在这个上面在建立schema。


    ————————————————

    版权声明:本文为CSDN博主「zhoche2008」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

    原文链接:https://blog.csdn.net/zhoche2008/article/details/7017767

    阅读全文>>

作者:戈戈分类:【javaEE浏览(65评论(0

2021-11-29 10:39:02

spring-@Autowired注入与构造函数注入使用

    前言

    因为业务关系也看了些同事写的代码,因为公司没有明确规定,有一部分人在注入依赖的时候使用了用Spring推荐的构造器注入的方式,一部分人使用了@Autowired的注解进行注入。

    因此,接下来我试着总结归纳一下相关的情况,做一次回顾。

    用自己的话去说出来才算是真的掌握。

    使用介绍

    1.@Autowired注入

     

    1. @RestController
    2. @RequestMapping("/test")
    3. public class TestController {
    4. @Autowired
    5. private List<TestService> testServices;
    6. @Autowired
    7. private List<ChainAsbtract> chains;
    8. private ChainAsbtract target;
    9. }

    2.构造器注入

    Spring4.3+之后,constructor注入支持非显示注入方式。

    1. @RestController
    2. @RequestMapping("/test")
    3. public class TestController {
    4. // @Autowired
    5. private final List<TestService> testServices;
    6. // @Autowired
    7. private final List<ChainAsbtract> chains;
    8. // @Autowired
    9. public TestController(List<TestService> testServices, List<ChainAsbtract> chains) {
    10. this.testServices = testServices;
    11. this.chains = chains;
    12. }
    13. }

     3.setter注入

    1. @RestController
    2. @RequestMapping("/test")
    3. public class TestController {
    4. // @Autowired
    5. private final List<TestService> testServices;
    6. // @Autowired
    7. private final List<ChainAsbtract> chains;
    8. @Autowired
    9. public void setTestServices(List<TestService> testServices){
    10. this.testServices = testServices;
    11. }
    12. @Autowired
    13. public void setTestServices(List<ChainAsbtract> chains){
    14. this.chains = chains;
    15. }
    16. }

    事实上,spring在4.x版本后就推荐使用构造器的方式的来注入fileld

    官方推荐理由

    单一职责: 当使用构造函数注入的时候,你会很容易发现参数是否过多,这个时候需要考虑你这个类的职责是否过大,考虑拆分的问题;而当使用@Autowired注入field的时候,不容易发现问题

    依赖不可变: 只有使用构造函数注入才能注入final

    依赖隐藏:使用依赖注入容器意味着类不再对依赖对象负责,获取依赖对象的职责就从类抽离出来,IOC容器会帮你自动装备。这意味着它应该使用更明确清晰的公用接口方法或者构造器,这种方式就能很清晰的知道类需要什么和到底是使用setter还是构造器

    降低容器耦合度: 依赖注入框架的核心思想之一是托管类不应依赖于所使用的DI容器。换句话说,它应该只是一个普通的POJO,只要您将其传递给所有必需的依赖项,就可以独立地实例化。这样,您可以在单元测试中实例化它,而无需启动IOC容器并单独进行测试(使用一个可以进行集成测试的容器)。如果没有容器耦合,则可以将该类用作托管或非托管类,甚至可以切换到新的DI框架。

     另外,在使用构造器的使用能避免注入的依赖是空的情况。

    因为在bean的生命周期里面先执行的是bean的构造器,然后才给bean里面的属性赋值。具体内容在bean的生命周期里面,后面我学习之后按照自己的理解写写。

    阅读全文>>

作者:戈戈分类:【javaEE浏览(215评论(0

2020-11-29 21:48:50

多想在平凡的生活拥抱你

    前言

    下班晚了,听一首抒情的怀旧青春的歌,最近隔壁老樊异常火爆,酷酷的烟嗓,帅气的外表,吸粉无数,小编为您带来一首他的好听的音乐,多想在平凡的生活拥抱你。欢迎来下载哦

    附上下载链接:http://sharehoo.cn/shop/source/151


    阅读全文>>

作者:戈戈分类:【javaEE浏览(172评论(0

2020-11-26 23:15:40