文章分类 » Blog my Blog

JVM堆外内存溢出

一个socket服务网项目,每台机器的线程量3w左右。最后一次更新发布后,出现了一个奇怪的问题,就是运行一段时间之后,jvm的堆外内存就会基本被占用完,需要重启一次服务器才行。为了服务器安全,设置了一个内存使用上限比例,当服务器内存使用比例到达这个数值之后,就不再接收用户的请求,表现出来的现象就是用户无法登陆了。问题很严重。

经过几位高级工程师的讨论和分析,猜测造成这种现象可能的原因有两个:
1.我们的应用中使用了ByteBuffer.allocateDirect ,这种方式会使用堆外内存,但由于线上服务器使用的jdk版本时 6.32之前的一个版本,在此之前的版本中存在堆外内存回收的bug,因此认为可能是这个原因导致了当前问题。
2.jdk工具包中的java.util.zip.Deflater方法会使用堆外内存,同时,这个方法还存在内存释放方面的bug。我们的应用中使用了xmpp,据说这个会很频繁的调用这个方法,有可能是这个原因造成的服务器堆外内存溢出 。

但是堆外内存很难检测,按照文章中的推荐,需要使用工具查看我们的应用中是否有不停的调用这个方法,推荐的工具是google-perftools。这个东西还没怎么用过,需要了解一下怎么安装和使用。尽快把环境部署起来吧。

个人学习总结分析。。。

从开始做开发到现在,真正做前端的时候不多,以前做的也是一些简单的页面,没有什么华丽的效果,绚丽的展现,但是如果能做出这么一个产品是我很大的一个梦想。到目前为止两次动手准备学前端,但是都没怎么坚持下来。毛病有很多,其中一个显著的是,当自己动手的时候,遇到了问题,会去网上找答案,找到了但是记不住。。。偶尔,还会迷失在浩如烟海的大批答案中。

各种各样的问题和不停的低效率的尝试总是非常快的消耗我的耐心和精力,而且少有连续的时间让我能连续的学习(这里是为自己找借口呢。。。)。实际是有时间的,有时候开始学习一点,然后就碰到一些诸如下班,开会等事情打断,一旦打断之后自己就很不容易接上之前的进度而继续学下去。

闲下来的时候,大把的时间也没有花在认真钻研一下某一个框架或者某一个产品上,而是花在了大致浏览其他新闻和新框架、新语言上面。虽然这样表现出自己对很多语言潮流和概念潮流都比较了解,但是并么有精通,导致自己也就嘴上厉害一点,但是做起东西来并不如意,总是各种卡壳,因为有太多细节不知道如何处理和技术功底不足,有些甚至只是一些很初级的东西。

一直有觉得,想要做出来一款产品,想要做私活,想要创业,需要自己也要会前端才行,这样才能做的来。最近自己想了一下,发现那样的话,还是拿自己作为一个开发人员去做,自己做的仍然是最低级的,最可替代的活,仍然不能提升自己的价值。诚然,能够做到高级的技术,也是非常挣钱,但仍然是可计算的,可替代的技术的钱。

因此,我觉得我应该在当前已经熟悉的模块和领域,深入的研究下去,精通这个之后,涉猎其他领域应该也轻松的多,因为大家都是使用的相同的协议而只是用了不同的语言、语法去实现而已。

回归博客

14年4月23日,工作算是告一段落,也有时间做点自己的东西了。
想动手做东西的时候,却发现自己其实已经很久没有动手,同时还导致了自己不但手上疏于联系 ,连脑袋都不怎么转了。既然重新回归,那就继续自己的博客呗。应该没有多少人看,也不想多少人看,作为一个自己记录自己思考与进步的地方,作为一个能让自己肆意放纵的地方,私有一些也许更好。

如果想要做一个网站,或者一个app,总要有个服务器,可是自己的台式机和笔记本又不能随时在线。最近看起来阿里云还凑合,发现有个88元/年的产品,基本已经满足我的需求,果断下手买了。

然后顺便在万网上瞅了一眼,发现之前自己用的那个域名已经由于没人注册,现在已经是空闲状态了,一看价格又不贵(其实是现在手头比较宽裕),于是就与空间一块买了。

公司网速太慢了,捯饬了半天都没能安装好。还是回家后给力,迅速安装完成了wordpress,把以前的日志导入进来。发现确实已经太久没整理了。中间写的一些东西都放在了百度空间里,有时间可以转移过来。

