2016-11-22 45 views
0

我正在开发一个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

我觉得这是因为当它完成了找到工作的在拦截当前User休眠已经关闭了数据库会话,因此它无法使用该User到另一个会话负载Order秒。但我真的不想再次访问数据库。如何在拦截器中加载当前用户并重新使用该用户实例来加载更多资源?

+0

_“可是我真的不想再打数据库。” _ _“我怎样才能加载当前用户在拦截和重复使用的用户实例加载更多资源“这是相当矛盾的。 – zeroflagL

回答

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; 
} 
+0

不,我不想为每个请求加载订单。 – Aetherus

+0

然后重新读取用户。使用回购找到相同的用户的id(你可以使用存储的用户的ID)adn从新检索的用户获得订单 – StanislavL

+0

感谢您的建议。我正在尝试这种方法,尽管我不喜欢两次使用完全相同的查询来访问数据库的想法。 – Aetherus

相关问题