- 浏览: 137885 次
- 性别:
- 来自: 杭州
最新评论
-
Golden_Sky:
需要自己写代码来调用么?还是他自己如果有配置级别的错误时候他就 ...
log4j 邮件 配置 -
Golden_Sky:
luckaway 写道我想相信问一下,这个如果在配置文件中配置 ...
log4j 邮件 配置 -
Golden_Sky:
panda_eyes 写道我也试用过了 还用这个在工作交流会 ...
log4j 邮件 配置 -
Golden_Sky:
sealv 写道你这个是啥版本 为啥我这没有setSMTPUs ...
log4j 邮件 配置 -
Golden_Sky:
我想相信问一下,这个如果在配置文件中配置好了,比如我调整的级别 ...
log4j 邮件 配置
网上已经有很多关于redirect和forward区别的文章,更多的都是只是一些概念上的描述,虽然在大多情况下,知道这些就已经足够了。但也有例外:forward not working for struts2,why?我也是在工作中碰到了这个问题,才特意看了下tomcat有关这部分的源代码。深刻的了解下也无妨。
redirect和forward都是属于servlet规范的,不同的servlet容器的实现可能会有一些区别,但原理都是类似的。
redirect和forward的定义:
1. redirect(重定向):服务端发送给客户端一个重定向的临时响应头,这个响应头包含重定向之后的URL,客户端用新的URL重新向服务器发送一个请求。
2. forward(请求转向):服务器程序内部请求转向,这个特性允许前一个程序用于处理请求,而后一个程序用来返回响应。
Redirect的原理比较简单,它的定义也已经描述的很清楚了,我也不想多讲什么,就贴一段简单的代码吧!
org.apache.catalina.connector.Response#sendRedirect(String):
方法行为:先把相对路径转换成绝对路径,再包装一个包含有新的URL的临时响应头,“SC_FOUND”的值是302,就是重定向临时响应头的状态码。如果传入的“location”值不合法,就包装一个404的响应头。
下面就来看看tomcat是如何实现forward的,forward为什么在struts2下会无效(注解:其实是可以设置的)。
先看下程序是如何调用forward的:
整个过程分两个步骤来执行
1. 得到一个请求调度器
2. 通过调度器把请求转发过去。
第一步骤,获取请求调度器。
org.apache.catalina.connector.Request#getRequestDispatcher(String)
方法行为:把获取RequestDispatcher的任务交个内部的request。它们之间的关系如下所示
org.apache.catalina.connector.RequestFacade和类org.apache.catalina.connector.Request都是实现了javax.servlet.http.HttpServletRequest接口,而RequestFacade内部有包装了个Request,对Request的访问做了些控制,应该是代理模式
org.apache.catalina.connector.Request#getRequestDispatcher(String)
方法行为:把绝对路径转换成相对路径,最终的格式如“/testForward”。若已经是这种格式的相对路径,就无需再转换了。
接下来就转交给ServletContext来处理,ServletContext是web项目的一个上下文,包含所有的Servlet集合,还定义了一些Servlet与容器之间交互的接口。
org.apache.catalina.core.ApplicationContext#getRequestDispatcher(String)
方法行为:根据路径名“path”找到一个包含有Servlet的Wrapper,最后实例化一个ApplicationDispatcher,并且返回该ApplicationDispatcher。
该方法里非常关键的一行:context.getMapper().map(uriMB, mappingData)。
Mapper的类定义我不知道如何描述,就贴上原文吧:Mapper, which implements the servlet API mapping rules (which are derived from the HTTP rules)。
不过只想了解forward的原理,熟悉map函数就够了。
org.apache.tomcat.util.http.mapper.Mapper#map(org.apache.tomcat.util.buf.MessageBytes, org.apache.tomcat.util.http.mapper.MappingData):
方法行为:。。。。。。。就介绍下参数吧,uri可以理解是path(“/testforward”)的一个变形,而mappingData用于存储当前线程用到的部分数据。该函数是没有返回值的,处理之后的结果就是存放到mappingData里的。
org.apache.tomcat.util.http.mapper.Mapper#internalMapWrapper(Mapper$Context,org.apache.tomcat.util.buf.CharChunk, org.apache.tomcat.util.http.mapper.MappingData):
方法行为:通过“path”从“context”里找到对应的Servlet,存放到“mappingData”里。
可以看到这里有7个匹配Servlet规则:
1. Rule 1 -- Exact Match:精确匹配,匹配web.xml配置的格式如“<url-pattern>/testQiu</url-pattern>”的Servlet
2. Rule 2 -- Prefix Matcha:前缀匹配,匹配的Servlet格式如“<url-pattern>/testQiu/*</url-pattern>”
3. Rule 3 -- Extension Match:扩展匹配,匹配jsp或者jspx
4. ---Rule 4a -- Welcome resources processing for exact macth:
5. ---Rule 4b -- Welcome resources processing for prefix match:
6. ---Rule 4c -- Welcome resources processing for physical folder:
7. Rule 7 --如果前面6条都没匹配到,那就返回org.apache.catalina.servlets.DefaultServlet。
其实这里真正的匹配的是Wapper,而不是Servlet,因为Wapper最重要的一个属性就是Servlet,说成“匹配Servlet”是为了更容易的表达。
至此返回RequestDispatcher就结束了。
接下来就是讲解RequestDispatcher.forward了。Forward的就不贴出全部的源代码,只贴一些重要的片段,绝大部分的逻辑都在org.apache.catalina.core.ApplicationDispatcher类里。
先描述下过程:
1. 设置request里的部分属性值,如:请求的路径、参数等。
2. 组装一个FilterChain链,调用doFilter方法。
3. 最后根据实际情况调用Filter的doFilter函数或者Servlet的service函数。
注:FilterChain和Filter是两个不同的接口,两个接口的UML
org.apache.catalina.core.ApplicationDispatcher#doForward(ServletRequest,ServletResponse):
第1步:设置新的request的属性:
第2步:组装FitlerChain链,根据web.xml配置信息,是否决定添加Filter----
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
org.apache.catalina.core.ApplicationFilterFactory#createFilterChain(ServletRequest, Wrapper, Servlet):
如果是<dispatcher>REQUEST</dispatcher>,那就不添加Filter,默认设置是REQUEST
如果是<dispatcher>FORWARD</dispatcher>,添加Filter到FilterChain。
第3步:调用doFilter或者service,代码删减了很多。
org.apache.catalina.core.ApplicationFilterChain#doFilter(ServletRequest, ServletResponse):
如果我对Filter非常了解的,根本就不需要花那么多时间去查看tomcat源代码。只要在web.xml增加一点配置就OK了。
forward到*.jsp那是没问题的
两个都配置起来,本来以为FORWARD是包含REQUEST。
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.htm</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
刚我试过了,可以用的
LZ,我以前好像也有遇到过你这样的问题,不过好像Sturts2.0他的默认方式是用forward的,所以也可以不用设置的。你试试呢!
赞楼主一个,想问下lz,Tomcat中SessionListener的机制。多个Session同时创建时,是形成一个队列调用session.create方法,还是各自并发地调用session.create方法?
应该需要分析源码吧?(给我点提示也可以)谢谢啦!
并发的调用session.create方法的,是设置sessionId的时候通知接听器的!!!
org.apache.catalina.session.StandardSession
tellNew():
必须要保证SessionListener的实现类是线程安全的!
如果你对接听器模式不太了解的话,建议你先去学习接听器模式!
SessionListener就是接听器模式
赞楼主一个,想问下lz,Tomcat中SessionListener的机制。多个Session同时创建时,是形成一个队列调用session.create方法,还是各自并发地调用session.create方法?
应该需要分析源码吧?(给我点提示也可以)谢谢啦!
两个都配置起来,本来以为FORWARD是包含REQUEST。
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.htm</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
刚我试过了,可以用的
我照你的配了报错啦 500 错误
贴一点错误
你是不是tomcat版本太低了! dispatcher的特性是servlet2.4规范里加的!
tomcat版本和servlet规范的对应
http://tomcat.apache.org/whichversion.html
两个都配置起来,本来以为FORWARD是包含REQUEST。
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.htm</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
刚我试过了,可以用的
我照你的配了报错啦 500 错误
贴一点错误
两个都配置起来,本来以为FORWARD是包含REQUEST。
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.htm</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
刚我试过了,可以用的
redirect和forward都是属于servlet规范的,不同的servlet容器的实现可能会有一些区别,但原理都是类似的。
redirect和forward的定义:
1. redirect(重定向):服务端发送给客户端一个重定向的临时响应头,这个响应头包含重定向之后的URL,客户端用新的URL重新向服务器发送一个请求。
2. forward(请求转向):服务器程序内部请求转向,这个特性允许前一个程序用于处理请求,而后一个程序用来返回响应。
Redirect的原理比较简单,它的定义也已经描述的很清楚了,我也不想多讲什么,就贴一段简单的代码吧!
org.apache.catalina.connector.Response#sendRedirect(String):
public void sendRedirect(String location) throws IOException { if (isCommitted()) throw new IllegalStateException (sm.getString("coyoteResponse.sendRedirect.ise")); // Ignore any call from an included servlet if (included) return; // Clear any data content that has been buffered resetBuffer(); // Generate a temporary redirect to the specified location try { String absolute = toAbsolute(location); setStatus(SC_FOUND); setHeader("Location", absolute); } catch (IllegalArgumentException e) { setStatus(SC_NOT_FOUND); } // Cause the response to be finished (from the application perspective) setSuspended(true); }
方法行为:先把相对路径转换成绝对路径,再包装一个包含有新的URL的临时响应头,“SC_FOUND”的值是302,就是重定向临时响应头的状态码。如果传入的“location”值不合法,就包装一个404的响应头。
下面就来看看tomcat是如何实现forward的,forward为什么在struts2下会无效(注解:其实是可以设置的)。
先看下程序是如何调用forward的:
req.getRequestDispatcher("testForward").forward(req, resp);
整个过程分两个步骤来执行
1. 得到一个请求调度器
2. 通过调度器把请求转发过去。
第一步骤,获取请求调度器。
org.apache.catalina.connector.Request#getRequestDispatcher(String)
public RequestDispatcher getRequestDispatcher(String path) { if (request == null) { throw new IllegalStateException( sm.getString("requestFacade.nullRequest")); } if (Globals.IS_SECURITY_ENABLED){ return (RequestDispatcher)AccessController.doPrivileged( new GetRequestDispatcherPrivilegedAction(path)); } else { return request.getRequestDispatcher(path); }
方法行为:把获取RequestDispatcher的任务交个内部的request。它们之间的关系如下所示
org.apache.catalina.connector.RequestFacade和类org.apache.catalina.connector.Request都是实现了javax.servlet.http.HttpServletRequest接口,而RequestFacade内部有包装了个Request,对Request的访问做了些控制,应该是代理模式
org.apache.catalina.connector.Request#getRequestDispatcher(String)
public RequestDispatcher getRequestDispatcher(String path) { if (path.startsWith("/")) return (context.getServletContext().getRequestDispatcher(path)); //省略了部分代码 return (context.getServletContext().getRequestDispatcher(relative)); }
方法行为:把绝对路径转换成相对路径,最终的格式如“/testForward”。若已经是这种格式的相对路径,就无需再转换了。
接下来就转交给ServletContext来处理,ServletContext是web项目的一个上下文,包含所有的Servlet集合,还定义了一些Servlet与容器之间交互的接口。
org.apache.catalina.core.ApplicationContext#getRequestDispatcher(String)
public RequestDispatcher getRequestDispatcher(String path) { //省去部分代码 context.getMapper().map(uriMB, mappingData); //省去部分代码 Wrapper wrapper = (Wrapper) mappingData.wrapper; String wrapperPath = mappingData.wrapperPath.toString(); String pathInfo = mappingData.pathInfo.toString(); mappingData.recycle(); // Construct a RequestDispatcher to process this request return new ApplicationDispatcher (wrapper, uriCC.toString(), wrapperPath, pathInfo, queryString, null); }
方法行为:根据路径名“path”找到一个包含有Servlet的Wrapper,最后实例化一个ApplicationDispatcher,并且返回该ApplicationDispatcher。
该方法里非常关键的一行:context.getMapper().map(uriMB, mappingData)。
Mapper的类定义我不知道如何描述,就贴上原文吧:Mapper, which implements the servlet API mapping rules (which are derived from the HTTP rules)。
不过只想了解forward的原理,熟悉map函数就够了。
org.apache.tomcat.util.http.mapper.Mapper#map(org.apache.tomcat.util.buf.MessageBytes, org.apache.tomcat.util.http.mapper.MappingData):
public void map(MessageBytes uri, MappingData mappingData) throws Exception { uri.toChars(); CharChunk uricc = uri.getCharChunk(); uricc.setLimit(-1); internalMapWrapper(context, uricc, mappingData); }
方法行为:。。。。。。。就介绍下参数吧,uri可以理解是path(“/testforward”)的一个变形,而mappingData用于存储当前线程用到的部分数据。该函数是没有返回值的,处理之后的结果就是存放到mappingData里的。
org.apache.tomcat.util.http.mapper.Mapper#internalMapWrapper(Mapper$Context,org.apache.tomcat.util.buf.CharChunk, org.apache.tomcat.util.http.mapper.MappingData):
private final void internalMapWrapper(Context context, CharChunk path, MappingData mappingData) throws Exception { int pathOffset = path.getOffset(); int pathEnd = path.getEnd(); int servletPath = pathOffset; boolean noServletPath = false; int length = context.name.length(); if (length != (pathEnd - pathOffset)) { servletPath = pathOffset + length; } else { noServletPath = true; path.append('/'); pathOffset = path.getOffset(); pathEnd = path.getEnd(); servletPath = pathOffset+length; } path.setOffset(servletPath); // Rule 1 -- Exact Match Wrapper[] exactWrappers = context.exactWrappers; internalMapExactWrapper(exactWrappers, path, mappingData); // Rule 2 -- Prefix Match boolean checkJspWelcomeFiles = false; Wrapper[] wildcardWrappers = context.wildcardWrappers; if (mappingData.wrapper == null) { internalMapWildcardWrapper(wildcardWrappers, context.nesting, path, mappingData); if (mappingData.wrapper != null && mappingData.jspWildCard) { char[] buf = path.getBuffer(); if (buf[pathEnd - 1] == '/') { /* * Path ending in '/' was mapped to JSP servlet based on * wildcard match (e.g., as specified in url-pattern of a * jsp-property-group. * Force the context's welcome files, which are interpreted * as JSP files (since they match the url-pattern), to be * considered. See Bugzilla 27664. */ mappingData.wrapper = null; checkJspWelcomeFiles = true; } else { // See Bugzilla 27704 mappingData.wrapperPath.setChars(buf, path.getStart(), path.getLength()); mappingData.pathInfo.recycle(); } } } if(mappingData.wrapper == null && noServletPath) { // The path is empty, redirect to "/" mappingData.redirectPath.setChars (path.getBuffer(), pathOffset, pathEnd); path.setEnd(pathEnd - 1); return; } // Rule 3 -- Extension Match Wrapper[] extensionWrappers = context.extensionWrappers; if (mappingData.wrapper == null && !checkJspWelcomeFiles) { internalMapExtensionWrapper(extensionWrappers, path, mappingData); } // Rule 4 -- Welcome resources processing for servlets if (mappingData.wrapper == null) { boolean checkWelcomeFiles = checkJspWelcomeFiles; if (!checkWelcomeFiles) { char[] buf = path.getBuffer(); checkWelcomeFiles = (buf[pathEnd - 1] == '/'); } if (checkWelcomeFiles) { for (int i = 0; (i < context.welcomeResources.length) && (mappingData.wrapper == null); i++) { path.setOffset(pathOffset); path.setEnd(pathEnd); path.append(context.welcomeResources[i], 0, context.welcomeResources[i].length()); path.setOffset(servletPath); // Rule 4a -- Welcome resources processing for exact macth internalMapExactWrapper(exactWrappers, path, mappingData); // Rule 4b -- Welcome resources processing for prefix match if (mappingData.wrapper == null) { internalMapWildcardWrapper (wildcardWrappers, context.nesting, path, mappingData); } // Rule 4c -- Welcome resources processing // for physical folder if (mappingData.wrapper == null && context.resources != null) { Object file = null; String pathStr = path.toString(); try { file = context.resources.lookup(pathStr); } catch(NamingException nex) { // Swallow not found, since this is normal } if (file != null && !(file instanceof DirContext) ) { internalMapExtensionWrapper(extensionWrappers, path, mappingData); if (mappingData.wrapper == null && context.defaultWrapper != null) { mappingData.wrapper = context.defaultWrapper.object; mappingData.requestPath.setChars (path.getBuffer(), path.getStart(), path.getLength()); mappingData.wrapperPath.setChars (path.getBuffer(), path.getStart(), path.getLength()); mappingData.requestPath.setString(pathStr); mappingData.wrapperPath.setString(pathStr); } } } } path.setOffset(servletPath); path.setEnd(pathEnd); } }
方法行为:通过“path”从“context”里找到对应的Servlet,存放到“mappingData”里。
可以看到这里有7个匹配Servlet规则:
1. Rule 1 -- Exact Match:精确匹配,匹配web.xml配置的格式如“<url-pattern>/testQiu</url-pattern>”的Servlet
2. Rule 2 -- Prefix Matcha:前缀匹配,匹配的Servlet格式如“<url-pattern>/testQiu/*</url-pattern>”
3. Rule 3 -- Extension Match:扩展匹配,匹配jsp或者jspx
4. ---Rule 4a -- Welcome resources processing for exact macth:
5. ---Rule 4b -- Welcome resources processing for prefix match:
6. ---Rule 4c -- Welcome resources processing for physical folder:
7. Rule 7 --如果前面6条都没匹配到,那就返回org.apache.catalina.servlets.DefaultServlet。
其实这里真正的匹配的是Wapper,而不是Servlet,因为Wapper最重要的一个属性就是Servlet,说成“匹配Servlet”是为了更容易的表达。
至此返回RequestDispatcher就结束了。
接下来就是讲解RequestDispatcher.forward了。Forward的就不贴出全部的源代码,只贴一些重要的片段,绝大部分的逻辑都在org.apache.catalina.core.ApplicationDispatcher类里。
先描述下过程:
1. 设置request里的部分属性值,如:请求的路径、参数等。
2. 组装一个FilterChain链,调用doFilter方法。
3. 最后根据实际情况调用Filter的doFilter函数或者Servlet的service函数。
注:FilterChain和Filter是两个不同的接口,两个接口的UML
org.apache.catalina.core.ApplicationDispatcher#doForward(ServletRequest,ServletResponse):
private void doForward(ServletRequest request, ServletResponse response) throws ServletException, IOException //省略了部分代码 // Handle an HTTP named dispatcher forward if ((servletPath == null) && (pathInfo == null)) { //省略了部分代码 } else {// Handle an HTTP path-based forward ApplicationHttpRequest wrequest = (ApplicationHttpRequest) wrapRequest(state); String contextPath = context.getPath(); HttpServletRequest hrequest = state.hrequest; if (hrequest.getAttribute(Globals.FORWARD_REQUEST_URI_ATTR) == null) { wrequest.setAttribute(Globals.FORWARD_REQUEST_URI_ATTR, hrequest.getRequestURI()); wrequest.setAttribute(Globals.FORWARD_CONTEXT_PATH_ATTR, hrequest.getContextPath()); wrequest.setAttribute(Globals.FORWARD_SERVLET_PATH_ATTR, hrequest.getServletPath()); wrequest.setAttribute(Globals.FORWARD_PATH_INFO_ATTR, hrequest.getPathInfo()); wrequest.setAttribute(Globals.FORWARD_QUERY_STRING_ATTR, hrequest.getQueryString()); } wrequest.setContextPath(contextPath); wrequest.setRequestURI(requestURI); wrequest.setServletPath(servletPath); wrequest.setPathInfo(pathInfo); if (queryString != null) { wrequest.setQueryString(queryString); wrequest.setQueryParams(queryString); } processRequest(request,response,state); } } //省略了部分代码 }
第1步:设置新的request的属性:
wrequest.setContextPath(contextPath); wrequest.setRequestURI(requestURI); wrequest.setServletPath(servletPath); wrequest.setPathInfo(pathInfo); if (queryString != null) { wrequest.setQueryString(queryString); wrequest.setQueryParams(queryString); }
第2步:组装FitlerChain链,根据web.xml配置信息,是否决定添加Filter----
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
org.apache.catalina.core.ApplicationFilterFactory#createFilterChain(ServletRequest, Wrapper, Servlet):
public ApplicationFilterChain createFilterChain(ServletRequest request, Wrapper wrapper, Servlet servlet) { //省略部分代码 filterChain = new ApplicationFilterChain(); } filterChain.setServlet(servlet); filterChain.setSupport (((StandardWrapper)wrapper).getInstanceSupport()); // Acquire the filter mappings for this Context StandardContext context = (StandardContext) wrapper.getParent(); FilterMap filterMaps[] = context.findFilterMaps(); // If there are no filter mappings, we are done if ((filterMaps == null) || (filterMaps.length == 0)) return (filterChain); // Acquire the information we will need to match filter mappings String servletName = wrapper.getName(); // Add the relevant path-mapped filters to this filter chain for (int i = 0; i < filterMaps.length; i++) { if (!matchDispatcher(filterMaps[i] ,dispatcher)) { continue; } if (!matchFiltersURL(filterMaps[i], requestPath)) continue; ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) context.findFilterConfig(filterMaps[i].getFilterName()); if (filterConfig == null) { ; // FIXME - log configuration problem continue; } boolean isCometFilter = false; if (comet) { try { isCometFilter = filterConfig.getFilter() instanceof CometFilter; } catch (Exception e) { // Note: The try catch is there because getFilter has a lot of // declared exceptions. However, the filter is allocated much // earlier } if (isCometFilter) { filterChain.addFilter(filterConfig); } } else { filterChain.addFilter(filterConfig); } } //省略部分代码 // Return the completed filter chain return (filterChain); }
如果是<dispatcher>REQUEST</dispatcher>,那就不添加Filter,默认设置是REQUEST
如果是<dispatcher>FORWARD</dispatcher>,添加Filter到FilterChain。
第3步:调用doFilter或者service,代码删减了很多。
org.apache.catalina.core.ApplicationFilterChain#doFilter(ServletRequest, ServletResponse):
public void doFilter(ServletRequest request, ServletResponse response)throws IOException, ServletException { internalDoFilter(request,response); } org.apache.catalina.core.ApplicationFilterChain#internalDoFilter(ServletRequest, ServletResponse) private void internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { // Call the next filter if there is one if (pos < n) { filter.doFilter(request, response, this); return; } servlet.service((HttpServletRequest) request,(HttpServletResponse) response); }
如果我对Filter非常了解的,根本就不需要花那么多时间去查看tomcat源代码。只要在web.xml增加一点配置就OK了。
<filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping>
评论
32 楼
cutesource
2010-07-20
<div class="quote_title">lsb 写道</div>
<div class="quote_div"> LZ 看这个有什么好的资料吗?推荐下看看。</div>
<p> </p>
<p>推荐你看<a href="http://download.csdn.net/source/1039743">《how tomcat works》</a></p>
<p>另外我也做过有关tomcat的源码分析,有兴趣可以参考一下:</p>
<h1 class="title_txt"><span style="font-size: medium;"><a href="http://blog.csdn.net/cutesource/archive/2009/12/14/5006062.aspx">Tomcat
源码分析(一)------ 架构</a></span></h1>
<h1 class="title_txt"><span style="font-size: medium;"><a href="http://blog.csdn.net/cutesource/archive/2009/12/19/5040417.aspx">Tomcat
源码分析(二)------ 一次完整请求的里里外外</a></span></h1>
<h1 class="title_txt"><span style="font-size: medium;"><a href="http://blog.csdn.net/cutesource/archive/2009/12/26/5081916.aspx">Tomcat
源码分析(三)------ 可携带状态的线程池</a></span></h1>
<h1 class="title_txt"><span style="font-size: medium;"><a href="http://blog.csdn.net/cutesource/archive/2009/12/28/5091732.aspx">Tomcat
源码分析(四)------ Request和Response处理的全过程</a></span></h1>
<div class="quote_div"> LZ 看这个有什么好的资料吗?推荐下看看。</div>
<p> </p>
<p>推荐你看<a href="http://download.csdn.net/source/1039743">《how tomcat works》</a></p>
<p>另外我也做过有关tomcat的源码分析,有兴趣可以参考一下:</p>
<h1 class="title_txt"><span style="font-size: medium;"><a href="http://blog.csdn.net/cutesource/archive/2009/12/14/5006062.aspx">Tomcat
源码分析(一)------ 架构</a></span></h1>
<h1 class="title_txt"><span style="font-size: medium;"><a href="http://blog.csdn.net/cutesource/archive/2009/12/19/5040417.aspx">Tomcat
源码分析(二)------ 一次完整请求的里里外外</a></span></h1>
<h1 class="title_txt"><span style="font-size: medium;"><a href="http://blog.csdn.net/cutesource/archive/2009/12/26/5081916.aspx">Tomcat
源码分析(三)------ 可携带状态的线程池</a></span></h1>
<h1 class="title_txt"><span style="font-size: medium;"><a href="http://blog.csdn.net/cutesource/archive/2009/12/28/5091732.aspx">Tomcat
源码分析(四)------ Request和Response处理的全过程</a></span></h1>
31 楼
lsb
2010-06-20
LZ 看这个有什么好的资料吗?推荐下看看。
30 楼
shmilyzyn
2010-06-07
mark下,有时间看看
29 楼
tzm1984
2010-06-04
mark一下,有时间也来研究下源码,就是自己太懒!
28 楼
hilor
2010-06-03
mark下, 支持源码研究贴, 有时间来看看
27 楼
不知云
2010-06-02
我也mark一下,以后再看。
26 楼
transist
2010-04-02
这股认真劲值得学习
25 楼
池中物
2010-03-31
嗯,新规范,默认request.forward是不需要经过的filte处理r的
配置了<dispatcher>FORWARD</dispatcher>就是要经过filter了
配置了<dispatcher>FORWARD</dispatcher>就是要经过filter了
24 楼
jackdown
2010-03-31
写的挺详细的,有空好好拜读,谢谢分享经验心得。
23 楼
luckaway
2010-01-04
vera_sq 写道
具体情况是这样的,用户登录后,url地址栏显示的地址是http://localhost:8080/mediaServer/view/login!login.action;jsessionid=BC71820C36F64745F0E850548D4F1403,但是用户希望不要这样显示,所以当时我在struts.xml里面配置了type="redirect"。这样用户登录后,进去的url地址就是http://localhost:8080/mediaServer/view/login.jsp这样的,但是其它的action请求我并没有设置他的type属性,他就是默认的forward。
forward到*.jsp那是没问题的
22 楼
vera_sq
2010-01-04
具体情况是这样的,用户登录后,url地址栏显示的地址是http://localhost:8080/mediaServer/view/login!login.action;jsessionid=BC71820C36F64745F0E850548D4F1403,但是用户希望不要这样显示,所以当时我在struts.xml里面配置了type="redirect"。这样用户登录后,进去的url地址就是http://localhost:8080/mediaServer/view/login.jsp这样的,但是其它的action请求我并没有设置他的type属性,他就是默认的forward。
21 楼
vera_sq
2010-01-04
luckaway 写道
vera_sq 写道
LZ,我在web.xml配置中增加<dispatcher>FORWARD</dispatcher>这句配置后,发送请求就报404错误啊!
我的项目用的是ssh+tomcat+mysql,我用的是struts2。
想请教下是怎么回事呢?是还需要配置什么地方吗?
我的项目用的是ssh+tomcat+mysql,我用的是struts2。
想请教下是怎么回事呢?是还需要配置什么地方吗?
两个都配置起来,本来以为FORWARD是包含REQUEST。
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.htm</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
刚我试过了,可以用的
LZ,我以前好像也有遇到过你这样的问题,不过好像Sturts2.0他的默认方式是用forward的,所以也可以不用设置的。你试试呢!
20 楼
luckaway
2010-01-01
xiaolongfeixiang 写道
luckaway 写道
网上已经有很多关于redirect和forward区别的文章,更多的都是只是一些概念上的描述,虽然在大多情况下,知道这些就已经足够了。但也有例外:forward not working for struts2,why?我也是在工作中碰到了这个问题,才特意看了下tomcat有关这部分的源代码。深刻的了解下也无妨。
redirect和forward都是属于servlet规范的,不同的servlet容器的实现可能会有一些区别,但原理都是类似的。
redirect和forward的定义:
1. redirect(重定向):服务端发送给客户端一个重定向的临时响应头,这个响应头包含重定向之后的URL,客户端用新的URL重新向服务器发送一个请求。
2. forward(请求转向):服务器程序内部请求转向,这个特性允许前一个程序用于处理请求,而后一个程序用来返回响应。
Redirect的原理比较简单,它的定义也已经描述的很清楚了,我也不想多讲什么,就贴一段简单的代码吧!
。。。。。。。。。。。。。。。。。。
redirect和forward都是属于servlet规范的,不同的servlet容器的实现可能会有一些区别,但原理都是类似的。
redirect和forward的定义:
1. redirect(重定向):服务端发送给客户端一个重定向的临时响应头,这个响应头包含重定向之后的URL,客户端用新的URL重新向服务器发送一个请求。
2. forward(请求转向):服务器程序内部请求转向,这个特性允许前一个程序用于处理请求,而后一个程序用来返回响应。
Redirect的原理比较简单,它的定义也已经描述的很清楚了,我也不想多讲什么,就贴一段简单的代码吧!
。。。。。。。。。。。。。。。。。。
赞楼主一个,想问下lz,Tomcat中SessionListener的机制。多个Session同时创建时,是形成一个队列调用session.create方法,还是各自并发地调用session.create方法?
应该需要分析源码吧?(给我点提示也可以)谢谢啦!
并发的调用session.create方法的,是设置sessionId的时候通知接听器的!!!
org.apache.catalina.session.StandardSession
/** * Set the session identifier for this session. * * @param id The new session identifier */ public void setId(String id) { if ((this.id != null) && (manager != null)) manager.remove(this); this.id = id; if (manager != null) manager.add(this); tellNew(); }
tellNew():
public void tellNew() { // Notify interested session event listeners fireSessionEvent(Session.SESSION_CREATED_EVENT, null); // Notify interested application event listeners Context context = (Context) manager.getContainer(); Object listeners[] = context.getApplicationLifecycleListeners(); if (listeners != null) { HttpSessionEvent event = new HttpSessionEvent(getSession()); for (int i = 0; i < listeners.length; i++) { if (!(listeners[i] instanceof HttpSessionListener)) continue; HttpSessionListener listener = (HttpSessionListener) listeners[i]; try { fireContainerEvent(context, "beforeSessionCreated", listener); listener.sessionCreated(event); fireContainerEvent(context, "afterSessionCreated", listener); } catch (Throwable t) { try { fireContainerEvent(context, "afterSessionCreated", listener); } catch (Exception e) { ; } manager.getContainer().getLogger().error (sm.getString("standardSession.sessionEvent"), t); } } } }
必须要保证SessionListener的实现类是线程安全的!
如果你对接听器模式不太了解的话,建议你先去学习接听器模式!
SessionListener就是接听器模式
19 楼
xiaolongfeixiang
2010-01-01
luckaway 写道
网上已经有很多关于redirect和forward区别的文章,更多的都是只是一些概念上的描述,虽然在大多情况下,知道这些就已经足够了。但也有例外:forward not working for struts2,why?我也是在工作中碰到了这个问题,才特意看了下tomcat有关这部分的源代码。深刻的了解下也无妨。
redirect和forward都是属于servlet规范的,不同的servlet容器的实现可能会有一些区别,但原理都是类似的。
redirect和forward的定义:
1. redirect(重定向):服务端发送给客户端一个重定向的临时响应头,这个响应头包含重定向之后的URL,客户端用新的URL重新向服务器发送一个请求。
2. forward(请求转向):服务器程序内部请求转向,这个特性允许前一个程序用于处理请求,而后一个程序用来返回响应。
Redirect的原理比较简单,它的定义也已经描述的很清楚了,我也不想多讲什么,就贴一段简单的代码吧!
。。。。。。。。。。。。。。。。。。
redirect和forward都是属于servlet规范的,不同的servlet容器的实现可能会有一些区别,但原理都是类似的。
redirect和forward的定义:
1. redirect(重定向):服务端发送给客户端一个重定向的临时响应头,这个响应头包含重定向之后的URL,客户端用新的URL重新向服务器发送一个请求。
2. forward(请求转向):服务器程序内部请求转向,这个特性允许前一个程序用于处理请求,而后一个程序用来返回响应。
Redirect的原理比较简单,它的定义也已经描述的很清楚了,我也不想多讲什么,就贴一段简单的代码吧!
。。。。。。。。。。。。。。。。。。
赞楼主一个,想问下lz,Tomcat中SessionListener的机制。多个Session同时创建时,是形成一个队列调用session.create方法,还是各自并发地调用session.create方法?
应该需要分析源码吧?(给我点提示也可以)谢谢啦!
18 楼
luckaway
2009-12-31
hanjiangit 写道
luckaway 写道
两个都配置起来,本来以为FORWARD是包含REQUEST。
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.htm</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
刚我试过了,可以用的
我照你的配了报错啦 500 错误
贴一点错误
javax.servlet.ServletException: Filter execution threw an exception org.apache.struts2.dispatcher.ServletDispatcherResult.doExecute(ServletDispatcherResult.java:154) org.apache.struts2.dispatcher.StrutsResultSupport.execute(StrutsResultSupport.java:186) com.opensymphony.xwork2.DefaultActionInvocation.executeResult(DefaultActionInvocation.java:361) com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:265) org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:52) org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:468)
你是不是tomcat版本太低了! dispatcher的特性是servlet2.4规范里加的!
tomcat版本和servlet规范的对应
http://tomcat.apache.org/whichversion.html
17 楼
hanjiangit
2009-12-31
luckaway 写道
两个都配置起来,本来以为FORWARD是包含REQUEST。
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.htm</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
刚我试过了,可以用的
我照你的配了报错啦 500 错误
贴一点错误
javax.servlet.ServletException: Filter execution threw an exception org.apache.struts2.dispatcher.ServletDispatcherResult.doExecute(ServletDispatcherResult.java:154) org.apache.struts2.dispatcher.StrutsResultSupport.execute(StrutsResultSupport.java:186) com.opensymphony.xwork2.DefaultActionInvocation.executeResult(DefaultActionInvocation.java:361) com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:265) org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:52) org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:468)
16 楼
hanjiangit
2009-12-31
向楼主致敬 学习 我学到东西了
15 楼
luckaway
2009-12-31
vera_sq 写道
LZ,我在web.xml配置中增加<dispatcher>FORWARD</dispatcher>这句配置后,发送请求就报404错误啊!
我的项目用的是ssh+tomcat+mysql,我用的是struts2。
想请教下是怎么回事呢?是还需要配置什么地方吗?
我的项目用的是ssh+tomcat+mysql,我用的是struts2。
想请教下是怎么回事呢?是还需要配置什么地方吗?
两个都配置起来,本来以为FORWARD是包含REQUEST。
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.htm</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
刚我试过了,可以用的
14 楼
vera_sq
2009-12-31
LZ,我在web.xml配置中增加<dispatcher>FORWARD</dispatcher>这句配置后,发送请求就报404错误啊!
我的项目用的是ssh+tomcat+mysql,我用的是struts2。
想请教下是怎么回事呢?是还需要配置什么地方吗?
我的项目用的是ssh+tomcat+mysql,我用的是struts2。
想请教下是怎么回事呢?是还需要配置什么地方吗?
13 楼
jelver
2009-12-31
不错,多谢分享
相关推荐
- `forward()`方法将请求转发给另一个资源,而`redirect()`则告诉客户端重新发起一个新的请求。 6. **过滤器(Filter)**: - Filter是Servlet技术的一部分,可以对请求和响应进行预处理和后处理,如登录验证、...
读者可能会接触到RequestDispatcher和Forward/Redirect的区别,以及如何使用Filter进行请求和响应的拦截处理。此外,对于初学者来说,这一章可能也会讲解如何组织项目结构,以符合良好的编程习惯和标准。 总之,这...
两者通过RequestDispatcher或Forward、Redirect等方式进行交互。 2. **MVC设计模式**:Model-View-Controller模式是Web开发中的常见架构,其中Model代表业务逻辑,View负责渲染视图,Controller处理请求并协调Model...
- <jsp:forward>和<jsp:redirect>处理页面跳转 - 创建和操作JavaBean - 和设置和获取Bean属性 2. **JSTL(JavaServer Pages Standard Tag Library)** - JSTL简介和优点 - JSTL核心库(fmt, fmt, sql, ...
20. forward 和redirect的区别 13 21. EJB与JAVA BEAN的区别? 13 22. Static Nested Class 和 Inner Class的不同。 13 23. JSP中动态INCLUDE与静态INCLUDE的区别? 14 24. List, Set, Map区别 14 25. 集合类都有...
在Web开发中,"转发"(Forward)和"重定向"(Redirect)是两种常见的页面跳转方式,它们虽然在效果上看似相似,但其实有着本质的区别。理解这两种技术的工作原理及其应用场景对于优化应用程序的性能和用户体验至关...
JSP主要负责视图层的展示,但两者可以通过转发(Forward)或重定向(Redirect)等方式协作。Servlet与JSP的配合使用,实现了MVC(Model-View-Controller)设计模式,有助于提高代码的可维护性和可扩展性。 **3. ...
22、forward 和redirect的区别 forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址...
- 常见的有转发(forward)和重定向(redirect)两种方式。 **4. 在Tomcat中配置数据源** - 通过配置文件`context.xml`设置数据库连接池。 **5. 持久化状态: Cookie, Session** - Cookie用于客户端存储少量数据,...
1. `forward()`与`redirect()`的区别: - `forward()`是服务器内部重定向,浏览器地址栏URL不变,请求参数仍有效,效率较高。 - `redirect()`是客户端重定向,浏览器重新发起请求,地址栏URL改变,请求参数需要...