您正在查看: 2016年7月

配置Apache2服务器以CGI方式运行Perl程序

Overview

这次我们开发Bastion4服务器使用了JAVA+Perl的架构,后端用Perl做服务器提供Webservice,用JAVA框架Struts接收处理用户请求,再跟Perl服务器交互。
我们使用Apache2作为Perl服务器,由于Apache2默认并不支持Perl,因此需要简单配置一下,使得Apache2CGI的方式支持Perl运行。在配置的过程中,参考了一些网页,但由于各个网页都没有完整地描述配置过程(至少在我们的服务器上是这样),所以这里记录一下我们配置的全过程。

1. Apache2基本配置

我们为Bastion4申请了一个新的云服务器,版本为NeCTAR Ubuntu 16.04 LTS x86_64,自带了Apache2服务器,下面简单列出了Apache2的一些基本信息:

  • /etc/apache2/ Apache2的配置文件目录
  • /var/www/ Apache2的网站存放目录
  • /var/log/apache2/ Apache2的日志存放目录
  • /etc/apache2/apache2.conf Apache2的配置主文件,以前的Apache版本中,主配置文件名字叫httpd.conf,所以很多网页中还用到这个名字,不知道的话会造成很多混淆。尽管apache2.conf是主配置文件,但是多数具体的配置信息并不是写在这个文件中的,/etc/apache2目录中有还有几个文件夹分别记录了几个模块的配置信息,apache2.conf负责把他们导入整合在一起。
  • /etc/apache2/sites-enabled/ 看名字就可以明白,Apache2的网站配置文件一般都是放在这个目录中的,这个目录下的000-default.conf是我们经常要修改的配置文件。

我们假定Apache存放网站的根目录是/var/www/,如果不确定(因为默认好像是/var/www/html这个目录),打开/etc/apache2/apache2.conf目录,查看下面的配置:

<Directory /var/www/>
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

如果在你的配置里是

<Directory /var/www/html/>

修改成

<Directory /var/www/>

这样,当你把一个名叫Mywebsite的网站(通常是一个文件夹),扔到/var/www中时,你就可以以http://localhost/Mywebsite/访问到这个网站了。

如果你的配置是<Directory /var/www/html/>,那你需要把你的网站扔到/var/www/html中,才能使用http://localhost/Mywebsite/访问,这是因为<Directory>设置了Apache的根目录,当你使用http://****/Mywebsite访问时,Apache会去当前的根目录/Mywebsite找这个网站。

由于Apache的端口号默认是80,而不加端口号的url访问都会被服务器默认定向到80端口,因此这里不需要添加端口号,如果你手动将Apache端口号修改成了别的端口号(比如8888),那你需要使用http://localhost:8888/Mywebsite/访问这个网站。

2. 配置Apache2支持Perl CGI程序

2.1 创建一个Perl网站

  1. /var/www下创建网站的目录,我们创建一个名字叫cgi-bin的网站作为例子:

    mkdir /var/www/cgi-bin
    

    需要使用管理员权限的命令,请自己加上sudo

  2. /var/www/cgi-bin中创建一个cgi_test.pl脚本,输入下面的内容:

    #!/usr/bin/perl -w
    use warnings;
    use CGI qw(:standard);
    #! must use 'my' to define a variable
    print header;
    my $now_string = localtime();
    print "<b>Hello, CGI using Perl!</b><br/>It's $now_string NOW!<br />";
    
  3. cgi_test.pl添加可执行权限:

    chmod +x /var/www/cgi-bin/cgi_test.pl
    
  4. 在命令行运行cgi_test.pl

    /var/cgi-bin/www/cgi_test.pl
    

    会得到下面的结果:

    Content-Type: text/html; charset=ISO-8859-1
    
    <b>Hello, CGI using Perl!</b><br/>It's Mon Aug  1 03:35:42 2016 NOW!<br />
    

    成功运行这个perl脚本需要先安装perlCGI

  5. 尽管现在我们可以在本地以命令行的形式运行这个perl脚本,但还是不能让这个脚本在服务器中运行,访问http://localhost:8888/cgi-bin/cgi_test.pl,浏览器会直接显示整个脚本的内容:

    #!/usr/bin/perl -w
    use warnings;
    use CGI qw(:standard);
    #! must use 'my' to define a variable
    print header;
    my $now_string = localtime();
    print "<b>Hello, CGI using Perl!</b><br/>It's $now_string NOW!<br />";
    

    而不是只把脚本打印的内容显示出来,所以,接下来我们继续配置Apache服务器。

