简体   繁体   English

Spring将自动连线的SessionAttribute注入服务层

[英]Spring Inject Autowired SessionAttribute into Service Layer

Is there a way to @Inject/@Autowired a SessionAttribute into the @Service layer directly without passing it through a @Controller ? 有没有一种方法可以直接将SessionAttribute @Inject/@Autowired插入@Service层,而无需通过@Controller传递它?

I'm looking for something like this: 我正在寻找这样的东西:

@Autowired 
@SessionAttribute("userprincipal") 
UserPrincipal principal;

Possible Solution: 可能的解决方案:

@Configuration
public class ApplicationConfig {

    @Bean
    @Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public UserPrincipal sessionUserPrincipal() {
        // not sure here the user does not exist at creation of bean
    }
}

My solution, hopefully this will save someone else some time. 我的解决方案,希望这可以节省其他人的时间。

Caution: The injected dependency is hidden, this will cause problems if used outside a session. 警告:注入的依赖项是隐藏的,如果在会话外部使用,将导致问题。 Use Optional<T> if this is the case and handle internally. 在这种情况下,请使用Optional<T>并在内部进行处理。 If you share your code your team will not be aware of the required dependency. 如果共享您的代码,您的团队将不会意识到所需的依赖关系。

Testing: When testing you will be required to provide the session bean for @Autowired functionality. 测试:测试时,您将需要提供用于@Autowired功能的会话bean。

Session Bean Class: 会话Bean类:

public class SessionUserPrincipal implements Serializable {

    private static final long serialVersionUID = 1L;

    private UserPrincipal principal;

    public SessionUserPrincipal() {}

    // mutator methods omitted
}

return Optional<T> if session attribute is not guarantied to be available 如果不保证会话属性可用,则返回Optional<T>

Add Bean to Context: 将Bean添加到上下文:

@Configuration
public class WebServletContextConfiguration implements WebMvcConfigurer {

    @Bean
    @Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public SessionUserPrincipal sessionUserPrincipal() {
        return new SessionUserPrincipal();
    }
}

Add RequestContextListener to web.xml 将RequestContextListener添加到web.xml

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

this is a requirement for the code below to work. 这是下面的代码正常工作的要求。 It exposes state necessary to implement session scope. 它公开了实现会话范围所必需的状态。 By default that state is exposed by DispatcherServlet, so it's not available before request enters DispatcherServlet (Spring Security filters). 默认情况下,状态由DispatcherServlet公开,因此在请求进入DispatcherServlet(Spring Security过滤器)之前,该状态不可用。 You will get an exception if you try to @Autowire a session bean before its available. 如果尝试在会话bean可用之前自动@Autowire请请请参见,请参见当您尝试@Autowire一个会话bean之前,您将获得一个例外)。

Add session attribute to session @Bean on successful authentication. 成功认证后,将session属性添加到session @Bean

public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    @Autowired SessionUserPrincipal sessionUserPrincipal;

    @Override
    public void onAuthenticationSuccess(
            HttpServletRequest request,
            HttpServletResponse response,
            Authentication authentication) throws IOException, ServletException
    {
        // find/get userprincipal code omitted
        sessionUserPrincipal.setPrincipal(userprincipal);
    }
}

Use session bean: 使用会话Bean:

@Service
public class DefaultSomeService implements SomeService {
    @Autowired private SessionUserPrincipal sessionUserPrincipal;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM