神奇好望角 The Magical Cape of Good Hope

庸人不必自扰,智者何需千虑?
posts - 26, comments - 50, trackbacks - 0, articles - 11
  BlogJava :: 首页 ::  :: 联系 :: 聚合  :: 管理

JAX-RS 从傻逼到牛叉 5:资源的动态定位

Posted on 2011-12-21 16:00 蜀山兆孨龘 阅读(2898) 评论(0)  编辑  收藏 所属分类: Java EESOA

目前我们的电影服务只提供了对电影信息的访问服务,现在我们要再增加两项级服务,分别用来访问导演和演员信息。加上原先的电信信息服务,我们把 URI 统一放到 /ms/rest/service/ 的子路径下。最先想到的方法就是为这三个 URI 分别写 JAX-RS 服务:

@Singleton
@Path("service/movie")
public class MovieService {
    // 此处省略若干行
}

@Singleton
@Path("service/director")
public class DirectorService {
    // 此处省略若干行
}

@Singleton
@Path("service/director")
public class ActorService {
    // 此处省略若干行
}
    

这种写法的缺点就是让三个本来有点关系(父级 URI 相同)的服务被放到了毫不相干的三个类里面,不一个个类地查看注解难以看出这点关系。为此,JAX-RS 提供了动态资源绑定的功能,让我们能够对这种情况做一些整理。

首先,我们引入一个服务定位器来处理集中管理这三个子级服务:

@Singleton
@Path("service")
public class ServiceLocator {
    @Inject
    private MovieService movieService;
    @Inject
    private DirectorService directorService;
    @Inject
    private ActorService actorService;
    private Map<String, Object> serviceMap;

    @PostConstruct
    private initServiceMap() {
        serviceMap = new HashMap<>();
        serviceMap.put("movie", movieService);
        serviceMap.put("director", directorService);
        serviceMap.put("actor", actorService);
    }

    @Path("{name}")
    public Object locateService(@PathParam("name") String name) {
        Object service = serviceMap.get(name);
        if (service == null) {
            throw new WebApplicationException(Status.SERVICE_UNAVAILABLE);
        }
        return service;
    }
}
    

该类中的 locateService 方法根据服务的名称返回相应的服务实例,注意该方法只有一个 @Path 注解,因为它并不清楚请求的具体内容;返回对象的类型为 Object,表明动态资源定位不要求服务类实现相同的接口,只需要它们的方法带有相应的 JAX-RS 注解,就能够被 JAX-RS 自动发现和处理(专业术语称为 introspect,内省),以 MovieService 为例:

@Singleton
public class MovieService {
    @GET
    @Path("{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public Movie find(@PathParam("id") int id) {
        Movie movie = movieDao.get(id);
        if (movie != null) {
            return movie;
        } else {
            throw new WebApplicationException(Status.NOT_FOUND);
        }
    }

    // 此处省略若干行
}

这样,每个请求实际上都由两个类先后处理。例如,处理请求 GET /ms/rest/service/movie/1 的时候,先由 ServiceLocator 返回相配的服务实例 movieService,然后再由该实例的 find 方法返回结果。比起最开始那三个简单的类,虽然多了一层调用,但换来了更加清晰的结构。

动态资源定位是一个非常灵活强大的功能,用好的话,完全可以把 URI 层次整理成一个类似于文件目录结构的抽象文件系统。


只有注册用户登录后才能发表评论。


网站导航: