Wicket 6有一个默认的复合请求映射器:SystemMapper
。它包含BookmarkableMapper
。我需要覆盖它,也就是说,改为使用我自己的FancyBookmarkableMapper
。
我尝试了什么:
SystemMapper
课程作为一个整体并更改以下行 add(new BookmarkableMapper());
到
add(new FancyBookmarkableMapper());
但这种方式非常丑陋且易于升级(尽管它似乎有效)。我这里只是为了完整而提到它。
使用SystemMapper
为ICompoundMapper
的事实,使用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;
}
虽然效果也不错,但也不是很好。
构建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();
}
};
}
但是,这不起作用,因为SystemMapper#mapRequest()
(实际上在CompoundRequestMapper
中定义)直接使用mappers
字段,而不是iterator()
方法。
最简单的方法:
private SystemMapper customizeSystemMapper2() {
final SystemMapper rootRequestMapper = (SystemMapper) getRootRequestMapper();
rootRequestMapper.add(new FancyBookmarkableMapper());
return rootRequestMapper;
}
这里我们将mapper添加到列表的开头。它扩展BookmarkableMapper
并继承其getCompatibilityScore()
,因此它与BookmarkableMapper
具有相同的分数,并且它在列表的前面,因此它优先。
这个项目4实际上有效。唯一能让我问这个问题的是,实际上,这两种映射器都位于SystemMapper
的内部列表中。是否可以保证我的映射器(后来添加并具有相同的分数)优先(包括未来的Wicket版本)?
答案 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进行了改进 如果您看到更多改进,请告诉我们!谢谢!