海水正蓝

面朝大海,春暖花开
posts - 145, comments - 29, trackbacks - 0, articles - 1
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

是自己编写的一个jar文件,每次添加单个jar到maven本地仓库的操作如下:

1.建立一个新的文件夹,将jar文件存放在该文件夹下。
  注意文件夹下最好只存放该文件。
2.在该文件夹下建立一个pom.xml文件,在pom文件中定义其maven坐标。
3.在cmd窗口中执行以下命令:
  mvn install:install-file -Dfile=<path-to-file> -DgroupId=<group-id> -DartifactId=<artifact-id> -Dversion=<version> -Dpackaging=<packaging>

例如
mvn install:install-file -Dfile=/home/xx.jar -DgroupId=xx -DartifactId=xx -Dversion=1.0 -Dpackaging=jar

posted @ 2012-08-03 16:51 小胡子 阅读(4521) | 评论 (1)编辑 收藏

     摘要: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  1 using System;  2 using System.Collections.Generic; &n...  阅读全文

posted @ 2012-08-01 22:52 小胡子 阅读(507) | 评论 (0)编辑 收藏

http://hb.qq.com/a/20110624/001008.htm
http://blog.163.com/popfei3707@126/blog/static/12297648420107542344500/
http://www.iteye.com/problems/30192
http://hi.baidu.com/guorabbit/item/dddca00b7521eb813d42e279

posted @ 2012-07-31 13:03 小胡子 阅读(222) | 评论 (0)编辑 收藏

修改
apache-tomcat-6.0.33\bin\catalina.bat 文件

@echo   off
if   "%OS% "   ==   "Windows_NT "   setlocal
rem   ---------------------------------------------------------------------------
rem   Start   script   for   the   CATALINA   Server
rem
rem   $Id:   startup.bat,v   1.4   2002/08/04   18:19:43   patrickl   Exp   $
rem   ---------------------------------------------------------------------------
set   JAVA_HOME=c:\jdk
set   CATALINA_HOME=c:\apache-tomcat-6.0.33

rem   Guess   CATALINA_HOME   if   not   defined
if   not   "%CATALINA_HOME% "   ==   " "   goto   gotHome

JAVA_HOME=c:\jdk
set   CATALINA_HOME=c:\apache-tomcat-6.0.33   中
c:\jdk   是你jdk工具包的目录,
c:\apache-tomcat-6.0.33  是tomcat 安装目录

posted @ 2012-07-31 10:49 小胡子 阅读(260) | 评论 (0)编辑 收藏

 表单是网站中重要的交互元素,用最直接有效的方式取得用户的输入数据。但多数表单都不是友好的,代表着繁重的输入工作,表单切换,烦人的格式提醒,漏填警告等。如何让表单变得更为别致和友好,让用户减少反感和枯燥感。本文选择了一些希望可以带给你灵感的应用。

Awesome

forms06

forms07

Foundation Six

forms09
forms10

Wanken

forms13
forms14

Visual Republic

forms15
forms16

Andrew McClintock

forms17

Chris Woods

forms18

bio-bak

forms19

Vincent Mazza

forms20

Ed Peixoto

forms21

Christian Sparrow

forms22

olga designs

forms23

Krista Ganelon

forms24

Forever Heavy

forms25

Cornerd

forms26
forms27

Justdot

forms28
forms29

sikbox

forms30

Justalab

forms31
forms32

Buffalo

forms33
forms34

Sprocket House

forms35

Gardener & Marks

forms36

Pentagon

forms11
forms12

Gams

forms08

All Creative

forms01

forms02

Creditable

forms03

Gowalla

forms04

forms05

原文:http://webdesignledger.com/inspiration/25-excellent-examples-of-forms-in-web-design

 

作   者:孟晨
出   处:http://www.cnblogs.com/xiaoyao2011/
个人站:  http://www.coderidea.com/
欢迎任何形式的转载,但请务必注明出处。

posted @ 2012-07-30 13:02 小胡子 阅读(134) | 评论 (0)编辑 收藏

jquery的功能总是那么的强大,用他可以开发任何web和移动框架,在浏览器市场,他一直是占有重要的份额,今天,就给大家分享20惊人的jQuery插件为设计师和开发人员。 比方说The-M-Project 可能就是你正在等待的一个开源的手机的 HTML5 的 JavaScript 框架,通过它可编写 HTML5/CSS3/SVG 应用,并支持多数数据平台,包括 iOS, Android, Palm webOS, 和 Blackberry OS。

 

 jShowOff:jQuery的内容肩 - jQuery插件

ShowOff 是一个基于 jQuery 的内容幻灯插件,之所以叫内容插件而不是图片幻灯插件,是因为jShowOff不仅支持图片,同时也支持任何HTML代码。jShowOff很易于使用, 对HTML结构的要求很简单,有一个父元素包裹的元素集合就可以了,并且jShowOff提供了丰富实用的配置参数。

预览:
jQuery插件 -  20惊人的jQuery插件和100 +优秀的jQuery资源

下载jQuery的内容肩插件

要求: jQuery的兼容性:所有主要浏览器下载:http://github.com/ekallevig/jShowOff

使用jQuery - Zoomy快速和方便的缩放

zoomy是简单的。zoomy是很容易实现和定制。Zoomy是一个快速简便的插件,使图片放大或缩小。你只需要两个副本图像和一个大的图像显示,然后缩放图像。大多数CMS系统保存或创建多个大小的图像,所以它很容易成立。只是链接上显示图片的放大图片,并告诉插件使用变焦时的链接。只需点点的脚本。Zoomy是一个很容易实现的jQuery插件,它可以帮助创建图像放大功能

预览:
jQuery插件 -  20惊人的jQuery插件和100 +优秀的jQuery资源

要求: jQuery的下载:http://redeyeoperations.com/plugins/zoomy/zoomy0.5.zip

使用php /jquery /image 图像裁剪插件

jQuery上传/图像上传工具的使用和作物不同类型的图像,JPG,GIF和PNG和你现在可以上传图片,并有一个随机的文件名 (此修复一些有缓存的问题)你需要“ 图片区选择 “插件。

我们需要的是一种方式来上传一个JPG图像,调整其大小,如果需要的话,那么裁剪给定的高度和宽度。

preivew:
jQuery插件 -  20惊人的jQuery插件和100 +优秀的jQuery资源

要求:jQuery的,PHP PHP的GD

Demo: http://www.webmotionuk.co.uk/jquery/image_upload_crop.php
Download: http://www.webmotionuk.co.uk/jquery/jquery_upload_crop.zip

ProcessWire:PHP的CMS的框架与jQuery

ProcessWire是一个开源的内容管理系统(CMS)Web应用程序框架,针对设计师,开发人员和他们的客户的需求。ProcessWire给你更多的控制领域,模板和标记比其他平台,并提供了强大的模板系统,ProcessWire的API使您的内容轻松,愉快的工作。相比,你可以用来管理和发展在ProcessWire的网站是惊人的简单。

预览:
jQuery插件 -  20惊人的jQuery插件和100 +优秀的jQuery资源

要求: PHP 5.2.4 +的MySQL 5.0.15 + 

演示:http://processwire.com/demo/ 

下载:https://github.com/ryancramerdesign/ProcessWire

jRating - 灵活的jQuery的Ajax评分插件

jRating是一个非常灵活的jQuery插件,用于快速创建一个Ajaxed星级评级制度。它是可以配置的每一个细节,从“数星星”,“如果星星可以代表小数或不”。还有一个选项,以显示大或小的恒星和图像可以很容易改变的任何其他文件。

预览:
jQuery插件 -  20惊人的jQuery插件和100 +优秀的jQuery资源

要求: jQuery的兼容性:所有主要


The-M-Project HTML5的跨平台移动应用的JavaScript框架

The-M-Project 可能就是你正在等待的一个开源的手机的 HTML5 的 JavaScript 框架,通过它可编写 HTML5/CSS3/SVG 应用,并支持多数数据平台,包括 iOS, Android, Palm webOS, 和 Blackberry OS。The-M-Project是一个令人兴奋的HTML5的JavaScript框架建立跨平台的移动网络应用程序(IOSAndroid,Palm的webOS,黑莓)。它使用jquery的JavaScript部分,并包含所有UI +像脱机支持,国际化和功能的核心文件。

预览:
jQuery插件 -  20惊人的jQuery插件和100 +优秀的jQuery资源

要求: Git的nodeJS 兼容性:所有主要的移动


arbor.js:使用Web和jQuery的图形可视化图书馆

