【发布时间】:2015-07-28 05:02:12
【问题描述】:
我现在在数据库中有 2 个表:
- 用户
- 用户数据库
在用户中,我存储登录名、密码、角色
在 user_database 我存储数据库驱动程序、url、密码和用户。
图表数据库
我希望用户登录到我的页面,然后他所做的下一个连接将被发送到用户数据库。为什么我需要什么?我规划了流行的电子商务地图并创建了用户登录并查看商店数据的android应用程序,可以添加和查看产品订单。
现在该去实践了,我对弹簧技术的了解很少,当我做错的时候请解释一下。
AbstractRoutingDataSource 的所有 web 示例都在持久性文件中声明数据源或创建数据源 bean 并开始使用 AbstractRoutingDataSource。
在我的项目中,我现在没有用户连接,我需要从数据库中获取它。我尝试使用存储库和这个例子
https://stackoverflow.com/a/17575648/3037869
但是我在控制器中的@Autowired 上得到了空值,我认为存储库的连接是空的。如何为此存储库设置连接并设置路由?这种方法的缺陷是当我添加用户时我需要重新启动服务器来刷新连接。
接下来尝试我现在使用的类User 实现UserDetails 用户登录后我可以从getPrincipal() 获取用户连接并添加到地图。
private void setDataSources() {
HashMap<Object, Object> targetDataSources = new HashMap<>();
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.driverClassName("org.h2.Driver");
dataSourceBuilder.url("jdbc:h2:mem:AZ;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
dataSourceBuilder.username("sa");
dataSourceBuilder.password("");
targetDataSources.put("auth", dataSourceBuilder.build());
setDefaultTargetDataSource(dataSourceBuilder.build());
if( SecurityContextHolder.getContext().getAuthentication()!=null) {
User user=(User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
System.out.println(user.getUserDatabase().getDriver());
dataSourceBuilder.driverClassName(user.getUserDatabase().getDriver());
dataSourceBuilder.url(user.getUserDatabase().getUrl());
dataSourceBuilder.username("3450_Menadzer");
dataSourceBuilder.password(user.getUserDatabase().getPassword());
targetDataSources.put("user", dataSourceBuilder.build());
}
setTargetDataSources(targetDataSources);
afterPropertiesSet(); //map is refresh when i add this
}
我在构造函数上运行这个方法并确定CurrentLookupKey
protected Object determineCurrentLookupKey() {
if( SecurityContextHolder.getContext().getAuthentication()!=null) {
setDataSources();
return "user";
}
return "auth";
}
这是有效的,但是当我刷新 3-4 次对用户数据库的请求时,我得到了
User 3450_Menadzer already has more than 'max_user_connections' active connections
手动设置连接映射而不刷新每个方法determineCurrentLookupKey运行我没有这个问题。我认为我的方法不是关闭连接。我怎样才能清理这个?这可能是更好的路由连接方法吗?
编辑 @SergeBallesta 我从您的示例中更改了一些代码 这是我的地图课
@Component
@Scope(value = "singleton")
public class DataSourceMap {
private Map<Object,Object> dataSourceMap;
public DataSourceMap()
{
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.driverClassName("org.h2.Driver");
dataSourceBuilder.url("jdbc:h2:mem:AZ;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
dataSourceBuilder.username("sa");
dataSourceBuilder.password("");
dataSourceMap=new HashMap<Object,Object>();
dataSourceMap.put("auth",dataSourceBuilder.build());
}
public void addDataSource(String session,DataSource dataSource)
{
this.dataSourceMap.put(session,dataSource);
}
public Map<Object,Object> getDataSourceMap()
{
return dataSourceMap;
}
public void removeSource(String session)
{
dataSourceMap.remove(session);
}
}
对于AbstractRoutingDataSource,我做了一些更改,我添加了afterPropertiesSet(),因为数据源没有刷新。我做了一些刷新,我没有收到错误,我认为这是有效的。我需要在未来测试更多的数据库
@Component
public class CustomRoutingDataSource extends AbstractRoutingDataSource{
@Autowired
DataSourceMap dataSources;
@Override
protected Object determineCurrentLookupKey() {
setDataSources(dataSources);
afterPropertiesSet();
System.out.println("test");
if( SecurityContextHolder.getContext().getAuthentication()!=null) {
HttpServletRequest request = ((ServletRequestAttributes)
RequestContextHolder.getRequestAttributes()).getRequest();
return request.getSession().getId();
}
return "auth";
}
@Autowired
public void setDataSources(DataSourceMap dataSources) {
System.out.println("data adding");
setTargetDataSources(dataSources.getDataSourceMap());
}
}
【问题讨论】:
-
你能分享你的代码吗?用户登录后我有同样的任务,连接到一个基本数据库并获取数据源,然后 CRUD 到 taht 数据源!但是我在 Spring Framework 中很新,我尝试了一个月但没有好的结果。我希望你的代码可以帮助我。
标签: java spring spring-security