2.2 配置Apache服务器

  1. 打开/etc/apache2/sites-enabled/000-default.conf配置文件,找到下面的配置信息:

    <VirtualHost *:8080>
    ...
    
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www
        
    ...
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
        
    </VirtualHost>
    

    我们需要添加一些配置信息,添加之后,000-default.conf的内容如下:

    <VirtualHost *:8080>
    ...
    
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www
    
    ScriptAlias /cgi-bin/ /var/www/cgi-bin/
    <Directory "/var/www/cgi-bin">
             AllowOverride all
             Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
             Order allow,deny
             Allow from all
             AddHandler cgi-script .cgi .pl
    </Directory>
    ...
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
       
    </VirtualHost>
    

    很容易看得出来,这部分配置主要是用来添加Apacheperl的支持。

  2. 默认情况下,Apache并没有启用CGI模块,我们可以从/etc/apache2/mods-enabled/中确认这点。

    ls -l /etc/apache2/mods-enabled/ | grep cgi
    

    显示结果为空。

    ls -l /etc/apache2/mods-available/ | grep cgi
    

    显示下面的结果:

    -rw-r--r-- 1 root root   74 Mar 19 09:48 authnz_fcgi.load
    -rw-r--r-- 1 root root   58 Mar 19 09:48 cgi.load
    -rw-r--r-- 1 root root  115 Mar 19 09:48 cgid.conf
    -rw-r--r-- 1 root root   60 Mar 19 09:48 cgid.load
    -rw-r--r-- 1 root root   89 Mar 19 09:48 proxy_fcgi.load
    -rw-r--r-- 1 root root   89 Mar 19 09:48 proxy_scgi.load
    

    从名字上就可以看出来,mods-enabled中存放的是已经启用的模块,mods-available中存放的是所有可用的模块,所以启用CGI模块变得很简单,把mods-available中的相关文件在mods-enabled中创建软连接就可以了。

  3. mods-enabled中创建软连接,指向mods-available中的cgid.*文件:

    ln -s /etc/apache2/mods-available/cgid.load /etc/apache2/mods-enabled/
    ln -s /etc/apache2/mods-available/cgid.conf /etc/apache2/mods-enabled/
    

    再次查看mods-enabled

    ls -l /etc/apache2/mods-enabled/ | grep cgi
    

    显示结果为:

    lrwxrwxrwx 1 root root 37 Jul 24 11:55 cgid.conf -> /etc/apache2/mods-available/cgid.conf
    lrwxrwxrwx 1 root root 37 Jul 24 11:55 cgid.load -> /etc/apache2/mods-available/cgid.load
    
  4. 重启Apache服务器:

    service apache2 restart
    

    或者重新载入配置文件:

    service apache2 reload
    

    稳妥的方式是restart Apache服务器,而不只是reload服务器,参见3.2

  5. 在浏览器中访问:http://localhost:8888/cgi-bin/cgi_test.pl就会显示:

    Hello, CGI using Perl!
    It's Mon Aug 1 03:48:37 2016 NOW!
    

可以看到perl脚本在Apache服务器中以CGI脚本的形式运行了。

3. 可能遇到的一些错误

实际上,如果你严格按照上面的步骤,基本上不会出现错误,但是在这里,还是列出一些常见的错误,以便真的遇到这些问题时可以快速查看。

