GeoServer之kvpParser解析器&KvpRequestReader
参考1:https://blog.csdn.net/eternity_xyf/article/details/78531834
/**
* Parses a key-value pair into a key-object pair.
*
*This class is intended to be subclassed. Subclasses need declare the key in which they parse,
* and the type of object they parse into.
*
*Instances need to be declared in a spring context like the following:
*
*
*
* <bean id="myKvpParser" class="org.xzy.MyKvpParser"/>
*
*
*
* Wherecom.xzy.MyKvpParser
could be something like:
*
*
*
* public class MyKvpParser extends KvpParser {
*
* public MyKvpParser() {
* super( "MyKvp", MyObject.class )l
* }
*
* public Object parse( String value ) {
* return new MyObject( value );
* }
* }
*
*
*
*Operation Binding
*
*In the normal case, a kvp parser is engaged when a request specifies a name which matches the
* name declared by the kvp parser. It is also possible to attach a kvp parser so that it only
* engages on a particular operation. This is done by declaring the one or more of the following:
*
*
- service
* - version
* - request
*
*
*
*
When a kvp parser declares one or more of these properties, it will only be engaged if an
* incoming request specicfies matching values of the properties.
*
*
The following bean declaration would create the above kvp parser so that it only engages when
* the service is "MyService", and the request is "MyRequest".
*
*
*
* <bean id="myKvpParser" class="org.xzy.MyKvpParser">
* <property name="service">MyService</property>
* <property name="request">MyRequest</property>
* <bean>
*
*
*
* @author Justin Deoliveira, The Open Planning Project, jdeolive@openplans.org
*/
可以看出,这其实是一个虚函数。。
一个实现它的类FormatOptionsKvpParser extends KvpParser,主要是实现parse()方法。
@Override
public Object parse(String value) throws Exception {
MapformatOptions = new CaseInsensitiveMap<>(new TreeMap<>());
Listkvps = KvpUtils.escapedTokens(value, ';');
List parsers = GeoServerExtensions.extensions(KvpParser.class, applicationContext);
for (String kvp : kvps) {
Listkv = KvpUtils.escapedTokens(kvp, ':', 2);
String key = kv.get(0);
String raw = kv.size() == 1 ? "true" : KvpUtils.unescape(kv.get(1));
Object parsed = null;
for (Object o : parsers) {
KvpParser parser = (KvpParser) o;
if (key.equalsIgnoreCase(parser.getKey())) {
parsed = parser.parse(raw);
if (parsed != null) {
break;
}
}
}
if (parsed == null) {
if (LOGGER.isLoggable(Level.FINER))
LOGGER.finer(
"Could not find kvp parser for: '" + key + "'. Storing as raw string.");
parsed = raw;
}
formatOptions.put(key, parsed);
}
return formatOptions;
}
可以看出,这里调用GeoServerExtensions.extensions(KvpParser.class, applicationContext)注册KvpParser类到扩展中。这样做的好处是,下次就可以直接调用,不需要重新初始化了吗?()。那为什么不直接getbean。。
>>KvpRequestReader
findKvpRequestReader(Class<?> type):寻找KvpRequestReader,可以接收任意类型的类为参数,这里以Message.class为例。
首先调用loadKvpRequestReaders,加载所有的KvpRequestReaders。。
public static CollectionloadKvpRequestReaders() {
CollectionkvpReaders =
GeoServerExtensions.extensions(KvpRequestReader.class);
if (!(new HashSet<>(kvpReaders).size() == kvpReaders.size())) {
String msg = "Two identical kvp readers found";
throw new IllegalStateException(msg);
}
return kvpReaders;
}
当然在查找之前,肯定要先加载bean。。也就是applicationContext.xml,
URL url = getClass().getResource("applicationContext.xml");
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext(url.toString())
Dispatcher dispatcher = (Dispatcher) context.getBean("dispatcher");
所以是怎么在extensions中通过KvpRequestReader找到MessageKvpRequestReader的?
public class MessageKvpRequestReader extends KvpRequestReader {
public MessageKvpRequestReader() {
super(Message.class);
}
@Override
public Object createRequest() {
return new Message();
}
}
可以看出MessageKvpRequestReader是KvpRequestReader的子类。。
context.getBeanNamesForType(extensionPoint);