获取语言环境的一种方法是使用 HttpHeaders#getAcceptableLanguages()
。
获取响应中可接受的语言列表。
如果未指定可接受的语言,则返回一个只读列表,其中包含一个带有“*”语言字段的通配符Locale实例。
返回:按其q值排序的可接受语言的只读列表,首选项最高。
您可以在几乎任何地方注入HttpHeaders
,使用@Context
public Response doSomething(@Context HttpHeaders headers) {
List<Locale> langs = headers.getAcceptableLanguages()
如果您想要在
过滤器中获取列表,还可以从
ContainerRequestContext
获取区域设置列表。
@Override
public void filter(ContainerRequestContext requestContext) throw .. {
List<Locales> langs = requestContext.getAcceptableLanguages();
}
如果你想在资源方法中使用
Locale
,但不想在方法中进行所有区域设置的"解析",你可以使用一些依赖注入,并创建一个
Factory
,在那里你可以注入
HttpHeaders
并在那里解析语言环境。
请参见:
Jersey 2.0中的依赖注入
下面是一个完整的测试用例示例,使用了我提到的最后两点的组合方法,即使用过滤器和依赖注入以及
Factory
,这样你就可以将已解决的
Locale
注入到资源方法中。该示例使用一个虚拟的语言环境解析器,只允许英语。在我们解析语言环境之后,我们将其设置为请求上下文属性,并从
Factory
内检索,以便我们可以将其注入到资源方法中。
@GET
public String get(@Context Locale locale) {
return locale.toString();
}
另请参阅: 如何将对象注入Jersey请求上下文?
如果您需要我解释示例的其他内容,请告诉我。
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import org.glassfish.hk2.api.Factory;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.filter.LoggingFilter;
import org.glassfish.jersey.process.internal.RequestScoped;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
public class AcceptLanguageTest extends JerseyTest {
@Path("language")
public static class TestResource {
@GET
public String get(@Context Locale locale) {
return locale.toString();
}
}
public static interface LocaleResolver {
Locale resolveLocale(List<Locale> locales);
}
public static class DefaultLocaleResolver implements LocaleResolver {
@Override
public Locale resolveLocale(List<Locale> locales) {
if (locales.contains(Locale.ENGLISH)) {
return Locale.ENGLISH;
}
return null;
}
}
@Provider
@PreMatching
public static class LocaleResolverFilter implements ContainerRequestFilter {
static final String LOCALE_PROPERTY = "LocaleResolverFilter.localProperty";
@Inject
private LocaleResolver localeResolver;
@Override
public void filter(ContainerRequestContext context) throws IOException {
List<Locale> locales = context.getAcceptableLanguages();
Locale locale = localeResolver.resolveLocale(locales);
if (locale == null) {
context.abortWith(Response.status(Response.Status.NOT_ACCEPTABLE).build());
return;
}
context.setProperty(LOCALE_PROPERTY, locale);
}
}
public static class LocaleFactory implements Factory<Locale> {
@Context
private ContainerRequestContext context;
@Override
public Locale provide() {
return (Locale) context.getProperty(LocaleResolverFilter.LOCALE_PROPERTY);
}
@Override
public void dispose(Locale l) {}
}
@Override
public ResourceConfig configure() {
return new ResourceConfig(TestResource.class)
.register(LocaleResolverFilter.class)
.register(new AbstractBinder() {
@Override
protected void configure() {
bindFactory(LocaleFactory.class)
.to(Locale.class).in(RequestScoped.class);
bind(DefaultLocaleResolver.class)
.to(LocaleResolver.class).in(Singleton.class);
}
})
.register(new LoggingFilter(Logger.getAnonymousLogger(), true));
}
@Test
public void shouldReturnEnglish() {
final String accept = "da, en-gb;q=0.8, en;q=0.7";
final Response response = target("language").request()
.acceptLanguage(accept)
.get();
assertThat(response.readEntity(String.class), is("en"));
}
@Test
public void shouldReturnNotAcceptable() {
final String accept = "da";
final Response response = target("language").request()
.acceptLanguage(accept)
.get();
assertThat(response.getStatus(), is(Response.Status.NOT_ACCEPTABLE.getStatusCode()));
}
}