本节主要取自Perl/CGI script with Apache2,所以里面的脚本名字(这里是echo.pl,脚本的路径(这里是/var/cgi-bin而不是/var/www/cgi-bin)和错误信息都沿用了这篇文章的内容,与本文上面使用的脚本名字,脚本路径和脚本内容内容稍有不同,但也都大同小异。

3.1 500 Internal Server Error

如果你使用浏览器访问perl脚本时,看到500 Internal Server Error错误,打开Apache的错误日志/var/log/apache2/error.log

  1. 如果显示下面的错误信息:

    [Wed Mar 19 15:19:15.740781 2014] [cgid:error] [pid 3493:tid 139896478103424] (8)Exec format error: AH01241: exec of '/var/cgi-bin/echo.pl' failed
    [Wed Mar 19 15:19:15.741057 2014] [cgid:error] [pid 3413:tid 139896186423040] [client 192.120.120.120:62309] End of script output before headers: echo.pl
    

    说明脚本的第一行sh-bang line没有正确指向'perl'的安装路径,检查你的perl脚本,确认第一行是下面的样子:

    #!/usr/bin/perl
    

    其实这样的错误非常罕见,除非你是新手,而且又完全自己手写了一段perl脚本。

  2. 如果显示下面的错误信息:

    No such file or directory: AH01241: exec of '/var/cgi-bin/echo.pl' failed
    [Wed Mar 19 15:24:33.505429 2014] [cgid:error] [pid 3412:tid 139896261957376] [client 192.120.120.120:58087] End of script output before headers: echo.pl
    

    说明echo.plDOS格式,而非Unix格式,如果你经常的是Windows,或者喜欢在Windows下写好脚本再上传到Unix/Linux服务器中,那么这会是一个常见而且通用的错误。使用dos2unix命令转换脚本的格式:

    dos2unix /var/cgi-bin/echo.pl
    

    系统默认可能并没有装dos2unix命令,需要自己安装一下。如果你用的是Ubuntu,用sudo apt install dos2unix安装。

  3. 如果显示下面的错误信息:

    [Wed Mar 19 15:40:31.179155 2014] [cgid:error] [pid 4796:tid 140208841959296] (13)Permission denied: AH01241: exec of '/var/cgi-bin/echo.pl' failed
    [Wed Mar 19 15:40:31.179515 2014] [cgid:error] [pid 4702:tid 140208670504704] [client 192.120.120.120:60337] End of script output before headers: echo.pl
    

    说明你没有为perl脚本添加可执行权限,使用chmod命令很容易更正这个错误:

    chmod +x /var/cgi-bin/echo.pl
    
  4. 如果显示下面的错误信息:

    Wed Mar 19 16:02:20.239624 2014] [cgid:error] [pid 4703:tid 140208594970368] [client 192.120.120.120:62841] malformed header from script 'echo.pl': Bad header: hi
    

    上面错误对应的脚本:

    #!/usr/bin/perl
    use strict;
    use warnings;
    
    print "hi\n";
    print qq(Content-type: text/plain\n\n);
    

    perl脚本输出Content-type之前输出了别的字符,而浏览器解析的时候把那些字符当做了Content-type,所以报了Bad header错误。所以,不要在print qq(Content-type: text/plain\n\n);之前,输出别的字符。

  5. 如果显示下面的错误信息:

    [Wed Mar 19 16:08:00.342999 2014] [cgid:error] [pid 4703:tid 140208536221440] [client 192.120.120.120:59319] End of script output before headers: echo.pl
    

    还是一个跟header相关的问题,说明你的脚本在打印Content-type之前就出了错误或者异常,error.log中也可能在上面的错误信息之前提供其他更具体的相关信息。所以,请仔细检查打印Content-type之前的perl代码。

    关于End of script output before headers错误,原文作者认为可能与Premature end of script headers是同样的原因。

3.2 503 Service Unavailable

如果在本文2.2节为mods-enabled创建了软连接之后,并及时重载了apache,会报下面的错误:

[Wed Mar 19 15:30:22.515457 2014] [cgid:error] [pid 3927:tid 140206699169536] (22)Invalid argument: [client 192.120.120.120:58349] AH01257: unable to connect to cgi daemon after multiple tries: /var/cgi-bin/echo.pl

我猜reload只是重新载入了服务器配置信息,并未将CGI进程启动,所以尽管已经配置了,但是由于CGI模块并未启动,所以自然也就没法连接CGI的守护进程。
所以,如果你只是修改了配置文件,reload就可以了,如果你启用或禁用了某个模块,需要restart,因为所有启用的模块,是在服务器启动过程中启动的。

稳妥的方式是restart Apache服务器,而不只是reload服务器。

3.3 404 Not Found

如果显示下面的错误信息:

[Wed Mar 19 15:35:13.487333 2014] [cgid:error] [pid 4194:tid 139911599433472] [client 192.120.120.120:58339] AH01264: script not found or unable to stat: /usr/lib/cgi-bin/echo.pl

echo.pl确实已经存在了,那么检查/etc/apache2/sites-enabled/000-default.conf中的DocumentRootScriptAlias是否配置正确。

3.4 403 Forbidden

如果你遇到403 Forbidden错误,问题一般也出现在/etc/apache2/sites-enabled/000-default.conf这里。检查<Directory>,确保里面涉及到权限的语句正确配置了。

4. 小结

CGI的方式运行perl是最直接最原始的方式,如果你已经成功地以CGI形式运行了perl脚本,建议你尝试下面的方式:

参考文章

Java后台获取客户端ip地址的注意事项

Overview

前面讲到,消息队列需要用到客户端的ip地址和时间戳,获取客户端的ip地址就需要下面几行简单的代码。

import javax.servlet.http.HttpServletRequest;

HttpServletRequest request = ServletActionContext.getRequest();
String ipAddress = request.getHeader("X-FORWARDED-FOR");  
if (ipAddress == null) {  
    ipAddress = request.getRemoteAddr();  
}
System.out.println(ipAddress);

我将上面几行代码,放入之前的PhosphoPredict项目的action中做实验,结果显示如下:

0:0:0:0:0:0:0:1

这和我们平时的认知不同,下面就是解决办法。

1.修改hosts文件

我在ubuntu14.04系统下,打开/etc/hosts文件,看到如下信息:

# Localhost
127.0.0.1       localhost
127.0.0.1       young
255.255.255.255     broadcasthost
::1     localhost
fe80::1%lo0     localhost

我们将

::1     localhost

这句注释掉,再提交,

127.0.0.1

正确答案就出现了。
其他系统,请自行查找文件目录并修改。

2.设置eclipse

我们在eclipse运行本程序的时候,可以配置一下运行参数:
依次点击Run→Run Configurations…→Apache Tomcat→Tomcat v7.0 Server at localhost,这时候点击右边的Arguments,在下面的VM arguments框中加上一句:

-Djava.net.preferIPv4Stack=true

最后点击Apply。然后就可以了。

总结:这是因为,只有在本机提交的时候,才会出现,客户端提交就会显示真实ip地址了。而系统会优先显示ipv6格式的本机ip。我们两种方法,第一种是屏蔽掉ipv6的表示方法,第二种则是指定优先ipv4表示。
两种方法更推荐第二种。

这篇文章主要参考了stackoverflow.

ssh和FileZilla远程连接服务器的问题

Overview

前些天用ssh通过命令行登录我们的bastion4服务器还一切正常,到了昨天已经不能使用,但是用了相同的密钥的FileZilla依然可以登录,这就很奇怪了。

1.问题所在

FileZilla登录到远程服务器,找到ubuntu用户下面的.ssh文件夹,打开之后可以看到只有一个文件authorized_keys,我把它下载下来。完成之后,我到本机的/home/young/Downloads文件夹里找到它,打开看到我的密钥已经添加进去了,看来是FileZilla可以找到本地/home/young/.ssh/BingjiaoYang_ssh这个文件,但是默认的

ssh ubuntu@bastion4.erc.monash.edu