具体自己下面要做个什么东西,暂时心里还没谱,但是总的来说,开始动手了就好。

环境空间支持python应该,将来用这个做服务脚本吧。

暂时先到这儿,太困了。睡觉先。

jQuery中给字符串替换值

jQuery字符串替换

[html]
  1. <head>
  2.         <title>test</title>
  3.         <script type=”text/javascript” src=”./jquery/jquery-1.7.1.js”></script>
  4.         <script type=”text/javascript”>
  5.             $(function(){
  6.                 var $inputValue = $(“#input”).val();
  7.                 re = new RegExp(“‘”,”i”);
  8.                 $inputValue = $inputValue.replace(re, “a”);
  9.                 alert($inputValue);
  10.             });
  11.         </script>
  12.     </head>
  13.     <body>
  14.         <a id=”a”>test</a>
  15.         <input id=”input” type=”text” value=”a”a”>
  16.     </body>

脚本说明:其中RegExp(“‘”,”i”)中第一个参数为你所想替换掉的字符串,第二个参数为替换字符串中第一个所匹配的,第二个参数也可以为”g”,表示替换字符串中所有匹配的字符串。replace(re,”a”)第一个参数为之前的对象,第二个参数为所要替换为的参数。

以上实例结果为:弹出“aa’a”,即为:将<input>的value中第一个匹配的单引号替换为a字符。
以上引自<http://blog.csdn.net/fengspg/article/details/7820165>

JS操作cookie实现单点登录

对于单点域名共享登录信息,我建议使用cookie是比较好的。

用cookie是因为它可以共享信息。
cookie是不能跨域访问的,但是在二级域名是可以共享cookie的。
然后你把你的项目统一平台,域名也统一,这样就可以实现cookie的单点登录了。
比如:http://tieba.baidu.com
http://mp3.baidu.com
这样的就算是统一域名。而二级域名可以共享cookie。
cookie的四个可选属性:
1 cookie的生存期属性:expires;默认情况下,cookie只在浏览器会话期存在.退出浏览器就丢失;可以用expires设置时间;退出浏览器后就不会丢失并存为客户端浏览器的cookie文件;过了时间后cookie失效,还会自动删除cookie文件.
2 path属性:默认情况下,在同一个目录下文件可以调用;
3 domain属性:例如设成”.baidu.com”则在.baidu.com下的所有服务器下的文件都可以调用cookie.
4 安全属性:默认情况下为false;用http协议不安全传输;true:用https等协议安全传输.
Javascript代码

Javascript代码  收藏代码
  1. /**
  2. 函数名称:getCookie
  3. 函数功能:获取指定名称的cookie的值
  4. 输入参数:需要测试的字符串
  5. 返回参数:
  6. */
  7. function getSSOCookie()
  8. {
  9.     var arrStr = document.cookie.split(“; “);
  10.     for(var i = 0;i < arrStr.length;i ++){
  11.         var temp = arrStr[i].split(“=”);
  12.         if(temp[0] == “sso”) {
  13.           return unescape(temp[1]);
  14.         }
  15.     }
  16.     return “”;
  17. }
  18. /**
  19. 函数名称:addCookie
  20. 函数功能:添加cookie
  21. 输入参数:需要测试的字符串
  22. 返回参数:
  23. */
  24. function addSSOCookie(objValue)
  25. {
  26.     var str = “sso” + “=” + escape(objValue);
  27.     if(true){//为0时不设定过期时间,浏览器关闭时cookie自动消失
  28.         str += “; path=/”;
  29.     }
  30.     document.cookie = str;
  31. }
  32. /**
  33. 函数名称:delCookie
  34. 函数功能:删除cookie
  35. 输入参数:需要测试的字符串
  36. 返回参数:
  37. */
  38. function delCookie()
  39. {//为了删除指定名称的cookie,可以将其过期时间设定为一个过去的时间
  40.     var date =  new  Date();
  41.     date.setTime(date.getTime() – 10000);
  42.     document.cookie = “sso” + “=a; expires=” + date.toGMTString()+”; path=/”;
  43. }

用户在统一加载平台认证系统认证通过后,使用addSSOCookie,用户权限信息保存到了cookie中,其他平台通过调用getSSOCookie,取得用户信息。这样用户就可以不再受平台限制,而实现自由访问各个系统了。

在addSSOCookie方法中,没有设置cookie的失效时间,这样在浏览器关闭后,cookie就自动消失。注意:这样cookie的有效性只能在同一浏览器进程,如果重新打开了一个浏览器进程,cookie信息是获取不到的,也就是单点登录只能在同一个浏览器进程有效。如果想在不用浏览器进程中共享cookie信息,那就设置失效时间,如下:
Javascript代码

Javascript代码  收藏代码
  1. function addCookie(objValue,objHours){//添加cookie
  2.            var str = “sso”+ “=” + escape(objValue);
  3.             if(objHours > 0){//为0时不设定过期时间,浏览器关闭时cookie自动消失
  4.                 var date = new Date();
  5.                 var ms = objHours*3600*1000;
  6.                 date.setTime(date.getTime() + ms);
  7.                 str += “; expires=” + date.toGMTString()+”; path=/; domain=.hanj.com”;
  8.             }
  9.             document.cookie = str;
  10.         }

这样cookie在指定的时间后失效。但这样安全性不能保证,如果时间设置太短,用户在使用中,可能cookie就失效了,需要重新登录。如果时间过长,用户在下次访问,或电脑重起访问,cookie还在有效期中,有可能别其他人使用。cookie不能准确的删除,存在安全隐患。

java使用sql之使用for update锁定表

一:

1>首先for update是对表的行进行锁定。锁定就好比我们学java Thread那一章时,为某个线程的run()枷锁,当实例化出来多个线程时,它必须一个线程全部执行完后,释放锁其他线程才有机会运行。本文for update功能上一样,就是为一个select语句枷锁,这样在对这个表进行update ,delete时就会处于等待状态,等待selec执行commit或rollback(相当于线程释放锁)后,才可以对表进行更改或删除。

怎样看效果呢?1:首先在“运行”–>cmd–>连接数据库 执行select * from emp for update

2 :然后在打开另一个窗口(就相当于创建了两个用户):“运行”–>cmd–>连接数据库  执行update emp set sal=100;你会发现它不执行了。

2>那马for update与for update of 有神马区别呢?

1.select * from Table1 for update 锁定表的所有行,只能读不能写

2  select * from Table1 where id = 1 for update 只锁定id=1的行

3  select * from Table1 a join Table2 b on a.id=b.id for update 锁定两个表的所有记录

4 select * from Table1 a join Table2 b on a.id=b.id where a.id = 10 for update 锁定两个表的中满足条件的行

5. select * from Table1 a join Table2 b on a.id=b.id where a.id = 10 for update of a.id 只锁定Table1中满足条件的行

for update 是把所有的表都锁点 for update of 根据of 后表的条件锁定相对应的表

3>关于oracle:select…for update of columns

按照1>步骤执行1:select * from emp for update of sal在另一个窗口中执:2:update emp set job=’clerk’ where empno=10;按照2>的的思维我们可能认:“1”只锁定了emp表的sal列,其实不然当运行“2”时,我们发现它任然不执行,所以for update of columns 是锁定的与sal相关的行。那么for update 与for update of 有神吗区别呢?区别在于多表连接时;

例如:

按照1>分别执行 select ename,dname from emp,dept where emp.deptno=dept.deptno for update;

另一窗口执行:update dept set dname=’haha’where deptno=10;我们发现dept表不能更改

当我们在 select ename,dname from emp,dept where emp.deptno=dept.deptno for update of sal;时

update dept set dname=’haha’where deptno=10;可以在执行了。

由此我们可以综结出:for update of columns 用在多表连接锁定时,可以指定要锁定的是哪几张表,而如果表中的列没有在for update of 后面出现的话,就意味着这张表其实并没有被锁定,其他用户是可以对这些表的数据进行update操作的。这种情况经常会出现在用户对带有连接查询的视图进行操作场景下。用户只锁定相关表的数据,其他用户仍然可以对视图中其他原始表的数据来进行操作。

4>关于nowait与wait

SELECT … FOR UPDATE [OF column_list][WAIT n|NOWAIT][SKIP LOCKED];
1:其中:

OF 子句用于指定即将更新的列,即锁定行上的特定列。

NOWAIT不进行等待,如果这条语句的锁没被释放,则会直接报出:系统资源正忙
WAIT 子句指定等待其他用户释放锁的秒数,防止无限期的等待。
“使用FOR UPDATE WAIT”子句的优点如下:
1防止无限期地等待被锁定的行;
2允许应用程序中对锁的等待时间进行更多的控制。
3对于交互式应用程序非常有用,因为这些用户不能等待不确定
4 若使用了skip locked,则可以越过锁定的行,不会报告由wait n 引发的‘资源忙’异常报告 :

2:现在执行如下操作:

在plsql develope中打开两个sql窗口, 在1窗口中运行sql
select * from t where a=’1′ for update;
在2窗口中运行sql1
1. select * from t where a=’1′; 这一点问题也没有,因为行级锁不会影响纯粹的select语句
再运行sql2
2. select * from t where a=’1′ for update; 则这一句sql在执行时,永远处于等待状态除非窗口1中sql 被提交或回滚。
如何才能让sql2不等待或等待指定的时间呢? 我们再运行sql3
3. select * from t where a=’1′ for update nowait; 则在执行此sql时,直接报资源忙的异常。
若执行 select * from t where a=’1′ for update wait 6; 则在等待6秒后,报 资源忙的异常。 如果我们执行 sql4
4. select * from t where a=’1′ for update nowait skip Locked; 则执行sql时,即不等待,也不报资源 忙异常。
现在我们看看执行如下操作将会发生什么呢?
在窗口1中执行:
select * from t where rownum<=3 nowait skip Locked;
在窗口2中执行:
select * from t where rownum<=6 nowait skip Locked;
select for update 也就如此了吧,insert、update、delete操作默认加行级锁,其原理和操作与select for update并无两样。
select for update of,这个of子句在牵连到多个表时,具有较大作用,如不使用of指定锁定的表的列,则所有表的相关行均被锁定,若在of中指定了需修改的列,则只有与这些列相关的表的行才会被锁定.

二:

1:

如果你想删除或者更新被Select For Update引用的记录,你可以使用Where Current Of语句

 

[sql]
  1. DECLARE
  2.   CURSOR CUR_NAME IS
  3.     SELECT * FROM EMP WHERE deptno=10 FOR UPDATE OF sal;
  4. BEGIN
  5.   FOR REC IN CUR_NAME LOOP
  6.     UPDATE EMP SET sal =100 ;
  7.   END LOOP;
  8. END;

上述pl/sql执行过之后我们发现emp表中所有的sal列数据都被更改,此时我们只想更改跟游标对应的行,所以我们又到where current of执行游标遍历时的当前行就好像for(int i=0;i++;i<10){}where current of与“i”的功能相似。所以当我们想执行游标影响的行时,上我们可以把上面pl/sql快改为:

 

[sql]
  1. DECLARE
  2.   CURSOR CUR_NAME IS
  3.     SELECT JOB FROM EMP WHERE deptno=10 FOR UPDATE OF sal;
  4. BEGIN
  5.   FOR REC IN CUR_NAME LOOP
  6.     UPDATE EMP SET sal =100 WHERE CURRENT OF CUR_NAME;
  7.   END LOOP;
  8. END;

Struts1开发流程描述

我们在这篇文章将会一步一步的讲解Struts的应用,以这样的形式打开Struts一道道神秘的大门,通过这样的过程,相信也能激起你在应用开发中如何应用Struts的灵感。如果你对Struts的一些术语不是很清楚的话,可以参考本系列前一篇对Struts作大体介绍的文章。
再次重复一遍,本文需要读者有如下几方面的知识和经验:JSP,Servlets,自定义标签库(CustomTaglibraries)和XML。此外,在本文中,我还会用到Jakarta项目组其他一些好东东,比如Tomcat(实现Servlet和JSP官方标准的Servlet容器,通俗的讲就是一个JSP的Web啦)和Ant(基于Java的自动编译发布工具,这可是好东东啊)。
作为一名一直使用前沿技术开发了诸多应用的技术人员,我一直坚信掌握新技术,理解该技术开发的逻辑是至关重要的。但这往往就是陷住我们学习步伐的泥潭,正因如此,我打算将利用Struts开发的一套完整流程作为我们教学的案例。该流程的这个案例可谓“麻雀虽小、五脏据全”,你完全可以将这个流程应用到你手头那些复杂庞大的项目中,至少在我们的大项目中应用这个流程效果不错。
有开发复杂商业应用的开发人员都知道,客户的需求总是在不停变幻,所以如果有一套规范的开发流程来遵循,当客户提出新的需求时,我们至少可以明确哪些“无理”需求其实是合理可行的。好,接下里我将在我的这个例子中向各位展示和应用整个流程。
本文中的示例代码是StrutsSample应用中的一部分,包括build.xml的完整代码可以到此处http://www.onjava.com/onjava/2001/10/31/examples/StrutsPartII.jar下载。
Struts开发过程
从Struts发布的版本号可以看出,Struts是个新玩意,她有好几个部分组成,明智的你如果搞清楚了何时该开发完成合适的部分,那将会更好的利用我们的开发时间。从我所开发的几个利用Struts应用中,我大致总结出如下这个比较有效的开发步骤:
1,明确应用需求;
2,由用户输入和获取数据的角度出发,明确和设计出每一个用户界面;
3,确定用户界面的进入路径;
4,由应用逻辑确定动作映射表;
5,由设计完成的用户界面开发其所用到的类和应用函数;
6,由用户界面中的数据开发ActionForm和相应的数据校验方法;
7,ActionMapping中将会被调用相应的Action或转到相应的JSP页面,这一步我们先开发这些Action;
8,开发商业应用逻辑,就是相应的JavaBean、EJB或其他东东;
9,开发由ActionMapping定义的系统工作流程完成对应的JSP页面;
10,完成系统:struts-config.xml和web.xml;
11,编译/测试/发布。
明确应用需求
开发任何应用系统的第一步就是收集用户需求。不管一个用户逻辑初看上去多么合理,但总有可能在开发时才发现它比看上去要难得多。所以,建议拟一份明确的用户需求列表,这不只是出于开发的目的,还能通过该表分析用户需求以确定哪些地方可能需要花更多的精力。
在我们这个StrutsSample项目中,应用需求就是:
作为一个展示Struts框架应用的完整例子,本示例完成的功能是用户登录。目的只为明确Struts的应用,本示例将不会涉及到一般复杂应用系统中可能应用的安全、、EJB开发等等相关技术。
设计用户界面
这个应用中,包括如下三个用户界面:
1)登录界面,用于用户名和密码输入;
2)当登录用户为合法用户时的欢迎界面;
3)当登录失败时的错误提示界面。
确定用户界面的进入路径
1)登录界面作为这个应用的默认页面;
2)欢迎界面只有当成功登录后才能进入;
3)任何可能发生错误的页面能可以进入错误提示界面;
由应用逻辑确定ActionMapping
ActionMapping为整个应用确定的“线路图”,在配置文件struts-config.xml对ActionMapping进行定义,通过转发请求(forward)来理顺应用的处理流程,确定应用中每个用户请求对应的动作。
通常我们在开发过程中就逐步确定了ActionMapping所需的,开发代码的过程就是在由草稿开始一步步完善struts-config.xml的过程。当Action类处理完用户请求后,其返回的的forward就是在ActionMapping中定义的一个。一个Action返回的forward完全有多种可能,尽管一个Action一般只定义其相关的几个forward。那么,如果有多个Action都可能返回的同一个forward,那么就可以将其定义为全局转发(globalforward)。这类似于C中的头文件中全局变量,如果在struts-config.xml描述中,某一个forward并不是在当前Action描述中定义的而是全局定义的,那么这个全局的将起作用,同样,一个Action中当前定义的forward将覆盖全局定义。在我们所给的这个简单实例中,我们定义了全局forward――“error”,当某Action返回的forward是“error”这个映射,那么Errorpage.jsp页面将会显示给用户,尽管当前Action并没有对其定义。
我们继续不断的开发,项目日渐完善,项目相关的配置文件也会越来越详细。在下面的例子中,我们将以StrutsSample中用到的struts-confug.xml文件为例,学习globalforward和一个Action中相关映射的定义。下面定义了一个名为“login”的Action,其为com.oreilly.actions.LoginAction的实例,当Action处理用户登录成功后将一个名为”success”的forward返回,用户也就会看到Welcome.jsp页面,如果登录失败,Action将返回对应的forward以再显示Login.jsp给用户,而如果处理过程中发生其他错误,Action将返回全局定义的forward――“error”,用户也就会看到错误提示页面Errorpage.jsp。
元素的相关属性–>
以下只列出常用属性,其他请参考org.apache.struts.action.ActionMapping的相关文档
path-当前Action对应的用户请求URI路径
type-实现当前Action的Javaclass的完整名字
name-当前Action中用到的ActionForm的名字,其具体在配置文件其他地方另有详细定义
unknown-如果将该属性设置为true,那么就是声明这个Action将处理整个应用中所有未找到相应处理Action的请求,当然,一个应用系统中也只会有一个Action的unknown属性可以设为true
scope-Action中所用到的ActionForm的生存期,可以为“request”或“session”,随着生存期的设置,该Action也会在相应的时间被创建
input-该Action中相关ActionForm获取用户输入的输入页面,当将ActionForm设为自动验证输入数据,发现不合法数据返回错误时,将返回该页面
validate-如果本属性为true则在Action动作之前其对应的ActionForm的validate方法会自动被调用,一般用以验证用户输入的数据
forward元素-定义当前Action相关的ActionForward
–>
type=”com.oreilly.actions.LoginAction”
name=”loginForm”
scope=”request”
input=”/Login.jsp”>
在前一篇文章中,我们曾说过,struts-config.xml就是MVC模式的的Controller。在确定struts-config.xml中的配置时,应该多花些时间精力在上面,以保证每一个Action定义及其相关定义是符合应用的需求的。如果在项目开始没有详细的设计其定义,当将所有代码和配置集成到一起的时候,我们将不可避免的将各部分的代码和配置完全重新组织一遍。
我们当前的例子StrusSample因为只是处理用户登录,所以只需要一个Action。一个应用系统中所要用到的Action的多少完全依应用的大小而定。一旦整套Action的映射完全的定义出来后,我们就可以一个一个开发其具体实现的Action和ActionForm类,并逐渐将完成的部分一点一点集成起来。
由设计完成的用户界面开发其所用到的类和应用函数
所有ActionForm的实现类都是org.apache.struts.ActionForm的子类。一个ActionForm是与页面上的输入表单相关联的,而且ActionForm的实现还可以对用户输入数据的合法性进行验证。作为一个JavaBean,ActionForm有Set和Get方法,当一个页面中表单被提交时,系统将自动调用Set方法将数据放入ActionForm中,而Get方法将为在Action中操作这些数据所提供。一般来说,处理表单中的所有数据,并进行合法性验证都完全可以交由ActionForm来完成。在应用中,就我个人而言,倾向于将ActionForm和Action划分到不同的包中,因为当一个页面中要用到几对ActionFrom和Action时,都放在一个包内会混淆的。

