linux 查找并替换文件中的指定内容

起因

在我刚刚把nginx搬到QTCreator的时候,由于nginx源码都是使用#include <xx.h>的形式,原先我并没有把nginx的头文件放在系统库头文件的变量中,于是乎,我脑抽般的想起,我把<>替换成“”的形式,这样就可以方便的运行了,当然,这个我想的太理想了,略2,但是还是让我学习到了如何查找并替换文件中的特定内容。

相关命令

我使用了这样的命令

<pre lang=”shell”>

find -name “.c” | xargs sed -i ‘s/<([a-z|A-Z|_|0-9].h)>/“\1”/g’

</pre>

现在来详细解释一下,find命令是用来查找文件的

详细可参见find 用法实例

xargs这个是给命令传递参数的一个过滤器,是传递内容的,

详细可参见xargs命令

sed这个命令可以参见sed命令

我解释一下我的用法,因为我是要替换“#include <xx.h>”中的<>成为””,所以使用

<pre lang=”shell”>

sed -i ‘s/<([a-z|A-Z|_|0-9]*.h)>/“\1”/g’

</pre>

-i的意思是把改变了的内容要回写进文件

至于后面一句是sed用来匹配替换文本,

s表示替换的意思

<([a-z|A-Z||0-9]*.h)>是我们的<xx.h>因为xx.h是变化的,所以我们使用正则表达式([a-z|A-Z||0-9]*.h)来准确的获取,但是我们要对()进行转义

“\1”:这里\1的意思就是正则表达式([a-z|A-Z|_|0-9]*.h)匹配上的第一个的字符串的值,同理\2就是匹配上的第二个字符串的值,它是一个变量。这样子我们就实现了这种替换。

 

使用QT Creator查看并调试nginx源码

1.前言

由于原先以前被vs2008以及eclipse宠坏了,vi使用又不熟悉,本来想好好学习nginx源码的我很是拙计,我亟需一个IDE来阅读以及调试源代码,于是我看上了QtCreator,,于是本博文就是介绍如何把nginx源码搞成qt creator工程。

2.建立.pro文件

我们要先学习一下QT Creator的工程文件.pro,因为QTCreator的qmake按照.pro文件生成Makefile的。

现在我们先来看看我们需要用到的.pro配置项

配置项的格式是:key = value

我们需要的key如下

我把我的.pro文件贴出来

TARGET = nginx
DESTDIR = ./objs
LIBS = -lpthread -lcrypt -lpcre -lcrypto -lcrypto -lz
INCLUDEPATH += \
        src/core \
        src/event \
        src/event/modules \
        src/os/unix \
        src/http/modules \
        src/http \
        objs
HEADERS = src/core/nginx.h \
        src/core/ngx_config.h \
        src/core/ngx_core.h \
        src/core/ngx_log.h \
        src/core/ngx_palloc.h \
        src/core/ngx_array.h \
        src/core/ngx_list.h \
        src/core/ngx_hash.h \
        src/core/ngx_buf.h \
        src/core/ngx_queue.h \
        src/core/ngx_string.h \
        src/core/ngx_parse.h \
        src/core/ngx_inet.h \
        src/core/ngx_file.h \
        src/core/ngx_crc.h \
        src/core/ngx_crc32.h \
        src/core/ngx_murmurhash.h \
        src/core/ngx_md5.h \
        src/core/ngx_sha1.h \
        src/core/ngx_rbtree.h \
        src/core/ngx_radix_tree.h \
        src/core/ngx_slab.h \
        src/core/ngx_times.h \
        src/core/ngx_shmtx.h \
        src/core/ngx_connection.h \
        src/core/ngx_cycle.h \
        src/core/ngx_conf_file.h \
        src/core/ngx_resolver.h \
        src/core/ngx_open_file_cache.h \
        src/core/ngx_crypt.h \
        src/event/ngx_event.h \
        src/event/ngx_event_timer.h \
        src/event/ngx_event_posted.h \
        src/event/ngx_event_busy_lock.h \
        src/event/ngx_event_connect.h \
        src/event/ngx_event_pipe.h \
        src/os/unix/ngx_time.h \
        src/os/unix/ngx_errno.h \
        src/os/unix/ngx_alloc.h \
        src/os/unix/ngx_files.h \
        src/os/unix/ngx_channel.h \
        src/os/unix/ngx_shmem.h \
        src/os/unix/ngx_process.h \
        src/os/unix/ngx_setaffinity.h \
        src/os/unix/ngx_setproctitle.h \
        src/os/unix/ngx_atomic.h \
        src/os/unix/ngx_gcc_atomic_x86.h \
        src/os/unix/ngx_thread.h \
        src/os/unix/ngx_socket.h \
        src/os/unix/ngx_os.h \
        src/os/unix/ngx_user.h \
        src/os/unix/ngx_process_cycle.h \
        src/os/unix/ngx_linux_config.h \
        src/os/unix/ngx_linux.h \
        src/core/ngx_regex.h \
        objs/ngx_auto_config.h \
        src/http/ngx_http.h \
        src/http/ngx_http_request.h \
        src/http/ngx_http_config.h \
        src/http/ngx_http_core_module.h \
        src/http/ngx_http_cache.h \
        src/http/ngx_http_variables.h \
        src/http/ngx_http_script.h \
        src/http/ngx_http_upstream.h \
        src/http/ngx_http_upstream_round_robin.h \
        src/http/ngx_http_busy_lock.h \
        src/http/modules/ngx_http_ssi_filter_module.h
SOURCES = src/core/nginx.c \
        src/core/ngx_log.c \
        src/core/ngx_palloc.c \
        src/core/ngx_array.c \
        src/core/ngx_list.c \
        src/core/ngx_hash.c \
        src/core/ngx_buf.c \
        src/core/ngx_queue.c \
        src/core/ngx_output_chain.c \
        src/core/ngx_string.c \
        src/core/ngx_parse.c \
        src/core/ngx_inet.c \
        src/core/ngx_file.c \
        src/core/ngx_crc32.c \
        src/core/ngx_murmurhash.c \
        src/core/ngx_md5.c \
        src/core/ngx_rbtree.c \
        src/core/ngx_radix_tree.c \
        src/core/ngx_slab.c \
        src/core/ngx_times.c \
        src/core/ngx_shmtx.c \
        src/core/ngx_connection.c \
        src/core/ngx_cycle.c \
        src/core/ngx_spinlock.c \
        src/core/ngx_cpuinfo.c \
        src/core/ngx_conf_file.c \
        src/core/ngx_resolver.c \
        src/core/ngx_open_file_cache.c \
        src/core/ngx_crypt.c \
        src/event/ngx_event.c \
        src/event/ngx_event_timer.c \
        src/event/ngx_event_posted.c \
        src/event/ngx_event_busy_lock.c \
        src/event/ngx_event_accept.c \
        src/event/ngx_event_connect.c \
        src/event/ngx_event_pipe.c \
        src/os/unix/ngx_time.c \
        src/os/unix/ngx_errno.c \
        src/os/unix/ngx_alloc.c \
        src/os/unix/ngx_files.c \
        src/os/unix/ngx_socket.c \
        src/os/unix/ngx_recv.c \
        src/os/unix/ngx_readv_chain.c \
        src/os/unix/ngx_udp_recv.c \
        src/os/unix/ngx_send.c \
        src/os/unix/ngx_writev_chain.c \
        src/os/unix/ngx_channel.c \
        src/os/unix/ngx_shmem.c \
        src/os/unix/ngx_process.c \
        src/os/unix/ngx_daemon.c \
        src/os/unix/ngx_setaffinity.c \
        src/os/unix/ngx_setproctitle.c \
        src/os/unix/ngx_posix_init.c \
        src/os/unix/ngx_user.c \
        src/os/unix/ngx_process_cycle.c \
        src/os/unix/ngx_linux_init.c \
        src/event/modules/ngx_epoll_module.c \
        src/os/unix/ngx_linux_sendfile_chain.c \
        src/core/ngx_regex.c \
        src/http/ngx_http.c \
        src/http/ngx_http_core_module.c \
        src/http/ngx_http_special_response.c \
        src/http/ngx_http_request.c \
        src/http/ngx_http_parse.c \
        src/http/ngx_http_header_filter_module.c \
        src/http/ngx_http_write_filter_module.c \
        src/http/ngx_http_copy_filter_module.c \
        src/http/modules/ngx_http_log_module.c \
        src/http/ngx_http_request_body.c \
        src/http/ngx_http_variables.c \
        src/http/ngx_http_script.c \
        src/http/ngx_http_upstream.c \
        src/http/ngx_http_upstream_round_robin.c \
        src/http/ngx_http_parse_time.c \
        src/http/modules/ngx_http_static_module.c \
        src/http/modules/ngx_http_index_module.c \
        src/http/modules/ngx_http_chunked_filter_module.c \
        src/http/modules/ngx_http_range_filter_module.c \
        src/http/modules/ngx_http_headers_filter_module.c \
        src/http/modules/ngx_http_not_modified_filter_module.c \
        src/http/ngx_http_busy_lock.c \
        src/http/ngx_http_file_cache.c \
        src/http/modules/ngx_http_gzip_filter_module.c \
        src/http/ngx_http_postpone_filter_module.c \
        src/http/modules/ngx_http_ssi_filter_module.c \
        src/http/modules/ngx_http_charset_filter_module.c \
        src/http/modules/ngx_http_userid_filter_module.c \
        src/http/modules/ngx_http_autoindex_module.c \
        src/http/modules/ngx_http_auth_basic_module.c \
        src/http/modules/ngx_http_access_module.c \
        src/http/modules/ngx_http_limit_conn_module.c \
        src/http/modules/ngx_http_limit_req_module.c \
        src/http/modules/ngx_http_geo_module.c \
        src/http/modules/ngx_http_map_module.c \
        src/http/modules/ngx_http_split_clients_module.c \
        src/http/modules/ngx_http_referer_module.c \
        src/http/modules/ngx_http_rewrite_module.c \
        src/http/modules/ngx_http_proxy_module.c \
        src/http/modules/ngx_http_fastcgi_module.c \
        src/http/modules/ngx_http_uwsgi_module.c \
        src/http/modules/ngx_http_scgi_module.c \
        src/http/modules/ngx_http_memcached_module.c \
        src/http/modules/ngx_http_empty_gif_module.c \
        src/http/modules/ngx_http_browser_module.c \
        src/http/modules/ngx_http_upstream_ip_hash_module.c \
        src/http/modules/ngx_http_upstream_least_conn_module.c \
        src/http/modules/ngx_http_upstream_keepalive_module.c \
        objs/ngx_modules.c

3.nginx的编译配置生成

由于nginx有很多的模块,在编译的过程中,nginx会根据系统环境的设置,生成ngx_modules.c、ngx_auto_config.h、ngx_auto_headers.h、Makefile等,然后,源代码中根据这些配置头文件,使用宏定义进行差异化编译。所以我们最重要的一步就是根据系统环境生成ngx_modules.c、ngx_auto_config.h、ngx_auto_headers.h、Makefile这几个文件。

步骤就是非常简单的,使用./configure就好了,以上文件都生成在nginx目录下的objs文件夹内。

生成QTCreator版本的nginx

打开QTCreator创建一个空的QTCreator项目,如下

现在把nginx文件夹下的src、objs文件夹拷贝到nginx目录下

修改.pro文件

TARGET = nginx
DESTDIR = ./objs
LIBS = -lpthread -lcrypt -lpcre -lcrypto -lcrypto -lz
INCLUDEPATH += \
        src/core \
        src/event \
        src/event/modules \
        src/os/unix \
        src/http/modules \
        src/http \
        objs
HEADERS = src/core/nginx.h \
        src/core/ngx_config.h \
        src/core/ngx_core.h \
        src/core/ngx_log.h \
        src/core/ngx_palloc.h \
        src/core/ngx_array.h \
        src/core/ngx_list.h \
        src/core/ngx_hash.h \
        src/core/ngx_buf.h \
        src/core/ngx_queue.h \
        src/core/ngx_string.h \
        src/core/ngx_parse.h \
        src/core/ngx_inet.h \
        src/core/ngx_file.h \
        src/core/ngx_crc.h \
        src/core/ngx_crc32.h \
        src/core/ngx_murmurhash.h \
        src/core/ngx_md5.h \
        src/core/ngx_sha1.h \
        src/core/ngx_rbtree.h \
        src/core/ngx_radix_tree.h \
        src/core/ngx_slab.h \
        src/core/ngx_times.h \
        src/core/ngx_shmtx.h \
        src/core/ngx_connection.h \
        src/core/ngx_cycle.h \
        src/core/ngx_conf_file.h \
        src/core/ngx_resolver.h \
        src/core/ngx_open_file_cache.h \
        src/core/ngx_crypt.h \
        src/event/ngx_event.h \
        src/event/ngx_event_timer.h \
        src/event/ngx_event_posted.h \
        src/event/ngx_event_busy_lock.h \
        src/event/ngx_event_connect.h \
        src/event/ngx_event_pipe.h \
        src/os/unix/ngx_time.h \
        src/os/unix/ngx_errno.h \
        src/os/unix/ngx_alloc.h \
        src/os/unix/ngx_files.h \
        src/os/unix/ngx_channel.h \
        src/os/unix/ngx_shmem.h \
        src/os/unix/ngx_process.h \
        src/os/unix/ngx_setaffinity.h \
        src/os/unix/ngx_setproctitle.h \
        src/os/unix/ngx_atomic.h \
        src/os/unix/ngx_gcc_atomic_x86.h \
        src/os/unix/ngx_thread.h \
        src/os/unix/ngx_socket.h \
        src/os/unix/ngx_os.h \
        src/os/unix/ngx_user.h \
        src/os/unix/ngx_process_cycle.h \
        src/os/unix/ngx_linux_config.h \
        src/os/unix/ngx_linux.h \
        src/core/ngx_regex.h \
        objs/ngx_auto_config.h \
        src/http/ngx_http.h \
        src/http/ngx_http_request.h \
        src/http/ngx_http_config.h \
        src/http/ngx_http_core_module.h \
        src/http/ngx_http_cache.h \
        src/http/ngx_http_variables.h \
        src/http/ngx_http_script.h \
        src/http/ngx_http_upstream.h \
        src/http/ngx_http_upstream_round_robin.h \
        src/http/ngx_http_busy_lock.h \
        src/http/modules/ngx_http_ssi_filter_module.h
