Groovy 学习笔记 (四)
- Groovy 支持操作符重载, 每个操作符对应一个方法签名, 如‘+’对应的是’plus’.
- Groovy 支持多种字符串表示, 单引号, 双引号(支持GString), 3个单引号(支持多行), 3个双引号(支持多行, 支持GString).
- 在 Groovy 中, 方法的括号是可选的, 如果一行只有一个语句, 那么语句后的分号也可省略不写.
- Groovy range, 可用于: 数字, 日期, 字符串. 只要数据类型实现了 next(++), previous(–), 和 java.lang.Comparable 接口, 就可以使用 range .
- Groovy list 默认使用 ArrayList, 欲使用 LinkedList 等其它类型 List, 需要明确声明.
- List 可以使用负值作为index值进行访问, 例如 list[-1]返回的就是list的最后一个值, list[-2]则返回倒数第二个值. 也可以指定倒序的 range, 如list[4..0].
- 需注意: list[0..<-2] 等价于 list[0..-1] 而非 list[0..-3].
- 声明空的map: [:]
- ['a':1] 等价于 [a:1]
Categorized in: Scripts · Tagged with: Groovy, Java, Scripts
Groovy 学习笔记 (三)
1. == 是判断是否 equals, 而判断是否是同一对象则用 is
2. list 和 map 的一些方法:
def x = 1..10
assert x.contains(5)
assert x.contains(15) == false
assert x.size() == 10
assert x.from == 1
assert x.to == 10
assert x.reverse() == 10..1
3. 以下对象都有 size() 方法
Array, String, StringBuffer, Collection, Map, File
4. 数据类型:12 – Integer, 100L – Long, 1.23F – Float, 1.23D – Double, 123G – BigInteger, 1.23,1.23G – BigDecimal
如果一个小数, 末尾什么字符都没加, 那么这个小数使用的是 BigDecimal.
5. 操作符重载
| Operator | Name | Method | Works with |
| a + b | Plus | a.plus(b) | Number,string,collection |
| a – b | Minus | a.minus(b) | Number,string,collection |
| a * b | Star | a.multiply(b) | Number,string,collection |
| a / b | Divide | a.div(b) | Number |
| a % b | Modulo | a.mod(b) | Integral number |
| a++ | Post increment | a.next() | Number,string,range |
| ++a | Pre increment | ||
| a– | Post decrement | a.previous() | Number,string,range |
| –a | Pre decrement | ||
| a**b | Power | a.power(b) | Number |
| a | b | Numerical or | a.or(b) | Integral number |
| a & b | Numerical and | a.and(b) | Integral number |
| a ^ b | Numerical xor | a.xor(b) | Integral number |
| ~a | Bitwise complement | a.negate() | Integral number,string (the latter returning a regular expression pattern) |
| a[b] | Subscript | a.getAt(b) | Object,list,map,string、Array |
| a[b] = c | Subscript assignment | a.puAt(b,c) | Object,list,map,StringBuffer, Array |
| a << b | Left shift | a.leftShift(b) | Integral number, also used like “append” to StringBuffers, Writers, Files, Sockets, Lists |
| a >> b | Right shift | a.rightShift(b) | Integral number |
| a >>> b | Right shift unsigned | a.rightShiftUnsigned(b) | Integral number |
| switch(a){ case b: } |
Classification | b.isCase(a) | Object, range, list, collection, pattern, closure; also used with collection c in c.grep(b), which returns all items of c where b.isCase(item) |
| a == b | Equals | a.equals(b) | Object, consider hashCode() |
| a != b | Not equals | !a.equals(b) | Object |
| a <=> b | Spaceship | a.compareTo(b) | java.lang.Comparable |
| a > b | Greater than | a.compareTo(b) > 0 | |
| a >= b | Greater than or equal to | a.compareTo(b) >= 0 | |
| a < b | Less than | a.compareTo(b) < 0 | |
| a <= b | Less than or equal to | a.compareTo(b) <= 0 | |
| a as type | Enforced coercion | a.asType(typeClass) | Any type |
class Money {
private int amount
private String currency
Money (amountValue, currencyValue) {
amount = amountValue
currency = currencyValue
}
boolean equals (Object other) {
if (null == other) return false
if (! (other instanceof Money)) return false
if (currency != other.currency) return false
if (amount != other.amount) return false
return true
}
int hashCode() {
amount.hashCode() + currency.hashCode()
}
Money plus (Money other) {
if (null == other) return null
if (other.currency != currency) {
throw new IllegalArgumentException("cannot add $other.currency to $currency")
}
return new Money(amount + other.amount, currency)
}
}
def buck = new Money(1, 'USD')
d Use overridden ==
assert buck
assert buck == new Money(1, 'USD')
e Use overridden +
assert buck + buck == new Money(2, 'USD')
6.
Categorized in: Scripts · Tagged with: Groovy, Java, Scripts
The interesting but useful mock assertion in Java
在某开源项目里, 发现它使用了一种很有意思的 assertion 机制. 这是一种仿 assertion 的方式来实现对输入参数或特定表达式的判断.
伪代码如下:
public final class Assert {
private Assert() {}
public static void notNull(Object o) {
notNull("Null object is used", o);
}
public static void notNull(String description, Object o) {
if(o == null) {
throw new AssertionException(description);
}
}
...... // other assertion methods
}
AssertionException 继承自 RuntimeException, 因此是可以不捕获的.
在某方法里可以如此使用这个 Assert :
public void someMethod(String arg1 ...) {
Assert.notNull(arg1);
...
}
好处是:
1. 类似 Java 已有的 Assertion 机制, 使用起来非常直观.
2. 减少了大量对参数进行 if-else 等的判断, 代码看起来更加整洁, 易懂.
3. 对类似错误可以进行统一处理, 对错误信息进行统一描述.
Categorized in: Java · Tagged with: Java, Open Source
XML 中的 schemaLocation 属性究竟是什么意思?
在 XML 实例文档中有时会发现有 schemaLocation 属性。很多人对此非常疑惑,搞不清这个属性究竟是什么意思,究竟该如何使用。
schemaLocation 属性用来引用(schema)模式文档,解析器可以在需要的情况下使用这个文档对 XML 实例文档进行校验。它的值(URI)是成对出现的,第一个值表示命名空间,第二个值则表示描述该命名空间的模式文档的具体位置,两个值之间以空格分隔。当然,在必要情况下,可以为 schemaLocation 属性指派多个这样的值对。
<p:Person
xmlns:p="http://contoso.com/People"
xmlns:v="http://contoso.com /Vehicles"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://contoso.com/People
http://contoso.com/schemas/people.xsd
http://contoso.com/schemas/Vehicles
http://contoso.com/schemas/vehicles.xsd
http://contoso.com/schemas/People
http://contoso.com/schemas/people.xsd">
<name>John</name>
<age>28</age>
<height>59</height>
<v:Vehicle>
<color>Red</color>
<wheels>4</wheels>
<seats>2</seats>
</v:Vehicle>
</p:Person>
如果为没有目标命名空间的模式文档指定位置,需用 noNamespaceSchemaLocation 属性.
Categorized in: SOA · Tagged with: schema, XML
Java Thread 注意事项
- 该同步要同步
- 同步块尽可能的小
- 循环内使用wait()
- notifyAll()优先于notify()
- yield()不可靠
- 在持有锁的时候, 尽量不要调用其它对象的方法(这些方法可能也是同步过的), 因为这很可能是死锁的源头.
-
对象锁:使用对方法进行synchronized时,线程进入该方法前需先获得该对象上的同步锁。所以,即使另外一个线程调用的是该对象上的另一个方法,因为此时该对象锁已被另一线程占有,所以该线程还是要排队等候以占有对象锁。由于线程进入非同步方法并不需要占有锁,所以非同步方法并不会被该对象上的同步方法所阻塞。
对象锁:使用对方法进行synchronized时,线程进入该方法前需先获得该对象上的同步锁。所以,即使另外一个线程调用的是该对象上的另一个方法,因为此时该对象锁已被另一线程占有,所以该线程还是要排队等候以占有对象锁。由于线程进入非同步方法并不需要占有锁,所以非同步方法并不会被该对象上的同步方法所阻塞.
- 类锁:对静态方法进行 synchronized,那么就决定了进入该静态同步方法前,线程必须先获得类锁。类锁其实是并不存在的,原因在于类锁是基于类的class对象,每个类都有唯一的一个class对象与之对应,该类的所有实例也都拥有该唯一class对象的引用,因此,静态同步方法所使用的锁其实就是类的class对象,本质上还是一个对象锁.
- 基于以上两点,对象锁与类锁互不相干,因为它们的锁是完全不同的.
- ThreadDeath 是 Error 的子类. 调用 Thread 类中带有零参数的 stop 方法(该方法已不推荐使用)时,受害线程将抛出一个 ThreadDeath 实例.
- 线程优先级取决于底层实现, 应尽量避免使用.
- 线程结束后,再次调用该线程对象的 start() 方法会抛出异常,也就是不要重新开始一个已经执行完毕的线程.
- 守护线程与非守护线程的区别: 当进程中所有非守护线程已(结束或)退出时, 即使仍有守护线程在运行,进程仍将结束.
- Thread.UncaughtExceptionHandler接口:当线程因未捕获异常而终止时,会调用本接口的实现进行处理。Thread.setDefaultUncaughtExceptionHandler静态方法设置的是全局默认处理程序。可对单个thread、ThreadGroup对象设置未捕获异常处理程序。调用顺序是:先尝试使用thread的未捕获异常处理程序,如果该线程未设置,则使用该线程所属线程组的,如果线程组也没有设置,则使用默认的未捕获异常处理程序。
synchronized (obj) {
while (condition) {
obj.wait();
}
}
因为唤醒后,条件是否满足还不一定,所以还需要再次检查。
Categorized in: Java · Tagged with: Java, Thread
SMTP Transport Binding for SOAP
SOAP 除了可以 bind 到 HTTP 上外, 也可以 bind 到 SMTP 上. 其实个人感觉, SOAP bind 到 SMTP 上的场景很少会使用到, 通常限于 one-way operation (比如通知等不需要响应). 如果需要实现 request/response, 那么是需要多做一些工作的(下文会有叙述).
soap:binding element 的 transport 属性需指定一个 http://xxx(例如:http://schemas.xmlsoap.org/soap/smtp) URL 来表明所要 binding 的 protocol. 似乎这个 URL 是任意形式, 只要能让调用方知道要使用什么协议即可. 在 soap:address 要给定 mailto:xxxx@xxx.xxx 这样形式的 URI.
<service name="StockQuoteServiceBinding_service">
<port name="StockQuoteServiceBinding_port"
binding="binding:StockQuoteServiceBinding">
<soap:address location="mailto:getQuote@test.com"/>
</port>
</service>
注意: 在 soap:address element 中, 可能会有一些扩展元素, 例如smtp server, smtp username, smtp password, etc.
在需要 request / response 语义情况下, 需使用标准的 Message-Id 和 In-Reply-To SMTP header 来实现这一目标. 请求包含一个 Message-Id header, 相应的响应则在 In-Reply-To header 中使用请求的 Message-Id header 值, 同时也创建一个新的 Message-Id header. 这样, 在请求与响应之间便建立了关联.
请求:
To: <soap@example.org> From: <soap@client.com> Reply-To: <soap@client.com> Date: Tue, 15 Nov 2001 23:27:00 -0700 Message-Id: <1F75D4D515C3EC3F34FEAB51237675B5@client.com> MIME-Version: 1.0 Content-Type: text/xml; charset=utf-8 Content-Transfer-Encoding: QUOTED-PRINTABLE <?xml version=3D"1.0" encoding=3D"UTF-8"?> <SOAP-ENV:Envelope SOAP-ENV:encodingStyle=3D"http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENC=3D"http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV=3D"http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd=3D"http://www.w3.org/2001/XMLSchema" xmlns:xsi=3D"http://www.w3.org/2001/XMLSchema-instance"> <SOAP-ENV:Body> <m:echoString xmlns:m=3D"http://soapinterop.org/"> <inputString>get your SOAP over SMTP here !</inputString> </m:echoString> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
响应:
To: <soap@client.com> From: <soap@example.org> Date: Tue, 13 Nov 2001 23:27:00 -0700 In-Reply-To: <1F75D4D515C3EC3F34FEAB51237675B5@client.com> Message-Id: <FF75D4D515C3EC3F34FEAB51237675B5@soap.example.org> MIME-Version: 1.0 Content-Type: TEXT/XML; charset=utf-8 Content-Transfer-Encoding: QUOTED-PRINTABLE <?xml version=3D"1.0" encoding=3D"UTF-8"?> <SOAP-ENV:Envelope SOAP-ENV:encodingStyle=3D"http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENC=3D"http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV=3D"http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd=3D"http://www.w3.org/2001/XMLSchema" xmlns:xsi=3D"http://www.w3.org/2001/XMLSchema-instance"> <SOAP-ENV:Body> <m:echoStringResponse xmlns:m=3D"http://soapinterop.org/"> <return>get your SOAP over SMTP here !</return> </m:echoStringResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
Resources:
Categorized in: SOA · Tagged with: SOAP, UDDI, Webservice, WSDL, XML
Java 中类的重载与覆盖之间的一点小区别
大的区分我想熟悉 Java 这门语言的人都知道,本文仅为记录在阅读《Effective Java》时所遇到的新知识。
在《Effective Java》中,Joshua Bloch提到:对于重载方法 (overloaded method) 的选择是静态的,而对于被改写的方法 (overridden method) 的选择是动态的。
对于被改写的方法,选择正确的方法版本是在运行时刻进行的,选择的依据是被调用方法所在对象的运行时类型。如果被改写方法是在子类实例上被调用,那么该子类实例中的方法将会执行。
而对于重载方法,则恰恰与改写方法的行为相反。
请看如下例子:
public class CollectionClassifier {
public static String classify(Set s) {
return "Set";
}
public static String classify(List l) {
return "List";
}
public static String classify(Collection c) {
return "Unknown Collection";
}
public static void main(String[] args) {
Collection[] cs = new Collection[] {
new HashSet(), new ArrayList(), new HashMap().values()
};
for (Collection c : cs) {
System.out.println(classify(c));
}
}
}
在这个例子中,将打印 “Unknown Collection” 三次。这是因为到底调用哪个重载方法是在编译时刻就做出决定的。在三次循环中,参数的编译类型都是:Collection。
Categorized in: Java · Tagged with: Java
Which style of WSDL should I use? (reship)
Date: 24 May 2005 (Published 31 Oct 2003)
Level: Advanced
Summary: A Web Services Description Language (WSDL) binding style can be RPC or document. The use can be encoded or literal. How do you determine which combination of style and use to use? The author describes the WSDL and SOAP messages for each combination to help you decide.
Introduction
A WSDL document describes a Web service. A WSDL binding describes how the service is bound to a messaging protocol, particularly the SOAP messaging protocol. A WSDL SOAP binding can be either a Remote Procedure Call (RPC) style binding or a document style binding. A SOAP binding can also have an encoded use or a literal use. This gives you four style/use models:
- RPC/encoded
- RPC/literal
- Document/encoded
- Document/literal
Add to this collection a pattern which is commonly called the document/literal wrapped pattern and you have five binding styles to choose from when creating a WSDL file. Which one should you choose?
Before I go any further, let me clear up some confusion that many of us have stumbled over. The terminology here is very unfortunate: RPC versus document. These terms imply that the RPC style should be used for RPC programming models and that the document style should be used for document or messaging programming models. That is not the case at all. The style has nothing to do with a programming model. It merely dictates how to translate a WSDL binding to a SOAP message. Nothing more. You can use either style with any programming model.
Likewise, the terms encoded and literal are only meaningful for the WSDL-to-SOAP mapping, though, at least here, the traditional meanings of the words make a bit more sense.
For this discussion, let’s start with the Java method in Listing 1 and apply the JAX-RPC Java-to-WSDL rules to it (see Resources for the JAX-RPC 1.1 specification).
public void myMethod(int x, float y); |
RPC/encoded
Take the method in Listing 1 and run it through your favorite Java-to-WSDL tool, specifying that you want it to generate RPC/encoded WSDL. You should end up with something like the WSDL snippet in Listing 2.
Listing 2. RPC/encoded WSDL for myMethod
<message name="myMethodRequest">
<part name="x" type="xsd:int"/>
<part name="y" type="xsd:float"/>
</message>
<message name="empty"/>
<portType name="PT">
<operation name="myMethod">
<input message="myMethodRequest"/>
<output message="empty"/>
</operation>
</portType>
<binding .../>
<!-- I won't bother with the details, just assume it's RPC/encoded. -->
|
Now invoke this method with “5″ as the value for parameter x and “5.0″ for parameter y. That sends a SOAP message which looks something like Listing 3.
Listing 3. RPC/encoded SOAP message for myMethod
<soap:envelope>
<soap:body>
<myMethod>
<x xsi:type="xsd:int">5</x>
<y xsi:type="xsd:float">5.0</y>
</myMethod>
</soap:body>
</soap:envelope>
|
There are a number of things to notice about the WSDL and SOAP message for this RPC/encoded example:
Strengths
- The WSDL is about as straightforward as it’s possible for WSDL to be.
- The operation name appears in the message, so the receiver has an easy time dispatching this message to the implementation of the operation.
Weaknesses
- The type encoding info (such as
xsi:type="xsd:int") is usually just overhead which degrades throughput performance. - You cannot easily validate this message since only the
<x ...>5</x>and<y ...>5.0</y>lines contain things defined in a schema; the rest of thesoap:bodycontents comes from WSDL definitions. - Although it is legal WSDL, RPC/encoded is not WS-I compliant.
Is there a way to keep the strengths and remove the weaknesses? Possibly. Let’s look at the RPC/literal style.

(
(4.00 out of 5)