GeoServer之kvpParser解析器&KvpRequestReader

参考1:https://blog.csdn.net/eternity_xyf/article/details/78531834

/**
* Parses a key-value pair into a key-object pair.
*
* <p>This class is intended to be subclassed. Subclasses need declare the key in which they parse,
* and the type of object they parse into.
*
* <p>Instances need to be declared in a spring context like the following:
*
* <pre>
* <code>
* &lt;bean id="myKvpParser" class="org.xzy.MyKvpParser"/&gt;
* </code>
* </pre>
*
* Where <code>com.xzy.MyKvpParser</code> could be something like:
*
* <pre>
* <code>
* public class MyKvpParser extends KvpParser {
*
* public MyKvpParser() {
* super( "MyKvp", MyObject.class )l
* }
*
* public Object parse( String value ) {
* return new MyObject( value );
* }
* }
* </code>
* </pre>
*
* <p><b>Operation Binding</b>
*
* <p>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:
*
* <ul>
* <li>service
* <li>version
* <li>request
* </ul>
*
* <p>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.
*
* <p>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".
*
* <pre>
* <code>
* &lt;bean id="myKvpParser" class="org.xzy.MyKvpParser"&gt;
* &lt;property name="service"&gt;MyService&lt;/property&gt;
* &lt;property name="request"&gt;MyRequest&lt;/property&gt;
* &lt;bean&gt;
* </code>
* </pre>
*
* @author Justin Deoliveira, The Open Planning Project, jdeolive@openplans.org
*/

可以看出,这其实是一个虚函数。。

一个实现它的类FormatOptionsKvpParser extends KvpParser,主要是实现parse()方法。

@Override
public Object parse(String value) throws Exception {
Map<String, Object> formatOptions = new CaseInsensitiveMap<>(new TreeMap<>());
List<String> kvps = KvpUtils.escapedTokens(value, ';');
List parsers = GeoServerExtensions.extensions(KvpParser.class, applicationContext);
for (String kvp : kvps) {
List<String> kv = 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类到扩展中。这样做的好处是,下次就可以直接调用,不需要重新初始化了吗?(工厂模式的Registry)。那为什么不直接getbean。。

>>KvpRequestReader

findKvpRequestReader(Class<?> type):寻找KvpRequestReader,可以接收任意类型的类为参数,这里以Message.class为例。

首先调用loadKvpRequestReaders,加载所有的KvpRequestReaders。。

public static Collection<KvpRequestReader> loadKvpRequestReaders() {
Collection<KvpRequestReader> kvpReaders =
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);
原文地址:https://www.cnblogs.com/2008nmj/p/15817651.html