arbor.js 是一个利用 Web Works 和 jQuery 创建的可视化图形库,它为图形组织和屏幕刷新处理提供了一个高效的、力导向的布局算法。

 

预览:
jQuery插件 -  20惊人的jQuery插件和100 +优秀的jQuery资源

要求: jQuery的兼容性:所有现代浏览器下载:https://github.com/samizdatco/arbor

jQuery.validval插件简化定制的表单验证

jQuery.validVal是一个插件,旨在简化和定制的验证形式。它是高度可定制,功能非常丰富,可以很容易地在任何类型的HTML形式(甚至AJAX的形式),。它可用于任何一种HTML表单(包括Ajaxed)的验证,并通过在类名定义的规则。

预览:
jQuery插件 -  20惊人的jQuery插件和100 +优秀的jQuery资源

要求: jQuery的兼容性:所有主要浏览器演示:http://validval.frebsite.nl/examples.php

FancyMoves Jquery的产品滑块

FancyMoves 是一个漂亮的产品图片滚动展播jQuery插件。支持键盘或点击图片导航浏览,当点击具体图片会弹出一个Lightbox模式对话框来显示原始图片。他有三种展现方式:使用键盘箭头,使用滑块两侧的左,右箭头,或在滑块只需点击下一个或最后一个项目。

FancyMoves,为您的网站或博客的一个新的jQuery滑块产品

预览:
jQuery插件 -  20惊人的jQuery插件和100 +优秀的jQuery资源

要求:
Demo: 
http://webdesignandsuch.com/posts/jquery-product-slider/jQuery-productSlider/index.html
Download: http://webdesignandsuch.com/posts/jquery-product-slider/jQuery-productSlider/FancyMoves.zip

jquery  自动复制插件sheepIt

SheepIt!是一个能够动态复制表单元素的jQuery插件,可以批量增加、删除某一个表单元素。在增加表单元素前/后都可以添加回调函数。

有时候,一个静态的形式是不够的,因为我们可能希望使人们有可能为用户定义灵活的地址,电话,电子邮件等

这是SheepIt! 

预览:
jQuery插件 -  20惊人的jQuery插件和100 +优秀的jQuery资源

要求: jQuery的1.4 + 的兼容性:所有主要


 jquery Overlay Effect Menu

Overlay Effect Menu是一款基于jquery的菜单插件,当鼠标经过菜单时候,将会产生遮罩,遮挡除了菜单的任何部分,并且展开子菜单.

预览:
jQuery插件 -  20惊人的jQuery插件和100 +优秀的jQuery资源

要求: jQuery的兼容性:所有主要的浏览器演示:

http://tympanus.net/Tutorials/OverlayEffectMenu/
Download: http://tympanus.net/Tutorials/OverlayEffectMenu/OverlayEffectMenu.zip

File Download jQuery Plugin: jDownload

jDownload是一个jQuery插件,其目的是要下载有关文件的说明

一旦下载链接被点击时,它发送一个Ajax查询到一个PHP文件,它返回一个模态窗口中的文件的名称,类型和大小。

预览:
jQuery插件 -  20惊人的jQuery插件和100 +优秀的jQuery资源

要求: jQuery的jQuery UI的兼容性:所有主要浏览器下载:http://code.google.com/p/jquery-jdownload/downloads/list

创意与jQuery自由基Web版式 - Lettering.js

lettering.js,重量轻,易于使用JavaScript <SPAN>插件用来实现比较激进的网页排版。

它只是简单地划分成片<SPAN>小号的任何给定的元素包装一个自定义类的每个字母。

preivew:
jQuery插件 -  20惊人的jQuery插件和100 +优秀的jQuery资源

要求: jQuery的兼容性:所有主要浏览器下载:http://github.com/davatron5000/Lettering.js

SlideNote:滑动通知的jQuery插件

SlideNote是一个可定制的,灵活jquery插件,可以很容易地显示在您的网站或在你的web应用滑动通知。欲了解更多信息或看到一个演示中,向下滚动。插件显示任何URL的内容,可选它可以显示该网址内的元素的内容。

预览:
jQuery插件 -  20惊人的jQuery插件和100 +优秀的jQuery资源

要求: jQuery的兼容性:所有主要浏览器下载:http://github.com/tommcfarlin/slidenote~~V

jQuery的水平手风琴 -Easy Accordion