spring之面向切面编程(AOP)PointCut匹配法则说明

Pointcut 是指那些方法需要被执行”AOP”,是由”Pointcut Expression”来描述的.
Pointcut可以有下列方式来定义或者通过&& || 和!的方式进行组合.
args()
@args()
execution()
this()
target()
@target()
within()
@within()
@annotation
其中execution 是用的最多的,其格式为:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)
returning type pattern,name pattern, and parameters pattern是必须的.
ret-type-pattern:可以为*表示任何返回值,全路径的类名等.
name-pattern:指定方法名,*代表所以,set*,代表以set开头的所有方法.
parameters pattern:指定方法参数(声明的类型),(..)代表所有参数,(*)代表一个参数,(*,String)代表第一个参数为任何值,第二个为String类型.
举例说明:
任意公共方法的执行:
execution(public * *(..))
任何一个以“set”开始的方法的执行:
execution(* set*(..))
AccountService 接口的任意方法的执行:
execution(* com.xyz.service.AccountService.*(..))
定义在service包里的任意方法的执行:
execution(* com.xyz.service.*.*(..))
定义在service包和所有子包里的任意类的任意方法的执行:
execution(* com.xyz.service..*.*(..))
定义在pointcutexp包和所有子包里的JoinPointObjP2类的任意方法的执行:
execution(* com.test.spring.aop.pointcutexp..JoinPointObjP2.*(..))”)
***> 最靠近(..)的为方法名,靠近.*(..))的为类名或者接口名,如上例的JoinPointObjP2.*(..))

