??xml version="1.0" encoding="utf-8" standalone="yes"?>
概念Q?/strong>它定义了一pd的算法,q将每一个算法封装v来,而且使它们还可以怺替换。策略模式让法的变化不?x)媄响到使用法的客戗?br />
{略模式很简单,实际上就是OO中的多态,举个例子Q某商场要进行促销Q对于普通顾客打88折,对于银卡客户?8折基上再?00?60Q对于金卡客户在88折基上再?00?00?br />
UML囑֦下所C:(x)
接口DiscountStrategy代码如下Q?br />
public interface DiscountStrategy {
public double discount(double sum);
}
cGeneralDiscountStrategycM码如下:(x)
public class GeneralDiscountStrategy implements DiscountStrategy {
@Override
public double discount(double sum) {
return sum * 0.88;
}
}
cSilverDiscountStrategycM码如下:(x)
public class SilverDiscountStrategy implements DiscountStrategy {
@Override
public double discount(double sum) {
sum = sum * 0.88;
int t = (int) sum / 400;
sum = sum - t * 160;
return sum;
}
}
cGoldenDiscountStrategy代码如下Q?br />
public class GoldenDiscountStrategy implements DiscountStrategy {
@Override
public double discount(double sum) {
sum = sum * 0.88;
int t = (int) sum / 400;
sum = sum - t * 200;
return sum;
}
}
cCashier代码如下Q?br />
public class Cashier {
private DiscountStrategy discountStrategy = new GeneralDiscountStrategy();
public void getDiscountStrategy(CustomerLevel customerLevel) {
switch (customerLevel) {
case GENERAL:
discountStrategy = new GeneralDiscountStrategy();
break;
case SILVER:
discountStrategy = new SilverDiscountStrategy();
break;
case GOLDEN:
discountStrategy = new GeneralDiscountStrategy();
break;
}
}
public double calculate(double price, int num) {
return discountStrategy.discount(price * num);
}
}
1、监控^台和g的健店硬件可以通过SNMPQW(xu)EB服务器和应用服务器可以通过他们自己的管理工兗数据库也是一L(fng)?br />
2、配|应用层面的资源。比如配|应用在查询l果中每|C的数量Q配|数据库q接池,或者外部请求数{?br />
3、收集应用程序的l计信息。如多少成功订单Q多失败订单等?br />
4、日志别,改变日志U别。出问题的时候,可以通过改变日志U别来打印调试信息,快速定位问题?br />
5、监视服务器的性能、负载,通过email、sms{通知关键性事Ӟ比如服务器负载超q预讄界限?br />
要满些需求往往是非常昂贵和困难的,理员通常需要通过不同的工h理不同的服务和g?nbsp;如果使用JMXQ创Z个满上面需求的理pȝ是廉h(hun)、更加灵zR所需旉更短?nbsp;
使用JMX的好?br />
1、非常容易用。特别是对一个JAVAE序员,要理解SNMP是困隄。而JMX对他来说非常Ҏ(gu)?br />
2、利用现有的技术:(x)现有的管理工具可以插入JMXQJMX提供了很多协议(SNMP、HTTPQ和传输方式Q如RMIQ,如果原有的应用和讑֤没有提供理能力Q则可以创徏JMX代理提供理能力?br />
3、模块化。以模块化的方式创徏你的理环境?br />
4、警告、事件和l计信息?br />
JMX提供了一套通知pȝQ充分利用了面向对象优势Q通知提供了不仅仅是数据,而是一个有分布式JAVA对象Q封装了数据和行为。例如,你发送了一个服务器负蝲的通知Q里面还包含了一个显C载重要性的U别的机Ӟ说白了就是对象里面有个方法,可以判定负蝲的严重程度?br />
5、快速的监控解决Ҏ(gu)。不同的开发h员只需要自己开发MBeanQ而不需要花很多的时间在怺的协作上面,q些MBean分布在不同的L上,但可以通过一个管理工具就可以理所有的q些应用?br />
JMX的一些术?br />
1、可理资源Q?font size="2">Manageable resourceQ?br />
可以是Q何的应用、设备、或者其他存在的实体Q能够被java讉K和包装。是被JMX MBean理的资源?br />
2、MBeanQManaged BeanQ?br />
是满x些命名规则和l承JMX 规范的javac,为可理资源的管理和讉K暴露接口。通过属性和行ؓ(f)来暴露接口。有q?c:(x)Standard, Dynamic, and Model MBeans?br />
3、MBean Server
理一lMBean的JAVAcR是JMX 理环境核心。是MBean的注册器?br />
4、JMX Agent
JMX代理是ؓ(f)理一lMBean提供一pd服务的javaq程。是一个MBean Server的容器,它还提供了一些有用的服务Q创建MBean之间的关p,动态加载类Q简单的监控服务Q定时器服务。Agent有一个协议适配器和q接器集合能使外部程序连接到他们?br />
5、Protocol adapters and connectors
协议适配器和q接器是位于JMX Agent内部的对象。把Agent暴露l管理程序和协议。一个Agent可以有很多适配器和q接器?br />
6、Management application
q接到JMX Agent的用户应用程序?br />
7、Notification
通知是Mbean或者Mbean server发送的java对象Q他们封装了事g、警告、或者其他的一般信息。其他的Mbean或者java对象可以注册成ؓ(f)监听器来接受通知?br />
8、InstrumentationQ设备化Q?br />
用MBean暴露一个可理资源的过E?br />
JMX架构
JMX架构主要分ؓ(f)三层Q?font size="2">Distributed layerQ?font size="2">Agent layerQ?font size="2">Instrumentation layerQ如下图所C:(x)
1?/span>Distributed layerQ分布式层)
属于JMX架构的最外层Q这层主要负责JMX Agent能对外部E序可用?nbsp; 又分ZU:(x)一U通过不同的协议(如SNMPQHTTPQ来为MBean提供可见性?/font> 另一U是把Agent API暴露l其他的分布式技术如RMI?br />
2?font size="2">The agent layerQ代理层Q?br />
它包含的最主要的组件是MBean ServerQ它q包?个代理服务ɽ理MBean更加Ҏ(gu)Q它们分别是Q?nbsp; 定时器(timerQ、监控服务、动态MBean加蝲、和MBean关系服务。Agent可以和被理的资源在同一个主ZQ也可以是远E的?br />
3?font size="2">The instrumentation layer
q是最靠近资源的一层,它包含了注册在Agent里面的MBean?br />
4?font size="2">Notifications
除了架构中的三层以外QJMX提供了一个通知机制Q类gJAVA事g模型。通知机制是管理系l的最后必ȝlg。Agent和MBean可以使用通知机制来发送警告或信息l管理应用?br />
以上是JMX架构的主要内容,下一构Z个HelloWorld的JMXE序?br />
Restful WS的特性:(x)
1?strong>可寻址性(AddressabilityQ?br />
资源通过URI来暴露给用户Q可d性是最基本的特性。由于可d性,你可以把URI保存在你的书{NQ你可以把链接发l别人,而不用把Html文g下蝲下来发给别hQ也可以通过URI对资源进行缓存?br />
2?strong>无状态性(StatelessnessQ?br />
无状态性意味着每个HTTPh是完全隔ȝ。每ơ客L(fng)发送请求都必须带上所有服务器端需要的信息?nbsp;
无状态的应用更容易分布到有负责均衡的多台服务器上Q无状态性也更容易缓存:(x)~存工具只需要看q一个请求,和Q何其他请求无兟?br />
应用状态和资源状态(Application State Versus Resource StateQ?br />
应用状态位于客L(fng)Q而资源状态位于服务器端,对于客户端,每个客户端都有各自的应用状态,例如Q在google搜烦Q你可能搜烦某个单词且当前页是第3,我可能搜索另一个单词且在第一,所以每个客L(fng)都有一个应用状态。当客户端发赯求的时候,必须告诉服务器你的应用状态,比如你当前要看某个单词搜索结果的W几,服务器端q回l果上有其他链接Q这些链接客L(fng)可能作ؓ(f)未来的请求?br />
而对于资源状态,对于每个客户端都是相同的Q就是服务器上的资源?nbsp;
3、表q性(RepresentationsQ?br />
表述性,是资源的表现Ş式,相同的资源可以有不同的表q性,比如同一个bug列表可以用XML文档表示Q也可以用文本方式表C等{。对于同一资源的不同的RepresentationQ如何知道客L(fng)h哪一U呢Q作者徏议不同的Representation使用不同的URI?br />
4、连通性(Links and ConnectednessQ?br />
单点_(d)是q回的结果中有对其他资源的链接(URIQ,比如google搜烦Q搜索结果可能有其他늚链接?br />
5、统一的接口(The Uniform InterfaceQ?br />
也就是说Restful WS使用HTTP的基本方法作Z的方法的表示Q主要用HTTP的四个方法:(x)GET,PUT,DELETE,POST。HEAD和OPTIONS用的比较?yu)?br />
取得某个资源的表q的时候用GET?br />
创徏一个新的资源的时候,PUTC个新的URIQ或者POSTC个已l存在的URI?br />
修改资源Q用PUT到存在的URI?br />
删除资源使用DELETE?br />
PUT和POST都可以创建新的资源,那有什么区别呢QPOST可以创徏从属资源Q如一个webblogE序通过资源Q?weblogs/myweblogQ暴露每个blogQ而某个blog下面的条目作Z属资源ؓ(f)/weblogs/myweblog/entries/1Q当你需要增加一个条目的时候,你可以POST到父资源/weblogs/myweblogQ同样PUT也可以完成这个工作,在这里POST和PUT的区别是Q当客户端可以控制新资源的URI的时候,则用PUTQ比如blog的下面的某篇文章使用名字来访问,?weblogs/myweblog/entries/restful_ws_1Q这h个博客下面的文章不能重复Q,则当你发表一新文章的时候,可以PUT到新的URI?weblogs/myweblog/entries/restful_ws_2来创源。而如果客L(fng)不能控制URI的时候,比如blog是通过服务器端某个序列h讉KQ客L(fng)是无法知道下一个序h什么,q时只能使用POSTQ这UPOST如果创徏成功Q则q回201Q响应头中的Location可以保护新创源的URI?br />
q有一个区别,POSTҎ(gu)个存在的资源更新Ӟ一般是q加QappendQ,比如说对某个日志文g做POSTQ则把日志追加到原日志的后面。如果是PUT则进行的是替换,所以PUT是等q的Q而POST不是Q后面会(x)Ԍ?br />
安全QSafetyQ?br />
GET和HEADҎ(gu)只是获取资源的表qͼ所以是安全的。当然也可能有一些副作用Q比如有些服务端?x)记录GET的次数等?br />
{幂性(IdempotenceQ?br />
{幂性简单点说就是一ơ请求和多次hQ资源的状态是一栗比如GET和HEADQ不Zh多少ơ,资源q是在那里。请注意QDELETE和PUT也是{幂的,以ؓ(f)对同一个资源删除一ơ或者多ơ,l果是一L(fng)Q就是资源被删除了,不存在了。ؓ(f)什么说PUT也是{幂的?当你PUT一个新资源的时候,资源被创建,再次PUTq个URI的时候,资源q是没变。当你PUT一个存在的资源Ӟ更新了资源,再次PUT的时候,q是更新成这个样子。在PUT更新的时候,不能做相对的更新Q依赖资源现在的状态)Q比如每ơ对一个数?Q这栯源状态就?x)变化。应该每ơ更新成某个敎ͼ比如把某个数变成4Q则无论多少ơPUTQ值都?Q这样就是等q了?br />
我们设计Restful WS的时候,GETQHEAD, PUT, DELETE一定要设计成等q的。由于网l是不可靠的Q安全性和{幂性就昑־特别重要。如果一ơ请求,服务器收到处理以后,客户端没有收到相应,客户端会(x)再次hQ如果没有等q性保障,׃(x)发生意想不到的问题?br />
POST是不安全也不{幂的,q是拿weblog的例子,如果两次POST相同的博文,则会(x)产生两个资源QURI可能是这?weblogs/myweblog/entries/1?weblogs/myweblog/entries/2Q尽他们的内容是一怸L(fng)?br />
1、启动类装蝲?br />
主要负责装蝲jdk_home/lib目录下的核心api ?-Xbootclasspath 选项指定的jar包。处于双亲委z最层Q该cd实是由C语言~写?br />
2、扩展类装蝲?br />
主要负责装蝲jdk_home/lib/ext目录下的jar包或 -Djava.ext.dirs 指定目录下的jar?br />
3、系l类装蝲?br />
主要负责装蝲ClassPath下的cR?br />
4、自定义c装载器
自定义类l承ClassLoader或其子类。可以运行时动态装载某些类?br />
其中Qu2代表2个字节的无符h数。u4代表4个字节的无符h敎ͼ其他?/code>cp_info
?/span>
field_info
是一些结构数据,接下M(x)讌Ӏ?br />
q次要解析的是一个非常简单的c:(x)TJ.javaQ代码如下:(x)使用jdk1.6~译Q生的二进制类文g如下Q?br />
下面对照上面的格式结构一点点的解析?br />
CA FE BA BEQ头四个字节是魔敎ͼ表示q是java class文g?br />
00 00Q次版本??br />
00 32Q主版本0x32Q表Cjdk1.6~译的。Jdk1.5?x31Qjdk1.4?x30?br />
00 16Q常量池的入口(entryQ数量。包括自己本w(q里很奇怪)Q所以接下来?1的帔R池入口?br />
我会(x)在每个常量池的前面表上索引。常量池的第一个字节表C类型。具体类型对照表如下Q?br />
Constant Type | Value |
---|---|
CONSTANT_Class |
7 |
CONSTANT_Fieldref |
9 |
CONSTANT_Methodref |
10 |
CONSTANT_InterfaceMethodref |
11 |
CONSTANT_String |
8 |
CONSTANT_Integer |
3 |
CONSTANT_Float |
4 |
CONSTANT_Long |
5 |
CONSTANT_Double |
6 |
CONSTANT_NameAndType |
12 |
CONSTANT_Utf8 |
1 |
0A 00 04 00 12Q?span style="color: red">??/span>Q第一个字节ؓ(f)10Q所以是CONSTANT_MethodrefQ它的结构如下:(x)
CONSTANT_Methodref_info {
u1 tag;
u2 class_index;
u2 name_and_type_index;
}
所以,class_index=4Qname_and_type_index=12,q两个代表常量池W?和W?2V?br />
09 00 03 00 13Q?span style="color: red">??/span> q是一个CONSTANT_FieldrefQ他的结构和上面的类似class_index=3Qname_and_type_index=13
07 00 14Q?span style="color: red">??/span>q个是CONSTANT_ClassQ它的结构如下:(x)
CONSTANT_Class_info {
u1 tag;
u2 name_index;
}
name_index?0Q指向的是一个utf8的字节码Q即TJQ这个后面会(x)看到?br />
07 00 15: ??也是一?/span>CONSTANT_ClassQname_index?1Q即java/lang/Object
01 00 02 66 31: ??/span>CONSTANT_Utf8Q结构如下:(x)
CONSTANT_Utf8_info {
u1 tag;
u2 length;
u1 bytes[length];
}
最后两个字节代表字W串“f1”的utf-8字节码?br />
01 00 01 49Q??/span>字符串I
01 00 0D 43 6F 6E 73 74 61 6E 74 56 61 6C 75 65 Q??/span>字符串ConstantValue
03 00 00 00 02Q??/span>CONSTANT_IntegerQ整数?
01 00 06 3C 69 6E 69 74 3EQ?】字W串<init>
01 00 03 28 29 56Q?0】字W串()V
01 00 04 43 6F 64 65Q?1】字W串code
01 00 0F 4C 69 6E 65 4E 75 6D 62 65 72 54 61 62 6C 65Q?2】字W串LineNumberTable
01 00 02 6D 31Q?3】字W串m1
01 00 04 28 49 29 49 Q?4】字W串(I)IQ表CZ个整数参Cq回整数的方法?br />
01 00 02 6D 32 Q?5】字W串m2
01 00 0A 53 6F 75 72 63 65 46 69 6C 65 Q?6】字W串SourceFile
01 00 07 54 4A 2E 6A 61 76 61Q?7】字W串TJ.java
0C 00 09 00 0AQ?8】CONSTANT_NameAndTypeQ结构如下:(x)
CONSTANT_NameAndType_info {
u1 tag;
u2 name_index;
u2 descriptor_index;
}
name_index=9Q代表方?lt;init>Qdescriptor_index=10Q?)VQ代表无参且q回void的方法?br />
0C 00 05 00 06Q?9】结构同上,name_index=5Q即f1Qdescriptor_index=6Q即整数?br />
01 00 02 54 4A Q?0】字W串TJ
01 00 10 6A 61 76 61 2F 6C 61 6E 67 2F 4F 62 6A 65 63 74Q?1】字W串java/lang/Object
到此Q常量池l束?br />
00 21Q类的描q符为public?br />
00 03 Qthis class为常量池W三个,TJQ即q个cȝ名字为TJ
00 04Qsuper class为常量池W四个,java/lang/ObjectQ即它的类为java.lang.Object
00 00Q接口个??br />
00 01Qfield数量1?br />
00 12 00 05 00 06 00 01 00 07 00 00 00 02 00 08Qfield的结构如?br />
field_info {
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
}
access_flags?0 12Q代表ACC_PRIVATE+ ACC_FINAL
name_indexQ常量池索引?的入口,即f1Q即cL员的名字为f1
descriptor_indexQIQ代表integer?br />
attributes_countQ?个?br />
attribute_infoQ?br />
attribute_info {
u2 attribute_name_index;
u4 attribute_length;
u1 info[attribute_length];
}
attribute_name_indexQ?Q即ConstantValueQ结构如?br />
ConstantValue_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 constantvalue_index;
}
attribute_lengthQ?
constantvalue_indexQ?
----------------------------------------下面开始方?/span>
00 03Q?个方法?br />
method_info {
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
}
--------------------------------------------W一个方?lt;init>Q这个是~译器生的生成实例的初始化Ҏ(gu)?br />
access_flagsQpublic
name_indexQ?0 09Q?lt;init>
descriptor_indexQ?0 0AQ?)V表示无参敎ͼq回void
attributes_count :00 01,1?br />
attribute_name_index Q?0 0B Qcode
attribute_lengthQ?8?br />
Code_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 max_stack;
u2 max_locals;
u4 code_length;
u1 code[code_length];
u2 exception_table_length;
{ u2 start_pc;
u2 end_pc;
u2 handler_pc;
u2 catch_type;
} exception_table[exception_table_length];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
max_stack: 00 02
max_locals: 00 01
code_length: 00 00 00 0A,10
code: 2A B7 00 01 2A 05 B5 00 02 B1,指o(h)
exception table lengthQ?0 00
attributes_countQ?
attribute_name_indexQ?0 0CQLineNumberTable
LineNumberTable_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 line_number_table_length;
{ u2 start_pc;
u2 line_number;
} line_number_table[line_number_table_length];
}
attribute_lengthQ?0
line_number_table_lengthQ?
start_pcQ?0 00
line_numberQ?0 01
tart_pcQ?0 04
line_numberQ?0 03
到此W一个方法结束?br />
----------------------------------------------------------------------W二个方法开?br />
access_flagsQ?span lang="EN-US">00 01Q?span lang="EN-US">public
name_indexQ?0 0DQm1
desc_indexQ?0 0EQ?I)IQ有一个整数参敎ͼq回一个整数?br />
00 01Q一个attr
00 0BQcode
00 00 00 1CQattr_length:28
Code_atrr:28个字节,不分析了和上面的Ҏ(gu)相同?br />
----------------------------------------------------------------------W三个方?br />
00 02Qprivate
00 0FQm2
00 0A: ()VQ无参,q回void
00 01Q一个attr
00 0BQcode
00 00 00 19Qattr_length 25
接下ȝ25个字节是Code_atrrQ同样不分析了?br />
------------------------------------------------------------------
00 01Q?个类的attr
00 10QSourceFile
00 00 00 02Qlen=2
00 11Q?7QTJ.java