1. 文件上传:实现项目中文件提交的核心步骤
文件上传是开发中必备的功能(如头像、附件上传),JavaWeb 中实现文件上传有严格的配置要求和固定步骤,缺一不可:
(1)前端表单配置要求
-
请求方式必须为
POST; -
表单属性
<form action="RoomInfoServlet?flag=save" method="post" enctype="multipart/form-data"> <button type="submit">上传</button> </form>enctype必须设置为multipart/form-data(表示以二进制流形式提交数据)。
(2)后端 Servlet 配置与核心代码
-
Servlet 上必须添加注解
@MultipartConfig,开启文件上传支持(可配置文件最大大小、存储目录等); -
通过
request.getPart("表单name值")获取上传文件; -
为避免文件名重复,通过时间戳 / UUID 生成新文件名,再通过
part.write()完成文件写入。@WebServlet("/RoomInfoServlet")
@MultipartConfig // 开启文件上传支持
public class RoomInfoServlet extends HttpServlet {
protected void save(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 1. 获取项目真实上传目录,不存在则创建
String realPath = this.getServletContext().getRealPath("/upload/");
File dir = new File(realPath);
if (!dir.exists()) dir.mkdirs();// 2. 获取上传的文件对象 Part part = request.getPart("pic"); // 3. 获取原始文件名,截取扩展名 String oldName = part.getSubmittedFileName(); String ext = oldName.substring(oldName.lastIndexOf(".")); // 4. 生成新文件名(时间戳+扩展名),避免重复 String newName = System.currentTimeMillis() + ext; // 5. 完成文件上传 part.write(realPath + newName); // 6. 可选:将文件路径存入数据库,供前端访问 // info.setPic("/upload/" + newName); }}
2. ServletConfig & ServletContext:配置与全局上下文对象
这两个对象是 Servlet 的核心配置对象,前者是单个 Servlet 的专属配置 ,后者是整个 Web 应用的全局对象,掌握它们的用法能让配置更灵活。
(1)ServletConfig:单个 Servlet 的配置参数对象
-
作用:读取当前 Servlet 的初始化参数,每个 Servlet 对应一个独立的 ServletConfig;
-
配置方式:xml 配置 / 注解
@WebInitParam; -
获取方式:
this.getServletConfig(),核心方法:getInitParameter(参数名)、getServletName()。// 注解方式配置Servlet初始化参数
@WebServlet(value = "/RoomInfoServlet", initParams = {
@WebInitParam(name = "status", value = "1:空,2:有客,3:空脏")
})
public class RoomInfoServlet extends HttpServlet {
@Override
public void init() throws ServletException {
// 获取ServletConfig对象
ServletConfig config = this.getServletConfig();
// 读取初始化参数
String status = config.getInitParameter("status");
System.out.println("房间状态配置:" + status);
}
}
(2)ServletContext:Web 应用的全局上下文对象
-
核心特性:整个 Web 应用只有一个 ServletContext 对象,项目启动时创建,停止时销毁,所有 Servlet 共享;
-
4 种获取方式:
ServletContext context = request.getServletContext(); ServletContext context = session.getServletContext(); ServletContext context = this.getServletConfig().getServletContext(); ServletContext context = this.getServletContext(); -
核心用法:
- 读取全局初始化参数 (web.xml 中
<context-param>配置); - 全局域存值 / 取值(
setAttribute()/getAttribute()),如监听器统计在线人数; - 获取项目真实路径、虚拟路径、服务器信息等。
// 读取全局参数
String email = this.getServletContext().getInitParameter("email");
// 获取项目真实根路径
String realPath = this.getServletContext().getRealPath("/");
// 全局域存值
this.getServletContext().setAttribute("onlineCount", 10); - 读取全局初始化参数 (web.xml 中
3. 监听器 Listener:监听 Web 对象状态变化,实现个性化业务
监听器是监听 Web 组件对象状态变化 的组件,能在对象创建 / 销毁、属性增删改时触发自定义逻辑,核心监听ServletRequest、HttpSession、ServletContext三大对象,Day7 重点讲解实战高频用法。
(1)监听器的核心配置
- 实现对应监听接口,重写事件方法;
- 注册方式:注解
@WebListener/web.xml 中<listener>配置(二选一)。
(2)经典实战:监听器统计在线人数
利用HttpSessionListener监听 Session 的创建(用户上线)和销毁(用户下线),结合ServletContext全局域存储在线人数,是面试和开发的经典案例:
java
运行
@WebListener // 注解注册监听器
public class OnlineCountListener implements HttpSessionListener {
private int onlineCount = 0; // 在线人数
// 监听Session创建:用户首次访问,创建Session时触发(上线+1)
@Override
public void sessionCreated(HttpSessionEvent se) {
onlineCount++;
// 存入全局域,供所有Servlet/JSP获取
se.getSession().getServletContext().setAttribute("onlineCount", onlineCount);
}
// 监听Session销毁:Session超时/手动销毁时触发(下线-1)
@Override
public void sessionDestroyed(HttpSessionEvent se) {
if (onlineCount > 0) onlineCount--;
se.getSession().getServletContext().setAttribute("onlineCount", onlineCount);
}
}
(3)监听器其他高频用法
3. JSP 内置对象:无需声明,直接使用的页面神器
JSP 内置对象(隐藏对象)是 JSP 容器自动创建的对象,无需手动 new,可直接在 JSP 页面使用 ,共 9 个,核心围绕请求、响应、会话、域对象展开,简化 JSP 页面的 Java 代码开发,是 JSP 的核心知识点。
9 大内置对象全表(含类型 + 核心作用)
表格
| 内置对象 | 对应类型 | 核心作用 | 作用域 |
|---|---|---|---|
| request | HttpServletRequest | 获取请求参数、请求头、请求转发 | 请求(一次请求) |
| response | HttpServletResponse | 重定向、设置响应头、文件下载 | 一次响应 |
| out | JspWriter | 向页面输出内容(替代 System.out) | 页面 |
| session | HttpSession | 会话跟踪,存储用户登录信息、购物车 | 会话(一次浏览器会话) |
| application | ServletContext | 全局域,存储整个应用的共享数据 | 应用(项目启动到停止) |
| pageContext | PageContext | 页面顶级域,获取其他 8 个内置对象 | 页面(仅当前 JSP) |
| page | Object | 代表当前 JSP 页面本身,相当于 this | 页面 |
| config | ServletConfig | 读取当前 JSP 对应的 Servlet 配置参数 | 页面 |
| exception | Throwable | 处理 JSP 页面异常,仅在isErrorPage=true的页面使用 |
页面 |
高频用法示例
jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<%-- 1. request获取前端参数 --%>
用户名:<%= request.getParameter("username") %><br>
<%-- 2. session存储/获取登录信息 --%>
<% session.setAttribute("user", "张三"); %>
当前登录用户:<%= session.getAttribute("user") %><br>
<%-- 3. application获取全局在线人数 --%>
当前在线人数:<%= application.getAttribute("onlineCount") %><br>
<%-- 4. out输出内容 --%>
<% out.print("这是out对象输出的内容"); %>
</body>
</html>
4. Web 全局配置与项目部署:web.xml 终极总结 + 项目发布
(1)web.xml 核心全局配置(一站式梳理)
web.xml 是 JavaWeb 的部署描述符文件,Day8 对其做了最终系统总结,核心配置如下,覆盖开发所有场景:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="4.0">
<!-- 1. 全局初始化参数 -->
<context-param>
<param-name>email</param-name>
<param-value>admin@126.com</param-value>
</context-param>
<!-- 2. 欢迎页(默认首页,按顺序匹配) -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
<!-- 3. 错误页面(404/500,统一异常展示) -->
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/500.jsp</location>
</error-page>
<!-- 4. Session全局超时时间(单位:分钟) -->
<session-config>
<session-timeout>20</session-timeout>
</session-config>
<!-- 5. 过滤器/监听器/Servlet配置(前文已讲,此处省略) -->
</web-app>
(2)JavaWeb 项目两种部署方式
开发完成后,需要将项目部署到 Tomcat 服务器才能访问,主流两种部署方式,简单高效:
<!-- hotel_system.xml -->
<Context path="/hotel_system" docBase="D:\workspace\JavaWeb\out\artifacts\HotelSystem_war_exploded"/>
5. MVC 模式:JavaWeb 的核心架构思想
Day8 最后梳理了 JavaWeb 的MVC 设计模式 ,这是后续学习 SSM、SpringBoot 的基础,核心是分层开发,解耦代码,将项目分为 Model、View、Controller 三层,各司其职。
(1)MVC 三层划分
(2)MVC 工作流程(核心)
(3)MVC 模式的核心优势
ServletContextListener:监听项目启动 / 停止,如项目启动时加载配置文件、启动定时任务;ServletRequestListener:监听请求的创建 / 销毁,如统计每个请求的处理时间。
1. HTTP 请求头解析:获取客户端隐藏信息
请求头是客户端发送请求时,附带的客户端环境信息、请求偏好 等数据(浏览器默认携带,前端不可见),服务器可通过request.getHeader()解析,实现个性化业务(如判断浏览器类型、限制访问设备、获取客户端 IP)。
(1)核心获取方法
@WebServlet("/HeadServlet")
public class HeadServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
// 获取所有请求头名称,返回枚举类型
Enumeration<String> headerNames = req.getHeaderNames();
// 遍历所有请求头,输出名和值
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String value = req.getHeader(name);
out.println(name + ":" + value + "<br>");
}
}
}
(2)开发中高频的请求头字段
表格
| 请求头字段 | 核心作用 | 实战场景 |
|---|---|---|
| User-Agent | 客户端软件环境(操作系统、浏览器版本) | 判断访问设备(PC / 手机)、限制浏览器访问 |
| Cookie | 客户端携带的 Cookie 键值对 | 会话跟踪,获取用户登录状态 |
| Host | 请求的主机和端口 | 域名解析、多域名部署 |
| Accept | 客户端可接收的响应数据类型 | 动态返回不同格式数据(HTML/JSON) |
| Referer | 请求的来源地址 | 防盗链、统计访问来源 |
2. 文件下载:实现服务器文件向客户端的传输
文件下载是文件上传的配套功能,核心是通过 IO 流读取服务器文件,写入响应输出流,并通过响应头告诉浏览器 "以下载方式处理数据",而非直接打开。
核心实战代码
@WebServlet("/DownloadServlet")
public class DownloadServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// 1. 获取要下载的文件路径(前端传递的文件相对路径)
String filePath = req.getParameter("path");
// 2. 获取文件名,解决中文文件名乱码
String fileName = filePath.substring(filePath.lastIndexOf("/") + 1);
fileName = new String(fileName.getBytes("utf-8"), "ISO-8859-1");
// 3. 设置响应头:告诉浏览器以下载方式处理
resp.setContentType("application/octet-stream"); // 二进制流数据
resp.setHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");
// 4. 获取服务器文件真实路径
String realPath = this.getServletContext().getRealPath("/") + filePath;
// 5. IO流实现文件下载:读服务器文件 → 写入响应输出流
FileInputStream fis = new FileInputStream(realPath);
OutputStream os = resp.getOutputStream();
byte[] buffer = new byte[1024]; // 缓冲区,提高效率
int len;
while ((len = fis.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
// 关闭流
fis.close();
os.close();
}
}
关键注意点
- 响应头
Content-Disposition的attachment表示 "附件下载",是实现下载的核心; - 中文文件名必须做编码转换 (
ISO-8859-1),否则会出现乱码; - 使用缓冲区(byte [])读取文件,避免一次性读取大文件导致内存溢出。
- 直接复制法 :将项目的 war 包 / 解压后的目录,复制到 Tomcat 的
webapps目录下,启动 Tomcat 自动部署; - XML 配置法 :在 Tomcat 的
conf/Catalina/localhost目录下,创建自定义名.xml,配置项目路径和真实目录,无需复制文件,适合开发调试: path:项目访问路径(如http://localhost:8080/hotel_system);docBase:项目在本地的真实目录路径。- View(视图层) :负责页面展示,接收用户输入,对应JSP、HTML、CSS、JS;
- Controller(控制层) :负责接收请求,分发业务,对应Servlet;
- Model(模型层) :负责业务逻辑处理和数据操作,对应实体类、Service、Dao(操作数据库)。
- 用户通过 View 层发送请求(如点击按钮);
- Controller 层(Servlet)接收请求,解析请求参数;
- Controller 层调用 Model 层的 Service/Dao,处理业务逻辑(如查询数据库、操作文件);
- Model 层将处理结果返回给 Controller 层;
- Controller 层根据结果,跳转到对应的 View 层;
- View 层渲染结果,响应给用户。
- 解耦:各层职责明确,修改一层不影响其他层(如改页面不用动业务代码);
- 易维护:代码结构清晰,便于定位问题和后续迭代;
- 易分工:前端开发负责 View 层,后端开发负责 Controller 和 Model 层,提高开发效率。