Multipart配置无法在奇怪的情况下为动态添加的servlet工作

时间:2013-10-10 13:40:08

标签: java jsp java-ee servlets jboss

JSP:

<!DOCTYPE html>
<form action="/{insert your context here}/p/hello" method="post" enctype="multipart/form-data">
  <input type="file" name="data">
  <button>Go</button>
</form>

的Servlet

@WebServlet
public class HelloServlet extends HttpServlet {
    private static final long serialVersionUID = 1;
    @Override
    protected void doPost( HttpServletRequest request, HttpServletResponse response )
    throws IOException, ServletException {
        if ( request.getPart( "data" ) != null ) {
            response.getWriter().print( "It worked\n\n" );
        } else {
            response.getWriter().print( "IT IS NOT WORKING!\n\n" );
        }
    }
}

过滤

@WebFilter( filterName = "hello" )
public class HelloFilter implements Filter {
    @Override
    public void init( FilterConfig config ) throws ServletException {}

    @Override
    public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain )
    throws IOException, ServletException {
        request
            .getRequestDispatcher( "/hello" )
            .include( request, response );

        request
            .getRequestDispatcher( "/hello.jsp" )
            .include( request, response );
    }

    @Override
    public void destroy() {}
}

监听

@WebListener
public class HelloListener implements ServletContextListener {
    @Override
    public void contextInitialized( ServletContextEvent event ) {
        ServletContext context = event.getServletContext();
        Dynamic hello = context.addServlet( "hello", HelloServlet.class );
        hello.addMapping( "/hello" );
        hello.setMultipartConfig( getMultiPartConfig() );
    }
    @Override
    public void contextDestroyed( ServletContextEvent event ) {}

    private MultipartConfigElement getMultiPartConfig() {
        String location = "";
        long maxFileSize = -1;
        long maxRequestSize = -1;
        int fileSizeThreshold = 0;
        return new MultipartConfigElement(
            location,
            maxFileSize,
            maxRequestSize,
            fileSizeThreshold
        );
    }
}

我的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:jsp="http://java.sun.com/xml/ns/javaee/jsp" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>{insert the context here}</display-name>
  <jsp-config>
    <jsp-property-group>
      <url-pattern>*.jsp</url-pattern>
      <page-encoding>UTF-8</page-encoding>
    </jsp-property-group>
  </jsp-config>
  <filter-mapping>
    <filter-name>hello</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

当我提交表单时,我收到输出“它不工作!”在答复的第一行。如果我将请求的路径从/{insert your context here}/p/hello更改为/{insert your context here}/hello则可行,为什么?

使用:
JBoss EAP 6.1

2 个答案:

答案 0 :(得分:2)

我能够使用Tomcat 7.0.30重现该问题。无论是使用@MultipartConfig注释动态还是静态配置“HelloServlet”,都会出现同样的问题。

我还测试了Jetty版本8.1.13.v20130916,它在两种情况下都运行良好; /{context}/p/hello/{context}/hello,未经任何修改。

如果您要像这样修改HelloListener

Dynamic hello = context.addServlet( "hello", HelloServlet.class );
hello.addMapping( "/hello" );
hello.addMapping( "/p/hello" );
hello.setMultipartConfig( getMultiPartConfig() );

它会起作用,但我怀疑这会破坏你想要做的目的。另一种选择是修改过滤器以根据需要动态添加新映射:

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {

    // dynamically add mappings
    ServletContext context = request.getServletContext();
    ServletRegistration registration = context.getServletRegistration("hello");
    registration.addMapping("/<dynamic path>/hello");

    request.getRequestDispatcher("/hello").include(request, response);
    request.getRequestDispatcher("/hello.jsp").include(request, response);
}

似乎tomcat / jboss仅根据原始请求路径是否与为多部分支持配置的servlet匹配而为请求启用多部分支持,而它应该启用基于支持的支持在它正在处理的请求的路径上(可能已被RequestDispatcher“包含”。

它看起来像一个tomcat / jboss错误,但你必须仔细阅读servlet规范才能找到,否则你可以使用Jetty。

答案 1 :(得分:0)

我随机地看到了这一点,同时也解决了你的两难困境。给定提供的注释,将使用{在此处插入您的上下文} / hello而不是{在此处插入您的上下文} / p / hello来访问该页面。看看Multiple folders in Java EE 6 web pages。它非常相似,BalusC提供了一些很好的信息。希望有所帮助。