简体   繁体   English

如何在不使用DAO的情况下使用Spring LDAP连接到多个URL?

[英]How to use Spring LDAP to connect to multiple urls without DAOs?

Currently I have an LDAP management system that uses Spring LDAP to connect to the LDAP server and manage it; 目前,我有一个LDAP管理系统,该系统使用Spring LDAP连接到LDAP服务器并对其进行管理。 however if I want to change to a different server, I have to shut down the system, change the config settings, and restart it. 但是,如果要更改为其他服务器,则必须关闭系统,更改配置设置,然后重新启动。 It would be much simpler if I could simply have a dropdown that allowed me to swap between different servers. 如果我可以简单地创建一个下拉菜单,使我可以在不同的服务器之间进行交换,那将更加简单。

Because of this, I'm investigating the possibility of setting the Context Source dynamically. 因此,我正在研究动态设置上下文源的可能性。 I have found Incorrect injection between beans , and the answer there looks like the sort of thing I would like to be able to accomplish. 我发现bean之间注入不正确 ,那里的答案看起来像我想完成的事情。 However, my system does not use DAOs, but rather uses LdapRepository to manage the users. 但是,我的系统不使用DAO,而是使用LdapRepository来管理用户。

My question is : how do I change the ContextSource being used by Spring to interact with LdapRepository classes at runtime as opposed to set in an xml file, while maintaining my current project structure as much as possible? 我的问题是 :如何更改Spring用于在运行时与LdapRepository类进行交互的ContextSource(而不是在xml文件中进行设置),同时尽可能地保持当前的项目结构?

I do not want to convert everything to use DAOs, but rather have such a feature work with existing code. 我不想将所有内容都转换为使用DAO,而是希望将这种功能与现有代码一起使用。

Edit: should also probably mention I'm letting Spring bootstrap the implementations of the repositories as well. 编辑:也许还应该提到我让Spring引导存储库的实现。

I found that other post on SO (not directly related to your question) that shows how to scope a LDAPTemplate in session. 我发现SO上的其他文章 (与您的问题没有直接关系)显示了如何在会话中LDAPTemplate范围。

Without knowing more of your sources, I cannot be sure that this solution will work for you, but I think it's worth trying. 在不了解您的更多消息来源的情况下,我不确定该解决方案是否适合您,但我认为值得尝试。

You should declare your LDAPTemplate scoped in session : 您应该在session中声明LDAPTemplate的作用域:

<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate" 
      p:contextSource_ref="contextSource" scope="session">
    <aop:scope-proxy/>
</bean>

You should try to inject it in your LDAPRepository classes as a LDAPOperation to allow Spring AOP to use JDK proxies. 您应该尝试将其作为LDAPOperation注入LDAPRepository类中,以允许Spring AOP使用JDK代理。 If it is not possible, you should configure Spring AOP to use cglib by <aop:scope-proxy proxy-target-class="true"/> 如果不可能,则应通过<aop:scope-proxy proxy-target-class="true"/>将Spring AOP配置为使用cglib

At the place you want to change your ContextSource , inject the LDAPTemplate . 在您要更改ContextSource ,注入LDAPTemplate If you could use JDK Proxies, inject it as a LDAPOperation to get the scoped proxy. 如果可以使用JDK代理,请将其作为LDAPOperation注入以获得作用域代理。 You should be able to get the correct LDAPTemplate via the Advised interface implemented by Spring AOP proxies : 你应该能够得到正确的LDAPTemplate通过Advised通过Spring AOP的代理实现的接口:

LDAPOperation ldapOperation;
...
LDAPTemplate ldapTemplate = (LDAPTemplate) ((Advised)ldapOperation)
                                             .getTargetSource().getTarget();
ldapTemplate.setContextSource(newContextSource);

Here are the references for accessing the target of a Spring AOP proxy : How To Acess Target Object Behind a Spring Proxy from Tech Per 以下是访问Spring AOP代理目标的参考: 如何从Tech Perl访问Spring代理后面的目标对象

This is kind of a cornercase. 这有点险恶。 The library is really not designed to do this, but I think the easiest way to achieve what you're trying to do would be to implement a custom delegating ContextSource that keeps references to all the different actual ContextSources you want to be able to use, eg: 该库实际上并非旨在执行此操作,但我认为实现您要尝试的操作的最简单方法是实现自定义委托ContextSource ,该引用保留对您要使用的所有不同实际ContextSource的引用,例如:

public class SessionBasedDelegatingContextSource implements ContextSource {
  private Map<String, ContextSource> contextSources;

  @Required
  public void setContextSources(Map<String, ContextSource> contextSources) {
    this.contextSources = new HashMap<>(contextSources);
  }

  protected final ContextSource getSessionContextSource() {
    String id = (String) RequestContextHolder.currentRequestAttributes()
                 .getAttribute("currentContextSource", SCOPE_SESSION);

    if(id == null) {
      throw new IllegalStateException("No Ldap target selected");
    }

    ContextSource contextSource = contextSources.get(id);
    if(contextSource == null) {
      throw new IllegalArgumentException("No Ldap target selected");
    }

    return contextSource;
  }

  @Override
  public DirContext getReadOnlyContext() {
    getSessionContextSource().getReadOnlyContext();
  }

  @Override
  public DirContext getReadWriteContext() {
    getSessionContextSource().getReadWriteContext();
  }

  @Override
  public DirContext getContext(String principal, String credentials) {
    getSessionContextSource().getContext(principal, credentials);
  }
}

Now, if you register a RequestContextFilter , declare all your different ContextSources, inject them to a SessionBasedDelegatingContextSource , and use this as the ContextSource for your repositories (ie the ContextSource used by your defined LdapTemplate), all you need to do is put an appropriate ContextSource identifier in the session and you should be OK. 现在,如果您注册一个RequestContextFilter ,声明所有不同的ContextSource,将它们注入到SessionBasedDelegatingContextSource ,并将其用作存储库的ContextSource(即,已定义的LdapTemplate使用的ContextSource),您要做的就是放置一个适当的ContextSource。会话中的标识符,您应该可以。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM