??xml version="1.0" encoding="utf-8" standalone="yes"?>辽宁快乐12开奖结果:BlogJava - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/xiaomage234/生命本就是一次凄美的漂流,记忆中放不下的,永远是孩提时代的那一份浪漫与纯真?/description>zh-cnMon, 15 Oct 2018 09:33:43 GMTMon, 15 Oct 2018 09:33:43 GMT60孤儿进程与僵尸进程[转] - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/xiaomage234/archive/2018/09/03/433354.html小马?/dc:creator>小马?/author>Mon, 03 Sep 2018 11:53:00 GMT//www.ot7t.com.cn/xiaomage234/archive/2018/09/03/433354.html//www.ot7t.com.cn/xiaomage234/comments/433354.html//www.ot7t.com.cn/xiaomage234/archive/2018/09/03/433354.html#Feedback0//www.ot7t.com.cn/xiaomage234/comments/commentRss/433354.html//www.ot7t.com.cn/xiaomage234/services/trackbacks/433354.html阅读全文

]]>
转: Nginx + Tomcat + HTTPS 配置不需要在 Tomcat 上启?SSL 支持 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/xiaomage234/archive/2017/10/12/432853.html小马?/dc:creator>小马?/author>Thu, 12 Oct 2017 03:02:00 GMT//www.ot7t.com.cn/xiaomage234/archive/2017/10/12/432853.html//www.ot7t.com.cn/xiaomage234/comments/432853.html//www.ot7t.com.cn/xiaomage234/archive/2017/10/12/432853.html#Feedback0//www.ot7t.com.cn/xiaomage234/comments/commentRss/432853.html//www.ot7t.com.cn/xiaomage234/services/trackbacks/432853.html

最近做了个Web项目, 架构上使用了 Nginx +tomcat 集群, 且全站HTTPS,用nginx 做负载,nginx和tomcat 使用内网http通信,遇到http css,js静态资源被浏览器拦截问题,网上搜索到的很多文章在描?Nginx + Tomcat 启用 HTTPS 支持的时候,都必须在 Nginx ?Tomcat 两边同时配置 SSL 支持,今天做个总结?/p>

