从接口设置 Jersey 响应状态代码而不返回 Response
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);
}
由于它创建了一个新资源,因此如果它 returned 状态代码 201 是合适的,但目前它 returns 200。
我发现如何设置状态代码的唯一方法是使用方法 return a javax.ws.rs.core.Response
并将其设置在那里,但我真的不希望我所有的接口都 return 一个通用的 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
注解。从那里,可以获取状态代码并将其设置在响应中。
因为它是一个名称绑定过滤器,它只会被用它注释的方法调用。查看更多 here.
然后要使用它,只需在方法中添加注释即可。
public interface ITestResource {
@GET
@Status(code=201)
String get();
}
如果您需要添加一些自定义 headers,也可以对 headers 执行相同的操作。
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);
我正在尝试设置以下 Jersey REST 端点的响应状态
@Path("/roles")
public interface IRoleService {
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
Role create(Role role);
}
由于它创建了一个新资源,因此如果它 returned 状态代码 201 是合适的,但目前它 returns 200。
我发现如何设置状态代码的唯一方法是使用方法 return a javax.ws.rs.core.Response
并将其设置在那里,但我真的不希望我所有的接口都 return 一个通用的 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
注解。从那里,可以获取状态代码并将其设置在响应中。
因为它是一个名称绑定过滤器,它只会被用它注释的方法调用。查看更多 here.
然后要使用它,只需在方法中添加注释即可。
public interface ITestResource {
@GET
@Status(code=201)
String get();
}
如果您需要添加一些自定义 headers,也可以对 headers 执行相同的操作。
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);