繁体   English   中英

从接口设置Jersey响应状态代码,而不返回响应

[英]Setting a Jersey response status code from interface without returning Response

我正在尝试设置以下Jersey REST端点的响应状态

@Path("/roles")
public interface IRoleService {

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    Role create(Role role);

}

由于它创建了新资源,因此如果返回状态码201,但当前返回200,则是合适的。

我发现如何设置状态代码的唯一方法是让该方法返回javax.ws.rs.core.Response并将其设置在那里,但我真的不希望我的所有接口都返回通用Response而不是实际响应对象(在这种情况下为Role )。

一种方法是创建自定义注释,并使用响应过滤器设置状态。 例如

注解

@NameBinding
@Target({METHOD, TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Status {
    int DEFAULT_CODE = 0;

    int code() default DEFAULT_CODE;
}

ContainerResponseFilter

@Status
@Provider
public class StatusFilter implements ContainerResponseFilter {

    @Context
    private ResourceInfo info;

    @Override
    public void filter(ContainerRequestContext req, ContainerResponseContext res) throws IOException {
        Status status = getInterfaceAnnotation(info.getResourceMethod());
        if (status != null) {
            int code = status.code();
            if (code != Status.DEFAULT_CODE && res.getStatus() == 200) {
                res.setStatus(code);
            }
        }
    }

    private static Status getInterfaceAnnotation(Method resourceMethod) {
        String methodName = resourceMethod.getName();
        Class<?>[] paramTypes = resourceMethod.getParameterTypes();
        Class<?> iface = resourceMethod.getDeclaringClass().getInterfaces()[0];
        Method ifaceMethod;
        try {
            ifaceMethod = iface.getDeclaredMethod(methodName, paramTypes);
        } catch (NoSuchMethodException e) {
            return null;
        }
        return ifaceMethod.getAnnotation(Status.class);
    }
}

在过滤器中,我们获得带有ResourceInfo的方法,并进行一些反射以获得@Status批注。 从那里,可以获取状态代码并在响应上进行设置。

由于它是一个“名称绑定”过滤器,因此只会为使用它进行注释的方法调用。 在这里查看更多。

然后使用它,只需将注释添加到方法中即可。

public interface ITestResource {
    @GET
    @Status(code=201)
    String get();
}

如果您需要添加一些自定义标头,则可以对标头执行相同的操作。

Removed ElementType.Type.

    @NameBinding
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Status {
        int DEFAULT_CODE = 0;
        int code() default DEFAULT_CODE;
    }

statusFilter class:

    @Provider
    public class StatusFilter implements ContainerResponseFilter {

        private static Logger logger = LoggerFactory.getLogger(StatusFilter.class);

        @Context
        private ResourceInfo resourceInfo;

        @Override
        public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
            Status status = resourceInfo.getResourceMethod().getAnnotation(Status.class);
            if(status!=null){
                int code = status.code();
                if(code != Status.DEFAULT_CODE && responseContext.getStatus() == 200) {
                    responseContext.setStatus(code);
                }
            }
        }
    }

Then use it in the resource interface method declaration

@POST
@Status(code = 201)
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
GetUserResponse createUser(UserRequest userRequest);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM