整个应用程序的公用共享数据对象

时间:2019-01-06 19:47:11

标签: spring-boot

我有一些在Spring Boot应用程序中通用的数据对象-一个是登录的employee对象,另一个是category。我创建了一个@Component类,其中包含这些都是静态变量。这样,我什至不必为其自动接线。它们可以像CurrentContext.employee一样直接在控制器中使用。

@Component
public final class CurrentContext {

public static Category currentCategory;
public static Employee employee;

@Autowired
private CategoryService categoryService;
@Autowired
private EmployeeService employeeService;

@EventListener
public void onApplicationEvent(ContextRefreshedEvent event) {
    currentCategory = categoryService.getCategory();
}

@EventListener
public void onLoginSuccess(InteractiveAuthenticationSuccessEvent event) {
    employee = employeeService.getEmployeeByUserId(((MyUserDetails) event.getAuthentication().getPrincipal()).getUserId());
}

}

这是正确的方法吗?请建议是否有更好的方法来处理共享数据

修改 一些背景-我需要当前登录的employee和一个category这对所有员工都是通用的。因此,我在控制器中autowired employeeServicecategoryService,并使用它们来获取数据。几乎所有控制器方法都需要它们,因此,我想创建一个此类的bean,以便直接在控制器中使用它们,并保存频繁的数据库调用。

1 个答案:

答案 0 :(得分:0)

通常,我们仅将与跨领域关注点相关的依赖项(即整个应用程序中的依赖项,例如安全性,日志记录,事务内容,时间提供者等)放在静态字段中。

通过以静态方式访问此类依赖关系,我们无需在对象之间通过方法参数/构造函数将它们传递给对象,这将使API更加整洁,而不会产生此类噪音(BTW。这称为{{ 1}}。)

您的Ambient Context Pattern对象很可能属于此类型,因此可以以静态方式访问它。但是由于它们的作用域是每个会话的,所以您不能简单地将其放在类的静态字段中。如果是,那么您在所有会议中总是得到同一名员工。相反,您必须以某种方式将其存储在会话范围内的对象中(例如Employee)。然后,在开始处理Web请求时,可以从会话中获取该请求,然后将其放入封装在“ ContextHolder”对象内的HttpSession中。然后,您以静态方式访问该“ ContextHolder”。

听起来很复杂又可怕吗?不用担心,因为Spring Security已经为您实现了这些东西。您需要做的是customize Authentication#getPrincipal()or extend default Authentication包含您的ThreadLocal。然后使用Employee

对于您的SecurityContextHolder.getContext().getAuthentication()来说,如果它们不是跨领域的关注点,并且不是应用程序范围,那么使singleton bean获得其值是一种更好的OOP设计。

currentCategory

然后将@Component public final class CurrentCategoryProvider { @Autowired private CategoryService categoryService; public Category getCurrentCategory(){ //or cache the value to the an internal properties depending on your requirements return categoryService.getCategory(); } } 注入需要访问CurrentCategoryProvider的bean。