HTTPServlet源码分析
HTTPServlet源码分析
-
HttpServelt类是专门为HTTP协议准备的。比GenericServlet更加适合HTTP协议下的开发。
-
HttpServlet在哪个包下?
- jakarta.servlet.http.HttpServlet
-
到目前为止我们接触了了servlet规范中的那些接口?
- jakarta.servlet.Servelt 核心接口
- jakarta.servlet.ServeltConfig Servlet配置信息接口
- jakarta.servlet.ServeltContext Servlet上下文接口
- jakarta.servlet.ServeltRequest Servlet请求接口
- jakarta.servlet.ServeltResponse Servlet响应接口
- jakarta.servlet.ServeltException Servlet 异常接口
- jakarta.servlet.GenericServlet Servlet 实现类接口
-
Http包下都有哪些类和接口呢?jakarta.servlet.http.*;
jakarta.servlet.http.HttpServlet(HTTP协议专用的Servlet类,抽象类)
jakarta.servlet.http.HttpServletRequest(HTTP协议专用的请求对象)
jakarta.servlet.http.HttpServletResponse(Http协议专用的响应对象) -
HttpServletRequest对象中封装了什么信息?
HttpServletRequest,简称request对象。
HttpServletRequest中封装了请求协议的全部内容。
Tomcat服务器(WEB服务器)将“请求协议”中的数据全部解析出来,然后将这些数据全部封装到了request对象当中了。
也就说,我们要面向HttpServletRequest,就可以获取协议中的数据 -
HttpServletResponse对象是专门用来响应HTTP协议到浏览器的。
-
回忆Servelt生命周期?
-
用户第一次请求
- Tomcat服务器通过反射机制,创建Servlet对象。(web.xml文件中的配置的Servlet类对应的对象。)
- Tomcat服务器调用Servlet对象的init方法完成初始化。
- Tomcat服务器调用Servlet对象的service方法处理请求。
-
用户的第二次请求
- Tomcat服务器调用Servlet对象的service方法处理请求。
-
- Tomcat服务器调用Servlet对象的service方法处理请求。
- …(.Tomcat服务器调用Servlet对象的service方法处理请求。)
- 服务器关闭
- Tomcat服务器调用Servlet对象的destroy方法,做销毁之前的准备工作。
-
-
HttpServlet 源码分析
public class HelloServlet extends HttpServlet { //用户第一次请求,创建HelloServlet对象的时候,会执行这个无参数构造方法。 public HelloServlet(){} } public abstract class GenericServlet implements Servlet,ServletConfig,java.io.Serializable{ //用户第一次请求的时候,HelloServlet对象第一次被创建之后,这个init方法会执行。 public void init(ServletConfig config) throws ServletException{ this.config = config; this.init() } //用户第一次请求的时候,带有参数的init(ServletConfig config)执行之后,会执行这个没有参数的init() public void init() throws ServletException{ } } //HttpServlet是一个典型的模板类 public abstract class HttpServlet extends GenericServlet{ //用户发送第一次请求的时候这个service会执行 //用户发送第N次请求的时候,这个service方法还是会执行。 //用户只要发送一次请求,这个service方法就会执行一次。 public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { HttpServletRequest request; HttpServletResponse response; try { //将ServletRequest和ServeltResponse向下转型为带有Http的HttpServletRequest和HttpServletResponse request = (HttpServletRequest)req; response = (HttpServletResponse)res; } catch (ClassCastException var6) { throw new ServletException(lStrings.getString("http.non_http")); } //调用重载的service方法 this.service(request, response); } //这个service方法的两个参数都是带有Http的 //这个service是一个模板方法 //在该方法中定义核心算法骨架,具体的实现步骤延迟到子类中去完成。 protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取请求方式 //这个请求方式最终可能是:"" //注意:request.getMethod()方法获取的是请求方式,可能是七种之一: //GET POST DELETE HEAD OPTIONS OOPTIONS TRACE String method = req.getMethod(); long lastModified; if (method.equals("GET")) { lastModified = this.getLastModified(req); if (lastModified == -1L) { this.doGet(req, resp); } else { long ifModifiedSince; try { ifModifiedSince = req.getDateHeader("If-Modified-Since"); } catch (IllegalArgumentException var9) { ifModifiedSince = -1L; } if (ifModifiedSince < lastModified / 1000L * 1000L) { this.maybeSetLastModified(resp, lastModified); this.doGet(req, resp); } else { resp.setStatus(304); } } } else if (method.equals("HEAD")) { lastModified = this.getLastModified(req); this.maybeSetLastModified(resp, lastModified); this.doHead(req, resp); } else if (method.equals("POST")) { this.doPost(req, resp); } else if (method.equals("PUT")) { this.doPut(req, resp); } else if (method.equals("DELETE")) { this.doDelete(req, resp); } else if (method.equals("OPTIONS")) { this.doOptions(req, resp); } else if (method.equals("TRACE")) { this.doTrace(req, resp); } else { String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[]{method}; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(501, errMsg); } } } protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //报405错误 String msg = lStrings.getString("http.method_get_not_supported"); this.sendMethodNotAllowed(req, resp, msg); } protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String msg = lStrings.getString("http.method_post_not_supported"); this.sendMethodNotAllowed(req, resp, msg); } /* 通过以上源代码分析: 假设前端发送的请求是get请求,后端程序员重写的方法是doPost 假设前端发送的请求是Post请求,后端程序员重写的方法是doGet 会发生什么呢? 发生405这样的一个错误。 405表示前端你的错误,发送的请求方式不对。和服务器不一致。不是服务器需要的请求方式。 通过以上源代码可以知道:只要HttpServlet类中的doGet方法或doPost方法执行了,必然405. 怎么避免405错误呢? 后端重写doGet方法,前端一定要发get请求。 后端重写doPost方法,前端一定要发Post请求。 有的人,你会看到为了避免405错误,在Servlet类当中,将doGet和doPost方法都进行了重写。这样,确实可以避免405的放生,但是不建议,405错误还是有用的,该报错的时候应该让他报错。
-
我们编写的HelloServlet直接继承HttpServlet,直接重写HttpServlet类中的service()方法行吗?
可以,只不过你享受不到405错误,享受不到HTTP协议专属的东西。
-
到今天我们终于得到了最终的一个Servlet类的开发步骤:
- 第一步:编写一个Servlet类,直接继承HttpServlet
- 第二步:重写doGet方法或者doPost方法,到底重写谁,程序员说了算。
- 第三步:将Servlet类配置到web.xml文件当中。
- 第四步:准备前端的页面(from表单),from表单中指定请求路径
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具