我正在开发一个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_USER
是ThreadLocal<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在另一场会议上。但我真的不想再次点击数据库了。如何在拦截器中加载当前用户并重用该用户实例以加载更多资源?
答案 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;
}