これは理想的なソリューションではありません。私の2番目の答えを見てください。
を使用してこれを解決しましたModelAndViewResolver
。AnnotationMethodHandlerAdapter
デフォルトの処理が発生する前に、これらが常に最初に開始されることを知っているという特典を使用して、これらを直接登録することができます。したがって、Spring のドキュメント -
/**
* Set a custom ModelAndViewResolvers to use for special method return types.
* <p>Such a custom ModelAndViewResolver will kick in first, having a chance to resolve
* a return value before the standard ModelAndView handling kicks in.
*/
public void setCustomModelAndViewResolver(ModelAndViewResolver customModelAndViewResolver) {
this.customModelAndViewResolvers = new ModelAndViewResolver[] {customModelAndViewResolver};
}
インターフェイスを見ると、ModelAndViewResolver
一部の機能をハンドラー メソッドの動作に拡張するために必要なすべての引数が含まれていることがわかりました。
public interface ModelAndViewResolver {
ModelAndView UNRESOLVED = new ModelAndView();
ModelAndView resolveModelAndView(Method handlerMethod,
Class handlerType,
Object returnValue,
ExtendedModelMap implicitModel,
NativeWebRequest webRequest);
}
のおいしい議論をすべて見てくださいresolveModelAndView
! 私は事実上、Spring がリクエストについて知っているすべてのものにアクセスできます。MappingJacksonHttpMessageConverter
以下は、単方向 (外向き) で except と非常によく似た動作をするようにインターフェイスを実装した方法です。
public class JsonModelAndViewResolver implements ModelAndViewResolver {
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
public static final MediaType DEFAULT_MEDIA_TYPE = new MediaType("application", "json", DEFAULT_CHARSET);
private boolean prefixJson = false;
public void setPrefixJson(boolean prefixJson) {
this.prefixJson = prefixJson;
}
/**
* Converts Json.mixins() to a Map<Class, Class>
*
* @param jsonFilter Json annotation
* @return Map of Target -> Mixin classes
*/
protected Map<Class<?>, Class<?>> getMixins(Json jsonFilter) {
Map<Class<?>, Class<?>> mixins = new HashMap<Class<?>, Class<?>>();
if(jsonFilter != null) {
for(JsonMixin jsonMixin : jsonFilter.mixins()) {
mixins.put(jsonMixin.target(), jsonMixin.mixin());
}
}
return mixins;
}
@Override
public ModelAndView resolveModelAndView(Method handlerMethod, Class handlerType, Object returnValue, ExtendedModelMap implicitModel, NativeWebRequest webRequest) {
if(handlerMethod.getAnnotation(Json.class) != null) {
try {
HttpServletResponse httpResponse = webRequest.getNativeResponse(HttpServletResponse.class);
httpResponse.setContentType(DEFAULT_MEDIA_TYPE.toString());
OutputStream out = httpResponse.getOutputStream();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setMixInAnnotations(getMixins(handlerMethod.getAnnotation(Json.class)));
JsonGenerator jsonGenerator =
objectMapper.getJsonFactory().createJsonGenerator(out, JsonEncoding.UTF8);
if (this.prefixJson) {
jsonGenerator.writeRaw("{} && ");
}
objectMapper.writeValue(jsonGenerator, returnValue);
out.flush();
out.close();
return null;
} catch (JsonProcessingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return UNRESOLVED;
}
}
上記で使用した唯一のカスタム クラスは、@Json
という 1 つのパラメーターを含む注釈クラスmixins
です。コントローラー側でこれを実装する方法は次のとおりです。
@Controller
public class Controller {
@Json({ @JsonMixin(target=MyTargetObject.class, mixin=MyTargetMixin.class) })
@RequestMapping(value="/my-rest/{id}/my-obj", method=RequestMethod.GET)
public @ResponseBody List<MyTargetObject> getListOfFoo(@PathVariable("id") Integer id) {
return MyServiceImpl.getInstance().getBarObj(id).getFoos();
}
}
それはかなり素晴らしい単純さです。ModelAndViewResolver は、返されたオブジェクトを自動的に JSON に変換し、注釈付きのミックスインも適用します。
新しい 3.0 タグでは ModelAndViewResolver を直接構成できないため、Spring 2.5 の構成方法に戻す必要があります。多分彼らはこれを見落としたのでしょうか?
My Old Config (Spring 3.1 スタイルを使用)
<mvc:annotation-driven />
My New Config (Spring 2.5 スタイルを使用)
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="customModelAndViewResolvers">
<list>
<bean class="my.package.mvc.JsonModelAndViewResolver" />
</list>
</property>
</bean>
^^ 3.0+ には、カスタム ModelAndViewResolver を接続する方法がありません。したがって、古いスタイルに戻ります。
カスタム注釈は次のとおりです。
ジェイソン
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Json {
/**
* A list of Jackson Mixins.
* <p>
* {@link http://wiki.fasterxml.com/JacksonMixInAnnotations}
*/
JsonMixin[] mixins() default {};
}
JsonMixin
public @interface JsonMixin {
public Class<? extends Serializable> target();
public Class<?> mixin();
}