【问题标题】:Create a new web resource with Jersey使用 Jersey 创建新的 Web 资源
【发布时间】:2013-09-03 12:42:29
【问题描述】:

我现在正在学习使用 Java 创建 Web 服务。准确地说,是带有 JAX-RS 的 RESTful Webservices 及其实现 Jersey。我正在 Eclipse 中开发一个动态 Web 项目。

Web 服务应该允许用户从他的计算机上传文件(这可以工作),然后保存在服务器上(也可以工作)。上传/保存后,服务应返回指定文件的 URI,并可用于与 Internet 上的其他人共享文件(这不起作用)。

Jersey 框架可以做到这一点吗?

我试图对这个主题进行一些研究,但由于我对这个主题相当陌生,所以我似乎在搜索错误的关键字。

这就是我想出的:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;

import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import com.sun.jersey.core.header.FormDataContentDisposition;
import com.sun.jersey.multipart.FormDataParam;


@Path("/file")
public class Upload {

@Context
private UriInfo uriInfo;
@Context 
private ServletContext context;

@GET
@Path("/upload")
@Produces(MediaType.TEXT_HTML)
public String getUploadForm() {

    StringBuilder htmlPageBuilder = new StringBuilder();

    htmlPageBuilder.append("<html>");
    htmlPageBuilder.append("<body>");
    htmlPageBuilder.append("<h1>File upload</h1>");
    htmlPageBuilder.append("<form action=\"rest/file/processed\" method=\"post\" enctype=\"multipart/form-data\">");
    htmlPageBuilder.append("<p>");
    htmlPageBuilder.append("Select a file : <input type=\"file\" name=\"file\" size=\"45\" />");
    htmlPageBuilder.append("</p>");
    htmlPageBuilder.append("<input type=\"submit\" value=\"Upload file\" />");
    htmlPageBuilder.append("</form>");
    htmlPageBuilder.append("</body>");
    htmlPageBuilder.append("</html>");      

    return htmlPageBuilder.toString();      
}

@POST
@Path("/rest/file/processed")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(@FormDataParam("file") InputStream uploadInputStream, 
                           @FormDataParam("file") FormDataContentDisposition fileDetail) {

    String uploadedFilePath = "C:\\Tomcat\\Data\\";
    uploadedFilePath += fileDetail.getFileName();

    //write the file onto the server
    File uploadedFile = this.writeToFile(uploadInputStream, uploadedFilePath);
    String uploadedFileName = uploadedFile.getName();

    String output = "File uploaded to: " + uploadedFilePath + uploadedFileName; 

    URI location = uriInfo.getAbsolutePathBuilder().path(uploadedFileName).build();

    //return Response.ok(output).build();
    return Response.created(location).entity(Entity.text(output)).build();
}

private File writeToFile(InputStream uploadInputStream, String uploadedFilePath) {

    File uploadedFile = new File(uploadedFilePath);

    try {

        OutputStream out = new FileOutputStream(uploadedFile);

        int read = 0;

        byte[] bytes = new byte[1024];

        while((read = uploadInputStream.read(bytes)) != -1) {

            out.write(bytes, 0, read);
        }

        out.flush();
        out.close();
    } 
    catch (FileNotFoundException e) {

        e.printStackTrace();
    } 
    catch (IOException e) {

        }
    }
}

所以对于POST方法返回Response为OK。作为 URI 的另一个响应甚至没有显示(我注释掉的部分)。我认为原因是资源不存在。

非常感谢任何帮助。

编辑

我尝试了 Aradom 提供的解决方案,并包含了 genson 库。现在我得到一个新的NullPointerException。这是堆栈跟踪:

