在Wicket 6中覆盖内置映射器的正确方法

时间:2017-03-11 16:18:57

标签: java wicket

Wicket 6有一个默认的复合请求映射器:SystemMapper。它包含BookmarkableMapper。我需要覆盖它,也就是说,改为使用我自己的FancyBookmarkableMapper

我尝试了什么:

  1. 复制SystemMapper课程作为一个整体并更改以下行
  2. add(new BookmarkableMapper());

    add(new FancyBookmarkableMapper());
    

    但这种方式非常丑陋且易于升级(尽管它似乎有效)。我这里只是为了完整而提到它。

    1. 使用SystemMapperICompoundMapper的事实,使用add()remove()iterator()方法替换映射器:

      private SystemMapper customizeSystemMapper() {
          final SystemMapper rootRequestMapper = (SystemMapper) getRootRequestMapper();
      
          IRequestMapper originalBookmarkableMapper = null;
          boolean afterBookmarkable = false;
          List<IRequestMapper> mappersAfterBookmarkable = new ArrayList<>();
          for (IRequestMapper mapper : rootRequestMapper) {
              if (mapper.getClass() == BookmarkableMapper.class) {
                  if (originalBookmarkableMapper != null) {
                      throw new IllegalStateException("There are two BookmarkableMapper instances in the initial mappers list");
                  }
                  originalBookmarkableMapper = mapper;
                  afterBookmarkable = true;
              } else {
                  if (afterBookmarkable) {
                      mappersAfterBookmarkable.add(mapper);
                  }
              }
          }
          if (originalBookmarkableMapper == null) {
              throw new IllegalStateException("There is no BookmarkableMapper in the initial mappers list");
          }
      
          for (IRequestMapper mapperToRemove : mappersAfterBookmarkable) {
              rootRequestMapper.remove(mapperToRemove);
          }
          rootRequestMapper.remove(originalBookmarkableMapper);
          rootRequestMapper.add(new FancyBookmarkableMapper());
          for (IRequestMapper mapperToAdd : mappersAfterBookmarkable) {
              rootRequestMapper.add(mapperToAdd);
          }
          return rootRequestMapper;
      }
      
    2. 虽然效果也不错,但也不是很好。

      1. 构建ICompoundMapper的实现并用它装饰SystemMapper实例。替换内置映射器的唯一方法是尝试使用iterator()方法:

        @Override
        public Iterator<IRequestMapper> iterator() {
            return new Iterator<IRequestMapper>() {
                private Iterator<IRequestMapper> originalIterator = delegate.iterator();
        
                @Override
                public boolean hasNext() {
                    return originalIterator.hasNext();
                }
        
                @Override
                public IRequestMapper next() {
                    IRequestMapper nextMapper = originalIterator.next();
                    if (nextMapper != null && nextMapper.getClass() == BookmarkableMapper.class) {
                        nextMapper = bookmarkableMapperReplacement;
                    }
                    return nextMapper;
                }
        
                @Override
                public void remove() {
                    originalIterator.remove();
                }
            };
        }
        
      2. 但是,这不起作用,因为SystemMapper#mapRequest()(实际上在CompoundRequestMapper中定义)直接使用mappers字段,而不是iterator()方法。

        1. 最简单的方法:

          private SystemMapper customizeSystemMapper2() {
              final SystemMapper rootRequestMapper = (SystemMapper) getRootRequestMapper();
              rootRequestMapper.add(new FancyBookmarkableMapper());
              return rootRequestMapper;
          }
          
        2. 这里我们将mapper添加到列表的开头。它扩展BookmarkableMapper并继承其getCompatibilityScore(),因此它与BookmarkableMapper具有相同的分数,并且它在列表的前面,因此它优先。

          这个项目4实际上有效。唯一能让我问这个问题的是,实际上,这两种映射器都位于SystemMapper的内部列表中。是否可以保证我的映射器(后来添加并具有相同的分数)优先(包括未来的Wicket版本)?

1 个答案:

答案 0 :(得分:1)

最简单(和官方)的方法是在YourApplication#init()方法中使用WebApplication#mount(new FancyBookmarkableMapper ()

明天我会检查你在3)的关注! 更新:使用https://git1-us-west.apache.org/repos/asf?p=wicket.git;a=commitdiff;h=0eb63480;hp=5821157738ac43a09232a2aeb0fa2ff808340f4d进行了改进 如果您看到更多改进,请告诉我们!谢谢!