我正在开发一个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
。
我觉得这是因为当它完成了找到工作的在拦截当前User
休眠已经关闭了数据库会话,因此它无法使用该User
到另一个会话负载Order
秒。但我真的不想再次访问数据库。如何在拦截器中加载当前用户并重新使用该用户实例来加载更多资源?
_“可是我真的不想再打数据库。” _ _“我怎样才能加载当前用户在拦截和重复使用的用户实例加载更多资源“这是相当矛盾的。 – zeroflagL