Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
爱吃血肠
spring-framework
提交
dc3851df
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 搜索 >>
提交
dc3851df
编写于
3月 27, 2017
作者:
R
Rossen Stoyanchev
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Extract AbstractCodecConfigurer base class
Issue: SPR-15247
上级
5211a099
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
717 addition
and
469 deletion
+717
-469
spring-web/src/main/java/org/springframework/http/codec/AbstractCodecConfigurer.java
...g/springframework/http/codec/AbstractCodecConfigurer.java
+400
-0
spring-web/src/main/java/org/springframework/http/codec/ServerCodecConfigurer.java
...org/springframework/http/codec/ServerCodecConfigurer.java
+27
-292
spring-web/src/test/java/org/springframework/http/codec/CodecConfigurerTests.java
.../org/springframework/http/codec/CodecConfigurerTests.java
+289
-0
spring-web/src/test/java/org/springframework/http/codec/ServerCodecConfigurerTests.java
...pringframework/http/codec/ServerCodecConfigurerTests.java
+0
-166
spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurationSupport.java
...work/web/reactive/config/WebFluxConfigurationSupport.java
+1
-11
未找到文件。
spring-web/src/main/java/org/springframework/http/codec/AbstractCodecConfigurer.java
0 → 100644
浏览文件 @
dc3851df
/*
* Copyright 2002-2017 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.http.codec
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.function.Supplier
;
import
org.springframework.core.ResolvableType
;
import
org.springframework.core.codec.ByteArrayDecoder
;
import
org.springframework.core.codec.ByteArrayEncoder
;
import
org.springframework.core.codec.ByteBufferDecoder
;
import
org.springframework.core.codec.ByteBufferEncoder
;
import
org.springframework.core.codec.CharSequenceEncoder
;
import
org.springframework.core.codec.DataBufferDecoder
;
import
org.springframework.core.codec.DataBufferEncoder
;
import
org.springframework.core.codec.Decoder
;
import
org.springframework.core.codec.Encoder
;
import
org.springframework.core.codec.ResourceDecoder
;
import
org.springframework.core.codec.StringDecoder
;
import
org.springframework.http.codec.json.Jackson2JsonDecoder
;
import
org.springframework.http.codec.json.Jackson2JsonEncoder
;
import
org.springframework.http.codec.xml.Jaxb2XmlDecoder
;
import
org.springframework.http.codec.xml.Jaxb2XmlEncoder
;
import
org.springframework.util.Assert
;
import
org.springframework.util.ClassUtils
;
/**
* Base class for client or server codec configurers.
*
* @author Rossen Stoyanchev
* @since 5.0
*/
public
abstract
class
AbstractCodecConfigurer
{
public
static
final
boolean
jackson2Present
=
ClassUtils
.
isPresent
(
"com.fasterxml.jackson.databind.ObjectMapper"
,
ServerCodecConfigurer
.
class
.
getClassLoader
())
&&
ClassUtils
.
isPresent
(
"com.fasterxml.jackson.core.JsonGenerator"
,
ServerCodecConfigurer
.
class
.
getClassLoader
());
public
static
final
boolean
jaxb2Present
=
ClassUtils
.
isPresent
(
"javax.xml.bind.Binder"
,
ServerCodecConfigurer
.
class
.
getClassLoader
());
private
final
DefaultCodecConfigurer
defaultCodecs
;
private
final
CustomCodecConfigurer
customCodecs
=
new
CustomCodecConfigurer
();
/**
* Protected constructor with the configurer for default readers and writers.
*/
protected
AbstractCodecConfigurer
(
DefaultCodecConfigurer
defaultCodecConfigurer
)
{
Assert
.
notNull
(
defaultCodecConfigurer
,
"DefaultCodecConfigurer is required."
);
this
.
defaultCodecs
=
defaultCodecConfigurer
;
}
/**
* Provide overrides for built-in HTTP message readers or writers.
*/
public
DefaultCodecConfigurer
defaultCodec
()
{
return
this
.
defaultCodecs
;
}
/**
* Whether to make default HTTP message reader and writer registrations.
* <p>By default this is set to {@code "true"}.
*/
public
void
registerDefaults
(
boolean
registerDefaults
)
{
this
.
defaultCodec
().
setSuppressed
(!
registerDefaults
);
}
/**
* Register a custom encoder or decoder.
*/
public
CustomCodecConfigurer
customCodec
()
{
return
this
.
customCodecs
;
}
/**
* Prepare a list of HTTP message readers.
*/
public
List
<
HttpMessageReader
<?>>
getReaders
()
{
List
<
HttpMessageReader
<?>>
result
=
new
ArrayList
<>();
addDefaultTypedReaders
(
result
);
addCustomTypedReaders
(
result
);
addDefaultObjectReaders
(
result
);
addCustomObjectReaders
(
result
);
defaultCodec
().
addStringReaderTo
(
result
);
return
result
;
}
/**
* Add built-in, concrete, Java type readers.
*/
protected
void
addDefaultTypedReaders
(
List
<
HttpMessageReader
<?>>
result
)
{
defaultCodec
().
addReaderTo
(
result
,
ByteArrayDecoder
.
class
,
ByteArrayDecoder:
:
new
);
defaultCodec
().
addReaderTo
(
result
,
ByteBufferDecoder
.
class
,
ByteBufferDecoder:
:
new
);
defaultCodec
().
addReaderTo
(
result
,
DataBufferDecoder
.
class
,
DataBufferDecoder:
:
new
);
defaultCodec
().
addReaderTo
(
result
,
ResourceDecoder
.
class
,
ResourceDecoder:
:
new
);
defaultCodec
().
addStringReaderTextOnlyTo
(
result
);
}
/**
* Add custom, concrete, Java type readers.
*/
protected
void
addCustomTypedReaders
(
List
<
HttpMessageReader
<?>>
result
)
{
customCodec
().
addTypedReadersTo
(
result
);
}
/**
* Add built-in, Object-based readers.
*/
protected
void
addDefaultObjectReaders
(
List
<
HttpMessageReader
<?>>
result
)
{
if
(
jaxb2Present
)
{
defaultCodec
().
addReaderTo
(
result
,
Jaxb2XmlDecoder
.
class
,
Jaxb2XmlDecoder:
:
new
);
}
if
(
jackson2Present
)
{
defaultCodec
().
addReaderTo
(
result
,
Jackson2JsonDecoder
.
class
,
Jackson2JsonDecoder:
:
new
);
}
}
/**
* Add custom, Object-based readers.
*/
protected
void
addCustomObjectReaders
(
List
<
HttpMessageReader
<?>>
result
)
{
customCodec
().
addObjectReadersTo
(
result
);
}
/**
* Prepare a list of HTTP message writers.
*/
public
List
<
HttpMessageWriter
<?>>
getWriters
()
{
List
<
HttpMessageWriter
<?>>
result
=
new
ArrayList
<>();
addDefaultTypedWriter
(
result
);
addCustomTypedWriter
(
result
);
addDefaultObjectWriters
(
result
);
addCustomObjectWriters
(
result
);
// String + "*/*"
defaultCodec
().
addStringWriterTo
(
result
);
return
result
;
}
/**
* Add built-in, concrete, Java type readers.
*/
protected
void
addDefaultTypedWriter
(
List
<
HttpMessageWriter
<?>>
result
)
{
defaultCodec
().
addWriterTo
(
result
,
ByteArrayEncoder
.
class
,
ByteArrayEncoder:
:
new
);
defaultCodec
().
addWriterTo
(
result
,
ByteBufferEncoder
.
class
,
ByteBufferEncoder:
:
new
);
defaultCodec
().
addWriterTo
(
result
,
DataBufferEncoder
.
class
,
DataBufferEncoder:
:
new
);
defaultCodec
().
addWriterTo
(
result
,
ResourceHttpMessageWriter:
:
new
);
defaultCodec
().
addStringWriterTextPlainOnlyTo
(
result
);
}
/**
* Add custom, concrete, Java type readers.
*/
protected
void
addCustomTypedWriter
(
List
<
HttpMessageWriter
<?>>
result
)
{
customCodec
().
addTypedWritersTo
(
result
);
}
/**
* Add built-in, Object-based readers.
*/
protected
void
addDefaultObjectWriters
(
List
<
HttpMessageWriter
<?>>
result
)
{
if
(
jaxb2Present
)
{
defaultCodec
().
addWriterTo
(
result
,
Jaxb2XmlEncoder
.
class
,
Jaxb2XmlEncoder:
:
new
);
}
if
(
jackson2Present
)
{
defaultCodec
().
addWriterTo
(
result
,
Jackson2JsonEncoder
.
class
,
Jackson2JsonEncoder:
:
new
);
}
}
/**
* Add custom, Object-based readers.
*/
protected
void
addCustomObjectWriters
(
List
<
HttpMessageWriter
<?>>
result
)
{
customCodec
().
addObjectWritersTo
(
result
);
}
/**
* A registry and a factory for built-in HTTP message readers and writers.
*/
public
static
class
DefaultCodecConfigurer
{
private
boolean
suppressed
=
false
;
private
final
Map
<
Class
<?>,
HttpMessageReader
<?>>
readers
=
new
HashMap
<>();
private
final
Map
<
Class
<?>,
HttpMessageWriter
<?>>
writers
=
new
HashMap
<>();
/**
* Override the default Jackson {@code Decoder}.
* @param decoder the decoder to use
*/
public
void
jackson2Decoder
(
Jackson2JsonDecoder
decoder
)
{
this
.
readers
.
put
(
Jackson2JsonDecoder
.
class
,
new
DecoderHttpMessageReader
<>(
decoder
));
}
/**
* Override the default Jackson {@code Encoder} for JSON.
* @param encoder the encoder to use
*/
public
void
jackson2Encoder
(
Jackson2JsonEncoder
encoder
)
{
this
.
writers
.
put
(
Jackson2JsonEncoder
.
class
,
new
EncoderHttpMessageWriter
<>(
encoder
));
}
// Accessors for internal use...
protected
Map
<
Class
<?>,
HttpMessageReader
<?>>
getReaders
()
{
return
this
.
readers
;
}
protected
Map
<
Class
<?>,
HttpMessageWriter
<?>>
getWriters
()
{
return
this
.
writers
;
}
private
void
setSuppressed
(
boolean
suppressed
)
{
this
.
suppressed
=
suppressed
;
}
// Protected methods for building a list of default readers or writers...
protected
<
T
,
D
extends
Decoder
<
T
>>
void
addReaderTo
(
List
<
HttpMessageReader
<?>>
result
,
Class
<
D
>
key
,
Supplier
<
D
>
fallback
)
{
addReaderTo
(
result
,
()
->
findDecoderReader
(
key
,
fallback
));
}
protected
void
addReaderTo
(
List
<
HttpMessageReader
<?>>
result
,
Supplier
<
HttpMessageReader
<?>>
reader
)
{
if
(!
this
.
suppressed
)
{
result
.
add
(
reader
.
get
());
}
}
protected
<
T
,
D
extends
Decoder
<
T
>>
DecoderHttpMessageReader
<?>
findDecoderReader
(
Class
<
D
>
decoderType
,
Supplier
<
D
>
fallback
)
{
DecoderHttpMessageReader
<?>
reader
=
(
DecoderHttpMessageReader
<?>)
this
.
readers
.
get
(
decoderType
);
return
reader
!=
null
?
reader
:
new
DecoderHttpMessageReader
<>(
fallback
.
get
());
}
@SuppressWarnings
(
"unchecked"
)
protected
HttpMessageReader
<?>
findReader
(
Class
<?>
key
,
Supplier
<
HttpMessageReader
<?>>
fallback
)
{
return
this
.
readers
.
containsKey
(
key
)
?
this
.
readers
.
get
(
key
)
:
fallback
.
get
();
}
protected
<
T
,
E
extends
Encoder
<
T
>>
void
addWriterTo
(
List
<
HttpMessageWriter
<?>>
result
,
Class
<
E
>
key
,
Supplier
<
E
>
fallback
)
{
addWriterTo
(
result
,
()
->
findEncoderWriter
(
key
,
fallback
));
}
protected
void
addWriterTo
(
List
<
HttpMessageWriter
<?>>
result
,
Supplier
<
HttpMessageWriter
<?>>
writer
)
{
if
(!
this
.
suppressed
)
{
result
.
add
(
writer
.
get
());
}
}
protected
<
T
,
E
extends
Encoder
<
T
>>
EncoderHttpMessageWriter
<?>
findEncoderWriter
(
Class
<
E
>
encoderType
,
Supplier
<
E
>
fallback
)
{
EncoderHttpMessageWriter
<?>
writer
=
(
EncoderHttpMessageWriter
<?>)
this
.
writers
.
get
(
encoderType
);
return
writer
!=
null
?
writer
:
new
EncoderHttpMessageWriter
<>(
fallback
.
get
());
}
@SuppressWarnings
(
"unchecked"
)
protected
HttpMessageWriter
<?>
findWriter
(
Class
<?>
key
,
Supplier
<
HttpMessageWriter
<?>>
fallback
)
{
return
this
.
writers
.
containsKey
(
key
)
?
this
.
writers
.
get
(
key
)
:
fallback
.
get
();
}
protected
void
addStringReaderTextOnlyTo
(
List
<
HttpMessageReader
<?>>
result
)
{
addReaderTo
(
result
,
()
->
new
DecoderHttpMessageReader
<>(
StringDecoder
.
textPlainOnly
(
true
)));
}
protected
void
addStringReaderTo
(
List
<
HttpMessageReader
<?>>
result
)
{
addReaderTo
(
result
,
()
->
new
DecoderHttpMessageReader
<>(
StringDecoder
.
allMimeTypes
(
true
)));
}
protected
void
addStringWriterTextPlainOnlyTo
(
List
<
HttpMessageWriter
<?>>
result
)
{
addWriterTo
(
result
,
()
->
new
EncoderHttpMessageWriter
<>(
CharSequenceEncoder
.
textPlainOnly
()));
}
protected
void
addStringWriterTo
(
List
<
HttpMessageWriter
<?>>
result
)
{
addWriterTo
(
result
,
()
->
new
EncoderHttpMessageWriter
<>(
CharSequenceEncoder
.
allMimeTypes
()));
}
}
/**
* Registry and container for custom HTTP message readers and writers.
*/
public
static
class
CustomCodecConfigurer
{
private
final
List
<
HttpMessageReader
<?>>
typedReaders
=
new
ArrayList
<>();
private
final
List
<
HttpMessageWriter
<?>>
typedWriters
=
new
ArrayList
<>();
private
final
List
<
HttpMessageReader
<?>>
objectReaders
=
new
ArrayList
<>();
private
final
List
<
HttpMessageWriter
<?>>
objectWriters
=
new
ArrayList
<>();
/**
* Add a custom {@code Decoder} internally wrapped with
* {@link DecoderHttpMessageReader}).
*/
public
void
decoder
(
Decoder
<?>
decoder
)
{
reader
(
new
DecoderHttpMessageReader
<>(
decoder
));
}
/**
* Add a custom {@code Encoder}, internally wrapped with
* {@link EncoderHttpMessageWriter}.
*/
public
void
encoder
(
Encoder
<?>
encoder
)
{
writer
(
new
EncoderHttpMessageWriter
<>(
encoder
));
}
/**
* Add a custom {@link HttpMessageReader}. For readers of type
* {@link DecoderHttpMessageReader} consider using the shortcut
* {@link #decoder(Decoder)} instead.
*/
public
void
reader
(
HttpMessageReader
<?>
reader
)
{
boolean
canReadToObject
=
reader
.
canRead
(
ResolvableType
.
forClass
(
Object
.
class
),
null
);
(
canReadToObject
?
this
.
objectReaders
:
this
.
typedReaders
).
add
(
reader
);
}
/**
* Add a custom {@link HttpMessageWriter}. For readers of type
* {@link EncoderHttpMessageWriter} consider using the shortcut
* {@link #encoder(Encoder)} instead.
*/
public
void
writer
(
HttpMessageWriter
<?>
writer
)
{
boolean
canWriteObject
=
writer
.
canWrite
(
ResolvableType
.
forClass
(
Object
.
class
),
null
);
(
canWriteObject
?
this
.
objectWriters
:
this
.
typedWriters
).
add
(
writer
);
}
// Internal methods for building a list of custom readers or writers...
protected
void
addTypedReadersTo
(
List
<
HttpMessageReader
<?>>
result
)
{
result
.
addAll
(
this
.
typedReaders
);
}
protected
void
addObjectReadersTo
(
List
<
HttpMessageReader
<?>>
result
)
{
result
.
addAll
(
this
.
objectReaders
);
}
protected
void
addTypedWritersTo
(
List
<
HttpMessageWriter
<?>>
result
)
{
result
.
addAll
(
this
.
typedWriters
);
}
protected
void
addObjectWritersTo
(
List
<
HttpMessageWriter
<?>>
result
)
{
result
.
addAll
(
this
.
objectWriters
);
}
}
}
spring-web/src/main/java/org/springframework/http/codec/ServerCodecConfigurer.java
浏览文件 @
dc3851df
...
...
@@ -15,343 +15,78 @@
*/
package
org.springframework.http.codec
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.function.Supplier
;
import
org.springframework.core.ResolvableType
;
import
org.springframework.core.codec.ByteArrayDecoder
;
import
org.springframework.core.codec.ByteArrayEncoder
;
import
org.springframework.core.codec.ByteBufferDecoder
;
import
org.springframework.core.codec.ByteBufferEncoder
;
import
org.springframework.core.codec.CharSequenceEncoder
;
import
org.springframework.core.codec.DataBufferDecoder
;
import
org.springframework.core.codec.DataBufferEncoder
;
import
org.springframework.core.codec.Decoder
;
import
org.springframework.core.codec.Encoder
;
import
org.springframework.core.codec.ResourceDecoder
;
import
org.springframework.core.codec.StringDecoder
;
import
org.springframework.http.codec.json.Jackson2JsonDecoder
;
import
org.springframework.http.codec.json.Jackson2JsonEncoder
;
import
org.springframework.http.codec.xml.Jaxb2XmlDecoder
;
import
org.springframework.http.codec.xml.Jaxb2XmlEncoder
;
import
org.springframework.util.ClassUtils
;
/**
* Helps to configure a list of server-side HTTP message readers and writers
* with support for built-in defaults and options to register additional custom
* readers and writers via {@link #customCodec()}.
*
* <p>The built-in defaults include basic data types such as
* {@link Byte byte[]}, {@link java.nio.ByteBuffer ByteBuffer},
* {@link org.springframework.core.io.buffer.DataBuffer DataBuffer},
* {@link String}, {@link org.springframework.core.io.Resource Resource},
* in addition to JAXB2 and Jackson 2 based on classpath detection, as well as
* support for Server-Sent Events. There are options to {@link #defaultCodec()
* override} some of the defaults or to have them
* <p>The built-in defaults include basic data types such as various byte
* representations, resources, strings, forms, but also others like JAXB2 and
* Jackson 2 based on classpath detection. There are options to
* {@link #defaultCodec() override} some of the defaults or to have them
* {@link #registerDefaults(boolean) turned off} completely.
*
* @author Rossen Stoyanchev
* @since 5.0
*/
public
class
ServerCodecConfigurer
{
public
class
ServerCodecConfigurer
extends
AbstractCodecConfigurer
{
private
static
final
boolean
jackson2Present
=
ClassUtils
.
isPresent
(
"com.fasterxml.jackson.databind.ObjectMapper"
,
ServerCodecConfigurer
.
class
.
getClassLoader
())
&&
ClassUtils
.
isPresent
(
"com.fasterxml.jackson.core.JsonGenerator"
,
ServerCodecConfigurer
.
class
.
getClassLoader
());
private
static
final
boolean
jaxb2Present
=
ClassUtils
.
isPresent
(
"javax.xml.bind.Binder"
,
ServerCodecConfigurer
.
class
.
getClassLoader
());
private
final
DefaultCodecConfigurer
defaultCodecs
=
new
DefaultCodecConfigurer
();
private
final
CustomCodecConfigurer
customCodecs
=
new
CustomCodecConfigurer
();
/**
* Provide overrides for built-in HTTP message readers and writers.
*/
public
DefaultCodecConfigurer
defaultCodec
()
{
return
this
.
defaultCodecs
;
public
ServerCodecConfigurer
()
{
super
(
new
ServerDefaultCodecConfigurer
());
}
/**
* Whether to make default HTTP message reader and writer registrations.
* <p>By default this is set to {@code "true"}.
*/
public
void
registerDefaults
(
boolean
register
)
{
this
.
defaultCodec
().
setSuppressed
(!
register
);
}
/**
* Register a custom encoder or decoder.
*/
public
CustomCodecConfigurer
customCodec
()
{
return
this
.
customCodecs
;
@Override
public
ServerDefaultCodecConfigurer
defaultCodec
()
{
return
(
ServerDefaultCodecConfigurer
)
super
.
defaultCodec
();
}
/**
* Prepare a list of HTTP message readers.
*/
public
List
<
HttpMessageReader
<?>>
getReaders
()
{
// Built-in, concrete Java type readers
List
<
HttpMessageReader
<?>>
result
=
new
ArrayList
<>();
this
.
defaultCodecs
.
addReaderTo
(
result
,
ByteArrayDecoder
.
class
,
ByteArrayDecoder:
:
new
);
this
.
defaultCodecs
.
addReaderTo
(
result
,
ByteBufferDecoder
.
class
,
ByteBufferDecoder:
:
new
);
this
.
defaultCodecs
.
addReaderTo
(
result
,
DataBufferDecoder
.
class
,
DataBufferDecoder:
:
new
);
this
.
defaultCodecs
.
addReaderTo
(
result
,
ResourceDecoder
.
class
,
ResourceDecoder:
:
new
);
this
.
defaultCodecs
.
addStringReaderTextOnlyTo
(
result
);
this
.
defaultCodecs
.
addReaderTo
(
result
,
FormHttpMessageReader:
:
new
);
// Custom, concrete Java type readers
this
.
customCodecs
.
addTypedReadersTo
(
result
);
// Built-in, Object-based readers
if
(
jaxb2Present
)
{
this
.
defaultCodecs
.
addReaderTo
(
result
,
Jaxb2XmlDecoder
.
class
,
Jaxb2XmlDecoder:
:
new
);
}
if
(
jackson2Present
)
{
this
.
defaultCodecs
.
addReaderTo
(
result
,
Jackson2JsonDecoder
.
class
,
Jackson2JsonDecoder:
:
new
);
}
// Custom, Object-based readers
this
.
customCodecs
.
addObjectReadersTo
(
result
);
// Potentially overlapping Java types + "*/*"
this
.
defaultCodecs
.
addStringReaderTo
(
result
);
return
result
;
protected
void
addDefaultTypedReaders
(
List
<
HttpMessageReader
<?>>
result
)
{
super
.
addDefaultTypedReaders
(
result
);
defaultCodec
().
addReaderTo
(
result
,
FormHttpMessageReader:
:
new
);
}
/**
* Prepare a list of HTTP message writers.
*/
public
List
<
HttpMessageWriter
<?>>
getWriters
()
{
// Built-in, concrete Java type readers
List
<
HttpMessageWriter
<?>>
result
=
new
ArrayList
<>();
this
.
defaultCodecs
.
addWriterTo
(
result
,
ByteArrayEncoder
.
class
,
ByteArrayEncoder:
:
new
);
this
.
defaultCodecs
.
addWriterTo
(
result
,
ByteBufferEncoder
.
class
,
ByteBufferEncoder:
:
new
);
this
.
defaultCodecs
.
addWriterTo
(
result
,
DataBufferEncoder
.
class
,
DataBufferEncoder:
:
new
);
this
.
defaultCodecs
.
addWriterTo
(
result
,
ResourceHttpMessageWriter:
:
new
);
this
.
defaultCodecs
.
addStringWriterTextPlainOnlyTo
(
result
);
// Custom, concrete Java type readers
this
.
customCodecs
.
addTypedWritersTo
(
result
);
// Built-in, Object-based readers
if
(
jaxb2Present
)
{
this
.
defaultCodecs
.
addWriterTo
(
result
,
Jaxb2XmlEncoder
.
class
,
Jaxb2XmlEncoder:
:
new
);
}
if
(
jackson2Present
)
{
this
.
defaultCodecs
.
addWriterTo
(
result
,
Jackson2JsonEncoder
.
class
,
Jackson2JsonEncoder:
:
new
);
}
this
.
defaultCodecs
.
addSseWriterTo
(
result
);
// Custom, Object-based readers
this
.
customCodecs
.
addObjectWritersTo
(
result
);
// Potentially overlapping Java types + "*/*"
this
.
defaultCodecs
.
addStringWriterTo
(
result
);
return
result
;
protected
void
addDefaultObjectWriters
(
List
<
HttpMessageWriter
<?>>
result
)
{
super
.
addDefaultObjectWriters
(
result
);
defaultCodec
().
addServerSentEventWriterTo
(
result
);
}
/**
*
A registry and a factory for built-in HTTP message readers and writer
s.
*
Extension of {@code DefaultCodecConfigurer} with extra server option
s.
*/
public
static
class
DefaultCodecConfigurer
{
private
boolean
suppressed
=
false
;
private
final
Map
<
Class
<?>,
HttpMessageReader
<?>>
readers
=
new
HashMap
<>();
private
final
Map
<
Class
<?>,
HttpMessageWriter
<?>>
writers
=
new
HashMap
<>();
/**
* Override the default Jackson {@code Decoder}.
* @param decoder the decoder to use
*/
public
void
jackson2Decoder
(
Jackson2JsonDecoder
decoder
)
{
this
.
readers
.
put
(
Jackson2JsonDecoder
.
class
,
new
DecoderHttpMessageReader
<>(
decoder
));
}
/**
* Override the default Jackson {@code Encoder} for JSON. Also used for
* SSE unless further overridden via {@link #sse(Encoder)}.
* @param encoder the encoder to use
*/
public
void
jackson2Encoder
(
Jackson2JsonEncoder
encoder
)
{
this
.
writers
.
put
(
Jackson2JsonEncoder
.
class
,
new
EncoderHttpMessageWriter
<>(
encoder
));
}
public
static
class
ServerDefaultCodecConfigurer
extends
DefaultCodecConfigurer
{
/**
* Configure the {@code Encoder} to use for Server-Sent Events.
* <p>By default the {@link #jackson2Encoder} override is used for SSE.
* @param encoder the encoder to use
*/
public
void
s
se
(
Encoder
<?>
encoder
)
{
public
void
s
erverSentEventEncoder
(
Encoder
<?>
encoder
)
{
HttpMessageWriter
<?>
writer
=
new
ServerSentEventHttpMessageWriter
(
encoder
);
this
.
writers
.
put
(
ServerSentEventHttpMessageWriter
.
class
,
writer
);
getWriters
()
.
put
(
ServerSentEventHttpMessageWriter
.
class
,
writer
);
}
// Internal methods for building a list of default readers or writers...
private
void
setSuppressed
(
boolean
suppressed
)
{
this
.
suppressed
=
suppressed
;
}
private
<
T
,
D
extends
Decoder
<
T
>>
void
addReaderTo
(
List
<
HttpMessageReader
<?>>
result
,
Class
<
D
>
key
,
Supplier
<
D
>
fallback
)
{
addReaderTo
(
result
,
()
->
findReader
(
key
,
fallback
));
}
private
void
addReaderTo
(
List
<
HttpMessageReader
<?>>
result
,
Supplier
<
HttpMessageReader
<?>>
reader
)
{
if
(!
this
.
suppressed
)
{
result
.
add
(
reader
.
get
());
}
}
private
<
T
,
D
extends
Decoder
<
T
>>
DecoderHttpMessageReader
<?>
findReader
(
Class
<
D
>
key
,
Supplier
<
D
>
fallback
)
{
DecoderHttpMessageReader
<?>
reader
=
(
DecoderHttpMessageReader
<?>)
this
.
readers
.
get
(
key
);
return
reader
!=
null
?
reader
:
new
DecoderHttpMessageReader
<>(
fallback
.
get
());
}
private
<
T
,
E
extends
Encoder
<
T
>>
void
addWriterTo
(
List
<
HttpMessageWriter
<?>>
result
,
Class
<
E
>
key
,
Supplier
<
E
>
fallback
)
{
addWriterTo
(
result
,
()
->
findWriter
(
key
,
fallback
));
}
private
void
addWriterTo
(
List
<
HttpMessageWriter
<?>>
result
,
Supplier
<
HttpMessageWriter
<?>>
writer
)
{
if
(!
this
.
suppressed
)
{
result
.
add
(
writer
.
get
());
}
}
private
<
T
,
E
extends
Encoder
<
T
>>
EncoderHttpMessageWriter
<?>
findWriter
(
Class
<
E
>
key
,
Supplier
<
E
>
fallback
)
{
EncoderHttpMessageWriter
<?>
writer
=
(
EncoderHttpMessageWriter
<?>)
this
.
writers
.
get
(
key
);
return
writer
!=
null
?
writer
:
new
EncoderHttpMessageWriter
<>(
fallback
.
get
());
}
private
void
addStringReaderTextOnlyTo
(
List
<
HttpMessageReader
<?>>
result
)
{
addReaderTo
(
result
,
()
->
new
DecoderHttpMessageReader
<>(
StringDecoder
.
textPlainOnly
(
true
)));
}
private
void
addStringReaderTo
(
List
<
HttpMessageReader
<?>>
result
)
{
addReaderTo
(
result
,
()
->
new
DecoderHttpMessageReader
<>(
StringDecoder
.
allMimeTypes
(
true
)));
}
private
void
addStringWriterTextPlainOnlyTo
(
List
<
HttpMessageWriter
<?>>
result
)
{
addWriterTo
(
result
,
()
->
new
EncoderHttpMessageWriter
<>(
CharSequenceEncoder
.
textPlainOnly
()));
}
private
void
addStringWriterTo
(
List
<
HttpMessageWriter
<?>>
result
)
{
addWriterTo
(
result
,
()
->
new
EncoderHttpMessageWriter
<>(
CharSequenceEncoder
.
allMimeTypes
()));
}
private
void
addSseWriterTo
(
List
<
HttpMessageWriter
<?>>
result
)
{
addWriterTo
(
result
,
()
->
{
HttpMessageWriter
<?>
writer
=
this
.
writers
.
get
(
ServerSentEventHttpMessageWriter
.
class
);
if
(
writer
!=
null
)
{
return
writer
;
}
private
void
addServerSentEventWriterTo
(
List
<
HttpMessageWriter
<?>>
result
)
{
addWriterTo
(
result
,
()
->
findWriter
(
ServerSentEventHttpMessageWriter
.
class
,
()
->
{
Encoder
<?>
encoder
=
null
;
if
(
jackson2Present
)
{
return
new
ServerSentEventHttpMessage
Writer
(
findWriter
(
Jackson2JsonEncoder
.
class
,
Jackson2JsonEncoder:
:
new
).
getEncoder
()
);
encoder
=
findEncoder
Writer
(
Jackson2JsonEncoder
.
class
,
Jackson2JsonEncoder:
:
new
).
getEncoder
(
);
}
return
new
ServerSentEventHttpMessageWriter
();
});
}
}
/**
* Registry and container for custom HTTP message readers and writers.
*/
public
static
class
CustomCodecConfigurer
{
private
final
List
<
HttpMessageReader
<?>>
typedReaders
=
new
ArrayList
<>();
private
final
List
<
HttpMessageWriter
<?>>
typedWriters
=
new
ArrayList
<>();
private
final
List
<
HttpMessageReader
<?>>
objectReaders
=
new
ArrayList
<>();
private
final
List
<
HttpMessageWriter
<?>>
objectWriters
=
new
ArrayList
<>();
/**
* Add a custom {@code Decoder} internally wrapped with
* {@link DecoderHttpMessageReader}).
*/
public
void
decoder
(
Decoder
<?>
decoder
)
{
reader
(
new
DecoderHttpMessageReader
<>(
decoder
));
}
/**
* Add a custom {@code Encoder}, internally wrapped with
* {@link EncoderHttpMessageWriter}.
*/
public
void
encoder
(
Encoder
<?>
encoder
)
{
writer
(
new
EncoderHttpMessageWriter
<>(
encoder
));
}
/**
* Add a custom {@link HttpMessageReader}. For readers of type
* {@link DecoderHttpMessageReader} consider using the shortcut
* {@link #decoder(Decoder)} instead.
*/
public
void
reader
(
HttpMessageReader
<?>
reader
)
{
boolean
canReadToObject
=
reader
.
canRead
(
ResolvableType
.
forClass
(
Object
.
class
),
null
);
(
canReadToObject
?
this
.
objectReaders
:
this
.
typedReaders
).
add
(
reader
);
}
/**
* Add a custom {@link HttpMessageWriter}. For readers of type
* {@link EncoderHttpMessageWriter} consider using the shortcut
* {@link #encoder(Encoder)} instead.
*/
public
void
writer
(
HttpMessageWriter
<?>
writer
)
{
boolean
canWriteObject
=
writer
.
canWrite
(
ResolvableType
.
forClass
(
Object
.
class
),
null
);
(
canWriteObject
?
this
.
objectWriters
:
this
.
typedWriters
).
add
(
writer
);
}
// Internal methods for building a list of custom readers or writers...
private
void
addTypedReadersTo
(
List
<
HttpMessageReader
<?>>
result
)
{
result
.
addAll
(
this
.
typedReaders
);
}
private
void
addObjectReadersTo
(
List
<
HttpMessageReader
<?>>
result
)
{
result
.
addAll
(
this
.
objectReaders
);
}
private
void
addTypedWritersTo
(
List
<
HttpMessageWriter
<?>>
result
)
{
result
.
addAll
(
this
.
typedWriters
);
}
private
void
addObjectWritersTo
(
List
<
HttpMessageWriter
<?>>
result
)
{
result
.
addAll
(
this
.
objectWriters
);
return
new
ServerSentEventHttpMessageWriter
(
encoder
);
}));
}
}
...
...
spring-web/src/test/java/org/springframework/http/codec/CodecConfigurerTests.java
0 → 100644
浏览文件 @
dc3851df
/*
* Copyright 2002-2017 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.http.codec
;
import
java.util.List
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
org.junit.Test
;
import
org.springframework.core.ResolvableType
;
import
org.springframework.core.codec.ByteArrayDecoder
;
import
org.springframework.core.codec.ByteArrayEncoder
;
import
org.springframework.core.codec.ByteBufferDecoder
;
import
org.springframework.core.codec.ByteBufferEncoder
;
import
org.springframework.core.codec.CharSequenceEncoder
;
import
org.springframework.core.codec.DataBufferDecoder
;
import
org.springframework.core.codec.DataBufferEncoder
;
import
org.springframework.core.codec.Decoder
;
import
org.springframework.core.codec.Encoder
;
import
org.springframework.core.codec.ResourceDecoder
;
import
org.springframework.core.codec.StringDecoder
;
import
org.springframework.http.MediaType
;
import
org.springframework.http.codec.json.Jackson2JsonDecoder
;
import
org.springframework.http.codec.json.Jackson2JsonEncoder
;
import
org.springframework.http.codec.xml.Jaxb2XmlDecoder
;
import
org.springframework.http.codec.xml.Jaxb2XmlEncoder
;
import
org.springframework.util.MimeTypeUtils
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertSame
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
when
;
import
static
org
.
springframework
.
core
.
ResolvableType
.
forClass
;
/**
* Unit tests for {@link ServerCodecConfigurer}.
* @author Rossen Stoyanchev
*/
public
class
CodecConfigurerTests
{
private
final
TestCodecConfigurer
configurer
=
new
TestCodecConfigurer
();
private
final
AtomicInteger
index
=
new
AtomicInteger
(
0
);
@Test
public
void
defaultReaders
()
throws
Exception
{
List
<
HttpMessageReader
<?>>
readers
=
this
.
configurer
.
getReaders
();
assertEquals
(
8
,
readers
.
size
());
assertEquals
(
ByteArrayDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
assertEquals
(
ByteBufferDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
assertEquals
(
DataBufferDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
assertEquals
(
ResourceDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
assertStringDecoder
(
getNextDecoder
(
readers
),
true
);
assertEquals
(
Jaxb2XmlDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
assertEquals
(
Jackson2JsonDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
assertStringDecoder
(
getNextDecoder
(
readers
),
false
);
}
@Test
public
void
defaultWriters
()
throws
Exception
{
List
<
HttpMessageWriter
<?>>
writers
=
this
.
configurer
.
getWriters
();
assertEquals
(
8
,
writers
.
size
());
assertEquals
(
ByteArrayEncoder
.
class
,
getNextEncoder
(
writers
).
getClass
());
assertEquals
(
ByteBufferEncoder
.
class
,
getNextEncoder
(
writers
).
getClass
());
assertEquals
(
DataBufferEncoder
.
class
,
getNextEncoder
(
writers
).
getClass
());
assertEquals
(
ResourceHttpMessageWriter
.
class
,
writers
.
get
(
index
.
getAndIncrement
()).
getClass
());
assertStringEncoder
(
getNextEncoder
(
writers
),
true
);
assertEquals
(
Jaxb2XmlEncoder
.
class
,
getNextEncoder
(
writers
).
getClass
());
assertEquals
(
Jackson2JsonEncoder
.
class
,
getNextEncoder
(
writers
).
getClass
());
assertStringEncoder
(
getNextEncoder
(
writers
),
false
);
}
@Test
public
void
defaultAndCustomReaders
()
throws
Exception
{
Decoder
<?>
customDecoder1
=
mock
(
Decoder
.
class
);
Decoder
<?>
customDecoder2
=
mock
(
Decoder
.
class
);
when
(
customDecoder1
.
canDecode
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
false
);
when
(
customDecoder2
.
canDecode
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
true
);
HttpMessageReader
<?>
customReader1
=
mock
(
HttpMessageReader
.
class
);
HttpMessageReader
<?>
customReader2
=
mock
(
HttpMessageReader
.
class
);
when
(
customReader1
.
canRead
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
false
);
when
(
customReader2
.
canRead
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
true
);
this
.
configurer
.
customCodec
().
decoder
(
customDecoder1
);
this
.
configurer
.
customCodec
().
decoder
(
customDecoder2
);
this
.
configurer
.
customCodec
().
reader
(
customReader1
);
this
.
configurer
.
customCodec
().
reader
(
customReader2
);
List
<
HttpMessageReader
<?>>
readers
=
this
.
configurer
.
getReaders
();
assertEquals
(
12
,
readers
.
size
());
assertEquals
(
ByteArrayDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
assertEquals
(
ByteBufferDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
assertEquals
(
DataBufferDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
assertEquals
(
ResourceDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
assertEquals
(
StringDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
assertSame
(
customDecoder1
,
getNextDecoder
(
readers
));
assertSame
(
customReader1
,
readers
.
get
(
this
.
index
.
getAndIncrement
()));
assertEquals
(
Jaxb2XmlDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
assertEquals
(
Jackson2JsonDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
assertSame
(
customDecoder2
,
getNextDecoder
(
readers
));
assertSame
(
customReader2
,
readers
.
get
(
this
.
index
.
getAndIncrement
()));
assertEquals
(
StringDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
}
@Test
public
void
defaultAndCustomWriters
()
throws
Exception
{
Encoder
<?>
customEncoder1
=
mock
(
Encoder
.
class
);
Encoder
<?>
customEncoder2
=
mock
(
Encoder
.
class
);
when
(
customEncoder1
.
canEncode
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
false
);
when
(
customEncoder2
.
canEncode
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
true
);
HttpMessageWriter
<?>
customWriter1
=
mock
(
HttpMessageWriter
.
class
);
HttpMessageWriter
<?>
customWriter2
=
mock
(
HttpMessageWriter
.
class
);
when
(
customWriter1
.
canWrite
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
false
);
when
(
customWriter2
.
canWrite
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
true
);
this
.
configurer
.
customCodec
().
encoder
(
customEncoder1
);
this
.
configurer
.
customCodec
().
encoder
(
customEncoder2
);
this
.
configurer
.
customCodec
().
writer
(
customWriter1
);
this
.
configurer
.
customCodec
().
writer
(
customWriter2
);
List
<
HttpMessageWriter
<?>>
writers
=
this
.
configurer
.
getWriters
();
assertEquals
(
12
,
writers
.
size
());
assertEquals
(
ByteArrayEncoder
.
class
,
getNextEncoder
(
writers
).
getClass
());
assertEquals
(
ByteBufferEncoder
.
class
,
getNextEncoder
(
writers
).
getClass
());
assertEquals
(
DataBufferEncoder
.
class
,
getNextEncoder
(
writers
).
getClass
());
assertEquals
(
ResourceHttpMessageWriter
.
class
,
writers
.
get
(
index
.
getAndIncrement
()).
getClass
());
assertEquals
(
CharSequenceEncoder
.
class
,
getNextEncoder
(
writers
).
getClass
());
assertSame
(
customEncoder1
,
getNextEncoder
(
writers
));
assertSame
(
customWriter1
,
writers
.
get
(
this
.
index
.
getAndIncrement
()));
assertEquals
(
Jaxb2XmlEncoder
.
class
,
getNextEncoder
(
writers
).
getClass
());
assertEquals
(
Jackson2JsonEncoder
.
class
,
getNextEncoder
(
writers
).
getClass
());
assertSame
(
customEncoder2
,
getNextEncoder
(
writers
));
assertSame
(
customWriter2
,
writers
.
get
(
this
.
index
.
getAndIncrement
()));
assertEquals
(
CharSequenceEncoder
.
class
,
getNextEncoder
(
writers
).
getClass
());
}
@Test
public
void
defaultsOffCustomReaders
()
throws
Exception
{
Decoder
<?>
customDecoder1
=
mock
(
Decoder
.
class
);
Decoder
<?>
customDecoder2
=
mock
(
Decoder
.
class
);
when
(
customDecoder1
.
canDecode
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
false
);
when
(
customDecoder2
.
canDecode
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
true
);
HttpMessageReader
<?>
customReader1
=
mock
(
HttpMessageReader
.
class
);
HttpMessageReader
<?>
customReader2
=
mock
(
HttpMessageReader
.
class
);
when
(
customReader1
.
canRead
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
false
);
when
(
customReader2
.
canRead
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
true
);
this
.
configurer
.
customCodec
().
decoder
(
customDecoder1
);
this
.
configurer
.
customCodec
().
decoder
(
customDecoder2
);
this
.
configurer
.
customCodec
().
reader
(
customReader1
);
this
.
configurer
.
customCodec
().
reader
(
customReader2
);
this
.
configurer
.
registerDefaults
(
false
);
List
<
HttpMessageReader
<?>>
readers
=
this
.
configurer
.
getReaders
();
assertEquals
(
4
,
readers
.
size
());
assertSame
(
customDecoder1
,
getNextDecoder
(
readers
));
assertSame
(
customReader1
,
readers
.
get
(
this
.
index
.
getAndIncrement
()));
assertSame
(
customDecoder2
,
getNextDecoder
(
readers
));
assertSame
(
customReader2
,
readers
.
get
(
this
.
index
.
getAndIncrement
()));
}
@Test
public
void
defaultsOffWithCustomWriters
()
throws
Exception
{
Encoder
<?>
customEncoder1
=
mock
(
Encoder
.
class
);
Encoder
<?>
customEncoder2
=
mock
(
Encoder
.
class
);
when
(
customEncoder1
.
canEncode
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
false
);
when
(
customEncoder2
.
canEncode
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
true
);
HttpMessageWriter
<?>
customWriter1
=
mock
(
HttpMessageWriter
.
class
);
HttpMessageWriter
<?>
customWriter2
=
mock
(
HttpMessageWriter
.
class
);
when
(
customWriter1
.
canWrite
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
false
);
when
(
customWriter2
.
canWrite
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
true
);
this
.
configurer
.
customCodec
().
encoder
(
customEncoder1
);
this
.
configurer
.
customCodec
().
encoder
(
customEncoder2
);
this
.
configurer
.
customCodec
().
writer
(
customWriter1
);
this
.
configurer
.
customCodec
().
writer
(
customWriter2
);
this
.
configurer
.
registerDefaults
(
false
);
List
<
HttpMessageWriter
<?>>
writers
=
this
.
configurer
.
getWriters
();
assertEquals
(
4
,
writers
.
size
());
assertSame
(
customEncoder1
,
getNextEncoder
(
writers
));
assertSame
(
customWriter1
,
writers
.
get
(
this
.
index
.
getAndIncrement
()));
assertSame
(
customEncoder2
,
getNextEncoder
(
writers
));
assertSame
(
customWriter2
,
writers
.
get
(
this
.
index
.
getAndIncrement
()));
}
@Test
public
void
jackson2DecoderOverride
()
throws
Exception
{
Jackson2JsonDecoder
decoder
=
new
Jackson2JsonDecoder
();
this
.
configurer
.
defaultCodec
().
jackson2Decoder
(
decoder
);
assertSame
(
decoder
,
this
.
configurer
.
getReaders
().
stream
()
.
filter
(
writer
->
writer
instanceof
DecoderHttpMessageReader
)
.
map
(
writer
->
((
DecoderHttpMessageReader
<?>)
writer
).
getDecoder
())
.
filter
(
e
->
Jackson2JsonDecoder
.
class
.
equals
(
e
.
getClass
()))
.
findFirst
()
.
filter
(
e
->
e
==
decoder
).
orElse
(
null
));
}
@Test
public
void
jackson2EncoderOverride
()
throws
Exception
{
Jackson2JsonEncoder
encoder
=
new
Jackson2JsonEncoder
();
this
.
configurer
.
defaultCodec
().
jackson2Encoder
(
encoder
);
assertSame
(
encoder
,
this
.
configurer
.
getWriters
().
stream
()
.
filter
(
writer
->
writer
instanceof
EncoderHttpMessageWriter
)
.
map
(
writer
->
((
EncoderHttpMessageWriter
<?>)
writer
).
getEncoder
())
.
filter
(
e
->
Jackson2JsonEncoder
.
class
.
equals
(
e
.
getClass
()))
.
findFirst
()
.
filter
(
e
->
e
==
encoder
).
orElse
(
null
));
}
private
Decoder
<?>
getNextDecoder
(
List
<
HttpMessageReader
<?>>
readers
)
{
HttpMessageReader
<?>
reader
=
readers
.
get
(
this
.
index
.
getAndIncrement
());
assertEquals
(
DecoderHttpMessageReader
.
class
,
reader
.
getClass
());
return
((
DecoderHttpMessageReader
)
reader
).
getDecoder
();
}
private
Encoder
<?>
getNextEncoder
(
List
<
HttpMessageWriter
<?>>
writers
)
{
HttpMessageWriter
<?>
writer
=
writers
.
get
(
this
.
index
.
getAndIncrement
());
assertEquals
(
EncoderHttpMessageWriter
.
class
,
writer
.
getClass
());
return
((
EncoderHttpMessageWriter
)
writer
).
getEncoder
();
}
private
void
assertStringDecoder
(
Decoder
<?>
decoder
,
boolean
textOnly
)
{
assertEquals
(
StringDecoder
.
class
,
decoder
.
getClass
());
assertTrue
(
decoder
.
canDecode
(
forClass
(
String
.
class
),
MimeTypeUtils
.
TEXT_PLAIN
));
assertEquals
(!
textOnly
,
decoder
.
canDecode
(
forClass
(
String
.
class
),
MediaType
.
TEXT_EVENT_STREAM
));
}
private
void
assertStringEncoder
(
Encoder
<?>
encoder
,
boolean
textOnly
)
{
assertEquals
(
CharSequenceEncoder
.
class
,
encoder
.
getClass
());
assertTrue
(
encoder
.
canEncode
(
forClass
(
String
.
class
),
MimeTypeUtils
.
TEXT_PLAIN
));
assertEquals
(!
textOnly
,
encoder
.
canEncode
(
forClass
(
String
.
class
),
MediaType
.
TEXT_EVENT_STREAM
));
}
private
static
class
TestCodecConfigurer
extends
AbstractCodecConfigurer
{
private
TestCodecConfigurer
()
{
super
(
new
DefaultCodecConfigurer
());
}
}
}
spring-web/src/test/java/org/springframework/http/codec/ServerCodecConfigurerTests.java
浏览文件 @
dc3851df
...
...
@@ -20,7 +20,6 @@ import java.util.concurrent.atomic.AtomicInteger;
import
org.junit.Test
;
import
org.springframework.core.ResolvableType
;
import
org.springframework.core.codec.ByteArrayDecoder
;
import
org.springframework.core.codec.ByteArrayEncoder
;
import
org.springframework.core.codec.ByteBufferDecoder
;
...
...
@@ -43,8 +42,6 @@ import static org.junit.Assert.assertEquals;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
import
static
org
.
junit
.
Assert
.
assertSame
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
when
;
import
static
org
.
springframework
.
core
.
ResolvableType
.
forClass
;
/**
...
...
@@ -88,175 +85,12 @@ public class ServerCodecConfigurerTests {
assertStringEncoder
(
getNextEncoder
(
writers
),
false
);
}
@Test
public
void
defaultAndCustomReaders
()
throws
Exception
{
Decoder
<?>
customDecoder1
=
mock
(
Decoder
.
class
);
Decoder
<?>
customDecoder2
=
mock
(
Decoder
.
class
);
when
(
customDecoder1
.
canDecode
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
false
);
when
(
customDecoder2
.
canDecode
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
true
);
HttpMessageReader
<?>
customReader1
=
mock
(
HttpMessageReader
.
class
);
HttpMessageReader
<?>
customReader2
=
mock
(
HttpMessageReader
.
class
);
when
(
customReader1
.
canRead
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
false
);
when
(
customReader2
.
canRead
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
true
);
this
.
configurer
.
customCodec
().
decoder
(
customDecoder1
);
this
.
configurer
.
customCodec
().
decoder
(
customDecoder2
);
this
.
configurer
.
customCodec
().
reader
(
customReader1
);
this
.
configurer
.
customCodec
().
reader
(
customReader2
);
List
<
HttpMessageReader
<?>>
readers
=
this
.
configurer
.
getReaders
();
assertEquals
(
13
,
readers
.
size
());
assertEquals
(
ByteArrayDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
assertEquals
(
ByteBufferDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
assertEquals
(
DataBufferDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
assertEquals
(
ResourceDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
assertEquals
(
StringDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
assertEquals
(
FormHttpMessageReader
.
class
,
readers
.
get
(
this
.
index
.
getAndIncrement
()).
getClass
());
assertSame
(
customDecoder1
,
getNextDecoder
(
readers
));
assertSame
(
customReader1
,
readers
.
get
(
this
.
index
.
getAndIncrement
()));
assertEquals
(
Jaxb2XmlDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
assertEquals
(
Jackson2JsonDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
assertSame
(
customDecoder2
,
getNextDecoder
(
readers
));
assertSame
(
customReader2
,
readers
.
get
(
this
.
index
.
getAndIncrement
()));
assertEquals
(
StringDecoder
.
class
,
getNextDecoder
(
readers
).
getClass
());
}
@Test
public
void
defaultAndCustomWriters
()
throws
Exception
{
Encoder
<?>
customEncoder1
=
mock
(
Encoder
.
class
);
Encoder
<?>
customEncoder2
=
mock
(
Encoder
.
class
);
when
(
customEncoder1
.
canEncode
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
false
);
when
(
customEncoder2
.
canEncode
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
true
);
HttpMessageWriter
<?>
customWriter1
=
mock
(
HttpMessageWriter
.
class
);
HttpMessageWriter
<?>
customWriter2
=
mock
(
HttpMessageWriter
.
class
);
when
(
customWriter1
.
canWrite
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
false
);
when
(
customWriter2
.
canWrite
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
true
);
this
.
configurer
.
customCodec
().
encoder
(
customEncoder1
);
this
.
configurer
.
customCodec
().
encoder
(
customEncoder2
);
this
.
configurer
.
customCodec
().
writer
(
customWriter1
);
this
.
configurer
.
customCodec
().
writer
(
customWriter2
);
List
<
HttpMessageWriter
<?>>
writers
=
this
.
configurer
.
getWriters
();
assertEquals
(
13
,
writers
.
size
());
assertEquals
(
ByteArrayEncoder
.
class
,
getNextEncoder
(
writers
).
getClass
());
assertEquals
(
ByteBufferEncoder
.
class
,
getNextEncoder
(
writers
).
getClass
());
assertEquals
(
DataBufferEncoder
.
class
,
getNextEncoder
(
writers
).
getClass
());
assertEquals
(
ResourceHttpMessageWriter
.
class
,
writers
.
get
(
index
.
getAndIncrement
()).
getClass
());
assertEquals
(
CharSequenceEncoder
.
class
,
getNextEncoder
(
writers
).
getClass
());
assertSame
(
customEncoder1
,
getNextEncoder
(
writers
));
assertSame
(
customWriter1
,
writers
.
get
(
this
.
index
.
getAndIncrement
()));
assertEquals
(
Jaxb2XmlEncoder
.
class
,
getNextEncoder
(
writers
).
getClass
());
assertEquals
(
Jackson2JsonEncoder
.
class
,
getNextEncoder
(
writers
).
getClass
());
assertEquals
(
ServerSentEventHttpMessageWriter
.
class
,
writers
.
get
(
this
.
index
.
getAndIncrement
()).
getClass
());
assertSame
(
customEncoder2
,
getNextEncoder
(
writers
));
assertSame
(
customWriter2
,
writers
.
get
(
this
.
index
.
getAndIncrement
()));
assertEquals
(
CharSequenceEncoder
.
class
,
getNextEncoder
(
writers
).
getClass
());
}
@Test
public
void
defaultsOffCustomReaders
()
throws
Exception
{
Decoder
<?>
customDecoder1
=
mock
(
Decoder
.
class
);
Decoder
<?>
customDecoder2
=
mock
(
Decoder
.
class
);
when
(
customDecoder1
.
canDecode
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
false
);
when
(
customDecoder2
.
canDecode
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
true
);
HttpMessageReader
<?>
customReader1
=
mock
(
HttpMessageReader
.
class
);
HttpMessageReader
<?>
customReader2
=
mock
(
HttpMessageReader
.
class
);
when
(
customReader1
.
canRead
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
false
);
when
(
customReader2
.
canRead
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
true
);
this
.
configurer
.
customCodec
().
decoder
(
customDecoder1
);
this
.
configurer
.
customCodec
().
decoder
(
customDecoder2
);
this
.
configurer
.
customCodec
().
reader
(
customReader1
);
this
.
configurer
.
customCodec
().
reader
(
customReader2
);
this
.
configurer
.
registerDefaults
(
false
);
List
<
HttpMessageReader
<?>>
readers
=
this
.
configurer
.
getReaders
();
assertEquals
(
4
,
readers
.
size
());
assertSame
(
customDecoder1
,
getNextDecoder
(
readers
));
assertSame
(
customReader1
,
readers
.
get
(
this
.
index
.
getAndIncrement
()));
assertSame
(
customDecoder2
,
getNextDecoder
(
readers
));
assertSame
(
customReader2
,
readers
.
get
(
this
.
index
.
getAndIncrement
()));
}
@Test
public
void
defaultsOffWithCustomWriters
()
throws
Exception
{
Encoder
<?>
customEncoder1
=
mock
(
Encoder
.
class
);
Encoder
<?>
customEncoder2
=
mock
(
Encoder
.
class
);
when
(
customEncoder1
.
canEncode
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
false
);
when
(
customEncoder2
.
canEncode
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
true
);
HttpMessageWriter
<?>
customWriter1
=
mock
(
HttpMessageWriter
.
class
);
HttpMessageWriter
<?>
customWriter2
=
mock
(
HttpMessageWriter
.
class
);
when
(
customWriter1
.
canWrite
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
false
);
when
(
customWriter2
.
canWrite
(
ResolvableType
.
forClass
(
Object
.
class
),
null
)).
thenReturn
(
true
);
this
.
configurer
.
customCodec
().
encoder
(
customEncoder1
);
this
.
configurer
.
customCodec
().
encoder
(
customEncoder2
);
this
.
configurer
.
customCodec
().
writer
(
customWriter1
);
this
.
configurer
.
customCodec
().
writer
(
customWriter2
);
this
.
configurer
.
registerDefaults
(
false
);
List
<
HttpMessageWriter
<?>>
writers
=
this
.
configurer
.
getWriters
();
assertEquals
(
4
,
writers
.
size
());
assertSame
(
customEncoder1
,
getNextEncoder
(
writers
));
assertSame
(
customWriter1
,
writers
.
get
(
this
.
index
.
getAndIncrement
()));
assertSame
(
customEncoder2
,
getNextEncoder
(
writers
));
assertSame
(
customWriter2
,
writers
.
get
(
this
.
index
.
getAndIncrement
()));
}
@Test
public
void
jackson2DecoderOverride
()
throws
Exception
{
Jackson2JsonDecoder
decoder
=
new
Jackson2JsonDecoder
();
this
.
configurer
.
defaultCodec
().
jackson2Decoder
(
decoder
);
assertSame
(
decoder
,
this
.
configurer
.
getReaders
().
stream
()
.
filter
(
writer
->
writer
instanceof
DecoderHttpMessageReader
)
.
map
(
writer
->
((
DecoderHttpMessageReader
<?>)
writer
).
getDecoder
())
.
filter
(
e
->
Jackson2JsonDecoder
.
class
.
equals
(
e
.
getClass
()))
.
findFirst
()
.
filter
(
e
->
e
==
decoder
).
orElse
(
null
));
}
@Test
public
void
jackson2EncoderOverride
()
throws
Exception
{
Jackson2JsonEncoder
encoder
=
new
Jackson2JsonEncoder
();
this
.
configurer
.
defaultCodec
().
jackson2Encoder
(
encoder
);
assertSame
(
encoder
,
this
.
configurer
.
getWriters
().
stream
()
.
filter
(
writer
->
writer
instanceof
EncoderHttpMessageWriter
)
.
map
(
writer
->
((
EncoderHttpMessageWriter
<?>)
writer
).
getEncoder
())
.
filter
(
e
->
Jackson2JsonEncoder
.
class
.
equals
(
e
.
getClass
()))
.
findFirst
()
.
filter
(
e
->
e
==
encoder
).
orElse
(
null
));
assertSame
(
encoder
,
this
.
configurer
.
getWriters
().
stream
()
.
filter
(
writer
->
ServerSentEventHttpMessageWriter
.
class
.
equals
(
writer
.
getClass
()))
.
map
(
writer
->
(
ServerSentEventHttpMessageWriter
)
writer
)
...
...
spring-webflux/src/main/java/org/springframework/web/reactive/config/WebFluxConfigurationSupport.java
浏览文件 @
dc3851df
...
...
@@ -71,16 +71,6 @@ import org.springframework.web.server.handler.ResponseStatusExceptionHandler;
*/
public
class
WebFluxConfigurationSupport
implements
ApplicationContextAware
{
private
static
final
boolean
jackson2Present
=
ClassUtils
.
isPresent
(
"com.fasterxml.jackson.databind.ObjectMapper"
,
WebFluxConfigurationSupport
.
class
.
getClassLoader
())
&&
ClassUtils
.
isPresent
(
"com.fasterxml.jackson.core.JsonGenerator"
,
WebFluxConfigurationSupport
.
class
.
getClassLoader
());
private
static
final
boolean
jaxb2Present
=
ClassUtils
.
isPresent
(
"javax.xml.bind.Binder"
,
WebFluxConfigurationSupport
.
class
.
getClassLoader
());
private
Map
<
String
,
CorsConfiguration
>
corsConfigurations
;
private
PathMatchConfigurer
pathMatchConfigurer
;
...
...
@@ -159,7 +149,7 @@ public class WebFluxConfigurationSupport implements ApplicationContextAware {
*/
protected
Map
<
String
,
MediaType
>
getDefaultMediaTypeMappings
()
{
Map
<
String
,
MediaType
>
map
=
new
HashMap
<>();
if
(
jackson2Present
)
{
if
(
ServerCodecConfigurer
.
jackson2Present
)
{
map
.
put
(
"json"
,
MediaType
.
APPLICATION_JSON
);
}
return
map
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录