如何使用 JAX-RS 设置字符集?我试过@Produces("text/html; charset=UTF-8")
了,但被忽略了,只text/html
用 HTTP 标头发送。我想在 MessageBodyWriter 中设置字符集,但不想通过我自己通过反射分析 @Produces 注释来提取媒体类型。
7 回答
正如 Daemon 在评论中指出的那样,最新版本的 JAX-RS(包括 2012 年 9 月的稳定版本)现在确实支持该@Produces
语法。所以你可以使用:
@Produces("text/html; charset=UTF-8")
只是为了保持最新。不确定旧版本的 Jersey 是否支持此功能,但如果您决定使用 ResponseBuilder.header(...) 方法,则可以使用 MediaType 方法withCharset()。像这样:
return Response.status(Status.OK)
.entity(result)
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_TYPE.withCharset("utf-8"))
.build());
也可以使用 ResponseBuilder.header(...) 方法来设置带有字符集的内容类型。请参阅下面的代码示例(使用 JAX-RS 1.1.1、CXF 2.3.1)。
final Response myResponse = Response.status(Response.Status.BAD_REQUEST)
.entity("La requête n'est pas correcte.\n ...")
.header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN+"; charset=ISO-8859-15" )
.build();
如果您想以 JAX-RS 实现中立的方式执行此操作,您可以在 MessageBodyWriter 中重置 Content-Type。就像是:
public void writeTo(Object obj,
Class<?> cls,
Type type,
Annotation[] annotations,
MediaType mt,
MultivaluedMap<String, Object> responseHttpHeaders,
OutputStream stream) throws IOException {
responseHttpHeaders.putSingle(javax.ws.rs.core.HttpHeaders.CONTENT_TYPE, mt.toString() + ";charset=UTF-8");
}
如果每个资源方法除了 UTF-8 之外还有不同的字符集,您可能需要创建一个自定义注释并将其添加到每个资源方法。然后,尝试在 writeTo() 方法中使用 annotations 参数。
仅供参考,Apache Wink支持在媒体类型上使用字符集和其他属性。我希望未来的 JAX-RS 规范修订使这更容易。
首先@Produces
在资源类方法上设置注释。
然后在MessageBodyWriter
您返回的类型中,您可以在writeTo()
方法中执行此操作:
response.setContentType(mediaType.toString);
备注:您可以通过以下方式注入response
您writer
的:
@Context
protected HttpServletResponse response;
我所做的是获取 servlet 响应对象的实例:
protected @Context HttpServletResponse response;
然后将字符编码设置为utf-8:
response.setCharacterEncoding("utf-8");
这对我行得通。
如果使用 RESTEasy,您可以注册一个 Inteceptor:
import org.jboss.resteasy.annotations.interception.ServerInterceptor;
import org.jboss.resteasy.core.ResourceMethodInvoker;
import org.jboss.resteasy.core.ServerResponse;
import org.jboss.resteasy.spi.Failure;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.interception.PreProcessInterceptor;
import org.jboss.resteasy.plugins.providers.multipart.InputPart;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.ext.Provider;
@Provider
@ServerInterceptor
public class ContentTypeSetter implements PreProcessInterceptor {
@Override
public ServerResponse preProcess(HttpRequest request, ResourceMethodInvoker resourceMethodInvoker) throws Failure, WebApplicationException {
request.setAttribute(InputPart.DEFAULT_CONTENT_TYPE_PROPERTY, "*/*; charset=UTF-8");
return null;
}
}
注意:如果您手动设置 @Produces 它会覆盖此拦截器设置的 ContentType。如果这样做,请在 @Produces 中设置字符集