如何使用GZip和Jersey压缩Java REST API中的响应

在某些情况下,您的REST api会提供非常长的响应,我们都知道移动设备/网络上的传输速度和带宽仍然非常重要。 我认为这是开发支持移动应用程序的REST api时需要解决的第一个性能优化点。 你猜怎么了? 因为响应是文本,所以我们可以压缩它们。 借助当今智能手机和平板电脑的强大功能,在客户端上解压缩它们并不是什么大不了的事。因此,在本文中,我将介绍如何使用泽西岛(Jersey)在Java中构建压缩REST API响应的方法。是JAX-RS参考实现(以及更多)…

1.球衣过滤器和拦截器

好吧,得益于Jersey强大的过滤器和拦截器功能,实现起来相当容易。 过滤器主要用于操纵请求和响应参数,例如HTTP头,URI和/或HTTP方法,而拦截器则用于通过操纵实体输入/输出流来操纵实体。

您已经在我的帖子中看到了过滤器的功能:

但要进行压缩,将使用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设计和实现

翻译自: https://www.javacodegeeks.com/2014/11/how-to-compress-responses-in-java-rest-api-with-gzip-and-jersey.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值