Servlet详解
概念[*]Servlet是运行在服务端的小程序(Server Applet),可以处理客户端的请求并返回响应,主要用于构建动态的Web应用,是SpringMVC的基础。
生命周期
加载和初始化
[*]懒加载(默认在客户端第一次请求加载到容器中),通过反射实例化,并调用init(),且init()只能被调用一次,因此每个Servlet是单例的,需注意线程安全。
请求处理
[*]Servlet 容器收到url请求后,路由到对应的Servlet,调用service()方法处理客户端请求,并返回响应。
[*]每次服务器收到一个请求时,Servlet 容器都会分配一个线程并调用service()方法,根据请求类型,执行对应的方法,也会存在线程安全问题,避免使用全局变量、非同步数据结构等。
销毁
[*]destroy()只会被调用一次,当容器被正常关闭时,释放一些使用了的资源。
[*]异常终止情况,不会调用destroy()。
流程图
https://p0-xtjj-private.juejin.cn/tos-cn-i-73owjymdk6/70b3541ac32a4a4aa179d6ab3e2b5166~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAgU2xhY2tDbGltYg==:q75.awebp?policy=eyJ2bSI6MywidWlkIjoiODY5MDc1Mjk1NDEwMDA5In0%3D&rk3s=e9ecf3d6&x-orig-authkey=f32326d3454f2ac7e96d3d06cdbb035152127018&x-orig-expires=1736400495&x-orig-sign=09KeAigAQIvWOoWRfaCpPKi%2BHWA%3D
其他应用
1. 过滤器(Filter)
1.1 作用
[*]对请求和响应进行预处理和后处理。
[*]典型应用场景:
[*]
[*]权限验证。
[*]请求参数编码处理。
[*]日志记录。
[*]防止 XSS 和 SQL 注入。
1.2 工作流程
[*]过滤器在 Servlet 执行之前运行,可以拦截并修改请求。
[*]过滤器在 Servlet 执行之后运行,可以修改响应。
1.3 关键接口
javax.servlet.Filter 接口,核心方法:
[*]init(FilterConfig filterConfig):在容器启动时初始化过滤器。
[*]doFilter(ServletRequest request, ServletResponse response, FilterChain chain):
[*]
[*]进行请求/响应的过滤处理。
[*]调用 chain.doFilter() 将请求传递到下一个过滤器或目标 Servlet。
[*]destroy():在容器关闭时释放资源。
1.4 示例
过滤器实现
@WebFilter(urlPatterns = "/*") // 拦截所有请求
public class LoggingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("过滤器初始化");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("请求到达过滤器");
chain.doFilter(request, response); // 将请求传递到下一个过滤器或 Servlet
System.out.println("响应从过滤器返回");
}
@Override
public void destroy() {
System.out.println("过滤器销毁");
}
}2. 监听器(Listener)
2.1 作用
[*]监听 Web 应用中对象(如请求、会话、上下文)生命周期事件或属性变化。
[*]典型应用场景:
[*]
[*]统计在线人数。
[*]初始化全局资源。
[*]监控会话销毁以释放资源。
2.2 关键接口
Servlet 提供了多种监听器接口:
[*]应用上下文监听器:
[*]
[*]ServletContextListener:监听应用启动和销毁事件。
[*]会话监听器:
[*]
[*]HttpSessionListener:监听会话创建和销毁事件。
[*]HttpSessionAttributeListener:监听会话属性变化。
[*]请求监听器:
[*]
[*]ServletRequestListener:监听请求创建和销毁事件。
[*]ServletRequestAttributeListener:监听请求属性变化。
2.3 示例
在线人数统计
@WebListener
public class OnlineUserListener implements HttpSessionListener {
private static int onlineUsers = 0;
@Override
public void sessionCreated(HttpSessionEvent se) {
onlineUsers++;
System.out.println("用户上线,当前在线人数:" + onlineUsers);
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
onlineUsers--;
System.out.println("用户下线,当前在线人数:" + onlineUsers);
}
}3. 异步处理
3.1 作用
[*]Servlet 3.0 引入异步处理,用于提高性能和响应速度。
[*]异步处理允许在 Servlet 请求线程结束后继续处理任务,释放容器线程资源。
3.2 核心方法
[*]在 Servlet 中启动异步支持:
@WebServlet(urlPatterns = "/async", asyncSupported = true)
public class AsyncServlet extends HttpServlet {
}
[*]异步请求处理逻辑:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
AsyncContext asyncContext = req.startAsync();
asyncContext.start(() -> {
try {
Thread.sleep(2000); // 模拟耗时操作
asyncContext.getResponse().getWriter().write("异步请求完成");
} catch (Exception e) {
e.printStackTrace();
} finally {
asyncContext.complete(); // 完成异步处理
}
});
}4. 文件上传与下载
4.1 文件上传
配置文件上传支持
Servlet 3.0 引入了对文件上传的直接支持,通过 @MultipartConfig 注解。
示例
@WebServlet("/upload")
@MultipartConfig(location = "/tmp", fileSizeThreshold = 1024 * 1024, maxFileSize = 5 * 1024 * 1024)
public class FileUploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Part filePart = req.getPart("file"); // 获取上传文件的部分
String fileName = filePart.getSubmittedFileName();
filePart.write("/uploads/" + fileName); // 保存文件
resp.getWriter().write("文件上传成功:" + fileName);
}
}4.2 文件下载
示例
@WebServlet("/download")
public class FileDownloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String fileName = "example.txt";
resp.setContentType("application/octet-stream");
resp.setHeader("Content-Disposition", "attachment;filename=" + fileName);
try (InputStream in = new FileInputStream("/uploads/" + fileName);
OutputStream out = resp.getOutputStream()) {
byte[] buffer = new byte;
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
}
}
}
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页:
[1]