遇到问题

  1. nginx强制使用https访问(http跳转到https)
  2. http的js,css 等静态资源被浏览器拦截(http不被信任?/li>

最后的解决方案

首先解决第一个问?/strong>全站https 
参?/a> 
三种方式,跟大家共享一?/p>

nginx的rewrite方法

server {   listen  192.168.1.111:80;   server_name test.com;   rewrite ^(.*)$  https://$host$1 permanent; }   

nginx?97状态码,我选择了这种方?/strong>

server {       listen       192.168.1.11:443;  #ssl端口       listen       192.168.1.11:80;   #用户习惯用http访问,加?0,后面通过497状态码让它自动跳到443端口       server_name  test.com;       #为一个server{......}开启ssl支持       ssl                  on;       #指定PEM格式的证书文?       ssl_certificate      /etc/nginx/test.pem;        #指定PEM格式的私钥文?      ssl_certificate_key  /etc/nginx/test.key;        #让http请求重定向到https请求        error_page 497  https://$host$uri?$args;   }   

index.html刷新网页

<html>   <meta http-equiv="refresh" content="0;url=https://test.com/">   </html>  

当http访问到index.html时候自动跳转到https


接下来解?strong style="box-sizing: border-box;">第二个问?/strong> 
如果tomcat 和nginx 双方没有配置X-Forwarded-Proto tomcat就不能正确区分实际用户是http 还是https,导致tomcat 里配置的静态资源被认为是http而被浏览器拦截,request.getScheme()总是 http,而不是实际的http或https

分别配置一?Nginx ?Tomcat ,果然好了?nbsp;
配置 Nginx 的转发选项?/strong>

 proxy_set_header       Host $host;       proxy_set_header  X-Real-IP  $remote_addr;       proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;       proxy_set_header X-Forwarded-Proto  $scheme;  
  • 1
  • 2
  • 3
  • 4

配置Tomcat server.xml ?Engine 模块下配置一?Valve?/strong>

<Valve className="org.apache.catalina.valves.RemoteIpValve"   remoteIpHeader="X-Forwarded-For"   protocolHeader="X-Forwarded-Proto"   protocolHeaderHttpsValue="https"/>  
  • 1
  • 2
  • 3
  • 4

?0端口配置 
Nginx增加以下配置 
proxy_set_header Host $host:$server_port; ?0端口 ,用80端口?不需?server_port 
proxy_set_header X-Real-IP $remote_addr; 
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
proxy_set_header X-Forwarded-Proto $scheme; 

Tomcat server.xml配置 
<Engine name="Catalina" defaultHost="localhost"> 
<Valve className="org.apache.catalina.valves.RemoteIpValve" 
remoteIpHeader="X-Forwarded-For" 
protocolHeader="X-Forwarded-Proto" 
protocolHeaderHttpsValue="https" httpsServerPort="7001"/> ?0端口时,必须增加httpsServerPort配置,不然request.getServerPort()方法返回 443. 
</Engine>

关于 RemoteIpValve,可以阅读?doc

//tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/valves/RemoteIpValve.html



]]>
gerrit - first commit - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/xiaomage234/archive/2017/08/11/432734.html小马?/dc:creator>小马?/author>Fri, 11 Aug 2017 03:23:00 GMT//www.ot7t.com.cn/xiaomage234/archive/2017/08/11/432734.html//www.ot7t.com.cn/xiaomage234/comments/432734.html//www.ot7t.com.cn/xiaomage234/archive/2017/08/11/432734.html#Feedback0//www.ot7t.com.cn/xiaomage234/comments/commentRss/432734.html//www.ot7t.com.cn/xiaomage234/services/trackbacks/432734.htmlgerrit还是轻易不要尝试引入,它的权限管理,真是复杂极了。对于小型团队,初期这将是个噩梦,但是对于像OpenStack,安卓这种大型team,又是一把利器?/span>
下面尝试测试了两个用户的简单情况,很多配置都是系统默认,没有进行啥复杂配置,即使这样也是错误百出,光一个commit就要折腾半天,而且还有些机制没搞清楚?div>
首先要做的准备工作就是准备两个gerrit用户,user1和user2,并且分别把user1和user2的ssh pub-key通过gerrit setting添加好?/div>
1. 首先user1创建一个叫HelloWord的project?/div>
   如何创建project请参考前期博客或者官方文??/div>
2. user1在自己的工作环境中把HelloWord clone下来
[user1@jenkins ~]$ git clone ssh://user1@gerrit.example.com:29418/HelloWorld.git
Initialized empty Git repository in /home/user1/HelloWorld/.git/
remote: Counting objects: 2, done
remote: Finding sources: 100% (2/2)
remote: Total 2 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (2/2), done.
加入user1没有添加ssh pubkey的话,这一步会出permission deny

clone后,创建一个README文件并add,commit
[user1@jenkins ~]$ cd HelloWorld
[user1@jenkins HelloWorld]$ ls
[user1@jenkins HelloWorld]$ touch README
[penxiao@jenkins test]$ git add README 
[penxiao@jenkins test]$ git commit -m add README
这里注意一点,在下面要push之前,一定要配置好git config?username和email
可以通过命令行或者直接编?~/.gitconfig文件实现,而且email一定要和gerrit里注册的email一致,否者push也会出错?br />[user1@jenkins HelloWorld]$ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 213 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: Processing changes: refs: 1, done    
To ssh://user1@gerrit.example.com:29418/HelloWorld.git
 * [new branch]      master -> master
[user1@jenkins HelloWorld]$

在gerrit的gitweb链接可以查看push的文件?/div>
3. user2加入
[user2@jenkins ~]$ git clone ssh://user1@gerrit.example.com:29418/HelloWorld.git
Initialized empty Git repository in /home/user2/HelloWorld/.git/
remote: Counting objects: 3, done
remote: Finding sources: 100% (3/3)
remote: Total 3 (delta 0), reused 3 (delta 0)
Receiving objects: 100% (3/3), done.
[user2@jenkins ~]$ cd HelloWorld
[user2@jenkins HelloWorld]$ ls
README
[user2@jenkins HelloWorld]$ 
user2对README文件进行修改,然后要commit,push
!!!也同样注意,user2的git config,username和email的配置,email要和gerrit setting里的一致?/div>
commit完以后可以看?/div>
[user2@jenkins HelloWorld]$ git log
commit 7959fe47bc2d2f53539a1861aa6b0d71afe0a531
Author: user2 <user2@gerrit.com>
Date:   Thu Dec 12 00:24:53 2013 -0500
    edit README
commit 98099fc0de3ba889b18cf36f9a5af267b3ddb501
Author: user1 <user@gerrit.com>
Date:   Thu Dec 12 00:15:08 2013 -0500
    add README
[user2@jenkins HelloWorld]$
现在user2要把这次的改变push到gerrit,可以么?/div>
不行的,可以看到
[user2@jenkins HelloWorld]$ git push origin master
Counting objects: 5, done.
Writing objects: 100% (3/3), 249 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: Branch refs/heads/master:
remote: You are not allowed to perform this operation.
remote: To push into this reference you need 'Push' rights.
remote: User: user2
remote: Please read the documentation and contact an administrator
remote: if you feel the configuration is incorrect
remote: Processing changes: refs: 1, done    
To ssh://user2@gerrit.example.com:29418/HelloWorld.git
 ! [remote rejected] master -> master (prohibited by Gerrit)
error: failed to push some refs to 'ssh://user2@gerrit.example.com:29418/HelloWorld.git'
[user2@jenkins HelloWorld]$ 
这就是gerrit的精髓所在了?span style="word-wrap: normal; word-break: normal; line-height: 21px; background-color: #ffffff;">原因是gerrit不允许直接将本地修改同步到远程仓库。客户机必须先push到远程仓库的refs/for/*分支上,等待审核。这也是为什么我们需要使用gerrit的原因。gerrit本身就是个代码审核工具?/span>

接下来更该push的地址? 
[user2@jenkins HelloWorld]$git config remote.origin.push refs/heads/*:refs/for/*  
此命令实际是更改的是本地仓库test_project/.git/config文件?nbsp;
再次push   
[user2@jenkins HelloWorld]$git push origin  
这次不要加master
[user2@jenkins HelloWorld]$ git push origin
Counting objects: 5, done.
Writing objects: 100% (3/3), 249 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: Processing changes: refs: 1, done    
remote: ERROR: missing Change-Id in commit message footer
remote: Suggestion for commit message:
remote: edit README
remote: 
remote: Change-Id: I7959fe47bc2d2f53539a1861aa6b0d71afe0a531
remote: 
remote: Hint: To automatically insert Change-Id, install the hook:
remote:   gitdir=$(git rev-parse --git-dir); scp -p -P 29418 user2@gerrit.example.com:hooks/commit-msg ${gitdir}/hooks/
remote: 
remote: 
To ssh://user2@gerrit.example.com:29418/HelloWorld.git
 ! [remote rejected] master -> refs/for/master (missing Change-Id in commit message footer)
error: failed to push some refs to 'ssh://user2@gerrit.example.com:29418/HelloWorld.git'
尼玛,还是不行,说缺change-Id,为了能让每次commit能自己insert 这个change-id,需要从gerrit server上下载一个脚?/div>
[user2@jenkins HelloWorld] scp -p 29418 user2@gerrit.example.com:hooks/commit-msg <local path to your git>/.git/hooks/
然后重新commit
[user2@jenkins HelloWorld]$ git commit --amend
再次查看git log
[user2@jenkins HelloWorld]$ git log
commit f6b5919170875b5b4870fca2ab906c516c97006e
Author: user2 <user2@gerrit.com>
Date:   Thu Dec 12 00:24:53 2013 -0500
    edit by user2
    
    Change-Id: Ieac68bebefee7c6d4237fa5c058386bf7c4f66b7
commit 98099fc0de3ba889b18cf36f9a5af267b3ddb501
Author: user1 <user1@gerrit.com>
Date:   Thu Dec 12 00:15:08 2013 -0500
    add README
[user2@jenkins HelloWorld]$ 
这次就有了change id
然后再次push
[user2@jenkins HelloWorld]$ git push origin
Counting objects: 5, done.
Writing objects: 100% (3/3), 289 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: Processing changes: new: 1, refs: 1, done    
remote: 
remote: New Changes:
remote:   //gerrit.example.com:8080/1
remote: 
To ssh://user2@gerrit.example.com:29418/HelloWorld.git
 * [new branch]      master -> refs/for/master
[user2@jenkins HelloWorld]$ 


]]>【OSGI?.初识OSGI-到底什么是OSGI 【转?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2017/08/10/432733.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Thu, 10 Aug 2017 07:57:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2017/08/10/432733.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/432733.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2017/08/10/432733.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/432733.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/432733.html</trackback:ping><description><![CDATA[<div style="padding-top: 20px; padding-bottom: 20px; font-family: Arial, Console, Verdana, "Courier New"; font-size: 12px; background-color: #ffffff;"><p style="margin: 0px; padding: 0px 0px 0px 10px; height: 14px; line-height: 14px; border-left: 3px solid #e41c1e; color: #666666; font-size: 14px;">from:<span style="font-size: 12px;">//blog.csdn.net/acmman/article/details/50848595</span></p><p style="margin: 0px; padding: 0px 0px 0px 10px; height: 14px; line-height: 14px; border-left: 3px solid #e41c1e; color: #666666; font-size: 14px;">版权声明:本文为博主原创文章,未经博主允许不得转载?/p></div><div id="article_content" tracking-ad"="" data-mod="popu_307" data-dsm="post" style="margin: 20px 0px 0px; font-stretch: normal; line-height: 26px; font-family: Arial; background-color: #ffffff;">目前,业内关于OSGI技术的学习资源或者技术文?还是很少的。我在某宝网搜索了一?#8220;OSGI”的书籍,结果倒是有,但是种类少的可怜,而且几乎没有人购买?br />因为工作的原因我需要学习OSGI,所以我不得不想尽办法来主动学习OSGI。我将用文字记录学习OSGI的整个过程,通过整理书籍和视频教程,来让我更加了解这门技术,同时也让需要学习这门技术的同志们有一个清晰的学习路线?br /><br />我们需要解决一下几问题:<br /><span style="font-size: 18px;"><strong class="yibqv">1.如何正确的理解和认识OSGI技术?</strong></span><br /><br />我们从外文资料上或者从翻译过来的资料上看到OSGi解释和定义,都是直译过来的,但是OSGI的真实意义未必是中文直译过来的意思。OSGI的解释就是Open Service Gateway Initiative,直译过来就?#8220;开放的服务入口(网关)的初始化”,听起来非常费解,什么是服务入口初始化?<br /><br />所以我们不去直译这个OSGI,我们换一种说法来描述OSGI技术?br /><br />我们来回到我们以前的某些开发场景中去,假设我们使用SSH(struts+spring+hibernate)框架来开发我们的Web项目,我们做产品设计和开发的时候都是分模块的,我们分模块的目的就是实现模块之间?#8220;解?#8221;,更进一步的目的是方便对一个项目的控制和管理?br />我们对一个项目进行模块化分解之后,我们就可以把不同模块交给不同的开发人员来完成开发,然后项目经理把大家完成的模块集中在一起,然后拼装成一个最终的产品。一般我们开发都是这样的基本情况?br /><br />那么我们开发的时候预计的是系统的功能,根据系统的功能来进行模块的划分,也就是说,这个产品的功能或客户的需求是划分的重要依据?br /><br />但是我们在开发过程中,我们模块之间还要彼此保持联系,比如A模块要从B模块拿到一些数据,而B模块可能要调用C模块中的一些方?除了公共底层的工具类之外)。所以这些模块只是一种逻辑意义上的划分?br /><br />最重要的一点是,我们把最终的项目要去部署到tomcat或者jBoss的服务器中去部署。那么我们启动服务器的时候,能不能关闭项目的某个模块或功能呢?很明显是做不到的,一旦服务器启动,所有模块就要一起启动,都要占用服务器资源,所以关闭不了模块,假设能强制拿掉,就会影响其它的功能?br /><br />以上就是我们传统模块式开发的一些局限性?br /><br />我们做软件开发一直在追求一个境界,就是<span style="color: #ff0000;"><strong class="yibqv">模块之间的真?#8220;解?#8221;?#8220;分离”</strong></span>,这样我们在软件的管理和开发上面就会更加的灵活,甚至包括给客户部署项目的时候都可以做到更加的灵活可控。但是我们以前使用SSH框架等架构模式进行产品开发的时候我们是达不到这种要求的?br /><br />所以我?#8220;架构?#8221;或顶尖的技术高手都在为模块化开发努力的摸索和尝试,然后我们的OSGI的技术规范就应运而生?br /><br />现在我们的OSGI技术就可以满足我们之前所说的境界:在不同的模块中做到彻底的分离,而不是逻辑意义上的分离,是物理上的分离,也就是说在运行部署之后都可以在不停止服务器的时候直接把某些模块拿下来,其他模块的功能也不受影响?br /><br />由此,OSGI技术将来会变得非常的重要,因为它在实现模块化解耦的路上,走得比现在大家经常所用的SSH框架走的更远。这个技术在未来大规模、高访问、高并发的Java模块化开发领域,或者是项目规范化管理中,会大大超过SSH等框架的地位?br /><br />现在主流的一些应用服务器,Oracle的weblogic服务器,IBM的WebSphere,JBoss,还有Sun公司的glassfish服务器,都对OSGI提供了强大的支持,都是在OSGI的技术基础上实现的。有那么多的大型厂商支持OSGI这门技术,我们既可以看到OSGI技术的重要性。所以将来OSGI是将来非常重要的技术?br /><br />但是OSGI仍然脱离不了框架的支持,因为OSGI本身也使用了很多spring等框架的基本控件(因为要实现AOP依赖注入等功?,但是哪个项目又不去依赖第三方jar呢?<br /><br /><br /><br /><span style="font-size: 18px;"><strong class="yibqv">2.OSGI技术对我们项目的开发有什么帮助?</strong></span><br /><br /><strong class="yibqv">(1)项目展示</strong><br />接下来我们同过项目代码来展示一下OSGI的魅?<br />我们先不要去急着理解如何使用OSGI,我们通过一个项目先来看一下OSGI的效果?br />(以下工程代码是网上教学视频中的样例,源码我这里是没有?<br />(提前说一?我们要学习的重点就是我们这个购物网站如何结合OSGI技术,使得项目更加的灵活可控,而购物网站本身并不是重点?<br /><br /><br />首先在Eclipse中先打开我们的单服务器版本的项目:<br /><img src="//img.blog.csdn.net/20160310173347989?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />启动成功:<br /><p style="margin: 0px; padding: 0px;"><img src="//img.blog.csdn.net/20160310173401567?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /></p><p style="margin: 0px; padding: 0px;"><img src="//img.blog.csdn.net/20160310173411895?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /></p><br /><br />这是一个Web项目,我们打开浏览器看一下效?<br /><img src="//img.blog.csdn.net/20160310173429161?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />可以看出是一个网上购物的项目?br /><br />我们来看一下我们基于OSGI技术的项目和我们一般的项目有什么区别?br />首先介绍一下这个项目的模块:<br /><br /><strong class="yibqv">1.大类展示</strong><br /><img src="//img.blog.csdn.net/20160310173537333?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /><br /><strong class="yibqv">2.小类展示(大类的子产品)</strong><br /><img src="//img.blog.csdn.net/20160310173552836?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />点进去之后就是产品的具体信息<br /><img src="//img.blog.csdn.net/20160310173601523?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /><br /><br /><strong class="yibqv">3.购物?/strong><br />没买东西是空?<br /><img src="//img.blog.csdn.net/20160310173611224?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />买完之后:<br /><img src="//img.blog.csdn.net/20160310173619274?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /><br /><br /><strong class="yibqv">4.商品管理(上架、下?</strong><br /><img src="//img.blog.csdn.net/20160310173629587?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /><br /><br />可以看到,这个项目和我们平常开发的项目没有什么不?我知道界面很简? =),重点是它的启动和加载过程?br /><br /><br /><strong class="yibqv">(2)关于服务?/strong><br />我们是通过动态加载,也就?#8220;热部?#8221;来启动我们的项目的。就是说,我们这个项目把它放在Web容器中之后,我们可以将某些功能给它拿下来,而且拿下来的时候不会对其他模块造成影响?br /><br />我们以前运行tomcat的时候,启动一下服务器,将Web项目一次性装载完毕,控制台会出现类似这种信息:<br /><img src="//img.blog.csdn.net/20160310173643287?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /><br />但是我们启动这个项目的时候并不是这样:<br /><img src="//img.blog.csdn.net/20160310173703556?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /><br />那么我们没有用tomcat和jBoss,那是如何部署和启动Web项目的呢?不可能没有Web服务器中间件的啊?这里告诉大家,OSGI技术里面也是内嵌了一个Web服务器的,就是jetty?br /><br /><br /><p style="margin: 0px; padding: 0px;">我们打开这个项目的Run Configuration配置窗口,看一下运行这个项目所需要的插件?</p><p style="margin: 0px; padding: 0px;"><img src="//img.blog.csdn.net/20160310173803120?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /></p>可以看到,除了一些Web项目需要的jar包,还是有jetty的存在的。所以用到的服务器是jetty,不再是tomcat?br /><br /><br />大家可能还是比较熟悉tomcat,对于jetty不是太熟悉,那么我们简单介绍一下jetty:<br />jetty也是一个比较优秀的Web容器,在某些性能方面要比tomcat强大的多(如高并发,长连接)。而且它的整个结构比tomcat轻巧很多(tomcat更臃?,具体区别大家可以去网上自己看一下?br /><br /><br /><strong class="yibqv">(3)运行模式和插?/strong><br />我们接下来正式看一下此项目在OSGI下的运行模式:<br />我们在启动的时候,加载了四个模块,分别?<br /><img src="//img.blog.csdn.net/20160310173817834?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />按照模块化的思想他们就是四个对应的功能模块?br />他们对应的四个功能模块的工程代码我们可以在Eclipse中看?<br /><img src="//img.blog.csdn.net/20160310173838100?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /><br /><br />我们看一下我们的启动配置(依然打开是Run Configuration配置窗口):<br /><p style="margin: 0px; padding: 0px;"><img src="//img.blog.csdn.net/20160310173851028?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /></p><p style="margin: 0px; padding: 0px;"><img src="//img.blog.csdn.net/20160310173908287?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /></p>配置分为“WorkSpace”?#8220;Target Platform”,分别是我们工作空间(我们自己写的项目模块和工具类)的插件和运行平台(一些依赖jar的配?的插件,两者结合启动我们的项目就会正常运行?br /><br />我们启动项目之后,在控制台输入指?#8220;ss”,就会出现我们所有加载的插件的运行情?<br /><img src="//img.blog.csdn.net/20160310173922491?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /><br />一启动的时候,它会首先加载Eclipse的OSGI插件(Eclipse本身也是一种OSGI的容??br /><br />我们打开我们的Eclipse安装目录,然后找到plugins文件夹,可以看到Eclipse所有的插件:<br /><img src="//img.blog.csdn.net/20160310173950670?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />可以看到有文件夹形式的,有jar形式的插件?br /><br />我们怎么去理解插件呢?br />插件其实就是被开发工具或OSGI容器管理和配置起来的jar包? <br /><br />我们随便打开一个文件夹类型的插件,可以看到:<br /><img src="//img.blog.csdn.net/20160310174004498?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />可以看到里面除了lib之外还有其它东西,然后有一?#8220;OSGI-INF”文件夹。且不管它是什么,这都足以说明我们的Eclipse就是一个OSGI容器?br /><br /><strong class="yibqv">(4)热部署和热启?/strong><br />我们接下来回到重点,在我们启动的过程中,我们不停止运行,然后去停掉其中的一个模?<br /><br />假如我们要停?#8220;管理”模块:<br /><img src="//img.blog.csdn.net/20160310174017304?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />也就是停掉id?2的插?br /><br />结果:<br /><p style="margin: 0px; padding: 0px;"><img src="//img.blog.csdn.net/20160310174029225?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /></p><br />然后刷新我们的网站主页面:<br /><img src="//img.blog.csdn.net/20160310174125101?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />发现我们?#8220;管理”模块消失?<br /><br />这个模块的消失并不是javascript的技术,而是一种服务器技术,我们是通过服务器内部把它动态卸载掉的?br /><br />我们的管理模块去掉之后,网站的其它功能不受任何影响。至此我们的服务器没有进行任何的暂停或关闭?br /><br />我们再停?#8220;购物?#8221;模块:<br /><img src="//img.blog.csdn.net/20160310174849760?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />效果:<br /><img src="//img.blog.csdn.net/20160310174743931?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />其它模块依旧不受影响?br /><br />我们关闭了两个模块,现在输入ss看一下所有插件和模块的运行情?<br /><img src="//img.blog.csdn.net/20160310174908917?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />可以看到我们的两个模块处于RESOLVED状态,也就是待解决状态?br /><br />当然我们也可以将我们的模块在服务器开启状态下部署上去:<br />如我们启动购物车模块:<br /><img src="//img.blog.csdn.net/20160310174936589?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /><br />发现购物车回来了:<br /><img src="//img.blog.csdn.net/20160310174946605?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /><br />这就是所谓的热部署,即是这个项目把它放在Web容器中之后,我们可以将某些功能给它拿下来,而且拿下来的时候不会对其他模块造成影响?br /><br /><br />通过购物网站这个项目让大家真实的感受一下OSGI这个技术在项目开发和管理的一些强大的功能?br /><br /><p style="margin: 0px; padding: 0px;">想进一步了解更多关于OSGI的知识可以查看以后的总结文章?/p><p style="margin: 0px; padding: 0px;"><strong class="yibqv"><span style="color: #ff0000;">转载请注明出处:<a target="_blank" style="color: #ca0000; text-decoration-line: none;">//blog.csdn.net/acmman/article/details/50848595</a></span></strong></p></div><div tracking-ad="" bdshare-button-style0-16"="" data-mod="popu_172" data-bd-bind="1502330276160" style="zoom: 1; font-family: Arial, Console, Verdana, "Courier New"; font-size: 12px; background-color: #ffffff; float: right;"><a data-cmd="more" target="_blank" style="color: #333333; text-decoration-line: none; float: left; padding-left: 17px; line-height: 16px; height: 16px; background-repeat: no-repeat; cursor: pointer; margin: 6px 6px 6px 0px; background-image: url("//bdimg.share.baidu.com/static/api/img/share/icons_0_16.png?v=d754dcc0.png") !important; background-position: 0px 0px !important;"></a><a data-cmd="qzone" title="分享到QQ空间" target="_blank" style="color: #ca0000; text-decoration-line: none; float: left; padding-left: 17px; line-height: 16px; height: 16px; background-image: url("../img/share/icons_0_16.png?v=91362611.png"); background-repeat: no-repeat; cursor: pointer; margin: 6px 6px 6px 0px; background-position: 0px -52px !important;"></a><a data-cmd="tsina" title="分享到新浪微? target="_blank" style="color: #ca0000; text-decoration-line: none; float: left; padding-left: 17px; line-height: 16px; height: 16px; background-image: url("../img/share/icons_0_16.png?v=91362611.png"); background-repeat: no-repeat; cursor: pointer; margin: 6px 6px 6px 0px; background-position: 0px -104px !important;"></a><a data-cmd="tqq" title="分享到腾讯微? target="_blank" style="color: #ca0000; text-decoration-line: none; float: left; padding-left: 17px; line-height: 16px; height: 16px; background-image: url("../img/share/icons_0_16.png?v=91362611.png"); background-repeat: no-repeat; cursor: pointer; margin: 6px 6px 6px 0px; background-position: 0px -260px !important;"></a><a data-cmd="renren" title="分享到人人网" target="_blank" style="color: #ca0000; text-decoration-line: none; float: left; padding-left: 17px; line-height: 16px; height: 16px; background-image: url("../img/share/icons_0_16.png?v=91362611.png"); background-repeat: no-repeat; cursor: pointer; margin: 6px 6px 6px 0px; background-position: 0px -208px !important;"></a><a data-cmd="weixin" title="分享到微? target="_blank" style="color: #ca0000; text-decoration-line: none; float: left; padding-left: 17px; line-height: 16px; height: 16px; background-image: url("../img/share/icons_0_16.png?v=91362611.png"); background-repeat: no-repeat; cursor: pointer; margin: 6px 6px 6px 0px; background-position: 0px -1612px !important;"></a></div><div id="digg" articleid="50848595" style="clear: both; width: 182px; margin: 0px auto; padding-top: 30px; padding-bottom: 15px; text-align: center; font-family: Arial, Console, Verdana, "Courier New"; font-size: 12px; background-color: #ffffff;"><dl id="btnDigg" digg_disable"="" style="display: inline-block; float: left; width: 72px; height: 72px; overflow: hidden; margin: 0px 2px; background: #999999; color: #ffffff; cursor: pointer;"><dt style="margin: 0px; padding: 12px 0px 3px; font-stretch: normal; font-size: 27px; line-height: 30px; font-family: "Microsoft YaHei";">?/dt><dd style="margin: 0px; font-stretch: normal; line-height: 22px; font-family: Arial;">20</dd></dl><dl id="btnBury" digg_disable"="" style="display: inline-block; float: left; width: 72px; height: 72px; overflow: hidden; margin: 0px 2px; background: #999999; color: #ffffff; cursor: pointer;"><dt style="margin: 0px; padding: 12px 0px 3px; font-stretch: normal; font-size: 27px; line-height: 30px; font-family: "Microsoft YaHei";">?/dt></dl></div><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/432733.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2017-08-10 15:57 <a href="//www.ot7t.com.cn/xiaomage234/archive/2017/08/10/432733.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《Spring Boot极简教程》第5?Spring Boot自动配置原理【转?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432717.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Wed, 02 Aug 2017 08:35:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432717.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/432717.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432717.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/432717.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/432717.html</trackback:ping><description><![CDATA[from://www.jianshu.com/p/ccadc2bdb6d7<br /><div class="yibqv"><div class="yibqv"><div data-note-content=""><h1>辽宁快乐12开奖结果:??Spring Boot自动配置原理</h1> <h2 class="yibqv">5.1 SpringBoot的核心组件模?/h2> <p>首先,我们来简单统计一下SpringBoot核心工程的源码java文件数量?/p> <p>我们cd到spring-boot-autoconfigure工程根目录下。执?/p> <pre gams"=""><code>$ tree | grep -c .java$</code></pre> <table> <thead> <tr> <th>模块</th> <th>java文件?/th> </tr> </thead> <tbody> <tr> <td>spring-boot</td> <td>551</td> </tr> <tr> <td>spring-boot-actuator</td> <td>423</td> </tr> <tr> <td>spring-boot-autoconfigure</td> <td>783</td> </tr> <tr> <td>spring-boot-devtools</td> <td>169</td> </tr> <tr> <td>spring-boot-cli</td> <td>180</td> </tr> <tr> <td>spring-boot-tools</td> <td>355</td> </tr> </tbody> </table> <p>我们可以看到?83个java文件。spring-boot核心工程?51个java文件。从上面的java文件数量大致可以看出,SpringBoot技术框架的核心组成部分?/p> <pre mel"=""><code>spring-boot-autoconfigure spring-boot spring-boot-tools</code></pre> <p>我们把SpringBoot源码导入IntelliJ IDEA,查看artifact的全部依赖关系?/p> <p>IDEA有个Maven Projects窗口,一般在右侧能够找到,如果没有可以从菜单栏打开:View>Tool Windows>Maven Projects;</p> <p>选择要分析的maven module(idea的module相当于eclipse的project),右击show dependencies,会出来该module的全部依赖关系图,非常清晰细致?/p> <p>例如,spring-boot-starter-freemarker的依赖图分析如下?/p> <div class="yibqv"> <img src="//upload-images.jianshu.io/upload_images/1233356-928607fa053a7199.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" data-original-src="//upload-images.jianshu.io/upload_images/1233356-928607fa053a7199.png?imageMogr2/auto-orient/strip%7CimageView2/2" style="cursor: zoom-in;" alt="" /><br /><div class="yibqv"></div> </div> <p>在spring-boot-build 的pom中,我们可以看到?/p> <pre crystal"=""><code> <modules> <module>spring-boot-dependencies</module> <module>spring-boot-parent</module> <module>spring-boot-tools</module> <module>spring-boot</module> <module>spring-boot-test</module> <module>spring-boot-autoconfigure</module> <module>spring-boot-test-autoconfigure</module> <module>spring-boot-actuator</module> <module>spring-boot-devtools</module> <module>spring-boot-docs</module> <module>spring-boot-starters</module> <module>spring-boot-actuator-docs</module> <module>spring-boot-cli</module> </modules></code></pre> <p>其中,在spring-boot-dependencies中,SpringBoot项目维护了一份庞大依赖。这些依赖的版本都是经过实践,测试通过,不会发生依赖冲突的。就这样一个事情,就大大减少了Spring开发过程中,出现jar包冲突的概率。spring-boot-parent依赖spring-boot-dependencies?/p> <p>下面我们简要介绍一下SpringBoot子modules?/p> <h4>spring-boot</h4> <p>SpringBoot核心工程?/p> <h4>spring-boot-starters</h4> <p>是SpringBoot的启动服务工程?/p> <h4>spring-boot-autoconfigure</h4> <p>是SpringBoot实现自动配置的核心工程?/p> <h4>spring-boot-actuator</h4> <p>提供SpringBoot应用的外围支撑性功能?比如?/p> <ul class="yibqv"> <li class="yibqv">Endpoints,SpringBoot应用状态监控管?/li> <li class="yibqv">HealthIndicator,SpringBoot应用健康指示?/li> <li class="yibqv">提供metrics支持</li> <li class="yibqv">提供远程shell支持</li> </ul> <h4>spring-boot-tools</h4> <p>提供了SpringBoot开发者的常用工具集。诸如,spring-boot-gradle-plugin,spring-boot-maven-plugin就是这个工程里面的?/p> <h4>spring-boot-cli</h4> <p>是Spring Boot命令行交互工具,可用于使用Spring进行快速原型搭建。你可以用它直接运行Groovy脚本。如果你不喜欢Maven或Gradle,Spring提供了CLI(Command Line Interface)来开发运行Spring应用程序。你可以使用它来运行Groovy脚本,甚至编写自定义命令?/p> <h2 class="yibqv">5.2 SpringBoot Starters</h2> <p>Spring boot中的starter概念是非常重要的机制,能够抛弃以前繁杂的配置,统一集成进starter,应用者只需要引入starter jar包,spring boot就能自动扫描到要加载的信息?/p> <p>starter让我们摆脱了各种依赖库的处理,需要配置各种信息的困扰。Spring Boot会自动通过classpath路径下的类发现需要的Bean,并织入bean?/p> <p>例如,如果你想使用Spring和用JPA访问数据库,你只要依?spring-boot-starter-data-jpa 即可?/p> <p>目前,github上spring-boot项目的最新的starter列表<a target="_blank">spring-boot/spring-boot-starters</a>如下?/p> <pre mel"=""><code>spring-boot-starter spring-boot-starter-activemq spring-boot-starter-actuator spring-boot-starter-amqp spring-boot-starter-aop spring-boot-starter-artemis spring-boot-starter-batch spring-boot-starter-cache spring-boot-starter-cloud-connectors spring-boot-starter-data-cassandra spring-boot-starter-data-couchbase spring-boot-starter-data-elasticsearch spring-boot-starter-data-jpa spring-boot-starter-data-ldap spring-boot-starter-data-mongodb spring-boot-starter-data-mongodb-reactive spring-boot-starter-data-neo4j spring-boot-starter-data-redis spring-boot-starter-data-rest spring-boot-starter-data-solr spring-boot-starter-freemarker spring-boot-starter-groovy-templates spring-boot-starter-hateoas spring-boot-starter-integration spring-boot-starter-jdbc spring-boot-starter-jersey spring-boot-starter-jetty spring-boot-starter-jooq spring-boot-starter-jta-atomikos spring-boot-starter-jta-bitronix spring-boot-starter-jta-narayana spring-boot-starter-log4j2 spring-boot-starter-logging spring-boot-starter-mail spring-boot-starter-mobile spring-boot-starter-mustache spring-boot-starter-parent spring-boot-starter-reactor-netty spring-boot-starter-security spring-boot-starter-social-facebook spring-boot-starter-social-linkedin spring-boot-starter-social-twitter spring-boot-starter-test spring-boot-starter-thymeleaf spring-boot-starter-tomcat spring-boot-starter-undertow spring-boot-starter-validation spring-boot-starter-web spring-boot-starter-web-services spring-boot-starter-webflux spring-boot-starter-websocket</code></pre> <p>(源代码目录执行shell:l|awk '{print $9}'?l|awk '{print $9}'|grep -c 'starter')</p> <p>?2个。每个starter工程里面的pom描述有相应的介绍。具体的说明,参考官网文?[1]。关于这些starters的使用例子,可以参?a target="_blank">spring-boot/spring-boot-samples</a></p> <p>比如说,spring-boot-starter是:</p> <blockquote><p>Core starter, including auto-configuration support, logging and YAML</p></blockquote> <p>这是Spring Boot的核心启动器,包含了自动配置、日志和YAML。它的项目依赖图如下?/p> <div class="yibqv"> <img src="//upload-images.jianshu.io/upload_images/1233356-84c9847c7ccdbda7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" data-original-src="//upload-images.jianshu.io/upload_images/1233356-84c9847c7ccdbda7.png?imageMogr2/auto-orient/strip%7CimageView2/2" style="cursor: zoom-in;" alt="" /><br /><div class="yibqv"></div> </div> <div class="yibqv"> <img src="//upload-images.jianshu.io/upload_images/1233356-20374baaeb3d6086.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" data-original-src="//upload-images.jianshu.io/upload_images/1233356-20374baaeb3d6086.png?imageMogr2/auto-orient/strip%7CimageView2/2" style="cursor: zoom-in;" alt="" /><br /><div class="yibqv"></div> </div> <p>可以看出,这些starter只是配置,真正做自动化配置的代码的是在spring-boot-autoconfigure里面。同时spring-boot-autoconfigure依赖spring-boot工程,这个spring-boot工程是SpringBoot的核心?/p> <p>SpringBoot会基于你的classpath中的jar包,试图猜测和配置您可能需要的bean?/p> <p>例如,如果你的classpath中有tomcat-embedded.jar,你可能会想要一个TomcatEmbeddedServletContainerFactory Bean (SpringBoot通过获取EmbeddedServletContainerFactory来启动对应的web服务器。常用的两个实现类是TomcatEmbeddedServletContainerFactory和JettyEmbeddedServletContainerFactory)?/p> <p>其他的所有基于Spring Boot的starter都依赖这个spring-boot-starter。比如说spring-boot-starter-actuator的依赖树,如下图?/p> <div class="yibqv"> <img src="//upload-images.jianshu.io/upload_images/1233356-5754dcdfcf085c48.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" data-original-src="//upload-images.jianshu.io/upload_images/1233356-5754dcdfcf085c48.png?imageMogr2/auto-orient/strip%7CimageView2/2" style="cursor: zoom-in;" alt="" /><br /><div class="yibqv"></div> </div> <h2 class="yibqv">5.3 @EnableAutoConfiguration自动配置原理</h2> <p>通过@EnableAutoConfiguration启用Spring应用程序上下文的自动配置,这个注解会导入一个EnableAutoConfigurationImportSelector的类,而这个类会去读取一个spring.factories下key为EnableAutoConfiguration对应的全限定名的值?/p> <p>这个spring.factories里面配置的那些类,主要作用是告诉Spring Boot这个stareter所需要加载的那些xxxAutoConfiguration类,也就是你真正的要自动注册的那些bean或功能。然后,我们实现一个spring.factories指定的类,标上@Configuration注解,一个starter就定义完了?/p> <p>如果想从自己的starter种读取应用的starter工程的配置,只需要在入口类上加上如下注解即可?/p> <pre css"=""><code>@EnableConfigurationProperties(MyProperties.class)</code></pre> <h3>读取spring.factories文件的实?/h3> <p>是通过org.springframework.core.io.support.SpringFactoriesLoader实现?/p> <p>SpringFactoriesLoader的实现类似于SPI(Service Provider Interface,在java.util.ServiceLoader的文?里有比较详细的介绍。java SPI提供一种服务发现机制,为某个接口寻找服务实现的机制。有点类似IOC的思想,就是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要[3])?/p> <p>SpringFactoriesLoader会加载classpath下所有JAR文件里面的META-INF/spring.factories文件?/p> <p>其中加载spring.factories文件的代码在loadFactoryNames方法?</p> <pre haxe"=""><code>public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"; .... public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) { String factoryClassName = factoryClass.getName(); try { Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); List<String> result = new ArrayList<>(); while (urls.hasMoreElements()) { URL url = urls.nextElement(); Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url)); String factoryClassNames = properties.getProperty(factoryClassName); result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames))); } return result; } catch (IOException ex) { throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex); } }</code></pre> <p>通过org.springframework.boot.autoconfigure.AutoConfigurationImportSelector里面的getCandidateConfigurations方法,获取到候选类的名字List<String>。该方法代码如下?/p> <pre lasso"=""><code> protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames( getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you " + "are using a custom packaging, make sure that file is correct."); return configurations; }</code></pre> <p>其中,getSpringFactoriesLoaderFactoryClass()方法直接返回的是EnableAutoConfiguration.class, 代码如下?/p> <pre fortran"=""><code> protected Class<?> getSpringFactoriesLoaderFactoryClass() { return EnableAutoConfiguration.class; }</code></pre> <p>所以,getCandidateConfigurations方法里面的这段代码:</p> <pre dart"=""><code>List<String> configurations = SpringFactoriesLoader.loadFactoryNames( getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());</code></pre> <p>会过滤出key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的全限定名对应的值。全限定名都使用如下命名方法?/p> <pre stylus"=""><code>包名.外部类名 包名.外部类名$内部类名 e.g: org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration</code></pre> <p>SpringBoot中的META-INF/spring.factories(完整路径:spring-boot/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories)中关于EnableAutoConfiguration的这段配置如下:</p> <pre stata"=""><code># Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\ org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\ org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\ org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\ org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\ org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\ org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\ org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\ org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.mongo.ReactiveMongoDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.mongo.ReactiveMongoRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\ org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\ org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\ org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\ org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\ org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\ org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\ org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\ org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\ org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\ org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\ org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\ org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\ org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\ org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\ org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\ org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\ org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\ org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\ org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\ org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\ org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\ org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\ org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\ org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\ org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\ org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\ org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\ org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\ org.springframework.boot.autoconfigure.mongo.ReactiveMongoAutoConfiguration,\ org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\ org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\ org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration,\ org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\ org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\ org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\ org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\ org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\ org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\ org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\ org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\ org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\ org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\ org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\ org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\ org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\ org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\ org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\ org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.WebFluxAnnotationAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\ org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\ org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration</code></pre> <p>当然了,这些AutoConfiguration不是所有都会加载的,会根据AutoConfiguration上的@ConditionalOnClass等条件,再进一步判断是否加载。我们下文通过FreeMarkerAutoConfiguration实例来分析整个自动配置的过程?/p> <h2 class="yibqv">5.4 FreeMarkerAutoConfiguration自动配置的实例分?/h2> <p>我们首先看spring-boot-starter-freemarker工程,目录结构如下:</p> <pre stylus"=""><code>. ├── pom.xml ├── spring-boot-starter-freemarker.iml └── src └── main └── resources └── META-INF └── spring.provides 4 directories, 3 files</code></pre> <p>我们可以看出,这个工程没有任何Java代码,只有两个文件:pom.xml跟spring.provides。starter本身在你的应用程序中实际上是空的?</p> <p>其中?br />spring.provides文件</p> <pre avrasm"=""><code>provides: freemarker,spring-context-support</code></pre> <p>主要是给这个starter起个好区分的名字?/p> <p>Spring Boot 通过starter对项目的依赖进行统一管理. starter利用了maven的传递依赖解析机?把常用库聚合在一? 组成了针对特定功能而定制的依赖starter?/p> <p>我们可以使用IDEA提供的maven依赖图分析的功能(如下图),得到spring-boot-starter-freemarker依赖的module?/p> <div class="yibqv"> <img src="//upload-images.jianshu.io/upload_images/1233356-bb4a9d7e8061ee83.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" data-original-src="//upload-images.jianshu.io/upload_images/1233356-bb4a9d7e8061ee83.png?imageMogr2/auto-orient/strip%7CimageView2/2" style="cursor: zoom-in;" alt="" /><br /><div class="yibqv">IDEA提供的maven依赖图分?/div> </div> <div class="yibqv"> <img src="//upload-images.jianshu.io/upload_images/1233356-28ff27d41a7ddeef.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" data-original-src="//upload-images.jianshu.io/upload_images/1233356-28ff27d41a7ddeef.png?imageMogr2/auto-orient/strip%7CimageView2/2" style="cursor: zoom-in;" alt="" /><br /><div class="yibqv">spring-boot-starter-freemarker依赖的module</div> </div> <p>从上面的依赖图,我们可以清晰看出其间依赖关系?/p> <p>当Spring Boot Application中自动配置EnableAutoConfiguration的相关类执行完毕之后,Spring Boot会进一步解析对应类的配置信息。如果我们配置了spring-boot-starter-freemarker ,maven就会通过这个starter所依赖的spring-boot-autoconfigure,自动传递到spring-boot-autoconfigure工程中?/p> <p>我们来简单分析一下spring-boot-autoconfigure工程的架构?/p> <p>其中,FreeMarker的自动配置类是org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration?/p> <p>下面我们来简要分析一下FreeMarkerAutoConfiguration这个类?/p> <p>在FreeMarkerAutoConfiguration类上面有四行注解?/p> <pre less"=""><code>@Configuration @ConditionalOnClass({ freemarker.template.Configuration.class, FreeMarkerConfigurationFactory.class }) @AutoConfigureAfter(WebMvcAutoConfiguration.class) @EnableConfigurationProperties(FreeMarkerProperties.class) public class FreeMarkerAutoConfiguration { ... }</code></pre> <p>其中?br />?)@Configuration,是org.springframework.context.annotation包里面的注解。这么说吧,用@Configuration注解该类,等?与XML中配置beans;用@Bean标注方法等价于XML中配置bean?/p> <p>?)@ConditionalOnClass,org.springframework.boot.autoconfigure.condition包里面的注解。意思是当类路径下有指定的类的条件下,才会去注册被标注的类为一个bean。在上面的代码中的意思就是,当类路径中有freemarker.template.Configuration.class,FreeMarkerConfigurationFactory.class两个类的时候,才会实例化FreeMarkerAutoConfiguration这个Bean?/p> <p>?)@AutoConfigureAfter,org.springframework.boot.autoconfigure包里面的注解。这个通过注解的名字意思就可以知道,当WebMvcAutoConfiguration.class这个类实例化完毕,才能实例化FreeMarkerAutoConfiguration(有个先后顺序)。SpringBoot使用@ AutoConfigureBefore、@AutoConfigureAfter注解来定义这些配置类的载入顺序?/p> <p>?)@EnableConfigurationProperties,表示启动对FreeMarkerProperties.class的内嵌配置支持,自动将FreeMarkerProperties注册为一个bean。这个FreeMarkerProperties类里面就是关于FreeMarker属性的配置?/p> <pre processing"=""><code>@ConfigurationProperties(prefix = "spring.freemarker") public class FreeMarkerProperties extends AbstractTemplateViewResolverProperties { public static final String DEFAULT_TEMPLATE_LOADER_PATH = "classpath:/templates/"; public static final String DEFAULT_PREFIX = ""; public static final String DEFAULT_SUFFIX = ".ftl"; /** * Well-known FreeMarker keys which will be passed to FreeMarker's Configuration. */ private Map<String, String> settings = new HashMap<>(); /** * Comma-separated list of template paths. */ private String[] templateLoaderPath = new String[] { DEFAULT_TEMPLATE_LOADER_PATH }; /** * Prefer file system access for template loading. File system access enables hot * detection of template changes. */ private boolean preferFileSystemAccess = true; public FreeMarkerProperties() { super(DEFAULT_PREFIX, DEFAULT_SUFFIX); } public Map<String, String> getSettings() { return this.settings; } public void setSettings(Map<String, String> settings) { this.settings = settings; } public String[] getTemplateLoaderPath() { return this.templateLoaderPath; } public boolean isPreferFileSystemAccess() { return this.preferFileSystemAccess; } public void setPreferFileSystemAccess(boolean preferFileSystemAccess) { this.preferFileSystemAccess = preferFileSystemAccess; } public void setTemplateLoaderPath(String... templateLoaderPaths) { this.templateLoaderPath = templateLoaderPaths; } }</code></pre> <p>综上,当?)(2)两个条件满足时,才会继续(3)(4)的动作,同时注册FreeMarkerAutoConfiguration这个Bean。该类的结构如下图:</p> <div class="yibqv"> <img src="//upload-images.jianshu.io/upload_images/1233356-ac415fb54e391999.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" data-original-src="//upload-images.jianshu.io/upload_images/1233356-ac415fb54e391999.png?imageMogr2/auto-orient/strip%7CimageView2/2" style="cursor: zoom-in;" alt="" /><br /><div class="yibqv"></div> </div> <p>我们来看其内部类FreeMarkerWebConfiguration的代码:</p> <pre scala"=""><code> @Configuration @ConditionalOnClass(Servlet.class) @ConditionalOnWebApplication(type = Type.SERVLET) public static class FreeMarkerWebConfiguration extends FreeMarkerConfiguration { @Bean @ConditionalOnMissingBean(FreeMarkerConfig.class) public FreeMarkerConfigurer freeMarkerConfigurer() { FreeMarkerConfigurer configurer = new FreeMarkerConfigurer(); applyProperties(configurer); return configurer; } @Bean public freemarker.template.Configuration freeMarkerConfiguration( FreeMarkerConfig configurer) { return configurer.getConfiguration(); } @Bean @ConditionalOnMissingBean(name = "freeMarkerViewResolver") @ConditionalOnProperty(name = "spring.freemarker.enabled", matchIfMissing = true) public FreeMarkerViewResolver freeMarkerViewResolver() { FreeMarkerViewResolver resolver = new FreeMarkerViewResolver(); this.properties.applyToViewResolver(resolver); return resolver; } @Bean @ConditionalOnMissingBean @ConditionalOnEnabledResourceChain public ResourceUrlEncodingFilter resourceUrlEncodingFilter() { return new ResourceUrlEncodingFilter(); } }</code></pre> <p>其中?br />?)@ConditionalOnWebApplication(type = Type.SERVLET)?是当该应用是基于Servlet的Web应用时?/p> <p>?)@ConditionalOnMissingBean(name = "freeMarkerViewResolver"),是当Spring容器中不存在freeMarkerViewResolver的Bean时?/p> <p>?)@ConditionalOnProperty(name = "spring.freemarker.enabled", matchIfMissing = true),指定的spring.freemarker.enabled属性是否有。如果没有(IfMissing),设为true?/p> <p>当(1)(2)(3)三个条件都满足,则注册freeMarkerViewResolver这个Bean?/p> <p>我们也可以自定义我们自己的my-starter,以及实现对应的@MyEnableAutoConfiguration。SpringBoot有很多第三方starter,其自动配置的原理基本都是这样,比如mybatis-spring-boot-starter的MybatisAutoConfiguration,阅读源?a target="_blank">https://github.com/mybatis/spring-boot-starter[4]</a>?/p> <p>上面文字描述了这么多,再用一张形象生动的图来说明[5]?/p> <div class="yibqv"> <img src="//upload-images.jianshu.io/upload_images/1233356-a464868b4a17bfc1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" data-original-src="//upload-images.jianshu.io/upload_images/1233356-a464868b4a17bfc1.png?imageMogr2/auto-orient/strip%7CimageView2/2" style="cursor: zoom-in;" alt="" /><br /><div class="yibqv">SpringBoot Autoconfigure 工作原理?/div> </div> <h2 class="yibqv">5.5 spring.factories与定义应用程序的初始化行?/h2> <p>上面说了这么多,讲的都是读取properties文件中key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的全限定名对应的值。SpringBoot内部还有许多其他的key用于过滤得到需要加载的类?/p> <pre mipsasm"=""><code># Initializers org.springframework.context.ApplicationContextInitializer=\ org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\ org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer # Application Listeners org.springframework.context.ApplicationListener=\ org.springframework.boot.autoconfigure.BackgroundPreinitializer # Auto Configuration Import Listeners org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\ org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener # Auto Configuration Import Filters org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\ org.springframework.boot.autoconfigure.condition.OnClassCondition # Failure analyzers org.springframework.boot.diagnostics.FailureAnalyzer=\ org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\ org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\ org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer # Template availability providers org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\ org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\ org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\ org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\ org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\ org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider</code></pre> <p>这些key仍然是定义在spring-boot/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories文件中?/p> <p>还有对应的用于测试的自动配置,在<br />spring-boot/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories文件中定义?/p> <p>另外,我们使用spring.factories里还可以定制应用程序的初始化行为。这样我们就可以在应用程序载入前操纵Spring的应用程序上下文ApplicationContext?</p> <p>例如,可以使用ConfigurableApplicationContext类的addApplicationListener()方法,在应用上下文ApplicationContext中创建监听器?</p> <p>自动配置运行日志报告功能就是这么实现的。我们来看在spring.factories中,Initializers一段的配置?/p> <pre livescript"=""><code># Initializers org.springframework.context.ApplicationContextInitializer=\ org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\ org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer</code></pre> <p>其中,AutoConfigurationReportLoggingInitializer监听到系统事件时,比如上下文刷新ContextRefreshedEvent或应用程序启动故障ApplicationFailedEvent之类的事件,Spring Boot可以做一些事情。这里说的代码在AutoConfigurationReportLoggingInitializer.AutoConfigurationReportListener里面。关于支持的事件类型supportsEventType的如下:</p> <pre java"=""><code> private class AutoConfigurationReportListener implements GenericApplicationListener { ... @Override public boolean supportsEventType(ResolvableType resolvableType) { Class<?> type = resolvableType.getRawClass(); if (type == null) { return false; } return ContextRefreshedEvent.class.isAssignableFrom(type) || ApplicationFailedEvent.class.isAssignableFrom(type); } @Override public boolean supportsSourceType(Class<?> sourceType) { return true; } @Override public void onApplicationEvent(ApplicationEvent event) { AutoConfigurationReportLoggingInitializer.this.onApplicationEvent(event); } }</code></pre> <p>要以调试模式启动应用程序,可以使?Ddebug标识,或者在application.properties文件这添加属性debug= true。这样,当我们以调试模式启动应用程序时,SpringBoot就可以帮助我们创建自动配置的运行报告。对于每个自动配置,通过报告我们可以看到它启动或失败的原因?这个报告内容格式大致如下?/p> <pre asciidoc"=""><code>========================= AUTO-CONFIGURATION REPORT ========================= Positive matches: ----------------- DataSourceAutoConfiguration matched: - @ConditionalOnClass found required classes 'javax.sql.DataSource', 'org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition) DataSourceAutoConfiguration#dataSourceInitializer matched: - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer; SearchStrategy: all) did not find any beans (OnBeanCondition) DataSourceAutoConfiguration.PooledDataSourceConfiguration matched: - AnyNestedCondition 2 matched 0 did not; NestedCondition on DataSourceAutoConfiguration.PooledDataSourceCondition.PooledDataSourceAvailable PooledDataSource found supported DataSource; NestedCondition on DataSourceAutoConfiguration.PooledDataSourceCondition.ExplicitType @ConditionalOnProperty (spring.datasource.type) matched (DataSourceAutoConfiguration.PooledDataSourceCondition) - @ConditionalOnMissingBean (types: javax.sql.DataSource,javax.sql.XADataSource; SearchStrategy: all) did not find any beans (OnBeanCondition) ... Exclusions: ----------- None Unconditional classes: ---------------------- org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration</code></pre> <p>除了SpringBoot官方提供的starter外,还有社区贡献的很多常用的第三方starter,列表可参考[2]?/p> <p>另外,国内很多公司使用RPC框架dubbo,关于SpringBoot集成dubbo,可参考:<a target="_blank">https://github.com/linux-china/spring-boot-dubbo?/a></p> <p>参考资料:</p> <p>1.<a target="_blank">//docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using-boot-starter</a><br />2.<a target="_blank">https://github.com/spring-projects/spring-boot/tree/master/spring-boot-starters</a><br />3.<a target="_blank">//www.cnblogs.com/javaee6/p/3714719.html</a><br />4.<a target="_blank">https://github.com/mybatis/spring-boot-starter</a><br />5.<a target="_blank">https://afoo.me/posts/2015-07-09-how-spring-boot-works.html</a></p> </div> <div class="yibqv"> <a href="/nb/10443788"> <em ic-search-notebook"=""></em> Spring Boot极简教程(??)</a></div></div><br /><br />作者:华夏商周秦汉唐宋元明清中华民?br />链接://www.jianshu.com/p/ccadc2bdb6d7<br />來源:简?br />著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处?/div><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/432717.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2017-08-02 16:35 <a href="//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432717.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java注解(Annotation)原理详解【转?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432713.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Wed, 02 Aug 2017 03:15:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432713.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/432713.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432713.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/432713.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/432713.html</trackback:ping><description><![CDATA[     摘要: from://blog.csdn.net/lylwo317/article/details/52163304序言注解在Java中到底是什么样的东西?具体是如何实现的?nbsp;本文将一层一层深入探究注解的实现原理。为了尽可能的将分析的过程呈现出来,所以文章包含了大量的截图和代码。(ps:如果图片看不清楚,请将网页放大来看,chrome可以通过ctrl+鼠标滚轮放大)前期准备知识方面开?..  <a href='//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432713.html'>阅读全文</a><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/432713.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2017-08-02 11:15 <a href="//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432713.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>深入理解Java:注解(Annotation?-注解处理?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432712.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Wed, 02 Aug 2017 03:07:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432712.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/432712.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432712.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/432712.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/432712.html</trackback:ping><description><![CDATA[<div id="cnblogs_post_body" style="margin: 0px 0px 20px; word-break: break-word; color: #333333; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13.3333px; background-color: #ffffff;"><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了。使用注解的过程中,很重要的一部分就是创建于使用注解处理器。Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处理器?/p><hr style="margin: 0px; padding: 0px;" /><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><strong style="margin: 0px; padding: 0px;">注解处理器类?java.lang.reflect.AnnotatedElement)?/strong></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">  Java使用Annotation接口来代表程序元素前面的注解,该接口是所有Annotation类型的父接口。除此之外,Java在java.lang.reflect 包下新增了AnnotatedElement接口,该接口代表程序中可以接受注解的程序元素,该接口主要有如下几个实现类?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">  Class:类定义<br style="margin: 0px; padding: 0px;" />  Constructor:构造器定义<br style="margin: 0px; padding: 0px;" />  Field:累的成员变量定?br style="margin: 0px; padding: 0px;" />  Method:类的方法定?br style="margin: 0px; padding: 0px;" />  Package:类的包定义</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">  java.lang.reflect 包下主要包含一些实现反射功能的工具类,实际上,java.lang.reflect 包所有提供的反射API扩充了读取运行时Annotation信息的能力。当一个Annotation类型被定义为运行时的Annotation后,该注解才能是运行时可见,当class文件被装载时被保存在class文件中的Annotation才会被虚拟机读取?br style="margin: 0px; padding: 0px;" />  AnnotatedElement 接口是所有程序元素(Class、Method和Constructor)的父接口,所以程序通过反射获取了某个类的AnnotatedElement对象之后,程序就可以调用该对象的如下四个个方法来访问Annotation信息?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">  方法1?lt;T extends Annotation> T getAnnotation(Class<T> annotationClass): 返回改程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null?br style="margin: 0px; padding: 0px;" />  方法2:Annotation[] getAnnotations():返回该程序元素上存在的所有注解?br style="margin: 0px; padding: 0px;" />  方法3:boolean is AnnotationPresent(Class<?extends Annotation> annotationClass):判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false.<br style="margin: 0px; padding: 0px;" />  方法4:Annotation[] getDeclaredAnnotations():返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">  一个简单的注解处理器:  </p><div style="margin: 5px 0px; color: #000000; font-size: 12px !important;"><div style="margin: 5px 0px 0px;"><span style="margin: 0px; padding: 0px 5px 0px 0px; line-height: 1.5 !important;"><a title="复制代码" style="margin: 0px; padding: 0px; border: none !important;"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码" style="margin: 0px; padding: 0px; max-width: 900px; border: none !important;" /></a></span></div><pre style="margin-top: 0px; margin-bottom: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "Courier New" !important;"><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*********注解声明**************</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span> <span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> * 水果名称注解 * </span><span style="margin: 0px; padding: 0px; color: #808080; line-height: 1.5 !important;">@author</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> peida * </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> @<span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">interface</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> FruitName { String value() </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">default</span> ""<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">; } </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> * 水果颜色注解 * </span><span style="margin: 0px; padding: 0px; color: #808080; line-height: 1.5 !important;">@author</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> peida * </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> @<span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">interface</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> FruitColor { </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> * 颜色枚举 * </span><span style="margin: 0px; padding: 0px; color: #808080; line-height: 1.5 !important;">@author</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> peida * </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">enum</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> Color{ BULE,RED,GREEN}; </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> * 颜色属? * </span><span style="margin: 0px; padding: 0px; color: #808080; line-height: 1.5 !important;">@return</span> <span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> Color fruitColor() </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">default</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> Color.GREEN; } </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> * 水果供应者注? * </span><span style="margin: 0px; padding: 0px; color: #808080; line-height: 1.5 !important;">@author</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> peida * </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> @<span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">interface</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> FruitProvider { </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> * 供应商编? * </span><span style="margin: 0px; padding: 0px; color: #808080; line-height: 1.5 !important;">@return</span> <span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">int</span> id() <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">default</span> -1<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">; </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> * 供应商名? * </span><span style="margin: 0px; padding: 0px; color: #808080; line-height: 1.5 !important;">@return</span> <span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> String name() <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">default</span> ""<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">; </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> * 供应商地址 * </span><span style="margin: 0px; padding: 0px; color: #808080; line-height: 1.5 !important;">@return</span> <span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> String address() <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">default</span> ""<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">; } </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*********注解使用**************</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">class</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> Apple { @FruitName(</span>"Apple"<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">) </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">private</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> String appleName; @FruitColor(fruitColor</span>=<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">Color.RED) </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">private</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> String appleColor; @FruitProvider(id</span>=1,name="陕西红富士集?,address="陕西省西安市延安?9号红富士大厦"<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">) </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">private</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> String appleProvider; </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">void</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> setAppleColor(String appleColor) { </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">this</span>.appleColor =<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> appleColor; } </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> String getAppleColor() { </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">return</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> appleColor; } </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">void</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> setAppleName(String appleName) { </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">this</span>.appleName =<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> appleName; } </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> String getAppleName() { </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">return</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> appleName; } </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">void</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> setAppleProvider(String appleProvider) { </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">this</span>.appleProvider =<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> appleProvider; } </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> String getAppleProvider() { </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">return</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> appleProvider; } </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">void</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> displayName(){ System.out.println(</span>"水果的名字是:苹?<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">); } } </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*********注解处理?*************</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">class</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> FruitInfoUtil { </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">static</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">void</span> getFruitInfo(Class<?><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> clazz){ String strFruitName</span>=" 水果名称?<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">; String strFruitColor</span>=" 水果颜色?<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">; String strFruitProvicer</span>="供应商信息:"<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">; Field[] fields </span>=<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> clazz.getDeclaredFields(); </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">for</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">(Field field :fields){ </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">if</span>(field.isAnnotationPresent(FruitName.<span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">class</span>)<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">){ FruitName fruitName </span>= (FruitName) field.getAnnotation(FruitName.<span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">class</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">); strFruitName</span>=strFruitName+<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">fruitName.value(); System.out.println(strFruitName); } <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">else</span> </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">if</span>(field.isAnnotationPresent(FruitColor.<span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">class</span>)<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">){ FruitColor fruitColor</span>= (FruitColor) field.getAnnotation(FruitColor.<span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">class</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">); strFruitColor</span>=strFruitColor+<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">fruitColor.fruitColor().toString(); System.out.println(strFruitColor); } <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">else </span></span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">if</span>(field.isAnnotationPresent(FruitProvider.<span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">class</span>)<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">){ FruitProvider fruitProvider</span>= (FruitProvider) field.getAnnotation(FruitProvider.<span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">class</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">); strFruitProvicer</span>=" 供应商编号:"+fruitProvider.id()+" 供应商名称:"+fruitProvider.name()+" 供应商地址?+<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">fruitProvider.address(); System.out.println(strFruitProvicer); } } } } </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*********输出结果**************</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">class</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> FruitRun { </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> * </span><span style="margin: 0px; padding: 0px; color: #808080; line-height: 1.5 !important;">@param</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> args </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">static</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">void</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> main(String[] args) { FruitInfoUtil.getFruitInfo(Apple.</span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">class</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">); } } </span>====================================<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> 水果名称:Apple 水果颜色:RED 供应商编号:</span>1 供应商名称:陕西红富士集?供应商地址:陕西省西安市延安路89号红富士大厦</pre><div style="margin: 5px 0px 0px;"><span style="margin: 0px; padding: 0px 5px 0px 0px; line-height: 1.5 !important;"><a title="复制代码" style="margin: 0px; padding: 0px; border: none !important;"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码" style="margin: 0px; padding: 0px; max-width: 900px; border: none !important;" /></a></span></div></div><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">   Java注解的基础知识点(见下面导图)基本都过了一遍,下一篇我们通过设计一个基于注解的简单的ORM框架,来综合应用和进一步加深对注解的各个知识点的理解和运用?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><img src="//images.cnitblog.com/blog/34483/201304/25200814-475cf2f3a8d24e0bb3b4c442a4b44734.jpg" alt="" style="margin: 0px; padding: 0px; border: 0px; max-width: 900px;" /></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"> </p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"> </p></div><div id="MySignature" style="margin: 0px; color: #333333; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13.3333px; background-color: #ffffff;"><p style="margin: 12px 0px 0px; padding: 0px;"><br style="margin: 0px; padding: 0px;" /><a target="_blank" style="margin: 0px; padding: 0px; text-decoration: none; color: #000000; border-bottom: 1px dotted #333333;"></a></p></div><div style="margin: 0px; clear: both; color: #333333; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13.3333px; background-color: #ffffff;"></div><div id="blog_post_info_block" style="margin: 20px 0px 0px; color: #333333; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13.3333px; background-color: #ffffff;"><div id="BlogPostCategory" style="margin: 0px 0px 10px;">分类: <a target="_blank" style="margin: 0px; padding: 0px; text-decoration: none; color: #000000; border-bottom: 1px dotted #333333;">java</a></div><div id="EntryTag" style="margin: 20px 0px 0px; font-size: 9pt; color: gray;">标签: <a style="margin: 0px; padding: 0px; text-decoration: none; color: #000000; border-bottom: 1px dotted #333333;">深入理解Java</a>, <a style="margin: 0px; padding: 0px; text-decoration: none; color: #000000; border-bottom: 1px dotted #333333;">Java注解</a>, <a style="margin: 0px; padding: 0px; text-decoration: none; color: #000000; border-bottom: 1px dotted #333333;">Annotation</a>, <a style="margin: 0px; padding: 0px; text-decoration: none; color: #000000; border-bottom: 1px dotted #333333;">注解处理?/a>, <a style="margin: 0px; padding: 0px; text-decoration: none; color: #000000; border-bottom: 1px dotted #333333;">AnnotatedElement</a></div></div><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/432712.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2017-08-02 11:07 <a href="//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432712.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jvm 打印所有XX参数及值[转] - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/xiaomage234/archive/2017/07/28/432701.html小马?/dc:creator>小马?/author>Fri, 28 Jul 2017 03:01:00 GMT//www.ot7t.com.cn/xiaomage234/archive/2017/07/28/432701.html//www.ot7t.com.cn/xiaomage234/comments/432701.html//www.ot7t.com.cn/xiaomage234/archive/2017/07/28/432701.html#Feedback0//www.ot7t.com.cn/xiaomage234/comments/commentRss/432701.html//www.ot7t.com.cn/xiaomage234/services/trackbacks/432701.html//blog.csdn.net/coslay/article/details/43458907
  1. 我们需要知道的是找到默认值的方法,掌握默认值的大概量级,在不同的版本下哪些是常用的默认参数,哪些是必须设置的参数,哪些是可以选择的、尽量不要去碰的设置?nbsp; 
  1. 参数设置同一个类型会有多种参数,而且都有默认值,大家不要混用噢,混用的结果很多时候难以预料,虽然在某种情况下可能得到了一个测试结果,但如果你没有真正了解JVM的内核源码,是不可能知道所有细节的,即测试结果不能当成任何场景下的一个结论,只能作为一种参考?nbsp; 

