Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
爱吃血肠
spring-framework
提交
e62ada89
S
spring-framework
项目概览
爱吃血肠
/
spring-framework
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
S
spring-framework
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
e62ada89
编写于
1月 26, 2016
作者:
R
Rossen Stoyanchev
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add @RequestAttribute with servlet-based support
Issue: SPR-13894
上级
698f923f
变更
12
隐藏空白更改
内联
并排
Showing
12 changed file
with
401 addition
and
137 deletion
+401
-137
spring-web/src/main/java/org/springframework/web/bind/annotation/RequestAttribute.java
...springframework/web/bind/annotation/RequestAttribute.java
+66
-0
spring-web/src/main/java/org/springframework/web/bind/annotation/RequestMapping.java
...g/springframework/web/bind/annotation/RequestMapping.java
+2
-0
spring-web/src/main/java/org/springframework/web/bind/annotation/SessionAttribute.java
...springframework/web/bind/annotation/SessionAttribute.java
+1
-0
spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java
.../method/annotation/ExceptionHandlerExceptionResolver.java
+1
-0
spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestAttributeMethodArgumentResolver.java
...od/annotation/RequestAttributeMethodArgumentResolver.java
+60
-0
spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java
...t/mvc/method/annotation/RequestMappingHandlerAdapter.java
+2
-0
spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/AbstractRequestAttributesArgumentResolverTests.java
...ation/AbstractRequestAttributesArgumentResolverTests.java
+185
-0
spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestAttributeMethodArgumentResolverTests.java
...notation/RequestAttributeMethodArgumentResolverTests.java
+45
-0
spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterIntegrationTests.java
...otation/RequestMappingHandlerAdapterIntegrationTests.java
+7
-1
spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/SessionAttributeMethodArgumentResolverTests.java
...notation/SessionAttributeMethodArgumentResolverTests.java
+13
-136
src/asciidoc/web-mvc.adoc
src/asciidoc/web-mvc.adoc
+18
-0
src/asciidoc/whats-new.adoc
src/asciidoc/whats-new.adoc
+1
-0
未找到文件。
spring-web/src/main/java/org/springframework/web/bind/annotation/RequestAttribute.java
0 → 100644
浏览文件 @
e62ada89
/*
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.springframework.web.bind.annotation
;
import
java.lang.annotation.Documented
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
import
org.springframework.core.annotation.AliasFor
;
/**
* Annotation to bind a method parameter to a request attribute.
*
* <p>The main motivation is to provide convenient access to request attributes
* from a controller method with an optional/required check and a cast to the
* target method parameter type.
*
* @author Rossen Stoyanchev
* @since 4.3
* @see RequestMapping
* @see SessionAttribute
*/
@Target
(
ElementType
.
PARAMETER
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
public
@interface
RequestAttribute
{
/**
* Alias for {@link #name}.
*/
@AliasFor
(
"name"
)
String
value
()
default
""
;
/**
* The name of the request attribute to bind to.
* <p>The default name is inferred from the method parameter name.
*/
@AliasFor
(
"value"
)
String
name
()
default
""
;
/**
* Whether the request attribute is required.
* <p>Defaults to {@code true}, leading to an exception being thrown
* if the attribute is missing. Switch this to {@code false} if you prefer
* a {@code null} or Java 1.8+ {@code java.util.Optional} if the attribute
* doesn't exist.
*/
boolean
required
()
default
true
;
}
spring-web/src/main/java/org/springframework/web/bind/annotation/RequestMapping.java
浏览文件 @
e62ada89
...
...
@@ -130,6 +130,8 @@ import org.springframework.core.annotation.AliasFor;
* to existing, permanent session attributes (e.g. user authentication object)
* as opposed to model attributes temporarily stored in the session as part of
* a controller workflow via {@link SessionAttributes}.
* <li>{@link RequestAttribute @RequestAttribute} annotated parameters for access
* to request attributes.
* <li>{@link org.springframework.http.HttpEntity HttpEntity<?>} parameters
* (Servlet-only) for access to the Servlet request HTTP headers and contents.
* The request stream will be converted to the entity body using
...
...
spring-web/src/main/java/org/springframework/web/bind/annotation/SessionAttribute.java
浏览文件 @
e62ada89
...
...
@@ -42,6 +42,7 @@ import org.springframework.core.annotation.AliasFor;
* @since 4.3
* @see RequestMapping
* @see SessionAttributes
* @see RequestAttribute
*/
@Target
(
ElementType
.
PARAMETER
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
...
...
spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java
浏览文件 @
e62ada89
...
...
@@ -292,6 +292,7 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
// Annotation-based argument resolution
resolvers
.
add
(
new
SessionAttributeMethodArgumentResolver
());
resolvers
.
add
(
new
RequestAttributeMethodArgumentResolver
());
// Type-based argument resolution
resolvers
.
add
(
new
ServletRequestMethodArgumentResolver
());
...
...
spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestAttributeMethodArgumentResolver.java
0 → 100644
浏览文件 @
e62ada89
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.springframework.web.servlet.mvc.method.annotation
;
import
javax.servlet.ServletException
;
import
org.springframework.core.MethodParameter
;
import
org.springframework.web.bind.ServletRequestBindingException
;
import
org.springframework.web.bind.annotation.RequestAttribute
;
import
org.springframework.web.bind.annotation.ValueConstants
;
import
org.springframework.web.context.request.NativeWebRequest
;
import
org.springframework.web.context.request.RequestAttributes
;
import
org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver
;
/**
* Resolves method arguments annotated with an @{@link RequestAttribute}.
*
* @author Rossen Stoyanchev
* @since 4.3
*/
public
class
RequestAttributeMethodArgumentResolver
extends
AbstractNamedValueMethodArgumentResolver
{
@Override
public
boolean
supportsParameter
(
MethodParameter
parameter
)
{
return
parameter
.
hasParameterAnnotation
(
RequestAttribute
.
class
);
}
@Override
protected
NamedValueInfo
createNamedValueInfo
(
MethodParameter
parameter
)
{
RequestAttribute
annot
=
parameter
.
getParameterAnnotation
(
RequestAttribute
.
class
);
return
new
NamedValueInfo
(
annot
.
name
(),
annot
.
required
(),
ValueConstants
.
DEFAULT_NONE
);
}
@Override
protected
Object
resolveName
(
String
name
,
MethodParameter
parameter
,
NativeWebRequest
request
){
return
request
.
getAttribute
(
name
,
RequestAttributes
.
SCOPE_REQUEST
);
}
@Override
protected
void
handleMissingValue
(
String
name
,
MethodParameter
parameter
)
throws
ServletException
{
throw
new
ServletRequestBindingException
(
"Missing request attribute '"
+
name
+
"' of type "
+
parameter
.
getNestedParameterType
().
getSimpleName
());
}
}
spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java
浏览文件 @
e62ada89
...
...
@@ -601,6 +601,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
resolvers
.
add
(
new
ServletCookieValueMethodArgumentResolver
(
getBeanFactory
()));
resolvers
.
add
(
new
ExpressionValueMethodArgumentResolver
(
getBeanFactory
()));
resolvers
.
add
(
new
SessionAttributeMethodArgumentResolver
());
resolvers
.
add
(
new
RequestAttributeMethodArgumentResolver
());
// Type-based argument resolution
resolvers
.
add
(
new
ServletRequestMethodArgumentResolver
());
...
...
@@ -641,6 +642,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
resolvers
.
add
(
new
MatrixVariableMapMethodArgumentResolver
());
resolvers
.
add
(
new
ExpressionValueMethodArgumentResolver
(
getBeanFactory
()));
resolvers
.
add
(
new
SessionAttributeMethodArgumentResolver
());
resolvers
.
add
(
new
RequestAttributeMethodArgumentResolver
());
// Type-based argument resolution
resolvers
.
add
(
new
ServletRequestMethodArgumentResolver
());
...
...
spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/AbstractRequestAttributesArgumentResolverTests.java
0 → 100644
浏览文件 @
e62ada89
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.springframework.web.servlet.mvc.method.annotation
;
import
java.lang.reflect.Method
;
import
java.util.Optional
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.springframework.core.DefaultParameterNameDiscoverer
;
import
org.springframework.core.GenericTypeResolver
;
import
org.springframework.core.MethodParameter
;
import
org.springframework.core.annotation.SynthesizingMethodParameter
;
import
org.springframework.core.convert.support.DefaultConversionService
;
import
org.springframework.mock.web.test.MockHttpServletRequest
;
import
org.springframework.mock.web.test.MockHttpServletResponse
;
import
org.springframework.web.bind.ServletRequestBindingException
;
import
org.springframework.web.bind.WebDataBinder
;
import
org.springframework.web.bind.annotation.RequestAttribute
;
import
org.springframework.web.bind.annotation.SessionAttribute
;
import
org.springframework.web.bind.support.WebDataBinderFactory
;
import
org.springframework.web.bind.support.WebRequestDataBinder
;
import
org.springframework.web.context.request.ServletWebRequest
;
import
org.springframework.web.method.support.HandlerMethodArgumentResolver
;
import
org.springframework.web.method.support.ModelAndViewContainer
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertFalse
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
import
static
org
.
junit
.
Assert
.
assertNull
;
import
static
org
.
junit
.
Assert
.
assertSame
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
junit
.
Assert
.
fail
;
import
static
org
.
mockito
.
BDDMockito
.
given
;
import
static
org
.
mockito
.
Mockito
.
mock
;
/**
* Base class for {@code @RequestAttribute} and {@code @SessionAttribute} method
* method argument resolution tests.
*
* @author Rossen Stoyanchev
* @since 4.3
*/
public
abstract
class
AbstractRequestAttributesArgumentResolverTests
{
private
ServletWebRequest
webRequest
;
private
HandlerMethodArgumentResolver
resolver
;
private
Method
handleMethod
;
@Before
public
void
setUp
()
throws
Exception
{
HttpServletRequest
request
=
new
MockHttpServletRequest
();
HttpServletResponse
response
=
new
MockHttpServletResponse
();
this
.
webRequest
=
new
ServletWebRequest
(
request
,
response
);
this
.
resolver
=
createResolver
();
this
.
handleMethod
=
AbstractRequestAttributesArgumentResolverTests
.
class
.
getDeclaredMethod
(
getHandleMethodName
(),
Foo
.
class
,
Foo
.
class
,
Foo
.
class
,
Optional
.
class
);
}
protected
abstract
HandlerMethodArgumentResolver
createResolver
();
protected
abstract
String
getHandleMethodName
();
protected
abstract
int
getScope
();
@Test
public
void
supportsParameter
()
throws
Exception
{
assertTrue
(
this
.
resolver
.
supportsParameter
(
new
MethodParameter
(
this
.
handleMethod
,
0
)));
assertFalse
(
this
.
resolver
.
supportsParameter
(
new
MethodParameter
(
this
.
handleMethod
,
4
)));
}
@Test
public
void
resolve
()
throws
Exception
{
MethodParameter
param
=
initMethodParameter
(
0
);
try
{
testResolveArgument
(
param
);
fail
(
"Should be required by default"
);
}
catch
(
ServletRequestBindingException
ex
)
{
assertTrue
(
ex
.
getMessage
().
startsWith
(
"Missing "
));
}
Foo
foo
=
new
Foo
();
this
.
webRequest
.
setAttribute
(
"foo"
,
foo
,
getScope
());
assertSame
(
foo
,
testResolveArgument
(
param
));
}
@Test
public
void
resolveWithName
()
throws
Exception
{
MethodParameter
param
=
initMethodParameter
(
1
);
Foo
foo
=
new
Foo
();
this
.
webRequest
.
setAttribute
(
"specialFoo"
,
foo
,
getScope
());
assertSame
(
foo
,
testResolveArgument
(
param
));
}
@Test
public
void
resolveNotRequired
()
throws
Exception
{
MethodParameter
param
=
initMethodParameter
(
2
);
assertNull
(
testResolveArgument
(
param
));
Foo
foo
=
new
Foo
();
this
.
webRequest
.
setAttribute
(
"foo"
,
foo
,
getScope
());
assertSame
(
foo
,
testResolveArgument
(
param
));
}
@Test
public
void
resolveOptional
()
throws
Exception
{
WebDataBinder
dataBinder
=
new
WebRequestDataBinder
(
null
);
dataBinder
.
setConversionService
(
new
DefaultConversionService
());
WebDataBinderFactory
factory
=
mock
(
WebDataBinderFactory
.
class
);
given
(
factory
.
createBinder
(
this
.
webRequest
,
null
,
"foo"
)).
willReturn
(
dataBinder
);
MethodParameter
param
=
initMethodParameter
(
3
);
Object
actual
=
testResolveArgument
(
param
,
factory
);
assertNotNull
(
actual
);
assertEquals
(
Optional
.
class
,
actual
.
getClass
());
assertFalse
(((
Optional
)
actual
).
isPresent
());
Foo
foo
=
new
Foo
();
this
.
webRequest
.
setAttribute
(
"foo"
,
foo
,
getScope
());
actual
=
testResolveArgument
(
param
,
factory
);
assertNotNull
(
actual
);
assertEquals
(
Optional
.
class
,
actual
.
getClass
());
assertTrue
(((
Optional
)
actual
).
isPresent
());
assertSame
(
foo
,
((
Optional
)
actual
).
get
());
}
private
Object
testResolveArgument
(
MethodParameter
param
)
throws
Exception
{
return
testResolveArgument
(
param
,
null
);
}
private
Object
testResolveArgument
(
MethodParameter
param
,
WebDataBinderFactory
factory
)
throws
Exception
{
ModelAndViewContainer
mavContainer
=
new
ModelAndViewContainer
();
return
this
.
resolver
.
resolveArgument
(
param
,
mavContainer
,
this
.
webRequest
,
factory
);
}
private
MethodParameter
initMethodParameter
(
int
parameterIndex
)
{
MethodParameter
param
=
new
SynthesizingMethodParameter
(
this
.
handleMethod
,
parameterIndex
);
param
.
initParameterNameDiscovery
(
new
DefaultParameterNameDiscoverer
());
GenericTypeResolver
.
resolveParameterType
(
param
,
this
.
resolver
.
getClass
());
return
param
;
}
@SuppressWarnings
(
"unused"
)
private
void
handleWithRequestAttribute
(
@RequestAttribute
Foo
foo
,
@RequestAttribute
(
"specialFoo"
)
Foo
namedFoo
,
@RequestAttribute
(
name
=
"foo"
,
required
=
false
)
Foo
notRequiredFoo
,
@RequestAttribute
(
name
=
"foo"
)
Optional
<
Foo
>
optionalFoo
)
{
}
@SuppressWarnings
(
"unused"
)
private
void
handleWithSessionAttribute
(
@SessionAttribute
Foo
foo
,
@SessionAttribute
(
"specialFoo"
)
Foo
namedFoo
,
@SessionAttribute
(
name
=
"foo"
,
required
=
false
)
Foo
notRequiredFoo
,
@SessionAttribute
(
name
=
"foo"
)
Optional
<
Foo
>
optionalFoo
)
{
}
private
static
class
Foo
{
}
}
spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestAttributeMethodArgumentResolverTests.java
0 → 100644
浏览文件 @
e62ada89
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.springframework.web.servlet.mvc.method.annotation
;
import
org.springframework.web.context.request.RequestAttributes
;
import
org.springframework.web.method.support.HandlerMethodArgumentResolver
;
/**
* Unit tests for {@link RequestAttributeMethodArgumentResolver}.
* @author Rossen Stoyanchev
*/
public
class
RequestAttributeMethodArgumentResolverTests
extends
AbstractRequestAttributesArgumentResolverTests
{
@Override
protected
HandlerMethodArgumentResolver
createResolver
()
{
return
new
RequestAttributeMethodArgumentResolver
();
}
@Override
protected
String
getHandleMethodName
()
{
return
"handleWithRequestAttribute"
;
}
@Override
protected
int
getScope
()
{
return
RequestAttributes
.
SCOPE_REQUEST
;
}
}
spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterIntegrationTests.java
浏览文件 @
e62ada89
...
...
@@ -62,6 +62,7 @@ import org.springframework.web.bind.annotation.CookieValue;
import
org.springframework.web.bind.annotation.InitBinder
;
import
org.springframework.web.bind.annotation.ModelAttribute
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.RequestAttribute
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestHeader
;
import
org.springframework.web.bind.annotation.RequestParam
;
...
...
@@ -149,13 +150,14 @@ public class RequestMappingHandlerAdapterIntegrationTests {
public
void
handle
()
throws
Exception
{
Class
<?>[]
parameterTypes
=
new
Class
<?>[]
{
int
.
class
,
String
.
class
,
String
.
class
,
String
.
class
,
Map
.
class
,
Date
.
class
,
Map
.
class
,
String
.
class
,
String
.
class
,
TestBean
.
class
,
Errors
.
class
,
TestBean
.
class
,
Color
.
class
,
HttpServletRequest
.
class
,
HttpServletResponse
.
class
,
TestBean
.
class
,
Color
.
class
,
HttpServletRequest
.
class
,
HttpServletResponse
.
class
,
TestBean
.
class
,
TestBean
.
class
,
User
.
class
,
OtherUser
.
class
,
Model
.
class
,
UriComponentsBuilder
.
class
};
String
datePattern
=
"yyyy.MM.dd"
;
String
formattedDate
=
"2011.03.16"
;
Date
date
=
new
GregorianCalendar
(
2011
,
Calendar
.
MARCH
,
16
).
getTime
();
TestBean
sessionAttribute
=
new
TestBean
();
TestBean
requestAttribute
=
new
TestBean
();
request
.
addHeader
(
"Content-Type"
,
"text/plain; charset=utf-8"
);
request
.
addHeader
(
"header"
,
"headerValue"
);
...
...
@@ -174,6 +176,7 @@ public class RequestMappingHandlerAdapterIntegrationTests {
uriTemplateVars
.
put
(
"pathvar"
,
"pathvarValue"
);
request
.
setAttribute
(
HandlerMapping
.
URI_TEMPLATE_VARIABLES_ATTRIBUTE
,
uriTemplateVars
);
request
.
getSession
().
setAttribute
(
"sessionAttribute"
,
sessionAttribute
);
request
.
setAttribute
(
"requestAttribute"
,
requestAttribute
);
HandlerMethod
handlerMethod
=
handlerMethod
(
"handle"
,
parameterTypes
);
ModelAndView
mav
=
handlerAdapter
.
handle
(
request
,
response
,
handlerMethod
);
...
...
@@ -219,6 +222,7 @@ public class RequestMappingHandlerAdapterIntegrationTests {
assertEquals
(
OtherUser
.
class
,
model
.
get
(
"otherUser"
).
getClass
());
assertSame
(
sessionAttribute
,
model
.
get
(
"sessionAttribute"
));
assertSame
(
requestAttribute
,
model
.
get
(
"requestAttribute"
));
assertEquals
(
new
URI
(
"http://localhost/contextPath/main/path"
),
model
.
get
(
"url"
));
}
...
...
@@ -369,6 +373,7 @@ public class RequestMappingHandlerAdapterIntegrationTests {
HttpServletRequest
request
,
HttpServletResponse
response
,
@SessionAttribute
TestBean
sessionAttribute
,
@RequestAttribute
TestBean
requestAttribute
,
User
user
,
@ModelAttribute
OtherUser
otherUser
,
Model
model
,
...
...
@@ -380,6 +385,7 @@ public class RequestMappingHandlerAdapterIntegrationTests {
.
addAttribute
(
"paramByConvention"
,
paramByConvention
).
addAttribute
(
"value"
,
value
)
.
addAttribute
(
"customArg"
,
customArg
).
addAttribute
(
user
)
.
addAttribute
(
"sessionAttribute"
,
sessionAttribute
)
.
addAttribute
(
"requestAttribute"
,
requestAttribute
)
.
addAttribute
(
"url"
,
builder
.
path
(
"/path"
).
build
().
toUri
());
assertNotNull
(
request
);
...
...
spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/SessionAttributeMethodArgumentResolverTests.java
浏览文件 @
e62ada89
...
...
@@ -15,154 +15,31 @@
*/
package
org.springframework.web.servlet.mvc.method.annotation
;
import
java.lang.reflect.Method
;
import
java.util.Optional
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.springframework.core.DefaultParameterNameDiscoverer
;
import
org.springframework.core.GenericTypeResolver
;
import
org.springframework.core.MethodParameter
;
import
org.springframework.core.annotation.SynthesizingMethodParameter
;
import
org.springframework.core.convert.support.DefaultConversionService
;
import
org.springframework.mock.web.test.MockHttpServletRequest
;
import
org.springframework.mock.web.test.MockHttpServletResponse
;
import
org.springframework.web.bind.ServletRequestBindingException
;
import
org.springframework.web.bind.WebDataBinder
;
import
org.springframework.web.bind.annotation.SessionAttribute
;
import
org.springframework.web.bind.support.WebDataBinderFactory
;
import
org.springframework.web.bind.support.WebRequestDataBinder
;
import
org.springframework.web.context.request.ServletWebRequest
;
import
org.springframework.web.method.support.ModelAndViewContainer
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertFalse
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
import
static
org
.
junit
.
Assert
.
assertNull
;
import
static
org
.
junit
.
Assert
.
assertSame
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
junit
.
Assert
.
fail
;
import
static
org
.
mockito
.
BDDMockito
.
given
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
org.springframework.web.context.request.RequestAttributes
;
import
org.springframework.web.method.support.HandlerMethodArgumentResolver
;
/**
* Unit tests for {@link SessionAttributeMethodArgumentResolver}.
* @author Rossen Stoyanchev
*/
public
class
SessionAttributeMethodArgumentResolverTests
{
private
ServletWebRequest
webRequest
;
private
MockHttpServletRequest
servletRequest
;
private
SessionAttributeMethodArgumentResolver
resolver
;
private
Method
handleMethod
;
public
class
SessionAttributeMethodArgumentResolverTests
extends
AbstractRequestAttributesArgumentResolverTests
{
@Before
public
void
setUp
()
throws
Exception
{
this
.
servletRequest
=
new
MockHttpServletRequest
();
this
.
webRequest
=
new
ServletWebRequest
(
this
.
servletRequest
,
new
MockHttpServletResponse
());
this
.
resolver
=
new
SessionAttributeMethodArgumentResolver
();
this
.
handleMethod
=
getClass
().
getDeclaredMethod
(
"handle"
,
Foo
.
class
,
Foo
.
class
,
Foo
.
class
,
Optional
.
class
,
Foo
.
class
);
}
@Test
public
void
supportsParameter
()
throws
Exception
{
assertTrue
(
this
.
resolver
.
supportsParameter
(
new
MethodParameter
(
this
.
handleMethod
,
0
)));
assertFalse
(
this
.
resolver
.
supportsParameter
(
new
MethodParameter
(
this
.
handleMethod
,
4
)));
}
@Test
public
void
resolve
()
throws
Exception
{
MethodParameter
param
=
initMethodParameter
(
0
);
try
{
testResolveArgument
(
param
);
fail
(
"Should be required by default"
);
}
catch
(
ServletRequestBindingException
ex
)
{
assertTrue
(
ex
.
getMessage
().
startsWith
(
"Missing session attribute"
));
}
Foo
foo
=
new
Foo
();
this
.
servletRequest
.
getSession
().
setAttribute
(
"foo"
,
foo
);
assertSame
(
foo
,
testResolveArgument
(
param
));
}
@Test
public
void
resolveWithName
()
throws
Exception
{
MethodParameter
param
=
initMethodParameter
(
1
);
Foo
foo
=
new
Foo
();
this
.
servletRequest
.
getSession
().
setAttribute
(
"specialFoo"
,
foo
);
assertSame
(
foo
,
testResolveArgument
(
param
));
@Override
protected
HandlerMethodArgumentResolver
createResolver
()
{
return
new
SessionAttributeMethodArgumentResolver
();
}
@Test
public
void
resolveNotRequired
()
throws
Exception
{
MethodParameter
param
=
initMethodParameter
(
2
);
assertNull
(
testResolveArgument
(
param
));
Foo
foo
=
new
Foo
();
this
.
servletRequest
.
getSession
().
setAttribute
(
"foo"
,
foo
);
assertSame
(
foo
,
testResolveArgument
(
param
));
}
@Test
public
void
resolveOptional
()
throws
Exception
{
WebDataBinder
dataBinder
=
new
WebRequestDataBinder
(
null
);
dataBinder
.
setConversionService
(
new
DefaultConversionService
());
WebDataBinderFactory
factory
=
mock
(
WebDataBinderFactory
.
class
);
given
(
factory
.
createBinder
(
this
.
webRequest
,
null
,
"foo"
)).
willReturn
(
dataBinder
);
MethodParameter
param
=
initMethodParameter
(
3
);
Object
actual
=
testResolveArgument
(
param
,
factory
);
assertNotNull
(
actual
);
assertEquals
(
Optional
.
class
,
actual
.
getClass
());
assertFalse
(((
Optional
)
actual
).
isPresent
());
Foo
foo
=
new
Foo
();
this
.
servletRequest
.
getSession
().
setAttribute
(
"foo"
,
foo
);
actual
=
testResolveArgument
(
param
,
factory
);
assertNotNull
(
actual
);
assertEquals
(
Optional
.
class
,
actual
.
getClass
());
assertTrue
(((
Optional
)
actual
).
isPresent
());
assertSame
(
foo
,
((
Optional
)
actual
).
get
());
}
private
Object
testResolveArgument
(
MethodParameter
param
)
throws
Exception
{
return
testResolveArgument
(
param
,
null
);
}
private
Object
testResolveArgument
(
MethodParameter
param
,
WebDataBinderFactory
factory
)
throws
Exception
{
ModelAndViewContainer
mavContainer
=
new
ModelAndViewContainer
();
return
this
.
resolver
.
resolveArgument
(
param
,
mavContainer
,
this
.
webRequest
,
factory
);
}
private
MethodParameter
initMethodParameter
(
int
parameterIndex
)
{
MethodParameter
param
=
new
SynthesizingMethodParameter
(
this
.
handleMethod
,
parameterIndex
);
param
.
initParameterNameDiscovery
(
new
DefaultParameterNameDiscoverer
());
GenericTypeResolver
.
resolveParameterType
(
param
,
SessionAttributeMethodArgumentResolver
.
class
);
return
param
;
}
@SuppressWarnings
(
"unused"
)
private
void
handle
(
@SessionAttribute
Foo
foo
,
@SessionAttribute
(
"specialFoo"
)
Foo
namedFoo
,
@SessionAttribute
(
name
=
"foo"
,
required
=
false
)
Foo
notRequiredFoo
,
@SessionAttribute
(
name
=
"foo"
)
Optional
<
Foo
>
optionalFoo
,
Foo
notAnnotatedFoo
)
{
@Override
protected
String
getHandleMethodName
()
{
return
"handleWithSessionAttribute"
;
}
private
static
class
Foo
{
@Override
protected
int
getScope
()
{
return
RequestAttributes
.
SCOPE_SESSION
;
}
}
src/asciidoc/web-mvc.adoc
浏览文件 @
e62ada89
...
...
@@ -1254,6 +1254,7 @@ multiple requests are allowed to access a session concurrently.
session attributes (e.g. user authentication object) as opposed to model
attributes temporarily stored in the session as part of a controller workflow
via `@SessionAttributes`.
* `@RequestAttribute` annotated parameters for access to request attributes.
* `HttpEntity
<?>` parameters for access to the Servlet request HTTP headers and
contents. The request stream will be converted to the entity body using
++HttpMessageConverter++s. See <<mvc-ann-httpentity>>.
...
...
@@ -1794,6 +1795,23 @@ workflow consider using `SessionAttributes` as described in
<
<
mvc-ann-sessionattrib
>
>.
[[mvc-ann-requestattrib]]
==== Using @RequestAttribute to access request attributes
Similar to `@SessionAttribute` the `@RequestAttribute` annotation can be used to
access pre-existing request attributes created by a filter or interceptor:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping("/")
public String handle(**@RequestAttribute** Client client) {
// ...
}
----
[[mvc-ann-form-urlencoded-data]]
==== Working with "application/x-www-form-urlencoded" data
...
...
src/asciidoc/whats-new.adoc
浏览文件 @
e62ada89
...
...
@@ -665,6 +665,7 @@ Spring 4.3 also improves the caching abstraction as follows:
* New `@RestControllerAdvice` annotation with combined `@ControllerAdvice` with `@ResponseBody` semantics.
* `@ResponseStatus` supported on the class level and inherited on all methods.
* New `@SessionAttribute` annotation for access to session attributes (see <<mvc-ann-sessionattrib-global, example>>).
* New `@RequestAttribute` annotation for access to session attributes (see <<mvc-ann-requestattrib, example>>).
* `AsyncRestTemplate` supports request interception.
=== WebSocket Messaging Improvements
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录