JSP是Java Web开发历史上最重要的一项技术之一,它的全称是JavaServer Pages,即Java服务器页面。简单来说,JSP是一种允许开发者在HTML页面中嵌入Java代码片段的技术,服务器在接收到请求后会将这些页面转换并编译成Servlet执行,最终把动态生成的HTML内容返回给浏览器。要理解JSP,需要从它的定位、运行原理、语法体系以及实际用法几个方面逐步展开。

一、JSP到底是什么,它和Servlet是什么关系
很多初学者第一次接触JSP时,会误以为它是一门独立的编程语言,其实不是。JSP本质上是Servlet的一种简化写法。我们知道,用纯Servlet输出一个HTML页面非常繁琐,你需要写大量类似out.print("<html>...")这样的语句,页面结构完全被Java代码淹没,前端人员和后端人员很难协作。
JSP的出现就是为了解决这个问题。它把思路反过来:默认写的就是HTML,只在需要动态内容的地方嵌入Java代码。这样一来,页面设计师可以直接维护HTML部分,开发者专注于嵌入的Java逻辑,分工清晰了很多。
从底层机制看,JSP文件在第一次被访问时会被容器(比如Tomcat)翻译成一个Java源文件,然后编译成class文件并加载执行。你可以在Tomcat的work目录下找到这些自动生成的源码,打开后会发现它其实就是一个继承了HttpJspBase的Servlet类。所以说,JSP是Servlet的模板化封装,两者在运行时是同一个东西,只是书写形式不同。
二、JSP的核心语法组成
JSP的语法主要由脚本元素、指令和动作标签三部分构成,理解这三块就能看懂绝大多数JSP页面。
第一类是脚本元素,包括三种写法。<% %>里可以写任意Java语句,叫脚本片段;<%= %>用于把表达式的值直接输出到页面上,叫表达式;<%! %>用于声明成员变量或方法,叫声明。第二种声明方式在实际开发中很少使用,因为它可能引发线程安全问题,多个请求并发访问同一个JSP时共享这些成员变量。
第二类是指令,常用的是<%@ page %>、<%@ include %>和<%@ taglib %>。page指令用于设置页面的编码、导入的包、错误页面等属性;include指令用于在编译期把另一个文件的内容合并进来,适合做公共头部和底部;taglib指令用于引入标签库,比如JSTL。
第三类是JSP提供的九大内置对象,这也是它方便的地方。在JSP页面里可以直接使用request、response、session、application、out等对象,不需要自己创建。这些对象其实是翻译后的Servlet类中预先定义好的成员变量,容器在调用服务方法时已经帮你初始化完毕了。
三、一个简单的JSP登录页面实例
下面通过一个登录页面的例子来看JSP的实际写法。页面接收用户提交的用户名和密码,通过request内置对象获取参数,再根据判断结果输出不同的提示信息。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>用户登录</title>
</head>
<body>
<h2>用户登录</h2>
<form action="login.jsp" method="post">
用户名:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
<input type="submit" value="登录"/>
</form>
<%
// 从request内置对象中获取表单参数
String username = request.getParameter("username");
String password = request.getParameter("password");
if (username != null && password != null) {
if ("admin".equals(username) && "123456".equals(password)) {
out.println("<p style='color:green'>欢迎您," + username + "</p>");
} else {
out.println("<p style='color:red'>用户名或密码错误</p>");
}
}
%>
</body>
</html>这个例子体现了JSP的典型用法:表单部分是纯HTML,处理逻辑用脚本片段嵌入。需要注意request.getParameter返回的参数在POST方式下不会有中文乱码问题,前提是page指令里的charset设置正确。如果出现乱码,可以在获取参数前调用request.setCharacterEncoding("UTF-8")。
实际项目中不建议把业务逻辑直接写在JSP里,更好的做法是让Servlet负责处理请求和业务调用,JSP只负责展示数据,这就是早期常说的MVC模式。配合JSTL标签库和EL表达式后,甚至可以把JSP里的Java代码完全消除,页面的可维护性会大幅提升。比如用${username}这种EL表达式取代<%= username %>,写法更简洁,也天然避免了空指针问题。
四、JSP的现状与适用场景
必须承认,JSP已经不是当前主流的前后端交互方式了。随着前后端分离架构的普及,前端用Vue、React等框架渲染页面,后端只提供JSON接口,JSP的使用场景被明显压缩。不少新项目直接采用Spring Boot加模板引擎的方案,即使需要服务端渲染,大家也更倾向于选择Thymeleaf这类语法更现代的模板。
不过JSP依然有其价值。首先,大量遗留系统仍在运行JSP页面,维护这类系统必须掌握JSP;其次,一些内部管理系统、教学演示项目对前端交互要求不高,JSP加JSTL的开发效率其实很不错;另外,理解JSP的翻译和执行机制,对深入理解Servlet容器的工作原理很有帮助。
总结一下,JSP是建立在Servlet之上的动态页面技术,核心机制是翻译加编译,语法核心是脚本元素、指令和内置对象。它见证了Java Web发展的黄金时代,即便今天不再是首选,作为Java开发者了解它的工作原理仍然是必要的功课。如果你正在学习Java Web,建议先扎实掌握Servlet,再学JSP,最后过渡到Spring MVC和前后端分离,这条学习路线能让你对整个技术演进有清晰的认识。