2016-11-09 120 views
0

我有一個基本的控制器(Spring MVC),它將獲取我的網站的用戶數據。它具有不同的端點,可以在不同的環境數據源中搜索/添加/更新數據。我的問題是,根據配置值,我只需要從某些環境中讀取和返回用戶數據列表(以及本文中省略的其他功能)。服務類授權

我已經建立了一個用於獲取用戶詳細信息的基本接口,併爲每個我需要的數據源實現了一個實現。

public interface BaseUserService { 
    //user service interface 
} 

@Service 
public class EnvironmentAService implements BaseUserService { 
    // do datasource specific dao stuff. 
} 

@Service 
public class EnvironmentBService implements BaseUserService { 
    // do datasource specific dao stuff. 
} 

@Service 
public class EnvironmentCService implements BaseUserService { 
    // do datasource specific dao stuff. 
} 

目前在我的控制,我做這樣的事情:

@RestController 
@RequestMapping("api") 
public class UserController { 

    @Autowired 
    ConfigurationService configurationService 

    @Autowired 
    BaseUserService environmentAService; 

    @Autowired 
    BaseUserService environmentBService; 

    @Autowired 
    BaseUserService environmentCService; 

    @RequestMapping(value = "/users", method = RequestMethod.GET, headers={"Accept=application/json,application/xml"}) 
    public List<User> userList(
      @RequestParam(value="configValue") String configValue, 
      @RequestParam(value="username") String username, 
      @RequestParam(value="lastName") String configValue, 
      @RequestParam(value="dob") Date dateOfBirth 
      ){ 

     Configuration config = configurationService.getConfiguration(configValue); 

     if(config.value == null) 
      throw new ConfigurationNotFoundException("Please enter a valid configuration value"); 

     List<User> userList = new ArrayList<User> users; 

     if(config.environments.contains(Environment.A)) 
      userList.addAll(environmentAService.getUserList(username,configValue,dateOfBirth)); 
     if(config.environments.contains(Environment.B)) 
      userList.addAll(environmentBService.getUserList(username,configValue,dateOfBirth)); 
     if(config.environments.contains(Environment.C)) 
      userList.addAll(environmentCService.getUserList(username,configValue,dateOfBirth)); 

     return userList; 
    } 
} 

這工作得很好,但我在尋找一個更好的解決方案,所以控制器不那麼依賴於該服務類。我正在研究委託和裝飾模式,可能在一個類中提供了條件語句,但是這些看起來好像不起作用,或者我不完全確定如何在我的情況下實現它。

+0

添加一個工廠,該工廠根據配置的環境返回請求的服務實例類型。循環返回的實例來構建用戶列表。 – dbugger

回答

1

如何注入BaseUserService的地圖而不是單個字段?

@Autowired 
Map<Environment, BaseUserService> serviceMap; 

... 

for (Entry<Environment, BaseUserService> e : serviceMap.entrySet()) { 
    if (config.environments.contains(e.getKey())) { 
     userList.addAll(e.getValue().getUserList(username,configValue,dateOfBirth)); 
    } 
} 

這樣你就可以不必修改控制器注入新的服務。

+0

它的工作!很好的解決方案。它使得爲其他環境添加服務變得非常簡單! – ephemeralCoder

0

您可以考慮使用Visitor Pattern

一些想法:

  • 每個environmentconfig.environments成爲的Visitable。
  • 創建一個訪客,比如UpdateUserListFromServiceVisitor。其中的visit(Environment.A)方法使用EnvironmentAService的實例來獲取用戶列表。同樣,visit(Environment.B)使用EnvironmentBServicevisit(Environment.C)使用EnvironmentCService

優點這種方法的:

  • 你擺脫控制器中的那個醜陋的if-else塊。
  • 添加新的BaseUserService不需要更改任何控制器。只需更改訪客類。
  • 目前,您需要的操作是從BaseUserService獲取用戶列表。將來添加更多操作只會涉及添加新的訪問者。

注意事項: - 如果config.environments可以包含重複的條目,上述的訪問者模式將作出相應BaseUserService重複呼叫。您可以考慮將其轉換爲Set