1 2 3 4 5 6 7 8 9 10 11 |
|
属性意义基本明确,这里我配置了一个名称是notice_cache的cache节点,其他的可以按此添加。
配置cacheManager和cacheManagerFactory,并将ehcache.xml配入即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
注解加在相应方法上,支持spel,详细参见文档查阅spring 4.0.x reference
1 2 3 4 5 6 7 8 9 |
|
至此配置完了,run一下,报错:没有序列化,将vo实现Serializable接口
1
|
|
标签:spring
这样ehcache集成完了,get方法对同一条记录只从数据库查询一次,cache是成功的,但search方法却一直读库,这里没有设置cache的key,设置的话如果是固定的,那么每次结果集都一样,不会更新;文档说不设key,将使用默认key生成器DefaultKeyGenerator:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
问题就在于object.hashCode(),看方法的参数string没问题,date没问题,Integer数组使用的就是Object类的hashCode是个内存地址,每次执行都变,要改用Arrays.hashCode(array)才不会变;
当然,分页类page也要重写hashCode;顺便说下,apache的commons-lang.jar提供了EqualsBuilder、HashCodeBuilder、ToStringBuilder可用于重写各方法。还要注意:分页列表不仅要缓存list,还要缓存分页信息,这样到前端才会分页,否则是不知道这个list是多少页的,故方法的返回值(上面search方法只返回list是不行的)可采用类似org.springframework.data.domain.Page
内部包含结果集
解决上面问题:重写生成器(继承DefaultKeyGenerator,需要注意的是对于param是list,set,map取hashcode,其泛型类也要重写hashCode方法)并配置:
1 2 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
显然@Cacheable是缓存,@CacheEvict是擦除,@CachePut相当于擦除后再缓存,对于key是确定的很好,比如getById(id),update(obj),其key可以用id,obj.id;update时也可以用@CachePut,要注意update方法要返回更新后的obj,void不行。
问题又出现了:不明确的key如何更新?例如search,当新添加一条记录后,就不能使用@CacheEvict(value=“notice_cache”, key=“?”),因为取不到key,也不能模糊匹配;这种情况下只能使用@CacheEvict(value = “notice_cache”, allEntries = true),将notice_cache所有的缓存擦除,多少有点粗糙,而memcached甚至没有某个cache的removeAll,这就要自己写个MemcachedCache
通常注解使用在service方法上,还有一个注意事项:因其使用aop的动态代理,对于内部调用无效,例如publish方法没加注解,内部调用update方法(加了@CachePut)更新状态值,但cache不会更新;controller方法(不加注解)调用service方法(加了注解)是可以;当然controller方法也可以加,需要单独处理,因为参数若有request、response之类,每次请求都变,就要在keyGenerator里做过滤了。
背景:现在的项目使用memcached做缓存,基本上是编码式的,在需要的时候,生成key,将value转为json再set到缓存,因此打算使用注解式更优雅的处理,就需要实现spring cache的相关接口和自定义一些方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
properties:
1 2 3 4 5 6 7 8 9 10 |
|
标签:技术
参考ehcache的源码(org.springframework.cache.ehcache包里):EhCacheCache和EhCacheCacheManager,manager用来获取cache,重写了getCache和loadCaches方法,这样配置在ehcache.xml里的cache name都会实例化成每个EhCacheCache,当执行到@Cacheable的方法上,就会调用getCache(name)获取cache,再根据key取得value;
MemcachedCacheManager:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
这样应用启动时实例化manager,在执行加缓存注解的的方法时,会调用getCache(获取或新建cache),根据缓存的key从cache中取值(没有就读库,然后将结果加入cache,下次相同的key就能取到缓存的值了)
要写MemcachedCache实现org.springframework.cache.Cache
接口,先来分析EhCacheCache:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
|
好了,来写memcachedCache,问题来了:
1.clear方法,spy的client没有removeAll,clear之类的方法,有个flush是全部清空,服务器N多个cache都会擦掉
2.@CacheEvict(value = “notice_cache”, allEntries = true)就是用的clear,“添加个notice都要清掉其他非notice_cache缓存”就很可怕,能不能根据cache名称清除呢?
3.上面两个实际是一个问题,memcached是key-value存储,所以要对key进行分组,采用一个集合保存key,然后将实际的key-value存入;如果想模糊匹配也是可行的,需要在此基础上做修改:key就得用字符串而不是字符串的hashCode了,或者自定义注解
常用的集合数据类型如list,map,set它也支持,考虑到key的字符限制和单个value不超过1MB,使用一个set存储一个cache里所有的key能达到2万以上(看key的字节数),使用压缩存储的更多,同时使用LRU(如LinkedHashMap,将过期的或长期不用的移除),基本满足使用
标签:memcached
MemcachedCache:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
|
这里keys也可以使用cacheName作为key存入缓存,就需要在put,evict,clear方法里使用client.replace(name, expire, keys);
保持更新
KeySet继承LinkedHashMap,为了使用removeEldestEntry,满了移除最旧元素,保持initSize:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
因为要存储keys,所以考虑使用哪种集合:HashSet\HashMap都不是线程安全的,例如Java HashMap的死循环;
安全的如Collections.synchronizedMap和ConcurrentHashMap(不允许value为null);
两者的区别是锁不同:synchronizedMap使用对象锁,相当于在方法上声明synchronized;ConcurrentHashMap比较复杂,在segment上加锁,将范围控制的很小,因而并发性能就高;
这里使用LinkedHashMap,ConcurrentHashMap不好包装,synchronizedMap效率低,不如加个ReentrantLock,或者使用读写锁ReentrantReadWriteLock(但这篇文章介绍了读写锁可能存在问题:小心LinkedHashMap的get()方法):
1 2 3 4 5 6 |
|
下面是HashMap占用cpu 100% bug的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
以上3.2.x使用正常,4.0版本改动了key生成器,源码也很简单:SimpleKeyGenerator和SimpleKey,toString方法将参数转为字符串,嫌长就改用hashCode
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
事实上,对于复杂的,类似Object数组(下面会有),那么无论是上面自定义keyGenerator还是spring4.0的都会有问题(hashCode和toString,不一致就取不到cache,会每次都读库),测试简单数组如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
这个测试Arrays.hashCode(array)和SimpleKey.toString()多次运行是一致的,也就是自定义keyGenerator和SimpleKeyGenerator正确
复杂的:Object[] mixed = new Object[] { 1, "11", array, list };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
结论:多次运行发现只有Arrays.deepToString和Arrays.deepHashCode是一致的,也就是对每个元素,如果是数组再递归;同理,如果是集合list,set,map之类,最好使用泛型,类型一致,不要混合
spring cache用好要注意很多:
1、搞清各注解意义和使用时机,逻辑正确,更新一致
2、缓存key的使用很重要,自定义key要考虑参数重写hashCode和toString
3、返回结果如分页结果集,不仅要有list还要有page
4、可虑清楚并测试加了Cacheable确实生效?
5、效益最大化:使用多注解多缓存的情景,一次方法执行缓存多个信息(要更新时也得多个更新,才能保持一致)
与你所相信的恰恰相反,单纯地每天埋头于工作并不能算是真正意义上的锻炼——参加会议并不能锻炼你的人际交往能力;回复邮件并不能提高你的打字水平。你必须定期留出时间,集中锻炼,这样才能把事情做得更好。wang chaoqun
我认识很多杰出的程序员——这是在亚马逊工作最好的额外“福利”之一。如果仔细观察他们,你会发现他们时时都在锻炼。他们已经很优秀了,但他们仍然不忘锻炼。他们锻炼的方法林林总总,而我在这篇文章中只会介绍其中的几种。
据我了解,这些杰出程序员之所以如此成功,就是因为他们一直在锻炼。完美的身材要靠定期的锻炼才能获得,而且必须坚持锻炼才能保持,否则身材就会走形。对于编程和软件工程来说,道理是一样的。
这是一个重要的区别——我每天都开车去上班,但我的驾驶水平远远不如专业车手;类似的情况,天天编程可能并不足以使你成为一名专业的程序员。那么,什么才能把一个普通人变成一名专业车手或者专业程序员呢?你需要锻炼什么呢?
答案就在《科学美国人》的一篇名为“The Expert Mind”(专家思维)的文章里:
爱立信提出,重要的并不是经验本身,而是“努力的学习”,也就是要不断地挑战自身能力之外的东西。一些狂热的爱好者花费了大量的时间去下棋、打高尔夫球或者玩乐器,但他们可能始终停留在业余水平上,而一个训练有素的学生却可以在相对较短的时间里超越他们,原因就在这里。值得注意的是,在提高水平方面,花费在下棋上的大量时间(即使参加各种比赛)似乎还是比不过专门的训练来得更为有效。训练的主要价值在于发现弱点,并有针对性地进行提高。
“努力的学习”意味着,要常常去处理那些刚好在你能力极限上的问题,也就是那些对你来说有很大可能失败的事情。如果不经历一些失败的话,你可能就不会成长。你必须不断地挑战自我,超越自己的极限。
那样的挑战有时会在工作中碰到,但也未必。将锻炼从职业工作中分离出来,这在编程领域常被人称为“编码套路”(Code Kata)。
Code Kata的概念是由David Thomas提出的,他是《程序员修炼之道:从小工到专家》的作者之一。这个概念主要指的是,针对某一种特定技术或技能进行重复性的练习,从而将其熟练掌握。——译者注
所谓套路,就是一系列的招式。这个概念借鉴于武术。
如果你想要看一些编码套路的例子(也就是努力学习和磨练编程技能的方法),SteveYegge的文章里倒是提出了一些不错的建议。他把它们称作为“实践演练”: 1.写一份自己的简历。把自己所有的相关技能都罗列出来,然后把那些在100年后还用得到的标出来。给每个技能打分,满分为10分。
2.罗列出你所景仰的程序员。尽量包括那些与你一起工作的人,因为你会在工作中从他们身上获取一些技能。记录下他们身上的1 ~ 2个闪光点,也就是你希望自己有所提高的方面。
3.查看维基百科上的“计算机科学”栏目,找到“计算机领域先驱者”这个分类,从这个列表中挑选一个人,阅读他的事迹,并且在阅读时打开任何你感兴趣的链接。
4.花20分钟通读别人的代码。读出色的代码和读糟糕的代码都是有益的,两者都要读,轮流切换。如果你无法感觉出它们之间的区别,可以求助于一位你尊敬的程序员,让他给你展示一下什么是出色的代码、什么是糟糕的代码。把你读过的代码给别人也看看,问问他们的看法。
5.罗列出你最喜欢的10个编程工具——那些你觉得你用得最多、非有不行的工具。随机挑选其中的一个工具,花一个小时去阅读它的文档。在这一个小时里,努力去学习这个工具的某个你不曾意识到的新功能,或者发现某种新的使用方法。
6.想一想,除了编程之外你最擅长什么事情?再想一想,你是通过怎样的锻炼才变得如此熟练和专业的?这对于你的编程工作又有什么启发呢?(怎么把这些经验应用到编程方面?)
7.拿出一叠简历,并和一组面试官在同一个房间里待上一个小时。确保每份简历都至少被3个面试官看过,并且要给出1 ~ 3分的评分。针对那些不同面试官评判大相径庭的简历展开讨论。
8.参与一个电话面试。事后写下你的反馈,抛出你的观点,然后与主持电话面试的人聊一聊,看看你们是否达成了一致的结论。
9.进行一次技术面试,并且被面试的人应该是某个你不太了解的领域里的专家。让他假定听众在该领域里一无所知,因此请他从最基础的讲起。努力去理解他所说的,必要时问一些问题。
10.有机会参与别人的技术面试。期间,你只是认真地听、认真地学。在应聘者努力解决技术问题的同时,你也要在自己脑子里尝试解决这些问题。
11.找到一个能和你交换实际问题的人,每隔一周,相互交流编程问题。花10 ~ 15分钟来尝试解决这些问题,再用10 ~ 15分钟进行讨论(无论能否解决)。
12.当你听到任何你一时之间也无法解决的面试问题时,赶紧回到你的座位上,把这个问题用电子邮件发给自己,以留作日后的提醒。在那一周里找出点时间,用自己最喜欢的编程语言来解决它。
我之所以喜欢Steve开出的这个清单,是因为它看上去很全面。有些程序员一想到“锻炼”,总认为就是一些编码上的难题。但在我看来,编程更在于人,而不是代码。因此,通过解决世上所有的、并且晦涩的编程面试题目,在提高你的个人能力方面,这种方法是有局限的。
关于“努力的学习”,我也很喜欢Peter Norvig在“Teach Yourself Programming in TenYears”(花10年时间自学编程)一文中提出的诸多建议:
1.与别的程序员交流。读别人的代码。这比任何书籍或培训课程都更重要。
2.动手写程序!最好的学习方法就是边做边学。
3.在本科或研究生的课程中学习编程课程。
4.找一些项目来做,并且需要与其他程序员形成团队来合作。在项目的进行过程中,学会辨别最出色的程序员以及最糟糕的程序员。
5.在项目中跟随别的程序员一起工作,了解如何维护那些不是你写的代码,并且学习如何写出利于他人维护的代码。
6.学习多种不同的编程语言,特别是那些与你现在所熟悉的语言有着不同的世界观和编程模型的。
7.了解硬件对软件的影响。知道你的电脑执行一条指令需要多少时间,从内存中取出一个字(在有缓存或没缓存的情况下)需要多少时间,在以太网(或者因特网)上传输数据需要多少时间,从磁盘中读取连续的数据或者在磁盘上跳转到另一个位置需要多少时间,等等。
你还可以从Dave Thomas的21种实用的编码套路中获取灵感(CodeKata.com),或者你更愿意加入一个你家当地的“编程武馆”(CodingDojo.org)。
对于“努力的学习”,我无法像Steve,Peter或者Dave那样提供一个长长的建议列表。我远不如他们有耐心。实际上,在我看来,“编程套路”只需两个招式:
1.写博客。我在2004年初创办了CodingHorror.com博客,作为我自己努力学习的一种形式。它在一开始很不起眼,到后来成为我职业生涯中做过的最重要的一件事。所以,你也应该写博客。最后“闻达于天下”的人,往往就是那些能够有效书写和沟通的人。他们的声音最响亮,是他们在制定游戏规则,并且引领世界的潮流。
2.积极参与著名的开源项目。所有的高谈阔论听起来都很好,但是,你是一个大话王还是一名实干家呢?别光说不练,这个非常重要,因为人们会用你的行动来衡量你,而不是你的言论。努力在公众面前留下些实实在在有用的东西吧,到时候你就可以说,“我在那个项目中出过力。”
当你能编写精彩的代码、并且能用精彩的言辞向世人解释那些代码时,到那时候,我会觉得你已经掌握了最牛的编码套路!
]]>将mongodb的zip解压到不同的文件夹(本文是windows下,linux类似),建立3个节点(1000X是myshard1分片的),注意端口号,启动:
1 2 3 |
|
使用config文件配置,mongo10001节点的内容如下,其他相应修改即可:
1 2 3 4 5 6 7 |
|
仲裁节点(可选,要的话后面还有要addArb)
1 2 3 |
|
将各节点启动后,cmd下连接并执行初始化命令:
1 2 |
|
这个2000X是myshard2分片的3个节点,需要像前面一样配好、启动、执行,不分片可忽略
1 2 |
|
查看状态
1
|
|
仲裁节点(可选,前面没配置就不要add了)
1
|
|
测试在一个节点导入数据后,查看其他节点数据也有了
1
|
|
注意:关于节点的读写操作 在primary节点中添加数据: db.xxxx.insert 如果在secondary备份节点查询,会出现错误:
1
|
|
执行如下语句:
1
|
|
这是因为对于replica set中的secondary节点默认是不可读的,由Secondary来分担读的压力,Primary只承担写操作,通过在连接时指定或者在主库指定slaveOk即可
原来使用单一mongo的,现在要用集群,就把spring xml配置和properties做相应修改:
1 2 3 |
|
[摘录]基本思想就是将集合切分成小块,这些块分散到若干片里面,每个片只负责总数据的一部分;应用程序不必知道
哪片对应哪些数据,甚至不需要知道数据已经被拆分了,所以在分片之前要运行一个路由进程,进程名mongos,这个路由器知道
所有数据的存放位置,所以应用可以连接它来正常发送请求;对应用来说,它仅知道连接了一个普通的mongod;路由器知道和片的
对应关系,能够转发请求到正确的片上;如果请求有了回应,路由器将其收集起来回送给应用。
标签:mongodb
所以,在下面的分片完成后,上面spring data mongodb的集群配置就要改回单一mongo的,注意要连接的是mongos,不是原来那个
好了,这里要有路由节点和config节点
开启config服务器(我配了3个,为了测试有节点挂掉的情况,这只是第1个),使用参数或config文件启动
1 2 |
|
config文件:
1 2 3 4 5 6 |
|
开启mongos服务器,使用参数或config文件启动
1 2 |
|
config文件:
1 2 3 4 5 |
|
启动mongod服务器,上面集群配了3个,启动即可(2000X是myshard2分片的,也启动)
1 2 3 4 5 6 |
|
连接mongos服务器
1 2 3 |
|
然后将10001,10002,10003的mongod交给mongos,添加分片也就是addshard()
两个分片的集群,每个分片3个备份节点
1 2 |
|
片已经集群了,但是mongos不知道该如何切分数据,要在mongos设置片键:
1. 开启数据库分片功能
1 2 |
|
2. 指定集合中分片的片键,这里使用users里的name
1 2 |
|
通过mongos向mongodb插入10w记录
1 2 3 4 5 6 7 8 9 |
|
通过printShardingStatus命令查看mongodb的数据分片情况
1
|
|
每个节点都看看,是不是数据都有了
http://blog.sina.com.cn/s/blog_498e79cc0101115v.html http://www.cnblogs.com/huangxincheng/archive/2012/03/04/2379755.html http://www.cnblogs.com/refactor/archive/2012/08/13/2600140.html
]]>1 2 |
|
wang chaoqun
设置开机启动
1
|
|
启动vsftpd服务
1
|
|
增加新用户ftpuser,设置权限和密码
1 2 3 4 |
|
配置vsftp
1
|
|
内容删掉换成以下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
添加chroot_list文件
1
|
|
内容ftpuser
重启服务service vsftpd restart
防火墙开放21端口
1 2 |
|
添加
1
|
|
重启防火墙服务
1
|
|
解决用户无法进入目录问题,终端执行:
1
|
|
然后重启FTP服务:
1
|
|
先定义好服务器、数据库、各目录、用户名、密码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
|
标签:技术
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
|
1 2 3 |
|
[正文]考虑一下这种场景,你开发了一个应用,它有十分优秀的布局设计,最新的特性以及其它的优秀特点。但是在性能这方面欠缺,不管这个应用如何都会遭到客户拒绝。客户总是期望它们的应用应该有更好的性能。如果你在产品中使用了Tomcat服务器,那么这篇文章就会给你几方面来提升Tomcat服务器的性能。wang chaoqun
感谢ITWorld article给本文提供资源。经过沉思我已经知道了和早期版本相比最新的Tomcat提供更好的性能和稳定性。所以一直使用最新的Tomcat版本。现在本文使用下面几步来提高Tomcat服务器的性能。
1. 增加JVM堆内存大小
2. 修复JRE内存泄漏
3. 线程池设置
4. 压缩
5. 数据库性能调优
6. Tomcat本地库
7. 其它选项
你使用过tomcat的话,简单的说就是“内存溢出”. 通常情况下,这种问题出现在实际的生产环境中.产生这种问题的原因是tomcat使用较少的内存给进程,通过配置TOmcat的配置文件(Windows 下的catalina.bat或Linux下的catalina.sh)可以解决这种问题.这种解决方法是通过增加JVM的栈内存实现的.也就是说,JVM通常不去调用垃圾回收器,所以服务器可以更多关注处理web请求,并要求尽快完成。要更改文件(catalina.sh) 位于”\tomcat server folder\bin\catalina.sh”,下面,给出这个文件的配置信息,
1 2 3 4 |
|
-Xms – 指定初始化时化的栈内存
-Xmx – 指定最大栈内存
在重启你的Tomcat服务器之后,这些配置的更改才会有效。下面将介绍如何处理JRE内存泄漏.
性能表现不佳的另一个主要原因是内存泄漏,正如我之前说过:始终使用最新的tomcat服务器以获得更好的性能和可伸缩性。现在,这句话变成真的。如果我们使用最新的tomcat版本6.0.26及以上就可以解决这个错误,因为它包含了一个监听器来处理JRE和PermGen的内存泄漏。使用的监听器是,
1
|
|
你可以在server.xml文件中找到这个监听器的配置,server.xml位置在“tomcat project folder/conf/server.xml”。接下来,我们将看看如何调整连接属性“maxThreads”。
线程池指定Web请求负载的数量,因此,为获得更好的性能这部分应小心处理。可以通过调整连接器属性“maxThreads”完成设置。maxThreads的值应该根据流量的大小,如果值过低,将有没有足够的线程来处理所有的请求,请求将进入等待状态,只有当一个的处理线程释放后才被处理;如果设置的太大,Tomcat的启动将花费更多时间。因此它取决于我们给maxThreads设置一个正确的值。
1 2 3 4 5 |
|
在上述配置中,maxThreads值设定为“250”,这指定可以由服务器处理的并发请求的最大数量。如果没有指定,这个属性的默认值为“200”。任何多出的并发请求将收到“拒绝连接”的错误提示,直到另一个处理请求进程被释放。错误看起来如下,
1 2 |
|
如果应用提示上述错误,务必检查上述错误是否是由于单个请求花费太长时间造成的,这个问题的原因是这样的,有时候如果数据库连接不释放的话,进程将不会处理其它请求。
根据我的经验,准确值的设定可以通过将应用在在各种环境中测试得出。接下来,我们来看看如何压缩的MIME类型。
Tomcat有一个通过在server.xml配置文件中设置压缩的选项。压缩可以在connector像如下设置中完成,
1 2 3 4 |
|
在前面的配置中,当文件的大小大于等于500bytes时才会压缩。如果当文件达到了大小但是却没有被压缩,那么设置属性compression=“on”。否则Tomcat默认设置是“off”。接下来我们将看看如何调优数据库。
Tomcat性能在等待数据库查询被执行期间会降低。如今大多数应用程序都是使用可能包含“命名查询”的关系型数据库。如果是那样的话,Tomcat会在启动时默认加载命名查询,这个可能会提升性能。另一件重要事是确保所有数据库连接正确地关闭。给数据库连接池设置正确值也是十分重要的。我所说的值是指Resource要素的最大空闲数(maxIdle),最大连接数(maxActive),最大建立连接等待时间(maxWait)属性的值。因为配置依赖与应用要求,我也不能在本文指定正确的值。你可以通过调用数据库性能测试来找到正确的值。
Tomcat的原生库基于Apache可移植运行时(Apache Portable Runtime简称APR),给程序员提供了超强的扩展性和性能,在产品运作中帮助融合原生的服务器技术以展现最佳的性能。想知道安装说明的朋友请参考Tomcat Native Library – (APR) Installation。
这些选项是: 开启浏览器的缓存,这样读取存放在webapps文件夹里的静态内容会更快,大大推动整体性能。 每当开机时,Tomcat服务器应当自动地重启。 一般情况下HTTPS请求会比HTTP请求慢。如果你想要更好的安全性,即使慢一点我们还是要选择HTTPS。
就这么多啦。在这篇文章里,我教给了大家一些提高Tomcat服务器性能的方法。如果你觉得这篇文章有用,或者你对提高Tomcat服务器性能有别的看法,请不要忘记留下宝贵的评论。祝你今天编程愉快!
全文完
另附tomcat5.5-6.0 server.xml参数说明:转:Tomcat Server.xml配置文件
]]>和SQL的对应关系:
WHERE $match (page 281)
GROUP BY $group (page 278)
HAVING $match (page 281)
SELECT $project (page 285)
ORDER BY $sort (page 287)
LIMIT $limit (page 280)
SUM() $sum
COUNT() $sum
join No direct corresponding operator; however, the $unwind (page 290) operator allows for
somewhat similar functionality, but with fields embedded within the document.
场景: 比如按省份城市统计发帖数目,比如按人统计发帖排名:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
标签:mongodb
java driver 官方示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
spring data mongodb,@since 1.3,注意升级
官方例子是对城市人口做统计,group两次(对第一次group的结果再group)
好处在于对结果进行了封装,返回List,注意ZipInfoStats嵌套City,使用nested和bind:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
对应的shell即是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
topic : reply = one to many,按topic(或发布者)分组统计回复数 shell:
1 2 |
|
wang chaoqun
spring-data-mongodb:
1 2 3 4 5 6 |
|
另一个例子:统计提问的回复(有内容的和简单赞踩),按权重计算热度
1 2 3 4 5 6 7 8 |
|
java driver:
1 2 3 |
|
场景:展示发帖或回帖的时间趋势图,或者说按整点显示此小时内的发帖数和回帖数,展示成折线图
创建时间保存的是number long,即date.getTime()的值,key要转成小时,使用new Date(y,m,d,h,0,0,0)
标签:mongodb
spring-data-mongodb:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
需要注意的是:结果存在reply的value字段里,是为了后面构造map好处理;场景不一样的话,先使用shell看看结果
1 2 3 4 |
|
shell:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
======result======
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
|
如果emit修改成
1
|
|
reduce里
1
|
|
结果就会是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
1 2 |
|
1 2 |
|
1 2 3 4 |
|
1 2 |
|
1 2 3 4 5 |
|
1 2 3 |
|
1
|
|
1 2 |
|
1 2 3 4 5 6 |
|
注意:key的顺序,因为MongoDB使用BSON的二进制数据格式
注意:limit的值例如为-5的话等同于5,为0则返回全部,汗
标签:技术
1
|
|
$elemMatch:前2个不对,匹配数组查询要用第3个
1 2 3 |
|
使用where可做运算
1 2 |
|
1 2 3 |
|
要返回限制的记录数量,要使用count(true)或count(非0)
1
|
|
多查一
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
一查多
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
1 2 3 4 5 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
设计需要权衡应用的需求,数据库各项性能指标,数据的获取模式;设计时一直要考虑应用如何使用数据如查询、更新、处理、索引、分片,还要考虑数据自身的内在结构
对照关系型数据库理解几个概念:
表:table vs collection
行:view/row(s) vs json document
索引:index vs index
关联:join vs embedding & linking across documents
分片:partition vs shard wang chaoqun
1、顶级对象,一般使用独立的collection,区别于嵌入
2、线性明细对象如订单里的订单项,一般使用嵌入
3、包含关系的对象通常使用嵌入
4、多对多的关系通常采用引用,dbref
5、只有少量数据的可以单独作为一个collection,这样可以快速缓存到应用服务器内存
6、嵌入对象比顶级对象难引用,至少现在还不能对它使用dbref
7、嵌入对象的获取有时候会比较难,例如各科分数嵌入到学生对象,从所有学生中获取前100个高分,不嵌入会更简单
8、如果嵌入对象数量很多,可以限制其大小
9、性能存在问题(应是查询的性能),使用嵌入
标签:mongodb
如cd,dvd,shipping里有包装尺寸,pricing里有折扣,details有属性或标签之类使用数组(数量不定,也不会很多),尤其像尺寸和属性,mongodb的灵活的优势就显现出来了,rdbms要么加预留字段,tag_1,tag_2之类,要么就得分出个表使用关联
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
页面内容(不经常变化的如联系我们,关于之类),新闻文章(标题,摘要,内容,作者,时间,栏目…),图片(相册或分类,标签,描述,时间,甚至图片文件)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
文件可以保存在数据库,使用BSON对象,但最大不能超过16MB,所以大的文件可以采用GridFS将数据存储在两个collection如这里是cms.assets.files保存基础数据,cms.assets.chunks保存文件数据;
cms.assets.files:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
an example of the GridFS interface in Java
1 2 3 4 5 6 7 8 9 10 11 |
|
标签:技术
有多种实现,平铺式?盖楼式?分页?选择哪种就要看具体需求了;如果未来想切换,成本很高
1、独立collection
2、嵌入,数量要限制
3、不嵌入,桶式存储(每个文档存储N个comments数组,page,count)
也要注意评论里的用户信息,考虑冗余用户id,昵称和头像还是使用dbref关联,区别在于前者性能好些但信息更新比如头像,之前的评论显示的头像就不一致了
官方手册
http://docs.mongodb.org/manual/
官方模式设计文档,有单独pdf,包含一对一,一对多,多对多,树状结构,原子操作,gridFS… http://docs.mongodb.org/manual/data-modeling/
Schema Design Basics – MongoSF Presentation (May 2011) http://www.10gen.com/video/mongosf2011/schemabasics
]]>官网下载setup-x86_64.exe,运行,下一步,到download site选第一个163的镜像,速度快些;下一步到select packages页面,不选不点,直接下一步,会下载安装默认配置的相关包;安装完默认,重新运行setup,选择要用的包,比如下面这些基本需要: 摘录自blog.developwithpassion.com
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
1 2 3 4 5 |
|
安装完成后,应用程序(application)->wine->wine configure稍作配置,也可能会提示download gecko,install 完成即可
把windows/system32下的MFC42.dll msxml.dll msvcp60.dll riched20.dll riched32.dll 这几个文件复制到 ~/.wine/drive_c/windows/system32里,再输入命令:winecfg
安装exe,英文系统会有中文乱码情况
1
|
|
我虚拟了两个centos,一个用make install安装并配置octopress环境,另一个同样方法却不成功,后来用rvm可行,不用yum install ruby 是因为版本过低。
1
|
|
1
|
|
显示版本即成功
1 2 3 4 5 6 7 |
|
下载rubyinstaller安装,devkit解压,然后cmd下 cdd到DevKit path
1 2 3 |
|
出现utf-8错误,使用chcp 1252,再进行上三句,done
标签:技术
然后配置octopress环境,英文下rake成功,有中文(比如文章分类、标签带中文的)不成;
摘录自txgcwm.github.io
在实际使用(rake generate/rake preview)的时候,若blog整体采用了非ascii码的编码格式(比如utf-8)就会出现类似这样的错误:
Liquid error: incompatible encoding regexp match (ascii-8bit regexp with utf-8 string)
其实是由于插件文件plugins/category_list_tag.rb本身是ascii编码所致:
1 2 |
|
category_list_tag.rb中很多地方用到了ruby的正则表达式,而ruby的正则表达式在匹配的时候,默认是按照“代码源文件”的编码格式(在这里是ascii)进行匹配的,而如果blog是utf-8编码的话就会出现上述错误。有两种解决办法:
1. 将category_list_tag.rb转成utf-8格式。
2. 更改category_list_tag.rb中所有的正则表达式声明,加上u选项(u的意思就是以utf-8编码格式来进行匹配)。例如,若原正则表达式是/regexp/, 则改成/regexp/u。
1 2 |
|
wang chaoqun
在本机使用git创建SSH Key
1 2 |
|
//if denied, use ssh-add ~/.ssh/id_rsa
to fix this.
备注: useremail为你注册github用户时的邮箱地址 这时,在系统目录下就会生成一个.ssh文件夹,里面为对应的SSH Key,其中id_rsa.pub是Gighub需要的SSH公钥文件。 将id_ras.pub文件里内容拷贝到Github的Account Settings里的key中。 这样你就可以直接使用Git和Github了.
1 2 3 4 5 6 7 |
|
通过Git从Github上克隆一份Octopress
1 2 3 4 |
|
安装Octopress默认的Theme
1
|
|
//if error: rake aborted!
//You have already activated rake 10.1.0, but your Gemfile requires rake 0.9.2.2.
delete your Gemfile.lock and edit the version of rake specified in your Gemfile to 10.1. Job done
1
|
|
1
|
|
预览效果:
1 2 |
|
然后在浏览器中打开http://localhost:4000
1 2 3 |
|
将博客发布到Github上,输入下面命令:
1
|
|
这样,生成的内容将会自动发布到master分支,并且可以使用 http://username.github.com 访问内容。
将source提交:
1 2 3 |
|
删除之前的添加信息 (配置文件在 ~/octopress/.git/config)
1 2 |
|
在_config.yml尾部添加如下行:
1 2 |
|
在source/_layouts/post.html尾部添加如下代码:
1 2 3 4 5 6 |
|
创建source/_includes/post/duoshuo.html文件,将从多说获得的代码放入其中。 标签:技术
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
打开source/_includes/post/sharing.html,注释掉<div class="share">...</div>
中的AddThis相关语句,然后在</div>
前加入从JiaThis获得的代码。
1 2 |
|
1 2 3 |
|
保存以下代码到plugins/category_list_tag.rb:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
将category加入到侧边导航栏,需要增加一个aside 复制以下代码到source/_includes/asides/category_list.html。
1 2 3 4 5 6 |
|
配置侧边栏需要修改_config.yml文件,修改其default_asides项: default_asides: […, asides/category_list.html, …]
侧边栏添加了文章分类后,英文分类没有问题,点击打开是分类下的文章列表;但中文分类,如云计算、设计模式之类就不行了,网上有各种解决办法,复杂了点;而且我发现新建日志的文件名如果是中文则会转成拼音,文章分类也是,你可以看下public/blog/categories下的文件名;所以如果能把边栏的链接地址改成拼音就行了,rakefile里有rake new_post
代码;查看分析发现和plugins/category_list_tag.rb
的处理类似,
category.gsub(/_|\P{Word}/, '-').gsub(/-{2,}/, '-').downcase
是转换为单词‘-’分隔并且小写,rakefile里是 mkdir_p
"#{source_dir}/#{posts_dir}"
filename = "#{source_dir}/#{posts_dir}/#{Time.now.strftime('%Y-%m-%d')}-#{title.to_url}.#{new_post_ext}"
注意:title多了.to_url
,原来如此,将category_list_tag.rb
里改成
category.gsub(/_|\P{Word}/, '-').gsub(/-{2,}/, '-').downcase.to_url
,
然后rake generate rake preview
done!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
|
标签:技术
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
|
在相应页面的toolbar里添加导出按钮,调用js function,例如:
1 2 3 4 5 6 7 8 |
|
jsUtil里的js逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
标签:java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
jsoup获取本博客文章标题和链接
1 2 3 4 5 6 7 8 9 10 |
|
想必你一定知道浏览器有个标准(Standards)模式和一个怪异(Quirks)模式,或许你还听说过有个“准标准(Almost Standards)”模式。而当你打开 Internet Explorer 的时候,又看到了什么浏览器模式、文档模式,还有什么兼容性视图等等…
这些都是什么?啥是浏览器模式,啥是文档模式?标准模式和准标准的模式有什么区别?IE9兼容性视图和真正的IE9有什么区别?什么情况下会触发这些模式,又该怎样才能检测到浏览器当前处于哪种模式中呢?本文将详细为你解答这些疑问。
首先我们要知道,为什么会有这么多模式。其实这是个历史遗留问题,在浏览器大战时期,网景浏览器(Netscape Navigator)和微软的IE浏览器(Microsoft Internet Explorer)对网页分别有不同的实现方式,那个时候的网页要针对这两种浏览器分别开发不同的版本。而到了 W3C 制定标准之后,这些浏览器就不能继续使用这种页面了,因而会导致大部分现有站点都不能使用。基于这个原因,浏览器才引入两种模式来处理一些遗留的站点。
现在的浏览器排版引擎支持三种模式:怪异(Quirks)模式、准标准(Almost Standards)和标准(Standards)模式。在怪异模式中,排版引擎会模拟 网景4 和 Windows 中的 IE5 的行为;在完全标准的模式中,会尽量执行 HTML 和 CSS 规范所指定的行为;而在准标准模式中,则只包含很少的一部分怪异模式中的行为。
那么所谓标准模式,就一定都“标准”吗?答案当然是否定的,因为各个浏览器厂商实现标准的阶段不同,所以各个浏览器的“标准模式”之间也会有很大的不同。
Firefox、Safari、Chrome、Opera (自 7.5 以后)、 IE8 和 IE9 都有一个准标准模式。那么既然标准模式都不那么标准,准标准的模式肯定就更不标准了。最初的准标准模式只会影响表格中的图像,而后来各个浏览器又或多或少地进行了修改。那么什么情况下会触发准标准模式呢?是的,正如你所想到的,某些 DOCTYPE 会触发准标准模式,例如:
1 2 3 4 5 |
|
一个完整的 DOCTYPE 例子如下:
<!DOCTYPE HTML PUBLIC “–//W3C//DTD HTML 4.01 Transitional//EN”
"http://www.w3.org/TR/html4/loose.dtd">
如果在 Firefox 中插入这种 DOCTYPE,并在页面中插入一个空的 span 标签,那么在 Firebug 中查看元素的布局就会发现不同:
准标准模式中元素的 line-height 被忽略了,元素既没有宽度也没有高度:
Almost Standards
标准模式中元素仍然保留了 line-height,拥有 18px 的高度:
Standards
在 Firefox 浏览器中,使用鼠标右键 –> 查看页面信息 可以看到当前浏览器运行在何种模式(只能看到“混杂模式”和“标准规范模式”两种表示):
mozilla-standard-mode
有位大神 Henri Sivonen 曾写过一篇文章叫做 Activating Browser Modes with Doctype,里面包含了一个完整的表格,展示了各种 DOCTYPE 设置将会使浏览器以何种方式渲染。这里还有一篇 秦歌 的译文 《用doctype激活浏览器模式》。
鉴于目前一些最新版本的浏览器已经放弃了准标准模式,所以关于准标准模式的细节这里就不再赘述了,感兴趣的同学可以详细阅读以下资料:
Gecko’s “Almost Standards” Mode
Line Height Calculations in Almost Standards Mode
Images, Tables, and Mysterious Gaps
almost-standards test
DOCTYPE Switches support in Opera Presto 2.10
那么,既然这么多的 DOCTYPE 都会触发非标准的模式,那么如何才能触发标准模式呢?对了!要使用 HTML5 DOCTYPE,即:
<!DOCTYPE html> 注意:如果文档中没有包含 DOCTYPE 或者包含了一个无法识别的 DOCTYPE,则浏览器就会进入怪异模式。
下面简单说一下怪异模式。怪异模式有许多“怪异”的行为,主要是为了兼容那些遗留的古老页面而保留的模式。不同浏览器的怪异模式也不尽相同,它们都有自己的实现方式。怪异模式与标准模式的差异主要体现在 盒模型(box model)、表格单元格高度的处理等。例如 IE 的怪异模式中,元素的 width 包含了 padding 和 border,而标准模式中 padding 和 border 并不属于宽度的一部分。
若想详细了解浏览器在怪异模式下的行为,可以参看下面两篇文章。不过不建议在这上面花太多的精力,这是个历史遗留问题,而且我们也尽量保证新开发的页面不要进入到怪异模式:
Mozilla Quirks Mode Behavior
What happens in Quirks Mode?
Compatability Mode Test
小结: 至此我们需要了解,浏览器有三种运行模式,即标准模式、准标准模式和怪异模式,要使用 <!DOCTYPE html> 来正确地触发标准模式。千万不要丢掉 DOCTYPE 声明,因为这会导致浏览器进入怪异模式。
IE8有4种模式:IE5.5怪异模式、IE7标准模式、IE8 准标准模式和IE8标准模式,而IE9有7种模式: IE5.5怪异模式、IE7标准模式、IE8准标准模式、IE8标准模式、IE9准标准模式、IE9标准模式、XML模式。
其中 XML模式 是针对 XML 文档的,这里不打算阐述,细节可以看这篇文章Defining Document Compatibility.aspx) 中有详细阐述。
在 IE8 及以后的的 IE 浏览器中,支持 X-UA-Compatible 头,可以通过在服务器端设置 HTTP 头,或者在页面中插入 标签来实现:
1 2 3 4 5 |
|
这种方法主要是防止老的页面在较新的浏览器中显示不正常的情况的, 比如上面的代码可以强制 IE8 以上版本的浏览器以IE7的模式进行渲染。
注意,不要在新开发的网页中使用这种技术,这种技术只应该作为新老网页更替过程中的过渡方案。由于目前新开发的网页都是尽量支持最新版本的浏览器的,所以这种技术也会慢慢被淘汰,感兴趣的同学可以详细阅读 微软的这篇文档。
小结: 这里我们需要知道有这种方式可以强制浏览器以某种模式运行,但只应作为过渡方案,不应在新开发的网页中使用。
如果你使用的是 IE9,那么按下 F12 键就会出现开发者工具,上面有两个下拉菜单:浏览器模式 和 文档模式。那么什么是浏览器模式?什么又是文档模式?二者有何区别?
浏览器模式用于切换IE针对该网页的默认文档模式、对不同版本浏览器的条件注释解析、以及发送给网站服务器的用户代理(User-Agent)字符串的值。网站可以根据浏览器返回的不同用户代理字符串判断浏览器的版本和及安装的功能,这样就可以根据不同的浏览器返回不同的页面内容了。
文档模式用于指定IE的页面排版引擎(Trident)以哪个版本的方式来解析并渲染网页代码。切换文档模式会导致网页被刷新,但不会更改用户代理字符串中的版本号,也不会从服务器重新下载网页。切换浏览器模式的同时,浏览器也会自动切换到相应的文档模式。
一言以蔽之,浏览器模式会影响服务器端对客户端浏览器版本的判断,对条件注释也有影响;而文档模式会影响IE的排版引擎,对网页渲染会有影响,对 CSS hack 也会产生影响。因此,通过条件注释可以判断浏览器模式,而使用 CSS hack 可以判断文档模式。
如果我们使用一句简单的 JavaScript 语句来查看用户代理(User-Agent)字符串的值,则可以看到 IE9 兼容性视图 与 IE9 的区别:
1 2 3 |
|
输出结果如下所示,注意其中的 MSIE 版本号已经不同。判断浏览器模式就是判断 User-Agent 中的版本号,即 MSIE 后面的数值:
// IE9 UA:Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; Tablet PC 2.0)
// IE9 兼容性视图 UA:Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; Tablet PC 2.0) 话说 IE9 兼容性视图 是模拟IE7的行为,那么 IE9 兼容性视图 与 IE7 有没有区别呢?肯定是有区别的,即使是 IE9 中的 IE7标准模式,与原生的IE7在渲染上也是有区别的,具体我们暂不去深究。
那么既然 IE9 兼容性视图 的版本号跟 IE7 相同,如何才能判断当前是 IE9 兼容性视图,还是纯正的 IE7 呢?其实很简单,只需要判断浏览器的用户代理(User-Agent)字符串中是否包含 Trident 即可。首先检测 MSIE 的版本号是否为 7.0,然后再判断是否含有 Trident 字串,若包含则为 IE9 兼容性视图,否则则为纯正的 IE7。
小结: 至此,你应该了解了什么是浏览器模式、什么是文档模式以及它们之间的区别了,另外还了解了 IE9 兼容性视图 与 IE9 以及 IE7 的区别。
当 Internet Explorer 9 遇到未包含 X-UA-Compatible 标头的网页时,它将使用 <!DOCTYPE> 指令来确定如何显示该网页。 如果该指令丢失或未指定基于标准的文档类型,则 Internet Explorer 9 将以 IE5 模式(怪异模式)来显示该网页。
如果 <!DOCTYPE> 指令指定了基于标准的文档类型,则 Internet Explorer 9 将以 IE9 模式显示该网页,但出现以下情况时除外:
为该网页启用了兼容性视图。 该网页是在 Intranet 区域中加载的,并且已将 Internet Explorer 9 配置为使用兼容性视图来显示 Intranet 区域中的网页。 已将 Internet Explorer 9 配置为使用兼容性视图来显示所有网站。 已将 Internet Explorer 9 配置为使用兼容性视图列表(其实是个黑名单,其中指定了一组始终使用兼容性视图显示的网站)。 已使用开发人员工具覆盖在该网页中指定的设置。 该网页遇到了页面布局错误,并且已将 Internet Explorer 9 配置为,通过在兼容性视图中重新打开网页来自动从此类错误中恢复。 此外,可以使用下面的注册表项来控制 Internet Explorer 对未包含 X-UA-Compatible 标头的页面的处理方式。
1 2 3 4 5 6 7 8 |
|
其中 DWORD 值必须等于下列值之一:
值 说明 7000 包含基于标准的 <!DOCTYPE> 指令的页面将以 IE7 模式显示。 8000 包含基于标准的 <!DOCTYPE> 指令的页面以 IE8 模式显示。 8888 页面始终以 IE8 模式显示,而不考虑 <!DOCTYPE> 指令。 (这可绕过前面列出的例外情况。) 关于IE浏览器确定文档模式的整个流程,可以参看这篇文章 How IE8 Determines Document Mode,文中详细阐述了整个流程与内部机制。
小结: 仍然坚持使用 <!DOCTYPE html>,可最大程度减小发生错误的几率。
在 JavaScript 中可以通过 documentMode 来检测文档模式,在 IE6 和 IE7 中是使用 compatMode 来确定文档模式的,这个属性自 IE8 开始已经被 documentMode 所替代。
那么,如果需要兼容 IE6 和 IE7 的话(必须的 …),则相应的检测代码大致如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
IE6 和 IE7 中的 compatMode 有两个可能的值“CSS1Compat”和“BackCompat ”,分别对应了 IE6 和 IE7 中的标准模式和怪异模式。上面的代码首先假定是怪异模式,然后再试图推翻假设。这里没有包含“IE6 标准模式”,因为它已经被 IE7标准模式 所替代,没有模拟的情况。
这里要注意,不同的文档模式对 JavaScript 也有一些影响,我们不必去深究不同文档模式对 JavaScript 有何种不同影响,只需要在编码时进行特定的 特性检测 即可。
小结: 一般情况下是没必要进行文档模式检测的,对于样式兼容我们可以写 CSS hack,而对于 JavaScript 来说,则更加推荐特性检测,而不是检测浏览器本身。
浏览器模式可以决定页面默认的文档模式,但文档模式可能会受其他因素影响而改变,如上文所述。如果浏览器模式与文档模式设置不同的话,会不会有什么影响呢?
我们已经知道浏览器模式主要用于标识浏览器本身,原则上不会对页面渲染产生影响。但是我们又知道,浏览器模式可以影响条件注释,所以如果你的页面中有条件注释的话,那么浏览器模式的变化就会影响到页面渲染。
服务器端只能通过浏览器模式所标识的版本来确定客户端浏览器的版本,如果你将浏览器模式标识为IE9,但文档模式选择为IE7标准的话,就可能会有问题。不过这还要看服务器端是否有针对不同浏览器的处理策略,如果服务器端并未对不同浏览器的输出做差异化处理的话,那么这两个模式选项不同就不会有问题。
小结: 如果服务器端对不同浏览器的输出做了差异化处理,那么浏览器模式和文档模式不一致就可能产生问题。
]]>1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
|
文档规范化正在形成的过程中,具体标准根据项目大小、要求、进度等不同而不同。开发人员写文档的能力向来是个短板,多看多借鉴国标、成熟的开发过程以及其他公司的文档,明白知道各文档所应涵盖的内容,学会并提高文档书写水平,是文档规范化的前提。在此基础之上,再召开会议讨论制定文档规范化模板,制定公司特色的文档体系才是可行的。wang chaoqun
二. 关于需求理解、分析设计
一般来讲,前期与客户沟通的不充分,调研工作不充分而产生需求理解上的偏差(如果排除人员能力水平、方法上的问题的话)是导致接下来分析设计以及开发工作偏差和反复修改的重要原因,并且有损开发人员的工作热情。因此,我提议重视和做好调研和需求分析工作,并在项目开始阶段召开几次分析会议,项目组成员充分讨论,每次会议都要评分,以使项目组员对项目需求和设计的理解程度达到进行开发的要求。
三. 关于项目产出物的管理
如各类文档、各类资料、可复用模块、产品化软件,需要制定出制度和管理流程,以达到规范化管理。涉及到具体的要求和流程,需要先制定出思路和计划,讨论研究。
四. 关于产品化开发和模块复用封装
就现在来看,公司已经积累了若干项目,其中的功能有可以剥离出来封装服用的,同时这项工作也有难度,它很大程度上需要大家有扎实的开发基础,良好的代码编写习惯,要写出逻辑清晰、方便调用的代码来。我的看法是简单的功能可以封装的先完成,以供日常使用;同时讨论、借鉴、探求产品化思路,制定实施规划。
标签:职业
五. 关于项目管理
项目开发过程中经常会出现各种问题,比如在团队建设、人员管理、与客户沟通以及编码开发、测试等各方面,人与人相处,尤其工作当中,难免出现误会争吵,实属正常,对事不对人就好。我所观察,项目开发中最大的矛盾可能是工作量大、时间紧张与开发人员能力、效率不高之间的矛盾了;我们需要可能是较长一段时间继续在项目开发中锻炼和成长;我所担心,无论是技术总监、项目经理、组长还是开发人员,会慢慢成为项目组乃至公司的短板,还是要关注自己,提高自己的能力。
六. 关于技术水平提高
如果最终的需求、产品、网站、系统以及客户给钱都是落在代码上,我们就无法忽略代码的重要性;因为大家每天大部分的时间都在敲代码,如果你珍惜你的时间而不是浪费,你也会去想到底如何才能写出整洁规范的代码,也无法忽略编码水平提高的需要;如果你要修改别人的代码,看到的却像是一地鸡毛,无从下手,影响心情,那你应该想一想你自己的代码是否在别人看也是这样;如何去从源头控制bug数量,提高代码的正确性、健壮性等等,关于代码的很多都是值得我们关注的。我认为代码审查机制是需要的,从规范性着手,从每周或每天的code review开始,改善我们的代码。另外一方面就是购置学习书籍,可以由全体员工积极推荐书目,大家投票决定是否购置,而且不限于技术方面。
七. 关于框架开发
我所计划框架的演进是有一个路线图的,从ibatis+struts,到ssh,到现在ss,以及ssh2或sh等等。实际上,如果项目经理或技术经理一直停留在一个框架上或是从外派公司拿的,只因为他很熟悉,那么势必造成组员技术水平的停滞不前甚至下降。虽然我一直维护框架文档并不时的更新,框架源码去年时候就发布出来,但是很多人没有认真看,遇到问题仍然不知怎样解决。培训时候就学习ssh,现在的开发框架也是ssh,大部分的功能都一样,不客气地讲,不会用的原因就是struts,spring,hibernate基础不牢固。待这几个项目做完,各人对框架应该是很上手加熟悉了,下一步的计划就是在重新开发自己的框架,类似开源项目,每个人都可以开发修改、维护这个框架,当然,前提是代码水平和编码习惯要改善。
另:关于员工职业规划
新员工培训中有职业素养,而对于工作一年和两年以上的员工,职场相关的交流和学习就比较少,如果能让大家成长成一个职业化、专业化、高效能的职业人士会在很大程度上促进公司的发展。
以上七个方面依然是我接下来工作的主要内容,需要按部就班推进执行。
审查年初的工作计划,存在规划粗略、执行的资源如工作时间、人力资源等不足的问题,其中应在接下来的年度继续规划和执行的工作如:
1、规范开发流程,这在项目管理体系中属于组织过程资产,是一个长期积累,不断发展的过程。
2、组织技术培训,是因为公司高度重视对人的培养,并为公司发展战略服务,通过帮助员工提升工作绩效和个人能力,推动员工与公司的共同成长。员工不仅可以选择技术、设计、产品、市场等专业技能发展通道,也可以有项目管理的发展通道。这项工作的开展需要管理层的支持。
3、产品研发的工作无论从技术上还是管理上都不同于普通项目,这方面我们的知识和经验不足,需要一个规划、学习、摸索实践以及积累的过程。
标签:职业
关于项目管理,之前项目管理工作中,如果有项目管理知识体系这些理论作为指导,去开展项目工作,问题会少很多,项目工作的效率和效果也会好很多。现在公司项目管理可改进的方面我认为:
1、客户相关的,涉及到项目范围、变更、沟通等,有效的管理客户是一个值得努力的方向;
2、人力资源相关,如团队建设和管理等,提高团队绩效、个人能力等方面是我们工作中需要关注和努力的。
3、成本和质量相关,需要我们在项目开发工作中重视项目工作的成本和项目完成的质量。
新的一年里,公司面临新的机遇和新的挑战,亟需深耕行业,形成自己的业务体系和战略布局,中级管理层人员更要提高业务和管理能力,为公司发展做出贡献。
]]>1、同步的静态方法,影响类内
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
2、同步的非静态方法,影响实例内
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
标签:多线程
测试示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
|
1 2 3 4 5 6 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
|
标签:算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|