在Java

时间:2017-02-23 14:01:26

标签: java xml multithreading jaxb

我目前正在开发一个通过套接字接收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中)?有什么想法吗?

1 个答案:

答案 0 :(得分:0)

一种可能的解决方案是反思。 此处介绍的解决方案假设如下

  1. 处理器可以处理多种xml消息类型(例如AuthorizationDataFacade处理AccessCheckLogin消息)
  2. 强制执行流程方法的约定:它必须命名为" process",有一个arg类型为一个xml消息,并且具有已知的返回类型。此约定用于为给定类型的xml msg搜索正确的处理方法。
  3. 当您需要处理新的xml消息时,根据约定(在您认为合适的任何类中)编写其process()方法,并向dispatchMap添加一个条目。那就是它。
  4. 解决方案如下所示,我添加了一些注释以澄清事情:

    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"));
        }
    }