Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
爱吃血肠
spring-framework
提交
698f923f
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,发现更多精彩内容 >>
提交
698f923f
编写于
1月 26, 2016
作者:
R
Rossen Stoyanchev
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add @SessionAttribute with Servlet-based support
Issue: SPR-13894
上级
7df3a327
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
394 addition
and
42 deletion
+394
-42
spring-web/src/main/java/org/springframework/web/bind/annotation/RequestMapping.java
...g/springframework/web/bind/annotation/RequestMapping.java
+5
-1
spring-web/src/main/java/org/springframework/web/bind/annotation/SessionAttribute.java
...springframework/web/bind/annotation/SessionAttribute.java
+73
-0
spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java
.../method/annotation/ExceptionHandlerExceptionResolver.java
+4
-1
spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java
...t/mvc/method/annotation/RequestMappingHandlerAdapter.java
+42
-36
spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/SessionAttributeMethodArgumentResolver.java
...od/annotation/SessionAttributeMethodArgumentResolver.java
+60
-0
spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterIntegrationTests.java
...otation/RequestMappingHandlerAdapterIntegrationTests.java
+9
-2
spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/SessionAttributeMethodArgumentResolverTests.java
...notation/SessionAttributeMethodArgumentResolverTests.java
+168
-0
src/asciidoc/web-mvc.adoc
src/asciidoc/web-mvc.adoc
+30
-0
src/asciidoc/whats-new.adoc
src/asciidoc/whats-new.adoc
+3
-2
未找到文件。
spring-web/src/main/java/org/springframework/web/bind/annotation/RequestMapping.java
浏览文件 @
698f923f
/*
* Copyright 2002-201
5
the original author or authors.
* Copyright 2002-201
6
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.
...
...
@@ -126,6 +126,10 @@ import org.springframework.core.annotation.AliasFor;
* {@link org.springframework.validation.Errors} argument.
* Instead a {@link org.springframework.web.bind.MethodArgumentNotValidException}
* exception is raised.
* <li>{@link SessionAttribute @SessionAttribute} annotated parameters for access
* 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 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
0 → 100644
浏览文件 @
698f923f
/*
* 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 session attribute.
*
* <p>The main motivation is to provide convenient access to existing, permanent
* session attributes (e.g. user authentication object) with an optional/required
* check and a cast to the target method parameter type.
*
* <p>For use cases that require adding or removing session attributes consider
* injecting {@code org.springframework.web.context.request.WebRequest} or
* {@code javax.servlet.http.HttpSession} into the controller method.
*
* <p>For temporary storage of model attributes in the session as part of the
* workflow for a controller, consider using {@link SessionAttributes} instead.
*
* @author Rossen Stoyanchev
* @since 4.3
* @see RequestMapping
* @see SessionAttributes
*/
@Target
(
ElementType
.
PARAMETER
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
public
@interface
SessionAttribute
{
/**
* Alias for {@link #name}.
*/
@AliasFor
(
"name"
)
String
value
()
default
""
;
/**
* The name of the session attribute to bind to.
* <p>The default name is inferred from the method parameter name.
*/
@AliasFor
(
"value"
)
String
name
()
default
""
;
/**
* Whether the session attribute is required.
* <p>Defaults to {@code true}, leading to an exception being thrown
* if the attribute is missing in the session or there is no session.
* 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-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java
浏览文件 @
698f923f
/*
* Copyright 2002-201
5
the original author or authors.
* Copyright 2002-201
6
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.
...
...
@@ -290,6 +290,9 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
protected
List
<
HandlerMethodArgumentResolver
>
getDefaultArgumentResolvers
()
{
List
<
HandlerMethodArgumentResolver
>
resolvers
=
new
ArrayList
<
HandlerMethodArgumentResolver
>();
// Annotation-based argument resolution
resolvers
.
add
(
new
SessionAttributeMethodArgumentResolver
());
// Type-based argument resolution
resolvers
.
add
(
new
ServletRequestMethodArgumentResolver
());
resolvers
.
add
(
new
ServletResponseMethodArgumentResolver
());
...
...
spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java
浏览文件 @
698f923f
...
...
@@ -600,6 +600,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
resolvers
.
add
(
new
RequestHeaderMapMethodArgumentResolver
());
resolvers
.
add
(
new
ServletCookieValueMethodArgumentResolver
(
getBeanFactory
()));
resolvers
.
add
(
new
ExpressionValueMethodArgumentResolver
(
getBeanFactory
()));
resolvers
.
add
(
new
SessionAttributeMethodArgumentResolver
());
// Type-based argument resolution
resolvers
.
add
(
new
ServletRequestMethodArgumentResolver
());
...
...
@@ -639,6 +640,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
resolvers
.
add
(
new
MatrixVariableMethodArgumentResolver
());
resolvers
.
add
(
new
MatrixVariableMapMethodArgumentResolver
());
resolvers
.
add
(
new
ExpressionValueMethodArgumentResolver
(
getBeanFactory
()));
resolvers
.
add
(
new
SessionAttributeMethodArgumentResolver
());
// Type-based argument resolution
resolvers
.
add
(
new
ServletRequestMethodArgumentResolver
());
...
...
@@ -788,46 +790,50 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
HttpServletResponse
response
,
HandlerMethod
handlerMethod
)
throws
Exception
{
ServletWebRequest
webRequest
=
new
ServletWebRequest
(
request
,
response
);
try
{
WebDataBinderFactory
binderFactory
=
getDataBinderFactory
(
handlerMethod
);
ModelFactory
modelFactory
=
getModelFactory
(
handlerMethod
,
binderFactory
);
ServletInvocableHandlerMethod
invocableMethod
=
createInvocableHandlerMethod
(
handlerMethod
);
invocableMethod
.
setHandlerMethodArgumentResolvers
(
this
.
argumentResolvers
);
invocableMethod
.
setHandlerMethodReturnValueHandlers
(
this
.
returnValueHandlers
);
invocableMethod
.
setDataBinderFactory
(
binderFactory
);
invocableMethod
.
setParameterNameDiscoverer
(
this
.
parameterNameDiscoverer
);
ModelAndViewContainer
mavContainer
=
new
ModelAndViewContainer
();
mavContainer
.
addAllAttributes
(
RequestContextUtils
.
getInputFlashMap
(
request
));
modelFactory
.
initModel
(
webRequest
,
mavContainer
,
invocableMethod
);
mavContainer
.
setIgnoreDefaultModelOnRedirect
(
this
.
ignoreDefaultModelOnRedirect
);
AsyncWebRequest
asyncWebRequest
=
WebAsyncUtils
.
createAsyncWebRequest
(
request
,
response
);
asyncWebRequest
.
setTimeout
(
this
.
asyncRequestTimeout
);
WebAsyncManager
asyncManager
=
WebAsyncUtils
.
getAsyncManager
(
request
);
asyncManager
.
setTaskExecutor
(
this
.
taskExecutor
);
asyncManager
.
setAsyncWebRequest
(
asyncWebRequest
);
asyncManager
.
registerCallableInterceptors
(
this
.
callableInterceptors
);
asyncManager
.
registerDeferredResultInterceptors
(
this
.
deferredResultInterceptors
);
if
(
asyncManager
.
hasConcurrentResult
())
{
Object
result
=
asyncManager
.
getConcurrentResult
();
mavContainer
=
(
ModelAndViewContainer
)
asyncManager
.
getConcurrentResultContext
()[
0
];
asyncManager
.
clearConcurrentResult
();
if
(
logger
.
isDebugEnabled
())
{
logger
.
debug
(
"Found concurrent result value ["
+
result
+
"]"
);
}
invocableMethod
=
invocableMethod
.
wrapConcurrentResult
(
result
);
}
WebDataBinderFactory
binderFactory
=
getDataBinderFactory
(
handlerMethod
);
ModelFactory
modelFactory
=
getModelFactory
(
handlerMethod
,
binderFactory
);
ServletInvocableHandlerMethod
invocableMethod
=
createInvocableHandlerMethod
(
handlerMethod
);
invocableMethod
.
setHandlerMethodArgumentResolvers
(
this
.
argumentResolvers
);
invocableMethod
.
setHandlerMethodReturnValueHandlers
(
this
.
returnValueHandlers
);
invocableMethod
.
setDataBinderFactory
(
binderFactory
);
invocableMethod
.
setParameterNameDiscoverer
(
this
.
parameterNameDiscoverer
);
ModelAndViewContainer
mavContainer
=
new
ModelAndViewContainer
();
mavContainer
.
addAllAttributes
(
RequestContextUtils
.
getInputFlashMap
(
request
));
modelFactory
.
initModel
(
webRequest
,
mavContainer
,
invocableMethod
);
mavContainer
.
setIgnoreDefaultModelOnRedirect
(
this
.
ignoreDefaultModelOnRedirect
);
AsyncWebRequest
asyncWebRequest
=
WebAsyncUtils
.
createAsyncWebRequest
(
request
,
response
);
asyncWebRequest
.
setTimeout
(
this
.
asyncRequestTimeout
);
WebAsyncManager
asyncManager
=
WebAsyncUtils
.
getAsyncManager
(
request
);
asyncManager
.
setTaskExecutor
(
this
.
taskExecutor
);
asyncManager
.
setAsyncWebRequest
(
asyncWebRequest
);
asyncManager
.
registerCallableInterceptors
(
this
.
callableInterceptors
);
asyncManager
.
registerDeferredResultInterceptors
(
this
.
deferredResultInterceptors
);
if
(
asyncManager
.
hasConcurrentResult
())
{
Object
result
=
asyncManager
.
getConcurrentResult
();
mavContainer
=
(
ModelAndViewContainer
)
asyncManager
.
getConcurrentResultContext
()[
0
];
asyncManager
.
clearConcurrentResult
();
if
(
logger
.
isDebugEnabled
())
{
logger
.
debug
(
"Found concurrent result value ["
+
result
+
"]"
);
invocableMethod
.
invokeAndHandle
(
webRequest
,
mavContainer
);
if
(
asyncManager
.
isConcurrentHandlingStarted
())
{
return
null
;
}
invocableMethod
=
invocableMethod
.
wrapConcurrentResult
(
result
);
}
invocableMethod
.
invokeAndHandle
(
webRequest
,
mavContainer
);
if
(
asyncManager
.
isConcurrentHandlingStarted
())
{
return
null
;
return
getModelAndView
(
mavContainer
,
modelFactory
,
webRequest
);
}
finally
{
webRequest
.
requestCompleted
();
}
return
getModelAndView
(
mavContainer
,
modelFactory
,
webRequest
);
}
/**
...
...
spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/SessionAttributeMethodArgumentResolver.java
0 → 100644
浏览文件 @
698f923f
/*
* 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.SessionAttribute
;
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 SessionAttribute}.
*
* @author Rossen Stoyanchev
* @since 4.3
*/
public
class
SessionAttributeMethodArgumentResolver
extends
AbstractNamedValueMethodArgumentResolver
{
@Override
public
boolean
supportsParameter
(
MethodParameter
parameter
)
{
return
parameter
.
hasParameterAnnotation
(
SessionAttribute
.
class
);
}
@Override
protected
NamedValueInfo
createNamedValueInfo
(
MethodParameter
parameter
)
{
SessionAttribute
annot
=
parameter
.
getParameterAnnotation
(
SessionAttribute
.
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_SESSION
);
}
@Override
protected
void
handleMissingValue
(
String
name
,
MethodParameter
parameter
)
throws
ServletException
{
throw
new
ServletRequestBindingException
(
"Missing session attribute '"
+
name
+
"' of type "
+
parameter
.
getNestedParameterType
().
getSimpleName
());
}
}
spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterIntegrationTests.java
浏览文件 @
698f923f
...
...
@@ -68,6 +68,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import
org.springframework.web.bind.annotation.RequestPart
;
import
org.springframework.web.bind.annotation.ResponseBody
;
import
org.springframework.web.bind.annotation.ResponseStatus
;
import
org.springframework.web.bind.annotation.SessionAttribute
;
import
org.springframework.web.bind.annotation.SessionAttributes
;
import
org.springframework.web.bind.support.ConfigurableWebBindingInitializer
;
import
org.springframework.web.bind.support.SessionStatus
;
...
...
@@ -148,12 +149,13 @@ 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
,
User
.
class
,
OtherUser
.
class
,
Model
.
class
,
UriComponentsBuilder
.
class
};
Color
.
class
,
HttpServletRequest
.
class
,
HttpServletResponse
.
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
();
request
.
addHeader
(
"Content-Type"
,
"text/plain; charset=utf-8"
);
request
.
addHeader
(
"header"
,
"headerValue"
);
...
...
@@ -171,6 +173,7 @@ public class RequestMappingHandlerAdapterIntegrationTests {
Map
<
String
,
String
>
uriTemplateVars
=
new
HashMap
<
String
,
String
>();
uriTemplateVars
.
put
(
"pathvar"
,
"pathvarValue"
);
request
.
setAttribute
(
HandlerMapping
.
URI_TEMPLATE_VARIABLES_ATTRIBUTE
,
uriTemplateVars
);
request
.
getSession
().
setAttribute
(
"sessionAttribute"
,
sessionAttribute
);
HandlerMethod
handlerMethod
=
handlerMethod
(
"handle"
,
parameterTypes
);
ModelAndView
mav
=
handlerAdapter
.
handle
(
request
,
response
,
handlerMethod
);
...
...
@@ -215,6 +218,8 @@ public class RequestMappingHandlerAdapterIntegrationTests {
assertEquals
(
User
.
class
,
model
.
get
(
"user"
).
getClass
());
assertEquals
(
OtherUser
.
class
,
model
.
get
(
"otherUser"
).
getClass
());
assertSame
(
sessionAttribute
,
model
.
get
(
"sessionAttribute"
));
assertEquals
(
new
URI
(
"http://localhost/contextPath/main/path"
),
model
.
get
(
"url"
));
}
...
...
@@ -363,6 +368,7 @@ public class RequestMappingHandlerAdapterIntegrationTests {
Color
customArg
,
HttpServletRequest
request
,
HttpServletResponse
response
,
@SessionAttribute
TestBean
sessionAttribute
,
User
user
,
@ModelAttribute
OtherUser
otherUser
,
Model
model
,
...
...
@@ -373,6 +379,7 @@ public class RequestMappingHandlerAdapterIntegrationTests {
.
addAttribute
(
"dateParam"
,
dateParam
).
addAttribute
(
"paramMap"
,
paramMap
)
.
addAttribute
(
"paramByConvention"
,
paramByConvention
).
addAttribute
(
"value"
,
value
)
.
addAttribute
(
"customArg"
,
customArg
).
addAttribute
(
user
)
.
addAttribute
(
"sessionAttribute"
,
sessionAttribute
)
.
addAttribute
(
"url"
,
builder
.
path
(
"/path"
).
build
().
toUri
());
assertNotNull
(
request
);
...
...
spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/SessionAttributeMethodArgumentResolverTests.java
0 → 100644
浏览文件 @
698f923f
/*
* 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
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
;
/**
* Unit tests for {@link SessionAttributeMethodArgumentResolver}.
* @author Rossen Stoyanchev
*/
public
class
SessionAttributeMethodArgumentResolverTests
{
private
ServletWebRequest
webRequest
;
private
MockHttpServletRequest
servletRequest
;
private
SessionAttributeMethodArgumentResolver
resolver
;
private
Method
handleMethod
;
@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
));
}
@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
)
{
}
private
static
class
Foo
{
}
}
src/asciidoc/web-mvc.adoc
浏览文件 @
698f923f
...
...
@@ -1250,6 +1250,10 @@ multiple requests are allowed to access a session concurrently.
* `@RequestPart` annotated parameters for access to the content of a
"multipart/form-data" request part. See
<
<
mvc-multipart-forms-non-browsers
>
> and
<
<
mvc-multipart
>
>.
* `@SessionAttribute` annotated parameters for access 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 `@SessionAttributes`.
* `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>>.
...
...
@@ -1765,6 +1769,32 @@ attribute name:
----
[[mvc-ann-sessionattrib-global]]
==== Using @SessionAttribute to access pre-existing global session attributes
If you need access to pre-existing session attributes that are managed globally,
i.e. outside the controller (e.g. by a filter), and may or may not be present
use the `@SessionAttribute` annotation on a method parameter:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@RequestMapping("/")
public String handle(**@SessionAttribute** User user) {
// ...
}
----
For use cases that require adding or removing session attributes consider injecting
`org.springframework.web.context.request.WebRequest` or
`javax.servlet.http.HttpSession` into the controller method.
For temporary storage of model attributes in the session as part of a controller
workflow consider using `SessionAttributes` as described in
<
<
mvc-ann-sessionattrib
>
>.
[[mvc-ann-form-urlencoded-data]]
==== Working with "application/x-www-form-urlencoded" data
...
...
src/asciidoc/whats-new.adoc
浏览文件 @
698f923f
...
...
@@ -662,8 +662,9 @@ Spring 4.3 also improves the caching abstraction as follows:
=== Web Improvements
* Built-in support for <<mvc-ann-requestmapping-head-options,HTTP HEAD and HTTP OPTIONS>>.
* New `@RestControllerAdvice` annotation combines `@ControllerAdvice` with `@ResponseBody`.
* `@ResponseStatus` can be used on a controller type and is inherited for all method.
* 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>>).
* `AsyncRestTemplate` supports request interception.
=== WebSocket Messaging Improvements
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录