命令现在已经找不到这个文件了。
经过JericoChris两个人的指点,使用如下命令:

ssh -vvv ubuntu@bastion4.erc.monash.edu

显示日志信息如下(只截取最后核心信息):

debug1: Next authentication method: publickey
debug1: Trying private key: /home/young/.ssh/id_rsa
debug3: no such identity: /home/young/.ssh/id_rsa: No such file or directory
debug1: Trying private key: /home/young/.ssh/id_dsa
debug3: no such identity: /home/young/.ssh/id_dsa: No such file or directory
debug1: Trying private key: /home/young/.ssh/id_ecdsa
debug3: no such identity: /home/young/.ssh/id_ecdsa: No such file or directory
debug1: Trying private key: /home/young/.ssh/id_ed25519
debug3: no such identity: /home/young/.ssh/id_ed25519: No such file or directory
debug2: we did not send a packet, disable method
debug1: No more authentication methods to try.
Permission denied (publickey).

意思就是找不到/home/young/.ssh/id_rsa这个文件。

2.解决办法

解决办法有如下两个。

2.1 文件改名(不推荐)

/home/young/.ssh/BingjiaoYang_ssh这个文件改名为id_rsa,同时把/home/young/.ssh/BingjiaoYang_ssh.pub这个文件改名为id_rsa.pub,这时候再用原命令登录就没有问题了。但是这个解决办法明显没有看透本质,所以推荐下一种。

2.2 直接指定密钥文件(推荐)

在命令行中直接输入ssh,可以看到ssh的用法:

➜  ~ ssh                                                                     
usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]
           [-D [bind_address:]port] [-E log_file] [-e escape_char]
           [-F configfile] [-I pkcs11] [-i identity_file]
           [-L [bind_address:]port:host:hostport] [-l login_name] [-m mac_spec]
           [-O ctl_cmd] [-o option] [-p port]
           [-Q cipher | cipher-auth | mac | kex | key]
           [-R [bind_address:]port:host:hostport] [-S ctl_path] [-W host:port]
           [-w local_tun[:remote_tun]] [user@]hostname [command]

可以看到,我们可以之间指定文件,来解决找不到文件的问题。所以,正确命令如下:

ssh ubuntu@bastion4.erc.monash.edu -i /home/young/.ssh/BingjiaoYang_ssh

以后就没有问题出现了。

还有一个问题有些人可能会困惑:为什么Filezilla仍然可以正常登录?
原因就在于,我们在首次用Filezilla登录时,会根据密钥文件生成一个BingjiaoYang_bastion4文件,以后Filezilla每次登录都会根据这个文件读取信息,一旦这个文件换了位置或者被删除,FileZilla一样会无法登录。
更多关于远程登录服务器的细节,参考Chris的文章:部署PhosphoPrediction
最后,感谢ChrisJerico的热心帮助。

kafka在java中简单应用

Overview

之前的这篇博客ubuntu14.04单机安装配置zookeeper和kafka,介绍了zookeeperkafka的安装配置,并在命令行下验证了生产者消费者可以跑通。但是实际项目中,需要和java交互,不可能接触到命令行和后台的。本文旨在记录一下javakafka的简单交互,web中道理相同,只不过程序入口换成了action

1.新建项目配置环境

打开eclipse,依次点击Window→Preferences→Java→Build Path→User Libraries,然后在右边选择New
,添加一个自己常用的Library,我命名为kafka。选中kafka,右边选择Add External JARS,然后到之前安装好的kafka的目录,找到libs这个文件夹,如果按照上次配置好的情况,这里应该是15jar文件,见下图:

2016-07-12 17:16:06屏幕截图.png

全部选中,点击确定。这样,我们以后就可以复用了。

然后我们在eclipse中构建一个普通的java项目testKafka。右击项目,依次点击Build Path→Add Libraries→User Library,选择kafka这个library,点击Finish。这样环境就搭建好了。

2.生产者消费者程序

下面编码测试程序,即消息生产者和消息消费者。