Easy Accordion是一个高度灵活的jQuery插件用于快速创建水平可折叠手风琴(Accordion),它支持在同一个页面中创建多个实例。可折叠任意内容如:图片、列表、Flash等,外观也完全可以通过CSS自定义。

预览:
jQuery插件 -  20惊人的jQuery插件和100 +优秀的jQuery资源

要求: jQuery的兼容性:所有主要


carouFredSel - 无限的jQuery传送带滚动水平和垂直插件

carouFredSel是一个内容无限循环播放容器jQuery,可以展示任何类型的HTML元素。支持水平和垂直两个方向。项目的高度和宽度可以不相同。可以动态从容器中删除/添加项目,可以利用向前/向后按纽播放项目或设置成自动播放。

Slick jQuery Image Slider Plugin “Orbit”

 

Orbit是一个设计良好并且容易使用的jQuery图片滑动幻灯片插件,它除了支持图片滚动切换展示外,还支持针对内容的滚动。插件的定制性相当高,它提供了多个参数的设置,通过设置你可以将它打造成完全符合你要求的样式。

预览:
jQuery插件 -  20惊人的jQuery插件和100 +优秀的jQuery资源

要求: jQuery的兼容性:所有主要浏览器网址:http://www.zurb.com/playground/jquery-image-slider-plugin/Orbit_Kit.zip


转自:http://www.cnblogs.com/web8cn/archive/2012/07/30/2614795.html

posted @ 2012-07-30 13:00 小胡子 阅读(1302) | 评论 (0)编辑 收藏

     摘要: 今天在网上看到了一篇关于JAVA图像处理的文章,博主贴出了一个处理类:特点是高品质缩小,具体代码如下: import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import&n...  阅读全文

posted @ 2012-07-27 15:29 小胡子 阅读(165) | 评论 (0)编辑 收藏

一、需要用到的类

java.awt.image.BufferedImage;

javax.imageio.ImageIO;

java.io.*;

 

二、为什么要将BufferedImage转为byte数组

 

在传输中,图片是不能直接传的,因此需要把图片变为字节数组,然后传输比较方便;只需要一般输出流的write方法即可;

而字节数组变成BufferedImage能够还原图像;

 

三、如何取得BufferedImage

 

BufferedImage image = ImageIO.read(new File("1.gif"));

 

四、BufferedImage  ---->byte[]

 

ImageIO.write(BufferedImage image,String format,OutputStream out);方法可以很好的解决问题;

参数image表示获得的BufferedImage;

参数format表示图片的格式,比如“gif”等;

参数out表示输出流,如果要转成Byte数组,则输出流为ByteArrayOutputStream即可;

执行完后,只需要toByteArray()就能得到byte[];

 

五、byte[] ------>BufferedImage

 

ByteArrayInputStream in = new ByteArrayInputStream(byte[]b);    //将b作为输入流;

BufferedImage image = ImageIO.read(InputStream in);     //将in作为输入流,读取图片存入image中,而这里in可以为ByteArrayInputStream();

 

六、显示BufferedImage

 

public void paint(Graphics g){

super.paint(g);

g.drawImage(image);    //image为BufferedImage类型

}

 

七、实例

 

要求:编写一个网络程序,通过Socket将图片从服务器端传到客户端,并存入文件系统;

Server端:

package org.exam3;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.net.ServerSocket;
import java.net.Socket;

import javax.imageio.ImageIO;

public class T6Server {

public static void main(String[] args) throws Exception {
ServerSocket server = new ServerSocket(8888);
Socket s = server.accept();
DataOutputStream dout = new DataOutputStream(s.getOutputStream());
BufferedImage image = ImageIO.read(new File("1.gif"));
ByteArrayOutputStream out = new ByteArrayOutputStream();
boolean flag = ImageIO.write(image, "gif", out);
byte[] b = out.toByteArray();
dout.write(b);
s.close();
}

}



Client端:

 

package org.exam3;

