Java @根据条件生成注释

Java @根据条件生成注释,java,internet-explorer,conditional,jax-rs,blueimp,Java,Internet Explorer,Conditional,Jax Rs,Blueimp,对于一个新项目,我们在客户端使用jQuery组件,其中一个是blueImp文件上传器。我们正在愉快地编写代码,在Chrome和Firefox中一切都运行得很好。。。直到有人试图在Internet Explorer中打开该站点。显然,IE在使用这个上传组件时无法处理从服务器返回的应用程序/json——而且,它只是将其作为文件流式传输给用户。不管怎样,很多用户确实有这个问题(在他们的网站上有提到,在他们的bug reporter的其他地方也有提到) 然而,这里提到的大多数解决方法都是基于PHP的。我

对于一个新项目,我们在客户端使用jQuery组件,其中一个是blueImp文件上传器。我们正在愉快地编写代码,在Chrome和Firefox中一切都运行得很好。。。直到有人试图在Internet Explorer中打开该站点。显然,IE在使用这个上传组件时无法处理从服务器返回的应用程序/json——而且,它只是将其作为文件流式传输给用户。不管怎样,很多用户确实有这个问题(在他们的网站上有提到,在他们的bug reporter的其他地方也有提到)

然而,这里提到的大多数解决方法都是基于PHP的。我们在服务器端使用Java,更具体地说:JAX-RS。现在,JAX-RS有一个可爱的@products注释,它是。。。嗯,相当静态。我一直在翻阅文件,但一点也不明白。有没有办法给@products注释添加一个条件?清楚地说:我想在用户使用IE时返回text/plain(或类似的内容),在用户使用浏览器时返回application/json。。。EEEERRM,我是说,其他浏览器:-)


谢谢

使用Servlet过滤器应该可以工作。以下是一个(未经测试的)示例:

以及添加到web.xml中的配置。您需要将blah更改为您在其中放置上述类的包,并且url模式应该与您用于文件上载的url匹配

  <filter>
    <filter-name>ieFixFilter</filter-name>
    <filter-class>blah.IEFixFilter</filter-class>
  </filter>

  <filter-mapping>
    <filter-name>ieFixFilter</filter-name>
    <url-pattern>/upload/url/*</url-pattern>
  </filter-mapping>

固定过滤器
诸如此类的过滤器
固定过滤器
/上传/url/*

我最终通过编写自己的提供者解决了这个问题(这实际上是我在这里提问之前开始做的)。对于那些感兴趣的人(目前还不知道):编写自己的提供者需要两个步骤:

  • 将@Provider添加到类中,然后将@products()添加到类中
  • 实现MessageBodyWriter接口,覆盖必要的方法
我的代码是:

package com.mypackage;    

import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.mypackage.UploadResponse;

import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

@Produces("text/plain")
@Provider
public class UploadResponseProvider implements MessageBodyWriter<UploadResponse> {
    @Override
    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
         /* You could check the type here, or do some additional checks, but I can just return true, because if it is an UploadResponse (which is inferred via the generic), it's all ok */ 
        return true;
    }

    @Override
    public long getSize(UploadResponse uploadResponse, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return -1;
    }

    @Override
    public void writeTo(UploadResponse uploadResponse, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
        OutputStreamWriter writer = new OutputStreamWriter(entityStream);
        writer.write(new Gson().toJson(Lists.newArrayList(uploadResponse)));
        writer.flush();
    }

}
package com.mypackage;
导入com.google.common.collect.list;
导入com.google.gson.gson;
导入com.mypackage.UploadResponse;
导入javax.ws.rs.products;
导入javax.ws.rs.WebApplicationException;
导入javax.ws.rs.core.MediaType;
导入javax.ws.rs.core.MultivaluedMap;
导入javax.ws.rs.ext.MessageBodyWriter;
导入javax.ws.rs.ext.Provider;
导入java.io.IOException;
导入java.io.OutputStream;
导入java.io.OutputStreamWriter;
导入java.lang.annotation.annotation;
导入java.lang.reflect.Type;
@生成(“文本/纯文本”)
@提供者
公共类UploadResponseProvider实现MessageBodyWriter{
@凌驾
公共布尔值可写(类类型、类型genericType、注释[]注释、MediaType MediaType){
/*您可以在这里检查类型,或者做一些额外的检查,但我可以返回true,因为如果它是一个UploadResponse(通过泛型推断),那么一切都正常*/
返回true;
}
@凌驾
public long getSize(UploadResponse UploadResponse,类类型,类型genericType,注释[]注释,MediaType MediaType){
返回-1;
}
@凌驾
public void writeTo(UploadResponse UploadResponse、类类型、类型genericType、注释[]注释、MediaType MediaType、多值Map httpHeaders、OutputStream entityStream)引发IOException、WebApplicationException{
OutputStreamWriter writer=新的OutputStreamWriter(entityStream);
write(new Gson().toJson(Lists.newArrayList(uploadResponse));
writer.flush();
}
}
只是稍微解释一下这段代码:UploadResponse是我要返回的对象。这是一个简单的POJO,包含url、大小和名称字段,以及getter和setter

我了解到返回text/plain使blueImp jQuery Fileupload功能正常,因此这是一个用于上传响应的text/plain输出的提供者

我在这里要做的是创建一个JSON对象,将其放入一个列表中,然后将该列表写入响应。我正在创建一个上传响应列表,因为我的UI期望这样。顺便说一句,blueImp文件上传在默认情况下需要这样做。我们在JAX-RS上进行自动上传,并且硬限制为1个文件,因此我不必处理超过1个项目。请注意,在重用此代码时,可能需要进行一些修改

正如你所看到的,这就是我所做的,没有更多。其余的只是默认实现,因为在我的情况下,我不关心任何一个


一个小提示:不要关闭编写器。把它冲洗一下。关闭它将在写入响应之前关闭它

在这个后期阶段,这可能没有什么用处,但我最近有了这个确切的要求,这是一个非常简单的解决方案。假设您正在返回一个八位字节流,但如果出现问题,您希望只返回纯JSON

  • 不要在restful方法的声明中指定@products
  • 根据您的方法中发生的情况,您将要做这类事情

    return Response.status(200).entity(file).type(MediaType.APPLICATION_OCTET_STREAM).build();
    
  • 所以,例如,如果您需要提前返回一个JSON对象,而不是一个八位字节流,那么只需这样做

        return Response.status(500).entity(errorObject).type(MediaType.APPLICATION_JSON).build();
    
    重要的是,在构建响应时,您要指明MediaType


    希望这能对其他人有所帮助。

    也许是一个servlet过滤器,它可以更改IE的Accept头,然后JAX-RS可以在上面进行调度?或者IE截取并重写JAX-RS输出的过滤器?您也可以使用diff@Products使用两种不同的方法,然后删除到同一种方法。哇,快速回复,谢谢:-)@Thilo:这似乎是可行的,尽管我不太喜欢在过滤器中重写响应。但这似乎是一个值得考虑的问题。谢谢@subirkumarsao:嗯,这意味着我必须修改PostURL客户端-这意味着在JS中编写浏览器检测逻辑。这是一种可能性,但不是我喜欢的。不过,如果响应已经提交,您可能无法再更改内容类型标题。这一点很好。这总是让我抓狂。也许可以使用aspectj aop来做一些事情
        return Response.status(500).entity(errorObject).type(MediaType.APPLICATION_JSON).build();