You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JAX-RS/Jersey/TomEE文件上传报HTTP 415错误求助

解决TomEE下JAX-RS文件上传的415 Unsupported Media Type问题

你的问题根源很明确:TomEE默认集成的是Apache CXF作为JAX-RS实现,而你使用的是Jersey的Multipart API,两者之间的冲突导致MultiPartFeature无法正常生效,从而无法处理multipart/form-data请求。Tomcat之所以正常,是因为它本身不自带JAX-RS实现,你的Jersey包可以完全接管请求处理。

下面提供两种可行的解决方案,根据你的需求选择:


方案一:切换到CXF原生Multipart API(推荐,适配TomEE环境)

既然TomEE内置了CXF,直接使用CXF的Multipart组件是最稳妥的方式,避免包冲突:

  1. 替换依赖:把pom.xml中的Jersey multipart依赖换成CXF的:
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-rs-multipart</artifactId>
    <version>3.3.6</version> <!-- 版本要和你的TomEE版本匹配,比如TomEE 8对应CXF 3.3.x -->
    <scope>provided</scope> <!-- TomEE已内置,无需打包到WAR -->
</dependency>
  1. 修改API代码的导入:将Jersey的Multipart相关注解替换为CXF的:
// 替换原来的Jersey导入
import org.apache.cxf.jaxrs.ext.multipart.FormDataContentDisposition;
import org.apache.cxf.jaxrs.ext.multipart.FormDataParam;

// 其余代码保持不变,@Consumes(MediaType.MULTIPART_FORM_DATA)和方法逻辑无需修改
@Path("/admin/upload")
@RequestScoped
public class UploadApiImpl {
    @POST
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response uploadFile(
            @FormDataParam("file") InputStream in,
            @FormDataParam("file") FormDataContentDisposition info) throws IOException {
        // 你的文件处理逻辑不变
        File upload = new File(info.getFileName());
        if (upload.exists()){
            String message = "file: " + upload.getName() + " already exists";
            return Response.status(Response.Status.CONFLICT).entity(message).build();
        } else {
            Files.copy(in, upload.toPath());
            return Response.status(Response.Status.OK).build();
        }
    }

    @GET
    public Response uploadFile(){
        return Response.status(Response.Status.OK).build();
    }
}
  1. 调整配置:
    • 如果你用Application类,继承标准的javax.ws.rs.core.Application而非Jersey的ResourceConfig,确保注册你的API类:
      import javax.ws.rs.ApplicationPath;
      import javax.ws.rs.core.Application;
      import java.util.HashSet;
      import java.util.Set;
      
      @ApplicationPath("/mb-portal-service/api/v1")
      public class MyApplication extends Application {
          @Override
          public Set<Class<?>> getClasses() {
              Set<Class<?>> classes = new HashSet<>();
              classes.add(UploadApiImpl.class);
              // CXF默认已注册MultipartProvider,无需额外添加
              return classes;
          }
      }
      
    • 如果你用web.xml,替换为CXF的Servlet配置:
      <web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
               xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
          <servlet>
              <servlet-name>CXF JAX-RS Servlet</servlet-name>
              <servlet-class>org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet</servlet-class>
              <init-param>
                  <param-name>jaxrs.serviceClasses</param-name>
                  <param-value>org.ftc.UploadApiImpl</param-value>
              </init-param>
              <load-on-startup>1</load-on-startup>
          </servlet>
          <servlet-mapping>
              <servlet-name>CXF JAX-RS Servlet</servlet-name>
              <url-pattern>/mb-portal-service/api/v1/*</url-pattern>
          </servlet-mapping>
      </web-app>
      

方案二:在TomEE中禁用CXF,强制使用Jersey

如果你坚持使用Jersey,需要让TomEE放弃自带的CXF JAX-RS实现:

  1. 修改TomEE配置:在TomEE的conf/system.properties文件中添加以下配置:
openejb.jaxrs.proxy=false
openejb.jaxrs.implementation=none

这会禁用TomEE自动加载的CXF JAX-RS组件。

  1. 恢复Jersey配置:
    • 确保pom.xml中保留Jersey的multipart依赖:
      <dependency>
          <groupId>org.glassfish.jersey.media</groupId>
          <artifactId>jersey-media-multipart</artifactId>
          <version>2.27</version>
      </dependency>
      
    • 在你的Application类中正确注册MultiPartFeature:
      @ApplicationPath("/mb-portal-service/api/v1")
      public class Application extends ResourceConfig {
          public Application() {
              packages("org.ftc");
              this.register(MultiPartFeature.class); // 打开这个注册语句
          }
      }
      
    • 或者在web.xml中确保Jersey的Servlet配置正确:
      <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
          <servlet>
              <servlet-name>Jersey Web Application</servlet-name>
              <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
              <init-param>
                  <param-name>jersey.config.server.provider.packages</param-name>
                  <param-value>org.ftc</param-value>
              </init-param>
              <init-param>
                  <param-name>jersey.config.server.provider.classnames</param-name>
                  <param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
              </init-param>
              <load-on-startup>1</load-on-startup>
          </servlet>
          <servlet-mapping>
              <servlet-name>Jersey Web Application</servlet-name>
              <url-pattern>/mb-portal-service/api/v1/*</url-pattern>
          </servlet-mapping>
      </web-app>
      

额外注意事项

  • 检查TomEE版本与依赖版本的兼容性:比如TomEE 8对应CXF 3.3.x,TomEE 9对应CXF 3.5.x,避免版本不匹配导致的异常。
  • 如果你同时使用web.xml和Application类配置JAX-RS,可能会出现冲突,建议只保留一种配置方式。

内容的提问来源于stack exchange,提问作者Stefan Đogo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 12:12:52