spring - 在 Tomcat 服务器上的应用程序中实现不同的目的地

标签 spring spring-mvc tomcat jco sap-r3

今年早些时候,我为我的一个 Spring MVC tomcat 应用程序开发了 SAP JCO CustomDestinationProvider 的实现。在我的应用程序中,我使用此实现在我的 SAP R/3 系统中调用 BAPI 来检索数据。

我现在正在开发第二个 Spring MVC tomcat 应用程序,我想在我的 SAP R/3 系统中调用 BAPI 来检索数据。我将调用不同的 BAPI,因此我将检索不同的数据。因为这是调用不同 BAPI 的不同应用程序,所以我想在我的配置中使用不同的 SAP 系统用户。这个新应用程序将运行在与第一个应用程序相同的物理 tomcat 服务器上。

我的问题是我应该为这个新应用程序开发 SAP JCO CustomDestinationProvider 的另一个实现,还是应该以某种方式重用第一个实现?如果答案是我应该为这个新应用程序开发另一个实现,那么我希望我会为我开发的每个需要与 SAP 通信的新 Spring MVC tomcat 应用程序开发另一个实现。这是正确的想法吗?

如果我为我的这个新应用程序做不同的实现,我应该在代码中使用相同的目标名称,还是应该使用不同的名称? 下面是我第一次实现 CustomDestinationDataProvider 的代码:

public class CustomDestinationDataProvider {
public class MyDestinationDataProvider implements DestinationDataProvider {
    private DestinationDataEventListener eL;
    private HashMap<String, Properties> secureDBStorage = new HashMap<String, Properties>();

    public Properties getDestinationProperties(String destinationName) {
        try {
            Properties p = secureDBStorage.get(destinationName);
            if(p!=null) {
                if(p.isEmpty())
                    throw new DataProviderException(DataProviderException.Reason.INVALID_CONFIGURATION, "destination configuration is incorrect", null);
                return p;
            }
            return null;
        } catch(RuntimeException re) {
            throw new DataProviderException(DataProviderException.Reason.INTERNAL_ERROR, re);
        }
    }
    public void setDestinationDataEventListener(DestinationDataEventListener eventListener) {
        this.eL = eventListener;
    }
    public boolean supportsEvents() {
        return true;
    }
    public void changeProperties(String destName, Properties properties) {
        synchronized(secureDBStorage) {
            if(properties==null) {
                if(secureDBStorage.remove(destName)!=null)
                    eL.deleted(destName);
            } else {
                secureDBStorage.put(destName, properties);
                eL.updated(destName); // create or updated
            }
        }
    }
}

public ArrayList<String> executeSAPCall(Properties connectProperties, ArrayList<String> partnumbers) throws Exception {
    String destName = "ABAP_AS";
    SAPDAO sapDAO = new SAPDAO(); 
    ArrayList<MaterialBean> searchResults = new ArrayList<MaterialBean>();
    MyDestinationDataProvider myProvider = new MyDestinationDataProvider();
    boolean destinationDataProviderRegistered = com.sap.conn.jco.ext.Environment.isDestinationDataProviderRegistered();
    JCoDestination dest;
    try {
        if (!destinationDataProviderRegistered) {
            com.sap.conn.jco.ext.Environment.registerDestinationDataProvider(myProvider);
            myProvider.changeProperties(destName, connectProperties);
        }
    } catch(IllegalStateException providerAlreadyRegisteredException) {
        logger.error("executeSAPCall: providerAlreadyRegisteredException!");
    }
    try {
        dest = JCoDestinationManager.getDestination(destName);
        searchResults = sapDAO.searchSAP(dest, partnumbers);
    } catch(JCoException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return searchResults;
}  
}

如果答案是我不需要为我的第二个应用程序实现另一个 CustomDestinationDataProvider,我还需要牢记哪些其他注意事项?

最佳答案

您只能注册一个 DestinationDataProvider,因此您设置的那个必须能够处理两个(或多个)不同的连接。为此,您需要为每个连接指定唯一的名称,即 destName 不能是固定值 ABAP_AS,您需要为每个连接创建一个。

您当前的提供程序实现对我来说看起来不错,但是在我看来,您调用 RFC 时的方法将连接的创建和实际的 RFC 调用混合在一起太多了。恕我直言,您应该将前者分离到它自己的方法中,这样您就可以从应用程序的其他部分调用它,例如做除 RFC 调用之外的其他事情。

关于spring - 在 Tomcat 服务器上的应用程序中实现不同的目的地,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46280376/

相关文章:

java - 根据请求url自动选择viewResolver?

java - 将 Spring MVC 投影与 JSON 和 Jackson 结合使用

java - 贾斯珀异常 : equal symbol expected

java - 使用默认模板的 spring mvc 出现 404 错误

java - Freemarker 找不到 JSP tld-s

java - Tomcat 7.0 启动时抛出错误

java - Tomcat 何时将 war 文件解压缩到 ROOT 文件夹?

java - 在数据库插入之前修剪空格

java - Spring Hibernate 的分页

javascript - 我如何从我的 View (jsp)将复杂对象列表传递给 Controller