Severe: Servlet.service() for servlet [RestServlet] in context with path [/FirstRestWebService] threw exception
java.lang.NullPointerException
    at com.owlike.genson.reflect.BeanViewDescriptorProvider$BeanViewPropertyFactory.createAccessor(BeanViewDescriptorProvider.java:122)
    at com.owlike.genson.reflect.BeanPropertyFactory$CompositeFactory.createAccessor(BeanPropertyFactory.java:49)
    at com.owlike.genson.reflect.BaseBeanDescriptorProvider.provideMethodAccessors(BaseBeanDescriptorProvider.java:187)
    at com.owlike.genson.reflect.BaseBeanDescriptorProvider.provideBeanPropertyAccessors(BaseBeanDescriptorProvider.java:94)
    at com.owlike.genson.reflect.AbstractBeanDescriptorProvider.provide(AbstractBeanDescriptorProvider.java:106)
    at com.owlike.genson.convert.BasicConvertersFactory.provide(BasicConvertersFactory.java:109)
    at com.owlike.genson.convert.BasicConvertersFactory.create(BasicConvertersFactory.java:74)
    at com.owlike.genson.convert.BasicConvertersFactory.create(BasicConvertersFactory.java:56)
    at com.owlike.genson.reflect.AbstractBeanDescriptorProvider$ContextualFactoryDecorator.create(AbstractBeanDescriptorProvider.java:79)
    at com.owlike.genson.reflect.AbstractBeanDescriptorProvider$ContextualFactoryDecorator.create(AbstractBeanDescriptorProvider.java:68)
    at com.owlike.genson.convert.ChainedFactory.create(ChainedFactory.java:93)
    at com.owlike.genson.convert.ChainedFactory.create(ChainedFactory.java:80)
    at com.owlike.genson.convert.ChainedFactory.create(ChainedFactory.java:93)
    at com.owlike.genson.convert.ChainedFactory.create(ChainedFactory.java:80)
    at com.owlike.genson.convert.ChainedFactory.create(ChainedFactory.java:93)
    at com.owlike.genson.convert.ChainedFactory.create(ChainedFactory.java:80)
    at com.owlike.genson.convert.CircularClassReferenceConverterFactory.create(CircularClassReferenceConverterFactory.java:58)
    at com.owlike.genson.convert.CircularClassReferenceConverterFactory.create(CircularClassReferenceConverterFactory.java:22)
    at com.owlike.genson.Genson.provideConverter(Genson.java:196)
    at com.owlike.genson.Genson.serialize(Genson.java:340)
    at com.owlike.genson.ext.jaxrs.GensonJsonConverter.writeTo(GensonJsonConverter.java:91)
    at com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:306)
    at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1479)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1391)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1381)
    at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416)
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:538)
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:716)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

我尝试查看 genson 库,看看是否能找到有关此异常的信息。到目前为止,我非常感谢您的帮助。

【问题讨论】:

  • 可以在局域网内共享上传的文件吗?
  • 您使用的是哪个版本的genson?尝试版本 0.98

标签: java web-services rest jersey uri


【解决方案1】:

继续编写您的代码。只需对您的 POST 方法进行这个小改动

URI location = ...
String output = ...
return Response.created(location).entity(Entity.text(output)).build();

【讨论】:

  • 您好,感谢您的快速回复。现在我遇到了一个例外。这是堆栈跟踪: javax.ws.rs.WebApplicationException: com.sun.jersey.api.MessageException: Java 类 javax.ws.rs.client.Entity 和 Java 类型类 javax.ws.rs 的消息体编写器.client.Entity 和 MIME 媒体类型 application/octet-stream 未找到
  • 尝试将 Genson 库添加到您的类路径 code.google.com/p/genson。它是一个 jsonjava 流和数据绑定 api。它与球衣很好地集成在一起,要让您运行,您需要 0 配置。 Jersey 检测到该库在您的类路径中,并通过委托给 Genson 来启用 json 映射。
  • 我添加了库,但出现了新异常。更新了我的问题,使其包含堆栈跟踪。
【解决方案2】:

您好,很抱歉回复晚了,但我花了一些时间才回到这个项目。现在我更有经验了,我知道仙女座的答案是正确的。

不过,我会尝试更彻底地解释我是如何解决这个问题的。这可能对遇到同样问题的人有用。

借用我自己的代码:

//get the context of the servlet
@Context
private ServletContext servletContext;
@Context 
private UriInfo uriInfo;

@POST
@Path("/rest/file/processed")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(@FormDataParam("file") InputStream uploadInputStream, 
                           @FormDataParam("file") FormDataContentDisposition fileDetail) {


    //create a new folder structure in the webapp folder
    //webapp
    //  |
    //  -> temp
    //       |
    //       -> tempFiles
    //get the path of the tempFiles folder
    String uploadedFilePath = servletContext.getRealPath("/temp/tempFiles/");
    //add the file name to the path
    uploadedFilePath += fileDetail.getFileName();

    //write the file onto the server
    File uploadedFile = this.writeToFile(uploadInputStream, uploadedFilePath);

    URI fileUri = null;

    try {

        fileUri = new URI(uriInfo.getBaseUri().toString() + "temp/tempFiles/" + uploadedFile.getName());
        //if you have any additional url-patterns in your web.xml file you might have to remove them i.e.
        //fileUri = new URI(uriInfo.getBaseUri().toString().replace("/url-pattern", "") + "temp/tempFiles/" + uploadedFile.getName());
    } 
    catch (URISyntaxException e) {

        uploadedFile.delete();

        //create a fitting response
        return Response.status(404).entity("Could not create the URI: " + fileUri).build();
    }

    //create a fitting response
    return Response.status(201).entity("Successfully uploaded the file. \n Resource created at: <a href=" + fileUri + ">" + fileUri + "</a>").build();
}

请记住,此文件只会临时保存在服务器的目录中。如果您想要永久存储,您可以将其保存到不同的目录或通过 FTP 将其发送到文件服务器(我现在正在尝试解决这个问题)。

我不知道这是否是最好的解决方案,但到目前为止它对我有用。

您好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-07-24
    • 1970-01-01
    • 1970-01-01
    • 2012-11-30
    • 1970-01-01
    • 2019-03-12
    • 1970-01-01
    相关资源
    最近更新 更多