pointcutexp包里的任意类.
within(com.test.spring.aop.pointcutexp.*)
pointcutexp包和所有子包里的任意类.
within(com.test.spring.aop.pointcutexp..*)
实现了Intf接口的所有类,如果Intf不是接口,限定Intf单个类.
this(com.test.spring.aop.pointcutexp.Intf)
***> 当一个实现了接口的类被AOP的时候,用getBean方法必须cast为接口类型,不能为该类的类型.

带有@Transactional标注的所有类的任意方法.
@within(org.springframework.transaction.annotation.Transactional)
@target(org.springframework.transaction.annotation.Transactional)
带有@Transactional标注的任意方法.
@annotation(org.springframework.transaction.annotation.Transactional)
***> @within和@target针对类的注解,@annotation是针对方法的注解

参数带有@Transactional标注的方法.
@args(org.springframework.transaction.annotation.Transactional)
参数为String类型(运行是决定)的方法.
args(String)
Pointcut 可以通过Java注解和XML两种方式配置,如下所示:

  1. <aop:config>
  2.     <aop:aspectrefaop:aspectref=”aspectDef”>
  3.         <aop:pointcutidaop:pointcutid=”pointcut1″expression=”execution(* com.test.spring.aop.pointcutexp..JoinPointObjP2.*(..))”/>
  4.         <aop:before pointcut-ref=”pointcut1″ method=”beforeAdvice” />
  5.     </aop:aspect>
  6. </aop:config>
  7. @Component
  8. @Aspect
  9. public class AspectDef {
  10.     //@Pointcut(“execution(* com.test.spring.aop.pointcutexp..JoinPointObjP2.*(..))”)
  11.     //@Pointcut(“within(com.test.spring.aop.pointcutexp..*)”)
  12.     //@Pointcut(“this(com.test.spring.aop.pointcutexp.Intf)”)
  13.     //@Pointcut(“target(com.test.spring.aop.pointcutexp.Intf)”)
  14.     //@Pointcut(“@within(org.springframework.transaction.annotation.Transactional)”)
  15.     //@Pointcut(“@annotation(org.springframework.transaction.annotation.Transactional)”)
  16.     @Pointcut(“args(String)”)
  17.     public void pointcut1() {
  18.     }
  19.     @Before(value = “pointcut1()”)
  20.     public void beforeAdvice() {
  21.         System.out.println(“pointcut1 @Before…”);
  22.     }

java_memcached-release 关键类及方法整理

java_memcached-release 关键类及方法整理说明如下。
SockIOPool
  这个类用来创建管理客户端和服务器通讯连接池,客户端主要的工作包括数据通讯、服务器定位、hash 码生成等都是由这个类完成的。
1.public static SockIOPool getInstance()
  获得连接池的单态方法。这个方法有一个重载方法getInstance( String poolName ),每个poolName 只构造一个SockIOPool 实例。缺省构造的poolName 是default。如果在客户端配置多个memcached 服务,一定要显式声明poolName。
2.public void setServers( String[] servers )
  设置连接池可用的cache 服务器列表,server 的构成形式是IP:PORT(如:127.0.0.1:11211)
3.public void setWeights( Integer[] weights )
  设置连接池可用cache 服务器的权重,和server 数组的位置一一对应其实现方法是通过根据每个权重在连接池的bucket 中放置同样数目的server(如下代码所示),因此所有权重的最大公约数应该是1,不然会引起bucket 资源的浪费。
4.public void setInitConn( int initConn )
  设置开始时每个cache 服务器的可用连接数
5.public void setMinConn( int minConn )
  设置每个服务器最少可用连接数
6.public void setMaxConn( int maxConn )
  设置每个服务器最大可用连接数
7.public void setMaxIdle( long maxIdle )
  设置可用连接池的最长等待时间
8.public void setMaintSleep( long maintSleep )
  设置连接池维护线程的睡眠时间 设置为0,维护线程不启动 维护线程主要通过log 输出socket 的运行状况,监测连接数目及空闲等待时间等参数以控制连接创建和关闭。
9.public void setNagle( boolean nagle )
  设置是否使用Nagle 算法,因为我们的通讯数据量通常都比较大(相对TCP 控制数据)而且要求响应及时,因此该值需要设置为false(默认是true)
10.public void setSocketTO( int socketTO )
  设置socket 的读取等待超时值
11.public void setSocketConnectTO( int socketConnectTO )
  设置socket 的连接等待超时值
12.public void setAliveCheck( boolean aliveCheck )
  设置连接心跳监测开关。 设为true 则每次通信都要进行连接是否有效的监测,造成通信次数倍增,加大网络负载,因此该参数应该在对HA 要求比较高的场合设为TRUE,默认状态是false。
13.public void setFailback( boolean failback )
  设置连接失败恢复开关 设置为TRUE,当宕机的服务器启动或中断的网络连接后,这个socket 连接还可继续使用,否则将不再使用,默认状态是true,建议保持默认。
14.public void setFailover( boolean failover )
  设置容错开关 设置为TRUE,当当前socket 不可用时,程序会自动查找可用连接并返回,否则返回NULL,默认状态是true,建议保持默认。
15.public void setHashingAlg( int alg )
  设置hash 算法 alg=0 使用String.hashCode()获得hash code,该方法依赖JDK,可能和其他客户端不兼容,建议不使用 alg=1 使用original 兼容hash 算法,兼容其他客户端; alg=2 使用CRC32 兼容hash 算法,兼容其他客户端,性能优于original 算法; alg=3 使用MD5 hash 算法采用前三种hash 算法的时候,查找cache 服务器使用余数方法。采用最后一种hash 算法查找cache 服务时使用consistent 方法。
16.public void initialize()
  设置完pool 参数后最后调用该方法,启动pool。
MemcachedClient
1.public void setCompressEnable( boolean compressEnable )
  设定是否压缩放入cache 中的数据 默认值是ture 如果设定该值为true,需要设定CompressThreshold
2.public void setCompressThreshold( long compressThreshold )
  设定需要压缩的cache 数据的阈值 默认值是30k
3.public void setPrimitiveAsString( boolean primitiveAsString )
  设置cache 数据的原始类型是String .默认值是false 只有在确定cache 的数据类型是string 的情况下才设为true,这样可以加快处理速度。
4.public void setDefaultEncoding( String defaultEncoding )
  当primitiveAsString 为true 时使用的编码转化格式 默认值是utf‐8 如果确认主要写入数据是中文等非ASCII 编码字符,建议采用GBK 等更短的编码格式
5.cache 数据写入操作方法
5.1.set 方法
  将数据保存到cache 服务器,如果保存成功则返回true 如果cache 服务器存在同样的key,则替换之 set 有5 个重载方法,key 和value 是必须的参数,还有过期时间,hash 码,value 是否字符串三个可选参数
5.2.add 方法
  将数据添加到cache 服务器,如果保存成功则返回true 如果cache 服务器存在同样key,则返回false add 有4 个重载方法,key 和value 是必须的参数,还有过期时间,hash 码两个可选参数
5.3.replace 方法
  将数据替换cache 服务器中相同的key,如果保存成功则返回true如果cache 服务器不存在同样key,则返回false replace 有4 个重载方法,key 和value 是必须的参数,还有过期时间,hash 码两个可选参数 建议分析key 的规律,如果呈现某种规律有序,则自己构造hash 码,提高存储效率
6.cache 数据读取操作方法
  使用get 方法从cache 服务器获取一个数据 如果写入时是压缩的或序列化的,则get的返回会自动解压缩及反序列化 get 方法有3 个重载方法,key 是必须的参数,hash 码和value是否字符串是可选参数 .

配置ant

Windows 下的安装和配置

安装步骤:

  1. 下载最新版本,ANT官方网站: http://ant.apache.org/ 下载后解压缩即可。
  2. 配置环境变量:

打开环境变量配置窗口可以通过下面步骤打开:我的电脑(Vista之后叫 计算机) –> 右键属性菜单点击 –> 高级(Vista之后是 高级系统设置) –>  点击环境变量按钮(如下图:)

image

然后在随后出现的环境变量窗口中的系统变量这里,增加下面的两个设置:

image

  • ANT_HOME:C:apache-ant-1.7.1                 (这里为你自己解压缩的目录)
  • PATH:%ANT_HOME%bin                          (这个设置是为了方便在dos环境下操作)

 

完成上述步骤,就安装完毕。

 

查看是否安装成功。

在dos窗口中输入命令ant,若出现结果:
Buildfile:build.xml does not exist!
Build failed
说明ant安装成功!因为ant默认运行build.xml文件,这个文件需要我们建立。

 

一个简单的使用ANT的例子

在 D 盘根目录下新建一个 build.xml 文件,文件的内容如下:

<?xml version="1.0" encoding="GBK"?>
<project name="测试脚本" default="copyfile" basedir="." >
   <target name="copyfile">
      <copy file="d:/a.txt" todir="e:/Temp" overwrite="true" />
   </target>
</project>

在 D 盘根目录下新建一个 a.txt 文件,内容随便。

进入DOS,依次执行:

d:
ant

如同下面的截图:

image

执行完毕后,我们会在 e:/Temp 目录下看到 a.txt 文件,跟D盘根目录下的完全一样,即Copy成功。

 

 

如果中间提示类似如下错误:

Unable to locate tools.jar. Expected to find it in C:Program FilesJavajre6libtools.jar

这是因为JDK 的安装有问题或者是 JAVA_HOME 环境变量没有设置或者设置有问题, jre下肯定没tools.jar。