2016-12-12 18 views
0

我在我的項目中使用Spring來進行依賴注入,但是我需要根據用戶登錄在生產環境和測試之間進行更改。 (有生產/測試checbox)如何根據用戶選擇在生產和測試彈簧環境之間進行切換?

每個用戶可以決定選擇生產數據庫還是測試數據庫。

我閱讀了@Profile,但每個配置文件都是在服務器或應用程序運行時定義的,但是我需要在登錄後更改此配置文件。

我該怎麼做?春天有可能嗎?

這是一些類來解釋這個問題:

的applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-4.0.xsd"> 

    <bean class="br.com.cpb.gsa.config.AppConfig" /> 
    <context:component-scan base-package="br.com.cpb.gsa" /> 

</beans> 

的AppConfig類

@Configuration 
@EnableVaadin 
public class AppConfig { 

    private DataSource dataSource; 

    @Profile("production") 
    @Bean(name = "dataSource") 
    public DataSource datasourceProdction() { 
     DriverManagerDataSource ds = new DriverManagerDataSource(); 
     ds.setDriverClassName("net.sourceforge.jtds.jdbc.Driver"); 
     ds.setUrl("jdbc:jtds:sqlserver://ip:1433;databaseName=myDataBase"); 
     ds.setUsername("user"); 
     ds.setPassword("pass"); 

     return this.dataSource = ds; 
    } 

    @Profile("test") 
    @Bean(name = "dataSource") 
    public DataSource datasourceProdction() { 
     DriverManagerDataSource ds = new DriverManagerDataSource(); 
     ds.setDriverClassName("net.sourceforge.jtds.jdbc.Driver"); 
     ds.setUrl("jdbc:jtds:sqlserver://ip:1433;databaseName=myDataBaseTest"); 
     ds.setUsername("user"); 
     ds.setPassword("pass"); 

     return this.dataSource = ds; 
    } 

    public DataSource getDataSource() { 
     return dataSource; 
    } 

    public void setDataSource(DataSource dataSource) { 
     this.dataSource = dataSource; 
    } 

} 

GSAUI - 我Vaadin類

@Theme("gsaTheme") 
@SpringUI 
@SpringViewDisplay 
public class GSAUI extends UI { 

    private static final long serialVersionUID = -4276841722171307964L; 

    public static final String VIEW_NAME = "mainView"; 

    @Autowired 
    ApplicationContext applicationContext; 

    @WebListener 
    public static class MyContextLoaderListener extends ContextLoaderListener { 
    } 

    ..... 

} 

d AO - UserDAO的

@Repository("userDAO") 
public class UserDAOImpl implements UserDAO { 

    @Autowired 
    private DataSource dataSource; 

    @Override 
    public Usuario getAuthenticatedUser(String login) { 

     try (Connection conn = dataSource.getConnection()){ 

      //... sample code, just for explanation ... 
      Usuario user = new Usuario(); 
      user.setLogin("test"); 

      return user; 

     } catch (SQLException e) { 
      throw new RuntimeException(e); 
     } 
    } 
} 

服務 - login服務

@Service("loginService") 
public class LoginServiceImpl implements LoginService, Serializable { 

    private static final long serialVersionUID = 4014652022146807624L; 

    @Autowired 
    private UserDAO userDAO; 

    public Usuario doLogin(Usuario user){ 

     if ((user == null) ||     (JavaUtil.isNull(user.getLogin(),"").trim().length() == 0)){ 
     throw new RuntimeException(Constant.LOGIN_OR_PASSWORD_NOT_PROVIDED); 
     } 

     //UsuarioDAO dao = (UsuarioDAO)  applicationContext.getBean("usuarioDAO"); 
     Usuario savedUser = userDAO.getAuthenticatedUser(user.getLogin()); 

     if ((savedUser == null) || (!savedUser.getSenha().equals(user.getSenha()))){ 
      throw new RuntimeException(Constant.INVALID_USER_OR_PASSWORD); 
     } 

     return user; 
    } 

} 

LoginView - 用戶登錄,並決定要使用的模式

