Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
dk131072
spring-framework
提交
936c83b0
S
spring-framework
项目概览
dk131072
/
spring-framework
与 Fork 源项目一致
从无法访问的项目Fork
通知
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,发现更多精彩内容 >>
提交
936c83b0
编写于
8月 14, 2011
作者:
R
Rossen Stoyanchev
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
SPR-6464 Add RedirectModel
上级
84ff2b49
变更
13
隐藏空白更改
内联
并排
Showing
13 changed file
with
541 addition
and
220 deletion
+541
-220
org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java
.../method/annotation/ExceptionHandlerExceptionResolver.java
+3
-5
org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java
...t/mvc/method/annotation/RequestMappingHandlerAdapter.java
+15
-6
org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/RedirectModelMethodArgumentResolver.java
...notation/support/RedirectModelMethodArgumentResolver.java
+56
-0
org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ViewMethodReturnValueHandler.java
...thod/annotation/support/ViewMethodReturnValueHandler.java
+42
-15
org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/support/RedirectResponse.java
...work/web/servlet/mvc/method/support/RedirectResponse.java
+0
-122
org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/support/ViewResponse.java
...ramework/web/servlet/mvc/method/support/ViewResponse.java
+0
-50
org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/support/RedirectModel.java
...pringframework/web/servlet/mvc/support/RedirectModel.java
+199
-0
org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletAnnotationControllerHandlerMethodTests.java
...tation/ServletAnnotationControllerHandlerMethodTests.java
+6
-5
org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ViewMethodReturnValueHandlerTests.java
...annotation/support/ViewMethodReturnValueHandlerTests.java
+25
-0
org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/support/RedirectModelTests.java
...framework/web/servlet/mvc/support/RedirectModelTests.java
+149
-0
org.springframework.web/src/main/java/org/springframework/web/method/annotation/SessionAttributesHandler.java
...ework/web/method/annotation/SessionAttributesHandler.java
+6
-6
org.springframework.web/src/main/java/org/springframework/web/method/support/ModelAndViewContainer.java
...ngframework/web/method/support/ModelAndViewContainer.java
+39
-10
org.springframework.web/src/test/java/org/springframework/web/method/annotation/InitBinderDataBinderFactoryTests.java
...b/method/annotation/InitBinderDataBinderFactoryTests.java
+1
-1
未找到文件。
org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java
浏览文件 @
936c83b0
...
...
@@ -60,7 +60,6 @@ import org.springframework.web.servlet.mvc.method.annotation.support.ServletRequ
import
org.springframework.web.servlet.mvc.method.annotation.support.ServletResponseMethodArgumentResolver
;
import
org.springframework.web.servlet.mvc.method.annotation.support.ServletWebArgumentResolverAdapter
;
import
org.springframework.web.servlet.mvc.method.annotation.support.ViewMethodReturnValueHandler
;
import
org.springframework.web.servlet.mvc.method.support.ResponseContext
;
/**
* An {@link AbstractHandlerMethodExceptionResolver} that supports using {@link ExceptionHandler}-annotated methods
...
...
@@ -214,10 +213,10 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
protected
ModelAndView
doResolveHandlerMethodException
(
HttpServletRequest
request
,
HttpServletResponse
response
,
HandlerMethod
handlerMethod
,
Exception
ex
)
{
Exception
ex
ception
)
{
if
(
handlerMethod
!=
null
)
{
ExceptionMethodMapping
mapping
=
getExceptionMethodMapping
(
handlerMethod
);
Method
method
=
mapping
.
getMethod
(
ex
);
Method
method
=
mapping
.
getMethod
(
ex
ception
);
if
(
method
!=
null
)
{
Object
handler
=
handlerMethod
.
getBean
();
...
...
@@ -232,9 +231,8 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce
}
ModelAndViewContainer
mavContainer
=
new
ModelAndViewContainer
();
ResponseContext
responseContext
=
new
ResponseContext
(
webRequest
,
mavContainer
);
exceptionHandler
.
invokeAndHandle
(
webRequest
,
mavContainer
,
ex
,
responseContext
);
exceptionHandler
.
invokeAndHandle
(
webRequest
,
mavContainer
,
ex
ception
);
if
(!
mavContainer
.
isResolveView
())
{
return
new
ModelAndView
();
...
...
org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java
浏览文件 @
936c83b0
...
...
@@ -40,6 +40,7 @@ import org.springframework.http.converter.HttpMessageConverter;
import
org.springframework.http.converter.StringHttpMessageConverter
;
import
org.springframework.http.converter.xml.SourceHttpMessageConverter
;
import
org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter
;
import
org.springframework.ui.ModelMap
;
import
org.springframework.util.ReflectionUtils.MethodFilter
;
import
org.springframework.validation.DataBinder
;
import
org.springframework.web.bind.WebDataBinder
;
...
...
@@ -84,6 +85,7 @@ import org.springframework.web.servlet.mvc.method.annotation.support.DefaultMeth
import
org.springframework.web.servlet.mvc.method.annotation.support.HttpEntityMethodProcessor
;
import
org.springframework.web.servlet.mvc.method.annotation.support.ModelAndViewMethodReturnValueHandler
;
import
org.springframework.web.servlet.mvc.method.annotation.support.PathVariableMethodArgumentResolver
;
import
org.springframework.web.servlet.mvc.method.annotation.support.RedirectModelMethodArgumentResolver
;
import
org.springframework.web.servlet.mvc.method.annotation.support.RequestPartMethodArgumentResolver
;
import
org.springframework.web.servlet.mvc.method.annotation.support.RequestResponseBodyMethodProcessor
;
import
org.springframework.web.servlet.mvc.method.annotation.support.ServletCookieValueMethodArgumentResolver
;
...
...
@@ -91,7 +93,8 @@ import org.springframework.web.servlet.mvc.method.annotation.support.ServletMode
import
org.springframework.web.servlet.mvc.method.annotation.support.ServletRequestMethodArgumentResolver
;
import
org.springframework.web.servlet.mvc.method.annotation.support.ServletResponseMethodArgumentResolver
;
import
org.springframework.web.servlet.mvc.method.annotation.support.ViewMethodReturnValueHandler
;
import
org.springframework.web.servlet.mvc.method.support.ResponseContext
;
import
org.springframework.web.servlet.mvc.support.RedirectModel
;
import
org.springframework.web.servlet.support.RequestContextUtils
;
import
org.springframework.web.util.WebUtils
;
/**
...
...
@@ -366,6 +369,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
argumentResolvers
.
addResolver
(
new
ServletRequestMethodArgumentResolver
());
argumentResolvers
.
addResolver
(
new
ServletResponseMethodArgumentResolver
());
argumentResolvers
.
addResolver
(
new
HttpEntityMethodProcessor
(
messageConverters
));
argumentResolvers
.
addResolver
(
new
RedirectModelMethodArgumentResolver
());
argumentResolvers
.
addResolver
(
new
ModelMethodProcessor
());
argumentResolvers
.
addResolver
(
new
ErrorsMethodArgumentResolver
());
...
...
@@ -512,27 +516,32 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter i
ServletInvocableHandlerMethod
requestMappingMethod
=
createRequestMappingMethod
(
handlerMethod
);
ModelFactory
modelFactory
=
getModelFactory
(
handlerMethod
);
FlashMap
f
lashMap
=
(
FlashMap
)
request
.
getAttribute
(
FlashMapManager
.
PREVIOUS_FLASH_MAP_ATTRIBUTE
);
FlashMap
previousF
lashMap
=
(
FlashMap
)
request
.
getAttribute
(
FlashMapManager
.
PREVIOUS_FLASH_MAP_ATTRIBUTE
);
ModelAndViewContainer
mavContainer
=
new
ModelAndViewContainer
();
mavContainer
.
addAllAttributes
(
f
lashMap
);
mavContainer
.
addAllAttributes
(
previousF
lashMap
);
modelFactory
.
initModel
(
webRequest
,
mavContainer
,
requestMappingMethod
);
SessionStatus
sessionStatus
=
new
SimpleSessionStatus
();
ResponseContext
responseContext
=
new
ResponseContext
(
webRequest
,
mavContainer
);
requestMappingMethod
.
invokeAndHandle
(
webRequest
,
mavContainer
,
sessionStatus
,
responseContext
);
requestMappingMethod
.
invokeAndHandle
(
webRequest
,
mavContainer
,
sessionStatus
);
modelFactory
.
updateModel
(
webRequest
,
mavContainer
,
sessionStatus
);
if
(!
mavContainer
.
isResolveView
())
{
return
null
;
}
else
{
ModelAndView
mav
=
new
ModelAndView
().
addAllObjects
(
mavContainer
.
getModel
());
ModelMap
model
=
mavContainer
.
getModel
();
ModelAndView
mav
=
new
ModelAndView
().
addAllObjects
(
model
);
mav
.
setViewName
(
mavContainer
.
getViewName
());
if
(!
mavContainer
.
isViewReference
())
{
mav
.
setView
((
View
)
mavContainer
.
getView
());
}
if
(
model
instanceof
RedirectModel
)
{
RedirectModel
redirectModel
=
(
RedirectModel
)
model
;
FlashMap
currentFlashMap
=
RequestContextUtils
.
getFlashMap
(
request
);
currentFlashMap
.
putAll
(
redirectModel
.
getFlashAttributes
());
}
return
mav
;
}
}
...
...
org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/
support/ResponseContext
.java
→
org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/
annotation/support/RedirectModelMethodArgumentResolver
.java
浏览文件 @
936c83b0
...
...
@@ -14,55 +14,43 @@
* limitations under the License.
*/
package
org.springframework.web.servlet.mvc.method.support
;
package
org.springframework.web.servlet.mvc.method.
annotation.
support
;
import
org.springframework.core.MethodParameter
;
import
org.springframework.ui.Model
;
import
org.springframework.ui.ModelMap
;
import
org.springframework.validation.DataBinder
;
import
org.springframework.web.bind.support.WebDataBinderFactory
;
import
org.springframework.web.context.request.NativeWebRequest
;
import
org.springframework.web.method.annotation.support.ModelMethodProcessor
;
import
org.springframework.web.method.support.HandlerMethodArgumentResolver
;
import
org.springframework.web.method.support.ModelAndViewContainer
;
import
org.springframework.web.servlet.mvc.support.RedirectModel
;
/**
* Provides annotated controllers with convenience methods for setting up view
* resolution.
* Resolves {@link RedirectModel} method arguments.
*
* @author Keith Donald
* <p>This resolver must be listed ahead of the {@link ModelMethodProcessor},
* which also resolves arguments of type {@link Model}.
*
* @author Rossen Stoyanchev
*
* @since 3.1
*/
public
class
ResponseContext
{
private
final
NativeWebRequest
webRequest
;
public
class
RedirectModelMethodArgumentResolver
implements
HandlerMethodArgumentResolver
{
private
final
ModelAndViewContainer
mavContainer
;
public
ResponseContext
(
NativeWebRequest
webRequest
,
ModelAndViewContainer
mavContainer
)
{
this
.
webRequest
=
webRequest
;
this
.
mavContainer
=
mavContainer
;
public
boolean
supportsParameter
(
MethodParameter
parameter
)
{
return
RedirectModel
.
class
.
equals
(
parameter
.
getParameterType
());
}
/**
* Set up view resolution based on the given view name and the implicit model
* of the current request.
*/
public
ViewResponse
view
(
String
viewName
)
{
this
.
mavContainer
.
setViewName
(
viewName
);
return
new
ViewResponse
(
this
.
mavContainer
);
}
/**
* Set up view resolution for a redirect. This method clears the implicit
* model. Use convenience methods on the returned {@link RedirectResponse}
* instance to add URI variables, query parameters, and flash attributes
* as necessary.
* @param redirectUri a URI template either relative to the current URL or
* absolute; do not prefix with "redirect:"
*/
public
RedirectResponse
redirect
(
String
redirectUri
)
{
if
(!
redirectUri
.
startsWith
(
"redirect:"
))
{
redirectUri
=
"redirect:"
+
redirectUri
;
}
this
.
mavContainer
.
getModel
().
clear
();
this
.
mavContainer
.
setViewName
(
redirectUri
);
return
new
RedirectResponse
(
this
.
webRequest
,
this
.
mavContainer
);
public
Object
resolveArgument
(
MethodParameter
parameter
,
ModelAndViewContainer
mavContainer
,
NativeWebRequest
webRequest
,
WebDataBinderFactory
binderFactory
)
throws
Exception
{
DataBinder
dataBinder
=
binderFactory
.
createBinder
(
webRequest
,
null
,
null
);
ModelMap
implicitModel
=
mavContainer
.
getModel
();
RedirectModel
redirectModel
=
new
RedirectModel
(
dataBinder
,
implicitModel
);
mavContainer
.
setRedirectModel
(
redirectModel
);
return
redirectModel
;
}
}
org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ViewMethodReturnValueHandler.java
浏览文件 @
936c83b0
...
...
@@ -16,8 +16,6 @@
package
org.springframework.web.servlet.mvc.method.annotation.support
;
import
java.lang.reflect.Method
;
import
org.springframework.core.MethodParameter
;
import
org.springframework.web.bind.annotation.ModelAttribute
;
import
org.springframework.web.bind.annotation.ResponseBody
;
...
...
@@ -26,18 +24,20 @@ import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import
org.springframework.web.method.support.ModelAndViewContainer
;
import
org.springframework.web.servlet.RequestToViewNameTranslator
;
import
org.springframework.web.servlet.View
;
import
org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
;
/**
* Handles return values that are of type {@code void}, {@code String} (i.e. logical view name), or {@link View}.
* Handles return values that are of type {@code void}, {@code String} (i.e.
* logical view name), or {@link View}.
*
* <p>A {@code null} return value, either due to a void return type or as the actual value returned from a
* method is left unhandled, leaving it to the configured {@link RequestToViewNameTranslator} to resolve the
* request to an actual view name. By default it is the {@link DefaultRequestToViewNameTranslator}.
* <p>A {@code null} return value, either due to a void return type or as the
* actual value returned from a method is left unhandled, leaving it to the
* configured {@link RequestToViewNameTranslator} to resolve the request to
* an actual view name.
*
* <p>Since a {@link String} return value may handled in different ways, especially in combination with method
* annotations such as @{@link ModelAttribute} and @{@link ResponseBody}, this handler should be ordered after
* return value handlers that support method annotations.
* <p>Since a {@link String} return value may be handled in combination with
* method annotations such as @{@link ModelAttribute} or @{@link ResponseBody},
* this handler should be ordered after return value handlers that support
* method annotations.
*
* @author Rossen Stoyanchev
* @since 3.1
...
...
@@ -57,17 +57,44 @@ public class ViewMethodReturnValueHandler implements HandlerMethodReturnValueHan
return
;
}
if
(
returnValue
instanceof
String
)
{
mavContainer
.
setViewName
((
String
)
returnValue
);
String
viewName
=
(
String
)
returnValue
;
mavContainer
.
setViewName
(
viewName
);
if
(
isRedirectViewName
(
viewName
))
{
mavContainer
.
useRedirectModel
();
}
}
else
if
(
returnValue
instanceof
View
){
mavContainer
.
setView
(
returnValue
);
View
view
=
(
View
)
returnValue
;
mavContainer
.
setView
(
view
);
if
(
isRedirectView
(
view
))
{
mavContainer
.
useRedirectModel
();
}
}
else
{
// should not happen
Method
method
=
returnType
.
getMethod
();
String
returnTypeName
=
returnType
.
getParameterType
().
getName
();
throw
new
UnsupportedOperationException
(
"Unknown return type: "
+
returnTypeName
+
" in method: "
+
method
);
throw
new
UnsupportedOperationException
(
"Unknown return type: "
+
returnType
.
getParameterType
().
getName
()
+
" in method: "
+
returnType
.
getMethod
());
}
}
/**
* Whether the given view name is a redirect view reference.
* @param viewName the view name to check, never {@code null}
* @return "true" if the given view name is recognized as a redirect view
* reference; "false" otherwise.
*/
protected
boolean
isRedirectViewName
(
String
viewName
)
{
return
viewName
.
startsWith
(
"redirect:"
);
}
/**
* Whether the given View instance is a redirect view.
* @param view a view instance, never {@code null}
* @return "true" if the given view is recognized as a redirect View;
* "false" otherwise.
*/
protected
boolean
isRedirectView
(
View
view
)
{
return
"RedirectView"
.
equals
(
view
.
getClass
().
getSimpleName
());
}
}
org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/support/RedirectResponse.java
已删除
100644 → 0
浏览文件 @
84ff2b49
/*
* Copyright 2002-2011 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.support
;
import
java.util.Collection
;
import
javax.servlet.http.HttpServletRequest
;
import
org.springframework.core.Conventions
;
import
org.springframework.util.Assert
;
import
org.springframework.web.context.request.NativeWebRequest
;
import
org.springframework.web.method.support.ModelAndViewContainer
;
import
org.springframework.web.servlet.FlashMap
;
import
org.springframework.web.servlet.support.RequestContextUtils
;
/**
* Provides annotated controller methods with convenience methods for setting
* up response with a view name that will result in a redirect.
*
* <p>An instance of this class is obtained via {@link ResponseContext#redirect}.
*
* @author Keith Donald
* @author Rossen Stoyanchev
*
* @since 3.1
*/
public
class
RedirectResponse
{
private
final
NativeWebRequest
webRequest
;
private
final
ModelAndViewContainer
mavContainer
;
RedirectResponse
(
NativeWebRequest
webRequest
,
ModelAndViewContainer
mavContainer
)
{
this
.
webRequest
=
webRequest
;
this
.
mavContainer
=
mavContainer
;
}
/**
* Add a URI template variable to use to expand the URI template into a URL.
* <p><strong>Note:</strong> URI template variables from the current
* request are automatically used when expanding the redirect URI template.
* They don't need to be added explicitly here.
*/
public
RedirectResponse
uriVariable
(
String
name
,
Object
value
)
{
this
.
mavContainer
.
addAttribute
(
name
,
value
);
return
this
;
}
/**
* Add a URI template variable to use to expand the URI template into a URL.
* The name of the variable is selected using a
* {@link org.springframework.core.Conventions#getVariableName generated name}.
* <p><strong>Note:</strong> URI template variables from the current
* request are automatically used when expanding the redirect URI template.
* They don't need to be added explicitly here.
*/
public
RedirectResponse
uriVariable
(
Object
value
)
{
this
.
mavContainer
.
addAttribute
(
value
);
return
this
;
}
/**
* Add a query parameter to append to the redirect URL.
*/
public
RedirectResponse
queryParam
(
String
name
,
Object
value
)
{
this
.
mavContainer
.
addAttribute
(
name
,
value
);
return
this
;
}
/**
* Add a query parameter to append to the redirect URL.
* The name of the parameter is selected using a
* {@link org.springframework.core.Conventions#getVariableName generated name}.
*/
public
RedirectResponse
queryParam
(
Object
value
)
{
this
.
mavContainer
.
addAttribute
(
value
);
return
this
;
}
/**
* Add a flash attribute to save and make available in the model of the
* target controller method after the redirect.
*/
public
RedirectResponse
flashAttribute
(
String
name
,
Object
value
)
{
getFlashMap
().
put
(
name
,
value
);
return
this
;
}
/**
* Add a flash attribute to save and make available in the model of the
* target controller method after the redirect.
* The name of the attribute is selected using a
* {@link org.springframework.core.Conventions#getVariableName generated name}.
*/
public
RedirectResponse
flashAttribute
(
Object
attributeValue
)
{
Assert
.
notNull
(
attributeValue
,
"Model object must not be null"
);
if
(
attributeValue
instanceof
Collection
&&
((
Collection
)
attributeValue
).
isEmpty
())
{
return
this
;
}
return
flashAttribute
(
Conventions
.
getVariableName
(
attributeValue
),
attributeValue
);
}
private
FlashMap
getFlashMap
()
{
HttpServletRequest
servletRequest
=
webRequest
.
getNativeRequest
(
HttpServletRequest
.
class
);
return
RequestContextUtils
.
getFlashMap
(
servletRequest
);
}
}
org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/support/ViewResponse.java
已删除
100644 → 0
浏览文件 @
84ff2b49
/*
* Copyright 2002-2011 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.support
;
import
org.springframework.web.method.support.ModelAndViewContainer
;
/**
* Provides annotated controller methods with convenience methods for setting
* up a response with a view name that does not have the "redirect:" prefix .
*
* <p>An instance of this class is obtained via {@link ResponseContext#view}.
*
* @author Keith Donald
* @author Rossen Stoyanchev
*
* @since 3.1
*/
public
class
ViewResponse
{
private
final
ModelAndViewContainer
mavContainer
;
ViewResponse
(
ModelAndViewContainer
mavContainer
)
{
this
.
mavContainer
=
mavContainer
;
}
public
ViewResponse
attribute
(
String
attributeName
,
Object
attributeValue
)
{
this
.
mavContainer
.
addAttribute
(
attributeName
,
attributeValue
);
return
this
;
}
public
ViewResponse
attribute
(
Object
attributeValue
)
{
this
.
mavContainer
.
addAttribute
(
attributeValue
);
return
this
;
}
}
org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/support/RedirectModel.java
0 → 100644
浏览文件 @
936c83b0
/*
* Copyright 2002-2011 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.support
;
import
java.beans.PropertyEditor
;
import
java.util.Collection
;
import
java.util.Map
;
import
org.springframework.core.convert.converter.Converter
;
import
org.springframework.format.Formatter
;
import
org.springframework.ui.ExtendedModelMap
;
import
org.springframework.ui.Model
;
import
org.springframework.ui.ModelMap
;
import
org.springframework.util.Assert
;
import
org.springframework.validation.DataBinder
;
/**
* A {@link Model} implementation that controllers can use when they wish to
* redirect. For a redirect a controller needs to use an empty model and
* only add those attributes that will be used in the redirect URL --
* either embedded as URI template variables or appended as query parameters.
* To be used in the URL such attributes need to be formatted as String
* values. Alternatively a controller may choose to keep attributes in
* flash storage instead for the duration of the redirect.
*
* <p>A RedirectModel serves the above needs as follows:
* <ul>
* <li>Formats attribute values as Strings before adding them using a
* registered {@link Converter}, {@link Formatter}, {@link PropertyEditor},
* or the attribute's {@link #toString()} method.
* <li>Wraps the the model of the current request and provides a method to
* copy attributes from it (see {@link #addModelAttributes(String...)}).
* <li>Provides methods to store attributes candidate for flash storage.
* </ul>
*
* <p>Note that a RedirectModel will not be used unless the controller decides
* to redirect.
*
* @author Rossen Stoyanchev
* @since 3.1
*/
@SuppressWarnings
(
"serial"
)
public
class
RedirectModel
extends
ExtendedModelMap
{
private
final
DataBinder
dataBinder
;
private
final
ModelMap
flashAttributes
=
new
ModelMap
();
private
final
ModelMap
implicitModel
;
/**
* Create a new instance without a DataBinder. Attribute values will be
* formatted via {@link #toString()}.
*/
public
RedirectModel
()
{
this
(
null
,
null
);
}
/**
* Create a new instance providing a DataBinder to use for formatting
* attribute values.
* @param dataBinder a DataBinder for converting attribute values to String.
* @param implicitModel the implicit model for the current request;
* used in conjunction with {@link #addModelAttributes(String...)}
* to copy attributes from the implicit model to the redirect model.
*/
public
RedirectModel
(
DataBinder
dataBinder
,
ModelMap
implicitModel
)
{
this
.
dataBinder
=
dataBinder
;
this
.
implicitModel
=
implicitModel
;
}
/**
* Return the attributes candidate for flash storage.
*/
public
Map
<
String
,
?>
getFlashAttributes
()
{
return
flashAttributes
;
}
/**
* Add an attribute. Before being added the attribute value is formatted as
* a String in preparation for use in the redirect URL. If the attribute
* value is null it is not be added to the model.
* @param attributeName the attribute name; never null
* @param attributeValue the attribute value; skipped if null
*/
public
RedirectModel
addAttribute
(
String
attributeName
,
Object
attributeValue
)
{
if
(
attributeValue
!=
null
)
{
super
.
addAttribute
(
attributeName
,
formatValue
(
attributeValue
));
}
return
this
;
}
private
String
formatValue
(
Object
value
)
{
return
(
dataBinder
!=
null
)
?
dataBinder
.
convertIfNecessary
(
value
,
String
.
class
)
:
value
.
toString
();
}
/**
* Add an attribute using a
* {@link org.springframework.core.Conventions#getVariableName generated name}.
* Before being added the attribute value is formatted as a String.
* @param attributeValue the attribute value; never null
*/
public
RedirectModel
addAttribute
(
Object
attributeValue
)
{
super
.
addAttribute
(
attributeValue
);
return
this
;
}
/**
* Copy all attributes in the supplied <code>Collection</code> into this
* Model using attribute name generation for each element.
* @see #addAttribute(Object)
*/
public
RedirectModel
addAllAttributes
(
Collection
<?>
attributeValues
)
{
super
.
addAllAttributes
(
attributeValues
);
return
this
;
}
/**
* Copy all supplied attributes into this redirect model.
* @see #addAttribute(String, Object)
*/
public
RedirectModel
addAllAttributes
(
Map
<
String
,
?>
attributes
)
{
if
(
attributes
!=
null
)
{
for
(
String
key
:
attributes
.
keySet
())
{
addAttribute
(
key
,
attributes
.
get
(
key
));
}
}
return
this
;
}
/**
* Copy all supplied attributes into this redirect model with with existing
* attributes of the same name taking precedence (i.e. not getting replaced).
* @see #addAttribute(String, Object)
*/
public
RedirectModel
mergeAttributes
(
Map
<
String
,
?>
attributes
)
{
if
(
attributes
!=
null
)
{
for
(
String
key
:
attributes
.
keySet
())
{
if
(!
containsKey
(
key
))
{
addAttribute
(
key
,
attributes
.
get
(
key
));
}
}
}
return
this
;
}
/**
* Copy the attributes specified by name from the "implicit" model of the
* current request to this redirect model instance.
* @param attributeNames the names of attributes present in the implicit model.
* attribute names are required to be present; if an attribute is present
* but is null, it is skipped
* @see #addAttribute(String, Object)
*/
public
RedirectModel
addModelAttributes
(
String
...
attributeNames
)
{
Assert
.
notNull
(
this
.
implicitModel
,
"The implicit model has not been set."
);
for
(
String
name
:
attributeNames
)
{
Assert
.
isTrue
(
this
.
implicitModel
.
containsAttribute
(
name
),
name
+
" not found in implicit model"
);
Object
value
=
this
.
implicitModel
.
get
(
name
);
addAttribute
(
name
,
value
);
}
return
this
;
}
/**
* Add the given attribute as a candidate for flash storage.
* @param attributeName the flash attribute name; never null
* @param attributeValue the flash attribute value; may be null
*/
public
RedirectModel
addFlashAttribute
(
String
attributeName
,
Object
attributeValue
)
{
this
.
flashAttributes
.
addAttribute
(
attributeName
,
attributeValue
);
return
this
;
}
/**
* Add the given attribute value as a candidate for flash storage using a
* {@link org.springframework.core.Conventions#getVariableName generated name}.
* @param attributeValue the flash attribute value; never null
*/
public
RedirectModel
addFlashAttribute
(
Object
attributeValue
)
{
this
.
flashAttributes
.
addAttribute
(
attributeValue
);
return
this
;
}
}
org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletAnnotationControllerHandlerMethodTests.java
浏览文件 @
936c83b0
...
...
@@ -138,7 +138,7 @@ import org.springframework.web.servlet.View;
import
org.springframework.web.servlet.ViewResolver
;
import
org.springframework.web.servlet.mvc.annotation.ModelAndViewResolver
;
import
org.springframework.web.servlet.mvc.method.annotation.support.ServletWebArgumentResolverAdapter
;
import
org.springframework.web.servlet.mvc.
method.support.ResponseContext
;
import
org.springframework.web.servlet.mvc.
support.RedirectModel
;
import
org.springframework.web.servlet.support.RequestContextUtils
;
import
org.springframework.web.servlet.view.InternalResourceViewResolver
;
...
...
@@ -2816,13 +2816,14 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
@RequestMapping
(
value
=
"/messages"
,
method
=
RequestMethod
.
POST
)
public
void
sendMessage
(
TestBean
testBean
,
BindingResult
result
,
ResponseContext
responseContext
)
{
public
String
sendMessage
(
TestBean
testBean
,
BindingResult
result
,
RedirectModel
redirectModel
)
{
if
(
result
.
hasErrors
())
{
re
sponseContext
.
view
(
"messages/new"
)
;
re
turn
"messages/new"
;
}
else
{
responseContext
.
redirect
(
"/messages/{id}"
).
uriVariable
(
"id"
,
"1"
).
queryParam
(
"name"
,
"value"
)
.
flashAttribute
(
"successMessage"
,
"yay!"
);
redirectModel
.
addAttribute
(
"id"
,
"1"
).
addAttribute
(
"name"
,
"value"
);
redirectModel
.
addFlashAttribute
(
"successMessage"
,
"yay!"
);
return
"redirect:/messages/{id}"
;
}
}
}
...
...
org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/support/ViewMethodReturnValueHandlerTests.java
浏览文件 @
936c83b0
...
...
@@ -29,7 +29,9 @@ import org.springframework.mock.web.MockHttpServletRequest;
import
org.springframework.web.context.request.ServletWebRequest
;
import
org.springframework.web.method.support.ModelAndViewContainer
;
import
org.springframework.web.servlet.View
;
import
org.springframework.web.servlet.mvc.support.RedirectModel
;
import
org.springframework.web.servlet.view.InternalResourceView
;
import
org.springframework.web.servlet.view.RedirectView
;
/**
* Test fixture with {@link DefaultMethodReturnValueHandler}.
...
...
@@ -61,15 +63,38 @@ public class ViewMethodReturnValueHandlerTests {
public
void
returnView
()
throws
Exception
{
InternalResourceView
view
=
new
InternalResourceView
(
"testView"
);
handler
.
handleReturnValue
(
view
,
createMethodParam
(
"view"
),
mavContainer
,
webRequest
);
assertSame
(
view
,
mavContainer
.
getView
());
}
@Test
public
void
returnViewRedirect
()
throws
Exception
{
RedirectView
redirectView
=
new
RedirectView
(
"testView"
);
RedirectModel
redirectModel
=
new
RedirectModel
();
mavContainer
.
setRedirectModel
(
redirectModel
);
handler
.
handleReturnValue
(
redirectView
,
createMethodParam
(
"view"
),
mavContainer
,
webRequest
);
assertSame
(
redirectView
,
mavContainer
.
getView
());
assertSame
(
"Should have switched to the RedirectModel"
,
redirectModel
,
mavContainer
.
getModel
());
}
@Test
public
void
returnViewName
()
throws
Exception
{
handler
.
handleReturnValue
(
"testView"
,
createMethodParam
(
"viewName"
),
mavContainer
,
webRequest
);
assertEquals
(
"testView"
,
mavContainer
.
getViewName
());
}
@Test
public
void
returnViewNameRedirect
()
throws
Exception
{
RedirectModel
redirectModel
=
new
RedirectModel
();
mavContainer
.
setRedirectModel
(
redirectModel
);
handler
.
handleReturnValue
(
"redirect:testView"
,
createMethodParam
(
"viewName"
),
mavContainer
,
webRequest
);
assertEquals
(
"redirect:testView"
,
mavContainer
.
getViewName
());
assertSame
(
"Should have switched to the RedirectModel"
,
redirectModel
,
mavContainer
.
getModel
());
}
private
MethodParameter
createMethodParam
(
String
methodName
)
throws
Exception
{
Method
method
=
getClass
().
getDeclaredMethod
(
methodName
);
return
new
MethodParameter
(
method
,
-
1
);
...
...
org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/support/RedirectModelTests.java
0 → 100644
浏览文件 @
936c83b0
/*
* Copyright 2002-2011 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.support
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.Map
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.springframework.beans.TestBean
;
import
org.springframework.core.convert.converter.Converter
;
import
org.springframework.format.support.DefaultFormattingConversionService
;
import
org.springframework.format.support.FormattingConversionService
;
import
org.springframework.ui.ModelMap
;
import
org.springframework.validation.DataBinder
;
/**
*
* Test fixture for RedirectModel tests.
*
* @author Rossen Stoyanchev
* @since 3.1
*/
public
class
RedirectModelTests
{
private
RedirectModel
redirectModel
;
private
FormattingConversionService
conversionService
;
private
ModelMap
implicitModel
;
@Before
public
void
setup
()
{
this
.
conversionService
=
new
DefaultFormattingConversionService
();
DataBinder
dataBinder
=
new
DataBinder
(
null
);
dataBinder
.
setConversionService
(
conversionService
);
this
.
implicitModel
=
new
ModelMap
();
this
.
redirectModel
=
new
RedirectModel
(
dataBinder
,
implicitModel
);
}
@Test
public
void
addAttributePrimitiveType
()
{
this
.
redirectModel
.
addAttribute
(
"speed"
,
65
);
assertEquals
(
"65"
,
this
.
redirectModel
.
get
(
"speed"
));
}
@Test
public
void
addAttributeCustomType
()
{
String
attrName
=
"person"
;
this
.
redirectModel
.
addAttribute
(
attrName
,
new
TestBean
(
"Fred"
));
assertEquals
(
"ConversionService should have invoked toString()"
,
"Fred"
,
this
.
redirectModel
.
get
(
attrName
));
this
.
conversionService
.
addConverter
(
new
TestBeanConverter
());
this
.
redirectModel
.
addAttribute
(
attrName
,
new
TestBean
(
"Fred"
));
assertEquals
(
"Type converter should have been used"
,
"[Fred]"
,
this
.
redirectModel
.
get
(
attrName
));
}
@Test
public
void
addAttributeToString
()
{
String
attrName
=
"person"
;
RedirectModel
model
=
new
RedirectModel
();
model
.
addAttribute
(
attrName
,
new
TestBean
(
"Fred"
));
assertEquals
(
"toString() should have been used"
,
"Fred"
,
model
.
get
(
attrName
));
}
@Test
public
void
addAttributeValue
()
{
this
.
redirectModel
.
addAttribute
(
new
TestBean
(
"Fred"
));
assertEquals
(
"Fred"
,
this
.
redirectModel
.
get
(
"testBean"
));
}
@Test
public
void
addAllAttributesList
()
{
this
.
redirectModel
.
addAllAttributes
(
Arrays
.
asList
(
new
TestBean
(
"Fred"
),
new
Integer
(
5
)));
assertEquals
(
"Fred"
,
this
.
redirectModel
.
get
(
"testBean"
));
assertEquals
(
"5"
,
this
.
redirectModel
.
get
(
"integer"
));
}
@Test
public
void
addAttributesMap
()
{
Map
<
String
,
Object
>
map
=
new
HashMap
<
String
,
Object
>();
map
.
put
(
"person"
,
new
TestBean
(
"Fred"
));
map
.
put
(
"age"
,
33
);
this
.
redirectModel
.
addAllAttributes
(
map
);
assertEquals
(
"Fred"
,
this
.
redirectModel
.
get
(
"person"
));
assertEquals
(
"33"
,
this
.
redirectModel
.
get
(
"age"
));
}
@Test
public
void
mergeAttributes
()
{
Map
<
String
,
Object
>
map
=
new
HashMap
<
String
,
Object
>();
map
.
put
(
"person"
,
new
TestBean
(
"Fred"
));
map
.
put
(
"age"
,
33
);
this
.
redirectModel
.
addAttribute
(
"person"
,
new
TestBean
(
"Ralph"
));
this
.
redirectModel
.
mergeAttributes
(
map
);
assertEquals
(
"Ralph"
,
this
.
redirectModel
.
get
(
"person"
));
assertEquals
(
"33"
,
this
.
redirectModel
.
get
(
"age"
));
}
@Test
public
void
addModelAttributes
()
{
this
.
implicitModel
.
addAttribute
(
"person"
,
new
TestBean
(
"Ralph"
));
this
.
implicitModel
.
addAttribute
(
"age"
,
33
);
this
.
redirectModel
.
addModelAttributes
(
"person"
,
"age"
);
assertEquals
(
"Ralph"
,
this
.
redirectModel
.
get
(
"person"
));
assertEquals
(
"33"
,
this
.
redirectModel
.
get
(
"age"
));
}
@Test
(
expected
=
IllegalArgumentException
.
class
)
public
void
addModelAttributesInvalidName
()
{
this
.
redirectModel
.
addModelAttributes
(
"person"
);
}
public
static
class
TestBeanConverter
implements
Converter
<
TestBean
,
String
>
{
public
String
convert
(
TestBean
source
)
{
return
"["
+
source
.
getName
()
+
"]"
;
}
}
}
org.springframework.web/src/main/java/org/springframework/web/method/annotation/SessionAttributesHandler.java
浏览文件 @
936c83b0
...
...
@@ -24,7 +24,6 @@ import java.util.Map;
import
java.util.Set
;
import
org.springframework.core.annotation.AnnotationUtils
;
import
org.springframework.ui.Model
;
import
org.springframework.util.Assert
;
import
org.springframework.web.bind.annotation.SessionAttributes
;
import
org.springframework.web.bind.support.SessionAttributeStore
;
...
...
@@ -35,11 +34,12 @@ import org.springframework.web.context.request.WebRequest;
* Manages handler-specific session attributes declared via @{@link SessionAttributes}.
* Actual storage is performed through an instance of {@link SessionAttributeStore}.
*
* <p>A typical scenario begins with a controller adding attributes to the {@link Model}.
* At the end of the request, model attributes are checked to see if any of them match
* the names and types declared via @{@link SessionAttributes}. Matching model
* attributes are "promoted" to the session and remain there until the controller
* calls {@link SessionStatus#setComplete()} to indicate the session attributes are
* <p>A typical scenario begins with a controller adding attributes to the
* {@link org.springframework.ui.Model Model}. At the end of the request, model
* attributes are checked to see if any of them match the names and types declared
* via @{@link SessionAttributes}. Matching model attributes are "promoted" to
* the session and remain there until the controller calls
* {@link SessionStatus#setComplete()} to indicate the session attributes are
* no longer needed and can be removed.
*
* @author Rossen Stoyanchev
...
...
org.springframework.web/src/main/java/org/springframework/web/method/support/ModelAndViewContainer.java
浏览文件 @
936c83b0
...
...
@@ -35,9 +35,13 @@ public class ModelAndViewContainer {
private
Object
view
;
private
boolean
resolveView
=
true
;
private
final
ModelMap
model
=
new
BindingAwareModelMap
();
private
final
ModelMap
model
=
new
BindingAwareModelMap
();
private
ModelMap
redirectModel
;
private
boolean
useRedirectModel
=
false
;
/**
* Create a new instance.
*/
...
...
@@ -104,10 +108,35 @@ public class ModelAndViewContainer {
}
/**
* Return the underlying {@code ModelMap} instance, never {@code null}.
* Return the internal model currently in use. Normally this is the
* implicit model created in the constructor of this class.
* However, when a redirect model is provided via {@link #setRedirectModel}
* and then enabled for use via {@link #useRedirectModel()}, this method
* returns the redirect model instead.
*
* @return the internal model currently in use, never {@code null}.
*/
public
ModelMap
getModel
()
{
return
this
.
model
;
return
this
.
useRedirectModel
?
this
.
redirectModel
:
this
.
model
;
}
/**
* Provide a model that may be used in case of a redirect.
* If {@link #useRedirectModel()} is called at any time after this method is
* called, the ModelAndViewContainer will switch to using the redirect model
* for all operations. Until then, the redirect model is not used.
*/
public
void
setRedirectModel
(
ModelMap
redirectModel
)
{
this
.
redirectModel
=
redirectModel
;
}
/**
* Make a switch internally from using the implicit model to using the
* redirect model provided earlier via {@link #setRedirectModel(ModelMap)}.
* If the redirect model was never set, this method has no effect.
*/
public
void
useRedirectModel
()
{
this
.
useRedirectModel
=
this
.
redirectModel
!=
null
;
}
/**
...
...
@@ -115,7 +144,7 @@ public class ModelAndViewContainer {
* @see ModelMap#addAttribute(String, Object)
*/
public
ModelAndViewContainer
addAttribute
(
String
name
,
Object
value
)
{
this
.
model
.
addAttribute
(
name
,
value
);
getModel
()
.
addAttribute
(
name
,
value
);
return
this
;
}
...
...
@@ -124,7 +153,7 @@ public class ModelAndViewContainer {
* @see Model#addAttribute(Object)
*/
public
ModelAndViewContainer
addAttribute
(
Object
value
)
{
this
.
model
.
addAttribute
(
value
);
getModel
()
.
addAttribute
(
value
);
return
this
;
}
...
...
@@ -133,7 +162,7 @@ public class ModelAndViewContainer {
* @see ModelMap#addAllAttributes(Map)
*/
public
ModelAndViewContainer
addAllAttributes
(
Map
<
String
,
?>
attributes
)
{
this
.
model
.
addAllAttributes
(
attributes
);
getModel
()
.
addAllAttributes
(
attributes
);
return
this
;
}
...
...
@@ -143,7 +172,7 @@ public class ModelAndViewContainer {
* @see ModelMap#mergeAttributes(Map)
*/
public
ModelAndViewContainer
mergeAttributes
(
Map
<
String
,
?>
attributes
)
{
this
.
model
.
mergeAttributes
(
attributes
);
getModel
()
.
mergeAttributes
(
attributes
);
return
this
;
}
...
...
@@ -152,7 +181,7 @@ public class ModelAndViewContainer {
* @see ModelMap#containsAttribute(String)
*/
public
boolean
containsAttribute
(
String
name
)
{
return
this
.
model
.
containsAttribute
(
name
);
return
getModel
()
.
containsAttribute
(
name
);
}
}
org.springframework.web/src/test/java/org/springframework/web/method/annotation/InitBinderDataBinderFactoryTests.java
浏览文件 @
936c83b0
...
...
@@ -74,7 +74,7 @@ public class InitBinderDataBinderFactoryTests {
@Test
public
void
createBinderWithGlobalInitialization
()
throws
Exception
{
ConversionService
conversionService
=
new
DefaultFormattingConversionService
();
bindingInitializer
.
setConversionService
(
conversionService
);
bindingInitializer
.
setConversionService
(
conversionService
);
WebDataBinderFactory
factory
=
createBinderFactory
(
"initBinder"
,
WebDataBinder
.
class
);
WebDataBinder
dataBinder
=
factory
.
createBinder
(
webRequest
,
null
,
null
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录