SOURCES = src/core/nginx.c \
        src/core/ngx_log.c \
        src/core/ngx_palloc.c \
        src/core/ngx_array.c \
        src/core/ngx_list.c \
        src/core/ngx_hash.c \
        src/core/ngx_buf.c \
        src/core/ngx_queue.c \
        src/core/ngx_output_chain.c \
        src/core/ngx_string.c \
        src/core/ngx_parse.c \
        src/core/ngx_inet.c \
        src/core/ngx_file.c \
        src/core/ngx_crc32.c \
        src/core/ngx_murmurhash.c \
        src/core/ngx_md5.c \
        src/core/ngx_rbtree.c \
        src/core/ngx_radix_tree.c \
        src/core/ngx_slab.c \
        src/core/ngx_times.c \
        src/core/ngx_shmtx.c \
        src/core/ngx_connection.c \
        src/core/ngx_cycle.c \
        src/core/ngx_spinlock.c \
        src/core/ngx_cpuinfo.c \
        src/core/ngx_conf_file.c \
        src/core/ngx_resolver.c \
        src/core/ngx_open_file_cache.c \
        src/core/ngx_crypt.c \
        src/event/ngx_event.c \
        src/event/ngx_event_timer.c \
        src/event/ngx_event_posted.c \
        src/event/ngx_event_busy_lock.c \
        src/event/ngx_event_accept.c \
        src/event/ngx_event_connect.c \
        src/event/ngx_event_pipe.c \
        src/os/unix/ngx_time.c \
        src/os/unix/ngx_errno.c \
        src/os/unix/ngx_alloc.c \
        src/os/unix/ngx_files.c \
        src/os/unix/ngx_socket.c \
        src/os/unix/ngx_recv.c \
        src/os/unix/ngx_readv_chain.c \
        src/os/unix/ngx_udp_recv.c \
        src/os/unix/ngx_send.c \
        src/os/unix/ngx_writev_chain.c \
        src/os/unix/ngx_channel.c \
        src/os/unix/ngx_shmem.c \
        src/os/unix/ngx_process.c \
        src/os/unix/ngx_daemon.c \
        src/os/unix/ngx_setaffinity.c \
        src/os/unix/ngx_setproctitle.c \
        src/os/unix/ngx_posix_init.c \
        src/os/unix/ngx_user.c \
        src/os/unix/ngx_process_cycle.c \
        src/os/unix/ngx_linux_init.c \
        src/event/modules/ngx_epoll_module.c \
        src/os/unix/ngx_linux_sendfile_chain.c \
        src/core/ngx_regex.c \
        src/http/ngx_http.c \
        src/http/ngx_http_core_module.c \
        src/http/ngx_http_special_response.c \
        src/http/ngx_http_request.c \
        src/http/ngx_http_parse.c \
        src/http/ngx_http_header_filter_module.c \
        src/http/ngx_http_write_filter_module.c \
        src/http/ngx_http_copy_filter_module.c \
        src/http/modules/ngx_http_log_module.c \
        src/http/ngx_http_request_body.c \
        src/http/ngx_http_variables.c \
        src/http/ngx_http_script.c \
        src/http/ngx_http_upstream.c \
        src/http/ngx_http_upstream_round_robin.c \
        src/http/ngx_http_parse_time.c \
        src/http/modules/ngx_http_static_module.c \
        src/http/modules/ngx_http_index_module.c \
        src/http/modules/ngx_http_chunked_filter_module.c \
        src/http/modules/ngx_http_range_filter_module.c \
        src/http/modules/ngx_http_headers_filter_module.c \
        src/http/modules/ngx_http_not_modified_filter_module.c \
        src/http/ngx_http_busy_lock.c \
        src/http/ngx_http_file_cache.c \
        src/http/modules/ngx_http_gzip_filter_module.c \
        src/http/ngx_http_postpone_filter_module.c \
        src/http/modules/ngx_http_ssi_filter_module.c \
        src/http/modules/ngx_http_charset_filter_module.c \
        src/http/modules/ngx_http_userid_filter_module.c \
        src/http/modules/ngx_http_autoindex_module.c \
        src/http/modules/ngx_http_auth_basic_module.c \
        src/http/modules/ngx_http_access_module.c \
        src/http/modules/ngx_http_limit_conn_module.c \
        src/http/modules/ngx_http_limit_req_module.c \
        src/http/modules/ngx_http_geo_module.c \
        src/http/modules/ngx_http_map_module.c \
        src/http/modules/ngx_http_split_clients_module.c \
        src/http/modules/ngx_http_referer_module.c \
        src/http/modules/ngx_http_rewrite_module.c \
        src/http/modules/ngx_http_proxy_module.c \
        src/http/modules/ngx_http_fastcgi_module.c \
        src/http/modules/ngx_http_uwsgi_module.c \
        src/http/modules/ngx_http_scgi_module.c \
        src/http/modules/ngx_http_memcached_module.c \
        src/http/modules/ngx_http_empty_gif_module.c \
        src/http/modules/ngx_http_browser_module.c \
        src/http/modules/ngx_http_upstream_ip_hash_module.c \
        src/http/modules/ngx_http_upstream_least_conn_module.c \
        src/http/modules/ngx_http_upstream_keepalive_module.c \
        objs/ngx_modules.c

现在来解释一下为什么这么用

主要解释一下INCLUDEPATH、LIBS,因为我在这上面吃过亏

好了,现在就可以编译了

Nginx如何处理一个请求

author: Igor Sysoev
翻译:赵培龙
原文地址

1.基于名字的虚拟服务器

nginx第一步就是要决定让哪一个服务器来处理相应的请求。我们使用一个简单的例子来说明:
我们现在配置3个虚拟服务器,都监听80端口,配置文件如下

server {
    listen      80;
    server_name example.org www.example.org;
    ...
}

server {
    listen      80;
    server_name example.net www.example.net;
    ...
}

server {
    listen      80;
    server_name example.com www.example.com;
    ...
}

在这个配置下的nginx,nginx会主动去检查http请求中的host字段,根据host字段的值来判断该把这个请求交给哪一个虚拟服务器来处理。如果没有找到匹配的虚拟服务器名,那么nginx会把这个请求交给默认的虚拟服务器,在上面的配置中,默认的服务器是第一个。当然我们也可以显示的指出(使用default_server)哪一个服务器是默认服务器,

server {
    listen      80 default_server;
    server_name example.net www.example.net;
    ...
}

在0.8.21的版本之后使用default_server,之前的版本都是使用的defalut

2.如何处理一个没有带host值的http请求

如果请求头里没有host的值,那么我们在配置中可以这样子定义:

server {
    listen      80;
    server_name "";
    return      444;
}
直接返回444
在0.8.48的版本之后,配置中默认的有这种处理方式,但之前的版本都是匹配上的默认服务器
# 基于IP和主机名的混合虚拟服务器 配置如下
server {
    listen      192.168.1.1:80;
    server_name example.org www.example.org;
    ...
}

server {
    listen      192.168.1.1:80;
    server_name example.net www.example.net;
    ...
}

server {
    listen      192.168.1.2:80;
    server_name example.com www.example.com;
    ...
}

在这种配置下,nginx首先是匹配请求里面的ip和端口,然后才是匹配头里面的host字段,都没有匹配到的情况下就会送给默认的服务器。

配置一个简单的php站点

配置如下:

server {
    listen      80;
    server_name example.org www.example.org;
    root        /data/www;

    location / {
        index   index.html index.php;
    }

    location ~* \.(gif|jpg|png)$ {
        expires 30d;
    }

    location ~ \.php$ {
        fastcgi_pass  localhost:9000;
        fastcgi_param SCRIPT_FILENAME
                      $document_root$fastcgi_script_name;
        include       fastcgi_params;
    }
}

location后面的那些字符串是一个正则表达式,用来匹配URI的,比如location后面的”/“就是来匹配任何请求的,nginx是最长匹配原则来匹配的。

注意到所有的location都没有包含URI的参数,这个是由于URI的参数的写法太多了,举个例子

/index.php?user=john&page=1
/index.php?page=1&user=john

