resteasy-links中的AddLinks功能实现
本文分析resteasy-links
当中,AddLinks
的功能实现。首先分析resteasy-links
提供的RESTUtils
。这个RESTUtils
工具类是resteasy-link
自己提供的,在项目里查找用到它的地方:
$ grep -rl 'RESTUtils' *
resteasy-links/src/main/java/org/jboss/resteasy/links/impl/LinkDecorator.java
resteasy-links/src/main/java/org/jboss/resteasy/links/impl/RESTUtils.java
$
可以看到是LinkDecorator
在使用。下面是使用之处:
$ grep -rl 'LinkDecorator' *
resteasy-links/src/main/java/org/jboss/resteasy/links/impl/LinkDecorator.java
resteasy-links/src/main/java/org/jboss/resteasy/links/AddLinks.java
$
以下是LinkDecorator
的具体实现:
public class LinkDecorator implements DecoratorProcessor<Marshaller, AddLinks> {
public Marshaller decorate(Marshaller target, final AddLinks annotation,
Class type, Annotation[] annotations, MediaType mediaType) {
target.setListener(new Listener() {
@Override
public void beforeMarshal(Object entity) {
UriInfo uriInfo = ResteasyContext.getContextData(UriInfo.class);
ResourceMethodRegistry registry = (ResourceMethodRegistry) ResteasyContext.getContextData(Registry.class);
// find all rest service classes and scan them
RESTUtils.addDiscovery(entity, uriInfo, registry);
}
});
return target;
}
}
可以看到decorate
方法的重点是往Marshaller target
里面添加一个listener。而这个listener干的事情是把RESTUtils.addDiscovery(..)
方法执行一下,注入ResourceMethodRegistry
。这样,RESTUtils
就可以在运行时工作了。下面这个是RESTUtils
的类图:
回到 LinkDecorator
,它是一个DecoratorProcessor
,用于decorate的Marshaller
,用户给需要decorate的class标注AddLinks
标记。下面是AddLinks
的源代码:
package org.jboss.resteasy.links;
import org.jboss.resteasy.annotations.Decorator;
import org.jboss.resteasy.links.impl.LinkDecorator;
import javax.xml.bind.Marshaller;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Use on any JAX-RS method if you want RESTEasy to inject the RESTServiceDiscovery
* to every entity in the response. This will only inject RESTServiceDiscovery instances
* on entities that have a field of this type, but it will be done recursively on the response's
* entity.
* @author <a href="mailto:stef@epardaud.fr">Stéphane Épardaud</a>
*/
@Target( { ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER,
ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Decorator(processor = LinkDecorator.class, target = Marshaller.class)
@Documented
public @interface AddLinks {
}
查找@AddLinks
使用到的地方:
$ grep -rl 'AddLinks' * | grep java
resteasy-links/src/test/java/org/jboss/resteasy/links/test/BookStoreMinimal.java
resteasy-links/src/test/java/org/jboss/resteasy/links/test/SecureBookStore.java
resteasy-links/src/test/java/org/jboss/resteasy/links/test/SecureBookStoreMinimal.java
resteasy-links/src/test/java/org/jboss/resteasy/links/test/el/BookStoreInvalidEL.java
resteasy-links/src/test/java/org/jboss/resteasy/links/test/el/BookStoreNoPackage.java
resteasy-links/src/test/java/org/jboss/resteasy/links/test/BookStore.java
resteasy-links/src/test/java/org/jboss/resteasy/links/test/IDServiceTest.java
resteasy-links/src/main/java/org/jboss/resteasy/links/impl/LinkDecorator.java
resteasy-links/src/main/java/org/jboss/resteasy/links/AddLinks.java
resteasy-links/src/main/java/org/jboss/resteasy/links/RESTServiceDiscovery.java
可以看到一些resteasy-links
的tests使用到了@AddLinks
功能并进行测试。后续分析这些测试就可以学习AddLinks
的整套工作机制。