学JSP从写第一个动态页面开始 Java服务器端脚本基础从零搭建可运行的Web应用
为什么是JSP?
说实话,现在网上说JSP是”过时技术”的人挺多的,但我还是想跟你聊聊它。为啥?因为JSP是Java Web开发的入门基石。理解了JSP,再去看Spring MVC、Thymeleaf这些现代框架,你会突然发现:”哦,原来原理是这样的!”
而且,很多地方还在用JSP——传统企业系统、银行系统、老项目维护。你不可能完全绕开它。更重要的是,JSP让你直接看到Java代码和HTML混写的样子,这对理解”服务器端渲染”这个概念超级有帮助。
今天,我们不急着讲原理,先动手。做一个能跑起来的页面,比看十篇理论文章都管用。
第一步:搭建开发环境
在你写第一行代码之前,需要准备好三样东西。
1. JDK安装
JDK是Java开发工具包,必须得有。建议下载JDK 11或JDK 17,这两个是长期支持版本。
安装后,打开命令行(Windows是CMD或PowerShell,Mac/Linux是终端),输入:
java -version
如果看到类似这样的输出,就说明安装成功了:
openjdk version "17.0.8" 2023-07-18
OpenJDK Runtime Environment (build 17.0.8+7)
OpenJDK 64-Bit Server VM (build 17.0.8+7, mixed mode)
2. IDE选择
你可以用IntelliJ IDEA(推荐社区版,免费够用)、Eclipse,或者VS Code配合插件。我推荐IntelliJ IDEA,因为它对Java Web项目的支持最友好,自动生成项目结构不费劲。
3. Tomcat服务器
JSP文件需要运行在支持Java Servlet的容器里,Tomcat是最 popular 的选择。
去Apache Tomcat官网下载Tomcat 10.x版本(注意:Tomcat 10要求JDK 11+)。下载后解压到一个没有中文、没有空格的路径,比如:
D:\apache-tomcat-10.1.15
或者Mac上:
/Users/yourname/apache-tomcat-10.1.15
配置一个环境变量 CATALINA_HOME 指向这个路径,然后在命令行启动Tomcat:
Windows:
%CATALINA_HOME%\bin\startup.bat
Mac/Linux:
$CATALINA_HOME/bin/startup.sh
启动成功后,打开浏览器访问 http://localhost:8080,看到Tomcat的欢迎页面,说明服务器跑起来了。
第二步:创建你的第一个JSP项目
打开IntelliJ IDEA,选择 New Project,类型选 Java Enterprise(或者你版本叫 Web Application)。
填写项目名称,比如 FirstJspApp,然后下一步。IDE会自动帮你创建一个标准的Web项目结构。
项目的文件夹结构大致是这样的:
FirstJspApp/
├── src/
│ └── (Java源码放这里)
├── web/
│ └── WEB-INF/
│ ├── web.xml (Web配置文件)
│ └── web.xml.bak (备份文件,不用管)
│ └── index.jsp (你的第一个JSP页面)
└── pom.xml (Maven依赖管理文件)
关键路径 web/WEB-INF/web.xml 是Web应用的配置文件,必须存在,否则Tomcat会报错。
第三步:写你的第一个JSP文件
右键点击 web 文件夹,选择 New → JSP/JSPX,文件名为 index.jsp。
IDE会生成一个空白的JSP文件,内容大概是:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>我的第一个JSP页面</title>
</head>
<body>
<h1>Hello, JSP!</h1>
</body>
</html>
现在,你需要理解这几行代码在说什么。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
这行叫”页面指令”,告诉服务器:
- 这个文件要输出HTML内容(
contentType="text/html") - 编码用UTF-8,避免中文乱码
- 语言是Java
<html>...<body>...</body></html>
这是标准的HTML结构。你可以放心地写HTML标签,就像写普通网页一样。
<h1>Hello, JSP!</h1>
这也是HTML。但现在,我们要加入Java代码了——这才是JSP的灵魂。
第四步:加入Java脚本元素
JSP允许你在HTML中直接写Java代码。有三种方式:
1. 脚本片段 <% %>
这是最常用的写法。把Java代码放在 <% 和 %> 之间。
修改 index.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.Date" %>
<html>
<head>
<title>我的第一个动态页面</title>
</head>
<body>
<h1>当前服务器时间:</h1>
<p>
<%
Date now = new Date();
out.println(now.toLocaleString());
%>
</p>
<hr>
<h2>欢迎信息</h2>
<p>
<%
String userName = "小明";
out.println("你好," + userName + "!欢迎来到JSP的世界。");
%>
</p>
</body>
</html>
注意这一行:
<%@ page import="java.util.Date" %>
这是导入Java类的指令。JSP默认不会自动导入 java.util.*,所以你需要显式导入。
运行这个页面(在IDE里配置好Tomcat,点击运行按钮),浏览器会显示当前时间,每次刷新都会变化。这就是”动态”的意义——内容是由服务器实时生成的,不是写死的HTML。
2. 表达式 <%= %>
如果你只是想输出一个值,可以用表达式,比脚本片段更简洁:
<%= new Date().toLocaleString() %>
这行代码等价于:
<%
out.println(new Date().toLocaleString());
%>
表达式后面不能加分号,因为JSP会自动帮你处理输出。
3. 声明 <%! %>
声明用于定义类的成员变量或方法,在整个JSP文件内有效:
<%!
private String getGreeting(String name) {
return "你好," + name + "!";
}
private int counter = 0;
%>
声明的代码会被转换成Servlet类的成员,而不是放在 _jspService() 方法里。这意味着如果你在声明中定义了一个变量,它在多次请求之间可能会共享(取决于服务器实现)。
第五步:理解JSP的底层原理
很多人觉得JSP很神秘,其实它没那么复杂。
当你的浏览器请求一个 .jsp 文件时,Tomcat服务器会做以下几件事:
- 翻译阶段:把
.jsp文件翻译成.java文件(一个Servlet) - 编译阶段:把
.java文件编译成.class文件 - 加载执行阶段:加载这个类,创建实例,处理请求
你可以在Tomcat的 work 目录下找到生成的Java文件。路径通常是:
%CATALINA_HOME%/work/Catalina/localhost/你的项目名/
打开生成的Java文件,你会发现它大致长这样:
public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
javax.servlet.jsp.JspSourceImports {
public void _jspService(final javax.servlet.http.HttpServletRequest request,
final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
final org.apache.jasper.runtime.PageContextImpl pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _out = null;
javax.servlet.jsp.pageContext.ResponsePageContext _jspx_page_context = null;
try {
response.setContentType("text/html;charset=UTF-8");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_out = out;
out.write('\n');
out.write('<html>\n<head>\n<title>我的第一个动态页面</title>\n</head>\n<body>\n');
out.write("\n <h1>当前服务器时间:</h1>\n <p>\n ");
out.print(new Date().toLocaleString());
out.write('\n </p>\n');
out.write("\n</body>\n</html>");
} catch (Throwable {
// 错误处理...
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
看到没?你的JSP代码最终变成了标准的Java Servlet类。这就是为什么JSP能写Java代码——因为它本质上就是Servlet。
第六步:使用JSP内置对象
JSP提供了9个内置对象,你不需要手动创建,可以直接使用。最常用的几个:
| 对象 | 类型 | 用途 |
|---|---|---|
request |
HttpServletRequest | 获取请求参数 |
response |
HttpServletResponse | 设置响应 |
out |
JspWriter | 输出内容到页面 |
session |
HttpSession | 存储用户会话数据 |
application |
ServletContext | 应用级别数据共享 |
pageContext |
PageContext | 页面上下文 |
来看一个实际例子。假设你有一个表单,用户输入名字后点击提交,页面显示欢迎信息:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>用户登录示例</title>
</head>
<body>
<h2>请输入你的名字</h2>
<form method="GET" action="welcome.jsp">
名字:<input type="text" name="username" placeholder="请输入...">
<input type="submit" value="提交">
</form>
<%
String name = request.getParameter("username");
if (name != null && !name.isEmpty()) {
session.setAttribute("userName", name);
response.sendRedirect("welcome.jsp");
}
%>
</body>
</html>
然后创建 welcome.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>欢迎页面</title>
</head>
<body>
<%
String name = (String) session.getAttribute("userName");
if (name == null) {
response.sendRedirect("index.jsp");
}
%>
<h1>欢迎,<%= name %>!</h1>
<p>你已经在系统中登录。</p>
<a href="index.jsp">返回</a>
</body>
</html>
这段代码展示了:
request.getParameter()获取表单参数session.setAttribute()保存会话数据session.getAttribute()读取会话数据response.sendRedirect()重定向页面
第七步:用JSP连接数据库
JSP真正的威力在于能连接数据库。下面是一个完整的例子,展示如何从数据库中读取数据并显示在页面上。
首先,你需要一个数据库。这里用MySQL为例,创建一张简单的用户表:
CREATE DATABASE jsp_db;
USE jsp_db;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO users (username, email) VALUES
('张三', 'zhangsan@example.com'),
('李四', 'lisi@example.com'),
('王五', 'wangwu@example.com');
然后,在项目中引入MySQL驱动。在 pom.xml 中添加依赖:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
接下来创建 users.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.sql.*" %>
<html>
<head>
<title>用户列表</title>
<style>
table { border-collapse: collapse; width: 80%; margin: 20px 0; }
th, td { border: 1px solid #ddd; padding: 12px; text-align: left; }
th { background-color: #4CAF50; color: white; }
tr:nth-child(even) { background-color: #f2f2f2; }
h1 { color: #333; }
</style>
</head>
<body>
<h1>用户列表</h1>
<%
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
// 加载数据库驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 建立连接
String url = "jdbc:mysql://localhost:3306/jsp_db?useSSL=false&serverTimezone=UTC";
String user = "root";
String password = "你的密码";
conn = DriverManager.getConnection(url, user, password);
// 执行查询
stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT * FROM users ORDER BY id DESC");
// 输出表格
%>
<table>
<tr>
<th>ID</th>
<th>用户名</th>
<th>邮箱</th>
<th>注册时间</th>
</tr>
<%
// 遍历结果集
while (rs.next()) {
%>
<tr>
<td><%= rs.getInt("id") %></td>
<td><%= rs.getString("username") %></td>
<td><%= rs.getString("email") %></td>
<td><%= rs.getTimestamp("create_time") %></td>
</tr>
<%
}
} catch (Exception e) {
out.println("<p style='color:red;'>数据库错误:" + e.getMessage() + "</p>");
} finally {
// 关闭资源
try { if (rs != null) rs.close(); } catch (Exception e) {}
try { if (stmt != null) stmt.close(); } catch (Exception e) {}
try { if (conn != null) conn.close(); } catch (Exception e) {}
}
%>
</table>
<p><a href="index.jsp">返回首页</a></p>
</body>
</html>
注意几个细节:
数据库驱动版本:MySQL Connector/J 8.x 的驱动类名是
com.mysql.cj.jdbc.Driver,不是老版本的com.mysql.jdbc.Driver。连接字符串:
useSSL=false和serverTimezone=UTC是针对MySQL 8.x的配置,避免时区和SSL警告。资源关闭:在
finally块中关闭ResultSet、Statement、Connection,这是好习惯,防止连接泄漏。内嵌Java代码和HTML交替:注意
<% %>和<%= %>的使用位置,这是JSP最典型也是最重要的写法。
第八步:理解JSP的编译和部署流程
为了让项目能够被Tomcat正确运行,你需要确保项目结构正确,并且配置好服务器。
项目结构
在IntelliJ IDEA中创建好项目后,结构应该是:
FirstJspApp/
├── src/
│ └── (Java源文件)
├── web/
│ ├── WEB-INF/
│ │ └── web.xml
│ ├── index.jsp
│ ├── welcome.jsp
│ └── users.jsp
└── pom.xml
web.xml配置
web.xml 是Web应用的部署描述符,最简单的配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app 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_4_0.xsd"
version="4.0">
<display-name>JSP入门项目</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
这段配置告诉Tomcat:
- 这个Web应用的显示名称
- 默认打开哪个页面(
index.jsp)
配置Tomcat运行
在IntelliJ IDEA中:
- 点击右上角的 Edit Configurations
- 点击 + 号,选择 Tomcat Server → Local
- 在 Server 标签页中:
- Application server 选择你安装的Tomcat路径
- URL 填
http://localhost:8080
- 在 Deployment 标签页中:
- 点击 + 号,选择 Artifact
- 选择你的项目(应该类似
FirstJspApp:war exploded)
- 点击 Apply → OK
- 点击运行按钮
启动成功后,浏览器自动打开 http://localhost:8080/FirstJspApp/,你应该能看到你的首页。
第九步:JSP的三种注释方式
JSP支持和HTML、Java类似的注释,但各有不同用途:
HTML注释(发送给客户端)
<!-- 这是HTML注释,浏览器可以查看到 -->
这种注释会出现在HTML源码中,用户右键”查看网页源代码”可以看到。
JSP注释(不发送给客户端)
<%-- 这是JSP注释,不会被发送到客户端 --%>
这种注释不会被编译,客户端看不到。用于隐藏敏感的Java代码逻辑。
Java注释(在脚本中)
<%
// 单行Java注释
/* 多行Java注释 */
Date now = new Date();
%>
第十步:常见问题和解决
问题1:中文乱码
如果你发现页面上的中文显示为乱码,检查以下几点:
- JSP文件的编码是否设置为UTF-8
<%@ page contentType="text/html;charset=UTF-8" %>是否包含charset- 浏览器是否使用了正确的编码(一般Chrome会自动处理)
问题2:ClassNotFoundException: com.mysql.cj.jdbc.Driver
这通常是因为:
- MySQL驱动JAR没有正确添加到项目中
- 驱动类名写错了(注意是小写
cj)
问题3:Tomcat启动报错,项目无法访问
检查:
- Tomcat是否正确安装并启动
- 项目是否配置了Artifact
- web.xml是否存在且格式正确
问题4:JSP文件中不能写分号
在 <%= %> 表达式中,末尾不要加分号。分号是Java语句的结束符,但表达式不需要。
总结:你学到了什么
到今天,你已经从零开始:
- 安装了JDK、IntelliJ IDEA和Tomcat
- 创建了第一个JSP项目
- 学会了JSP的三种脚本元素:
<% %>、<%= %>、<%! %> - 理解了JSP的底层原理(翻译成Servlet)
- 使用了JSP内置对象(request、session、out等)
- 完成了数据库连接和数据显示
- 配置了Tomcat并成功运行了项目
这还不够,但足够让你迈出第一步。JSP的学习不是一蹴而就的,你需要多动手、多尝试。改一改代码,看看会发生什么,这才是最好的学习方式。
下一个目标可以是:学习JSP的EL表达式和JSTL标签库,那会让你的页面代码更简洁、更专业。但那是下一篇文章的事了。
现在,打开你的IDE,运行起来,看到那个”Hello, JSP!“的那一刻——你会觉得一切都值得。
