我有一个基本的控制器(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 :(得分:1)
如何注入BaseUserService
s而不是单个字段的地图?
@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));
}
}
通过这种方式,您无需修改控制器即可注入新服务。
答案 1 :(得分:0)
您可以考虑使用Visitor Pattern。
一些想法:
environment
中的每个config.environments
都变为可访问。UpdateUserListFromServiceVisitor
。其中的visit(Environment.A)
方法使用EnvironmentAService
的实例来获取用户列表。同样,visit(Environment.B)
使用EnvironmentBService
而visit(Environment.C)
使用EnvironmentCService
。这种方法的优点:
BaseUserService
不需要更改任何控制器。只需更改访客类。BaseUserService
获取用户列表。将来添加更多操作只需要添加新的访问者。注意事项:
- 如果config.environments
可以包含重复的条目,则上述访问者模式将对相应的BaseUserService
进行重复调用。您可以考虑将其转换为Set
。