import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.PrintWriter;
import java.net.Socket;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class T6Client extends JFrame {
JButton button;
MyPanel panel;
public T6Client() {
setSize(300, 400);
button = new JButton("获取图像");
add(button,BorderLayout.NORTH);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
try {
Socket s = new Socket("localhost",8888);
PrintWriter out = new PrintWriter(s.getOutputStream());
out.print("a");
DataInputStream in = new DataInputStream(s.getInputStream());
byte[]b = new byte[1000000];
in.read(b);
ByteArrayInputStream bin = new ByteArrayInputStream(b);
BufferedImage image = ImageIO.read(bin);
ImageIO.write(image, "gif", new File("2.gif"));
s.close();
} catch (Exception e) {
}
}
});
panel = new MyPanel();
add(panel);

}
public static void main(String[] args) throws Exception {
T6Client frame = new T6Client();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}

}
转自:

posted @ 2012-07-27 15:28 小胡子 阅读(889) | 评论 (0)编辑 收藏

这两个概念是早些时候Martin Fowler总结出来的两种常见模型设计类型,没有说谁好谁不好,为不同的模型类别选择合适的场景是设计者的工作。没有工具本身的问题,只有工具使用者的问题。

 

 

贫血模型是指领域对象里只有get和set方法(POJO),所有的业务逻辑都不包含在内而是放在Business Logic层。

 


 

优点是系统的层次结构清楚,各层之间单向依赖,Client->(Business Facade)->Business Logic->Data Access Object。可见,领域对象几乎只作传输介质之用,不会影响到层次的划分。

 

该模型的缺点是不够面向对象,领域对象只是作为保存状态或者传递状态使用,它是没有生命的,只有数据没有行为的对象不是真正的对象,在Business Logic里面处理所有的业务逻辑,对于细粒度的逻辑处理,通过增加一层Facade达到门面包装的效果。

 

在使用Spring的时候,通常暗示着你使用了贫血模型,我们把Domain类用来单纯地存储数据,Spring管不着这些类的注入和管理,Spring关心的逻辑层(比如单例的被池化了的Business Logic层)可以被设计成singleton的bean。

 

假使我们这里逆天而行,硬要在Domain类中提供业务逻辑方法,那么我们在使用Spring构造这样的数据bean的时候就遇到许多麻烦,比如:bean之间的引用,可能引起大范围的bean之间的嵌套构造器的调用。

 

贫血模型实施的最大难度在于如何梳理好Business Logic层内部的划分关系,由于该层会比较庞大,边界不易控制,内部的各个模块之间的依赖关系不易管理,可以考虑这样这样的实现思路:

(1)铺设扁平的原子业务逻辑层,即简单的CRUD操作(含批量数据操作);

(2)特定业务清晰的逻辑通过Facade层来组装原子操作实现。

(3)给业务逻辑层实施模块划分,保持模块之间的松耦合的关系。

 

举例说明:

原子业务逻辑层(Service)提供了用户模型的条件查询方法:

List<User> queryUser(Condition con)

Facade层则提供了一种特定的业务场景的分子接口,满足18岁的中国公民,内部实现调用的正是上述的原子接口:

List<User> queryAdultChinese()

Facade、Service层纵向划分为几个大的领域包:用户、内容和产品。

 

 

充血模型层次结构和上面的差不多,不过大多业务逻辑和持久化放在 Domain Object里面,Business Logic只是简单封装部分业务逻辑以及控制事务、权限等,这样层次结构就变成Client->(Business Facade)->Business Logic->Domain Object->Data Access Object。

 


 

它的优点是面向对象,Business Logic符合单一职责,不像在贫血模型里面那样包含所有的业务逻辑太过沉重。

 

缺点是如何划分业务逻辑,什么样的逻辑应该放在Domain Object中,什么样的业务逻辑应该放在Business Logic中,这是很含糊的。即使划分好了业务逻辑,由于分散在Business Logic和Domain Object层中,不能更好的分模块开发。熟悉业务逻辑的开发人员需要渗透到Domain Logic中去,而在Domian Logic又包含了持久化,对于开发者来说这十分混乱。  其次,如果Business Logic要控制事务并且为上层提供一个统一的服务调用入口点,它就必须把在Domain Logic里实现的业务逻辑全部重新包装一遍,完全属于重复劳动。

 

使用RoR开发时, 每一个领域模型对象都可以具备自己的基础业务方法,通常满足充血模型的特征。充血模型更加适合较复杂业务逻辑的设计开发。

 

充血模型的层次和模块的划分是一门学问,对开发人员要求亦较高,可以考虑定义这样的一些规则:

(1)事务控制不要放在领域模型的对象中实现,可以放在facade中完成。

