gzip解压
在某些情况下,您的REST api会提供非常长的响应,并且我们都知道,移动设备/网络上的传输速度和带宽仍然非常重要。 我认为这是开发支持移动应用程序的REST api时需要解决的第一个性能优化点。 你猜怎么了? 因为响应是文本,所以我们可以压缩它们。 借助当今智能手机和平板电脑的强大功能,在客户端上解压缩它们应该没什么大不了的。因此,在本文中,我将介绍如何使用泽西岛(Jersey)在Java中构建选择性地压缩REST API响应。是JAX-RS参考实现(以及更多)…
1.球衣过滤器和拦截器
好吧,得益于Jersey强大的过滤器和拦截器功能,实现起来非常容易。 过滤器主要用于操纵请求和响应参数,例如HTTP头,URI和/或HTTP方法,而拦截器则用于通过操纵实体输入/输出流来操纵实体。
您已经在我的帖子中看到了过滤器的功能:
- 如何使用Jersey来在Java的服务器端添加CORS支持,在此我展示了如何CORS启用REST API和
- 如何使用SLF4J和Logback登录Spring ,在那里我展示了如何记录来自REST API的请求和响应
但要进行压缩,将使用GZip WriterInterceptor
。 Writer拦截器用于将实体写入“电线”的情况,在这种情况下,在服务器端,这意味着当写出响应实体时。
GZip作家拦截器
因此,让我们看一下我们的GZip Writer拦截器:
GZip作家拦截器
package org.codingpedia.demo.rest.interceptors;
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.GZIPOutputStream;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.WriterInterceptor;
import javax.ws.rs.ext.WriterInterceptorContext;
@Provider
@Compress
public class GZIPWriterInterceptor implements WriterInterceptor {
@Override
public void aroundWriteTo(WriterInterceptorContext context)
throws IOException, WebApplicationException {
MultivaluedMap<String,Object> headers = context.getHeaders();
headers.add("Content-Encoding", "gzip");
final OutputStream outputStream = context.getOutputStream();
context.setOutputStream(new GZIPOutputStream(outputStream));
context.proceed();
}
}
注意:
- 它实现了
WriterInterceptor
,它是消息正文WriterInterceptor
器拦截器的接口,该拦截器包装了对javax.ws.rs.ext.MessageBodyWriter.writeTo
调用。 - 实现
WriterInterceptor
合同的提供程序必须在JAX-RS运行时中以编程方式注册,或者必须使用@Provider批注进行注释,以在提供程序扫描阶段由JAX-RS运行时自动发现。 -
@Compress
是名称绑定批注,我们将在下一段中对其进行详细讨论 - “拦截器从WriterInterceptorContext获取输出流,并设置一个新流,它是原始输出流的GZIP包装器。 执行完所有拦截器后,最后设置为WriterInterceptorContext的输出流将用于实体的序列化。 在上面的示例中,实体字节将被写入GZIPOutputStream,它将压缩流数据并将其写入原始输出流。 原始流始终是将数据写入“电线”的流。 在服务器上使用拦截器时,原始输出流是将数据写入底层服务器容器流的流,该服务器容器流将响应发送到客户端。” [2]
- “ WriteTo()的重写方法将WriterInterceptorContext作为参数。 此上下文包含标头参数,请求属性,实体,实体流和其他属性的获取器和设置器。” [2]; 压缩响应时,应将“ Content-Encoding”标头设置为“ gzip”
压缩注释
过滤器和拦截器可以绑定名称。 名称绑定是一个概念,它允许对JAX-RS运行时说,仅针对特定的资源方法才执行特定的过滤器或拦截器。 当过滤器或拦截器仅限于特定资源方法时,我们说它是名称绑定的。 没有这种限制的过滤器和拦截器称为global 。 在我们的案例中,我们构建了@Compress批注:
压缩注释
package org.codingpedia.demo.rest.interceptors;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.ws.rs.NameBinding;
//@Compress annotation is the name binding annotation
@NameBinding
@Retention(RetentionPolicy.RUNTIME)
public @interface Compress {}
并用它来标记应压缩的资源上的方法(例如,使用PodcastsResource
获取所有播PodcastsResource
):
@Compress资源方法上的注释用法
@Component
@Path("/podcasts")
public class PodcastsResource {
@Autowired
private PodcastService podcastService;
...........................
/*
* *********************************** READ ***********************************
*/
/**
* Returns all resources (podcasts) from the database
*
* @return
* @throws IOException
* @throws JsonMappingException
* @throws JsonGenerationException
* @throws AppException
*/
@GET
@Compress
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public List<Podcast> getPodcasts(
@QueryParam("orderByInsertionDate") String orderByInsertionDate,
@QueryParam("numberDaysToLookBack") Integer numberDaysToLookBack)
throws IOException, AppException {
List<Podcast> podcasts = podcastService.getPodcasts(
orderByInsertionDate, numberDaysToLookBack);
return podcasts;
}
...........................
}
2.测试
SOAPui
好吧,如果您正在使用SOAPui进行测试,则可以针对PodcastsResource
发出以下请求。
请求:
请求示例
GET http://localhost:8888/demo-rest-jersey-spring/podcasts/?orderByInsertionDate=DESC HTTP/1.1
Accept-Encoding: gzip,deflate
Accept: application/json, application/xml
Host: localhost:8888
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
响应:
GZipped json响应,由SOAPui自动解压缩
HTTP/1.1 200 OK
Content-Type: application/json
Content-Encoding: gzip
Content-Length: 409
Server: Jetty(9.0.7.v20131107)
[
{
"id": 2,
"title": "Quarks & Co - zum Mitnehmen",
"linkOnPodcastpedia": "http://www.podcastpedia.org/quarks",
"feed": "http://podcast.wdr.de/quarks.xml",
"description": "Quarks & Co: Das Wissenschaftsmagazin",
"insertionDate": "2014-10-29T10:46:13.00+0100"
},
{
"id": 1,
"title": "- The Naked Scientists Podcast - Stripping Down Science",
"linkOnPodcastpedia": "http://www.podcastpedia.org/podcasts/792/-The-Naked-Scientists-Podcast-Stripping-Down-Science",
"feed": "feed_placeholder",
"description": "The Naked Scientists flagship science show brings you a lighthearted look at the latest scientific breakthroughs, interviews with the world top scientists, answers to your science questions and science experiments to try at home.",
"insertionDate": "2014-10-29T10:46:02.00+0100"
}
]
SOAPui可以识别Content-Type: gzip
标头(已添加到GZIPWriterInterceptor
并自动解压缩响应并将其显示为人眼可读。
好,就是这样。 您已经了解到Jersey如何直接压缩REST api响应。
提示:如果您真的想学习如何在Java中设计和实现REST API,请阅读以下教程-借助Jersey和Spring在Java中进行REST API设计和实现
gzip解压