2.1 生产者

package testKafka;

import java.util.Properties;

import kafka.javaapi.producer.Producer;
import kafka.producer.KeyedMessage;
import kafka.producer.ProducerConfig;

public class MsgProducer {
    private static Producer<String,String> producer;
    private final Properties props=new Properties();
    public MsgProducer(){
        //定义连接的broker list
        props.put("metadata.broker.list", "127.0.0.1:9092");
        //定义序列化类,Java中对象传输之前要序列化
        props.put("serializer.class", "kafka.serializer.StringEncoder");
        producer = new Producer<String, String>(new ProducerConfig(props));
    }
    public static void main(String[] args) {
        MsgProducer mProducer=new MsgProducer();
        //定义topic
        String topic="testkafka";
        
        //定义要发送给topic的消息
        String mString = "Hello kafka!";
                
        //构建消息对象
        KeyedMessage<String, String> data = new KeyedMessage<String, String>(topic, mString);
 
        //推送消息到broker
        producer.send(data);
        producer.close();
    }
}

这里需要注意,生产者这里,最少需要两个配置项:metadata.broker.list127.0.0.1:9092serializer.class设置为kafka.serializer.StringEncoder。打开上次配置的producer.properties文件,看到这两项配置分别为metadata.broker.list=localhost:9092serializer.class=kafka.serializer.DefaultEncoderbroker list要一致,否则会报错。
这些项,最好写在配置文件里,方便以后添加服务器时候更改。

2.2 消费者

package testKafka;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import kafka.consumer.Consumer;
import kafka.consumer.ConsumerConfig;
import kafka.consumer.ConsumerIterator;
import kafka.consumer.KafkaStream;
import kafka.javaapi.consumer.ConsumerConnector;

public class MsgConsumer {
    private final ConsumerConnector consumer;
    private final String topic;

    public MsgConsumer(String zookeeper, String groupId, String topic) {
        Properties props = new Properties();
        //定义连接zookeeper信息
        props.put("zookeeper.connect", zookeeper);
        //定义Consumer所有的groupID
        props.put("group.id", groupId);
        props.put("zookeeper.session.timeout.ms", "500");
        props.put("zookeeper.sync.time.ms", "250");
        props.put("auto.commit.interval.ms", "1000");
        consumer = Consumer.createJavaConsumerConnector(new ConsumerConfig(props));
        this.topic = topic;
    }

    public void testConsumer() {
        Map<String, Integer> topicCount = new HashMap<String, Integer>();
        //定义订阅topic数量
        topicCount.put(topic, new Integer(1));
        //返回的是所有topic的Map
        Map<String, List<KafkaStream<byte[], byte[]>>> consumerStreams = consumer.createMessageStreams(topicCount);
        //取出我们要需要的topic中的消息流
        List<KafkaStream<byte[], byte[]>> streams = consumerStreams.get(topic);
        for (final KafkaStream stream : streams) {
            ConsumerIterator<byte[], byte[]> consumerIte = stream.iterator();
            while (consumerIte.hasNext()) {
                System.out.println(new String(consumerIte.next().message()));
            }
        }
        if (consumer != null) {
            consumer.shutdown();
        }
            
    }

    public static void main(String[] args) {
        String topic = "testkafka";
        MsgConsumer mConsumer = new MsgConsumer("127.0.0.1:2181", "test-consumer-group", topic);
        mConsumer.testConsumer();
    }

}

这里需要注意,消费者的配置信息,应该和生产者对应。最关键的配置是两项:zookeeper.connectgroup.id。这两项打开consumer.properties就可以看到。

3. 测试

首先,要在命令行中启动zookeeperkafka

在消费者程序里面,运行一下,Console框显示如下:

log4j:WARN No appenders could be found for logger (kafka.utils.VerifiableProperties).
log4j:WARN Please initialize the log4j system properly.

这个不是错误信息,不用理睬。
接着在生产者那里,运行一下,Console框显示如下:

log4j:WARN No appenders could be found for logger (kafka.utils.VerifiableProperties).
log4j:WARN Please initialize the log4j system properly.
Hello kafka!

这样,我们的程序就跑通了。
这里主要参考了kafka官方例子:生产者消费者

SQLite数据库在java中应用

Overview

这次的服务器,我们准备使用消息队列和SQLite这两个新东西,SQLite主要负责将用户提交的序列信息存储,并在结果页面查询显示。存储的信息包括用户的ip+timeStamp,序列内容,序列的处理状态。

1.安装SQLite

SQLite的安装特别简单。
ubuntu14.04这个版本自带SQLite,在命令行输入sqlite3,显示如下:

~sqlite3
SQLite version 3.8.2 2013-12-06 14:53:30
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite>

如果没有出现上述信息,可以使用如下命令进行安装:

sudo apt-get install sqlite3

每个版本的ubuntu的软件源略有新旧不同,但不影响使用。

2.SQLitejava交互

SQLitejava中的基本使用方法和其他诸如mysql等数据库大同小异,下面我们从创建并连接数据库,建表,增,删,改,查这6个方面简单介绍下。

2.1 创建并连接数据库

package testSQLite;

import java.sql.Connection;
import java.sql.DriverManager;

public class SQLiteJDBC {
    public static void main( String args[] ) {
        Connection c;
        try {
            Class.forName("org.sqlite.JDBC");
            c = DriverManager.getConnection("jdbc:sqlite:testSQLite.db");
        } catch ( Exception e ) {
            e.printStackTrace();
        }
        System.out.println("Connected database successfully");
    }
}

2.2 建表

package testSQLite;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class createTable {
    public static void main( String args[] ) {
        Connection c;
        Statement stmt;
        try {
            Class.forName("org.sqlite.JDBC");
            c = DriverManager.getConnection("jdbc:sqlite:testSQLite.db");
            System.out.println("Connected database successfully");

            stmt = c.createStatement();
            String sql = "CREATE TABLE TEAM " +
                         "(NUMBER INT PRIMARY KEY     NOT NULL, " +
                         " NAME           TEXT    NOT NULL, " + 
                         " AGE            INT     NOT NULL, " + 
                         " COUNTRY        CHAR(50), " + 
                         " POSITION       CHAR(50))"; 
            stmt.executeUpdate(sql);
            stmt.close();
            c.close();
        } catch ( Exception e ) {
            e.printStackTrace();
        }
        System.out.println("Table created successfully");
    }

}

2.3 增加(insert)

package testSQLite;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;


public class insert {
    public static void main(String args[]) {
        Connection c;
        Statement stmt;
        try {
            Class.forName("org.sqlite.JDBC");
            c = DriverManager.getConnection("jdbc:sqlite:testSQLite.db");
            c.setAutoCommit(false);
            System.out.println("Connected database successfully");

            stmt = c.createStatement();
            String sql = "INSERT INTO TEAM (NUMBER,NAME,AGE,COUNTRY,POSITION) " +
                       "VALUES (1, 'Navas', 29, 'Costa Rica', 'goalkeeper' );"; 
            stmt.executeUpdate(sql);

            sql = "INSERT INTO TEAM (NUMBER,NAME,AGE,COUNTRY,POSITION) " +
                "VALUES (2, 'Varane', 23, 'France', 'center back' );"; 
            stmt.executeUpdate(sql);

            sql = "INSERT INTO TEAM (NUMBER,NAME,AGE,COUNTRY,POSITION) " +
                "VALUES (3, 'Pepe', 33, 'Portugal', 'center back' );"; 
            stmt.executeUpdate(sql);

            sql = "INSERT INTO TEAM (NUMBER,NAME,AGE,COUNTRY,POSITION) " +
                "VALUES (4, 'Ramos', 30, 'Spain', 'center back' );";            
            stmt.executeUpdate(sql);
            
            sql = "INSERT INTO TEAM (NUMBER,NAME,AGE,COUNTRY,POSITION) " +
                    "VALUES (7, 'Ronaldo', 31, 'Portugal', 'stricker' );";          
            stmt.executeUpdate(sql);

            stmt.close();
            c.commit();
            c.close();
        } catch ( Exception e ) {
            e.printStackTrace();
        }
        System.out.println("Insert successfully");      
    }

}

