如何在拦截器中获取当前用户并在控制器中检索其资源

时间:2016-11-22 08:19:36

标签: hibernate spring-mvc spring-boot

我正在开发一个Spring MVC项目,我想实现自己的身份验证拦截器。它看起来像这样:

@Component
public class AuthenticationInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    private UsersRepo usersRepo;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod)) return true;
        HandlerMethod handlerMethod = (HandlerMethod) handler;

        if (handlerMethod.getMethodAnnotation(Authenticated.class) == null) return true;

        HttpSession session = request.getSession(false);
        if (session == null) return reject(response);

        Long id = (Long) session.getAttribute("userId");
        if (id == null) return reject(response);

        User user = usersRepo.findOne(id);
        if (user == null) return reject(response);

        RequestContext.CURRENT_USER.set(user);

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        RequestContext.CURRENT_USER.remove();
    }

    private boolean reject(HttpServletResponse response) {
        response.setStatus(403);
        return false;
    }
}

RequestContext.CURRENT_USERThreadLocal<User>

在控制器中,我想检索当前用户的订单:

@RestController
@RequestMapping("/orders")
public class OrdersController {

    @RequestMapping(method = RequestMethod.GET)
    @Authenticated
    public Collection<Order> index() {
        Collection<Order> orders = RequestContext.CURRENT_USER.get().getOrders();
        return orders;
    }

}

它给了我Could not write content: failed to lazily initialize a collection of role: myapp.models.User.orders, could not initialize proxy - no Session

我认为这是因为Hibernate完成了在拦截器中找到当前User的工作时关闭了数据库会话,因此它无法使用User加载Order s在另一场会议上。但我真的不想再次点击数据库了。如何在拦截器中加载当前用户并重用该用户实例以加载更多资源?

1 个答案:

答案 0 :(得分:0)

在将用户存储在本地线程中之前,您需要初始化订单集合。致电

user.getOrders();

之前

RequestContext.CURRENT_USER.set(user);

或者您可以只存储用户ID。当您需要当前用户的订单检索新用户

public Collection<Order> index() {
    User user = usersRepo.findOne(RequestContext.CURRENT_USER.get());
    Collection<Order> orders = user.getOrders();
    return orders;
}