本篇文章基于Java 6?/span>update 21oder 21之后)版本, HotSpot JVM 提供给了两个新的参数,在JVM启动后,在命令行中可以输出所?/span>XX参数和值?/span>

  1. -XX:+PrintFlagsFinal and -XX:+PrintFlagsInitial  

让我们现在就了解一下新参数的输出。以 -client 作为参数?-XX:+PrintFlagsFinal   的结果是一个按字母排序?90个参数表格(注意,每个release版本参数的数量会不一样)

  1. $ java -client -XX:+PrintFlagsFinal Benchmark  
  2. [Global flags]  
  3. uintx AdaptivePermSizeWeight               = 20               {product}  
  4. uintx AdaptiveSizeDecrementScaleFactor     = 4                {product}  
  5. uintx AdaptiveSizeMajorGCDecayTimeScale    = 10               {product}  
  6. uintx AdaptiveSizePausePolicy              = 0                {product}[...]  
  7. uintx YoungGenerationSizeSupplementDecay   = 8                {product}  
  8. uintx YoungPLABSize                        = 4096             {product}  
  9.  bool ZeroTLAB                             = false            {product}  
  10.  intx hashCode                             = 0                {product}  

(校对注:你可以尝试在命令行输入上面的命令,亲自实现下)

表格的每一行包括五列,来表示一个XX参数。第一列表示参数的数据类型,第二列是名称,第四列为值,第五列是参数的类别。第三列”=”表示第四列是参数的默认值,?#8221;:=” 表明了参数被用户或者JVM赋值了?/p>

注意对于这个例子我只是用了Benchmark类,因为这个系列前面的章节也是用的这个类。甚至没有一个主类的情况下你能得到相同的输出,通过运行Java 带另外的参数 -version.现在让我们检查下 server VM提供了多少个参数。我们也能指定参?code>-XX:+UnlockExperimentalVMOptions ?code>-XX:+UnlockDiagnosticVMOptions ;来解锁任何额外的隐藏参数?/code>

  1. $ java -server -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal Benchmark  
724个参数,让我们看一眼那些已经被赋值的参数?/span>
  1. $ java -server -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal Benchmark | grep ":"  
  2. uintx InitialHeapSize                     := 57505088         {product}  
  3. uintx MaxHeapSize                         := 920649728        {product}  
  4. uintx ParallelGCThreads                   := 4                {product}  
  5.  bool PrintFlagsFinal                     := true             {product}  
  6.  bool UseParallelGC                       := true             {product}  

(校对注:这个命令非常有用)我们仅设置一个自己的参数 -XX:+PrintFlagsFinal。其他参数通过server VM基于系统设置的,以便以合适的堆大小和GC设置运行?/p>

如果我们只想看下所有XX参数的默认值,能够用一个相关的参数?XX:+PrintFlagsInitial  ??nbsp;-XX:+PrintFlagsInitial, 只是展示了第三列?#8220;=”的数据(也包括那些被设置其他值的参数)?/p>