(2)领域模型对象中只保留该模型驱动的一般方法,对于业务特征明显的特异场景方法调用放在facade中完成。

 

 

万事都不是绝对的,也有一些看起来不易解决的问题。例如,考虑到性能的需要,我需要一次查询出满足某种条件的用户和某种条件的产品,他们二者之间通过订购关系关联起来,可能发现这种情形下,上述的模型层次划分变得无解了……

 

怎么办呢?包括以上种种,欢迎大家讨论。


转自:

http://raychase.iteye.com/blog/1328224

posted @ 2012-07-26 14:03 小胡子 阅读(170) | 评论 (0)编辑 收藏

简介: EhCache 是一个纯 Java 的进程内缓存框架,具有快速、精干等特点,是 Hibernate 中默认的 CacheProvider。本文充分的介绍了 EhCache 缓存系统对集群环境的支持以及使用方法。

本文的标签:  java, 不错, 缓存

发布日期: 2010 年 4 月 01 日
级别: 初级
访问情况 : 13809 次浏览
评论: 1 (查看 | 添加评论 - 登录)

平均分 5 星 共 58 个评分 平均分 (58个评分)
为本文评分

EhCache 缓存系统简介

EhCache 是一个纯 Java 的进程内缓存框架,具有快速、精干等特点,是 Hibernate 中默认的 CacheProvider。

下图是 EhCache 在应用程序中的位置:


图 1. EhCache 应用架构图
图 1. EhCache 应用架构图

EhCache 的主要特性有:

  1. 快速;
  2. 简单;
  3. 多种缓存策略;
  4. 缓存数据有两级:内存和磁盘,因此无需担心容量问题;
  5. 缓存数据会在虚拟机重启的过程中写入磁盘;
  6. 可以通过 RMI、可插入 API 等方式进行分布式缓存;
  7. 具有缓存和缓存管理器的侦听接口;
  8. 支持多缓存管理器实例,以及一个实例的多个缓存区域;
  9. 提供 Hibernate 的缓存实现;
  10. 等等 …

由于 EhCache 是进程中的缓存系统,一旦将应用部署在集群环境中,每一个节点维护各自的缓存数据,当某个节点对缓存数据进行更新,这些更新的数据无法在其它节点中共享, 这不仅会降低节点运行的效率,而且会导致数据不同步的情况发生。例如某个网站采用 A、B 两个节点作为集群部署,当 A 节点的缓存更新后,而 B 节点缓存尚未更新就可能出现用户在浏览页面的时候,一会是更新后的数据,一会是尚未更新的数据,尽管我们也可以通过 Session Sticky 技术来将用户锁定在某个节点上,但对于一些交互性比较强或者是非 Web 方式的系统来说,Session Sticky 显然不太适合。所以就需要用到 EhCache 的集群解决方案。

EhCache 从 1.7 版本开始,支持五种集群方案,分别是:

  • Terracotta
  • RMI
  • JMS
  • JGroups
  • EhCache Server

本文主要介绍其中的三种最为常用集群方式,分别是 RMI、JGroups 以及 EhCache Server 。

回页首

RMI 集群模式

RMI 是 Java 的一种远程方法调用技术,是一种点对点的基于 Java 对象的通讯方式。EhCache 从 1.2 版本开始就支持 RMI 方式的缓存集群。在集群环境中 EhCache 所有缓存对象的键和值都必须是可序列化的,也就是必须实现 java.io.Serializable 接口,这点在其它集群方式下也是需要遵守的。

下图是 RMI 集群模式的结构图:


图 2. RMI 集群模式结构图
图 2. RMI 集群模式结构图

采用 RMI 集群模式时,集群中的每个节点都是对等关系,并不存在主节点或者从节点的概念,因此节点间必须有一个机制能够互相认识对方,必须知道其它节点的信息,包括 主机地址、端口号等。EhCache 提供两种节点的发现方式:手工配置和自动发现。手工配置方式要求在每个节点中配置其它所有节点的连接信息,一旦集群中的节点发生变化时,需要对缓存进行重 新配置。

由于 RMI 是 Java 中内置支持的技术,因此使用 RMI 集群模式时,无需引入其它的 Jar 包,EhCache 本身就带有支持 RMI 集群的功能。使用 RMI 集群模式需要在 ehcache.xml 配置文件中定义 cacheManagerPeerProviderFactory 节点。假设集群中有两个节点,分别对应的 RMI 绑定信息是:

节点 1 192.168.0.11 4567 /oschina_cache
节点 2 192.168.0.12 4567 /oschina_cache
节点 3 192.168.0.13 4567 /oschina_cache

那么对应的手工配置信息如下:


<cacheManagerPeerProviderFactory      
   
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"      
   properties
="hostName=localhost,     
   port=4567,     
   socketTimeoutMillis
=2000,     
   peerDiscovery
=manual,     
   rmiUrls
=//192.168.0.12:4567/oschina_cache|//192.168.0.13:4567/oschina_cache" />

其它节点配置类似,只需把 rmiUrls 中的两个 IP 地址换成另外两个节点对应的 IP 地址即可。

接下来在需要进行缓存数据复制的区域(Region)上配置如下即可:


<cache name="sampleCache2"     
 maxElementsInMemory
="10"     
 eternal
="false"     
 timeToIdleSeconds
="100"     
 timeToLiveSeconds
="100"     
 overflowToDisk
="false">     
<cacheEventListenerFactory         
 
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"         
 properties
="replicateAsynchronously=true,      
 replicatePuts=true,      
 replicateUpdates
=true,         
 replicateUpdatesViaCopy
=false,      
 replicateRemovals
=true "/> 
</cache>

具体每个参数代表的意义请参考 EhCache 的手册,此处不再详细说明。

EhCache 的 RMI 集群模式还有另外一种节点发现方式,就是通过多播( multicast )来维护集群中的所有有效节点。这也是最为简单而且灵活的方式,与手工模式不同的是,每个节点上的配置信息都相同,大大方便了节点的部署,避免人为的错漏出现。

在上述三个节点的例子中,配置如下:


<cacheManagerPeerProviderFactory     
 
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
 properties
="peerDiscovery=automatic, 
 multicastGroupAddress=230.0.0.1,    
 multicastGroupPort
=4446, timeToLive=32" />

其中需要指定节点发现模式 peerDiscovery 值为 automatic 自动;同时组播地址可以指定 D 类 IP 地址空间,范围从 224.0.1.0 到 238.255.255.255 中的任何一个地址。

回页首

JGroups 集群模式

EhCache 从 1.5. 版本开始增加了 JGroups 的分布式集群模式。与 RMI 方式相比较, JGroups 提供了一个非常灵活的协议栈、可靠的单播和多播消息传输,主要的缺点是配置复杂以及一些协议栈对第三方包的依赖。

JGroups 也提供了基于 TCP 的单播 ( Unicast ) 和基于 UDP 的多播 ( Multicast ) ,对应 RMI 的手工配置和自动发现。使用单播方式需要指定其它节点的主机地址和端口,下面是两个节点,并使用了单播方式的配置:


<cacheManagerPeerProviderFactory     
 
class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory" 
 properties
="connect=TCP(start_port=7800):         
 TCPPING(initial_hosts=host1[7800],host2[7800]; port_range=10;timeout=3000;     
 num_initial_members
=3;up_thread=true;down_thread=true):         
 VERIFY_SUSPECT(timeout
=1500;down_thread=false;up_thread=false):         
 pbcast.NAKACK(down_thread
=true;up_thread=true;gc_lag=100;     
 retransmit_timeout
=3000):         
 pbcast.GMS(join_timeout
=5000;join_retry_timeout=2000;shun=false;         
 print_local_addr
=false;down_thread=true;up_thread=true)" propertySeparator="::" />

使用多播方式配置如下:


<cacheManagerPeerProviderFactory     
 
class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory"     
 properties
="connect=UDP(mcast_addr=231.12.21.132;mcast_port=45566;):PING:MERGE2:FD_SOCK:VERIFY_SUSPECT:pbcast.NAKACK:UNICAST:pbcast.STABLE:FRAG:pbcast.GMS"     propertySeparator="::" />

从上面的配置来看,JGroups 的配置要比 RMI 复杂得多,但也提供更多的微调参数,有助于提升缓存数据复制的性能。详细的 JGroups 配置参数的具体意义可参考 JGroups 的配置手册。

JGroups 方式对应缓存节点的配置信息如下:


<cache name="sampleCache2"     
 maxElementsInMemory
="10"     
 eternal
