Filtering JSON feeds from Spring 3's REST support using addMixInAnnotations
来源:互联网 发布:上市公司毛利率算法 编辑:程序博客网 时间:2024/06/05 14:42
Spring3 allows you to output JSON payloads quite easily with its REST support. It uses Jackson (an advanced, fast API that does JSON serialization essentially converts Java object to JSON).
The problem is that depending on which REST request we get, we may want to show different parts of a particular object.
We don't want 10 different subclasses of the same object. Jackson provides a way to filter objects based on addMixInAnnotations (read previous post for more detail).
We would like to easily vary what gets returned on a request method handler by request handler basis.
[See earlier discussion on filtering JSON serialization on a use case by use case basis which was in the post just before this one]
A request handler in Spring3 that returns a JSON payload looks like this:
@RequestMapping(value = "/{locale}/apps/{publicSlug}/", method = RequestMethod.GET)
public @ResponseBody ApplicationEntry getAppDetail(@PathVariable String publicSlug, @PathVariable String locale,
HttpServletResponse response, HttpServletRequest request) throws Exception {
...
return ApplicationEntry.findApplicationEntry(publicSlug, country, language);
}
We would like to do this to apply a JSON filter.
Define an interface (which is the filter) as follows:
@JsonIgnoreProperties( { "country",
})
@JsonPropertyOrder(value={"title", "id", "version", "price", "summary"})
public interface AppDetailFilter {
}
Then use the annotation to filter the response as follows:
@JsonFilter(mixin=AppDetailFilter.class)
@RequestMapping(value = "/{locale}/apps/{publicSlug}/", method = RequestMethod.GET)
public @ResponseBody ApplicationEntry getAppDetail(@PathVariable String publicSlug, @PathVariable String locale,
HttpServletResponse response, HttpServletRequest request) throws Exception {
...
return ApplicationEntry.findApplicationEntry(publicSlug, country, language);
}
Ok so we added this capability.
This is what the annotation looks like:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface JsonFilter {
Class<?> mixin();
}
Then we just write the glue code to apply the behavior of outputting the returned object to the HTTP stream as follows:
public aspect JsonFilterAspect {
protected final Logger log = Logger.getLogger(getClass());
pointcut filterJsonResponses(): execution(@JsonFilter public * com.somecompany.someapp.web..*.*(..));
Object around() : filterJsonResponses() {
MethodSignature msig = (MethodSignature) thisJoinPoint.getSignature();
/* Grab the annotation. */
JsonFilter annotation = msig.getMethod().getAnnotation(JsonFilter.class);
Class<?> mixin = annotation.mixin();
ObjectMapper mapper = new ObjectMapper();
mapper.getSerializationConfig().addMixInAnnotations(msig.getMethod().getReturnType(), mixin);
try {
mapper.writeValue(WebContext.getInstance().getResponse().getOutputStream(), proceed());
} catch(Exception ex) {
throw new RuntimeException(ex);
}
return null;
}
}
The above applies custom JSON serialization code based on Jackson's support for adding mixin annotations (described in the previous post).
You might wonder what WebContext is. It is a helper class I wrote that gets populated by a ServletFilter. The context is stored in a ThreadLocal and then removed after the request is done (both by the filter). For completeness, here is the filter and WebContext object.
@Component("webContextFilter")
public class WebContextFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
ServletContext servletContext = this.getServletContext();
WebContext.create(request, response, servletContext);
chain.doFilter(request, response);
WebContext.clear();
}
}
@RooJavaBean
@RooToString
public class WebContext {
private static ThreadLocal<WebContext> tlv = new ThreadLocal<WebContext>();
private HttpServletRequest request;
private HttpServletResponse response;
private ServletContext servletContext;
protected WebContext() {}
private WebContext(HttpServletRequest request, HttpServletResponse response,
ServletContext servletContext) {
this.request = request;
this.response = response;
this.servletContext = servletContext;
}
public static WebContext getInstance() {
return tlv.get();
}
public static void create(HttpServletRequest request, HttpServletResponse response,
ServletContext servletContext) {
WebContext wc = new WebContext(request, response, servletContext);
tlv.set(wc);
}
public static void clear() {
tlv.set(null);
}
}
Now we can annotate any request handler with @JsonFilter(mixin=AppDetailFilter.class) and it will apply the Jackson JSON custom streaming, i.e., filtering.
0 0
- Filtering JSON feeds from Spring 3's REST support using addMixInAnnotations
- Using SQL Server's XML Support
- Secure Spring REST API using OAuth2
- Secure Spring REST API using OAuth2
- RSS Feeds with Spring Boot
- Post Json 例子 Spring Rest Template & HttpClient
- Spring REST Hello World JSON Example
- spring+cxf+maven+rest风格+json/xml
- Shadow removal using bilateral filtering
- Spring Boot Spring MVC Rest json输出日期的问题
- Using AutoCAD's file selection dialog from .NET
- get file's name from a folder using Java
- Calling lua functions from .lua's using handles?
- Populate an ASP.NET ListBox from JSON results using jQuery
- FEEDS Could not retrieve title from feed. in Drupal
- spring boot data rest 3
- Spring MVC Rest Json,XML多视图解析 配置
- Spring MVC Rest Json,XML多视图解析 配置
- Ubuntu15.10下mysql 5.6.28中文乱码问题
- scanf()和getchar()在控制终端菜单
- Activiti 学习笔记 小结
- Bootstrap_day1
- Lua初识(4)_判断语句
- Filtering JSON feeds from Spring 3's REST support using addMixInAnnotations
- Embedded Linux S3C2440 Environment Startup
- ssh查询分页(同页面的多个方法查询)的思路分析:
- 判断二叉树是不是平衡二叉树
- 如何在本地环境配置github
- Java编码
- 斐波那契数列通项公式
- Github的学习使用
- 王学岗app设计框架:mvc框架