我目前正在开发一个通过套接字接收XML消息的Java应用程序。有不同类型的XML消息,我现在正在寻找最优雅的方式/最佳实践来正确发送和处理这些消息。
目前我有一个工作测试设置,其中包含一个包含一个接收已经解析过的消息的进程方法的一般Dispatch类。对于这些类型中的每一种,我都有一个特定的处理方法。用于测试连接等但不是那么漂亮。
public class Dispatch
public Object process(XMLMessage xml){
Object obj = xml.getXml();
if (obj instanceof AccessCheck)
return processObject((AccessCheck) obj);
else if (obj instanceof Note)
return processObject((Note) obj);
else if (obj instanceof Login)
return processObject((Login) obj);
...
return null;
}
}
由于最终解决方案包含更多消息类型,并且还应包含数据库连接和缓存,我正在寻找一种方法来对每个域的消息进行分组处理,并且最好还使用显式强制转换来消除或减少这个大的if语句
我考虑过这样做,每个域都有一个门面(这也允许每个域有一个单独的缓存):
public class Dispatch
public Object process(XMLMessage xml){
Object obj = xml.getXml();
if (obj instanceof AccessCheck)
return AuthorizationDataFacade.process((AccessCheck) obj);
else if (obj instanceof Note)
return SomeOtherDataFacade.process((Note) obj);
else if (obj instanceof Login)
return AuthorizationDataFacade.process((Login) obj);
...
return null;
}
}
public class AuthorizationDataFacade {
public Object processAccessCheck(AccessCheck check){
//do something and return the response
return null;
}
public Object processLogin(Login login){
//do something and return the response
return null;
}
但是有没有办法用显式转换消除那个大的if语句?或者我应该重新考虑我的XSD / XML设计并将一些消息合并在一起(即将AccessCheck和Login合并到一般授权xml中)?有什么想法吗?
答案 0 :(得分:0)
一种可能的解决方案是反思。 此处介绍的解决方案假设如下
AuthorizationDataFacade
处理AccessCheck
和Login
消息)process()
方法,并向dispatchMap
添加一个条目。那就是它。解决方案如下所示,我添加了一些注释以澄清事情:
import java.lang.reflect.*;
import java.util.*;
public class Dispatcher
{
// the map associates xml msg type to processor type
private static Map<Class<?>, Class<?>> dispatchMap = new HashMap<>();
static
{
dispatchMap.put(AccessCheck.class, AuthorizationDataFacade.class);
dispatchMap.put(Login.class, AuthorizationDataFacade.class);
dispatchMap.put(Note.class, SomeOtherDataFacade.class);
}
public String dispatch(Object obj)
{
Class<?> xmlMsgType = obj.getClass();
// search for xml msg type in dispatch map
if (!dispatchMap.containsKey(xmlMsgType)) {
return "unrecognized message type";
}
// found match, now locate process method
try {
Class<?> ProcessorType = dispatchMap.get(xmlMsgType);
Method[] processorTypeMethods = ProcessorType.getDeclaredMethods();
Method chosenProcssMethod =
Arrays.stream(processorTypeMethods)
.filter(m -> methodFitForXmlMsg(m, xmlMsgType))
.findFirst()
.orElse(null);
if (chosenProcssMethod != null) {
// found match, instantiate processor and invoke method
Object processorInstance = ProcessorType.newInstance();
return (String)chosenProcssMethod.invoke(
processorInstance,
chosenProcssMethod.getParameterTypes()[0].cast(obj));
}
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
// no match found or error
return "error";
}
// a method is dimmed fit for processing a given xml msg type
// if it is named "process", returns a String, has one arg that is of the given type
private boolean methodFitForXmlMsg(Method m, Class<?> xmlMsgType)
{
return m.getName().equals("process") &&
m.getReturnType() == String.class &&
m.getParameterCount() == 1 &&
m.getParameterTypes()[0].equals(xmlMsgType);
}
public static void main(String... args)
{
Dispatcher d = new Dispatcher();
System.out.println(d.dispatch(new AccessCheck()));
System.out.println(d.dispatch(new Login()));
System.out.println(d.dispatch(new Note()));
System.out.println(d.dispatch("something else"));
}
}