
📃个人主页:编程的一拳超人
⛺️ 欢迎关注:👍点赞 👂🏽留言 😍收藏 💞 💞 💞
于高山之巅,方见大河奔涌;于群峰之上,更觉长风浩荡。 ——《人民日报》
目录
第二章 Servlet篇
2.1 Servlet概述
Servlet是Java EE中处理Web请求的核心组件,运行于Web容器(如Tomcat)中,遵循MVC架构中的控制器角色。
2.1.1 Servlet生命周期
-
实例化(Instantiation)
- 容器启动时或首次请求时创建Servlet实例(单例模式,默认仅创建一次)。
- 示例:
MyServlet servlet = new MyServlet();
(容器自动创建,无需手动实例化)。
-
初始化(Initialization)
- 调用
init(ServletConfig config)
方法,读取配置参数(如config.getInitParameter("url")
)。
public class MyServlet extends HttpServlet { private String dbUrl; @Override public void init() throws ServletException { dbUrl = getInitParameter("dbUrl"); } }
- 调用
-
服务处理(Service)
- 接收请求后调用
service(HttpServletRequest req, HttpServletResponse resp)
,根据请求方法分发到doGet()
、doPost()
等方法。
protected void doGet(HttpServletRequest req, HttpServletResponse resp) { resp.getWriter().println("Handle GET request"); }
- 接收请求后调用
-
销毁(Destruction)
- 容器关闭时调用
destroy()
,释放资源(如数据库连接)。
- 容器关闭时调用
2.1.2 线程安全问题
- 单例非线程安全:Servlet实例被所有请求共享,若存在全局变量可能引发线程安全问题。
- 解决方案:
- 避免全局变量:使用局部变量或方法参数存储请求数据。
- ThreadLocal:为每个线程创建独立副本。
private ThreadLocal<String> userThreadLocal = new ThreadLocal<>(); protected void doGet(HttpServletRequest req, HttpServletResponse resp) { userThreadLocal.set(req.getParameter("user")); // 使用userThreadLocal.get() }
- 同步块:对共享资源加锁(如
synchronized(this)
),但影响性能。
2.1.3 与MVC框架的关系
- Struts1的
ActionServlet
、Spring MVC的DispatcherServlet
均基于Servlet扩展,作为前端控制器处理请求分发。
2.2 九大隐式对象
Servlet/JSP中预定义的九大隐式对象,按功能分类:
类别 | 对象 | 作用 |
---|---|---|
输入/输出 | request 、response 、out | request 获取请求参数;response 设置响应;out 输出响应内容(如out.println() ) |
作用域通信 | session 、application 、pageContext | session 存储会话数据;application 存储全局数据;pageContext 访问页面作用域 |
Servlet相关 | page 、config | page 指向当前Servlet实例(等价于this );config 获取Servlet配置参数 |
错误处理 | exception | 存储异常对象(仅在错误页面有效) |
示例:使用request
获取参数,session
存储登录用户
String username = request.getParameter("username");
session.setAttribute("currentUser", username);
2.3 page和pageContext的区别
-
page:
- 类型:
javax.servlet.jsp.HttpJspPage
,等价于当前Servlet实例(this
)。 - 作用范围:仅限当前JSP页面,访问Servlet的方法和属性。
- 类型:
-
pageContext:
- 类型:
javax.servlet.jsp.PageContext
,用于访问四大作用域(page、request、session、application)。 - 功能:通过
setAttribute(String name, Object value, int scope)
存储数据,作用域通过PAGE_SCOPE
、REQUEST_SCOPE
等常量指定。
pageContext.setAttribute("msg", "Hello", PageContext.REQUEST_SCOPE);
- 类型:
2.4 GET和POST的区别
特性 | GET | POST |
---|---|---|
用途 | 获取资源(安全幂等) | 提交数据(非幂等,可能修改状态) |
请求体 | 无请求体,参数附在URL后(如?key=value ) | 有请求体,支持大文件上传 |
安全性 | 低(参数可见于URL) | 高(参数在请求体中) |
缓存 | 可被缓存 | 通常不被缓存 |
URL长度限制 | 浏览器限制(如Chrome约8KB) | 无固定限制(取决于服务器配置) |
示例:登录接口用POST避免密码暴露
<!-- GET不安全,密码可见于URL -->
<form method="GET" action="/login">
用户名:<input name="username">
密码:<input name="password">
</form>
<!-- POST安全,密码在请求体中 -->
<form method="POST" action="/login">
用户名:<input name="username">
密码:<input name="password">
</form>
2.5 转发与重定向的区别
特性 | 转发(forward) | 重定向(redirect) |
---|---|---|
数据共享 | 共享request 作用域数据 | 不共享,需通过URL或session 传递 |
地址栏 | 不变(始终显示原始URL) | 改变(显示新URL) |
性能 | 高(一次请求) | 低(两次请求) |
适用场景 | 同应用内跳转 | 跨应用跳转或需要更新浏览器历史 |
代码示例:
- 转发:
request.getRequestDispatcher("/newPage.jsp").forward(request, response);
- 重定向:
response.sendRedirect("/newPage.jsp");
2.6 四大作用域介绍
作用域从小到大:page < request < session < application
-
page(页面作用域)
- 生命周期:JSP页面处理期间有效。
- 示例:
pageContext.setAttribute("msg", "Page Scope", PageContext.PAGE_SCOPE);
-
request(请求作用域)
- 生命周期:一次请求内有效(转发时共享)。
- 应用:表单处理后传递临时数据到视图层。
request.setAttribute("errorMsg", "用户名错误"); request.getRequestDispatcher("/error.jsp").forward(request, response);
-
session(会话作用域)
- 生命周期:用户会话期间有效(默认30分钟,可通过
session.setMaxInactiveInterval(600)
设置)。 - 应用:存储登录用户信息。
session.setAttribute("userId", 123);
- 生命周期:用户会话期间有效(默认30分钟,可通过
-
application(应用作用域)
- 生命周期:应用启动到停止,所有用户共享。
- 应用:存储全局配置或计数器。
application.setAttribute("appVersion", "1.0");
2.7 session和cookie的区别
特性 | session | cookie |
---|---|---|
存储位置 | 服务器内存(或分布式缓存) | 客户端浏览器(内存/硬盘) |
安全性 | 高(需通过session ID访问) | 低(可被禁用或篡改) |
大小限制 | 无固定限制(受服务器内存影响) | 通常≤4KB(单个cookie) |
生命周期 | 会话期间或超时(默认30分钟) | 会话cookie(浏览器关闭失效)或持久化(指定过期时间) |
依赖关系 | 依赖cookie存储session ID | 可不依赖session(独立存储数据) |
示例:Session依赖Cookie存储JSESSIONID
// 服务器生成session ID
String sessionId = session.getId();
// 客户端cookie存储JSESSIONID
Cookie cookie = new Cookie("JSESSIONID", sessionId);
response.addCookie(cookie);
2.8 request和session的区别
- 生命周期:
request
:一次请求响应周期(从请求到达至响应结束)。session
:从用户首次访问到会话超时或关闭。
- 数据共享范围:
request
:仅当前请求内有效(包括转发的多个页面)。session
:跨请求有效(同一用户多次请求共享)。
- 内存占用:
request
:轻量,处理完即释放。session
:若存储大量数据可能占用服务器内存,需定期清理。
2.9 报错状态码
状态码 | 含义 | 典型场景 |
---|---|---|
200 OK | 请求成功 | 正常响应数据 |
301 Moved Permanently | 永久重定向(SEO友好) | 域名变更(如旧域名永久指向新域名) |
302 Found | 临时重定向 | 登录后跳转首页 |
403 Forbidden | 权限拒绝 | 用户无访问权限 |
404 Not Found | 资源未找到 | 访问不存在的URL |
500 Internal Server Error | 服务器内部错误 | 代码异常(如空指针) |
503 Service Unavailable | 服务不可用 | 服务器过载或维护中 |
示例:自定义404页面
<!-- web.xml配置 -->
<error-page>
<error-code>404</error-code>
<location>/error/404.jsp</location>
</error-page>
2.10 常见协议及默认端口号
协议 | 端口 | 用途 |
---|---|---|
HTTP | 80 | 超文本传输(明文,不安全) |
HTTPS | 443 | 加密HTTP(通过SSL/TLS) |
FTP | 21 | 文件传输协议 |
SSH | 22 | 安全远程登录 |
Tomcat | 8080 | 默认Web服务端口 |
MySQL | 3306 | 数据库连接 |
Oracle | 1521 | 数据库监听端口 |
注意:Tomcat端口可通过conf/server.xml
修改,生产环境建议将HTTP端口改为80,HTTPS端口443。
2.11 对过滤器的理解
过滤器(Filter)用于预处理请求和后处理响应,实现功能如编码转换、权限验证、日志记录。
2.11.1 生命周期
- init(FilterConfig config):初始化,读取配置参数(如
config.getInitParameter("encoding")
)。 - doFilter(ServletRequest req, ServletResponse resp, FilterChain chain):
- 处理请求(如设置编码
req.setCharacterEncoding("UTF-8")
)。 - 调用
chain.doFilter(req, resp)
传递请求到下一个过滤器或Servlet。
- 处理请求(如设置编码
- destroy():销毁,释放资源。
2.11.2 应用案例:编码过滤器
public class EncodingFilter implements Filter {
private String encoding = "UTF-8";
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
req.setCharacterEncoding(encoding);
resp.setCharacterEncoding(encoding);
chain.doFilter(req, resp); // 传递请求
}
}
配置web.xml:
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>com.example.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern> <!-- 匹配所有请求 -->
</filter-mapping>
2.11.3 与拦截器的区别
- Filter:基于Servlet规范,处理请求/响应的原始数据,在Servlet之前执行。
- Interceptor(如Struts2拦截器):基于框架(如Spring MVC),处理Action请求,支持更细粒度的控制(如方法级拦截)。
通过以上深入拓展,详细解析了Servlet篇的核心知识点,结合代码示例和对比分析,帮助理解Servlet生命周期、请求处理、作用域通信、安全机制等关键内容,适用于面试准备和实际开发应用。