神奇好望角 The Magical Cape of Good Hope

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

          目前我們的電影服務(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)。

          主站蜘蛛池模板: 山阳县| 内乡县| 江川县| 渭南市| 嘉峪关市| 济阳县| 房产| 佳木斯市| 仙桃市| 临沧市| 沙坪坝区| 宝鸡市| 甘洛县| 信阳市| 句容市| 天镇县| 惠州市| 丰县| 乐都县| 东安县| 桃源县| 镇赉县| 噶尔县| 南丹县| 正蓝旗| 凤冈县| 山阴县| 隆安县| 定兴县| 青岛市| 璧山县| 策勒县| 山东省| 黄梅县| 景东| 同仁县| 祁连县| 天峻县| 平安县| 卓尼县| 南皮县|