@SpringView(name = LoginView.VIEW_NAME) 
public class LoginView extends LoginDesign implements View { 

    private static final long serialVersionUID = 1L; 
    public static final String VIEW_NAME = "loginView"; 

    public LoginView() { 
     setSizeFull(); 

     btnEnter.setClickShortcut(KeyCode.ENTER); 
     btnEnter.addClickListener(e -> this.login()); 
    } 

    public void login() { 
     Usuario user = new Usuario(); 

     user.setLogin(login.getValue()); 
     user.setSenha(senha.getValue()); 

     /******** Here i would like to define the profile, but the context  already have been loaded ********/ 
     ConfigurableEnvironment env = (ConfigurableEnvironment) ((GSAUI)getUI()).getApplicationContext().getEnvironment(); 

     if (user.getSenha() == "spedtjob"){ 
      env.setActiveProfiles("producao"); 
     }else{ 
      env.setActiveProfiles("test"); 
     user.setSenha("spedtjob"); 
     } 

     LoginService loginService = (LoginService) ((GSAUI)getUI()).getApplicationContext().getBean(LoginService.class); 
     Usuario loggedUser = loginService.doLogin(user); 

     System.out.println(loggedUser.getLogin()); 
     getUI().removeStyleName("loginview"); 

     ((GSAUI)getUI()).setUser(loggedUser); 

     getUI().getNavigator().navigateTo(((GSAUI)getUI()).getRedirectPage());  
     ((Window)getParent()).close(); 
    } 


} 

我用這種方法測試,但不起作用。 我將不勝感激。

+2

*爲什麼*你是這樣做的,而不是單獨推出?如果您的暫存代碼中存在一個令人討厭的錯誤,並且正在以編程方式進行切換,那麼您的生產系統就像完全取消臨時環境一樣危險。 – chrylis

+0

Hi @chrylis!我瞭解風險,但我們有15家公司使用相同的系統,並部署15個系統對我們來說會更加複雜。 – Weles

回答

1

在我給出答案之前,我還想建議完全分開運行測試和生產系統 - 我會嘗試僅使一個常用登錄頁面,讓用戶登錄,然後重定向到基於用戶選擇系統。

但是,如果你想在單個JVM測試/生產那麼我認爲「春天的bean作用域」你在找什麼:http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-factory-scopes

默認範圍是「單身」,這意味着,在應用程序開始時創建和連接bean,然後很難更改它們。

如果你想爲用戶A使用不同的DataSource bean,而對於用戶B不同,那麼你可能需要爲你的DataSource bean使用「session」作用域(甚至可能是「request」作用域) - 這意味着即使你使用@Autowired作爲DataSource,將爲每個會話創建實際的bean - >這意味着您可以控制將爲每個登錄用戶使用哪個bean ...

+0

我使用vaadin彈簧,由於某種原因會話或請求不適合我,但原型是。謝謝! – Weles

1

你可以以某種方式保存用戶的選擇(在一個數據庫中,在一個bean內......等)並且連接到兩個數據庫。訪問數據庫時,請檢查以確定實際訪問哪個數據庫。

您可能想要創建一個專用於決定爲每個用戶使用哪個數據庫的bean。

但是,如果您的預算允許,我會建議做@chrylis所說的並分開部署。它可以避免大量的問題(比如已經指出的問題),並且可以減少代碼的複雜性。

+0

嗨@Adam Rosini我看不到如何做到這一點,因爲dataSource是通過「@Autowire」註釋注入的,我無法傳遞參數。你有樣品嗎? – Weles

+0

@Weles注入兩個數據源(testDatasource,prodDatasource)。 http://stackoverflow.com/questions/30362546/how-to-use-2-or-more-databases-with-spring。但是你必須小心確保始終使用正確的數據源!這是有風險的,但如果它真的需要,我會用下面的方法創建一個bean:'getDataSourceForUser(...)' – Adam

+0

Hi @Adam Rosini!好,我明白了。我想找到一個像配置文件這樣的選項,可以在運行時更改。但感謝解釋。 – Weles

相關問題