Как проверить доступность области запроса в Spring?

Я пытаюсь настроить некоторый код, который будет вести себя так, если доступна область запроса Spring, и по-другому, если указанная область недоступна.

Рассматриваемое приложение является веб-приложением, но есть некоторые триггеры JMX и запланированные задачи (например, Quartz), которые также вызывают вызовы.

E.g.

/**
 * This class is a spring-managed singleton
 */
@Named
class MySingletonBean{

    /**
     * This bean is always request scoped
     */
    @Inject
    private MyRequestScopedBean myRequestScopedBean; 

    /* can be invoked either as part of request handling
       or as part of a JMX trigger or scheduled task */
    public void someMethod(){
        if(/* check to see if request scope is available */){
            myRequestScopedBean.invoke();
        }else{
            //do something else
        }
    }
}

Предполагая, что myRequestScopedBean находится в области запроса.

Я знаю, что это можно сделать с помощью try-catch вокруг вызова myRequestScopedBean, например:

/**
 * This class is a spring-managed singleton
 */
@Named
class MySingletonBean{

    /**
     * This bean is always request scoped
     */
    @Inject
    private MyRequestScopedBean myRequestScopedBean; 

    /* can be invoked either as part of request handling
       or as part of a JMX trigger or scheduled task */
    public void someMethod(){
        try{
            myRequestScopedBean.invoke();
        }catch(Exception e){
            //do something else
        }
    }
}

но это кажется действительно неуклюжим, поэтому мне интересно, знает ли кто-нибудь об элегантном способе Spring опросить что-то, чтобы узнать, доступны ли bean-компоненты с областью запроса.

Большое спасибо!


person Taylor    schedule 01.04.2015    source источник
comment
Зачем вам нужно проверять, находится ли компонент в области запроса? Это кажется очень отсталым.   -  person Sotirios Delimanolis    schedule 01.04.2015
comment
Извините, возможно, это было непонятно. Компонент всегда находится в области запроса, но вызов someMethod может не быть частью обработки запроса.   -  person Taylor    schedule 01.04.2015
comment
Я все еще в замешательстве. MyRequestScopedBean находится в области запроса. MySingletonBean имеет одноэлементную область видимости. Что нужно проверить и почему?   -  person Sotirios Delimanolis    schedule 01.04.2015
comment
Я попытался немного прояснить вопрос. Что мне нужно, так это то, что если bean-компоненты с областью запроса доступны, чтобы использовать их, а в противном случае - вернуться к чему-то другому. Я понимаю, что вопрос немного расплывчатый, но я не могу быть более конкретным по причинам IP-адреса работодателя.   -  person Taylor    schedule 01.04.2015
comment
Если bean-компонент недоступен, инициализация контекста завершится ошибкой при попытке внедрить его в синглетон. Если область запроса недоступна (обычно она предоставляется в WebApplicationContexts), то при попытке инициализировать этот компонент снова произойдет сбой инициализации.   -  person Sotirios Delimanolis    schedule 01.04.2015
comment
Я не уверен, что это точно. Кажется, что Spring вводит одноэлементный прокси-сервер, а затем при вызове bean-компонента с областью запроса попытается извлечь его из некоторого внутреннего хранилища (я полагаю, что локальный поток). Если поток, который входит в MySingletonBean, является потоком обработки запросов, тогда все будет работать нормально, но если поток запускается как часть триггера JMX, вы получите некоторое исключение из внутренних компонентов Spring.   -  person Taylor    schedule 01.04.2015
comment
А, в этом ты прав. Так что это поведение, которое вы хотите поймать, что исключение выдается из-за отсутствия области запроса или из-за отсутствия запроса, привязанного к потоку.   -  person Sotirios Delimanolis    schedule 01.04.2015
comment
Да, точно. Это легко сделать с помощью try-catch, но я надеюсь, что есть что-то более элегантное.   -  person Taylor    schedule 01.04.2015


Ответы (2)


Вы можете использовать описанную здесь проверку if

SPRING — получить текущую область действия

if (RequestContextHolder.getRequestAttributes() != null) 
    // request thread

вместо того, чтобы ловить исключения. Иногда это выглядит как самое простое решение.

person Sergey Shcherbakov    schedule 06.10.2016

Вы можете внедрить Provider<MyRequestScopedBean> и перехватить исключение при вызове метода get, но вам следует переосмыслить свой дизайн. Если вы серьезно относитесь к этому, вам, вероятно, следует иметь два bean-компонента с разными квалификаторами.

Редактировать

С другой стороны, если вы используете конфигурацию Java, @Scope("prototype") свой метод @Bean и принимаете решение там, вы можете получить дескриптор контекста запроса через RequestContextHolder, если он доступен. Но я настоятельно рекомендую вам переосмыслить свой дизайн

person Lev Kuznetsov    schedule 01.04.2015
comment
Спасибо за ответ. Если я правильно понял, вы предлагаете завернуть try-catch в провайдера? Я пытаюсь выяснить, есть ли способ узнать, будет ли это работать, вместо того, чтобы пытаться и потерпеть неудачу. Тем не менее, оцените ответ. - person Taylor; 01.04.2015