神奇好望角 The Magical Cape of Good Hope

          庸人不必自擾,智者何需千慮?
          posts - 26, comments - 50, trackbacks - 0, articles - 11
            BlogJava :: 首頁 ::  :: 聯(lián)系 :: 聚合  :: 管理

          JAX-RS 從傻逼到牛叉 5:資源的動態(tài)定位

          Posted on 2011-12-21 16:00 蜀山兆孨龘 閱讀(2932) 評論(0)  編輯  收藏 所屬分類: Java EE 、SOA

          目前我們的電影服務只提供了對電影信息的訪問服務,現(xiàn)在我們要再增加兩項級服務,分別用來訪問導演和演員信息。加上原先的電信信息服務,我們把 URI 統(tǒng)一放到 /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 提供了動態(tài)資源綁定的功能,讓我們能夠對這種情況做一些整理。

          首先,我們引入一個服務定位器來處理集中管理這三個子級服務:

          @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ù)服務的名稱返回相應的服務實例,注意該方法只有一個 @Path 注解,因為它并不清楚請求的具體內(nèi)容;返回對象的類型為 Object,表明動態(tài)資源定位不要求服務類實現(xiàn)相同的接口,只需要它們的方法帶有相應的 JAX-RS 注解,就能夠被 JAX-RS 自動發(fā)現(xiàn)和處理(專業(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);
                  }
              }
          
              // 此處省略若干行
          }
          

          這樣,每個請求實際上都由兩個類先后處理。例如,處理請求 GET /ms/rest/service/movie/1 的時候,先由 ServiceLocator 返回相配的服務實例 movieService,然后再由該實例的 find 方法返回結果。比起最開始那三個簡單的類,雖然多了一層調(diào)用,但換來了更加清晰的結構。

          動態(tài)資源定位是一個非常靈活強大的功能,用好的話,完全可以把 URI 層次整理成一個類似于文件目錄結構的抽象文件系統(tǒng)。

          主站蜘蛛池模板: 嘉鱼县| 牡丹江市| 万盛区| 宽城| 扶余县| 封丘县| 山东省| 天水市| 镇雄县| 南岸区| 贵溪市| 务川| 毕节市| 浦江县| 泗阳县| 台中县| 富顺县| 奈曼旗| 老河口市| 张家川| 胶南市| 达孜县| 深泽县| 桓台县| 隆昌县| 韩城市| 湾仔区| 宿迁市| 常山县| 兴国县| 微山县| 兴业县| 曲靖市| 定结县| 尼勒克县| 乐亭县| 黄平县| 濮阳市| 如东县| 唐山市| 翁源县|