Tomcat请求处理中Servlet实例的调用是和Filter的调用联系在一起的,是在StandardWrapperValve类的#invoke()方法中调用的,前面的文章中提到过,就是下面的这句:
filterChain.doFilter(request.getRequest(), response.getResponse());
它的源代码如下:
- public void doFilter(ServletRequest request, ServletResponse response) throws IOException,
- ServletException {
- if (Globals.IS_SECURITY_ENABLED) {
- final ServletRequest req = request;
- final ServletResponse res = response;
- try {
- java.security.AccessController
- .doPrivileged(new java.security.PrivilegedExceptionAction() {
- public Object run() throws ServletException, IOException {
- internalDoFilter(req, res);
- return null;
- }
- });
- } catch (PrivilegedActionException pe) {
- Exception e = pe.getException();
- if (e instanceof ServletException)
- throw (ServletException) e;
- else if (e instanceof IOException)
- throw (IOException) e;
- else if (e instanceof RuntimeException)
- throw (RuntimeException) e;
- else
- throw new ServletException(e.getMessage(), e);
- }
- } else {
- internalDoFilter(request, response);
- }
- }
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if (Globals.IS_SECURITY_ENABLED) { final ServletRequest req = request; final ServletResponse res = response; try { java.security.AccessController .doPrivileged(new java.security.PrivilegedExceptionAction() { public Object run() throws ServletException, IOException { internalDoFilter(req, res); return null; } }); } catch (PrivilegedActionException pe) { Exception e = pe.getException(); if (e instanceof ServletException) throw (ServletException) e; else if (e instanceof IOException) throw (IOException) e; else if (e instanceof RuntimeException) throw (RuntimeException) e; else throw new ServletException(e.getMessage(), e); } } else { internalDoFilter(request, response); } }
这个方法只是调用了#internalDoFilter(),这个才是Filter调用的核心,源代码如下所示:
- private void internalDoFilter(ServletRequest request, ServletResponse response)
- throws IOException, ServletException {
- if (pos < n) {
- ApplicationFilterConfig filterConfig = filters[pos++];
- Filter filter = null;
- try {
- // 得到当前Filter
- filter = filterConfig.getFilter();
- support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT, filter, request,
- response);
- // 调用Filter的#doFilter()方法。
- // 在Filter内部,如果Filter调用成功,会调用chain.doFilter(request,response); 这个语句。
- // 这里传递给忒Filter的chain实例就是ApplicationFilterChain类的对象。
- // 于是程序又回到了#doFilter(),然后再次调用本方法。也应该是一种变相的递归了。
- if (Globals.IS_SECURITY_ENABLED) {
- final ServletRequest req = request;
- final ServletResponse res = response;
- Principal principal = ((HttpServletRequest) req).getUserPrincipal();
- Object[] args = new Object[] { req, res, this };
- SecurityUtil.doAsPrivilege("doFilter", filter, classType, args);
- args = null;
- } else {
- filter.doFilter(request, response, this);
- }
- support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request,
- response);
- } catch (IOException e) {
- if (filter != null)
- support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request,
- response, e);
- throw e;
- } catch (ServletException e) {
- if (filter != null)
- support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request,
- response, e);
- throw e;
- } catch (RuntimeException e) {
- if (filter != null)
- support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request,
- response, e);
- throw e;
- } catch (Throwable e) {
- if (filter != null)
- support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request,
- response, e);
- throw new ServletException(sm.getString("filterChain.filter"), e);
- }
- return;
- }
- try {
- if (Globals.STRICT_SERVLET_COMPLIANCE) {
- lastServicedRequest.set(request);
- lastServicedResponse.set(response);
- }
- // Filter全部调用完毕后,就会把请求真正的传递给Servlet了,调用它的#service()方法。
- support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT, servlet, request,
- response);
- if ((request instanceof HttpServletRequest)
- && (response instanceof HttpServletResponse)) {
- if (Globals.IS_SECURITY_ENABLED) {
- final ServletRequest req = request;
- final ServletResponse res = response;
- Principal principal = ((HttpServletRequest) req).getUserPrincipal();
- Object[] args = new Object[] { req, res };
- SecurityUtil.doAsPrivilege("service", servlet, classTypeUsedInService, args,
- principal);
- args = null;
- } else {
- servlet.service((HttpServletRequest) request, (HttpServletResponse) response);
- }
- } else {
- servlet.service(request, response);
- }
- support
- .fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request,
- response);
- } catch (IOException e) {
- support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request,
- response, e);
- throw e;
- } catch (ServletException e) {
- support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request,
- response, e);
- throw e;
- } catch (RuntimeException e) {
- support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request,
- response, e);
- throw e;
- } catch (Throwable e) {
- support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request,
- response, e);
- throw new ServletException(sm.getString("filterChain.servlet"), e);
- } finally {
- if (Globals.STRICT_SERVLET_COMPLIANCE) {
- lastServicedRequest.set(null);
- lastServicedResponse.set(null);
- }
- }
- }
private void internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if (pos < n) { ApplicationFilterConfig filterConfig = filters[pos++]; Filter filter = null; try { // 得到当前Filter filter = filterConfig.getFilter(); support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT, filter, request, response); // 调用Filter的#doFilter()方法。 // 在Filter内部,如果Filter调用成功,会调用chain.doFilter(request,response); 这个语句。 // 这里传递给忒Filter的chain实例就是ApplicationFilterChain类的对象。 // 于是程序又回到了#doFilter(),然后再次调用本方法。也应该是一种变相的递归了。 if (Globals.IS_SECURITY_ENABLED) { final ServletRequest req = request; final ServletResponse res = response; Principal principal = ((HttpServletRequest) req).getUserPrincipal(); Object[] args = new Object[] { req, res, this }; SecurityUtil.doAsPrivilege("doFilter", filter, classType, args); args = null; } else { filter.doFilter(request, response, this); } support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response); } catch (IOException e) { if (filter != null) support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response, e); throw e; } catch (ServletException e) { if (filter != null) support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response, e); throw e; } catch (RuntimeException e) { if (filter != null) support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response, e); throw e; } catch (Throwable e) { if (filter != null) support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response, e); throw new ServletException(sm.getString("filterChain.filter"), e); } return; } try { if (Globals.STRICT_SERVLET_COMPLIANCE) { lastServicedRequest.set(request); lastServicedResponse.set(response); } // Filter全部调用完毕后,就会把请求真正的传递给Servlet了,调用它的#service()方法。 support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT, servlet, request, response); if ((request instanceof HttpServletRequest) && (response instanceof HttpServletResponse)) { if (Globals.IS_SECURITY_ENABLED) { final ServletRequest req = request; final ServletResponse res = response; Principal principal = ((HttpServletRequest) req).getUserPrincipal(); Object[] args = new Object[] { req, res }; SecurityUtil.doAsPrivilege("service", servlet, classTypeUsedInService, args, principal); args = null; } else { servlet.service((HttpServletRequest) request, (HttpServletResponse) response); } } else { servlet.service(request, response); } support .fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response); } catch (IOException e) { support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e); throw e; } catch (ServletException e) { support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e); throw e; } catch (RuntimeException e) { support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e); throw e; } catch (Throwable e) { support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e); throw new ServletException(sm.getString("filterChain.servlet"), e); } finally { if (Globals.STRICT_SERVLET_COMPLIANCE) { lastServicedRequest.set(null); lastServicedResponse.set(null); } } }
程序到了这里,就出现了分水岭,分别对应着对Servlet,JSP,和静态资源的处理。
Servlet比较简单,因为这里的"servlet"就是真实的Servlet实例了,直接调用开发人员自己编写的#service()方法了(#service()内部是会调用#doGet(),#doPost()等方法的)。
对于静态资源,是调用org.apache.catalina.servlets.DefaultServlet的#service()方法,由于DefaultServlet并没有重写这个方法,所以直接使用HttpServlet的#service()方法。但是DefaultServlet重写了#doGet(),#doPost()等方法(#doPost()内部又调用了#doGet()),所以请求就又到了#doGet()这个方法中,DefaultServlet的#doGet()只调用了#serveResource()这个方法来提取资源,代码太长,就不再仔细的看了。
对于JSP资源,就比较复杂了,还有编译等操作,下面来重点看一下。
首先,要调用org.apache.jasper.servlet.JspServlet的#service()方法,源代码如下:
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获得请求的JSP文件的路径 String jspUri = null; String jspFile = (String) request.getAttribute(Constants.JSP_FILE); if (jspFile != null) { // 通过web.xml中的<jsp-file>标签定义 jspUri = jspFile; } else { jspUri = (String) request.getAttribute(Constants.INC_SERVLET_PATH); if (jspUri != null) { String pathInfo = (String) request.getAttribute("javax.servlet.include.path_info"); if (pathInfo != null) { jspUri += pathInfo; } } else { jspUri = request.getServletPath(); String pathInfo = request.getPathInfo(); if (pathInfo != null) { jspUri += pathInfo; } } } if (log.isDebugEnabled()) { log.debug("JspEngine --> " + jspUri); log.debug("\t ServletPath: " + request.getServletPath()); log.debug("\t PathInfo: " + request.getPathInfo()); log.debug("\t RealPath: " + context.getRealPath(jspUri)); log.debug("\t RequestURI: " + request.getRequestURI()); log.debug("\t QueryString: " + request.getQueryString()); log.debug("\t Request Params: "); Enumeration e = request.getParameterNames(); while (e.hasMoreElements()) { String name = (String) e.nextElement(); log.debug("\t\t " + name + " = " + request.getParameter(name)); } } try { // 预编译模式,如果是预编译模式,只是对JSP进行编译,不会返回页面执行结果 boolean precompile = preCompile(request); // 继续JSP请求 serviceJspFile(request, response, jspUri, null, precompile); } catch (RuntimeException e) { throw e; } catch (ServletException e) { throw e; } catch (IOException e) { throw e; } catch (Throwable e) { throw new ServletException(e); } }
这里,有两个方法需要看一下,一个是预编译方法#preCompile(),另外一个是调用JSP的#serviceJspFile()方法。
首先来看一下#preCompile():
boolean preCompile(HttpServletRequest request) throws ServletException { // 获得查询字符串 String queryString = request.getQueryString(); if (queryString == null) { return (false); } // 看是否有预编译参数,默认是jsp_precompile int start = queryString.indexOf(Constants.PRECOMPILE); if (start < 0) { return (false); } queryString = queryString.substring(start + Constants.PRECOMPILE.length()); if (queryString.length() == 0) { return (true); } if (queryString.startsWith("&")) { return (true); } if (!queryString.startsWith("=")) { return (false); } int limit = queryString.length(); int ampersand = queryString.indexOf("&"); if (ampersand > 0) { limit = ampersand; } String value = queryString.substring(1, limit); // 如果jsp_precompile的值为true,代表此次请求为预编译JSP的请求。 if (value.equals("true")) { return (true); } else if (value.equals("false")) { // 这里要注意下,如果是false,同样是返回true的。 // 因为规范中说如果这个参数是false,那么请求不应该被提交到JSP页面的,那么此次请求就变得毫无意义了,所以索性都预编译好了。 return (true); } else {// 如果是true和false之外的值就要抛出异常了。 throw new ServletException("Cannot have request parameter " + Constants.PRECOMPILE + " set to " + value); } }
从这个方法中看出,要想预编译一个页面,只要在页面名字后加上查询字符串jsp_precompile=true就可以了。
下面是#serviceJspFile()方法,这个方法提供对请求进行了进一步的处理。
private void serviceJspFile(HttpServletRequest request, HttpServletResponse response, String jspUri, Throwable exception, boolean precompile) throws ServletException, IOException { // 获取JspServletWrapper实例 JspServletWrapper wrapper = (JspServletWrapper) rctxt.getWrapper(jspUri); if (wrapper == null) { synchronized (this) { wrapper = (JspServletWrapper) rctxt.getWrapper(jspUri); if (wrapper == null) { if (null == context.getResource(jspUri)) { String includeRequestUri = (String) request .getAttribute("javax.servlet.include.request_uri"); if (includeRequestUri != null) { String msg = Localizer.getMessage("jsp.error.file.not.found", jspUri); throw new ServletException(SecurityUtil.filter(msg)); } else { try { response.sendError(HttpServletResponse.SC_NOT_FOUND, request .getRequestURI()); } catch (IllegalStateException ise) { log.error(Localizer.getMessage("jsp.error.file.not.found", jspUri)); } } return; } boolean isErrorPage = exception != null; wrapper = new JspServletWrapper(config, options, jspUri, isErrorPage, rctxt); rctxt.addWrapper(jspUri, wrapper); } } } // 调用它的#service()方法。 wrapper.service(request, response, precompile); }
org.apache.jasper.servlet.JspServletWrapper的service()方法包括了编译,载入和执行Servlet几个步骤,如下所示:
public void service(HttpServletRequest request, HttpServletResponse response, boolean precompile) throws ServletException, IOException, FileNotFoundException { try { if (ctxt.isRemoved()) { throw new FileNotFoundException(jspUri); } if ((available > 0L) && (available < Long.MAX_VALUE)) { if (available > System.currentTimeMillis()) { response.setDateHeader("Retry-After", available); response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, Localizer .getMessage("jsp.error.unavailable")); return; } else { // Wait period has expired. Reset. available = 0; } } // (1) 编译 if (options.getDevelopment() || firstTime) { synchronized (this) { firstTime = false; // The following sets reload to true, if necessary ctxt.compile(); } } else { if (compileException != null) { // Throw cached compilation exception throw compileException; } } // (2) 载入Servlet类文件 getServlet(); // 如果是预编译,那么直接返回 if (precompile) { return; } } catch (ServletException ex) { if (options.getDevelopment()) { throw handleJspException(ex); } else { throw ex; } } catch (IOException ex) { if (options.getDevelopment()) { throw handleJspException(ex); } else { throw ex; } } catch (IllegalStateException ex) { if (options.getDevelopment()) { throw handleJspException(ex); } else { throw ex; } } catch (Exception ex) { if (options.getDevelopment()) { throw handleJspException(ex); } else { throw new JasperException(ex); } } try { // (3) 调用Servlet处理请求 if (theServlet instanceof SingleThreadModel) { synchronized (this) { theServlet.service(request, response); } } else { theServlet.service(request, response); } } catch (UnavailableException ex) { String includeRequestUri = (String) request .getAttribute("javax.servlet.include.request_uri"); if (includeRequestUri != null) { throw ex; } else { int unavailableSeconds = ex.getUnavailableSeconds(); if (unavailableSeconds <= 0) { unavailableSeconds = 60; // Arbitrary default } available = System.currentTimeMillis() + (unavailableSeconds * 1000L); response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, ex.getMessage()); } } catch (ServletException ex) { if (options.getDevelopment()) { throw handleJspException(ex); } else { throw ex; } } catch (IOException ex) { if (options.getDevelopment()) { throw handleJspException(ex); } else { throw ex; } } catch (IllegalStateException ex) { if (options.getDevelopment()) { throw handleJspException(ex); } else { throw ex; } } catch (Exception ex) { if (options.getDevelopment()) { throw handleJspException(ex); } else { throw new JasperException(ex); } } }
#compile()方法实现了对JSP文件向java类(Servlet)的编译,源代码如下所示:
public void compile() throws JasperException, FileNotFoundException { // 创建"jspCompiler"的实例 createCompiler(); // 判断是否过期,即是否需要重新编译,这个方法中主要用源代码和编译后的文件的修改时间等因素进行判断 if (jspCompiler.isOutDated()) { try { jspCompiler.removeGeneratedFiles(); jspLoader = null; // 执行编译 jspCompiler.compile(); // 设定reload标志为true,让#getServlet()方法载入新的类 jsw.setReload(true); jsw.setCompilationException(null); } catch (JasperException ex) { // Cache compilation exception jsw.setCompilationException(ex); throw ex; } catch (Exception ex) { JasperException je = new JasperException( Localizer.getMessage("jsp.error.unable.compile"), ex); // Cache compilation exception jsw.setCompilationException(je); throw je; } } }
可以看出,JSP页面没有修改的前提下Tomcat是不会对JSP进行多次编译的,只在第一次调用它的时候编译。
看完#compile()后,再来看一下#getServlet(),它载入了前面编译生成的Servlet类。
public Servlet getServlet() throws ServletException, IOException, FileNotFoundException { if (reload) { synchronized (this) { if (reload) { // 销毁旧的Servlet destroy(); Servlet servlet = null; try { // 载入Servlet servletClass = ctxt.load(); servlet = (Servlet) servletClass.newInstance(); AnnotationProcessor annotationProcessor = (AnnotationProcessor) config .getServletContext().getAttribute( AnnotationProcessor.class.getName()); if (annotationProcessor != null) { annotationProcessor.processAnnotations(servlet); annotationProcessor.postConstruct(servlet); } } catch (IllegalAccessException e) { throw new JasperException(e); } catch (InstantiationException e) { throw new JasperException(e); } catch (Exception e) { throw new JasperException(e); } // Servlet初始化 servlet.init(config); if (!firstTime) { ctxt.getRuntimeContext().incrementJspReloadCount(); } theServlet = servlet; // reload值复原 reload = false; } } } return theServlet; }
通过这个类,获得了一个"theServlet"实例作为JSP编译之后的Servlet引用,并且在JSP没有改动前,这个实例是不需要重新生成的。
通过这两个步骤后,最后调用了JSP编译后的Servlet类的#service()方法去处理请求。至此,Tomcat的请求处理结束了。
发表评论
-
出现java.lang.UnsupportedClassVersionError 错误的原因
2010-08-16 23:11 871出现java.lang.UnsupportedClassVer ... -
请求在Tomcat中传到了CoyoteAdapter的#service()方法中后,就要准备进入Pi
2009-05-07 11:35 1812首先,来看一下Servlet的载入过程。 具体是在org.ap ... -
Tomcat请求处理(五) -- 请求在容器间的流动
2009-05-07 11:34 1435请求在Tomcat中传到了CoyoteAdapter的#ser ... -
Tomcat请求处理(四) -- Request, Response, 和Pipeline
2009-05-07 11:33 12851. Request和Response 当处理请求的时候,To ... -
Tomcat请求处理(三) -- coyote请求处理
2009-05-07 11:32 1325在上一篇文章文章中,Tomcat的请求处理到了JIoEndpo ... -
Tomcat请求处理(二) -- 请求处理框架
2009-05-07 11:30 991书接上文。 当Tomcat的Acceptor监听到有请求到来时 ... -
Tomcat请求处理(一) -- 服务器端口监听
2009-05-07 11:29 1402其实tomcat在哪个类中监听请求的代码很容易找到: 在org ... -
Tomcat启动部分源代码分析(五) -- 应用程序加载
2009-05-07 11:28 1200前面所叙述的tomcat启动 ... -
Tomcat启动部分源代码分析(四) -- 开启容器
2009-05-07 11:27 1205四. 开启容器 最后是Bootstrap#start()方法的 ... -
Tomcat启动部分源代码分析(三) -- 载入
2009-05-07 11:23 1195二. 载入 2. Bootstrap的#Bootstrap#l ... -
Tomcat启动部分源代码分析(二) -- 初始化
2009-05-07 11:20 1098二. 初始化 1. 首先是Bootstrap的#init()操 ... -
Tomcat启动部分源代码分析(一) -- 概览
2009-05-07 11:17 1433一. 概览 本文所涉及的Tomcat为6.0版本。 Tomca ... -
Tomcat的Session管理(二) - Session后台处理
2009-05-07 10:10 973Tomcat会开启一个后台线程每隔一段时间检查Session的 ... -
Tomcat的Session管理(一) - Session的生成
2009-05-07 10:02 1499Session对象的创建一般是源于这样的一条语句: Sessi ...
相关推荐
每个Servlet都必须实现`init()`, `service()`, `destroy()`这三个方法,分别对应Servlet的初始化、处理请求和销毁的生命周期阶段。Tomcat源码中,这些方法的实现为Servlet提供了标准的运行环境。 2. **Servlet容器*...
在Servlet的生命周期中,`init()`方法在Servlet实例化后首次被调用,用于初始化Servlet;`service()`方法处理客户端请求;而`destroy()`方法在Servlet销毁前执行,用于释放资源。源码中,我们可以看到这些方法的具体...
因此,对于同一Servlet实例,`init()`方法只在对象创建时调用一次,而`service()`方法则在每次请求时调用。 5. **销毁**: 当Web应用程序卸载或Tomcat服务器关闭时,Servlet的`destroy()`方法会被调用,这提供了...
- **StandardWrapper**:当找到匹配的Servlet后,容器会将请求传递给具体的Servlet实例。 - **StandardWrapperValve**:容器中的包装器阀(StandardWrapperValve)负责执行Servlet的生命周期方法,如`service()`。 -...
4. **Servlet实例**:通过实际案例,演示如何编写和运行Servlet。 5. **Servlet与JSP结合**:讲解如何在Servlet中转发或重定向到JSP页面,以及数据传递的方法。 6. **Servlet的高级特性**:如多线程处理、过滤器...
Tomcat通过解析HTTP请求,调用相应的Servlet实例,执行业务逻辑,并将结果返回给客户端。在Tomcat中,Servlets和JSPs通常一起使用,JSP用于生成动态HTML内容,而Servlet则负责处理业务逻辑。 Tomcat 7.0.64是该软件...
当容器收到对Servlet的请求时,它将实例化Servlet或创建一个新的线程来处理请求,然后调用Servlet的方法(如doPost()或doGet())。 4. Servlet的方法:Servlet有两个主要方法:doPost()和doGet()。doPost()方法处理...
该方法根据请求类型(GET、POST等)选择合适的`doGet()`或`doPost()`等方法来处理请求。 3. 销毁:当Web应用被卸载或者服务器关闭时,Web容器会调用Servlet的`destroy()`方法,释放Servlet占用的资源。 四、Servlet...
Servlet容器接收HTTP请求,创建Servlet实例,调用Servlet的方法来处理请求,并将响应返回给客户端。 2. **JSP支持**:除了Servlet,Tomcat还支持JSP技术,使得开发者可以使用HTML、CSS和Java代码混合编写动态网页。...
Servlet容器(如Tomcat)接收HTTP请求,创建相应的Servlet实例,调用Servlet的`service()`方法来处理请求。Servlet可以根据请求方法(GET、POST等)执行不同的操作,并通过`doGet()`或`doPost()`方法生成响应内容。...
CGI Servlet允许Tomcat服务器处理CGI(Common Gateway Interface)请求,这些请求可以调用服务器上的外部程序来生成动态内容。攻击者可以通过发送特别构造的CGI请求,利用这个漏洞在具有Apache Tomcat权限的系统上...
开发者通常会重写`init()`方法进行初始化操作,`service()`方法处理请求,以及`destroy()`方法释放资源。 创建Servlet有三种方式: 1. 实现Servlet接口,覆盖其中的方法。 2. 继承HttpServlet类,该类已经实现了...
2. **处理请求**: 当用户提交猜测后,Servlet通过`doPost()`方法接收到请求。请求参数通常包含用户的猜测值,可以从`HttpServletRequest`对象中获取。 3. **验证猜测**: Servlet将接收到的猜测值与目标数字进行比较...
如果是,容器会根据Servlet的配置信息创建Servlet实例,调用其`service()`方法来处理请求。`service()`方法会自动选择适当的`doGet()`或`doPost()`方法,具体取决于HTTP请求的方法类型(GET或POST)。 接下来,我们...
4. **执行Servlet**:Tomcat创建一个Servlet实例(如果尚未创建),调用其`service()`方法来处理请求。 5. **响应生成**:Servlet生成响应内容,可能是HTML、JSON或其他格式,然后返回给Tomcat。 6. **发送响应**:...
对于高并发场景,为了提高性能和资源利用率,Servlet容器通常会采用线程池来处理请求,而不是为每个请求创建一个新的Servlet实例。 1. **线程安全问题**: - 当多个请求同时到达Servlet时,Tomcat会从线程池中取出...
4. 销毁:当Servlet不再需要时,Tomcat会调用`destroy()`方法释放资源,然后销毁Servlet实例。 在描述中提到的“博文链接:https://hbiao68.iteye.com/blog/1570415”可能提供了一个具体的示例或问题解决方案,但...
在Web应用启动时,Servlet容器会根据web.xml或注解加载Servlet实例,并调用`init`方法进行初始化。在接收到请求时,调用`service`方法处理请求。当Web应用关闭或Servlet不再需要时,调用`destroy`方法进行清理。 四...
源码中的`catalina`目录包含了这部分内容,你可以看到如何解析请求、创建响应以及管理Servlet实例。 2. **JSP引擎**:Tomcat也实现了JSP规范,允许开发者使用动态HTML。这部分源码主要位于`jasper`目录下,包含JSP...
接着,服务器根据请求调用Servlet的`service()`方法,该方法会根据请求类型(GET、POST等)选择适当的方法来处理请求。在Servlet执行完任务后,如果服务器决定关闭或者更新Servlet,将调用`destroy()`方法,让...