今天就servlet进行一个收尾总结吧。今天不聊复杂的框架,就按我之前写过的内容,絮叨絮叨 Servlet 这门手艺的来龙去脉,全是些边踩坑边悟出来的实在话。

一、Servlet 概论
刚入行时,师傅扔给我一句 “Servlet 就是 Java 写的 Web 组件,跑在服务器上处理请求的”,我琢磨了半天才明白 —— 这东西既不是前端页面,也不是后端数据库,就是个 “中间件”:浏览器发个 HTTP 请求过来,它接过来、处理完,再把结果扔回去。
你问为啥非得用 Servlet?早年用 CGI 写 Web,每个请求都起个进程,并发一高服务器就卡成 PPT;后来有了 PHP、ASP,倒是简单,但在 Java 生态里总觉得 “隔了一层”。Servlet 不一样,它跑在 JVM 里,单实例多线程,省资源还快,关键是能跟 Java 的其他家伙 ——JDBC、RMI、集合框架 —— 无缝搭伙,这才快,关键是能跟 Java 的其他家伙 ——JDBC、RMI、集合框架 —— 无缝搭伙,这才是 Java 程序员的 “本命工具”。
不过写 Servlet 也不是啥都不用准备:JDK 得有吧,Tomcat、Jetty 这类 Servlet 容器得装吧,还得懂点 HTTP 协议 —— 至少知道 GET 和 POST 的区别,不然写出来的接口要么传错参数,要么接不到数据。当年我第一次写 Servlet,忘了配置 web.xml,结果访问时 404,对着屏幕愣了俩小时,后来才知道 “得告诉服务器哪个请求归哪个 Servlet 管”。
最后说句实在的:学 Servlet 别一开始就扎进细节,先把 “请求 - 处理 - 响应” 这个流程刻在脑子里 —— 浏览器发请求→容器把请求转给 Servlet→Servlet 调用 service/doGet/doPost 处理→容器把响应返回给浏览器,这才是 Servlet 的 “骨架”,后面所有复杂功能,都是在这个骨架上添肉。
二、Java Web 服务器
Servlet 这东西 “娇生惯养”,自己跑不起来,得找个 “家”—— 也就是 Java Web 服务器,比如 Tomcat、JBoss。这些服务器都按 JavaServer 的体系来搭:最外层是服务框架,管着端口监听、请求接收;中间是服务器框架,处理线程池、资源管理;最里面才是 Servlet 框架,负责创建 Servlet 实例、调用生命周期方法。
早年用 Tomcat,总爱瞎折腾 “系统管理”—— 改改端口号、调调线程池大小,后来才知道:8080 端口别跟其他服务冲突,最大线程数得根据服务器配置来,不然小马拉大车,越调越慢。还有那些 “内部 Servlet”,比如处理静态资源的 FileServlet、处理 SSI 的 Server-Side Include Servlet,平时不用管,但出问题时得知道在哪找 —— 当年静态页面的 CSS 加载不出来,查了半天才发现是 FileServlet 没配置对,把 “/static/*” 的映射给漏了。
访问 Java Web 服务器也有讲究:本地测试用 “http://localhost:8080/项目名 / 接口名”,线上得配域名、开防火墙,还得注意端口映射 —— 别把 Tomcat 的 8080 直接暴露在外网,加个 Nginx 反向代理,安全还能扛并发。
三、第一个 Servlet
每个 Java 程序员都有个 “第一个 Servlet” 的故事。我当年写的是个 PropertiesServlet,功能特简单:读个配置文件,把键值对返回给浏览器。就这东西,我踩了仨坑:
一是写代码时忘了继承 HttpServlet,结果编译都通不过,后来才知道 “所有 Servlet 都得是 HttpServlet 的子类”;二是配置 Tomcat 时,把类文件放错了地方 —— 应该扔到 WEB-INF/classes 里,我却直接放了 WEB-INF,结果服务器找不到类;三是写 HTML 表单时,action 地址写错了,多了个斜杠,导致请求发不出去。
后来跑通了,又遇到个新问题:改了 Servlet 代码,重启 Tomcat 才生效,麻烦得很。师傅告诉我 “Tomcat 能开热部署”,配置一下 server.xml,改了代码不用重启,直接生效 —— 这招当年救了我不少时间。
现在回想起来,第一个 Servlet 的价值不在 “功能多复杂”,而在 “把流程走通”:从写代码、配容器、写前端调用页面,到最后看到浏览器显示结果,这个过程走顺了,后面学 Servlet 链、会话管理,都跟 “顺藤摸瓜” 似的。
四、Servlet 链与 Server-Side Includes
单个 Servlet 处理请求,简单是简单,但遇到复杂需求就 “力不从心”—— 比如先过滤请求参数、再查数据库、最后渲染页面,总不能把所有代码堆在一个 Servlet 里吧?这时候就得用 Servlet 链。
Servlet 链说白了就是 “多个 Servlet 接力处理一个请求”:第一个 Servlet 过滤参数,处理完把请求传给第二个;第二个查数据库,再传给第三个;第三个生成 HTML 页面,最后返回给浏览器。当年做用户登录功能,就用了俩 Servlet:LoginFilterServlet 先校验用户名密码格式,没问题再传给 LoginServlet 查数据库,这样职责分明,后来改需求时也不用大动干戈。
还有个好用的东西叫 Server-Side Includes(SSI),就是在 HTML 页面里插个标记,让服务器把其他资源 “拼” 进来 —— 比如所有页面的页头、页脚都一样,不用每个页面都写一遍,用 SSI 插个 “” 就行。当年做企业官网,用 SSI 统一管理页头页脚,改一次全网站都生效,省了不少重复活。
不过用 Servlet 链和 SSI 也得注意:Servlet 链的顺序不能乱,得先过滤再处理;SSI 别嵌套太多,不然服务器拼接页面时会变慢,影响访问速度。
五、会话管理
做 Web 项目,最烦的就是 “用户每次访问都得登录”—— 早年用 Cookie 存用户信息,结果用户清了 Cookie,又得重新登录;后来用 Session,才解决了这个问题。
Session 这东西就是服务器给每个用户建的 “小账本”:用户第一次登录,服务器给个 SessionID,存在 Cookie 里;下次用户访问,带着 SessionID 过来,服务器就知道 “哦,是上次那个用户”,不用再让他登录。但 Session 也有麻烦:默认 30 分钟过期,用户抱怨 “我才离开一会儿就掉登录了”;后来把 session-timeout 改成 60,又加了 “记住我” 功能 —— 把用户信息加密存 Cookie 里,Session 过期了就用 Cookie 自动登录,这才平息了抱怨。
还有个 URL 重写,当年做手机端项目,有些浏览器禁用 Cookie,SessionID 传不过去,就把 SessionID 拼在 URL 后面 ——“http://xxx.com/order?jsessionid=123456”,虽然丑了点,但能用。不过现在很少用了,一是 HTTPS 普及后,URL 里带参数不安全;二是大部分浏览器都支持 Cookie,犯不着折腾。
最后提醒一句:会话数据别存太多,尤其是 application 域 —— 那是全局共享的,存多了占内存,还容易线程不安全。当年在 application 里存 “在线用户数”,没加锁,结果并发高了计数不准,查了半天才发现是多线程抢着改数据导致的。
六、安全性
做 Web 开发,安全是 “底线”—— 当年有个项目没做登录验证,结果被人直接访问后台接口,删了半库数据,老板差点把我开了。从那以后,我对 Servlet 的安全就特别上心。
最简单的是 HTTP 认证,让服务器弹个框要用户名密码,虽然丑,但简单有效;后来做电商,用 HTML 表单认证,加了验证码、密码加密,还限制 “连续输错 3 次锁账号”;再后来涉及支付,就得上 SSL—— 也就是 HTTPS,把数据加密传输,防止被人抓包偷信息。
还有个容易被忽略的点:表单提交要防 CSRF,就是在表单里加个 Token,服务器校验 Token 对不对,不然别人能伪造请求;参数要防 SQL 注入,别直接把用户输入的内容拼到 SQL 里,用 PreparedStatement 预编译,当年我就吃过这亏,用户输入个 “' or 1=1 --”,直接把整个表的数据都查出来了。
说句实在的:Servlet 的安全不是 “一劳永逸” 的,得跟着漏洞更新走 —— 今天补个 XSS 漏洞,明天升级下 SSL 协议,后天优化下密码策略,这活就跟 “给房子补漏洞” 似的,得常盯着。
七、HTML 表单与 JDBC
Servlet 处理请求,离不开两样东西:前端的 HTML 表单传数据,后端的 JDBC 查数据库 —— 这俩是 Servlet 的 “左膀右臂”。
早年写 HTML 表单,总爱犯些低级错误:input 标签忘了加 name 属性,结果 Servlet 用 getParameter 拿不到值;下拉框的 option 没设 value,传过去的是显示文本不是实际 ID;表单提交用 GET,把密码暴露在 URL 里 —— 后来才知道,表单提交尽量用 POST,敏感数据要加密,还得加个 onsubmit 事件做前端校验,别什么脏数据都往后台传。
JDBC 更是 Servlet 的 “老搭档”—— 查用户、下单、对账,都得靠它跟数据库打交道。但早年写 JDBC,总忘了关连接,结果数据库连接池被耗尽,服务器报 “Connection refused”;后来学乖了,用 try-with-resources 自动关连接,还加了连接池 —— 提前建一批连接放在池里,用的时候拿,用完了还回去,比每次都新建连接快多了。
当年做员工管理系统,用 Servlet+JDBC 做了个 EmployeeList 接口,还加了头像显示 —— 把头像存数据库里,用 Servlet 读出来,设置响应头 “Content-Type: image/jpeg”,再用 OutputStream 写出去,页面里用
调用,效果还不错。
八、Applet 与 Servlet 通信、RMI
早年 Java Applet 还火的时候,常常用它跟 Servlet 通信 ——Applet 做前端界面,Servlet 做后端接口,俩配合着干活。但 Applet 有个毛病:受沙箱限制,不能直接访问本地文件,也不能跨域,后来就用 “隧道技术”—— 把数据包装成 HTTP 请求,通过 Servlet 转发,这才绕开了限制。当年做个远程计算器,Applet 发 “1+1” 给 Servlet,Servlet 算完返回 “2”,虽然简单,但也算摸清了 “客户端 - 服务器” 通信的门道。
后来做分布式项目,又用上了 RMI—— 让 Servlet 调用其他服务器上的 Java 对象。比如订单 Servlet 在 A 服务器,库存 Servlet 在 B 服务器,用 RMI 让 A 调用 B 的库存接口,减完库存再下单。但 RMI 也麻烦:得定义远程接口、生成 Stub/Skeleton、启动注册中心,当年第一次用 RMI,忘了启动 rmiregistry,结果报 “Connection refused”,查了半天没找到原因,后来才知道 “得先启动注册中心,再注册远程对象”。
不过现在 Applet 基本没人用了,RMI 也被 Dubbo、Spring Cloud 这类微服务框架取代了,但当年用它们练手的经历,让我明白一个道理:Servlet 不是 “孤军奋战” 的,它能跟各种 Java 技术搭伙,这才是它的生命力所在。
九、最后小结
写了这么多,突然发现 Servlet 这东西挺 “倔强”—— 这些年 Spring MVC、Spring Boot 火了,很多人觉得 “不用直接写 Servlet 了”,但你掀开框架的盖子看看,Spring MVC 的 DispatcherServlet 不还是个 Servlet?只不过框架帮你做了路由、参数绑定这些脏活累活。
对我们老程序员来说,Servlet 不仅是个技术,更是一种 “Web 开发的思维”—— 理解了 Servlet 的请求处理流程,再学任何 Web 框架都快;踩过 Servlet 的坑,后面写代码时就会更谨慎:线程安全要注意、资源要关闭、安全要做好。
最后给刚入行的小伙子们提个醒:别觉得 Servlet 老就不学了,这东西是 Java Web 的 “根”,是web万物之源..........

3975

被折叠的 条评论
为什么被折叠?



