在tomcat项目work目录查看jsp编译后的servlet源代码可以发现:
final javax.servlet.jsp.PageContext pageContext;
可以知晓pageContext是一个javax.servlet.jsp.PageContext类对象
我们知道pageContext可以获得其他容器的引用:
源代码:
- package javax.servlet.jsp;
- public abstract class PageContext extends JspContext
- {
- public static final int PAGE_SCOPE = 1;
- public static final int REQUEST_SCOPE = 2;
- public static final int SESSION_SCOPE = 3;
- public static final int APPLICATION_SCOPE = 4;
- public static final String PAGE = "javax.servlet.jsp.jspPage";
- public static final String PAGECONTEXT = "javax.servlet.jsp.jspPageContext";
- public static final String REQUEST = "javax.servlet.jsp.jspRequest";
- public static final String RESPONSE = "javax.servlet.jsp.jspResponse";
- public static final String CONFIG = "javax.servlet.jsp.jspConfig";
- public static final String SESSION = "javax.servlet.jsp.jspSession";
- public static final String OUT = "javax.servlet.jsp.jspOut";
- public static final String APPLICATION = "javax.servlet.jsp.jspApplication";
- public static final String EXCEPTION = "javax.servlet.jsp.jspException";
- public abstract void initialize(Servlet paramServlet, ServletRequest paramServletRequest, ServletResponse paramServletResponse, String paramString, boolean paramBoolean1, int paramInt, boolean paramBoolean2)
- throws IOException, IllegalStateException, IllegalArgumentException;
- public abstract void release();
- public abstract HttpSession getSession();
- public abstract Object getPage();
- public abstract ServletRequest getRequest();
- public abstract ServletResponse getResponse();
- public abstract Exception getException();
- public abstract ServletConfig getServletConfig();
- public abstract ServletContext getServletContext();
- public abstract void forward(String paramString)
- throws ServletException, IOException;
- public abstract void include(String paramString)
- throws ServletException, IOException;
- public abstract void include(String paramString, boolean paramBoolean)
- throws ServletException, IOException;
- public abstract void handlePageException(Exception paramException)
- throws ServletException, IOException;
- public abstract void handlePageException(Throwable paramThrowable)
- throws ServletException, IOException;
- public BodyContent pushBody()
- {
- return null;
- }
- public ErrorData getErrorData()
- {
- int status = 0;
- Integer status_code = (Integer)getRequest().getAttribute("javax.servlet.error.status_code");
- if (status_code != null) {
- status = status_code.intValue();
- }
- return new ErrorData((Throwable)getRequest().getAttribute("javax.servlet.error.exception"), status, (String)getRequest().getAttribute("javax.servlet.error.request_uri"), (String)getRequest().getAttribute("javax.servlet.error.servlet_name"));
- }
- }
是一个继承了JspContext抽象类的抽象类
- package javax.servlet.jsp;
- public abstract class JspContext
- {
- public abstract void setAttribute(String paramString, Object paramObject);
- public abstract void setAttribute(String paramString, Object paramObject, int paramInt);
- public abstract Object getAttribute(String paramString);
- public abstract Object getAttribute(String paramString, int paramInt);
- public abstract Object findAttribute(String paramString);
- public abstract void removeAttribute(String paramString);
- public abstract void removeAttribute(String paramString, int paramInt);
- public abstract int getAttributesScope(String paramString);
- public abstract Enumeration<String> getAttributeNamesInScope(int paramInt);
- public abstract JspWriter getOut();
- /** @deprecated */
- public abstract ExpressionEvaluator getExpressionEvaluator();
- public abstract ELContext getELContext();
- /** @deprecated */
- public abstract VariableResolver getVariableResolver();
- public JspWriter pushBody(Writer writer)
- {
- return null;
- }
- public JspWriter popBody()
- {
- return null;
- }
- }
注意存取的第二个变量决定作用域的范围
public static final int PAGE_SCOPE = 1;
public static final int REQUEST_SCOPE = 2;
public static final int SESSION_SCOPE = 3;
public static final int APPLICATION_SCOPE = 4;
我们了解了pageContent是一个抽象类,那么是怎么具体实现的?
private static final javax.servlet.jsp.JspFactory _jspxFactory = javax.servlet.jsp.JspFactory.getDefaultFactory();
pageContext = _jspxFactory.getPageContext(this, request, response,null, true, 8192, true);
发现是由javax.servlet.jsp.JspFactory来构造
- getPageContext(Servlet paramServlet, ServletRequest paramServletRequest, ServletResponse paramServletResponse, String paramString, boolean paramBoolean1, int paramInt, boolean paramBoolean2);
- package javax.servlet.jsp;
- public abstract class JspFactory
- {
- private static volatile JspFactory deflt = null;
- public static void setDefaultFactory(JspFactory deflt)
- {
- deflt = deflt;
- }
- public static JspFactory getDefaultFactory()
- {
- return deflt;
- }
- public abstract PageContext getPageContext(Servlet paramServlet, ServletRequest paramServletRequest, ServletResponse paramServletResponse, String paramString, boolean paramBoolean1, int paramInt, boolean paramBoolean2);
- public abstract void releasePageContext(PageContext paramPageContext);
- public abstract JspEngineInfo getEngineInfo();
- public abstract JspApplicationContext getJspApplicationContext(ServletContext paramServletContext);
- }
- package org.apache.jasper.runtime;
- public class JspFactoryImpl extends JspFactory
- {
- private final Log log;
- private static final String SPEC_VERSION = "2.1";
- private static final boolean USE_POOL = Boolean.valueOf(System.getProperty("org.apache.jasper.runtime.JspFactoryImpl.USE_POOL", "true")).booleanValue();
- private static final int POOL_SIZE = Integer.valueOf(System.getProperty("org.apache.jasper.runtime.JspFactoryImpl.POOL_SIZE", "8")).intValue();
- private ThreadLocal<PageContextPool> localPool;
- public JspFactoryImpl()
- {
- this.log = LogFactory.getLog(JspFactoryImpl.class);
- this.localPool = new ThreadLocal();
- }
- public PageContext getPageContext(Servlet servlet, ServletRequest request, ServletResponse response, String errorPageURL, boolean needsSession, int bufferSize, boolean autoflush)
- {
- if (Constants.IS_SECURITY_ENABLED) {
- PrivilegedGetPageContext dp = new PrivilegedGetPageContext(this, servlet, request, response, errorPageURL, needsSession, bufferSize, autoflush);
- return ((PageContext)AccessController.doPrivileged(dp));
- }
- return internalGetPageContext(servlet, request, response, errorPageURL, needsSession, bufferSize, autoflush);
- }
- public PageContext getPageContext(Servlet servlet, ServletRequest request, ServletResponse response, String errorPageURL, boolean needsSession, int bufferSize, boolean autoflush)
- {
- if (Constants.IS_SECURITY_ENABLED) {
- PrivilegedGetPageContext dp = new PrivilegedGetPageContext(this, servlet, request, response, errorPageURL, needsSession, bufferSize, autoflush);
- return ((PageContext)AccessController.doPrivileged(dp));
- }
- return internalGetPageContext(servlet, request, response, errorPageURL, needsSession, bufferSize, autoflush);
- }
而pageContent的pushbody()源码:
因为javax.servlet.jsp.PageContext是一个抽象类,工厂方法必定构造其子类
- package org.apache.jasper.runtime;
- public class PageContextImpl extends PageContext
- {
- private static final JspFactory jspf = JspFactory.getDefaultFactory();
- private BodyContentImpl[] outs;
- private int depth;
- private Servlet servlet;
- private ServletConfig config;
- private ServletContext context;
- private JspApplicationContextImpl applicationContext;
- private String errorPageURL;
- private transient HashMap<String, Object> attributes;
- private transient ServletRequest request;
- private transient ServletResponse response;
- private transient HttpSession session;
- private transient ELContextImpl elContext;
- private boolean isIncluded;
- private transient JspWriter out;
- private transient JspWriterImpl baseOut;
- PageContextImpl()
- {
- this.outs = new BodyContentImpl[0];
- this.attributes = new HashMap(16);
- this.depth = -1;
- }
- public void initialize(Servlet servlet, ServletRequest request, ServletResponse response, String errorPageURL, boolean needsSession, int bufferSize, boolean autoFlush)
- throws IOException
- {
- _initialize(servlet, request, response, errorPageURL, needsSession, bufferSize, autoFlush);
- }
- private void _initialize(Servlet servlet, ServletRequest request, ServletResponse response, String errorPageURL, boolean needsSession, int bufferSize, boolean autoFlush)
- {
- this.servlet = servlet;
- this.config = servlet.getServletConfig();
- this.context = this.config.getServletContext();
- this.errorPageURL = errorPageURL;
- this.request = request;
- this.response = response;
- this.applicationContext = JspApplicationContextImpl.getInstance(this.context);
- if ((request instanceof HttpServletRequest) && (needsSession))
- this.session = ((HttpServletRequest)request).getSession();
- if ((needsSession) && (this.session == null)) {
- throw new IllegalStateException("Page needs a session and none is available");
- }
- this.depth = -1;
- if (this.baseOut == null)
- this.baseOut = new JspWriterImpl(response, bufferSize, autoFlush);
- else {
- this.baseOut.init(response, bufferSize, autoFlush);
- }
- this.out = this.baseOut;
- setAttribute("javax.servlet.jsp.jspOut", this.out);
- setAttribute("javax.servlet.jsp.jspRequest", request);
- setAttribute("javax.servlet.jsp.jspResponse", response);
- if (this.session != null) {
- setAttribute("javax.servlet.jsp.jspSession", this.session);
- }
- setAttribute("javax.servlet.jsp.jspPage", servlet);
- setAttribute("javax.servlet.jsp.jspConfig", this.config);
- setAttribute("javax.servlet.jsp.jspPageContext", this);
- setAttribute("javax.servlet.jsp.jspApplication", this.context);
- this.isIncluded = (request.getAttribute("javax.servlet.include.servlet_path") != null);
- }
- <pre name="code" class="java">
- @Override
- public JspWriter pushBody(Writer writer) {
- depth++;
- if (depth >= outs.length) {
- BodyContentImpl[] newOuts = new BodyContentImpl[depth + 1];
- for (int i = 0; i < outs.length; i++) {
- newOuts[i] = outs[i];
- }
- newOuts[depth] = new BodyContentImpl(out);
- outs = newOuts;
- }
- outs[depth].setWriter(writer);
- out = outs[depth];
- // Update the value of the "out" attribute in the page scope
- // attribute namespace of this PageContext
- setAttribute(OUT, out);
- return outs[depth];
- }
- @Override
- public Object findAttribute(final String name) {
- if (SecurityUtil.isPackageProtectionEnabled()) {
- return AccessController.doPrivileged(
- new PrivilegedAction<Object>() {
- @Override
- public Object run() {
- if (name == null) {
- throw new NullPointerException(Localizer
- .getMessage("jsp.error.attribute.null_name"));
- }
- return doFindAttribute(name);
- }
- });
- } else {
- if (name == null) {
- throw new NullPointerException(Localizer
- .getMessage("jsp.error.attribute.null_name"));
- }
- return doFindAttribute(name);
- }
- }
- <pre name="code" class="java">
- <pre name="code" class="java"><span style="color:#000000;"> private Object doFindAttribute(String name) {
- Object o = attributes.get(name);
- if (o != null)
- return o;
- o = request.getAttribute(name);
- if (o != null)
- return o;
- if (session != null) {
- try {
- o = session.getAttribute(name);
- } catch(IllegalStateException ise) {
- // Session has been invalidated.
- // Ignore and fall through to application scope.
- }
- if (o != null)
- return o;
- }
- return context.getAttribute(name);
- }</span>
了解到由pageContext---->request--->session--->ServeltContext四个范围容器中依次从小到大查找,返回其值。