然而,注意当与-XX:+PrintFlagsFinal 对比的时候,一些参数会丢失,大概因为这些参数是动态创建的?/p>

研究表格的内容是很有意思的,通过比较client和server VM的行为,很明显了解哪些参数会影响其他的参数。有兴趣的读者,可以看一下这篇不错文?a target="_blank" style="color: #4ec103; text-decoration: none; outline: none;">Inspecting HotSpot JVM Options。这个文章主要解释了第五列的参数类别?/p>

-XX:+PrintCommandLineFlags

让我们看下另外一个参数,事实上这个参数非常有? -XX:+PrintCommandLineFlags。这个参数让JVM打印出那些已经被用户或者JVM设置过的详细的XX参数的名称和值?/p>

换句话说,它列举?nbsp;-XX:+PrintFlagsFinal的结果中第三列有":="的参数。以这种方式?/code>我们可以?XX:+PrintCommandLineFlags作为快捷方式来查看修改过的参数。看下面的例子?/p>

  1. $ java -server -XX:+PrintCommandLineFlags Benchmark   

  1. -XX:InitialHeapSize=57505088 -XX:MaxHeapSize=920081408 -XX:ParallelGCThreads=4 -XX:+PrintCommandLineFlags -XX:+UseParallelGC  

现在如果我们每次启动java 程序的时候设?-XX:+PrintCommandLineFlags 并且输出到日志文件上,这样会记录下我们设置的JVM 参数对应用程序性能的影响。类似于 -showversion(?Part1),我建议 –XX:+PrintCommandLineFlags 这个参数应该总是设置在JVM启动的配置项里。因为你从不知道你什么时候会需要这些信息?/p>

