简体   繁体   中英

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 ?

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. 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.

Session Bean Class:

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

Add Bean to Context:

@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

<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). You will get an exception if you try to @Autowire a session bean before its available.

Add session attribute to session @Bean on successful authentication.

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:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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