现在我们来看看具体的例子


  1. 一个带有”/logo.gif”首先被 location “/“匹配,然后被”.(gif|jpg|png)$”匹配,但是这个是被后面的那个处理,由于root的值是/data/www所以访问的文件的地址是/data/www/logo.gif,nginx会把这个文件发给客户端
  2. 一个带有”/index.php”依然首先被”/“匹配到,然后被”.(php)$”匹配,这个还是被后面那个location处理。这个请求会传递给fastCGI服务器localhost:9000,fastcgi_param这个配置项是设置FastCGI参数”SCRPT_FILENAME”为”data/www/index.php”,FastCGI服务器会执行这个php脚本,变量$document_root就是root配置项的值,变量$fastcgi_script_name的值就等于请求的URI,这里是”/index.php”
  3. 一个带有”/about.html”依然会最先被”/“匹配,但是由于没有其他的匹配他,所以就直接被”/“处理了,由于root的值是/data/www,所以nginx会找到/data/www/about.html发给客户端。
  4. 处理一个请求”/“更加复杂,这个请求首先被location “/“匹配上,然后又被其处理
    ,这个location里面有一个配置项叫做index,这个配置项测试在/data/www(root配置项的值)文件夹下是否有inde.html文件,如果有,则发给客户端,如果没有,若是存在/data/www/index.phph,则重定向到”/index.php”,这个请求又会重新被定向到处理php的location中进行处理,流程和普通的带有”/*.php”一样。

Nginx源码分析(1)——学习使用nginx

一直以来感觉技术水平偏弱,于是乎,挑了nginx作为练手,希望能通过这个的锻炼,真正切切的提高自己的水平,现在nginx网上的资料已经非常多了,今天就开始做分析nginx的准备工作。

我的nginx版本:1.2.9

源码阅读工具:source Insight

nginx目录

源码目录

1. core    // 是Nginx服务器的主干部分,包含基本数据结构,main()函数,写log等等

2. event    // 事件驱动模型以及相关代码

3. http    // 不用多解释了,肯定与http的实现相关了

4. mail    // 邮件代理相关了

5. misc    //C++兼容性测试和google perftools模块的源码

6. os      // 包装(是包装)了系统的函数调用,Unix网络编程里面把这个方式叫做“包裹函数”

此外,auto这个文件夹下,都是自动化配置脚本
现在我们先来看nginx是如何使用的

nginx配置文件全解
官方配置详解
nginx.conf该文件是启动nginx的主要配置文件

user       www www;  ## Default: nobody
worker_processes  5;  ## Default: 1
error_log  logs/error.log;
pid        logs/nginx.pid;
worker_rlimit_nofile 8192;

events {
  worker_connections  4096;  ## Default: 1024
}

http {
  include    conf/mime.types;
  include    /etc/nginx/proxy.conf;
  include    /etc/nginx/fastcgi.conf;
  index    index.html index.htm index.php;

  default_type application/octet-stream;
  log_format   main '$remote_addr - $remote_user [$time_local]  $status '
    '"$request" $body_bytes_sent "$http_referer" '
    '"$http_user_agent" "$http_x_forwarded_for"';
  access_log   logs/access.log  main;
  sendfile     on;
  tcp_nopush   on;
  server_names_hash_bucket_size 128; # this seems to be required for some vhosts

  server { # php/fastcgi
    listen       80;
    server_name  domain1.com www.domain1.com;
    access_log   logs/domain1.access.log  main;
    root         html;

    location ~ \.php$ {
      fastcgi_pass   127.0.0.1:1025;
    }
  }

  server { # simple reverse-proxy
    listen       80;
    server_name  domain2.com www.domain2.com;
    access_log   logs/domain2.access.log  main;

    # serve static files
    location ~ ^/(images|javascript|js|css|flash|media|static)/  {
      root    /var/www/virtual/big.server.com/htdocs;
      expires 30d;
    }

    # pass requests for dynamic content to rails/turbogears/zope, et al
    location / {
      proxy_pass      http://127.0.0.1:8080;
    }
  }

  upstream big_server_com {
    server 127.0.0.3:8000 weight=5;
    server 127.0.0.3:8001 weight=5;
    server 192.168.0.1:8000;
    server 192.168.0.1:8001;
  }

  server { # simple load balancing
    listen          80;
    server_name     big.server.com;
    access_log      logs/big.server.access.log main;

    location / {
      proxy_pass      http://big_server_com;
    }
  }
}

nginx官方教程

官方教程地址
nginx如何处理一个请求
最后附一张nginx大图

如何更好的读懂别人的C代码

在我们向程序猿进军的过程中阅读别人的代码总是难以避免的,我们常常都喜欢阅读自己的代码而不喜欢阅读别人的代码,归根结底都是由于人与人之间的思维不太可能完全一样,这种思维之间的差异造成了阅读别人代码的障碍。

在我阅读别人的代码过程中,最让我痛苦的事儿就是每一个语法我都认识,但是我就不知道他想干什么!但是,如果代码的作者把他的思路告诉了你,给你画了流程图什么的,你就会较为容易的阅读源代码了,这个就是文档的重要性。因为文档给了你大致的方向,你可以从宏观的角度去审视代码,而不是陷于代码细节之中,让自己一阵阵头大。

我今天写这篇博文的原因只有一个,我发现了一种可以分析代码之间相互调用的工具,而且这种工具还是DIY的,让我震惊了一小把

虽然是别人05年写的这篇文章《用Graphviz可视化函数调用》,但是不得不说,这个东西真的很有用,今天晚上实验了一下,效果很不错,下面是我自动生成的调用关系图:

[![](http://zt2peilong-wordpress.stor.sinaapp.com/uploads/2013/12/graph.jpg "graph")](http://zt2peilong-wordpress.stor.sinaapp.com/uploads/2013/12/graph.jpg)

代码如下:

#include

void level2()
{
    printf("f1\n");
}

void level1()
{
    printf("f2\n");
    level2();
}

main()
{
    level2();
    level1();
}

HDFS RAID




## 背景

HDFS RAID的工作源自Facebook。首先,看看HDFS RAID的作者之一Dhruba Borthakur在2009年发表的博文的一部分。

HDFS的主要不足之一是每份数据要复制在三个地方,当今,磁盘存储越来越便宜,这是可以接受的,相对于小型或中型规模的机群,这并不是一个问题。使用15块磁盘和10块磁盘的价格差距并不大。假设每GB数据的成本为$1,那么15块1TB磁盘和10块1TB磁盘的价格差只是$5k。但如果机群的总数据量是10PB的话,那么将数据存储在两个地方而不是三个,节省的成本是$10,000,000!

上述是在2009年的数据,如今磁盘存储的成本已不到¥1/GB了。

HDFS使用3副本是因为它使用商用机器以及磁盘有不可忽略的出现故障的机率。据观测,在实践中使用3副本已经足以保证不丢失数据。现在的挑战是要保持真实的副本数接近2而有效副本数是3。Erasure Codes是最好的实现方案。

作者的想法参考自CMU的DiskReduce,这是一种在HDFS实现erasure codes的方法。HDFS的代码本身就比较复杂,为了不使其变得更加复杂,作者将HDFS Erasure Coding作为HDFS之上的一个软件层,而不是HDFS中的一部分。

## 概况

HDFS RAID模块提供一个使用Hadoop分布式系统(DFS)的分布式Raid文件系统(DRFS),在DRFS中存储的文件被分成多个由块组成的stripe。对于每个stripe,若干parity(校验)块存储在与源文件对应的parity文件中。这使得当源文件或parity文件中的块丢失或损坏进可以重新计算并恢复成为可能。

DRFS的主要好处是增加针对数据损坏的保护,有了这样的保护,可以采用更低的副本数来保持同样的可用性保障,将会节省很大的存储空间。

## 架构与实现

Raid是Hadoop mapreduce的一个contrib,Hadoop 0.21.0以上版本就有。

HDFS Raid包含几个软件模块:

DRFS client:为应用提供访问DRFS中文件的接口,当在读文件时能透明地恢复任意损坏或丢失的块; RaidNode:为存储在DRFS的所有数据文件创建和维护parity文件的后台进程;
BlockFixer:周期性重新计算已经丢失或损坏的块; Raidshell:允许管理员手动触发丢失或损坏的块的重新计算或检查已遭受不可恢复损坏的文件;
ErasureCode:提供对块中字节的编码及解码。

### DRFS client

DRFS client作为DFS client之上的一软件层,拦截所有进来的请求并传它们传递给下边的客户端。当下边的DFS抛出ChecksumException或BlockMissingException异常,DFS client捕获这些异常,定位当前source文件的parity文件,并在返回丢失的块给应用前将它们重新计算。

值得注意的是,DRFS client在读到损坏的文件重新计算丢失的块时,并不会将这些丢失的块存到文件系统中,它在完成应用的请求后将其忽略。BlockFixer和RaidShell能用来永远地修改损坏的块。

### RaidNode

RaidNode定期扫描配置指定的所有路径,对于每个路径,递归地检查所有拥有超过2个块的文件并选择那些最近(默认是24小时内)没被修改过的文件。一旦选择了一个source文件,它会遍历该文件的所有stripe并为每个stripe创建合适数量的parity块,最后所有的parity块会被合并在一起并存储在与source文件相关的parity文件。RaidNode也会定期删除那些已经孤立或过时的parity文件。

当前RaidNode有两种实现:
LocalRaidNode:在RaidNode本地计算parity块,因为计算parity块是一个计算密集型任务,所以这种方法的可扩展性受到限制;
DistributedRaidNode:分配MapReduce任务来计算parity块。

### BlockFixer

BlockFixer是一个运行在RaidNode上的一个后台进程,周期性地检查DRFS配置的所有路径的状态。当发现一个有丢失或损坏块时,这些块会被重新计算并放回文件系统中。

从Namenode获得损坏文件列表,source文件通过“解码”来重新构造,parity文件通过“编码”来重新构造。

当前BlockFixer有两种实现:
LocalBlockFixer:在RaidNode本地重新计算损坏的块;
DistBlockFixer:分配MapReduce任务来重新计算块。

### RaidShell

RaidShell是一个允许管理维护和检查DRFS的工具,支持手动触发重新计算坏数据块的命令,允许管理查看不可修复文件列表。

运行以下命令可以检验文件系统的完整性:
$HADOOP_HOME/bin/hadoop org.apache.hadoop.raid.RaidShell -fsck [path]

这会打印已损坏文件列表。

### ErasureCode

ErasureCode是被BlockFixer和RaiNode用来生成parity块和修改parity/source块的一组件,ErasureCode实现编码和解码。当在编码时,ErasureCode取几个source字节并生成一些parity字节。当在解码时,ErasureCode通过剩余的souce字节和parity字节来生成丢失的字节。

能被恢复的丢失的字节的个数等于被创建的parity字节的个数。比如,我们把10个source字节编码成3个parity字节,我们能通过剩下的10个字节来恢复任意3个丢失的字节。

ErasureCode有两种实现:
XOR:只允许创建一个parity字节;
* Reed-Solomon:允许创建任意给定数目的parity字节。
使用Reed-Solomon,source文件的副本数能减少到1而不造成数据丢失。1个块只有1个副本的不足是只能通过1个固定的机器来读取1个块,减少了并行性。因此,Reed-Solomon应该用在不会被频繁使用的数据。

## 参考资料

1. HDFS and Erasure Codes (HDFS-RAID)
2. HDFS-RAID
3. http://www.doc88.com/p-307249898331.html

## 后记

文中若有错误或疏漏之处,烦请批评指正。

P2P对等网络读后笔记


作者:赵培龙 日期:2013/11/8



### p2p的研究对象




p2p的研究有人说在三个方面:

1. 实现技术
2. 通信模式
3. 网络拓扑
我认为这三方面主要就是解决2个问题:

1. 如何在p2p网络中找到相应的资源
2. 如何从找到的资源里得到资源
就是如何找和如何得到的问题的研究。

之所以分为上面的三个方面,我个人觉得,网络拓扑就主要是为寻找资源做支撑,通信模式主要是为寻找资源和得到资源做支撑,
实现技术就是讲从网络拓扑、通信模式上如何实现。




我们先从p2p的网络拓扑模式说起。




### P2P网络拓扑的分类和发展

<div class="title">

第一代P2P网络:中央集权

</div>
<div class="content">

    第一代P2P网络的代表就是大名鼎鼎的Napster了,这个牛叉的音乐共享软件,掀起了一个共享的时代,让版权商无比头疼的时代。

    第一代P2P网络的特点就是“中央集权”,这种网络有一个中央服务器,这中央服务器是在整个P2P网络中知道全网所有的资源所处的位置,
    任何一个用户想要得到某个资源只需要向中央服务器问就好了。

    这相当于我们在现实生活中使用搜索引擎达到我们查找网站的目的类似,我们向搜索引擎寻找目标网站的关键字,搜索引擎返回网站的网址,我们然后在直接访问网站。

    这是一种非常朴素的思想,也是一种非常管用而且好实现的思想。

    but 这种P2P的网络有个明显的缺点:

    那就是单点瓶颈,很明显,第一代的P2P网络是围绕中央服务器形成的一种星状网络图,只要中央服务器挂了,那么维系这个网络
    的枢纽节点就没有了,那么这个网络就失效了。

    而且在那个年代,最致命的是这种模式很容易让版权商抓到小辫子,以侵权的借口就可以用法律的手段让这个网络立马陷入瘫痪。

    由于第一代网络的这种巨大软肋,于是出现了和第一代P2P网络完全不同,完全极端的方式的第二代P2P网络。

</div>
<div class="title">

第二代P2P网络:人民战争

</div>
<div class="content">

    由于第一代网络的致命弱点,推动产生了第二代的P2P网络:

    即纯分布式的P2P网络,形象的说就是“人民战争”。
    这个网络的特点是,完全没有一个中央服务器,甚至连类似中央服务器功能的节点都没有!

    每个参与这个网络的节点功能都完全一模一样。

    每个节点都是随机的加入这个网络,
    所以可以想象,这样子的网络会是什么样的拓扑结构?完全没有拓扑,完全的随机,网络拓扑是无比的复杂。

    <div class="qustion">
        <p>那这样子的网络,他们是如何查找资源呢?

    </div>
    我们可以联想一下,你面前有100万个人,你现在需要一块钱的硬币,你怎么才能最快的从人群中借到一块钱的硬币?(假设,每个人都是乐于助人的且,不是每个人都有一块钱硬币)
    最佳的方式应该只有你去问离你最近的人,你最近的人要是没有的话,你周边的人又去问他周边的人,这样子很快这100万人都会知道你需要一块钱的硬币,
    其中有一块钱的硬币的人就会借给你。(有一个很有意思的模型,叫做小世界模型,大概的意思就是说世界很小,每个不相识的人只需要通过他认识的几个人连续介绍几次就认识了)

    从上面的那个实例里,我们可以抽象成我们的P2P网络,比如我们的P2P网络中有100万个节点,某个节点需要查找某个资源,那么这个节点只有向他周围的节点去问!
    这就是一种泛洪的思想。只要是网络是连通的,那么总会通知到有这个资源的节点。这样就解决了内容查找的问题了

    but,这也有很大的缺点。
    当这个P2P网络足够大的时候,由于每一个节点都在产生或者转发请求消息,很有可能产生网络风暴,让网络的可用性变差。
    而且还有一个问题,就是响应风暴,比如我们刚刚举得那个借一块钱的硬币的例子,若是这个100万人之中有50万人有一块钱的硬币,他们直接把硬币向你抛过来,
    那么可以想象的结果是,你被钱给砸死了!哈哈。

    同理!请求资源的节点也极有可能被热情的群众们给弄死。

    这种纯P2P网络的代表主要有Gnutella
</p>
</div>
<div class="title">

混合式P2P网络:古人云,中庸之道

</div>
<div class="content">

        前面的P2P网络都是太过于极端了,要么中央集权,要么就是纯人民路线,人民其实也是需要领导的,在这种要求下,出现了混合式的P2P网络

        即局部是集中式的,整体上还是纯分布式的。
        这样子就可以大大降低纯分布式的P2P网络的规模,原先是每个节点都为P2P的节点,如今在纯分布式P2P的网络层面上,参与者不在是单个节点了
        而是有局部的中央节点和围绕中央节点组成的大一撮节点,有点像抱团。

</div>
<div class="title">

结构化的P2P网络

</div>
<div class="content">

    从上面的介绍我们可以看出,P2P网络的一个核心就在于如何定位到资源所在何处,由于这个问题的存在,所以才有中央服务器,或者泛洪查询
    这些机制,但是这些机制都有着或多或少的缺点,我们从问题的根本上出发,发现有一种数据结构能解决类似的这种问题。
    那就是哈希表。

    哈希表的特点是:我们计算出哈希值之后就能快速的定位到哈希表了,只要是原始数据一样,那么计算出来的哈希值就是一致的,就能快速定位到
    哈希表中的相关位置,这样子查询几乎是O(1).

    在P2P网络中,我们需要的资源的内容一致,那么我们就可以计算这资源的哈希值,我们希望通过哈希值能够快速定位到拥有资源的节点上。
    于是产生了DHT(Distribution Hash Table)分布式哈希表。

    从结构上看,DHT主要分为了三个部分
  1. key值空间

        这就是一个哈希值的集合,包含了所有会出现的哈希值。2.  key值空间分割
    
        这个的主要目的是将哈希值分割成若干部分,这是由于P2P网络中的分布式特性决定的,由每一个节点管理一部分哈希值空间,在整体上只要能覆盖全整个哈希值空间就行了3.  延展网路
    我们从DHT发布一个文件名为filename且内容为value的文件举个栗子
    
  2. 计算出文件名filename的哈希值key

  3. 使用put(key,value)的方法把这个随机送到参与分布式哈希表中的任意节点上
  4. 信息在网络中传递,一直传到key被管理的节点上
  5. 然后最终的节点存储

    具体的实现可以详细看看Chord、Pastry、CAN算法
    最后附上一个连接关于一致性哈希[一致性哈希](http://blog.csdn.net/sparkliang/article/details/5279393)
    

这里文章我主要是参考了P2P对等网络原理与应用/蔡康 … [等] 编著

</div>

session和cookie的学习总结



## seesion和cookie的使用和学习总结




#### 问题的提出:如何让用户登陆了系统之后,在以后的一段的时间内不再需要登陆认证了呢?

首先要需要知道为什么会有这个问题,我们先来了解一下web服务器和浏览器之间的交互方式。

众所周知,web服务器和浏览器之间都是使用http协议来进行交互的,那么我们就先来简单了解一下http协议吧

http协议是建立在tcp上的一个应用层协议,而且它的消息体都是可见的asc字符,

浏览器向web服务器发出“GET”“PUT”的http消息报。

web服务器依据浏览器的请求回复一系列的内容。

http有个最重要的特点是无状态的,什么是无状态的呢?

无状态就是表示浏览器向服务器发起一次tcp连接,服务器向浏览器回复了之后,tcp的连接就断开了,当浏览器再次访问的时候,服务器就不记得你了,就像失忆了一样,
这就是说,服务器不管你是谁,你来了我就根据你的请求回复你就行了,这就叫做无状态。
由于http的无状态性,服务器会把每一次的连接都当做未知的请求,所以一般的情况下,你就不能一次登录,多次免登陆。


好了,这下我们知道了问题的由来,那么要怎么才能解决我们提出的问题呢?
我第二次访问服务器的时候,服务器他妹儿的就不认识我了,那我怎么才能不需要登录就可以进行活动呢?



我们来转换一下想法:

比如说你去网吧上网,每一次都需要叫网管,给网管钱,然后让网管开机。



我们的问题和上面那个例子做对比,
我们把网管那部分比喻成登陆系统,把你上网的部分比喻成服务器提供的服务,
我们现在不想每次都叫网管了,怎么办?

有了生活中的例子做比较就方便解决我们在文章头提出的问题了,我们怎么样才能一次登录,多次享用呢?

我们都知道网吧有个东西叫做会员卡,你只需要办理一张会员卡,冲一些钱进去,你从此就不需要叫网管了
进去直接找台电脑上网就行了。
所以同理,我们需要服务器给我们一个会员卡,这样子每次上网只需要亮一下会员卡就行了。

会员卡是网吧提供的,所以我们要解决上面的问题,就要求服务器必须有能力提供“会员卡”的功能,

会员卡是放在我们身上的,所以我们要解决上面的问题,也要求客户端有存放“会员卡”的功能。

这下子我们就明了。我们要实现这样的功能就要求服务器和客户端分别满足上面的要求就是了。

所以,我们的主角登场了,cookie&seesion
cookie就是服务器放在客户端的一小块文本,cookie就是我们的会员卡!


cookie在客户端是如何存放的呢?
在客户端里面会将用户访问过的所有的cookie存放在一起,有点像“卡包”的感觉,每当客户端访问服务器的时候,客户端就直接把“卡包”给服务器,服务器需要在卡包里面
找自己的那张“会员卡”。

session也是依靠cookie实现的,

从上面关于cookie的介绍知道了,cookie确实不怎安全,因为它把所以的会员卡信息都保存在客户那里,客户还会把“卡包”一次性的给别人?!!

这怎么能忍?!

所以session就是为了解决这个问题出生的。

session就是直接给客户端一个连客户端都看不懂的一大串的字符串,相当于全球唯一的id,这id号就别人都仿造不出来的,只有本服务器拥有。
这是为了防止别人假冒。
有了个全世界人民除了本服务看得懂的id,服务器就可以有一个map,对应的id可以存在客户无数多特有的信息。

这其实本质和cookie一样,只是说原先有客户端放具体内容,变成了客户端放一个指针,
以上内容是本人是这么理解的,如果有错误请不吝指出

现在可以解决问题了,

首先,用户访问我们的系统的时候,我们先查看他卡包中有没有我们的会员卡,如果有,就让他直接通过了,如果没有,那么就需要验证用户,
用户验证通过之后马上给他办张会员卡,那么他在第二次访问的时候我们就知道他可以直接通过了,我们就不需要验证了。
蛤蛤 问题解决了,是不是感觉too young too simple~

myBatis和spring整合的一个例子以及其中出现的问题

mybatis和spring的整个经过

准备步骤如下

  1. 创建数据库表
  2. 创建数据库中表的模型对象
  3. 创建操作数据库表的接口
  4. 对于数据库操作的两种方式

    *   [创建操作数据库的映射xml文件](#41)
    
  5. 写spring的配置文件详解
  6. 期间遇到的问题

    创建数据库表

ddl如下

<pre lang="sql">
    CREATE TABLE `user` (
    `state` INT(11) DEFAULT NULL,
    `name` CHAR(20) DEFAULT NULL,
    `pwd` CHAR(100) DEFAULT NULL,
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    PRIMARY KEY (`id`)
    ) 
</pre>

**创建数据库中表的模型对象**

User类如下

<pre lang="java">
//User.java
    public class User {

    private int id;
    private String pwd;
    private String name;
    private int state;

    //setter &amp; getter

    } 
</pre>

**创建操作数据库表的接口**

UserDao类如下

<pre lang="java">
//UserDao.java
    public interface UserDao {
    //增加用户
    void addUser(User u);

    //删除用户
    void deleteUser(User u);

    //更新用户信息
    void updateUser(User u);

    //的到用户信息
    User getUserById(int id);

    //得到用户数目
    int getUserNum();
    } 
</pre>

**对数据库操作的两种方式**

mybatis对数据库进行操作肯定是需要sql语句的,那么sql语句要放在哪儿呢?现在有2种方法如下

**一、创建操作数据库的映射xml文件**

映射文件的xml代码如下

<pre lang="xml">

//UserMapper.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper 
    PUBLIC "-//mybatis.org/DTD Mapper 3.0//EN"
     "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

     <mapper namespace="com.model.dao.UserDao">
        <select id="getUserById" resultType="User" parameterType="int" >
            SELECT
                *
            FROM user
            WHERE
            id= #{id}
        </select>

        <select id="getUserNum" resultType="int" >
            SELECT
                COUNT(*)
            FROM user
        </select>

        <insert id="addUser" parameterType="User">
            INSERT
            INTO user(name,pwd,state)
            VALUES(#{name},#{pwd},#{state})
        </insert>

        <update id="updateUser" parameterType="User">
            UPDATE user
            SET
            name=#{name}
            WHERE
            id=#{id}
        </update>

        <update id="deleteUser" parameterType="User">
            UPDATE user
            SET
            state=#{state}
            WHERE
            id=#{id}
        </update>

     </mapper> 
</pre>

**二、直接在接口里面写入sql语句**

在我们第三步时候创建的接口是表示我们对这个模型的数据库可以进行哪一些的操作,同样,我们可以再这里使用标注的方式写出sql,方面查看,这样,接口就变成下面那样了

<pre lang="java">

//UserDao.java

package com.model.dao;

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import com.model.User;

public interface UserDao {
    //增加用户
    @Insert("         INSERT    INTO user(name,pwd,state)    VALUES(#{name},#{pwd},#{state})")
    void addUser(User u);

    //删除用户
    @Update("         UPDATE user    SET    state=#{state}    WHERE    id=#{id}")
    void deleteUser(User u);

    //更新用户信息
    @Update("         UPDATE user    SET    name=#{name}    WHERE    id=#{id}")
    void updateUser(User u);

    //的到用户信息
    @Select("         SELECT    * FROM user    WHERE    id= #{id}")
    User getUserById(int id);

    //得到用户数目
    @Select("         SELECT    COUNT(*)    FROM user")
    int getUserNum();

}
</pre>

**写spring的配置文件详解**

配置文件如下

<pre lang="xml">

//spring-config-dao.xml

    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">

            <!-- 这个是一个数据源,专门连接数据库的 -->
            <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
                <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
                <property name="url" value="jdbc:mysql://localhost:3306/springtestdb"></property>
                <property name="username" value="root"></property>
                <property name="password" value="123456"></property>
            </bean> 

            <!-- 这下面都是mybatis的配置 -->

            <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
                <property name="dataSource" ref="dataSource" />
                <property name="typeAliasesPackage" value="com.model"></property>
                <!-- 备注:这里要是在接口里面写了sql语句,那么这一样就可以注释掉,这一行的意思是寻找所有的sql映射文件            
                <property name="mapperLocations" value="classpath:model/*Mapper.xml"></property>
                 -->
            </bean> 

            <!-- 这个是创建一个bean,他的名字叫做userDao,也可以使用基于包的方式来自动装在 -->
            <bean id="userDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
                <property name="mapperInterface"  
                   value="com.model.dao.UserDao" />  
                <property name="sqlSessionFactory" ref="sqlSessionFactory" /> 
            </bean>

    </beans> 
</pre>

**下面展示一下对这个的单元测试代码**
<pre lang="java">

//UserDaoTest.java

package com.model;

import junit.framework.TestCase;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.model.dao.UserDao;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:spring-config-dao.xml")
public class UserDaoTest extends TestCase{

    @Autowired
    private UserDao userDao;

    @Test
    public void getNumTest(){
        System.out.println(userDao.getUserNum());
    }
}

</pre>

**期间遇到的问题**

1.对于配置文件找不到的问题,主要是classpath明白不了,参考了下面的这篇文章,大体明白了,向大家推荐下
http://my.oschina.net/yjx/blog/6253

2.期间出现了一个异常

<pre lang="java">
org.apache.ibatis.binding.BindingException
</pre>

查了一下主要是由于映射文件的namespace和映射的接口不一致,我参考下面的文章
mybatis绑定错误

mybatis-spring学习网站这个是个好网站

mybatis与spring的整合经过

防止以后忘记,所以我现在写下做纪念:

第一步:下载相关的包

我是使用maven自动添加依赖:

主要需要的包有

  • commons-collections
  • mysql-connector-java
  • commons-pool
  • commons-dbcp
  • mybatis-spring
  • mybatis
    这上面是除了spring需要的包外的整合mybatis的包

第二步:设计数据库

我们的最终目标还是读出数据库之中的数据,首先我们建立一张表,表的ddl如下

CREATE TABLE `user` (
`state` int(11) DEFAULT NULL,
`name` char(20) DEFAULT NULL,
`pwd` char(100) DEFAULT NULL,
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
)
和我们的表相对应的类我们取名字为User 代码如下
public class User {

private int id;
private String pwd;
private String name;
private int state;

//setter & getter

}
第三步:创建对User表操作的接口 我们使用mybatis操作数据库,那么我们就要符合mybatis的规范,mybatis中可以建立接口对数据库操作,其余的对象只需要调用调用接口就可以对数据库进行操作了,神奇的是,我们并不需要对这个接口进行实现,因为我们只需要写一个xml的文本就可以代表实现这个接口,这样子我们就不需要管建立连接等等乱七八糟的事儿,大大的简化了我们的劳动量,废话不说, 先创建User的接口,我取名字叫做UserMapper
public interface UserMapper {
//增加用户
void addUser(User u);

//删除用户
void deleteUser(User u);

//更新用户信息
void updateUser(User u);

//的到用户信息
User getUserById(int id);

//得到用户数目
int getUserNum();

}
这下我们创建好了,下一步我们就需要创建记录描述的该接口的具体业务sql的xml文件了 第四步:创建描述sql的xml文件 文件类容如下



 
     

     

     
         INSERT
         INTO user(name,pwd,state)
         VALUES(#{name},#{pwd},#{state})
     

     
         UPDATE user
         SET
         name=#{name}
         WHERE
         id=#{id}
     

      
         UPDATE user
         SET
         state=#{state}
         WHERE
         id=#{id}
     

 

我们命名为User.xml

第五步:配置mybatis配置文件

我们要配置好mybatis的配置文件,mybatis的配置文件的作用还是主要是

在res下建立一个新的xml文件作为mybatis的配置文件,我取名字叫做mybatis-config.xml

这个配置文件里面主要有2个标签

  
      
 
这里是给对象模型取个别名,因为和数据库中表相对应的对象可以在很深的包里面,在其余的地方引用的话会让人很不方便,于是就可以去个别名,让引用变得更加方便。实例如下:
` <typeAliases> <typeAlias type="daoBean.User" alias="User" /> </typeAliases>`
我们把daoBean这个包里面的User取了个别名叫做User,这样我们在需要些daoBean.User的地方就可以直接写User 和 <mappers> 这个是指示出映射文件的位置 比如说找到我们刚刚写的那个sql的xml文件的位置


  
      
        
    
  

第六步:配置spring的配置文件

在这里我遇到了一个坑,就是这个配置文件前面beans的xmlns的域名一堆的schema文件位置

我直接copy了一份,准备找个时间在细细的研究


...


这个问题解决掉了之后,我们第一步要配置数据源

        
            
            
            
            
        

第二步就是

        
        
            
            
                

sqlSessionFactory是mybatis里面很牛叉的东西,不信去百度

最后一个配置项就是需要将我们先前写的接口写进来,靠着这个来与写着sql的xml文件建立一一对应的关系。

有2中方式

大家看


        
                第二种
        
            
        

这样子我们就做完所有的工作了