JAX-RS 從傻逼到牛叉 5:資源的動(dòng)態(tài)定位
Posted on 2011-12-21 16:00 蜀山兆孨龘 閱讀(2940) 評(píng)論(0) 編輯 收藏 所屬分類: Java EE 、SOA目前我們的電影服務(wù)只提供了對(duì)電影信息的訪問(wèn)服務(wù),現(xiàn)在我們要再增加兩項(xiàng)級(jí)服務(wù),分別用來(lái)訪問(wèn)導(dǎo)演和演員信息。加上原先的電信信息服務(wù),我們把 URI 統(tǒng)一放到 /ms/rest/service/
的子路徑下。最先想到的方法就是為這三個(gè) URI 分別寫(xiě) JAX-RS 服務(wù):
@Singleton @Path("service/movie") public class MovieService { // 此處省略若干行 } @Singleton @Path("service/director") public class DirectorService { // 此處省略若干行 } @Singleton @Path("service/director") public class ActorService { // 此處省略若干行 }
這種寫(xiě)法的缺點(diǎn)就是讓三個(gè)本來(lái)有點(diǎn)關(guān)系(父級(jí) URI 相同)的服務(wù)被放到了毫不相干的三個(gè)類里面,不一個(gè)個(gè)類地查看注解難以看出這點(diǎn)關(guān)系。為此,JAX-RS 提供了動(dòng)態(tài)資源綁定的功能,讓我們能夠?qū)@種情況做一些整理。
首先,我們引入一個(gè)服務(wù)定位器來(lái)處理集中管理這三個(gè)子級(jí)服務(wù):
@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
方法根據(jù)服務(wù)的名稱返回相應(yīng)的服務(wù)實(shí)例,注意該方法只有一個(gè) @Path
注解,因?yàn)樗⒉磺宄?qǐng)求的具體內(nèi)容;返回對(duì)象的類型為 Object
,表明動(dòng)態(tài)資源定位不要求服務(wù)類實(shí)現(xiàn)相同的接口,只需要它們的方法帶有相應(yīng)的 JAX-RS 注解,就能夠被 JAX-RS 自動(dòng)發(fā)現(xiàn)和處理(專業(yè)術(shù)語(yǔ)稱為 introspect,內(nèi)省),以 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); } } // 此處省略若干行 }
這樣,每個(gè)請(qǐng)求實(shí)際上都由兩個(gè)類先后處理。例如,處理請(qǐng)求 GET /ms/rest/service/movie/1
的時(shí)候,先由 ServiceLocator
返回相配的服務(wù)實(shí)例 movieService
,然后再由該實(shí)例的 find
方法返回結(jié)果。比起最開(kāi)始那三個(gè)簡(jiǎn)單的類,雖然多了一層調(diào)用,但換來(lái)了更加清晰的結(jié)構(gòu)。
動(dòng)態(tài)資源定位是一個(gè)非常靈活強(qiáng)大的功能,用好的話,完全可以把 URI 層次整理成一個(gè)類似于文件目錄結(jié)構(gòu)的抽象文件系統(tǒng)。