Burada en az iki seçenek görmek
public class CustomRequestBodyArgumentResolver implements HandlerMethodArgumentResolver {
private final ObjectMapperResolver objectMapperResolver;
public CustomRequestBodyArgumentResolver(ObjectMapperResolver objectMapperResolver) {
this.objectMapperResolver = objectMapperResolver;
}
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
return methodParameter.getParameterAnnotation(CustomRequestBody.class) != null;
}
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
if (this.supportsParameter(methodParameter)) {
ObjectMapper objectMapper = objectMapperResolver.getObjectMapper();
HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
return objectMapper.readValue(request.getInputStream(), methodParameter.getParameterType());
} else {
return WebArgumentResolver.UNRESOLVED;
}
}
}
ObjectMapperResolver
bir arayüz Kullanmak için gerçek ObjectMapper
örneğini çözmek için kullanacağız, aşağıda tartışacağız. Elbette, özel eşlemeye ihtiyacınız olan tek bir kullanım durumunuz varsa, eşleştirmeyi buraya kolayca başlatabilirsiniz.
Bu yapılandırmayla özel argüman çözümleyicinizi ekleyebilirsiniz:
@Configuration
public class WebConfiguration extends WebMvcConfigurerAdapter {
@Bean
public CustomRequestBodyArgumentResolver customBodyArgumentResolver(ObjectMapperResolver objectMapperResolver) {
return new CustomRequestBodyArgumentResolver(objectMapperResolver)
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(customBodyArgumentResolver(objectMapperResolver()));
}
}
Her şeyden önce, tüm yöntem çağrılarını altta yatan bir nesneye çevirecek bir ara kesiciye ihtiyacımız var.
public abstract class ObjectMapperInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
return ReflectionUtils.invokeMethod(invocation.getMethod(), getObject(), invocation.getArguments());
}
protected abstract ObjectMapper getObject();
}
Şimdi bizim ObjectMapper
vekil fasulye gibi görünecektir:
@Bean
public ObjectMapper objectMapper(ObjectMapperResolver objectMapperResolver) {
ProxyFactory factory = new ProxyFactory();
factory.setTargetClass(ObjectMapper.class);
factory.addAdvice(new ObjectMapperInterceptor() {
@Override
protected ObjectMapper getObject() {
return objectMapperResolver.getObjectMapper();
}
});
return (ObjectMapper) factory.getProxy();
}
Not: Ben, bu yüzden dolayı onun modüler sınıf yükleme Wildfly, bu proxy ile sınıf yükleme sorunları vardıObjectMapper
'u (herhangi bir şeyi değiştirmeden) genişleterek sınıfımı modülümden kullanabilirim.
bir arada, bu yapılandırma ile bağlanmış tüm: @Configuration
public class WebConfiguration extends WebMvcConfigurerAdapter {
@Bean
public MappingJackson2HttpMessageConverter jackson2HttpMessageConverter() {
return new MappingJackson2HttpMessageConverter(objectMapper(objectMapperResolver()));
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(jackson2HttpMessageConverter());
}
}
ObjectMapperResolver
uygulamaları
Nihai parça kullanılması gerektiğini eşleyici tespit mantığı, bir ObjectMapperResolver
arayüz içinde ihtiva edilecektir. özel haritacılarla kullanım durumları çok yoksa
public interface ObjectMapperResolver {
ObjectMapper getObjectMapper();
}
basitçe tuşları olarak ReqeustMatcher
s ile önceden yapılandırılmış durumlarda bir haritasını yapabiliriz: Sadece bir bakış yukarı yöntem içerir. Böyle bir şey:
public class RequestMatcherObjectMapperResolver implements ObjectMapperResolver {
private final ObjectMapper defaultMapper;
private final Map<RequestMatcher, ObjectMapper> mapping = new HashMap<>();
public RequestMatcherObjectMapperResolver(ObjectMapper defaultMapper, Map<RequestMatcher, ObjectMapper> mapping) {
this.defaultMapper = defaultMapper;
this.mapping.putAll(mapping);
}
public RequestMatcherObjectMapperResolver(ObjectMapper defaultMapper) {
this.defaultMapper = defaultMapper;
}
@Override
public ObjectMapper getObjectMapper() {
ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = sra.getRequest();
for (Map.Entry<RequestMatcher, ObjectMapper> entry : mapping.entrySet()) {
if (entry.getKey().matches(request)) {
return entry.getValue();
}
}
return defaultMapper;
}
}
Ayrıca isteği kullanabilirsiniz ObjectMapper
kapsamlı ve daha sonra her istek temelinde yapılandırın. Bu yapılandırmayı kullanın:
@Bean
public ObjectMapperResolver objectMapperResolver() {
return new ObjectMapperResolver() {
@Override
public ObjectMapper getObjectMapper() {
return requestScopedObjectMapper();
}
};
}
@Bean
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public ObjectMapper requestScopedObjectMapper() {
return new ObjectMapper();
}
sağ denetleyici yönteminde yapılandırabilirsiniz, bu durum özel bir yanıt serileştirme için uygundur. Özel serileştirme için, denetleyici yöntemi tetiklenmeden önce geçerli eşleştirmeyi etkin eşleştiriciyi yapılandırmak için Filter
/HandlerInterceptor
/HandlerInterceptor
/ControllerAdvice
'u da kullanmanız gerekir.
public interface ObjectMapperConfigurer {
void configureObjectMapper(ObjectMapper objectMapper);
}
Sonra tuşları olarak RequstMatcher
s ile bu durumlarda bir haritasını yapmak ve onu RequestMatcherObjectMapperResolver
bir Filter
/HandlerInterceptor
/ControllerAdvice
benzer koymak:
Sen ObjectMapperResolver
benzer bir arayüz oluşturabilir.
P.S.Dinamik ObjectMapper
yapılandırmasını biraz daha keşfetmek isterseniz, eski cevabımı here önerebilirim. Çalışma zamanında dinamik @JsonFilter
s nasıl yapabileceğinizi açıklar. Ayrıca, yorumlarda önerdiğim genişletilmiş MappingJackson2HttpMessageConverter
ile daha eski yaklaşımımı içerir.
Nesne eşleyicisi yazma hakkında ne düşünüyorsunuz? İçinde ihtiyacınız olan serileştirme mantığını ekleyebilirsiniz. – reos
Sorun, bir nesne eşleyicisi oluşturmuyor. Sorum şu: web uygulaması içinde global olarak değil, bir nesne eşleyicisini denetleyici bazında nasıl yapılandırabilirim. – Mark
Sorunuzu anlıyorum, tüm denetleyicilerinde kullanılacak bir nesne eşleştiricisi yazmayı öneririm, ancak isteğine bağlı olarak nesneyi seri hale getirebilir. – reos