October 12
Restlet 是一个Java下的轻量级REST框架。通过拥抱REST(REST是一种Web架构风格)它模糊了Web站点和Web服务之间的界限,从而帮助开发人员构建Web应用。每一个主要的REST概念(REST concept)都有一个对应的Java类。你的REST化的Web设计和你的代码之间的映射是非常简单直接的。为什么有必要创建另一种框架?难道Servlet API还不够好用吗?Servlet AIP在1998年发布,从那个时候起它的核心设计一直没有很大的变化。它是Java EE的众多API中最成功的一个,但是它的几个设计缺陷和一些限制损害了它。举个例子,URI模式和它的处理者(handler)之间的映射是受限制的,而且其配置都集中在一个配置文件中。还有,它把socket流的控制直接交给了应用系统开发人员,Servlet容器阻碍了我们充分使用NIO特性对IO 操作进行优化。另一个主要问题就是Servlet API鼓励应用开发者在应用或者用户会话级别直接将session状态保存于内存中,尽管这看上去不错,但它造成了Servlet容器扩展性和高可用性的主要问题。为了克服这些问题,就必须实现复杂的负载均衡、session复制、持久化机制。这导致了可扩展性必然成为灾难。
如何看待别的框架中对REST的支持(例如Axis2,或者CXF/XFire)?
这些支持非常有效,但是作用非常有限。我的主要观点是设计这些项目是为了符合WS-*/SOAP Stack,它们与REST世界并不非常契合。在REST世界里,定义了一个全新的范例:面向资源的设计,而非通过远程方法调用这样的范例。例如 Axis2仅仅支持GET和POST两种HTTP方法,它需要远程方法的传递需要一个URI参数。这在REST中式不允许的,这种做法也不能被称之为 REST化。XFire1.2不支持REST,但是它发布了一个项目用于将POJO映射到REST化的Web服务。这有点类似最近发布的JSR-311,此JSR试图基于一套annotation和助手类标准化这种映射。
REST与HTTP协议
REST 软件架构是由Roy Thomas Fielding博士在2000年首次提出的。他为我们描绘了开发基于互联网的网络软件的蓝图。REST软件架构是一个抽象的概念,是一种为了实现这一互联网的超媒体分布式系统的行动指南。利用任何的技术都可以实现这种理念。而实现这一软件架构最著名的就是HTTP协议。通常我们把REST也写作为 REST/HTTP,在实际中往往把REST理解为基于HTTP的REST软件架构,或者更进一步把REST和HTTP看作为等同的概念。今天,HTTP 是互联网上应用最广泛的计算机协议。HTTP不是一个简单的运载数据的协议,而是一个具有丰富内涵的网络软件的协议。它不仅仅能够对于互联网资源进行唯一定位,而且还能告诉我们对于该资源进行怎样运作。这也是REST软件架构当中最重要的两个理念。而REST软件架构理念是真正理解HTTP协议而形成的。有了REST软件架构理念出现,才使得软件业避免了对HTTP协议的片面理解。只有正确的理论指导,才能避免在软件开发的实际工作过程中少走弯路。
REST与URI(资源定位)
REST软件架构之所以是一个超媒体系统,是因为它可以把网络上所有资源进行唯一的定位,不管你的文件是图片、文件Word还是视频文件,也不管你的文件是txt文件格式、xml文件格式还是其它文本文件格式。它利用支持HTTP的TCP/IP协议来确定互联网上的资源。
REST与CRUD原则
REST软件架构遵循了CRUD原则,该原则告诉我们对于资源(包括网络资源)只需要四种行为:创建(Create)、获取(Read)、更新(Update)和销毁(DELETE)就可以完成对其操作和处理了。其实世界万物都是遵循这一规律:生、变、见、灭。所以计算机世界也不例外。这个原则是源自于我们对于数据库表的数据操作:insert(生)、select(见)、update(变)和delete(灭),所以有时候CRUD也写作为 RUDI,其中的I就是insert。这四个操作是一种原子操作,即一种无法再分的操作,通过它们可以构造复杂的操作过程,正如数学上四则运算是数字的最基本的运算一样。
REST与网络服务
尽管在Java语言世界中网络服务目前是以SOAP技术为主,但是REST将是是网络服务的另一选择,并且是真正意义上的网络服务。基于REST思想的网络服务不久的将来也会成为是网络服务的主流技术。REST不仅仅把HTTP作为自己的数据运输协议,而且也作为直接进行数据处理的工具。而当前的网络服务技术都需要使用其它手段来完成数据处理工作,它们完全独立于HTTP协议来进行的,这样增加了大量的复杂软件架构设计工作。REST的思想充分利用了现有的HTTP技术的网络能力。在德国电视台上曾经出现过一个这样的五十万欧元智力题:如何实现网络服务才能充分利用现有的HTTP协议?该问题给出了四个答案:去问微软;WSDL2.0/SOAP1.2;WS-Transfer;根本没有。这个问题告诉我们HTTP并不是一个简单的数据传来传去的协议,而是一个聪明的会表现自己的协议,这也许是REST = Representational State Transfer的真正含义。实际上目前很多大公司已经采用了REST技术作为网络服务,如Google、Amazon等。在Java语言中重要的两个以 SOAP技术开始的网络服务框架XFire和Axis也把REST作为自己的另一种选择。它们的新的项目分别是Apache CXF和Axis2。Java语言也制定关于REST网络服务规范:JAX-RS: Java API for RESTful Web Services (JSR 311)。相信还会出现更多与REST相关的激动人心的信息。
REST与AJAX技术
尽管AJAX技术的出现才不到两年时间,但是AJAX技术遵循了REST的一些重要原则。AJAX技术充分利用了HTTP来获取网络资源并且实现了 HTTP没有的对于异步数据进行传输的功能。AJAX技术还使得软件更好地实现分布性功能,在一个企业内只要一个人下载了AJAX引擎,其它企业内部的人员,就可以共享该资源了。AJAX技术遵守REST准则的应用程序中简单和可伸缩的架构,凡是采用AJAX技术的页面简洁而又丰富,一个页面表现了丰富多彩的形态。AJAX技术还使用了一种不同于XML格式的JSON文件格式,这个意义在哪里呢?在REST软件架构下我们不能对于XML文件进行序列化处理,这样程序员必须要使用自己的XML绑定框架。而以序列化的JavaScript对象为基础的JSON已经获得了广泛认可,它被认为能以远比XML更好的方式来序列化和传输简单数据结构,而且它更简洁。这对REST是一个极大贡献和补充。当前的网络应用软件还违背了REST的"无状态服务器"约束。 REST服务器只知道自己的状态。REST不关心客户端的状态,客户端的状态自己来管理,这是AJAX技术的应用之地。通过AJAX技术,可以发挥有状态网络客户机的优势。而REST的服务器关心的是从所有网络客户端发送到服务器操作的顺序。这样使得互联网这样一个巨大的网络得到有序的管理。
REST与Rails框架
Ruby on Rails框架(简称Rails或者Rails框架)是一个基于Ruby语言的越来越流行的网络应用软件开发框架。它提供了关于REST最好的支持,也是当今应用REST最成功的一个软件开发框架。Rails框架(从版本1.2.x起)成为了第一个引入REST作为核心思想的主流网络软件开发框架。在 Rails框架的充分利用了REST软件架构之后,人们更加坚信REST的重要性和必要性。Rails利用REST软件架构思想对网络服务也提供了一流的支持。从最直观的角度看待REST,它是网络服务最理想的手段,但是Rails框架把REST带到了网络应用软件开发框架。这是一次飞跃,让REST的思想从网络服务的应用提升到了网络应用软件开发。利用REST思想的simply_restful插件已经成为了Rails框架的核心内容。
REST安全性
我们把现有基于SOAP的网络服务和基于REST/HTTP网络服务作个比喻,前者是一种传统的寄信方式,而后者是现代网络的电子邮件方式。要是是寄信和电子邮件都有病毒存在的话,传统的寄信被送到对方就很危险,而电子邮件是开发的,电子邮件供应商比如Google为我们检查了电子邮件是否有病毒。这里并不是说明SOAP网络服务消息包含义病毒,而是说明HTTP是无法处理SOAP信息包究竟好不好,需要额外的软件工具解决这一问题,包括防火墙也用不上和管不了。
REST/HTTP网络服务的信息包可以被防火墙理解和控制。你可以按照操作和链接进行过滤信息包,如你可以规定从外部来的只能读取(GET操作)自己服务器的资源。这样对于系统管理员而言使得软件管理更为简单。REST的安全性还可以利用传输安全协议SSL/TLS、基本和摘要式认证(Basic und Digest Authentication)。除了这些REST自身的安全性功能外,还可以利用像基于信息的Web Services Security(JSR 155)作为REST不错的补充。
Uniform 是一个 Abstract 类,定义了和 HTTPMethod 对应的方法如 get,post,delete,put 等等。子类 Restlet 应该是这个框架的核心类了,restlet 有些像 servlet API,可以得到 application和 context 两个对象,其子类分别为链接器,应用,路由器,查找器,组件和过滤器。核心实现:

October 10
<bean id="communityService"
class="org.springmodules.cache.interceptor.proxy.CacheProxyFactoryBean">
<property name="cacheProviderFacade" ref="oscacheFacade" />
<property name="cachingModels">
<map>
<entry key="loadCommunity">
<bean class="org.springmodules.cache.provider.oscache.OsCacheCachingModel">
<property name="refreshPeriod" value="3600" />
<property name="groups">
<list>
<value>communityinfo</value>
</list>
</property>
</bean>
</entry>
</map>
</property>
<property name="flushingModels">
<map>
<entry key="transferMastership">
<bean class="org.springmodules.cache.provider.oscache.OsCacheFlushingModel">
<property name="groups">
<list>
<value>communityuser</value>
</list>
</property>
</bean>
</entry>
</map>
</property>
<property name="target" ref="communityServiceProxy" />
</bean>
主要是cachingModels、flushingModels和target,通过target指定目标,通过cachingModels指定目标bean中需要缓存的方法,可以为缓存entry指定自动刷新时间和缓存名字,flushingModels是指定在执行那些更新操作的时候会刷新缓存,指定方法名称和要刷新的缓存名称,另有些全局配置都通用没有必要描述。
spring model缓存的实现可以结合ehcache或者oscache都可以,配置方式可以是配置文件也可以是注解都非常灵活,这样就可脱离持久层框架,比如hibernate或则ibatis,当结合使用多种持久层处理方式的时候就显得耦合性得到了解放,最主要持久层可以处理刷新的缓存只是当前执行的实体模块,假如我更新一个人的积分的时候同时需要处理更新这个人的威望,那么结合spring model就可以通过管理业务层方法,对多个实体模块进行缓存管理,有效保证缓存触发多节点数据同步
September 25
try { //写cookie,当前访问用户最近浏览的3个不同的群乐,cookie参数 群乐id、群乐名称
Cookie ck = CookieUtil.getCookie(request, SessionUser.USER_COUMMNITY_KEY);
String ch = "|---|";
String sh = ":::===";
String coding = "gbk";
String charset = "iso-8859-1";
String communityName = new String(community.getName().getBytes(charset), coding);
StringBuffer names = new StringBuffer();
if (null != ck) {
String name2 = URLDecoder.decode(ck.getValue(), coding);
if (!name2.contains(communityName)) {
names.append(community.getId());
names.append(sh);
names.append(communityName);
names.append(ch);
StringTokenizer st = new StringTokenizer(name2, ch);
if (st.hasMoreTokens()) {
names.append(st.nextToken(ch));
names.append(ch);
}
if (st.hasMoreTokens()) {
names.append(st.nextToken(ch));
}
}
if(names.length()<1){
names.append(name2);
}
} else {
names.append(community.getId());
names.append(sh);
names.append(communityName);
names.append(ch);
}
// CookieUtil.writeCookie(response, SessionUser.USER_COUMMNITY_KEY, URLEncoder.encode(names.toString(), coding), 30 * 24 * 60 * 60);
Cookie cookie= new Cookie(SessionUser.USER_COUMMNITY_KEY,URLEncoder.encode(names.toString(), coding));
cookie.setDomain(".yesky.com");
cookie.setMaxAge( 30 * 24 * 60 * 60);
cookie.setPath("/");//设置全局目录可访问
response.addCookie(cookie);
} catch (Exception e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
主要没注意setPath("/");这个方法耽误了很多功夫,设置根目录是为了任何目录可访问这个cookie值,如果不设置的话只能当前目录,和当前目录的子集目录可访问。所以哥们应用中前辈写的cookie是用户登录的就在根,而我是搞定最近浏览帖子,被彻底虐了几天,研究api才发现忽略了这么重要的实现。另外其中会有中文乱码只需要使用加密解密手段正确转换下字符集,然后清除原来乱码的cookie就没什么问题,多测试几次就ok
String urlRegex = "<a[^>]*href=['\"\\s]*([^\\s'\"]+)[^>]*([^>]*)>(.+?)</a>";
Pattern p = Pattern.compile(urlRegex,Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(content);
这个地方m.group()取所有匹配的,m.group(1)、m.group(3)是我要获取的匹配的结果中的一段字符串,然后重点说明m.group(3)网上大多数人使用的(.*?),这个模式的问题就是如果同一行当中出现多个超链接,正则最后匹配成了一个,而把第一个<a 和最后一个</a>之间的内容都当做了标签体,所以使用加号为匹配一次
这个表达式可以取出文本中所有的超链接,并解析出超链接中的访问地址和文本内容
August 28
httpd.exe: Could not reliably determine the server's fully qualified domain name, using 192.168.0.8 for ServerName
host配置不正确,
httpd.conf 中serverName 为 conntsing.yesky.com
host 中 127.0.0.1 conntsing.yesky.com
添加 192.168.0.8 conntsing.yesky.com
后正确启动,问题是由于 ip 地址 与 域名没有正确匹配引起
(OS 10048)通常每个套接字地址 (协议/网络地址/端口) 只允许使用一次: make_sock: could not bind to address 0.0.0.0:80
在运行里输入 cmd 进入DOS命令行窗口
输入命令 netstat -anb
看到80端口 被Thunder5.exe占用
简单配置重写url访问(访问apache根路径重写到百度)
<VirtualHost *:80>
ServerAdmin suncq@staff.chinabyte.com
ServerName conntsing.yesky.com
DocumentRoot E:/
<Directory "E:/">
Options FollowSymLinks
AllowOverride None
Order deny,allow
Allow from all
</Directory>
RewriteEngine on
RewriteRule ^\/$ http://www.baidu.com [R=301,L]
</VirtualHost>