Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
爱吃血肠
spring-framework
提交
aba04d57
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,体验更适合开发者的 AI 搜索 >>
提交
aba04d57
编写于
2月 10, 2016
作者:
R
Rossen Stoyanchev
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Polish RedirectViewTests
上级
8558cbc9
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
80 addition
and
104 deletion
+80
-104
spring-webmvc/src/test/java/org/springframework/web/servlet/view/RedirectViewTests.java
...g/springframework/web/servlet/view/RedirectViewTests.java
+80
-104
未找到文件。
spring-webmvc/src/test/java/org/springframework/web/servlet/view/RedirectViewTests.java
浏览文件 @
aba04d57
/*
* Copyright 2002-201
4
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.
...
...
@@ -17,12 +17,13 @@
package
org.springframework.web.servlet.view
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.Map
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.springframework.http.HttpStatus
;
...
...
@@ -35,15 +36,17 @@ import org.springframework.web.context.ContextLoader;
import
org.springframework.web.context.support.StaticWebApplicationContext
;
import
org.springframework.web.servlet.DispatcherServlet
;
import
org.springframework.web.servlet.FlashMap
;
import
org.springframework.web.servlet.FlashMapManager
;
import
org.springframework.web.servlet.View
;
import
org.springframework.web.servlet.support.RequestDataValueProcessor
;
import
org.springframework.web.servlet.support.RequestDataValueProcessorWrapper
;
import
org.springframework.web.servlet.support.SessionFlashMapManager
;
import
org.springframework.web.util.WebUtils
;
import
static
org
.
junit
.
Assert
.*;
import
static
org
.
mockito
.
BDDMockito
.*;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
mockito
.
BDDMockito
.
given
;
import
static
org
.
mockito
.
BDDMockito
.
mock
;
import
static
org
.
mockito
.
BDDMockito
.
verify
;
/**
* Tests for redirect view, and query string construction.
...
...
@@ -53,10 +56,28 @@ import static org.mockito.BDDMockito.*;
* @author Juergen Hoeller
* @author Sam Brannen
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @since 27.05.2003
*/
public
class
RedirectViewTests
{
private
MockHttpServletRequest
request
;
private
MockHttpServletResponse
response
;
@Before
public
void
setUp
()
throws
Exception
{
this
.
request
=
new
MockHttpServletRequest
();
this
.
request
.
setContextPath
(
"/context"
);
this
.
request
.
setCharacterEncoding
(
WebUtils
.
DEFAULT_CHARACTER_ENCODING
);
this
.
request
.
setAttribute
(
DispatcherServlet
.
OUTPUT_FLASH_MAP_ATTRIBUTE
,
new
FlashMap
());
this
.
request
.
setAttribute
(
DispatcherServlet
.
FLASH_MAP_MANAGER_ATTRIBUTE
,
new
SessionFlashMapManager
());
this
.
response
=
new
MockHttpServletResponse
();
}
@Test
(
expected
=
IllegalArgumentException
.
class
)
public
void
noUrlSet
()
throws
Exception
{
RedirectView
rv
=
new
RedirectView
();
...
...
@@ -68,31 +89,18 @@ public class RedirectViewTests {
RedirectView
rv
=
new
RedirectView
();
rv
.
setUrl
(
"http://url.somewhere.com"
);
rv
.
setHttp10Compatible
(
false
);
MockHttpServletRequest
request
=
createRequest
();
MockHttpServletResponse
response
=
new
MockHttpServletResponse
();
request
.
setAttribute
(
DispatcherServlet
.
OUTPUT_FLASH_MAP_ATTRIBUTE
,
new
FlashMap
());
request
.
setAttribute
(
DispatcherServlet
.
FLASH_MAP_MANAGER_ATTRIBUTE
,
new
SessionFlashMapManager
());
rv
.
render
(
new
HashMap
<
String
,
Object
>(),
request
,
response
);
rv
.
render
(
new
HashMap
<>(),
request
,
response
);
assertEquals
(
303
,
response
.
getStatus
());
assertEquals
(
"http://url.somewhere.com"
,
response
.
getHeader
(
"Location"
));
}
private
MockHttpServletRequest
createRequest
()
{
MockHttpServletRequest
request
=
new
MockHttpServletRequest
();
request
.
setAttribute
(
DispatcherServlet
.
OUTPUT_FLASH_MAP_ATTRIBUTE
,
new
FlashMap
());
request
.
setAttribute
(
DispatcherServlet
.
FLASH_MAP_MANAGER_ATTRIBUTE
,
new
SessionFlashMapManager
());
return
request
;
}
@Test
public
void
explicitStatusCodeHttp11
()
throws
Exception
{
RedirectView
rv
=
new
RedirectView
();
rv
.
setUrl
(
"http://url.somewhere.com"
);
rv
.
setHttp10Compatible
(
false
);
rv
.
setStatusCode
(
HttpStatus
.
MOVED_PERMANENTLY
);
MockHttpServletRequest
request
=
createRequest
();
MockHttpServletResponse
response
=
new
MockHttpServletResponse
();
rv
.
render
(
new
HashMap
<
String
,
Object
>(),
request
,
response
);
rv
.
render
(
new
HashMap
<>(),
request
,
response
);
assertEquals
(
301
,
response
.
getStatus
());
assertEquals
(
"http://url.somewhere.com"
,
response
.
getHeader
(
"Location"
));
}
...
...
@@ -102,9 +110,7 @@ public class RedirectViewTests {
RedirectView
rv
=
new
RedirectView
();
rv
.
setUrl
(
"http://url.somewhere.com"
);
rv
.
setStatusCode
(
HttpStatus
.
MOVED_PERMANENTLY
);
MockHttpServletRequest
request
=
createRequest
();
MockHttpServletResponse
response
=
new
MockHttpServletResponse
();
rv
.
render
(
new
HashMap
<
String
,
Object
>(),
request
,
response
);
rv
.
render
(
new
HashMap
<>(),
request
,
response
);
assertEquals
(
301
,
response
.
getStatus
());
assertEquals
(
"http://url.somewhere.com"
,
response
.
getHeader
(
"Location"
));
}
...
...
@@ -113,10 +119,8 @@ public class RedirectViewTests {
public
void
attributeStatusCodeHttp10
()
throws
Exception
{
RedirectView
rv
=
new
RedirectView
();
rv
.
setUrl
(
"http://url.somewhere.com"
);
MockHttpServletRequest
request
=
createRequest
();
request
.
setAttribute
(
View
.
RESPONSE_STATUS_ATTRIBUTE
,
HttpStatus
.
CREATED
);
MockHttpServletResponse
response
=
new
MockHttpServletResponse
();
rv
.
render
(
new
HashMap
<
String
,
Object
>(),
request
,
response
);
rv
.
render
(
new
HashMap
<>(),
request
,
response
);
assertEquals
(
201
,
response
.
getStatus
());
assertEquals
(
"http://url.somewhere.com"
,
response
.
getHeader
(
"Location"
));
}
...
...
@@ -126,21 +130,18 @@ public class RedirectViewTests {
RedirectView
rv
=
new
RedirectView
();
rv
.
setUrl
(
"http://url.somewhere.com"
);
rv
.
setHttp10Compatible
(
false
);
MockHttpServletRequest
request
=
createRequest
();
request
.
setAttribute
(
View
.
RESPONSE_STATUS_ATTRIBUTE
,
HttpStatus
.
CREATED
);
MockHttpServletResponse
response
=
new
MockHttpServletResponse
();
rv
.
render
(
new
HashMap
<
String
,
Object
>(),
request
,
response
);
rv
.
render
(
new
HashMap
<>(),
request
,
response
);
assertEquals
(
201
,
response
.
getStatus
());
assertEquals
(
"http://url.somewhere.com"
,
response
.
getHeader
(
"Location"
));
}
@SuppressWarnings
(
"AssertEqualsBetweenInconvertibleTypes"
)
@Test
public
void
flashMap
()
throws
Exception
{
RedirectView
rv
=
new
RedirectView
();
rv
.
setUrl
(
"http://url.somewhere.com/path"
);
rv
.
setHttp10Compatible
(
false
);
MockHttpServletRequest
request
=
createRequest
();
HttpServletResponse
response
=
new
MockHttpServletResponse
();
FlashMap
flashMap
=
new
FlashMap
();
flashMap
.
put
(
"successMessage"
,
"yay!"
);
request
.
setAttribute
(
DispatcherServlet
.
OUTPUT_FLASH_MAP_ATTRIBUTE
,
flashMap
);
...
...
@@ -167,9 +168,7 @@ public class RedirectViewTests {
rv
.
setApplicationContext
(
wac
);
// Init RedirectView with WebAppCxt
rv
.
setUrl
(
"/path"
);
MockHttpServletRequest
request
=
createRequest
();
request
.
setAttribute
(
DispatcherServlet
.
WEB_APPLICATION_CONTEXT_ATTRIBUTE
,
wac
);
HttpServletResponse
response
=
new
MockHttpServletResponse
();
given
(
mockProcessor
.
processUrl
(
request
,
"/path"
)).
willReturn
(
"/path?key=123"
);
...
...
@@ -195,9 +194,6 @@ public class RedirectViewTests {
RedirectView
rv
=
new
RedirectView
();
rv
.
setUrl
(
"/path"
);
MockHttpServletRequest
request
=
createRequest
();
HttpServletResponse
response
=
new
MockHttpServletResponse
();
given
(
mockProcessor
.
processUrl
(
request
,
"/path"
)).
willReturn
(
"/path?key=123"
);
rv
.
render
(
new
ModelMap
(),
request
,
response
);
...
...
@@ -212,13 +208,13 @@ public class RedirectViewTests {
@Test
public
void
emptyMap
()
throws
Exception
{
String
url
=
"/myUrl"
;
doTest
(
new
HashMap
<
String
,
Object
>(),
url
,
false
,
url
);
doTest
(
new
HashMap
<>(),
url
,
false
,
url
);
}
@Test
public
void
emptyMapWithContextRelative
()
throws
Exception
{
String
url
=
"/myUrl"
;
doTest
(
new
HashMap
<
String
,
Object
>(),
url
,
true
,
url
);
doTest
(
new
HashMap
<
>(),
url
,
true
,
"/context"
+
url
);
}
@Test
...
...
@@ -226,7 +222,7 @@ public class RedirectViewTests {
String
url
=
"http://url.somewhere.com"
;
String
key
=
"foo"
;
String
val
=
"bar"
;
Map
<
String
,
String
>
model
=
new
HashMap
<
String
,
String
>();
Map
<
String
,
String
>
model
=
new
HashMap
<>();
model
.
put
(
key
,
val
);
String
expectedUrlForEncoding
=
url
+
"?"
+
key
+
"="
+
val
;
doTest
(
model
,
url
,
false
,
expectedUrlForEncoding
);
...
...
@@ -235,12 +231,13 @@ public class RedirectViewTests {
@Test
public
void
singleParamWithoutExposingModelAttributes
()
throws
Exception
{
String
url
=
"http://url.somewhere.com"
;
String
key
=
"foo"
;
String
val
=
"bar"
;
Map
<
String
,
String
>
model
=
new
HashMap
<
String
,
String
>();
model
.
put
(
key
,
val
);
String
expectedUrlForEncoding
=
url
;
// + "?" + key + "=" + val;
doTest
(
model
,
url
,
false
,
false
,
expectedUrlForEncoding
);
Map
<
String
,
String
>
model
=
Collections
.
singletonMap
(
"foo"
,
"bar"
);
TestRedirectView
rv
=
new
TestRedirectView
(
url
,
false
,
model
);
rv
.
setExposeModelAttributes
(
false
);
rv
.
render
(
model
,
request
,
response
);
assertEquals
(
url
,
this
.
response
.
getRedirectedUrl
());
}
@Test
...
...
@@ -248,7 +245,7 @@ public class RedirectViewTests {
String
url
=
"http://url.somewhere.com/test.htm#myAnchor"
;
String
key
=
"foo"
;
String
val
=
"bar"
;
Map
<
String
,
String
>
model
=
new
HashMap
<
String
,
String
>();
Map
<
String
,
String
>
model
=
new
HashMap
<>();
model
.
put
(
key
,
val
);
String
expectedUrlForEncoding
=
"http://url.somewhere.com/test.htm"
+
"?"
+
key
+
"="
+
val
+
"#myAnchor"
;
doTest
(
model
,
url
,
false
,
expectedUrlForEncoding
);
...
...
@@ -257,7 +254,7 @@ public class RedirectViewTests {
@Test
public
void
contextRelativeQueryParam
()
throws
Exception
{
String
url
=
"/test.html?id=1"
;
doTest
(
new
HashMap
<
String
,
Object
>(),
url
,
true
,
url
);
doTest
(
new
HashMap
<
>(),
url
,
true
,
"/context"
+
url
);
}
@Test
...
...
@@ -267,16 +264,16 @@ public class RedirectViewTests {
String
val
=
"bar"
;
String
key2
=
"thisIsKey2"
;
String
val2
=
"andThisIsVal2"
;
Map
<
String
,
String
>
model
=
new
HashMap
<
String
,
String
>();
Map
<
String
,
String
>
model
=
new
HashMap
<>();
model
.
put
(
key
,
val
);
model
.
put
(
key2
,
val2
);
try
{
String
expectedUrlForEncoding
=
"http://url.somewhere.com
?"
+
key
+
"="
+
val
+
"&"
+
key2
+
"="
+
val2
;
String
expectedUrlForEncoding
=
url
+
"
?"
+
key
+
"="
+
val
+
"&"
+
key2
+
"="
+
val2
;
doTest
(
model
,
url
,
false
,
expectedUrlForEncoding
);
}
catch
(
AssertionError
err
)
{
// OK, so it's the other order... probably on Sun JDK 1.6 or IBM JDK 1.5
String
expectedUrlForEncoding
=
"http://url.somewhere.com
?"
+
key2
+
"="
+
val2
+
"&"
+
key
+
"="
+
val
;
String
expectedUrlForEncoding
=
url
+
"
?"
+
key2
+
"="
+
val2
+
"&"
+
key
+
"="
+
val
;
doTest
(
model
,
url
,
false
,
expectedUrlForEncoding
);
}
}
...
...
@@ -286,15 +283,15 @@ public class RedirectViewTests {
String
url
=
"http://url.somewhere.com"
;
String
key
=
"foo"
;
String
[]
val
=
new
String
[]
{
"bar"
,
"baz"
};
Map
<
String
,
String
[]>
model
=
new
HashMap
<
String
,
String
[]
>();
Map
<
String
,
String
[]>
model
=
new
HashMap
<>();
model
.
put
(
key
,
val
);
try
{
String
expectedUrlForEncoding
=
"http://url.somewhere.com
?"
+
key
+
"="
+
val
[
0
]
+
"&"
+
key
+
"="
+
val
[
1
];
String
expectedUrlForEncoding
=
url
+
"
?"
+
key
+
"="
+
val
[
0
]
+
"&"
+
key
+
"="
+
val
[
1
];
doTest
(
model
,
url
,
false
,
expectedUrlForEncoding
);
}
catch
(
AssertionError
err
)
{
// OK, so it's the other order... probably on Sun JDK 1.6 or IBM JDK 1.5
String
expectedUrlForEncoding
=
"http://url.somewhere.com
?"
+
key
+
"="
+
val
[
1
]
+
"&"
+
key
+
"="
+
val
[
0
];
String
expectedUrlForEncoding
=
url
+
"
?"
+
key
+
"="
+
val
[
1
]
+
"&"
+
key
+
"="
+
val
[
0
];
doTest
(
model
,
url
,
false
,
expectedUrlForEncoding
);
}
}
...
...
@@ -303,18 +300,18 @@ public class RedirectViewTests {
public
void
collectionParam
()
throws
Exception
{
String
url
=
"http://url.somewhere.com"
;
String
key
=
"foo"
;
List
<
String
>
val
=
new
ArrayList
<
String
>();
List
<
String
>
val
=
new
ArrayList
<>();
val
.
add
(
"bar"
);
val
.
add
(
"baz"
);
Map
<
String
,
List
<
String
>>
model
=
new
HashMap
<
String
,
List
<
String
>
>();
Map
<
String
,
List
<
String
>>
model
=
new
HashMap
<>();
model
.
put
(
key
,
val
);
try
{
String
expectedUrlForEncoding
=
"http://url.somewhere.com
?"
+
key
+
"="
+
val
.
get
(
0
)
+
"&"
+
key
+
"="
+
val
.
get
(
1
);
String
expectedUrlForEncoding
=
url
+
"
?"
+
key
+
"="
+
val
.
get
(
0
)
+
"&"
+
key
+
"="
+
val
.
get
(
1
);
doTest
(
model
,
url
,
false
,
expectedUrlForEncoding
);
}
catch
(
AssertionError
err
)
{
// OK, so it's the other order... probably on Sun JDK 1.6 or IBM JDK 1.5
String
expectedUrlForEncoding
=
"http://url.somewhere.com
?"
+
key
+
"="
+
val
.
get
(
1
)
+
"&"
+
key
+
"="
+
val
.
get
(
0
);
String
expectedUrlForEncoding
=
url
+
"
?"
+
key
+
"="
+
val
.
get
(
1
)
+
"&"
+
key
+
"="
+
val
.
get
(
0
);
doTest
(
model
,
url
,
false
,
expectedUrlForEncoding
);
}
}
...
...
@@ -325,14 +322,14 @@ public class RedirectViewTests {
String
key
=
"foo"
;
String
val
=
"bar"
;
String
key2
=
"int2"
;
Object
val2
=
new
Long
(
611
)
;
Object
val2
=
611
;
String
key3
=
"tb"
;
Object
val3
=
new
TestBean
();
Map
<
String
,
Object
>
model
=
new
HashMap
<
String
,
Object
>();
Map
<
String
,
Object
>
model
=
new
LinkedHashMap
<
>();
model
.
put
(
key
,
val
);
model
.
put
(
key2
,
val2
);
model
.
put
(
key3
,
val3
);
String
expectedUrlForEncoding
=
"http://url.somewhere.com
?"
+
key
+
"="
+
val
+
"&"
+
key2
+
"="
+
val2
;
String
expectedUrlForEncoding
=
url
+
"
?"
+
key
+
"="
+
val
+
"&"
+
key2
+
"="
+
val2
;
doTest
(
model
,
url
,
false
,
expectedUrlForEncoding
);
}
...
...
@@ -341,64 +338,43 @@ public class RedirectViewTests {
RedirectView
rv
=
new
RedirectView
();
rv
.
setPropagateQueryParams
(
true
);
rv
.
setUrl
(
"http://url.somewhere.com?foo=bar#bazz"
);
MockHttpServletRequest
request
=
createRequest
();
MockHttpServletResponse
response
=
new
MockHttpServletResponse
();
request
.
setQueryString
(
"a=b&c=d"
);
rv
.
render
(
new
HashMap
<
String
,
Object
>(),
request
,
response
);
rv
.
render
(
new
HashMap
<>(),
request
,
response
);
assertEquals
(
302
,
response
.
getStatus
());
assertEquals
(
"http://url.somewhere.com?foo=bar&a=b&c=d#bazz"
,
response
.
getHeader
(
"Location"
));
}
private
void
doTest
(
Map
<
String
,
?>
map
,
String
url
,
boolean
contextRelative
,
String
expectedUrl
ForEncoding
)
private
void
doTest
(
Map
<
String
,
?>
map
,
String
url
,
boolean
contextRelative
,
String
expectedUrl
)
throws
Exception
{
doTest
(
map
,
url
,
contextRelative
,
true
,
expectedUrlForEncoding
);
}
private
void
doTest
(
final
Map
<
String
,
?>
map
,
final
String
url
,
final
boolean
contextRelative
,
final
boolean
exposeModelAttributes
,
String
expectedUrlForEncoding
)
throws
Exception
{
class
TestRedirectView
extends
RedirectView
{
TestRedirectView
rv
=
new
TestRedirectView
(
url
,
contextRelative
,
map
);
rv
.
render
(
map
,
request
,
response
);
public
boolean
queryPropertiesCalled
=
false
;
assertTrue
(
"queryProperties() should have been called."
,
rv
.
queryPropertiesCalled
);
assertEquals
(
expectedUrl
,
this
.
response
.
getRedirectedUrl
());
}
/**
* Test whether this callback method is called with correct args
*/
@Override
protected
Map
<
String
,
Object
>
queryProperties
(
Map
<
String
,
Object
>
model
)
{
// They may not be the same model instance, but they're still equal
assertTrue
(
"Map and model must be equal."
,
map
.
equals
(
model
));
this
.
queryPropertiesCalled
=
true
;
return
super
.
queryProperties
(
model
);
}
}
TestRedirectView
rv
=
new
TestRedirectView
();
rv
.
setUrl
(
url
);
rv
.
setContextRelative
(
contextRelative
);
rv
.
setExposeModelAttributes
(
exposeModelAttributes
);
private
static
class
TestRedirectView
extends
RedirectView
{
HttpServletRequest
request
=
mock
(
HttpServletRequest
.
class
,
"request"
);
if
(
exposeModelAttributes
)
{
given
(
request
.
getCharacterEncoding
()).
willReturn
(
WebUtils
.
DEFAULT_CHARACTER_ENCODING
);
}
if
(
contextRelative
)
{
expectedUrlForEncoding
=
"/context"
+
expectedUrlForEncoding
;
given
(
request
.
getContextPath
()).
willReturn
(
"/context"
);
}
private
Map
<
String
,
?>
expectedModel
;
given
(
request
.
getAttribute
(
DispatcherServlet
.
OUTPUT_FLASH_MAP_ATTRIBUTE
)).
willReturn
(
new
FlashMap
())
;
private
boolean
queryPropertiesCalled
=
false
;
FlashMapManager
flashMapManager
=
new
SessionFlashMapManager
();
given
(
request
.
getAttribute
(
DispatcherServlet
.
FLASH_MAP_MANAGER_ATTRIBUTE
)).
willReturn
(
flashMapManager
);
HttpServletResponse
response
=
mock
(
HttpServletResponse
.
class
,
"response"
);
given
(
response
.
encodeRedirectURL
(
expectedUrlForEncoding
)).
willReturn
(
expectedUrlForEncoding
);
response
.
sendRedirect
(
expectedUrlForEncoding
);
public
TestRedirectView
(
String
url
,
boolean
contextRelative
,
Map
<
String
,
?>
expectedModel
)
{
super
(
url
,
contextRelative
);
this
.
expectedModel
=
expectedModel
;
}
rv
.
render
(
map
,
request
,
response
);
if
(
exposeModelAttributes
)
{
assertTrue
(
"queryProperties() should have been called."
,
rv
.
queryPropertiesCalled
);
/**
* Test whether this callback method is called with correct args
*/
@Override
protected
Map
<
String
,
Object
>
queryProperties
(
Map
<
String
,
Object
>
model
)
{
assertTrue
(
"Map and model must be equal."
,
this
.
expectedModel
.
equals
(
model
));
this
.
queryPropertiesCalled
=
true
;
return
super
.
queryProperties
(
model
);
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录