1. Servlet基础概念与核心机制Servlet作为JavaEE规范的核心组件其本质是一个运行在Web服务器上的Java程序。与传统的CGI技术相比Servlet采用线程池处理请求而非进程创建这使得它在高并发场景下性能表现优异。当我们在Tomcat中部署一个Servlet时容器会通过反射机制调用其无参构造函数完成实例化这个生命周期仅发生一次。Servlet的核心方法莫过于service()它就像是一个交通警察根据HTTP请求方法类型GET/POST等将请求分发给对应的doGet()或doPost()方法。我曾在一个电商项目中遇到性能瓶颈通过重写service()方法实现请求分流使QPS提升了近40%。这提醒我们理解底层机制往往能带来意想不到的优化空间。关键点Servlet是单例多线程的务必注意线程安全问题。实例变量需要特殊处理建议使用ThreadLocal或方法内局部变量。2. MVC模式的三层解耦实践2.1 模型层的业务封装模型层(Model)不应只是简单的数据容器。在图书管理系统案例中我将业务规则如借阅期限计算、库存校验封装在Book模型的对应方法中这使得控制器可以保持简洁。一个常见的误区是把模型写成贫血对象这实际上违背了MVC的初衷。2.2 控制器的路由优化控制器(Controller)作为调度中心最忌变成上帝类。我曾重构过一个2000行的Servlet控制器通过命令模式将其拆分为多个Handler。例如// 优化前 protected void doPost(HttpServletRequest req...){ String action req.getParameter(action); if(addBook.equals(action)){ // 50行处理逻辑 } else if(queryBook.equals(action)){ // 80行处理逻辑 } } // 优化后 MapString, ActionHandler handlers new HashMap(); handlers.put(addBook, new AddBookHandler()); handlers.put(queryBook, new QueryBookHandler()); protected void doPost(...){ handlers.get(req.getParameter(action)).handle(req,resp); }2.3 视图层的动态渲染JSP作为传统视图层技术其自定义标签库能有效减少脚本片段。在实现视频播放列表时我结合JSTL的c:forEach和EL表达式将后端传递的List优雅地渲染为HTML5的标签组。记住永远不要在JSP中编写业务逻辑那是控制器的职责。3. Servlet与JSP的协作陷阱3.1 作用域对象的选用策略四个作用域page/request/session/application的选择需要谨慎页面跳转用request.setAttribute()用户会话数据用session.setAttribute()全局配置用getServletContext().setAttribute()我曾遇到一个内存泄漏案例将10MB的报表数据误存到session而非request中导致服务器内存快速耗尽。3.2 中文乱码的终极解决方案乱码问题困扰着许多初学者这里给出完整解决方案// 请求编码处理POST request.setCharacterEncoding(UTF-8); // 响应编码 response.setContentType(text/html;charsetUTF-8); PrintWriter out response.getWriter(); // JSP页面头部 % page contentTypetext/html;charsetUTF-8 %3.3 转发与重定向的抉择特性RequestDispatcher.forward()response.sendRedirect()URL变化否是数据传递通过request属性需URL参数或session服务器负载低高二次请求典型场景内部流程跳转跨应用/登录后跳转在支付流程中forward适合处理银行接口回调而redirect更适合支付完成后的结果页跳转。4. 现代MVC框架的演进启示虽然现在Spring MVC大行其道但理解原生Servlet MVC仍具价值。以DispatcherServlet为例其核心原理正是我们讨论的MVC模式升级版通过HandlerMapping实现请求到控制器的映射采用适配器模式统一处理不同类型的控制器视图解析器链支持多种视图技术在2024年的新项目中我建议中小型项目可用JFinal这类轻量框架企业级应用首选Spring MVC学习阶段务必手动实现至少一个Servlet MVC案例5. 实战构建图书管理模块5.1 模型设计public class Book { private String isbn; private String title; private ListString authors; // 业务方法示例 public boolean isAvailable() { return borrowRecords.stream() .noneMatch(r - r.getReturnDate() null); } }5.2 控制器实现WebServlet(/book) public class BookServlet extends HttpServlet { private BookService service new BookServiceImpl(); protected void doGet(...) { String id request.getParameter(id); Book book service.findById(id); request.setAttribute(book, book); request.getRequestDispatcher(/bookDetail.jsp).forward(...); } }5.3 视图渲染% taglib prefixc urihttp://java.sun.com/jsp/jstl/core % div classbook-info h2${book.title}/h2 c:forEach items${book.authors} varauthor span classbadge${author}/span /c:forEach p库存状态: ${book.available ? 可借阅 : 已借出}/p /div6. 性能优化备忘录Servlet线程池配置Tomcat为例Connector port8080 maxThreads200 minSpareThreads20 acceptCount100/JSP预编译生产环境建议用JSPC编译器提前生成Servlet类静态资源处理配置DefaultServlet的缓存策略Context cachingAllowedtrue cacheTTL86400000/会话优化对只读操作设置sessionfalse% page sessionfalse %在最近的压力测试中通过调整线程池参数配合NIO连接器系统成功支撑了每秒5000的并发请求。这印证了基础架构优化的重要性——再好的架构设计也需要合理的参数调优。