2.4 查找(select)

package testSQLite;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class select {

    public static void main(String[] args) {
        Connection c;
        Statement stmt;
        try {
            Class.forName("org.sqlite.JDBC");
            c = DriverManager.getConnection("jdbc:sqlite:testSQLite.db");
            c.setAutoCommit(false);
            System.out.println("Connected database successfully");

            stmt = c.createStatement();
            ResultSet rs = stmt.executeQuery( "SELECT * FROM TEAM;" );
            while ( rs.next() ) {
                int number = rs.getInt("number");
                String  name = rs.getString("name");
                int age  = rs.getInt("age");
                String  country = rs.getString("country");
                String position = rs.getString("position");
                System.out.println( "NUMBER = " + number );
                System.out.println( "NAME = " + name );
                System.out.println( "AGE = " + age );
                System.out.println( "COUNTRY = " + country );
                System.out.println( "POSITION = " + position );
                System.out.println();
            }
            rs.close();
            stmt.close();
            c.close();
        } catch ( Exception e ) {
            e.printStackTrace();
        }
        System.out.println("Select successfully");

    }

}


2.5 更改(update)

package testSQLite;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class update {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Connection c = null;
        Statement stmt = null;
        try {
            Class.forName("org.sqlite.JDBC");
            c = DriverManager.getConnection("jdbc:sqlite:testSQLite.db");
            c.setAutoCommit(false);
            System.out.println("Connected database successfully");

            stmt = c.createStatement();
            String sql = "UPDATE TEAM set POSITION = 'fullback' where NUMBER=4;";
            stmt.executeUpdate(sql);
            c.commit();

            ResultSet rs = stmt.executeQuery( "SELECT * FROM TEAM;" );
            while ( rs.next() ) {
                int number = rs.getInt("number");
                String  name = rs.getString("name");
                int age  = rs.getInt("age");
                String  country = rs.getString("country");
                String position = rs.getString("position");
                System.out.println( "NUMBER = " + number );
                System.out.println( "NAME = " + name );
                System.out.println( "AGE = " + age );
                System.out.println( "COUNTRY = " + country );
                System.out.println( "POSTION = " + position );
                System.out.println();
            }
            rs.close();
            stmt.close();
            c.close();
        } catch ( Exception e ) {
            e.printStackTrace();
        }
        System.out.println("Update successfully");

    }

}

2.6 删除(delete)

package testSQLite;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class delete {

    public static void main(String[] args) {
        Connection c = null;
        Statement stmt = null;
        try {
            Class.forName("org.sqlite.JDBC");
            c = DriverManager.getConnection("jdbc:sqlite:testSQLite.db");
            c.setAutoCommit(false);
            System.out.println("Connected database successfully");

            stmt = c.createStatement();
            String sql = "DELETE from TEAM where NUMBER=3;";
            stmt.executeUpdate(sql);
            c.commit();

            ResultSet rs = stmt.executeQuery( "SELECT * FROM TEAM;" );
            while ( rs.next() ) {
                int number = rs.getInt("number");
                String  name = rs.getString("name");
                int age  = rs.getInt("age");
                String  country = rs.getString("country");
                String position = rs.getString("position");
                System.out.println( "NUMBER = " + number );
                System.out.println( "NAME = " + name );
                System.out.println( "AGE = " + age );
                System.out.println( "COUNTRY = " + country );
                System.out.println( "POSTION = " + position );
                System.out.println();
            }
            rs.close();
            stmt.close();
            c.close();
        } catch ( Exception e ) {
            e.printStackTrace();
        }
        System.out.println("Delete successfully");

    }

}

这篇文章主要参考了这里:SQLite - Java