如何在 JAX-RS 中实现 HTTP 方法的默认功能?
How do I implement a default functionality for HTTP Method in JAX-RS?
我正在使用 JAX-RS,它具有 @OPTIONS
和 @HEAD
方法的默认实现,但我想提供不同的功能。
我目前做的是这样的:
@GET
@Path("path/to/resource")
@Produces(MediaType.APPLICATION_JSON)
public Response resourceCall(){
// Normal method implementation
}
@OPTIONS
@Path("path/to/resource")
@Produces(MediaType.APPLICATION_JSON)
public Response resourceCall(){
Response.status(Response.Status.METHOD_NOT_ALLOWED).build();
}
所以基本上我对我的每个资源都创建了一个新调用。但是我想在这里有一个 catch-all 方法来处理我对 @OPTION
或 @HEAD
.
的所有调用
如何实现这样的功能?
编辑
只是为了清楚起见。我知道如何使用 Servlet 过滤器来执行此操作,但我想知道 JAX-RS
是否具有针对特定情况的内置功能。
默认选项处理程序是通过
实现的
@OPTIONS
@Path("{path: .*}")
public Response allOptions() {
}
由于您正在使用 Jersey,因此 Jersey 具有允许您 programmatically add and modify resources 的功能。因此,您可以向所有资源添加 OPTIONS
和 HEAD
方法,而无需触及您的资源 类。下面是一个只发送带有 No <Method>
消息的 405 的示例。可能不是你想要的,但你应该能够弄清楚你需要修改什么才能得到你想要的。
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.core.Configuration;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import org.glassfish.jersey.process.Inflector;
import org.glassfish.jersey.server.model.ModelProcessor;
import org.glassfish.jersey.server.model.Resource;
import org.glassfish.jersey.server.model.ResourceModel;
@Provider
public class HeadAndOptionsModelProcessor implements ModelProcessor {
@Override
public ResourceModel processResourceModel(ResourceModel resourceModel,
Configuration configuration) {
ResourceModel.Builder resourceModelBuilder = new ResourceModel.Builder(false);
for (Resource rootResource: resourceModel.getResources()) {
final Resource.Builder rootResourceBuilder = Resource.builder(rootResource);
addOptions(rootResourceBuilder);
addHead(rootResourceBuilder);
for (Resource childResource: rootResource.getChildResources()) {
final Resource.Builder childResourceBuilder = Resource.builder(childResource);
addOptions(childResourceBuilder);
addHead(childResourceBuilder);
rootResourceBuilder.addChildResource(childResourceBuilder.build());
}
resourceModelBuilder.addResource(rootResourceBuilder.build());
}
return resourceModelBuilder.build();
}
@Override
public ResourceModel processSubResource(ResourceModel subResourceModel,
Configuration configuration) {
return subResourceModel;
}
private void addOptions(Resource.Builder resourceBuilder) {
resourceBuilder.addMethod("OPTIONS")
.handledBy(new Inflector<ContainerRequestContext, Response>() {
@Override
public Response apply(ContainerRequestContext context) {
return getOptionsResponse(context);
}
}).produces(MediaType.TEXT_PLAIN).extended(true);
}
private void addHead(Resource.Builder resourceBuilder) {
resourceBuilder.addMethod("HEAD")
.handledBy(new Inflector<ContainerRequestContext, Response>() {
@Override
public Response apply(ContainerRequestContext context) {
return getHeadResponse(context);
}
}).produces(MediaType.TEXT_PLAIN).extended(true);
}
private static Response getOptionsResponse(ContainerRequestContext context) {
return Response.status(Response.Status.METHOD_NOT_ALLOWED).entity("No Options").build();
}
private static Response getHeadResponse(ContainerRequestContext context) {
return Response.status(Response.Status.METHOD_NOT_ALLOWED).entity("No Head").build();
}
}
我正在使用 JAX-RS,它具有 @OPTIONS
和 @HEAD
方法的默认实现,但我想提供不同的功能。
我目前做的是这样的:
@GET
@Path("path/to/resource")
@Produces(MediaType.APPLICATION_JSON)
public Response resourceCall(){
// Normal method implementation
}
@OPTIONS
@Path("path/to/resource")
@Produces(MediaType.APPLICATION_JSON)
public Response resourceCall(){
Response.status(Response.Status.METHOD_NOT_ALLOWED).build();
}
所以基本上我对我的每个资源都创建了一个新调用。但是我想在这里有一个 catch-all 方法来处理我对 @OPTION
或 @HEAD
.
如何实现这样的功能?
编辑
只是为了清楚起见。我知道如何使用 Servlet 过滤器来执行此操作,但我想知道 JAX-RS
是否具有针对特定情况的内置功能。
默认选项处理程序是通过
实现的@OPTIONS
@Path("{path: .*}")
public Response allOptions() {
}
由于您正在使用 Jersey,因此 Jersey 具有允许您 programmatically add and modify resources 的功能。因此,您可以向所有资源添加 OPTIONS
和 HEAD
方法,而无需触及您的资源 类。下面是一个只发送带有 No <Method>
消息的 405 的示例。可能不是你想要的,但你应该能够弄清楚你需要修改什么才能得到你想要的。
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.core.Configuration;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import org.glassfish.jersey.process.Inflector;
import org.glassfish.jersey.server.model.ModelProcessor;
import org.glassfish.jersey.server.model.Resource;
import org.glassfish.jersey.server.model.ResourceModel;
@Provider
public class HeadAndOptionsModelProcessor implements ModelProcessor {
@Override
public ResourceModel processResourceModel(ResourceModel resourceModel,
Configuration configuration) {
ResourceModel.Builder resourceModelBuilder = new ResourceModel.Builder(false);
for (Resource rootResource: resourceModel.getResources()) {
final Resource.Builder rootResourceBuilder = Resource.builder(rootResource);
addOptions(rootResourceBuilder);
addHead(rootResourceBuilder);
for (Resource childResource: rootResource.getChildResources()) {
final Resource.Builder childResourceBuilder = Resource.builder(childResource);
addOptions(childResourceBuilder);
addHead(childResourceBuilder);
rootResourceBuilder.addChildResource(childResourceBuilder.build());
}
resourceModelBuilder.addResource(rootResourceBuilder.build());
}
return resourceModelBuilder.build();
}
@Override
public ResourceModel processSubResource(ResourceModel subResourceModel,
Configuration configuration) {
return subResourceModel;
}
private void addOptions(Resource.Builder resourceBuilder) {
resourceBuilder.addMethod("OPTIONS")
.handledBy(new Inflector<ContainerRequestContext, Response>() {
@Override
public Response apply(ContainerRequestContext context) {
return getOptionsResponse(context);
}
}).produces(MediaType.TEXT_PLAIN).extended(true);
}
private void addHead(Resource.Builder resourceBuilder) {
resourceBuilder.addMethod("HEAD")
.handledBy(new Inflector<ContainerRequestContext, Response>() {
@Override
public Response apply(ContainerRequestContext context) {
return getHeadResponse(context);
}
}).produces(MediaType.TEXT_PLAIN).extended(true);
}
private static Response getOptionsResponse(ContainerRequestContext context) {
return Response.status(Response.Status.METHOD_NOT_ALLOWED).entity("No Options").build();
}
private static Response getHeadResponse(ContainerRequestContext context) {
return Response.status(Response.Status.METHOD_NOT_ALLOWED).entity("No Head").build();
}
}