首先,这绝不是错误。这是预期的行为。媒体类型映射的目的与处理文件无关,而是在内容标头可能不可用的情况下(例如在浏览器中)使用内容协商的另一种形式。
尽管不在正式规范中,但此功能是规范最终发布之前的草案的一部分。大多数实现都决定以一种或另一种方式包含它。泽西碰巧让您对其进行配置。因此可以在3.7.1请求预处理的规范中看到此处
组
M={config.getMediaTypeMappings().keySet()} L={config.getLanguageMappings().keySet()} m=null l=null- 其中config是ApplicationConfig的应用程序提供的子类的实例。
对于最终路径段中从右到左扫描的每个扩展名(一个
.字符后跟一个或多个字母数字字符)e:(a)删除开头的“。” 来自的字符
e- (b)如果
misnull和eis是的成员,M则从有效请求URI中删除相应的扩展名并设置m = e。- (c)如果
lis是null和eis的成员,L则从有效请求URI中删除相应的扩展名并设置l = e。否则转到步骤4- 如果m不为null,则将Accept标头的值设置为
config.getExtensionMappings().get(m)
3(b)基本上是说应将扩展名从请求的URI中删除,而4则表示应该有一些扩展名映射,将
json(扩展名)映射到该扩展名
application/json并将其设置为
Accept标头。您可以从不同的测试中看到这种行为
@POST@Path("/files/{file}")@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})public Response doTest(@PathParam("file") String fileName, @Context HttpHeaders headers) { String accept = headers.getHeaderString(HttpHeaders.ACCEPT); return Response.ok(fileName + "; Accept: " + accept).build();}...Map<String, MediaType> map = new HashMap<>();map.put("xml", MediaType.APPLICATION_XML_TYPE);resourceCnfig.property(ServerProperties.MEDIA_TYPE_MAPPINGS, map);curl -v http://localhost:8080/api/mapping/files/file.xml -X POST
结果:file; Accept: application/xml
如果我们注释掉该配置属性,您将看到
Accept尚未设置标头。
curl -v http://localhost:8080/api/mapping/files/file.xml -X POST
结果:file.xml; Accept: */**
话虽如此…
配置时
ServerProperties.MEDIA_TYPE_MAPPINGS,
org.glassfish.jersey.server.filter.UriConnegFilter就是用于此功能的过滤器。您可以在源代码的204和211行中看到,其中过滤器正在剥离扩展名。
path = new StringBuilder(path).delete(index, index + suffix.length() + 1).toString();...rc.setRequestUri(uriInfo.getRequestUriBuilder().replacePath(path).build(new Object[0]));
因此,没有办法进行配置(至少就我看源代码而言),因此我们将不得不扩展该类,重写该
filter方法,并至少取出实际进行替换的最后一行,然后注册过滤器。这是我为使其正常工作所做的。我只是复制并粘贴了过滤器中的代码,并在替换扩展名的行中添加了注释
import java.io.IOException;import java.util.List;import java.util.Map;import javax.annotation.Priority;import javax.ws.rs.container.ContainerRequestContext;import javax.ws.rs.container.PreMatching;import javax.ws.rs.core.Configuration;import javax.ws.rs.core.Context;import javax.ws.rs.core.MediaType;import javax.ws.rs.core.PathSegment;import javax.ws.rs.core.UriInfo;import org.glassfish.jersey.server.filter.UriConnegFilter;@PreMatching@Priority(3000)public class MyUriConnegFilter extends UriConnegFilter { public MyUriConnegFilter(@Context Configuration config) { super(config); } public MyUriConnegFilter(Map<String, MediaType> mediaTypeMappings, Map<String, String> languageMappings) { super(mediaTypeMappings, languageMappings); } @Override public void filter(ContainerRequestContext rc) throws IOException { UriInfo uriInfo = rc.getUriInfo(); String path = uriInfo.getRequestUri().getRawPath(); if (path.indexOf('.') == -1) { return; } List<PathSegment> l = uriInfo.getPathSegments(false); if (l.isEmpty()) { return; } PathSegment segment = null; for (int i = l.size() - 1; i >= 0; i--) { segment = (PathSegment) l.get(i); if (segment.getPath().length() > 0) { break; } } if (segment == null) { return; } int length = path.length(); String[] suffixes = segment.getPath().split("\."); for (int i = suffixes.length - 1; i >= 1; i--) { String suffix = suffixes[i]; if (suffix.length() != 0) { MediaType accept = (MediaType) this.mediaTypeMappings.get(suffix); if (accept != null) { rc.getHeaders().putSingle("Accept", accept.toString()); int index = path.lastIndexOf('.' + suffix); path = new StringBuilder(path).delete(index, index + suffix.length() + 1).toString(); suffixes[i] = ""; break; } } } for (int i = suffixes.length - 1; i >= 1; i--) { String suffix = suffixes[i]; if (suffix.length() != 0) { String acceptLanguage = (String) this.languageMappings.get(suffix); if (acceptLanguage != null) { rc.getHeaders().putSingle("Accept-Language", acceptLanguage); int index = path.lastIndexOf('.' + suffix); path = new StringBuilder(path).delete(index, index + suffix.length() + 1).toString(); suffixes[i] = ""; break; } } } if (length != path.length()) { //rc.setRequestUri(uriInfo.getRequestUriBuilder().replacePath(path).build(new Object[0])); } }}然后配置它
Map<String, MediaType> map = new HashMap<>();map.put("xml", MediaType.APPLICATION_XML_TYPE);map.put("json", MediaType.APPLICATION_JSON_TYPE);resourceConfig.register(new MyUriConnegFilter(map, null));curl -v http://localhost:8080/api/mapping/files/file.xml -X POST
结果:file.xml; Accept: application/xmlcurl -v http://localhost:8080/api/mapping/files/file.json -X POST
结果:file.json; Accept: application/json



