当前位置: 首页 > 知识库问答 >
问题:

如何仅为一个方法或控制器类禁用泽西POJOMappingFeature

邢凌
2023-03-14

我在我的web.xml中打开了Jersey JSON POJOsMappingFeature特性,如下所示,以便在POJO和JSON之间进行转换:

<init-param>
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
</init-param>

我在其中一个控制器中有一个处理文件上传的方法。它接受多部分表单数据,从表单中提取文件输入字段,将其转换为InputStream并将文件保存到磁盘:

@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces("application/json")
public FileMetaData uploadFiles(FormDataMultiPart formDataMultiPart) {
    return new FileUploadHandler(SERVER_FILE_UPLOAD_LOCATION).upload(formDataMultiPart);
}

public FileMetaData upload(FormDataMultiPart formDataMultiPart) {
    FormDataBodyPart formFile = formDataMultiPart.getField("files");
    ContentDisposition contentDisposition = formFile.getContentDisposition();
    return saveFile(formFile.getValueAs(InputStream.class), contentDisposition.getFileName(), formFile.getMediaType().toString());
}

这适用于所有文件格式,除非我尝试上传JSON文件,formFile.getValueAs(InputStream.class)会抛出一个错误,抱怨字符串无法转换为InputStream。我假设这是因为泽西岛自动将JSON文件转换为字符串对象。那么,我该如何防止泽西岛仅仅为了这种方法或控制器而这样做呢?我的要求是,我需要将json文件本身保存为文件。

我试着在这方面搜索了很多,但最终得到的都是关于如何启用POJOMapping的文档,而不是有选择地禁用它。任何帮助都将非常感谢!

更新:我的自定义MessageBodyReader如下所示:

public class JSONMessageBodyReader implements MessageBodyReader<Object> {

private static final Logger log = LoggerFactory.getLogger(JSONMessageBodyReader.class);

@Override
public boolean isReadable(Class<?> type, Type genericType,
                          Annotation[] annotations, MediaType mediaType) {
    // return true;
    return mediaType.isCompatible(MediaType.APPLICATION_JSON_TYPE)
            || mediaType.isCompatible(MediaType.APPLICATION_OCTET_STREAM_TYPE);
            || mediaType.isCompatible(MediaType.TEXT_HTML_TYPE);
}

@Override
public Object readFrom(Class<Object> type, Type genericType,
                       Annotation[] annotations, MediaType mediaType,
                       MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
        throws IOException, WebApplicationException {
    if (log.isTraceEnabled()) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] chunk = new byte[256];
        int read = -1;
        while ((read = entityStream.read(chunk)) != -1) {
            baos.write(chunk, 0, read);
        }
        chunk = baos.toByteArray();
        String entity = new String(chunk);
        log.trace("the entity: " + entity);
        return ObjectMapperFactory.getInstance().readValue(chunk, 0, chunk.length, type);
    }

    return ObjectMapperFactory.getInstance().readValue(entityStream, type);
}

}

共有1个答案

琴俊人
2023-03-14

我最终通过使用较低级别的HttpServletRequest而不是泽西的FormDataParams处理上传的文件来解决我的要求,如下所示:

@POST
@Path("/upload")
@Consumes("multipart/form-data")
@Produces("application/json")
public FileMetaData uploadFiles(@Context ServletContext servletContext, @Context HttpServletRequest request) {
    return fileUploadHandler.upload(request, servletContext);
}


public FileMetaData upload(HttpServletRequest request, ServletContext servletContext) {
    FileMetaData fileMetaData = null;
    boolean isMultipart = ServletFileUpload.isMultipartContent(request);
    if (isMultipart) {
        LOGGER.info("About to save file on the server : {}", this.SERVER_UPLOAD_DIRECTORY);

        DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
        File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
        diskFileItemFactory.setRepository(repository);
        ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
        try {
            List<FileItem> files = servletFileUpload.parseRequest(request);
            Iterator<FileItem> iter = files.iterator();
            while(iter.hasNext()) {
                FileItem fileItem = iter.next();
                String fileName = fileItem.getName();
                if (fileName != null) {
                    fileName = FilenameUtils.getName(fileName);
                }
                String fileUploadDirectory = this.SERVER_UPLOAD_DIRECTORY;
                File uploadDirectory = new File(fileUploadDirectory);
                if(!uploadDirectory.exists()) {
                    uploadDirectory.mkdir();
                    LOGGER.info("creating directory {}", uploadDirectory.getAbsolutePath());
                }
                String fileUploadPath = fileUploadDirectory + File.separator + fileName;
                File fileToStore = new File(fileUploadPath);
                LOGGER.info("saved file {} on server", fileName);

                fileItem.write(fileToStore);
                long fileSize = fileToStore.length();
                String size = (fileSize > 1024) ? (fileSize/1024) + "Kb" : fileSize + "b";
                fileMetaData = new FileMetaData(fileName, size, true);
            }
        } catch (Exception e) {
            LOGGER.warn("error occurred while saving file to server : {}", e.getStackTrace());
            e.printStackTrace();
        }
    }

    else {
        LOGGER.info("No files to upload in request");
    }

    return fileMetaData;
}

这个解决方案非常适合我,尽管我觉得它是对我原来问题的一种破解。如果这个解决方案也能帮助其他人,我会很高兴。但是必须有人提供一种纯粹的方法来解决这个问题,而不涉及HttpServletRequest。我非常乐意尝试一下。谢谢!

 类似资料:
  • 我的webapp包含一个库,其中包含一个用注释的类。如果存在此类,我的webapp(部署为EAR中的WAR)将无法启动,并出现以下错误: 我根本没有使用jersey,我没有使用任何jax-rs服务和我的web。xml不包含与jersey相关的servlet。我不明白为什么weblogic在我的应用程序中初始化jersey并扫描jars相关的JAR。 我在互联网上找到的与此相关的大多数信息导致人们以

  • 问题内容: 使用SceneBuilder。我有2个阶段,每个阶段都有一个控制器: , 。 Stage1Controller: Stage2Controller: 这是使用2种方法 (称为in 方法)将这两个fxml文件加载到Main.java类中的方式: 该方法在第一阶段中用作方法,它在两个阶段都转换视图。 如何输入方法?谢谢 问题答案: “快速又脏”的方法是给的引用: 现在在您的主应用程序中:

  • 我刚刚学习了如何通过JAXB映射将单个复杂对象发送到基于Jersey的REST web服务:http://jersey.java.net/nonav/documentation/latest/xml.html#d4e820 然而,我想做得更多一点。 1)我可以有一个接受多个复杂对象的方法,所有这些对象都用JAXB注释吗?我的意思是: 泽西岛允许这样的方法吗?使用泽西岛/客户端,客户端对应部分会是什

  • 我不想让泽西做任何依赖注射。我认为有从Jersey到Guice的桥梁,但是基于我不能在这里显示的程序需求,我需要自己创建REST控制器实例,并向Guice请求它们。 我的问题:我怎样才能禁用泽西岛的依赖注入? 我当前正在使用注释。也许我可以改用注释,以为Jersey不会在寻找这些注释。但我还是宁愿把泽西岛的依赖注射关了。我怎么能那样做?

  • 问题内容: 在编写RESTful Web服务时,如果在客户端(当前是.NET胖客户端)上启用任何类型的缓存,则会遇到问题。默认情况下,Jersey不发送任何类型的缓存控制标头,因此客户端将自动缓存大多数页面(这似乎是有效的行为)。 我希望默认情况下,Jersey发送“ no-cache”的缓存控件,然后特别是响应将覆盖该缓存控件。 有没有办法用泽西岛做到这一点? 我发现RESTeasy可以使用@N

  • 有没有减少代码冗余的方法?