pageContext的用法
在tomcat项目work目录查看jsp编译后的servlet源代码可以发现:final javax.servlet.jsp.PageContext pageContext;可以知晓pageContext是一个javax.servlet.jsp.PageContext类对象我们知道pageContext可以获得其他容器的引用:源代码:package javax.serv
在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);
}
子类的函数实现父类,pageContext由此制造出:
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);
}
pageContext处理字节字符流共存问题:
而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];
}
pageContext的finAttribute(paramName);
@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四个范围容器中依次从小到大查找,返回其值。
更多推荐
所有评论(0)