zoukankan      html  css  js  c++  java
  • Apache2.4配置总结(转)

     

    文章内容转自- ->https://blog.csdn.net/u012291157/article/details/46492137

    1、apache开机自启动

    [root@csr ~]# cp `which apachectl` /etc/init.d/httpd
    [root@csr ~]# vim /etc/init.d/httpd 在#!/bin/bash下加入:(前面需要'#')
    # chkconfig: 2345 85 15
    # description: httpd2.4...
    [root@csr ~]# chkconfig --add /etc/init.d/httpd
    [root@csr ~]# chkconfig --list httpd
    httpd    0:off  1:off   2:on    3:on    4:on    5:on    6:off
    

      

    2、配置多个虚拟主机:基于域名、IP、PORT

    很多时候你想在一台机器上跑多个网站,比如一个跑discuz、一个跑wordpress、一个跑其他网站...
    这时候你就要需要开启apache的虚拟主机配置了。
    
    前面几篇实际上有介绍过这个了,这里还是重新讲下吧:
    第一步:编辑httpd.conf将vhost的注释去掉(去掉'#')
    # Include conf/extra/httpd-vhosts.conf
    第二步:开始配置虚拟主机
    [root@csr ~]# vim /usr/local/apache2/conf/extra/httpd-vhosts.conf
    # 基于域名的
    <VirtualHost *:80>
        DocumentRoot "/data/www" # 指定你的web根目录
        ServerName www.csr.com # 配置多个的时候改这里即可
    </VirtualHost>
    # 基于IP的
    <VirtualHost 192.168.137.22:80>
        DocumentRoot "/data/www1"
        ServerName www.csr.com
    </VirtualHost>
    # 基于PORT的,只是这个还必须编辑httpd.conf加入:Listen 8080
    <VirtualHost *:8080>
        DocumentRoot "/data/www2"
        ServerName www.csr.com
    </VirtualHost>
    
    对于http,默认端口是80,如果是基于端口的,用户每次请求还需要输入port,而且很多用户甚至不懂的怎么做,所以这种方法不常用; 
    基于ip的,现如今ip地址紧缺,使用基于ip也并不是什么好方法; 
    所以最常用的就是这个基于域名的虚拟主机了(申请一个域名相对与ip来说一般还是便宜很多的)
    

      

    3、配置域名跳转

    因为各种原因,你换了个域名;但你的老顾客并不知道或者并不想记你的新域名,这时候就可以通过域名跳转将其跳转到你的新域名了。
    
    [root@csr ~]# vim /usr/local/apache2/conf/extra/httpd-vhosts.conf
    <VirtualHost *:80>
        DocumentRoot "/data/www"
        ServerName www.csrnew.com # 新域名
        ServerAlias www.csr.com # 别名(老域名)
    
        # 方法一:开启rewrite,但会降低效率
        # mod_rewrite应该是最后手段,除非没有其他方法,否则不要轻易使用它(这句来自Apache2.4官方文档翻译的)
        # 首先还得开启rewrite_module模块
        [root@csr ~]# vim /usr/local/apache2/conf/httpd.conf 去掉注释
        #LoadModule rewrite_module modules/mod_rewrite.so
        [root@csr ~]# apachectl graceful
        # 检查是否已经加载
        [root@csr ~]# apachectl -M |grep -i 'rewrite'
         rewrite_module (shared)
        # 然后编辑vhost开始使用mod_rewrite模块
    #   <IfModule mod_rewrite.c> 
    #       RewriteEngine on # 开启rewrite引擎
    #       RewriteCond %{HTTP_HOST} ^www.csr.com$ [OR]   
    #       RewriteCond %{HTTP_HOST} ^csr.com$ [OR]     
    #       RewriteCond %{HTTP_HOST} ^csrnew.com$     
    #       RewriteRule ^/(.*)$ http://www.csrnew.com/$1 [R=301,L] 
    #   </IfModule>
    
        # 方法二:简单高效,不需要开启rewrite模块
        <If "(%{HTTP_HOST} == 'www.csr.com') || (%{HTTP_HOST} == 'csr.com') || (%{HTTP_HOST} == 'csrnew.com')">
            Redirect permanent / http://www.csrnew.com/ # 301重定向
        </If>
        # 后面继续判断,比如其他人用www.nocsr.com域名绑定你的IP,加上这个他就访问不到了(403 Forbidden)
        # 自己测试的时候改hosts绑定IP即可,看看是不是403 Forbidden
        <ElseIf "!(%{HTTP_HOST} == 'www.csrnew.com') && !(%{HTTP_HOST} == 'localhost')">
            Require all denied
        </ElseIf>
    </VirtualHost>
    
    # 使用curl测试,也可以在windows上打开浏览器->打开审查元素(按F12也可以打开)->Network查看,如图1
    
    # curl -I 只请求http首部(使用HEAD方法) -x 使用HTTP代理proxy,结果见图2
    [root@csr ~]# curl -x127.0.0.1:80 www.test.com/static/image/common/logo.png -I
    

      

    4、屏蔽恶意USER_AGENG

    有时候可能会有一些恶意的USER_AGENG会一直爬你的网站,这时你需要屏蔽他们。
    (或者你不想让某些蜘蛛爬你的网站,同样可以使用USER_AGENG屏蔽他们)
    
    [root@csr ~]# vim /usr/local/apache2/conf/extra/httpd-vhosts.conf
    # 方法一:使用mod_rewrite模块,并不推荐这个方法,除非你真的不懂其他方法了
    #   不加[OR]默认是表示AND,只允许匹配Firefox、Too Bot/1.0的访问,其他的一律拒绝,i忽略大小写,可以用m##代替//
    #   <IfModule mod_rewrite.c>
    #        RewriteEngine on
    #        RewriteCond expr "!(%{HTTP_USER_AGENT} =~ /Firefox/i)"  [NC]
    #        RewriteCond expr "!(%{HTTP_USER_AGENT} =~ m#Too Bot/1.0#i)"  [NC]
    #        RewriteRule  .*  -  [F]
    #    </IfModule>
    
    # 方法二:只允许匹配chrome,google的user_agent访问,其他的一律拒绝
    #   <If "!(%{HTTP_USER_AGENT} =~ /google/i) && !(%{HTTP_USER_AGENT} =~ /chrome/i)">
    #       Require all denied
    #   </If>
    
    # 开始测试,结果见下图
    [root@csr ~]# apachectl -t 
    Syntax OK 
    [root@csr~]# apachectl graceful
    [root@csr ~]# curl -x127.0.0.1:80 -A "baidu/1.0" www.test.com -I
    [root@csr ~]# curl -x127.0.0.1:80 -A "chrome/1.0" www.test.com -I
    

      

    5、配置用户认证

    对于一些重要内容,需要加一些安全措施,用户认证就可以在一定程度上保证它的安全。
    
    [root@csr ~]# vim /usr/local/apache2/conf/extra/httpd-vhosts.conf
    # FilesMatch后面的文件是相对路径,而Files、Directory则使用绝对路径
    # (比如这里Directory则为:"/data/www/admin.php")
    <FilesMatch "admin.php">
        AllowOverride AuthConfig
        AuthName "csr: test Authentication."
        AuthType Basic
        AuthUserFile /data/.htpasswd # 基于用户的
        # AuthGroupFile /data/.htgpasswd    # 基于组的
        # Require user csr      # 只允许csr用户认证
        Require valid-user  允许有效用户认证
        # Require group group-csr   允许group-csr组认证
    </FilesMatch>
    
    [root@csr ~]# apachectl -t 
    Syntax OK 
    [root@csr~]# apachectl graceful
    
    # /usr/local/apache2/bin/htpasswd:用于创建用户认证的账户和密码
    # htpasswd第一次创建用户要用到-c 参数 第2次就不能加-c了,否则会覆盖前面已建立好的用户
    [root@csr ~]# /usr/local/apache2/bin/htpasswd -c /data/.htpasswd  test
    # 提示输入密码然后完成
    
    # 结果如图:
    

      

    6、访问控制

    访问控制,很基础但非常重要,很多安全设置都是靠他实现的:
    比如某些企业只允许本局域网内的主机对某一特定目录的某类文件进行访问,外来的则全部禁止:
    <Directory /path/>
        <FilesMatch ".+.(txt|doc)$">
            Require all denied
            Require ip 192.168.0.0/16
        </FilesMatch>
    </Directory>
    
    Apache2.4以下版本的访问控制方法有点奇特,规则是这样的:
    -- 首先看Order后面是那个再前面
    -- 如果deny(allow)在前,那么看deny(allow) from,按顺序看完再看allow(deny)的
    
    例一、禁止5.5.5.5和6.6.6.6的:
    Order allow deny 也可以这样: Order allow deny
    Deny from 5.5.5.5           Allow from all
    Deny from 6.6.6.6           Deny from 6.6.6.6
    Allow from all              Deny from 5.5.5.5
    
    例二、只允许5.5.5.5和6.6.6.6的:
    Order deny allow 也可以这样: Order deny allow
    Allow from 5.5.5.5          Deny from all
    Allow from 6.6.6.6          Allow from 6.6.6.6
    Deny from all               Allow from 5.5.5.5
    
    Apache2.4开始,取消这种奇怪的规则,改成更通俗易懂的:
    #   Require all denied   全部禁止
    #   Require all granted  全部允许 
    #   Require host www.csr.com  
    #   Require ip 192.168.1 192.168.2 
    #   Require ip 192.168.1/24 
    ...
    其他的等用到了再介绍吧
    

      

    7、配置防盗链

    有时候,你的网站莫名其妙的访问量变大,不要高兴的太早,有可能是被别人盗链了...
    举个例子:比如我搭的这个discuz论坛,有人发了一个贴,里面全是些xxx图片视频;
    然后将他网站上访问图片的地址重定向到我的discuz上,这样他的服务器就可以空闲出来了;
    也就是说别人访问他网站的图片视频,消耗的确是你服务器的资源;
    网络上访问xxx图片视频的人很多,这样就很有可能导致你的discuz负载超核挂了;
    
    解决这个问题的方法是配置下防盗链,让外来的盗不了链;
    (不过最本质的方法还是自己定期删除些违法的内容,没有这些违法内容别人也不会去盗链)
    
    # 对视频图片压缩包等比较耗资源的做下防盗链
    SetEnvIfNoCase Referer "^http://www.csr.com" local_ref
    SetEnvIfNoCase Referer "^http://csr.com" local_ref
    <filesmatch ".(mp3|mp4|zip|rar|jpg|gif|png)"> 
        # 2.4版本以下的
        方法一:
        Order Deny,Allow 
        Allow from env=local_ref 
        Deny from all
        方法二:
        Order Allow,Deny 
        Allow from env=local_ref
    
        2.4版本以上,方法如下:
        Require all denied
        Require env local_ref
    </filesmatch> 
    
    # graceful下apache然后结果如下图:

    8、配置静态文件缓存

    配置静态缓存可以减少浏览器下载同一资源的次数,同时也可以减轻服务器的压力和节省带宽;
    比如说浏览器请求一个csr.html,该html里面包含一张csr.png图片;
    没有配置静态缓存则每次请求都要重新加载下csr.png图片;
    而配置了静态缓存则在有效期内不会再请求该图片。
    
    # 首先要开启mod_expires模块(取消前面的注释'#')
    [root@csr ~]# vim /usr/local/apache2/conf/httpd.conf
    LoadModule expires_module modules/mod_expires.so
    [root@csr ~]# apachectl -t 
    Syntax OK 
    # 检查模块是否正确开启
    [root@csr ~]# apachectl graceful
    [root@csr ~]# apachectl -M |grep expires_module
     expires_module (shared)
    
    # 开始配置静态缓存
    [root@csr ~]# vim /usr/local/apache2/conf/extra/httpd-vhosts.conf
    <IfModule mod_expires.c>
        ExpiresActive on
        ExpiresByType image/gif  "access plus 1 days"
        ExpiresByType image/jpeg "access plus 24 hours"
        ExpiresByType image/png "access plus 24 hours"
        ExpiresByType text/css "now plus 2 hour"
        ExpiresByType application/x-javascript "now plus 2 hours"
        ExpiresByType application/x-shockwave-flash "now plus 2 hours"
        ExpiresDefault "now plus 0 min"
    </IfModule>
    
    # 打开浏览器,查看结果是否正确(304表示缓存了),缓存时间是否与配置的一致
    # 这里不能使用curl测试了,因为curl命令并不支持缓存功能,所以看不到304的
    

      

    9、配置伪静态

    对于某些更新频繁的网站来说,使用静态则不利与更新,而使用动态又不利于网络蜘蛛爬你的网站,于是,就产生了伪静态技术。
    
    伪静态只是使用rewrite模块改变了URL,实际上还是动态页面;
    例如:你请求www.csr.com/a.html,服务器提取出uri,然后使用rewrite模块重写为a.php,再调用a.php将结果返回浏览器。
    从这里的分析可以看出,伪静态实际上比动态还要耗资源,因为对每个请求,都必须使用rewrite重写URL。
    
    # 这里不能再使用前面的方法了,因为expr中只有匹配没有替换,所以,重写URL的话就只能使用rewrite模块了
    # 既然要使用rewrite模块,那么就要先开启才行:
    [root@csr ~]# vim /usr/local/apache2/conf/httpd.conf
    LoadModule rewrite_module modules/mod_rewrite.so
    [root@csr ~]# apachectl -t 
    Syntax OK 
    [root@csr ~]# apachectl graceful
    [root@csr ~]# apachectl -M |grep rewrite_module
     rewrite_module (shared)
    
     # discuz伪静态配置
     # 自己一个个重写有点麻烦,这里就直接使用aminglinux里的discuz伪静态配置了
     # 规则很简单,提取整个查询字符串,然后将....html的重写成后面的形式
    [root@csr ~]# vim /usr/local/apache2/conf/extra/httpd-vhosts.conf
    RewriteCond %{QUERY_STRING} ^(.*)$
    RewriteRule ^/topic-(.+).html$ /portal.php?mod=topic&topic=$1&%1
    RewriteCond %{QUERY_STRING} ^(.*)$
    RewriteRule ^/article-([0-9]+)-([0-9]+).html$ /portal.php?mod=view&aid=$1&page=$2&%1
    RewriteCond %{QUERY_STRING} ^(.*)$
    RewriteRule ^/forum-(w+)-([0-9]+).html$ /forum.php?mod=forumdisplay&fid=$1&page=$2&%1
    RewriteCond %{QUERY_STRING} ^(.*)$
    RewriteRule ^/thread-([0-9]+)-([0-9]+)-([0-9]+).html$ /forum.php?mod=viewthread&tid=$1&extra=page\%3D$3&page=$2&%1
    RewriteCond %{QUERY_STRING} ^(.*)$
    RewriteRule ^/group-([0-9]+)-([0-9]+).html$ /forum.php?mod=group&fid=$1&page=$2&%1
    RewriteCond %{QUERY_STRING} ^(.*)$
    RewriteRule ^/space-(username|uid)-(.+).html$ /home.php?mod=space&$1=$2&%1
    RewriteCond %{QUERY_STRING} ^(.*)$
    RewriteRule ^/blog-([0-9]+)-([0-9]+).html$ /home.php?mod=space&uid=$1&do=blog&id=$2&%1
    RewriteCond %{QUERY_STRING} ^(.*)$
    RewriteRule ^/archiver/(fid|tid)-([0-9]+).html$ /archiver/index.php?action=$1&value=$2&%1
    RewriteCond %{QUERY_STRING} ^(.*)$
    RewriteRule ^/([a-z]+[a-z0-9_]*)-([a-z0-9_-]+).html$ /plugin.php?id=$1:$2&%1
    

      

    10、自定义访问日志+错误日志格式

    很多时候,apache默认的日志格式并不满足我们的需求,这时我们就需要自定义日志的格式了。
    
    例如:%h 记录访问者的IP,如果在web的前端有一层代理,那么%h其实是代理机器的IP;
    而%{X-FORWARDED-FOR}i 字段则会记录客户端真实的IP。
    
    1、自定义访问日志(范围:全局、vhost都可以)
    # 在<IfModule log_config_module>模块里加入:(如下图)
     [root@csr ~]# vim /usr/local/apache2/conf/httpd.conf
     LogFormat "%h %{X-FORWARDED-FOR}i %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"" csr
    
    2、自定义错误日志(范围:全局、vhost都可以)
    # 在<IfModule log_config_module>模块里加入:(如下图)
    [root@csr ~]# vim /usr/local/apache2/conf/httpd.conf
    ErrorLogFormat "[%t] [%l] [pid %P] %F: %E: [client %a] %M"
    
    根据个人的喜好可以配置成不同的格式,每个参数具体意义详见Apache2.4官方文档,这里再介绍内容就太多了。
    

      

    11、排除无意义的日志

    对于一般的请求图片、css等日志,是根本不需要记录的,反而还会增加日志的大小。
    对于大访问量的图片网站,则更需要排除没意义的日志记录。
    
    # 使用上面的自定义日志格式,同时不记录后缀为gif、jpg等日志
    [root@csr ~]# vim /usr/local/apache2/conf/extra/httpd-vhosts.conf
        SetEnvIf Request_URI ".*.gif$" image-request
        SetEnvIf Request_URI ".*.jpg$" image-request
        SetEnvIf Request_URI ".*.png$" image-request
        SetEnvIf Request_URI ".*.bmp$" image-request
        SetEnvIf Request_URI ".*.swf$" image-request
        SetEnvIf Request_URI ".*.js$" image-request
        SetEnvIf Request_URI ".*.css$" image-request
        SetEnvIf Request_URI ".*.ico$" image-request
        CustomLog "/tmp/1.log" csr env=!image-request
    

      

    12、日志切割

    随着时间的增加,服务器产生的日志文件会越来越大,如果不对日志进行分割;
    那么删除日志只能整个删除,这样会丢失很多宝贵的信息。
    而且分割日志对以后查看日志也更加方便了,删除的时候也可以选择保留最近一段时间的日志。
    
    # 日志分割,需要用到apache自带的rotatelogs工具
    /usr/local/apache2/bin/rotatelogs 
    rotatelogs --help   查看帮助信息可以让我们了解怎么分割日志
    
    # 以天为单位进行分割,-l指定使用本地时间,86400单位为秒=1天
    # 配置时结合上面的“不记录没意义日志”,重复了这里就不加上了
    [root@csr bin]# vim /usr/local/apache2/conf/extra/httpd-vhosts.conf
    CustomLog "|/usr/local/apache2/bin/rotatelogs -l /tmp/access_%Y%m%d.log 86400" csr env=!image-request
    ErrorLog "|/usr/local/apache2/bin/rotatelogs -l /tmp/discuz_error_%Y%m%d.log 86400"
    

      

    13、错误日志级别-差异记录

    有时候网站有问题了,查看错误日志却没有发现上面异常,很可能是你定义的日志级别太高导致没有记录到;
    这时就可以将级别(LogLevel)调成debug然后进行调试。
    
    # LogLevel:作用范围:全局、vhost、Directory
    # 也就是说可以细到对每个目录进行差异记录,这很有用!
    # 比如你可以在总的httpd.conf里设置为error,然后在某些很重要的目录设置级别为debug;
    # 这样记录日志的时候就可以记录更多重要目录的信息而不会把其他目录也记录下来了。
    
    # 例如全局设置为error,而passwd目录(里面存着很多人的银行卡密码)设置为debug
    [root@csr bin]# vim /usr/local/apache2/conf/httpd.conf
    ...
    LogLevel error
    ...
    <Directory "/data/zhifubao/passwd/">
      LogLevel debug
    </Directory>
    
    # 下面列出LogLevel的所有级别(来自Apache2.4官方文档)
    Level   Description     Example
    emerg   Emergencies - system is unusable.   "Child cannot open lock file. Exiting"
    alert   Action must be taken immediately.   "getpwuid: couldn't determine user name from uid"
    crit    Critical Conditions.    "socket: Failed to get a socket, exiting child"
    error   Error conditions.   "Premature end of script headers"
    warn    Warning conditions. "child process 1234 did not exit, sending another SIGHUP"
    notice  Normal but significant condition.   "httpd: caught SIGBUS, attempting to dump core in ..."
    info    Informational.  "Server seems busy, (you may need to increase StartServers, or Min/MaxSpareServers)..."
    debug   Debug-level messages    "Opening config file ..."
    trace1  Trace messages  "proxy: FTP: control connection complete"
    trace2  Trace messages  "proxy: CONNECT: sending the CONNECT request to the remote proxy"
    trace3  Trace messages  "openssl: Handshake: start"
    trace4  Trace messages  "read from buffered SSL brigade, mode 0, 17 bytes"
    trace5  Trace messages  "map lookup FAILED: map=rewritemap key=keyname"
    trace6  Trace messages  "cache lookup FAILED, forcing new map lookup"
    trace7  Trace messages, dumping large amounts of data   "| 0000: 02 23 44 30 13 40 ac 34 df 3d bf 9a 19 49 39 15 |"
    trace8  Trace messages, dumping large amounts of data   "| 0000: 02 23 44 30 13 40 ac 34 df 3d bf 9a 19 49 39 15 |"
    

      

    14、开启server-info、server-status

    对于服务器的状态和配置信息,Apache也提供了一个方法:通过server-info、server-status查看;
    通过查看这两个我们可以很方便的了解到Apache当前的详细状态与配置信息,很好用,不过必须加上访问控制,否则就可能让外来人看到你的配置信息了。
    这也很简单,根据前面所讲的只允许本局域网内的主机查看,更细致点,只允许特定几台主机查看,这样就不用担心会泄露了。
    
    # ...老是直接教怎么做却没有告诉你们方法学了可能也是白学,拿这个为例:
    1、首先server-info、server-status的信息在httpd-info.conf里有介绍,查看该文件
    [root@csr bin]# vim /usr/local/apache2/conf/extra/httpd-info.conf
    
    2、里面有这样的三行:
    # Required modules: mod_authz_core, mod_authz_host,
    #                   mod_info (for the server-info handler),
    #                   mod_status (for the server-status handler)
    说明他们依赖这些模块,要开启则必须先加载这些模块...加载这些模块
    (至于加载模块前面已经讲过多次了,取消LoadModule前面的注释然后grep检查是否正确加载即可)
    
    3、接着往下看:with the URL of http://servername/server-status
    这个介绍了配置好后怎么在浏览器里打开他们
    
    4、继续:发现它已经给了大致模版了,编辑vhost文件将其加入,然后修改下访问控制,例如status:
    <Location /server-status>
        SetHandler server-status
        Require all denied
        Require ip 127.0.0.1
        Require ip x.x.x.x
        ...
    </Location>
    
    5、graceful下Apache,然后浏览器测试,发现提示not found
    仔细想想httpd-info.conf配置文件和虚拟主机配置一样在./conf/extra/下,
    这下面的配置文件想要生效必须在httpd.conf里取消Include ...的注释;
    
    6、于是,编辑httpd.conf,开启httpd-info.conf配置文件
    # Real-time info on requests and configuration
    # Include conf/extra/httpd-info.conf
    
    7、再次测试,发现可以查看了(结果见下图)
    
    8、从server-info、server-status可以看到很多有用的信息
    比如status可以看到等待连接的请求有多少个、cpu的使用率、空闲(忙碌)的线程数等等
    而info中可以很方便的看到某一模块在哪些行被配置使用,点击模块还会跳转到该模块下面...
    具体的自己去试试吧
    

      

    15、 HTTP/1.1 状态码

    --来自HTTP/1.1RFC文档
    -1xx: 报告的 - 接收到请求,继续进程.
    -2xx 成功 - 步骤成功接收,被理解,并被接受
    -3xx 重发 - 为了完成请求,必须采取进一步措施.
    -4xx 客户端出错 - 请求包括错的顺序或不能完成.
    -5xx 服务器出错 - 服务器无法完成显然有效的请求.
    

      

    16、ErrorDocument+Alias

    1、自定义404 not found 页面
    # vim vhost.conf加入
    ErrorDocument 404 "/csrtest/not_found.html"
    # cat not_found.html
    <html><title>404</title><body>...not found...</body></html>
    这样以后只要是404 not found就会显示not_found.html的内容了
    
    2、Alias URL路径 文件系统的绝对路径
    # Alias指令使文档可以被存储在DocumentRoot以外的本地文件系统中
    
    # 下面的是将URL/csr2映射到系统的/data/www/csrtest下
    # 例如请求www.csr110.xyz/csr2/1.php,apache则会读取/data/www/csrtest/1.php的内容
    #   Alias /csr2 /data/www/csrtest
    

      

    
    
  • 相关阅读:
    缺少动态连接库.so--cannot open shared object file: No such file or directory
    BST删除节点
    python中列表字典和字符串的相互转化
    浅谈WM算法
    MySql--主从复制
    python中的__getattr__(self, name)浅谈
    Linux下python路径查找不到的解决办法
    Python闭包和装饰器
    Python操作Mysql数据库
    MySQL----联结
  • 原文地址:https://www.cnblogs.com/tcheng/p/9158103.html
Copyright © 2011-2022 走看看