奇怪的是在这个例子中,通过 -XX:+PrintCommandLineFlags 列出堆的最大值会比通过-XX:+PrintFlagsFinal列举出的相应值小一点。如果谁知道两者之间不同的原因,请告诉我?/p>

转载自://ifeve.com/useful-jvm-flags-part-3-printing-all-xx-flags-and-their-values/



   Java程序员有时候需要了解JVM相关的参数,不管是出于好奇或者工作需要?a title="Oracle知识? target="_blank" style="color: #df3434; text-decoration: none; font-weight: bold;">Oracle的文?中列出了一些,?a target="_blank" style="color: #ca0000; text-decoration: none;">点击这里),单并不是全部,而且有些参数的设置会默认启用或者关闭其他一些参数,而在某些情况下设置某个参数是不会生效的。还有些时候你想让JVM做某些事情,但是你不知道那个参数可以用。下面介绍一些办法用以列出所有参数,这样你在研究或者Google的时候也比较有明确的目标?/p>

    如果你想查看一下线上正在运行的JVM到底设置了那些参数,生效的是那些,可能用到的方法?/p>

    1. ?a title="Linux知识? target="_blank" style="color: #df3434; text-decoration: none; font-weight: bold;">Linux下用ps命令找到启动Java应用时的参数

  1. ps -ef | grep "your java app name"    

    这个命令会打出你启动Java应用时传给java命令的所有参数,你可以看到里面的JVM参数?/p>

    2.直接看启动脚本,或者参数配?/p>

    你未必能找到所有设置这JVM参数的地方,容易遗漏?br />

    一般来讲以上两种办法都需要对JVM了如指掌或者非常熟悉,至少对特定的参数?/p>

    

    其实JVM中有一个参?XX:+PrintFlagsFinal,可以打印出几乎所有的JVM支持的参数以及他们的默认值。如果你想要查看你的Java应用到底使用了那些参数,只要在启动的时候加上这个参数就可以了?/p>

    1.查看你使用的JDK支持的参?/p>

  1. java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version    

    2.打印Java应用启用的JVM参数

  1. java -XX:+PrintFlagsFinal -classpath=/path/to/your/libs MainClass    

    3.如果你的Java应用已经是运行状态了,你想查看某个JVM参数生效没有可以使用jinfo这个工具?strong>比如说大名鼎鼎的G1垃圾回收器,在JDK7update3中不论是客户?-client)还是服务?-server)模式下都不是默认启动的?/strong>

    jinfo是随JDK一起发布的,使用时先用jps找到Java应用的pid。直接运行jinfo可以查看使用说明?/p>

  1. jinfo -flag UseParallelOldGC 31072    

    3.如果你的Java应用已经是运行状态了,你想查看某个JVM参数生效没有可以使用jinfo这个工具?strong>比如说大名鼎鼎的G1垃圾回收器,在JDK7update3中不论是客户?-client)还是服务?-server)模式下都不是默认启动的?/strong>

    jinfo是随JDK一起发布的,使用时先用jps找到Java应用的pid。直接运行jinfo可以查看使用说明?/p>

  1. jinfo -flag UseParallelOldGC 31072  <span style="color: rgb(0, 204, 0); line-height: 18px; font-family: Consolas, 'Courier New', Courier, mono, serif; background-color: inherit;"> </span>  
  1. -XX:+UseParallelOldGC    
    JDK中实用的工具还很多,可以逐个的体验一?{JAVA_HOME}/bin目录中的每个命令,有惊喜?/span>