="false"     
 timeToIdleSeconds
="100"     
 timeToLiveSeconds
="100"     
 overflowToDisk
="false">     
<cacheEventListenerFactory
 
class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"
 properties
="replicateAsynchronously=true, 
 replicatePuts=true,        
 replicateUpdates
=true
 replicateUpdatesViaCopy
=false, replicateRemovals=true" /> 
</cache>

使用组播方式的注意事项

使用 JGroups 需要引入 JGroups 的 Jar 包以及 EhCache 对 JGroups 的封装包 ehcache-jgroupsreplication-xxx.jar 。

在一些启用了 IPv6 的电脑中,经常启动的时候报如下错误信息:

java.lang.RuntimeException: the type of the stack (IPv6) and the user supplied addresses (IPv4) don't match: /231.12.21.132.

解决的办法是增加 JVM 参数:-Djava.net.preferIPv4Stack=true。如果是 Tomcat 服务器,可在 catalina.bat 或者 catalina.sh 中增加如下环境变量即可:


SET CATALINA_OPTS=-Djava.net.preferIPv4Stack=true 

经过实际测试发现,集群方式下的缓存数据都可以在 1 秒钟之内完成到其节点的复制。

回页首

EhCache Server

与前面介绍的两种集群方案不同的是, EhCache Server 是一个独立的缓存服务器,其内部使用 EhCache 做为缓存系统,可利用前面提到的两种方式进行内部集群。对外提供编程语言无关的基于 HTTP 的 RESTful 或者是 SOAP 的数据缓存操作接口。

下面是 EhCache Server 提供的对缓存数据进行操作的方法:

OPTIONS /{cache}}

获取某个缓存的可用操作的信息。

HEAD /{cache}/{element}

获取缓存中某个元素的 HTTP 头信息,例如:


curl --head  http://localhost:8080/ehcache/rest/sampleCache2/2 

EhCache Server 返回的信息如下:


HTTP/1.1 200 OK  X-Powered-By: Servlet/2.5  
Server: GlassFish
/v3  Last-Modified: Sun, 27 Jul 2008 08:08:49 GMT  
ETag: 
"1217146129490" Content-Type: text/plain; charset=iso-8859-1  
Content
-Length: 157  Date: Sun, 27 Jul 2008 08:17:09 GMT 

GET /{cache}/{element}

读取缓存中某个数据的值。

PUT /{cache}/{element}

写缓存。

由于这些操作都是基于 HTTP 协议的,因此你可以在任何一种编程语言中使用它,例如 Perl、PHP 和 Ruby 等等。

下图是 EhCache Server 在应用中的架构:


图 3. EhCache Server 应用架构图
图 3. EhCache Server 应用架构图

EhCache Server 同时也提供强大的安全机制、监控功能。在数据存储方面,最大的 Ehcache 单实例在内存中可以缓存 20GB。最大的磁盘可以缓存 100GB。通过将节点整合在一起,这样缓存数据就可以跨越节点,以此获得更大的容量。将缓存 20GB 的 50 个节点整合在一起就是 1TB 了。

回页首

总结

以上我们介绍了三种 EhCache 的集群方案,除了第三种跨编程语言的方案外,EhCache 的集群对应用程序的代码编写都是透明的,程序人员无需考虑缓存数据是如何复制到其它节点上。既保持了代码的轻量级,同时又支持庞大的数据集群。 EhCache 可谓是深入人心。

2009 年年中,Terracotta 宣布收购 EhCache 产品。Terracotta 公司的产品 Terracotta 是一个 JVM 级的开源群集框架,提供 HTTP Session 复制、分布式缓存、POJO 群集、跨越集群的 JVM 来实现分布式应用程序协调。最近 EhCache 主要的改进都集中在跟 Terracotta 框架的集成上,这是一个真正意义上的企业级缓存解决方案。


参考资料

学习

获得产品和技术

讨论

关于作者

刘柄成,开源中国社区(http://www.oschina.net)站长,DLOG4J 作者,十年的 Java 开发经验,热衷于开源软件的开发和应用。


http://www.ibm.com/developerworks/cn/java/j-lo-ehcache/

posted @ 2012-07-26 13:09 小胡子 阅读(169) | 评论 (0)编辑 收藏

仅列出标题
共15页: First 上一页 6 7 8 9 10 11 12 13 14 下一页 Last