这不是理想的解决方案。看到我的第二个答案。
我使用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
除了在单向方式(向外):
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
其包括称为mixins
一个参数。这是我如何在Controller端实现的。
@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并应用带注释的混合插件。
这个“不利的一面”(如果你这样称呼的话)就是不得不恢复到Spring 2。因为新的3.0标签不允许直接配置ModelAndViewResolver,所以可以采用5种方法来配置它。也许他们只是忽略了这一点?
我的老配置(使用Spring 3.1风格)
<mvc:annotation-driven />
我的新配置(使用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。因此,切换回旧式。
这里的定制注释:
的Json
@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();
}