参考://blog.csdn.net/redhat456/article/details/7360249

?/dt>
0


]]>杂谈GC【转?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2017/07/27/432697.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Thu, 27 Jul 2017 06:33:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2017/07/27/432697.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/432697.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2017/07/27/432697.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/432697.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/432697.html</trackback:ping><description><![CDATA[from://www.jianshu.com/p/2750c7c202ef<br /><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">上周有幸给部门的小伙伴分享了一些JVM相关的知识,在整个做PPT的过程中,也是对一个领域的碎片知识的整理,本文将针对虚拟机GC相关的一些内容进行整理,本文不会涉及到G1收集器?/p><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">在Hotspot VM实现中,主要有两大类GC</p><ol style="box-sizing: border-box; margin-top: 0px; margin-bottom: 20px; word-break: break-word; padding: 0px; margin-left: 22px; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;"><li style="box-sizing: border-box; line-height: 30px; margin-bottom: 10px;"><span style="box-sizing: border-box; font-weight: 700;">Partial GC</span>:并不会堆整个GC堆进行收?ul style="box-sizing: border-box; margin-top: 15px; margin-bottom: 20px; padding: 0px; word-break: break-word; margin-left: 22px;"><li style="box-sizing: border-box; line-height: 30px; margin-bottom: 10px;">young gc:只收集 young gen 的GC</li><li style="box-sizing: border-box; line-height: 30px; margin-bottom: 10px;">old gc:只收集 old gen 的GC,只有CMS?concurrent collection</li><li style="box-sizing: border-box; line-height: 30px; margin-bottom: 10px;">mixed GC:收集整?young gen 以及部分 old gen 的GC,只有G1</li></ul></li><li style="box-sizing: border-box; line-height: 30px; margin-bottom: 10px;"><span style="box-sizing: border-box; font-weight: 700;">Full GC</span>:收集整个堆,包括young gen、old gen、perm gen(如果存在的话)?/li></ol><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">其实在各种文章或书上还可以看到Minor GC、Major GC的字眼,其中minor GC和young gc对应,而Major GC通常是和Full GC是等价的,由于HotSpot VM发展了这么多年,外界对各种名词的解读已经完全混乱了,所以Major GC有时也可能是指old gc,在下定论之前一定要先问清楚?/p><h3>单线程、并行、并?/h3><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">在GC收集器实现中,分为了单线程、并行和并发?br style="box-sizing: border-box;" /><span style="box-sizing: border-box; font-weight: 700;">单线程收集器</span>:如 Serial GC,这个比较好理解,即垃圾收集过程中只有单一线程在进行收集工作,实现也最简单?/p><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;"><span style="box-sizing: border-box; font-weight: 700;">并行收集?/span>:如Parallel GC,每次运行时,不管是YGC,还是FGC,会 stop-the-world,暂停所有的用户线程,并采用多个线程同时进行垃圾收集?/p><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;"><span style="box-sizing: border-box; font-weight: 700;">并发收集?/span>:如CMS GC,在新生代进行垃圾收集时和并行收集器类似,都是并行收集(当然具体算法中,你也可以设置成采用单线程进行收集),而且都会stop-the-world,主要的区别在于老年代的收集上,CMS在老年代进行垃圾收集时,大部分时间可以和用户线程并发执行的,只有小部分的时间stop-the-world,这就是它的优势,可以大大降低应用的暂停时间,当然也是有劣势的?/p><h3>算法组合</h3><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">Hotspot VM实现的几种GC算法组合中,其中CMS GC使用最广,因为现在都是大内存时代?/p><h4>1、Serial GC</h4><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">Serial generational collector (-XX:+UseSerialGC)<br style="box-sizing: border-box;" />是全局范围的Full GC,这种算法组合是最早出现的,当年的Java堆内存大小都还不大,使用Serial GC进行单线程收集,还感觉不出来GC耗时导致应用暂停的问?/p><h4>2、Parallel GC</h4><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">Parallel for young space, serial for old space generational collector (-XX:+UseParallelGC).<br style="box-sizing: border-box;" />Parallel for young and old space generational collector (-XX:+UseParallelOldGC)<br style="box-sizing: border-box;" />当Java堆慢慢变大时,发现已经无法忍受GC耗时带来的应用暂停了,出现了Parallel GC,采用多线程的方式进行垃圾收集,很明显可以提升垃圾收集效率?/p><h4>3、CMS GC</h4><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">Concurrent mark sweep with serial young space collector (-XX:+UseConcMarkSweepGC<br style="box-sizing: border-box;" />–XX:-UseParNewGC)<br style="box-sizing: border-box;" />Concurrent mark sweep with parallel young space collector (-XX:+UseConcMarkSweepGC)<br style="box-sizing: border-box;" />当Java堆达到更大时,比?G,使用Parallel GC带来的应用暂停已经很明显了,所有又出现?CMS GC,这是目前我看到线上环境使用的比较多的GC策略,在参数中添?code style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 12px; color: #657b83; background-color: #f6f6f6; border-radius: 4px; padding: 2px 4px; border: none; white-space: pre-wrap;">-XX:+UseConcMarkSweepGC</code>,对?young gen,会自动选用 ParNewGC,不需要额外添?nbsp;<code style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 12px; color: #657b83; background-color: #f6f6f6; border-radius: 4px; padding: 2px 4px; border: none; white-space: pre-wrap;">-XX:+UseParNewGC</code>?/p><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">CMS虽然好,因为它的特殊算法,大部分的收集过程可以和用户线程并发执行,大大降低应用的暂停时间,不过也会带来负面影响,在收集完 old gen 之后,CMS并不会做整理过程,会产生空间碎片,如果这些碎片空间得不到利用,就会造成空间的浪费,整个过程中可能发?concurrent mode failure,导致一次真正意义的 full gc,采用单线程对整个堆(young+old+perm?使用MSC(Mark-Sweep-Compact)进行收集,这个过程意味着很慢很慢很慢,而且这个碎片问题是无法预测的.</p><h4>4、G1 GC</h4><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">G1 garbage collector (-XX:+UseG1GC),本文不对G1进行介绍</p><h3>触发条件</h3><h4>young gc</h4><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">对于 young gc,触发条件似乎要简单很多,?eden 区的内存不够时,就会触发young gc,我们看看在 eden 区给对象分配一块内存是怎样一个过程,画了一个简单的流程图,我一直觉得一个好的示意图可以让一个枯燥的过程变得更有意思?/p><div style="box-sizing: border-box; padding-bottom: 25px; width: 700px; margin-left: -40px; text-align: center; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;"><img src="//upload-images.jianshu.io/upload_images/2184951-b2c677f3d53a2d93.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" data-original-src="//upload-images.jianshu.io/upload_images/2184951-b2c677f3d53a2d93.png?imageMogr2/auto-orient/strip%7CimageView2/2" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 100%; height: auto; cursor: zoom-in; transition: all 0.25s ease-in-out;" alt="" /></div><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">?eden 区分配空间内存不足时有两种情况,为对象分配内存、为TLAB分配内存,总之就是内存不够,需要进行一?young gc 为eden区腾出空间为后续的内存申请做准备,然后由一个用户线程通知VM Thread,接下去要执行一?young gc?/p><h4>full gc</h4><h5>1、old gen 空间不足</h5><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">当创建一个大对象、大数组时,eden 区不足以分配这么大的空间,会尝试在old gen 中分配,如果这时 old gen 空间也不足时,会触发 full gc,为了避免上述导致的 full gc,调优时应尽量让对象?young gc 时就能够被回收,还有不要创建过大的对象和数组?/p><h5>2、统计得到的 young gc 晋升?old gen的对象平均总大小大于old gen 的剩余空?/h5><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">当准备触发一?young gc时,会判断这?young gc 是否安全,这里所谓的安全是当前老年代的剩余空间可以容纳之前 young gc 晋升对象的平均大小,或者可以容?young gen 的全部对象,如果结果是不安全的,就不会执行这?young gc,转而执行一?full gc</p><h5>3、perm gen 空间不足</h5><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">如果有perm gen的话,当系统中要加载的类、反射的类和调用的方法较多,而且perm gen没有足够空间时,也会触发一?full gc</p><h5>4、ygc出现 promotion failure</h5><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">promotion failure 发生?young gc 阶段,即 cms ?ParNewGC,当对象的gc年龄达到阈值时,或?eden ?to 区放不下时,会把该对象复制到 old gen,如?old gen 空间不足时,会发?promotion failure,并接下去触发full gc</p><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">在GC日志中,有时会看?concurrent mode failure 关键字,这是因为什么原因导致的问题? 对这一块的理解,很多文章都是说因为 concurrent mode failure 导致触发full gc,其实应该反过来,是full gc 导致?concurrent mode failure,在cms gc的算法实现中,通常说的cms是由一个后台线程定时触发的,默认每2秒检查一次old gen的内存使用率,当 old gen 的内存使用率达到<code style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 12px; color: #657b83; background-color: #f6f6f6; border-radius: 4px; padding: 2px 4px; border: none; white-space: pre-wrap;">-XX:CMSInitiatingOccupancyFraction</code>设置的值时,会触发一?cms gc,对 old gen 进行并发收集,而真正的 full gc 是通过 vm thread线程触发的,而且在判断当前ygc会失败的情况下触发full gc,如上一次ygc出现了promotion failure,如果执?full gc 时,发现后台线程正在执行 cms gc,就会导?concurrent mode failure?/p><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">对于以上这些情况?code style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 12px; color: #657b83; background-color: #f6f6f6; border-radius: 4px; padding: 2px 4px; border: none; white-space: pre-wrap;">CMSInitiatingOccupancyFraction</code>参数的设置就显得尤为重要,设置的太大的话,发生CMS时的剩余空间太小,在ygc的时候容易发生promotion failure,导?concurrent mode failure 发生的概率就增大,如果设置太小的话,会导?cms gc 的频率会增加,所以需要根据应用的需求对该参数进行调优?/p><h5>5、执?nbsp;<code style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: #657b83; background-color: #f6f6f6; border-radius: 4px; padding: 2px 4px; border: none; white-space: pre-wrap;">System.gc()</code>?code style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: #657b83; background-color: #f6f6f6; border-radius: 4px; padding: 2px 4px; border: none; white-space: pre-wrap;">jmap -histo:live <pid></code>?code style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: #657b83; background-color: #f6f6f6; border-radius: 4px; padding: 2px 4px; border: none; white-space: pre-wrap;">jmap -dump ...</code></h5><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">参考资?br style="box-sizing: border-box;" /><a target="_blank" style="box-sizing: border-box; background-color: transparent; color: #3194d0; text-decoration: none; cursor: pointer;">Major GC和Full GC的区别是什么?触发条件?/a></p><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">个人公众?/p><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/432697.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2017-07-27 14:33 <a href="//www.ot7t.com.cn/xiaomage234/archive/2017/07/27/432697.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>学习Cassandra资料的一些整理【转?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2017/07/18/432666.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Tue, 18 Jul 2017 01:57:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2017/07/18/432666.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/432666.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2017/07/18/432666.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/432666.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/432666.html</trackback:ping><description><![CDATA[<p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">from:<span style="font-family: verdana, "courier new"; font-size: 14px;">//www.cnblogs.com/foohack/p/5627163.html</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">Cassandra note:</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">依赖:需要java 8 (//www.oracle.com/technetwork/java/javase/downloads/index.html?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">数据模型: 与Hbase同样是属于列式数据库,Key-Value存储系统。(//www.ibm.com/developerworks/cn/opensource/os-cn-cassandra/?br style="margin: 0px; padding: 0px;" />//www.datastax.com/dev/blog/basic-rules-of-cassandra-data-modeling</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">集群中的数据是靠partion key的hash code均匀映射到不同的节点上去的。partionkey是primary key的第一个元素,所以选一个好的主<br style="margin: 0px; padding: 0px;" />key才能使数据更好的均匀存储在不同的节点上?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"><br style="margin: 0px; padding: 0px;" />Cassandra的节点实例叫Cluster,里面可以包含一个或多个键空?KeysSpace).键空间是存放列族(Column Family)的容器,相当于<br style="margin: 0px; padding: 0px;" />关系数据中的database,schema。列族是存放列(column)的容器,类似与关系数据库中的table。超级列(Super column)是一?br style="margin: 0px; padding: 0px;" />特殊的列,它的value值可以包含多个column?columns是cassandra的最基本单位,有name,value,timestamp构成?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"> </p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">列式数据库的优点: <br style="margin: 0px; padding: 0px;" />1.适合存储大量数据,而不是小量数据。因为数据是是基于列存储的,所以可以忽略不需要的列的数据,提高查找效率?br style="margin: 0px; padding: 0px;" />与之对应的是行数据库?br style="margin: 0px; padding: 0px;" />2.高压缩比。节省存储空间,也节省CPU和内存?br style="margin: 0px; padding: 0px;" />3.高装载速度?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">列式数据库的缺点:<br style="margin: 0px; padding: 0px;" />1.不适合扫描小量数据?br style="margin: 0px; padding: 0px;" />2.不适合随机更新数据?br style="margin: 0px; padding: 0px;" />3.不适合做含有删除的更新的实时操作?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"><br style="margin: 0px; padding: 0px;" />查询数据:<br style="margin: 0px; padding: 0px;" />Cassandra有自己的一套查询语言CQL(类似SQL),在数据访问方式上亦是如此。客户端可以与集群中的任意节点相连,并访问任意的数据?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">cassandra在写入数据之前需要记录日?CommitLog),然后数据开始写入到 Column Family 对应?Memtable 中,<br style="margin: 0px; padding: 0px;" />Memtable 是一种按?key 排序数据的内存结构,在满足一定条件时,再?Memtable 的数据批量的刷新到磁盘上,存储为 SSTable ?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">存储二进制大文件(不推荐存储)://wiki.apache.org/cassandra/FAQ#large_file_and_blob_storage</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">Cassandra的GUI管理工具整理://wiki.apache.org/cassandra/FAQ#gui 也有自带的CLI工具连接Cassandra</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">Cassandra集群种子的概念(很重要)://wiki.apache.org/cassandra/FAQ#seed<br style="margin: 0px; padding: 0px;" />类似与Cassandra集群的初始化节点(集线器),各个节点通过种子节点互相学习(交换)各自的数据(状态),所以新加入的Cassandra节点都需要给?br style="margin: 0px; padding: 0px;" />指定种子节点,下次启动的时候就不需要了?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"><br style="margin: 0px; padding: 0px;" />Cassandra 的C++ 接口?br style="margin: 0px; padding: 0px;" />Cassandra的各种编程语言的接口是有Thrift这个开源工具生成的,语言无关的Thrift输入文件(cassandra.thrift)Cassandra已经自带<br style="margin: 0px; padding: 0px;" />,安装thrift运行 thrift.exe -gen cpp cassandra.thrift生成就可以了?cpp的接口依赖thrift的核心库叫libthrift,libthrift依赖boost1.53.0<br style="margin: 0px; padding: 0px;" />版本和openssl</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"><br style="margin: 0px; padding: 0px;" />Cassandra windows 安装配置:<br style="margin: 0px; padding: 0px;" />解压,配置好CASSANDRA_HOME环境变量的路径(也就是你解压的cassandra根目录),然后运行bin下的cassandra.bat,如果发现logs<br style="margin: 0px; padding: 0px;" />目录底下的system.log文件中有INFO - Starting up server gossip,那么恭喜你,Cassandra已经在你的本机启动起来了?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"> </p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"> </p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">*****************************************Cassandra的基本操?***********************************************</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">数据模型:多维的hash表,每行可以有不同的列。每行都有个? keyspace包含若干列族<br style="margin: 0px; padding: 0px;" />(列族和表是同一个概念://stackoverflow.com/questions/18824390/whats-the-difference-between-creating-a-table-and-creating-a-columnfamily-in-ca)?br style="margin: 0px; padding: 0px;" />keyspace在逻辑上是容纳列族和某些配置属性的命名空间。列族定义了相关的数据名字和它们的排序方式?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">入门必读://wiki.apache.org/cassandra/GettingStarted</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">CQLSH中运行外部创建的cql脚本文件: SOURCE '[file_path]'</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">键空间的创建: <br style="margin: 0px; padding: 0px;" />CREATE KEYSPACE [keyspace_name] WITH REPLICATION = {'class' : 'NetworkTopologyStrategy', 'datacenter1' : 3};</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">----键空间的创建要附带副本属性,class可以指定NetworkTopologyStrategy或SimpleStrategy。SimpleStrategy只用于测试评估Cassandra<br style="margin: 0px; padding: 0px;" />生产环境使用NetworkTopologyStrategy. 键空间类似关系型数据库中的数据库(database?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">键空间的修改?br style="margin: 0px; padding: 0px;" />ALTER KEYSPACE [keyspace_name] WITH REPLICATION = {};</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">键空间的删除:<br style="margin: 0px; padding: 0px;" />DROP KEYSPACE [keyspace_name]</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">键空间的使用:<br style="margin: 0px; padding: 0px;" />USE [keyspace_name]</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"><br style="margin: 0px; padding: 0px;" />列出已存在的键空?<br style="margin: 0px; padding: 0px;" />DESCRIBE keyspaces;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">列出某个键空间下的所有表?br style="margin: 0px; padding: 0px;" />USE [keyspace_name];<br style="margin: 0px; padding: 0px;" />DESCRIBE tables;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">列出某个键空间下的所有列族:<br style="margin: 0px; padding: 0px;" />USE [keyspace_name];<br style="margin: 0px; padding: 0px;" />DESCRIBE columnfamilies;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">列出特定的表的基本信息:<br style="margin: 0px; padding: 0px;" />DESCRIBE TABLE [keyspace_name].[table_name];</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">建表?br style="margin: 0px; padding: 0px;" />//docs.datastax.com/en/cql/3.1/cql/cql_using/create_table_t.html<br style="margin: 0px; padding: 0px;" />表的主键可以是复合的,就是多个列组成一个主键:<br style="margin: 0px; padding: 0px;" />CREATE TABLE emp (<br style="margin: 0px; padding: 0px;" />empID int,<br style="margin: 0px; padding: 0px;" />deptID int,<br style="margin: 0px; padding: 0px;" />first_name varchar,<br style="margin: 0px; padding: 0px;" />last_name varchar,<br style="margin: 0px; padding: 0px;" />PRIMARY KEY (empID, deptID)); //主键的第一个键就是分区键(empID),分区键的目的就是把表中的数据均分到集群中?br style="margin: 0px; padding: 0px;" />各个节点?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">更改表:<br style="margin: 0px; padding: 0px;" />ALERT TABLE [table_name] [some change]<br style="margin: 0px; padding: 0px;" />https://docs.datastax.com/en/cql/3.0/cql/cql_reference/alter_table_r.html<br style="margin: 0px; padding: 0px;" />没办法更改主键,因为主键涉及到数据的物理储存</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">给表的某列建立索引:<br style="margin: 0px; padding: 0px;" />CREATE INDEX ON [table_name] (column_name);</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"><br style="margin: 0px; padding: 0px;" />查表?br style="margin: 0px; padding: 0px;" />SELCT [column_name] FROM [keyspace].[table_name] WHERE [column_name] = [value] //其中column_name必须是主键的其中部分?br style="margin: 0px; padding: 0px;" />如果有多个条件必须其中有一个是分区?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">更新表中的?<br style="margin: 0px; padding: 0px;" />UPDATE [keyspace].[table_name] SET [column_name] = [new_value] WHERE [column_name]=[value]</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">删除表中列或行:<br style="margin: 0px; padding: 0px;" />删除列中值:DELETE [column_name] FROM [table_name] WHERE [column_name] = [value] # 同查?br style="margin: 0px; padding: 0px;" />删除一整行:DELETE FROM [table_name] WHERE [column_name] = [value] #同上</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">自定义数据类?//docs.datastax.com/en/cql/3.1/cql/cql_using/cqlUseUDT.html):<br style="margin: 0px; padding: 0px;" />CREATE TYPE [keyspace_name].[type_name] (<br style="margin: 0px; padding: 0px;" />street text,<br style="margin: 0px; padding: 0px;" />city text,<br style="margin: 0px; padding: 0px;" />zip_code int,<br style="margin: 0px; padding: 0px;" />phones set<text><br style="margin: 0px; padding: 0px;" />);<br style="margin: 0px; padding: 0px;" />自定义的数据类型的字面值是json-style的风格?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">内建的数据类?//docs.datastax.com/en/cql/3.1/cql/cql_reference/cql_data_types_c.html)?br style="margin: 0px; padding: 0px;" />ascii,bigint,blob,boolean,counter,double,float,inet,int,list,map,set,text,uuid,<br style="margin: 0px; padding: 0px;" />timestamp,tuple,varchar(UTF-8 encoded string) ,varint</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"><br style="margin: 0px; padding: 0px;" />查看集群信息?br style="margin: 0px; padding: 0px;" />SELECT * FROM system.peers;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;">本地帮助文的查?<br style="margin: 0px; padding: 0px;" />HELP [COMMAND]<br style="margin: 0px; padding: 0px;" />比如:查看创建键空间 HELP CREATE_KEYSPACE;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"><br style="margin: 0px; padding: 0px;" />CQL语句支持多语句提交(Batch):<br style="margin: 0px; padding: 0px;" />可以减少Node之间的流量交换,类似于事务,是原子的?br style="margin: 0px; padding: 0px;" />//docs.datastax.com/en/cql/3.1/cql/cql_reference/batch_r.html#reference_ds_djf_xdd_xj__batch-conditional<br style="margin: 0px; padding: 0px;" />//docs.datastax.com/en/cql/3.1/cql/cql_using/use-batch-static.html</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"><br style="margin: 0px; padding: 0px;" />给数据设置存活期?br style="margin: 0px; padding: 0px;" />超过存活期的数据,将被销毁?br style="margin: 0px; padding: 0px;" />INSERT INTO [table_name]<br style="margin: 0px; padding: 0px;" />([column_name1], [column_name2])<br style="margin: 0px; padding: 0px;" />VALUES ([column_value1], [column_value2]) USING TTL 86400; # 86400 sec 大概是一天的存活?br style="margin: 0px; padding: 0px;" />是给column_name2设置?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; line-height: 1.5; font-size: 13px; font-family: Verdana, Arial, Helvetica, sans-serif; background-color: #fefef2;"><br style="margin: 0px; padding: 0px;" />UPDATE [table_name] USING TTL 432000 SET [column_name] = [column_value]<br style="margin: 0px; padding: 0px;" />WHERE user_name = 'cbrown';</p><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/432666.html" width = "1" height = "1" /><br><br><div align=right><a href="//www.ot7t.com.cn/" title="四川福利彩票快乐12">四川福利彩票快乐12</a></div>]]></description></item></channel></rss> <script>(function(){ var src = (document.location.protocol == "http:") ? "//js.passport.qihucdn.com/11.0.1.js?f7a6bc378844a5df707c414e6b6fea33":"https://jspassport.ssl.qhimg.com/11.0.1.js?f7a6bc378844a5df707c414e6b6fea33"; document.write('<script src="' + src + '" id="sozz"><\/script>'); })(); </script>