在泽西岛处理不匹配的内容类型

Handling mismatching Content-Type in Jersey

我不断收到以下形式的错误:

java.lang.IllegalStateException: The @FormParam is utilized when the content type of the request entity is not application/x-www-form-urlencoded

所以我尝试防御这个错误,如下:

@Path("auth")
@Produces(MediaType.APPLICATION_JSON)
public class Auth {

@POST
@Path("login")
@Consumes(MediaType.WILDCARD)
public Response create()
{
    return Response.status(Status.UNSUPPORTED_MEDIA_TYPE).build();
}

@POST
@Path("login")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response create(@Valid @NotNull @FormParam("username") final String username,
        @Valid @NotNull @FormParam("password") final String password)
{

但是,这并不能解决问题。生成的 FINE 日志消息非常垃圾。

我有两个问题:

  1. 为什么当 Content-Type 为空时不调用更通用的方法?
  2. 当实际方法与其@Consumes 不匹配时,如何防止调用实际方法以避免日志垃圾邮件?

环境是运行Grizzly 2.3.28,Jersey 2.25.1,MOXy 2.7.1

我认为如果您制作自定义注释来验证内容类型并且只接受 MediaType.APPLICATION_FORM_URLENCODED

,您就可以让它工作

如果 MediaType.APPLICATION_FORM_URLENCODED 内容类型不存在,您可以使用 ContainerRequestFilter 读取 headers 和 return 400 错误请求。

声明注解接口

@NameBinding
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface ContentTypeFilterAnnotation {}

将其实现为 ContainerRequestFilter

@Provider
@ContentTypeFilterAnnotation
public class ContentTypeFilter implements ContainerRequestFilter {

  @Override
  public void filter(ContainerRequestContext requestContext) throws IOException {
    MultivaluedMap<String,String> headers = requestContext.getHeaders();
    List<String> contentType = headers.get(HttpHeaders.CONTENT_TYPE);
    // if MediaType.APPLICATION_FORM_URLENCODED is not present in the content type header, return a 400
    if(contentType == null || !contentType.contains(MediaType.APPLICATION_FORM_URLENCODED)) {
      // build your error as you want it
      Response.ResponseBuilder responseBuilder = Response.serverError();
      Response response = responseBuilder.status(Response.Status.BAD_REQUEST).build();
      requestContext.abortWith(response);
    }
  }
}

然后将其应用到您的端点

@POST
@Path("login")
@ContentTypeFilterAnnotation
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response create(@Valid @NotNull @FormParam("username") final String username,
                       @Valid @NotNull @FormParam("password") final String password) {
    ...
}

如果内容类型不是 MediaType.APPLICATION_FORM_URLENCODED

,这应该可以防止 Jersey 尝试获取表单参数