使用javax.servlet-api-3.1.0调用getSubmittedFileName()出现NoSuchMethodError
问题原因
这个NoSuchMethodError本质是编译时依赖与运行时依赖版本不一致:
- 编译阶段你使用的
javax.servlet-api-3.1.0中,Part类确实包含getSubmittedFileName()方法; - 但运行Web应用的Tomcat版本不支持Servlet 3.1规范——只有Tomcat 8.0及以上版本才实现Servlet 3.1,Tomcat 7及以下对应Servlet 3.0,其中
Part类并没有这个方法,因此运行时会抛出方法不存在的异常。
解决方案
方案1:升级Tomcat至8.0及以上版本
直接将运行环境更换为Tomcat 8.0/8.5/9.0(这些版本均支持Servlet 3.1规范),运行时即可正常找到getSubmittedFileName()方法。
方案2:不升级Tomcat,手动解析文件名
如果暂时无法升级Tomcat,可以通过解析Part的Content-Disposition请求头来获取文件名,替代getSubmittedFileName()方法:
修改clickUpload()方法中的文件名获取逻辑:
public String clickUpload() { try { // 替换原有的getSubmittedFileName()调用 String fileName = getFileName(getUploadFile()); long uploadFileSize = getUploadFile().getSize(); InputStream is = getUploadFile().getInputStream(); byte[] uploadBytes = new byte[(int)uploadFileSize]; int bytesRead = is.read(uploadBytes); setNotesText(new String(uploadBytes)); is.close(); } catch (IOException ioe) { ioe.printStackTrace(); } return "display"; } // 手动解析文件名的工具方法 private String getFileName(Part part) { String contentDisposition = part.getHeader("Content-Disposition"); String[] tokens = contentDisposition.split(";"); for (String token : tokens) { if (token.trim().startsWith("filename")) { return token.substring(token.indexOf("=") + 1).trim().replace("\"", ""); } } return null; }
方案3:修正依赖的scope配置
确保javax.servlet-api依赖的scope设置为provided,避免将API包打包到war文件中——服务器本身已提供Servlet API的实现,打包进去会与服务器版本冲突:
Maven配置示例:
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency>
Gradle配置示例:
providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
额外提示
判断文件是否为.zip格式,除了通过文件名后缀,更可靠的方式是检查文件魔数(文件头字节)——.zip文件的前4个字节为50 4B 03 04,可避免用户修改文件名后缀绕过判断。
内容的提问来源于stack exchange,提问作者DougMH
相关产品推荐
相关产品推荐

