2016-11-22 26 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

相關問題