2016-11-22 2 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を見つける仕事をしていたときに、Hibernateは、データベースのセッションを閉じたので、それは別のセッションでOrder SをロードするためにUserことを使用することができませんだからそれはだと思います。しかし、私は本当にデータベースをもう一度打つことは望まない。現在のユーザーをインターセプターにロードして、そのユーザー・インスタンスを再利用してより多くのリソースをロードするにはどうすればよいですか?

+0

_ _ _ "どのように私は迎撃に現在のユーザーを読み込むことができます「しかし、私は本当に。再びデータベースをヒットしたくない」と、よりロードするために、そのユーザーのインスタンスを再利用しますリソース "_それはかなりの矛盾です。 – zeroflagL

答えて

0

ユーザーをスレッドローカルに保存する前に注文コレクションを初期化する必要があります。

RequestContext.CURRENT_USER.set(user); 

user.getOrders(); 

を呼び出すか、あなただけのユーザー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を使用できます)。新しく取得したユーザーからの注文を受け取ります。 – StanislavL

+0

提案をいただきありがとうございます。私はこのアプローチをしようとしていますが、まったく同じクエリでデータベースを2回ヒットするのは嫌です。 – Aetherus

関連する問題