Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
爱吃血肠
spring-framework
提交
7ee61306
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,发现更多精彩内容 >>
提交
7ee61306
编写于
4月 12, 2018
作者:
J
Juergen Hoeller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Revised reference example for linkable controller method signature
Issue: SPR-16710
上级
97ee94f4
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
131 addition
and
72 deletion
+131
-72
spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilderTests.java
...t/mvc/method/annotation/MvcUriComponentsBuilderTests.java
+118
-70
src/docs/asciidoc/web/webmvc.adoc
src/docs/asciidoc/web/webmvc.adoc
+13
-2
未找到文件。
spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilderTests.java
浏览文件 @
7ee61306
...
...
@@ -50,6 +50,7 @@ import org.springframework.web.context.request.RequestContextHolder;
import
org.springframework.web.context.request.ServletRequestAttributes
;
import
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
;
import
org.springframework.web.servlet.DispatcherServlet
;
import
org.springframework.web.servlet.ModelAndView
;
import
org.springframework.web.servlet.config.annotation.EnableWebMvc
;
import
org.springframework.web.servlet.config.annotation.WebMvcConfigurer
;
import
org.springframework.web.util.UriComponents
;
...
...
@@ -85,38 +86,38 @@ public class MvcUriComponentsBuilderTests {
@Test
public
void
testFromController
()
{
public
void
fromControllerPlain
()
{
UriComponents
uriComponents
=
fromController
(
PersonControllerImpl
.
class
).
build
();
assertThat
(
uriComponents
.
toUriString
(),
Matchers
.
endsWith
(
"/people"
));
}
@Test
public
void
testF
romControllerUriTemplate
()
{
public
void
f
romControllerUriTemplate
()
{
UriComponents
uriComponents
=
fromController
(
PersonsAddressesController
.
class
).
buildAndExpand
(
15
);
assertThat
(
uriComponents
.
toUriString
(),
endsWith
(
"/people/15/addresses"
));
}
@Test
public
void
testF
romControllerSubResource
()
{
public
void
f
romControllerSubResource
()
{
UriComponents
uriComponents
=
fromController
(
PersonControllerImpl
.
class
).
pathSegment
(
"something"
).
build
();
assertThat
(
uriComponents
.
toUriString
(),
endsWith
(
"/people/something"
));
}
@Test
public
void
testF
romControllerTwoTypeLevelMappings
()
{
public
void
f
romControllerTwoTypeLevelMappings
()
{
UriComponents
uriComponents
=
fromController
(
InvalidController
.
class
).
build
();
assertThat
(
uriComponents
.
toUriString
(),
is
(
"http://localhost/persons"
));
}
@Test
public
void
testF
romControllerNotMapped
()
{
public
void
f
romControllerNotMapped
()
{
UriComponents
uriComponents
=
fromController
(
UnmappedController
.
class
).
build
();
assertThat
(
uriComponents
.
toUriString
(),
is
(
"http://localhost/"
));
}
@Test
public
void
testF
romControllerWithCustomBaseUrlViaStaticCall
()
{
public
void
f
romControllerWithCustomBaseUrlViaStaticCall
()
{
UriComponentsBuilder
builder
=
UriComponentsBuilder
.
fromUriString
(
"http://example.org:9090/base"
);
UriComponents
uriComponents
=
fromController
(
builder
,
PersonControllerImpl
.
class
).
build
();
...
...
@@ -125,9 +126,9 @@ public class MvcUriComponentsBuilderTests {
}
@Test
public
void
testF
romControllerWithCustomBaseUrlViaInstance
()
{
public
void
f
romControllerWithCustomBaseUrlViaInstance
()
{
UriComponentsBuilder
builder
=
UriComponentsBuilder
.
fromUriString
(
"http://example.org:9090/base"
);
MvcUriComponentsBuilder
mvcBuilder
=
MvcUriComponentsBuilder
.
relativeTo
(
builder
);
MvcUriComponentsBuilder
mvcBuilder
=
relativeTo
(
builder
);
UriComponents
uriComponents
=
mvcBuilder
.
withController
(
PersonControllerImpl
.
class
).
build
();
assertEquals
(
"http://example.org:9090/base/people"
,
uriComponents
.
toString
());
...
...
@@ -135,7 +136,31 @@ public class MvcUriComponentsBuilderTests {
}
@Test
public
void
testFromMethodNamePathVariable
()
{
public
void
usesForwardedHostAsHostIfHeaderIsSet
()
{
this
.
request
.
addHeader
(
"X-Forwarded-Host"
,
"somethingDifferent"
);
UriComponents
uriComponents
=
fromController
(
PersonControllerImpl
.
class
).
build
();
assertThat
(
uriComponents
.
toUriString
(),
startsWith
(
"http://somethingDifferent"
));
}
@Test
public
void
usesForwardedHostAndPortFromHeader
()
{
request
.
addHeader
(
"X-Forwarded-Host"
,
"foobar:8088"
);
UriComponents
uriComponents
=
fromController
(
PersonControllerImpl
.
class
).
build
();
assertThat
(
uriComponents
.
toUriString
(),
startsWith
(
"http://foobar:8088"
));
}
@Test
public
void
usesFirstHostOfXForwardedHost
()
{
request
.
addHeader
(
"X-Forwarded-Host"
,
"barfoo:8888, localhost:8088"
);
UriComponents
uriComponents
=
fromController
(
PersonControllerImpl
.
class
).
build
();
assertThat
(
uriComponents
.
toUriString
(),
startsWith
(
"http://barfoo:8888"
));
}
@Test
public
void
fromMethodNamePathVariable
()
{
UriComponents
uriComponents
=
fromMethodName
(
ControllerWithMethods
.
class
,
"methodWithPathVariable"
,
"1"
).
build
();
...
...
@@ -143,7 +168,7 @@ public class MvcUriComponentsBuilderTests {
}
@Test
public
void
testF
romMethodNameTypeLevelPathVariable
()
{
public
void
f
romMethodNameTypeLevelPathVariable
()
{
this
.
request
.
setContextPath
(
"/myapp"
);
UriComponents
uriComponents
=
fromMethodName
(
PersonsAddressesController
.
class
,
"getAddressesForCountry"
,
"DE"
).
buildAndExpand
(
"1"
);
...
...
@@ -152,7 +177,7 @@ public class MvcUriComponentsBuilderTests {
}
@Test
public
void
testF
romMethodNameTwoPathVariables
()
{
public
void
f
romMethodNameTwoPathVariables
()
{
DateTime
now
=
DateTime
.
now
();
UriComponents
uriComponents
=
fromMethodName
(
ControllerWithMethods
.
class
,
"methodWithTwoPathVariables"
,
1
,
now
).
build
();
...
...
@@ -161,7 +186,7 @@ public class MvcUriComponentsBuilderTests {
}
@Test
public
void
testF
romMethodNameWithPathVarAndRequestParam
()
{
public
void
f
romMethodNameWithPathVarAndRequestParam
()
{
UriComponents
uriComponents
=
fromMethodName
(
ControllerWithMethods
.
class
,
"methodForNextPage"
,
"1"
,
10
,
5
).
build
();
...
...
@@ -179,21 +204,21 @@ public class MvcUriComponentsBuilderTests {
}
@Test
// SPR-11391
public
void
testF
romMethodNameTypeLevelPathVariableWithoutArgumentValue
()
{
public
void
f
romMethodNameTypeLevelPathVariableWithoutArgumentValue
()
{
UriComponents
uriComponents
=
fromMethodName
(
UserContactController
.
class
,
"showCreate"
,
123
).
build
();
assertThat
(
uriComponents
.
getPath
(),
is
(
"/user/123/contacts/create"
));
}
@Test
public
void
testF
romMethodNameNotMapped
()
{
public
void
f
romMethodNameNotMapped
()
{
UriComponents
uriComponents
=
fromMethodName
(
UnmappedController
.
class
,
"unmappedMethod"
).
build
();
assertThat
(
uriComponents
.
toUriString
(),
is
(
"http://localhost/"
));
}
@Test
public
void
testF
romMethodNameWithCustomBaseUrlViaStaticCall
()
{
public
void
f
romMethodNameWithCustomBaseUrlViaStaticCall
()
{
UriComponentsBuilder
builder
=
UriComponentsBuilder
.
fromUriString
(
"http://example.org:9090/base"
);
UriComponents
uriComponents
=
fromMethodName
(
builder
,
ControllerWithMethods
.
class
,
"methodWithPathVariable"
,
"1"
).
build
();
...
...
@@ -203,9 +228,9 @@ public class MvcUriComponentsBuilderTests {
}
@Test
public
void
testF
romMethodNameWithCustomBaseUrlViaInstance
()
{
public
void
f
romMethodNameWithCustomBaseUrlViaInstance
()
{
UriComponentsBuilder
builder
=
UriComponentsBuilder
.
fromUriString
(
"http://example.org:9090/base"
);
MvcUriComponentsBuilder
mvcBuilder
=
MvcUriComponentsBuilder
.
relativeTo
(
builder
);
MvcUriComponentsBuilder
mvcBuilder
=
relativeTo
(
builder
);
UriComponents
uriComponents
=
mvcBuilder
.
withMethodName
(
ControllerWithMethods
.
class
,
"methodWithPathVariable"
,
"1"
).
build
();
...
...
@@ -213,14 +238,8 @@ public class MvcUriComponentsBuilderTests {
assertEquals
(
"http://example.org:9090/base"
,
builder
.
toUriString
());
}
@Test
public
void
testFromMethodNameWithMetaAnnotation
()
{
UriComponents
uriComponents
=
fromMethodName
(
MetaAnnotationController
.
class
,
"handleInput"
).
build
();
assertThat
(
uriComponents
.
toUriString
(),
is
(
"http://localhost/input"
));
}
@Test
// SPR-14405
public
void
testFromMapping
NameWithOptionalParam
()
{
public
void
fromMethod
NameWithOptionalParam
()
{
UriComponents
uriComponents
=
fromMethodName
(
ControllerWithMethods
.
class
,
"methodWithOptionalParam"
,
new
Object
[]
{
null
}).
build
();
...
...
@@ -228,7 +247,14 @@ public class MvcUriComponentsBuilderTests {
}
@Test
public
void
testFromMethodCall
()
{
public
void
fromMethodNameWithMetaAnnotation
()
{
UriComponents
uriComponents
=
fromMethodName
(
MetaAnnotationController
.
class
,
"handleInput"
).
build
();
assertThat
(
uriComponents
.
toUriString
(),
is
(
"http://localhost/input"
));
}
@Test
public
void
fromMethodCallPlain
()
{
UriComponents
uriComponents
=
fromMethodCall
(
on
(
ControllerWithMethods
.
class
).
myMethod
(
null
)).
build
();
assertThat
(
uriComponents
.
toUriString
(),
startsWith
(
"http://localhost"
));
...
...
@@ -236,7 +262,7 @@ public class MvcUriComponentsBuilderTests {
}
@Test
public
void
testF
romMethodCallOnSubclass
()
{
public
void
f
romMethodCallOnSubclass
()
{
UriComponents
uriComponents
=
fromMethodCall
(
on
(
ExtendedController
.
class
).
myMethod
(
null
)).
build
();
assertThat
(
uriComponents
.
toUriString
(),
startsWith
(
"http://localhost"
));
...
...
@@ -244,16 +270,15 @@ public class MvcUriComponentsBuilderTests {
}
@Test
public
void
testF
romMethodCallWithTypeLevelUriVars
()
{
public
void
f
romMethodCallWithTypeLevelUriVars
()
{
UriComponents
uriComponents
=
fromMethodCall
(
on
(
PersonsAddressesController
.
class
).
getAddressesForCountry
(
"DE"
)).
buildAndExpand
(
15
);
assertThat
(
uriComponents
.
toUriString
(),
endsWith
(
"/people/15/addresses/DE"
));
}
@Test
public
void
testFromMethodCallWithPathVar
()
{
public
void
fromMethodCallWithPathVariable
()
{
UriComponents
uriComponents
=
fromMethodCall
(
on
(
ControllerWithMethods
.
class
).
methodWithPathVariable
(
"1"
)).
build
();
...
...
@@ -262,7 +287,7 @@ public class MvcUriComponentsBuilderTests {
}
@Test
public
void
testFromMethodCallWithPathVar
AndRequestParams
()
{
public
void
fromMethodCallWithPathVariable
AndRequestParams
()
{
UriComponents
uriComponents
=
fromMethodCall
(
on
(
ControllerWithMethods
.
class
).
methodForNextPage
(
"1"
,
10
,
5
)).
build
();
...
...
@@ -274,7 +299,7 @@ public class MvcUriComponentsBuilderTests {
}
@Test
public
void
testFromMethodCallWithPathVar
AndMultiValueRequestParams
()
{
public
void
fromMethodCallWithPathVariable
AndMultiValueRequestParams
()
{
UriComponents
uriComponents
=
fromMethodCall
(
on
(
ControllerWithMethods
.
class
).
methodWithMultiValueRequestParams
(
"1"
,
Arrays
.
asList
(
3
,
7
),
5
)).
build
();
...
...
@@ -286,7 +311,7 @@ public class MvcUriComponentsBuilderTests {
}
@Test
public
void
testF
romMethodCallWithCustomBaseUrlViaStaticCall
()
{
public
void
f
romMethodCallWithCustomBaseUrlViaStaticCall
()
{
UriComponentsBuilder
builder
=
UriComponentsBuilder
.
fromUriString
(
"http://example.org:9090/base"
);
UriComponents
uriComponents
=
fromMethodCall
(
builder
,
on
(
ControllerWithMethods
.
class
).
myMethod
(
null
)).
build
();
...
...
@@ -295,17 +320,49 @@ public class MvcUriComponentsBuilderTests {
}
@Test
public
void
testF
romMethodCallWithCustomBaseUrlViaInstance
()
{
public
void
f
romMethodCallWithCustomBaseUrlViaInstance
()
{
UriComponentsBuilder
builder
=
UriComponentsBuilder
.
fromUriString
(
"http://example.org:9090/base"
);
MvcUriComponentsBuilder
mvcBuilder
=
MvcUriComponentsBuilder
.
relativeTo
(
builder
);
MvcUriComponentsBuilder
mvcBuilder
=
relativeTo
(
builder
);
UriComponents
result
=
mvcBuilder
.
withMethodCall
(
on
(
ControllerWithMethods
.
class
).
myMethod
(
null
)).
build
();
assertEquals
(
"http://example.org:9090/base/something/else"
,
result
.
toString
());
assertEquals
(
"http://example.org:9090/base"
,
builder
.
toUriString
());
}
@Test
// SPR-16710
public
void
fromMethodCallWithModelAndViewReturnType
()
{
UriComponents
uriComponents
=
fromMethodCall
(
on
(
BookingControllerWithModelAndView
.
class
).
getBooking
(
21L
)).
buildAndExpand
(
42
);
assertEquals
(
"http://localhost/hotels/42/bookings/21"
,
uriComponents
.
encode
().
toUri
().
toString
());
}
@Test
// SPR-16710
public
void
fromMethodCallWithObjectReturnType
()
{
UriComponents
uriComponents
=
fromMethodCall
(
on
(
BookingControllerWithObject
.
class
).
getBooking
(
21L
)).
buildAndExpand
(
42
);
assertEquals
(
"http://localhost/hotels/42/bookings/21"
,
uriComponents
.
encode
().
toUri
().
toString
());
}
@Test
(
expected
=
IllegalStateException
.
class
)
// SPR-16710
public
void
fromMethodCallWithStringReturnType
()
{
UriComponents
uriComponents
=
fromMethodCall
(
on
(
BookingControllerWithString
.
class
).
getBooking
(
21L
)).
buildAndExpand
(
42
);
assertEquals
(
"http://localhost/hotels/42/bookings/21"
,
uriComponents
.
encode
().
toUri
().
toString
());
}
@Test
// SPR-16710
public
void
fromMethodNameWithStringReturnType
()
{
UriComponents
uriComponents
=
fromMethodName
(
BookingControllerWithString
.
class
,
"getBooking"
,
21L
).
buildAndExpand
(
42
);
assertEquals
(
"http://localhost/hotels/42/bookings/21"
,
uriComponents
.
encode
().
toUri
().
toString
());
}
@Test
public
void
testFromMappingName
()
{
public
void
fromMappingNamePlain
()
{
AnnotationConfigWebApplicationContext
context
=
new
AnnotationConfigWebApplicationContext
();
context
.
setServletContext
(
new
MockServletContext
());
context
.
register
(
WebConfig
.
class
);
...
...
@@ -317,12 +374,12 @@ public class MvcUriComponentsBuilderTests {
this
.
request
.
setContextPath
(
"/base"
);
String
mappingName
=
"PAC#getAddressesForCountry"
;
String
url
=
MvcUriComponentsBuilder
.
fromMappingName
(
mappingName
).
arg
(
0
,
"DE"
).
buildAndExpand
(
123
);
String
url
=
fromMappingName
(
mappingName
).
arg
(
0
,
"DE"
).
buildAndExpand
(
123
);
assertEquals
(
"/base/people/123/addresses/DE"
,
url
);
}
@Test
public
void
testF
romMappingNameWithCustomBaseUrl
()
{
public
void
f
romMappingNameWithCustomBaseUrl
()
{
AnnotationConfigWebApplicationContext
context
=
new
AnnotationConfigWebApplicationContext
();
context
.
setServletContext
(
new
MockServletContext
());
context
.
register
(
WebConfig
.
class
);
...
...
@@ -331,42 +388,11 @@ public class MvcUriComponentsBuilderTests {
this
.
request
.
setAttribute
(
DispatcherServlet
.
WEB_APPLICATION_CONTEXT_ATTRIBUTE
,
context
);
UriComponentsBuilder
baseUrl
=
UriComponentsBuilder
.
fromUriString
(
"http://example.org:9999/base"
);
MvcUriComponentsBuilder
mvcBuilder
=
MvcUriComponentsBuilder
.
relativeTo
(
baseUrl
);
MvcUriComponentsBuilder
mvcBuilder
=
relativeTo
(
baseUrl
);
String
url
=
mvcBuilder
.
withMappingName
(
"PAC#getAddressesForCountry"
).
arg
(
0
,
"DE"
).
buildAndExpand
(
123
);
assertEquals
(
"http://example.org:9999/base/people/123/addresses/DE"
,
url
);
}
@Test
public
void
usesForwardedHostAsHostIfHeaderIsSet
()
{
this
.
request
.
addHeader
(
"X-Forwarded-Host"
,
"somethingDifferent"
);
UriComponents
uriComponents
=
fromController
(
PersonControllerImpl
.
class
).
build
();
assertThat
(
uriComponents
.
toUriString
(),
startsWith
(
"http://somethingDifferent"
));
}
@Test
public
void
usesForwardedHostAndPortFromHeader
()
{
request
.
addHeader
(
"X-Forwarded-Host"
,
"foobar:8088"
);
UriComponents
uriComponents
=
fromController
(
PersonControllerImpl
.
class
).
build
();
assertThat
(
uriComponents
.
toUriString
(),
startsWith
(
"http://foobar:8088"
));
}
@Test
public
void
usesFirstHostOfXForwardedHost
()
{
request
.
addHeader
(
"X-Forwarded-Host"
,
"barfoo:8888, localhost:8088"
);
UriComponents
uriComponents
=
fromController
(
PersonControllerImpl
.
class
).
build
();
assertThat
(
uriComponents
.
toUriString
(),
startsWith
(
"http://barfoo:8888"
));
}
@Test
// SPR-16710
public
void
withStringReturnType
()
{
UriComponents
uriComponents
=
MvcUriComponentsBuilder
.
fromMethodCall
(
on
(
BookingController
.
class
).
getBooking
(
21L
)).
buildAndExpand
(
42
);
assertEquals
(
"http://localhost/hotels/42/bookings/21"
,
uriComponents
.
encode
().
toUri
().
toString
());
}
static
class
Person
{
...
...
@@ -516,7 +542,18 @@ public class MvcUriComponentsBuilderTests {
@Controller
@RequestMapping
(
"/hotels/{hotel}"
)
public
class
BookingController
{
static
class
BookingControllerWithModelAndView
{
@GetMapping
(
"/bookings/{booking}"
)
public
ModelAndView
getBooking
(
@PathVariable
Long
booking
)
{
return
new
ModelAndView
(
"url"
);
}
}
@Controller
@RequestMapping
(
"/hotels/{hotel}"
)
static
class
BookingControllerWithObject
{
@GetMapping
(
"/bookings/{booking}"
)
public
Object
getBooking
(
@PathVariable
Long
booking
)
{
...
...
@@ -524,4 +561,15 @@ public class MvcUriComponentsBuilderTests {
}
}
@Controller
@RequestMapping
(
"/hotels/{hotel}"
)
static
class
BookingControllerWithString
{
@GetMapping
(
"/bookings/{booking}"
)
public
String
getBooking
(
@PathVariable
Long
booking
)
{
return
"url"
;
}
}
}
src/docs/asciidoc/web/webmvc.adoc
浏览文件 @
7ee61306
...
...
@@ -3098,7 +3098,8 @@ per request, and also provides an option to remove and ignore such headers.
[[mvc-links-to-controllers]]
=== Links to controllers
Spring MVC provides a mechanism to prepare links to controller methods. For example:
Spring MVC provides a mechanism to prepare links to controller methods. For example,
the following MVC controller easily allows for link creation:
[source,java,indent=0]
[subs="verbatim,quotes"]
...
...
@@ -3108,7 +3109,7 @@ Spring MVC provides a mechanism to prepare links to controller methods. For exam
public class BookingController {
@GetMapping("/bookings/{booking}")
public
String
getBooking(@PathVariable Long booking) {
public
ModelAndView
getBooking(@PathVariable Long booking) {
// ...
}
}
...
...
@@ -3145,6 +3146,16 @@ akin to mock testing through proxies to avoid referring to the controller method
URI uri = uriComponents.encode().toUri();
----
[NOTE]
====
Controller method signatures are limited in their design when supposed to be usable for
link creation with `fromMethodCall`. Aside from needing a proper parameter signature,
there is a technical limitation on the return type: namely generating a runtime proxy
for link builder invocations, so the return type must not be `final`. In particular,
the common `String` return type for view names does not work here; use `ModelAndView`
or even plain `Object` (with a `String` return value) instead.
====
The above examples use static methods in `MvcUriComponentsBuilder`. Internally they rely
on `ServletUriComponentsBuilder` to prepare a base URL from the scheme, host, port,
context path and servlet path of the current request. This works well in most cases,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录