JSP文件在服务器上跑不起来,八成是导入路径写错了。这事我见过太多次,新手把<%@ page import="java.util.*" %>当成万能钥匙,结果连自己写的类都导不进去。
先分清两种导入。一种是JSP内置的page指令,另一种是引入外部JSP片段。前者管Java类,后者管页面结构。很多人混着用,不报错才怪。
导入Java类,写法固定:<%@ page import="java.util.List, java.util.ArrayList" %>。多个类用逗号隔开,或者写多个page指令也行。但有个坑——默认导入的包只有java.lang、javax.servlet这些,你自定义的Bean类,必须写全限定名,或者先import再使用。我见过有人把Bean放在com.mycompany.model包里,页面里直接写User user = new User(),Tomcat直接甩ClassNotFoundException。这时候要么<%@ page import="com.mycompany.model.User" %>,要么写全名com.mycompany.model.User user = new com.mycompany.model.User()。后者丑,但应急管用。
再说引入外部JSP文件。静态导入用<%@ include file="header.jsp" %>,动态导入用<jsp:include page="header.jsp" />。差别在哪?静态导入是编译期把文件内容复制进来,相当于把代码粘贴到当前页面,两个页面共享同一个局部变量作用域——你要是定义了同名变量,直接编译冲突。动态导入是运行期把请求转发过去,输出结果再嵌回来,各自独立,互不干扰。选哪个?如果header里只是纯HTML展示,用静态include,省一次请求开销。如果header里要读session或者动态数据,用动态include,灵活。
实际操作里还有个隐蔽问题。有人把JSP文件放在/WEB-INF/views/下面,然后想用<%@ include file="/WEB-INF/views/header.jsp" %>。路径写对了,但容器可能报404——因为/WEB-INF目录默认禁止直接访问。这时候要么把公共片段挪到/common/下,要么改用JSTL的<c:import>标签。我踩过这个坑,当时排查了半天,最后发现是路径权限问题,不是代码逻辑错。
还有个细节很多人忽略:page指令必须放在JSP文件最顶部,且前面不能有任何空白字符或输出。如果你在<%@ page %>前面写了空行或注释,某些严格容器会报错。别问为什么,规范就是这么定的。我习惯在文件第一行写page指令,紧接着写include指令,中间不留空行。
最后说个土办法。如果你不确定导入是否生效,在页面里临时输出<%= Class.forName("com.mycompany.model.User") %>,能打印出类对象就说明导入成功。要是抛ClassNotFoundException,检查你的类路径——WEB-INF/classes下有没有编译好的.class文件,或者WEB-INF/lib里有没有对应jar包。这比盯着import语句瞎猜快多了。
JSP导入不是背语法,是理解容器怎么加载类、怎么合并文件。路径错了就改路径,作用域冲突就拆文件。别指望一个import解决所有问题,它只是告诉容器“我要用这些东西”,至于东西在哪、能不能用,那是另一回事。