JavaServlet解析

1. 基础概念与原理

JavaServlet 是运行在 Web 服务器上的小型 Java 程序,用于处理客户端请求并生成动态响应。它是 Java EE 平台的核心组件之一,主要用于开发 Web 应用程序。

核心原理:

  • Servlet 容器(如 Tomcat)负责加载和管理 Servlet 生命周期
  • 客户端请求通过 HTTP 协议发送到服务器,由容器将请求分发到对应 Servlet
  • Servlet 通过实现doGet()doPost()等方法处理请求,并返回响应
  • 采用多线程模型,每个请求由独立线程处理,需注意线程安全问题
2. 生命周期详解

Servlet 生命周期由容器管理,包含以下阶段:

public class MyServlet extends HttpServlet {
    
    // 1. 初始化方法,容器加载Servlet时调用(单例)
    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("Servlet初始化完成");
    }
    
    // 2. 处理GET请求
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        resp.getWriter().println("Hello from GET");
    }
    
    // 3. 处理POST请求
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        resp.getWriter().println("Hello from POST");
    }
    
    // 4. 销毁方法,容器卸载Servlet时调用
    @Override
    public void destroy() {
        System.out.println("Servlet即将销毁");
    }
}
3. 请求与响应处理

请求处理示例:

protected void doGet(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
    
    // 获取请求参数
    String username = request.getParameter("username");
    
    // 获取请求头
    String userAgent = request.getHeader("User-Agent");
    
    // 设置响应内容类型
    response.setContentType("text/html;charset=UTF-8");
    
    // 获取输出流
    PrintWriter out = response.getWriter();
    out.println("<html><body>");
    out.println("<h1>欢迎 " + username + "</h1>");
    out.println("</body></html>");
}

请求转发与重定向:

// 请求转发(服务器内部跳转)
request.getRequestDispatcher("/target.jsp").forward(request, response);

// 重定向(客户端跳转)
response.sendRedirect("/contextPath/target.jsp");
4. 高级特性

过滤器(Filter):

public class EncodingFilter implements Filter {
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
            FilterChain chain) throws IOException, ServletException {
        
        // 设置请求编码
        request.setCharacterEncoding("UTF-8");
        
        // 传递请求到下一个过滤器或Servlet
        chain.doFilter(request, response);
        
        // 响应处理(可在此添加响应处理逻辑)
    }
}

监听器(Listener):

public class SessionCounterListener implements HttpSessionListener {
    
    private static int activeSessions = 0;
    
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        activeSessions++;
        System.out.println("新会话创建,当前活跃会话: " + activeSessions);
    }
    
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        activeSessions--;
        System.out.println("会话销毁,当前活跃会话: " + activeSessions);
    }
}
5. 异步 Servlet 处理

Java Servlet 3.0 引入异步处理支持,适用于长耗时操作:

protected void doGet(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
    
    // 开启异步处理
    AsyncContext asyncContext = request.startAsync();
    
    // 设置超时时间
    asyncContext.setTimeout(30000);
    
    // 启动异步线程处理
    asyncContext.start(() -> {
        try {
            // 模拟耗时操作
            Thread.sleep(5000);
            
            // 获取响应并输出
            PrintWriter out = asyncContext.getResponse().getWriter();
            out.println("异步处理完成");
            
            // 完成异步处理
            asyncContext.complete();
        } catch (Exception e) {
            e.printStackTrace();
        }
    });
}
6. 与 Spring 框架集成

Servlet 与 Spring 集成是现代 Java Web 开发的主流方式:

// 配置Spring MVC DispatcherServlet
public class AppInitializer implements WebApplicationInitializer {
    
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        
        // 创建Spring应用上下文
        AnnotationConfigWebApplicationContext context = 
                new AnnotationConfigWebApplicationContext();
        context.register(AppConfig.class);
        
        // 添加DispatcherServlet
        DispatcherServlet dispatcherServlet = new DispatcherServlet(context);
        ServletRegistration.Dynamic registration = 
                servletContext.addServlet("dispatcher", dispatcherServlet);
        
        // 设置映射路径
        registration.setLoadOnStartup(1);
        registration.addMapping("/");
    }
}
7. 面试常考问题
  1. Servlet 与 CGI 的区别

    • Servlet 在服务器进程内运行,效率高;CGI 为每个请求创建新进程
    • Servlet 线程安全需开发者处理;CGI 无此问题
    • Servlet 可管理会话状态;CGI 需依赖外部机制
  2. Servlet 线程安全问题

    • 多个请求可能同时访问同一个 Servlet 实例
    • 避免使用实例变量,或使用 ThreadLocal 存储线程私有数据
    • 可使用synchronized关键字,但可能影响性能
  3. Servlet 生命周期关键方法

    • init():初始化 Servlet(单例)
    • service():处理请求的核心方法
    • destroy():Servlet 销毁前调用
  4. 请求转发与重定向的区别

    • 转发是服务器内部跳转,地址栏不变
    • 重定向是客户端跳转,地址栏改变
    • 转发效率高,重定向更灵活
  5. 过滤器的应用场景

    • 字符编码处理
    • 权限验证
    • 日志记录
    • 敏感信息过滤
8. 性能优化与最佳实践
  1. 合理配置线程池

    • 在 Servlet 容器中调整线程池参数,避免创建过多线程
    • 如 Tomcat 的maxThreadsacceptCount等参数
  2. 使用异步处理

    • 对于长耗时操作(如 IO 密集型任务),使用异步 Servlet
  3. 避免阻塞操作

    • 数据库查询、网络调用等应使用连接池和异步 API
  4. 适当缓存

    • 使用 ServletContext 缓存常用数据
    • 考虑使用分布式缓存(如 Redis)
  5. 安全加固

    • 防止 SQL 注入和 XSS 攻击
    • 合理设置 HTTP 头(如 CSP、X-Frame-Options)
    • 避免暴露敏感信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值