Почему я могу вводить bean-объекты в области запроса при отсутствии запроса? - PullRequest
0 голосов
/ 23 апреля 2019

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

java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.

как надо.

(см. В конце этого поста примеры кода)

Я знаю три способа пройти тест ниже, чтобы стать зелёным:

  1. изменить область действия UsingBean
  2. метод введения
  3. прокси в области действия

([1] является скорее взломом, чем решением и может вызвать проблемы в дальнейшем, но делает тест зеленым.: P)

И хотя я понимаю идею этих трех вариантов, я не понимаю , почему они вообще работают.

Я имею в виду, что даже если я изменю область действия на "сеанс" в [1], у меня все равно не будет ни сеанса, ни запроса, когда я создаю экземпляр UsingBean.

Что касается [2] и [3], они избегают получения экземпляра при запуске, но у меня все еще нет запроса, когда они действительно получают экземпляр.

И все же тест не проходит. Почему?

ПРИМЕР КОДА

Допустим, у меня есть боб в области запроса

@Repository
@Scope("request")
class RequestScopedBean : ScopedBean{
    override fun foo(): String {
        return "Hello World"
    }
}

используется в синглтоне с областью действия

@Service
class UsingBean{
    private val scopedBean:ScopedBean

    @Inject
    constructor(scopedBean: ScopedBean) {
        this.scopedBean = scopedBean
    }

    fun foo():String{
        val foo = scopedBean.foo()
        println(foo)
        return foo
    }
}

и давайте также создадим небольшой тест для этого:

@RunWith(SpringJUnit4ClassRunner::class)
@SpringBootTest
@WebAppConfiguration
class RequestScopedBeansIT{

    @Inject
    private lateinit var bean : UsingBean

    @Test
    fun canInject(){
        assertThat(bean.foo()).isEqualTo("Hello World")
    }
}

1) изменить область действия из UsingBean

@Service
@Scope("session")
class UsingBean{
    private val scopedBean:ScopedBean

    @Inject
    constructor(scopedBean: ScopedBean) {
        this.scopedBean = scopedBean
    }

    fun foo():String{
        val foo = scopedBean.foo()
        println(foo)
        return foo
    }
}

2) метод впрыска

@Service
class UsingBean{
    private val scopedBean:ScopedBean
        get() = injectBean()

    fun foo():String{
        val foo = scopedBean.foo()
        println(foo)
        return foo
    }

    @Lookup
    fun injectBean():ScopedBean{
        TODO("will be replaced by spring")
    }
}

3) Scoped Proxy

@Repository
@Scope("request",proxyMode = ScopedProxyMode.TARGET_CLASS)
class RequestScopedBean : ScopedBean{
    override fun foo(): String {
        return "Hello World"
    }
}

или

@Repository
@RequestScope
class RequestScopedBean : ScopedBean{
    override fun foo(): String {
        return "Hello World"
    }
}

1 Ответ

1 голос
/ 23 апреля 2019

Хотя вы можете подумать, что у вас нет текущего запроса, а сеанс у вас действительно есть.

@WebAppConfiguration - это то, что вызывает это.Он активирует ServletTestExecutionListener, который зарегистрирует привязанный к потоку фиктивный запрос и ответ.

Что объясняет, почему тест завершается успешно при наличии запроса с привязкой к потоку.

...